diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..aca25232dd7d026e2b6f00a78e2a3504b9ba930f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.gitignore b/.gitignore index dad43d5c42eb92672d82f08c4f81dd3c08b1647c..2cc62bbb310800b4025c4b84e7157c7f57578084 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +/www/lib/ionic-material +/www/lib/robotodraft # Specifies intentionally untracked files to ignore when using Git # http://git-scm.com/docs/gitignore @@ -6,4 +8,8 @@ platforms/ plugins/ .idea/ cesium.iml -pom.xml \ No newline at end of file +pom.xml +www/css/ionic.app.css +www/css/ionic.app.min.css + +www/js/config.js \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/README.md b/README.md index 3f4af2e30ba79eb62739a4db641e40219d6acf46..bf86f8c394e6f5eb611514f662ab4aa2509d4f0a 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,42 @@ [Unhosted webapp](https://unhosted.org) client for [uCoin](http://ucoin.io) network. -Try it at: http://cesium.ucoin.io \ No newline at end of file +Try it at: http://cesium.ucoin.io + +## Developer + +To contribute and compile cesium, you will have to: + + - Installing [mvn](https://github.com/creationix/nvm) +``` + wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash +``` + + - Configure NodeJS to use a version 5: +``` + nvm install 5 +``` + + - Installing other build dependencies: +``` + sudo apt-get install build-essential +``` + + - Getting source and installing project dependencies: +``` + git clone https://www.github.com/ucoin-io/cesium.git + cd cesium + npm install +``` + + - Compiling and running application +``` + gulp & ionic serve +``` + + - To build on another environment : + - Add your environment config into `app/config.json` + - Run compitaltion using option `--env`: +``` + gulp default --env <your_env_name> +``` diff --git a/app/config.json b/app/config.json new file mode 100644 index 0000000000000000000000000000000000000000..b93fc485b8beac50e8451b560e396c7b733eab84 --- /dev/null +++ b/app/config.json @@ -0,0 +1,34 @@ +{ + "default": { + "APP_CONFIG": { + "UCOIN_NODE": "metab.ucoin.io" + } + }, + + "ucoin-io": { + "APP_CONFIG": { + "UCOIN_NODE": "metab.ucoin.io" + } + }, + + "twiced-fr": { + "APP_CONFIG": { + "UCOIN_NODE": "twiced.fr:9330" + } + }, + + "ucoin-fr": { + "APP_CONFIG": { + "UCOIN_NODE": "twiced.fr:9330", + "UCOIN_NODE_ES": "es.ucoin.fr" + } + }, + + "dev": { + "APP_CONFIG": { + "UCOIN_NODE": "192.168.0.28:9201", + "UCOIN_NODE_ES": "192.168.0.5:9200" + } + } + +} diff --git a/bower.json b/bower.json index 26ce45b551932ad451926a99a7b8a61752329470..b6e003529efe3f4cabb6950be242315c4843752f 100644 --- a/bower.json +++ b/bower.json @@ -1,10 +1,13 @@ { - "name": "HelloIonic", + "name": "Cesium", "private": "true", "devDependencies": { - "ionic": "driftyco/ionic-bower#1.0.1" + "ionic": "driftyco/ionic-bower#1.2.4" }, "dependencies": { - "angular-messages": "1.3.13" + "angular-messages": "1.3.13", + "robotodraft": "1.1.0", + "ionic-material": "0.4.2", + "js-nacl": "0.6.0" } } diff --git a/config.xml b/config.xml index 0b1722877229bbc0becc30af06533fcb78f87e41..3a91ad31cae947644c10895b4f7a3c8493163896 100644 --- a/config.xml +++ b/config.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<widget id="com.ionicframework.cesium795009" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> +<widget id="com.ionicframework.lesou" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <name>Cesium</name> <description> - A webapp client for uCoin network + A webapp client for Duniter </description> - <author email="admin@ucoin.io" href="http://ucoin.io"> - cgeek - </author> + <author email="contact@le-sou.org" href="http://le-sou.org"> + le Sou + </author> <content src="index.html"/> <access origin="*"/> <preference name="webviewbounce" value="false"/> @@ -39,4 +39,33 @@ <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/> <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/> </platform> + <platform name="ios"> + <icon src="resources/ios/icon/icon.png" width="57" height="57"/> + <icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/> + <icon src="resources/ios/icon/icon-40.png" width="40" height="40"/> + <icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/> + <icon src="resources/ios/icon/icon-50.png" width="50" height="50"/> + <icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/> + <icon src="resources/ios/icon/icon-60.png" width="60" height="60"/> + <icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/> + <icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/> + <icon src="resources/ios/icon/icon-72.png" width="72" height="72"/> + <icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/> + <icon src="resources/ios/icon/icon-76.png" width="76" height="76"/> + <icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/> + <icon src="resources/ios/icon/icon-small.png" width="29" height="29"/> + <icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/> + <icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/> + <splash src="resources/ios/splash/Default-568h@2x~iphone.png" height="1136" width="640"/> + <splash src="resources/ios/splash/Default-667h.png" height="1334" width="750"/> + <splash src="resources/ios/splash/Default-736h.png" height="2208" width="1242"/> + <splash src="resources/ios/splash/Default-Landscape-736h.png" height="1242" width="2208"/> + <splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" height="1536" width="2048"/> + <splash src="resources/ios/splash/Default-Landscape~ipad.png" height="768" width="1024"/> + <splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" height="2048" width="1536"/> + <splash src="resources/ios/splash/Default-Portrait~ipad.png" height="1024" width="768"/> + <splash src="resources/ios/splash/Default@2x~iphone.png" height="960" width="640"/> + <splash src="resources/ios/splash/Default~iphone.png" height="480" width="320"/> + </platform> + <allow-navigation href="*"/> </widget> \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 3efdfc0a155bfeca424e5ef5a7d75c4b145def99..77017c0e9dfc2de540f6ad9f4a5b1d4d1b599ea7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,3 +1,5 @@ +'use strict'; + var gulp = require('gulp'); var gutil = require('gulp-util'); var bower = require('bower'); @@ -6,18 +8,21 @@ var sass = require('gulp-sass'); var minifyCss = require('gulp-minify-css'); var rename = require('gulp-rename'); var sh = require('shelljs'); +var ngConstant = require('gulp-ng-constant'); +var fs = require("fs"); +var argv = require('yargs').argv; +var header = require('gulp-header'); var paths = { - sass: ['./scss/**/*.scss'] + sass: ['./scss/**/*.scss'], + config: ['./app/config.json'] }; -gulp.task('default', ['sass']); +gulp.task('default', ['sass', 'config']); gulp.task('sass', function(done) { gulp.src('./scss/ionic.app.scss') - .pipe(sass({ - errLogToConsole: true - })) + .pipe(sass()).on('error', sass.logError) .pipe(gulp.dest('./www/css/')) .pipe(minifyCss({ keepSpecialComments: 0 @@ -29,6 +34,7 @@ gulp.task('sass', function(done) { gulp.task('watch', function() { gulp.watch(paths.sass, ['sass']); + //gulp.watch(paths.config, ['config']); }); gulp.task('install', ['git-check'], function() { @@ -50,3 +56,34 @@ gulp.task('git-check', function(done) { } done(); }); + +gulp.task('config', function (done) { + var allConfig = JSON.parse(fs.readFileSync('./app/config.json', 'utf8')); + + // Determine which environment to use when building config. + var env = argv.env || 'default'; + var config = allConfig[env]; + + if(!config) { + gutil.log(gutil.colors.red("=> Could not load `" + env + "` environment!")); + return done(); + } + + gutil.log(gutil.colors.green("Building `www/js/config.js` for `" + env + "` environment...")); + + config['APP_CONFIG']['VERSION'] = JSON.parse(fs.readFileSync('./package.json', 'utf8')).version; + config['APP_CONFIG']['BUILD_DATE'] = (new Date()).toJSON(); + + return ngConstant({ + name: 'cesium.config', + constants: config, + stream: true, + dest: 'config.js' + }) + // Add a warning header + .pipe(header("/******\n* !! WARNING: This is a generated file !!\n*\n* PLEASE DO NOT MODIFY DIRECTLY\n*\n* => Changes should be done on file 'app/config.json'.\n******/\n\n")) + // Writes into file www/js/config.js + .pipe(rename('config.js')) + .pipe(gulp.dest('www/js')) + ; +}); diff --git a/hooks/README.md b/hooks/README.md old mode 100644 new mode 100755 diff --git a/hooks/before_prepare/02_jshint.js b/hooks/before_prepare/02_jshint.js new file mode 100755 index 0000000000000000000000000000000000000000..4d05587c8831b9c8bcf3295d0f99578c6de72024 --- /dev/null +++ b/hooks/before_prepare/02_jshint.js @@ -0,0 +1,75 @@ +#!/usr/bin/env node + +var fs = require('fs'); +var path = require('path'); +var jshint = require('jshint').JSHINT; +var async = require('async'); + +var foldersToProcess = [ + 'js', + 'js/controllers', + 'js/entity', + 'js/services' +]; + +foldersToProcess.forEach(function(folder) { + processFiles("www/" + folder); +}); + +function processFiles(dir, callback) { + var errorCount = 0; + fs.readdir(dir, function(err, list) { + if (err) { + console.log('processFiles err: ' + err); + return; + } + async.eachSeries(list, function(file, innercallback) { + file = dir + '/' + file; + fs.stat(file, function(err, stat) { + if(!stat.isDirectory()) { + if(path.extname(file) === ".js") { + lintFile(file, function(hasError) { + if(hasError) { + errorCount++; + } + innercallback(); + }); + } else { + innercallback(); + } + } else { + innercallback(); + } + }); + }, function(error) { + if(errorCount > 0) { + process.exit(1); + } + }); + }); +} + +function lintFile(file, callback) { + console.log("Linting " + file); + fs.readFile(file, function(err, data) { + if(err) { + console.log('Error: ' + err); + return; + } + if(jshint(data.toString())) { + console.log('File ' + file + ' has no errors.'); + console.log('-----------------------------------------'); + callback(false); + } else { + console.log('Errors in file ' + file); + var out = jshint.data(), + errors = out.errors; + for(var j = 0; j < errors.length; j++) { + console.log(errors[j].line + ':' + errors[j].character + ' -> ' + errors[j].reason + ' -> ' + +errors[j].evidence); + } + console.log('-----------------------------------------'); + callback(true); + } + }); +} diff --git a/ionic.project b/ionic.project index fc436c7b9720493086c3674611c74bc8393c5394..45fe9334234dffc405265ebdc58702a8cd75e093 100644 --- a/ionic.project +++ b/ionic.project @@ -1,4 +1,12 @@ { "name": "Cesium", - "app_id": "" -} \ No newline at end of file + "app_id": "", + "watchPatterns": [ + "www/**/*", + "!www/lib/**/*" + ], + "gulpStartupTasks": [ + "sass", + "watch" + ] +} diff --git a/package.json b/package.json index d9d7e3d2455cc1c895d4af91245d8e1e3934276f..56c94080c60c11fac2677b1b64c8063732ae1e7c 100644 --- a/package.json +++ b/package.json @@ -3,28 +3,31 @@ "version": "0.0.1", "description": "A webapp client for uCoin network", "dependencies": { - "gulp": "^3.5.6", - "gulp-sass": "^1.3.3", + "gulp": "^3.9.1", "gulp-concat": "^2.2.0", "gulp-minify-css": "^0.3.0", - "gulp-rename": "^1.2.0" + "gulp-rename": "^1.2.0", + "gulp-sass": "^2.2.0", + "node-sass": "^3.3.3" }, "devDependencies": { "bower": "^1.3.3", + "gulp-header": "^1.7.1", + "gulp-ng-constant": "^1.1.0", "gulp-util": "^2.2.14", - "shelljs": "^0.3.0" + "ionic-minify": "^2.0.8", + "shelljs": "^0.3.0", + "yargs": "^4.3.1" }, "cordovaPlugins": [ - "cordova-plugin-device", - "cordova-plugin-console", "cordova-plugin-whitelist", "cordova-plugin-splashscreen", - "com.ionic.keyboard" + "cordova-plugin-console", + "ionic-plugin-keyboard", + "cordova-plugin-device" ], "cordovaPlatforms": [ - { - "platform": "android", - "locator": "browser" - } + "android", + "ios" ] -} \ No newline at end of file +} diff --git a/resources/android/icon/drawable-hdpi-icon.png b/resources/android/icon/drawable-hdpi-icon.png index b9100934dac7ce92fd44c4c90aa50b1469d67c04..2b1090995ef08b202133bf058facc6185da703b3 100644 Binary files a/resources/android/icon/drawable-hdpi-icon.png and b/resources/android/icon/drawable-hdpi-icon.png differ diff --git a/resources/android/icon/drawable-ldpi-icon.png b/resources/android/icon/drawable-ldpi-icon.png index 16cd5dba33faeda3f256eaba98fab310ba722778..d8082c7a685930cc9119698d7e4a2b0a3c7ed423 100644 Binary files a/resources/android/icon/drawable-ldpi-icon.png and b/resources/android/icon/drawable-ldpi-icon.png differ diff --git a/resources/android/icon/drawable-mdpi-icon.png b/resources/android/icon/drawable-mdpi-icon.png index 64a6cbc52de2a6cad2d8a0f23c19ede85d62b7a5..9b11185a05917bdce0b362256716f4907b5f822e 100644 Binary files a/resources/android/icon/drawable-mdpi-icon.png and b/resources/android/icon/drawable-mdpi-icon.png differ diff --git a/resources/android/icon/drawable-xhdpi-icon.png b/resources/android/icon/drawable-xhdpi-icon.png index 1605f695fa85116686adfcc5bb760879c6b40dd8..4be0cda3af048053a1f596c01752e2368445a4e0 100644 Binary files a/resources/android/icon/drawable-xhdpi-icon.png and b/resources/android/icon/drawable-xhdpi-icon.png differ diff --git a/resources/android/icon/drawable-xxhdpi-icon.png b/resources/android/icon/drawable-xxhdpi-icon.png index 56fb29e64e62d8afc5488de5f4ab6119becc6901..7e75954ae39d004eb8f374bbfa06afafff632cfe 100644 Binary files a/resources/android/icon/drawable-xxhdpi-icon.png and b/resources/android/icon/drawable-xxhdpi-icon.png differ diff --git a/resources/android/icon/drawable-xxxhdpi-icon.png b/resources/android/icon/drawable-xxxhdpi-icon.png index e4a915254b11c257a9803d2e543b9f8358911e1e..129447eee6cc90ef87e9d7ce36b14c1f504c1c22 100644 Binary files a/resources/android/icon/drawable-xxxhdpi-icon.png and b/resources/android/icon/drawable-xxxhdpi-icon.png differ diff --git a/resources/android/icon/lesou-120px.png b/resources/android/icon/lesou-120px.png new file mode 100644 index 0000000000000000000000000000000000000000..05998c2193bf33c89ce40c5b214b6093f4583ca9 Binary files /dev/null and b/resources/android/icon/lesou-120px.png differ diff --git a/resources/android/splash/drawable-land-hdpi-screen.png b/resources/android/splash/drawable-land-hdpi-screen.png index 66b12feae4c452712f980111a029f47929ebc97c..b3806f495e7d248551b3a5eb4f0f7136784bc8dd 100644 Binary files a/resources/android/splash/drawable-land-hdpi-screen.png and b/resources/android/splash/drawable-land-hdpi-screen.png differ diff --git a/resources/android/splash/drawable-land-ldpi-screen.png b/resources/android/splash/drawable-land-ldpi-screen.png index 7dceec7b7839e6dff6dca211af6e54d696ca7762..f1ea72731aa7b11a2fb508b33f231f3e118fc3bd 100644 Binary files a/resources/android/splash/drawable-land-ldpi-screen.png and b/resources/android/splash/drawable-land-ldpi-screen.png differ diff --git a/resources/android/splash/drawable-land-mdpi-screen.png b/resources/android/splash/drawable-land-mdpi-screen.png index 0dc2ba75fba77e6fc273af17ad6f2740e2e909d3..62a9906d5638b248aed4158c1e0973d809a95c7e 100644 Binary files a/resources/android/splash/drawable-land-mdpi-screen.png and b/resources/android/splash/drawable-land-mdpi-screen.png differ diff --git a/resources/android/splash/drawable-land-xhdpi-screen.png b/resources/android/splash/drawable-land-xhdpi-screen.png index 39ae00c33dd22b801a78f305bcdb99f9ec7a5a44..4c252f431aa5ddfed3c9791da3ade8bb1b5798f4 100644 Binary files a/resources/android/splash/drawable-land-xhdpi-screen.png and b/resources/android/splash/drawable-land-xhdpi-screen.png differ diff --git a/resources/android/splash/drawable-land-xxhdpi-screen.png b/resources/android/splash/drawable-land-xxhdpi-screen.png index 3f591b1e6a0b0213e7faca4c32c4525db1f517ff..38d4075b7be74f15f929157ee215b88160a49439 100644 Binary files a/resources/android/splash/drawable-land-xxhdpi-screen.png and b/resources/android/splash/drawable-land-xxhdpi-screen.png differ diff --git a/resources/android/splash/drawable-land-xxxhdpi-screen.png b/resources/android/splash/drawable-land-xxxhdpi-screen.png index 253e6f1834511ed0d5a91c8701f7edffbb4d8a45..25cff7cb20d842a553e5e9aad8f683a7c16a8fee 100644 Binary files a/resources/android/splash/drawable-land-xxxhdpi-screen.png and b/resources/android/splash/drawable-land-xxxhdpi-screen.png differ diff --git a/resources/android/splash/drawable-port-hdpi-screen.png b/resources/android/splash/drawable-port-hdpi-screen.png index e0dbb62f2ba12fc0fcc462b9f48207af683efbcb..ef20c5341c71d3841010fd54e14c99a304b9cdb5 100644 Binary files a/resources/android/splash/drawable-port-hdpi-screen.png and b/resources/android/splash/drawable-port-hdpi-screen.png differ diff --git a/resources/android/splash/drawable-port-ldpi-screen.png b/resources/android/splash/drawable-port-ldpi-screen.png index 8e93c2d642ef802e83195f67ee3132a59e27dcd5..8b853be247417a86b5fd5bd547c5a7471582c4c9 100644 Binary files a/resources/android/splash/drawable-port-ldpi-screen.png and b/resources/android/splash/drawable-port-ldpi-screen.png differ diff --git a/resources/android/splash/drawable-port-mdpi-screen.png b/resources/android/splash/drawable-port-mdpi-screen.png index 0aaad62bf54b00c139487886748a46a3d7a17036..2ced5a7754d6edf7d68ef1aa90e348a8b81110c9 100644 Binary files a/resources/android/splash/drawable-port-mdpi-screen.png and b/resources/android/splash/drawable-port-mdpi-screen.png differ diff --git a/resources/android/splash/drawable-port-xhdpi-screen.png b/resources/android/splash/drawable-port-xhdpi-screen.png index 64c27f8a66ec53a569741e5726f19cf2bdd35bf2..bebbc94a1e3181423ec30f26a4568b085ff110c7 100644 Binary files a/resources/android/splash/drawable-port-xhdpi-screen.png and b/resources/android/splash/drawable-port-xhdpi-screen.png differ diff --git a/resources/android/splash/drawable-port-xxhdpi-screen.png b/resources/android/splash/drawable-port-xxhdpi-screen.png index f605e6a3d58fdd63e472b4820d079450ff3ad2a9..bf1d1d65f44494969e46be27095b57c0c8d48f4f 100644 Binary files a/resources/android/splash/drawable-port-xxhdpi-screen.png and b/resources/android/splash/drawable-port-xxhdpi-screen.png differ diff --git a/resources/android/splash/drawable-port-xxxhdpi-screen.png b/resources/android/splash/drawable-port-xxxhdpi-screen.png index 2b993cff7758f7cebb1cafc09397a20b39f2a923..13de29c03170fcbb85d60f85baa473e51b39758c 100644 Binary files a/resources/android/splash/drawable-port-xxxhdpi-screen.png and b/resources/android/splash/drawable-port-xxxhdpi-screen.png differ diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss index 9eb2f782020c94863c6d5573d8c58e1262199e22..9162cbb2c74489e13592b9f7635efb25b755ba17 100644 --- a/scss/ionic.app.scss +++ b/scss/ionic.app.scss @@ -15,9 +15,212 @@ $royal: #886aea !default; $dark: #444 !default; */ +//$royal: #030055 !default; +//$assertive: #ff7a00 !default; +//$balanced: #33cd5f !default; + +//$dark: #030055 !default; // bleu foncé uCoin App +//$assertive: #94c11f !default; +//$balanced: #94c11f !default; + // The path for our ionicons font files, relative to the built CSS in www/css $ionicons-font-path: "../lib/ionic/fonts" !default; // Include all of Ionic @import "www/lib/ionic/scss/ionic"; +// Add robotodraft fonts (need for ionic material) +$RobotoDraftFontPath: "../lib/ionic/fonts/robotdraft"; +$RobotoDraftFontName: "RobotoDraft"; +$RobotoDraftFontVersion: "1.1.0"; + +@import "www/lib/robotodraft/sass/robotodraft"; + +// Include all of Ionic-Material +@import "www/lib/ionic-material/src/scss/index"; + + +// -------------------------------------------------- +// Responsive: Utility classes +// -------------------------------------------------- +$screen-xs-max: 747px; +$screen-sm: 748px; +$screen-sm-max: 991px; +$screen-md: 992px; +$screen-md-max: 1199px; +$screen-lg: 1200px; +// IE10 on Windows Phone 8 +// IE10 on WP8 doesn't report CSS pixels, but actual device pixels. In +// other words, say on a Lumia, you'll get 768px as the device width, +// meaning users will see the tablet styles and not phone styles. +// +// Alternatively you can override this with JS (see source below), but +// we won't be doing that here given our limited scope. +// +// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/ +// +// >>Autre doc http://getbootstrap.com/css/#responsive-utilities-classes +// +@media screen and (max-width: 400px) { + @-ms-viewport{ + width: 320px; + } +} + +// Extra small device: Phones (<747px) +@media screen and (max-width: $screen-xs-max) { + .hidden-xs { + display: none !important; + visibility: hidden !important; + } +} +@media screen and (min-width: $screen-sm) { + .hidden-xs { + display: inherited; + visibility: visible !important; + } +} +@media screen and (max-width: $screen-xs-max) { + .visible-xs { + display: inherited; + visibility: visible !important; + } +} +@media screen and (min-width: $screen-sm) { + .visible-xs { + display: none !important; + visibility: hidden !important; + } +} +@media screen and (max-width: $screen-xs-max) { + .no-padding-xs { + padding: 0px !important; + } +} +@media screen and (min-width: $screen-sm) { + .no-padding-xs { + padding: inherited; + } +} +@media screen and (max-width: $screen-xs-max) { + .no-margin-xs { + margin: 0px !important; + } +} +@media screen and (min-width: $screen-sm) { + .no-margin-xs { + margin: inherited; + } +} +// Small devices: Tablets (≥768px) +@media screen and (max-width: $screen-sm-max) and (min-width: $screen-sm){ + .hidden-sm { + display: none !important; + visibility: hidden !important; + } +} +@media screen and (min-width: $screen-md) { + .hidden-sm { + display: inherited; + visibility: visible !important; + } +} +@media screen and (max-width: $screen-xs-max) { + .hidden-sm { + display: inherited; + visibility: visible !important; + } +} +@media screen and (max-width: $screen-sm-max) { + .visible-sm { + display: inherited; + visibility: visible !important; + } +} +@media screen and (min-width: $screen-md) { + .visible-sm { + display: none !important; + visibility: hidden !important; + } +} +@media screen and (max-width: $screen-xs-max) { + .visible-sm { + display: none !important; + visibility: hidden !important; + } +} +@media screen and (max-width: $screen-sm-max) { + body { + cursor: url('http://ionicframework.com/img/finger.png'), auto; + } +} +@media screen and (min-width: $screen-md) { + body { + cursor: inherit; + } +} + +// Medium devices: Desktops (≥992px) +@media screen and (min-width: $screen-md) and (max-width: $screen-md-max) { + .hidden-md { + display: none !important; + visibility: hidden !important; + } +} +@media screen and (min-width: $screen-lg) { + .hidden-md { + display: inherit; + visibility: visible; + } +} +@media screen and (max-width: $screen-sm-max) { + .hidden-md { + display: inherit; + visibility: visible; + } +} +@media screen and (min-width: $screen-md) and (max-width: $screen-md-max) { + .visible-md { + display: inherit; + visibility: visible !important; + } +} +@media screen and (min-width: $screen-lg) { + .visible-md { + display: none; + visibility: hidden; + } +} +@media screen and (max-width: $screen-sm-max) { + .visible-md { + display: none; + visibility: hidden; + } +} + + +// Large devices: Desktops (≥1200px) +@media screen and (min-width: $screen-lg) { + .hidden-lg { + display: none !important; + visibility: hidden !important; + } +} +@media screen and (max-width: $screen-md-max) { + .hidden-lg { + display: inherited; + visibility: visible; + } +} +@media screen and (min-width: $screen-lg) { + .visible-lg { + display: inherited; + visibility: visible !important; + } +} +@media screen and (max-width: $screen-md-max) { + .visible-lg { + display: none; + visibility: hidden; + } +} diff --git a/www/css/ionic.app.css b/www/css/ionic.app.css new file mode 100644 index 0000000000000000000000000000000000000000..7818e9736f72502d58c45065529c6b4fbf0accbb --- /dev/null +++ b/www/css/ionic.app.css @@ -0,0 +1,12882 @@ +@charset "UTF-8"; +/* +To customize the look and feel of Ionic, you can override the variables +in ionic's _variables.scss file. + +For example, you might change some of the default colors: + +$light: #fff !default; +$stable: #f8f8f8 !default; +$positive: #387ef5 !default; +$calm: #11c1f3 !default; +$balanced: #33cd5f !default; +$energized: #ffc900 !default; +$assertive: #ef473a !default; +$royal: #886aea !default; +$dark: #444 !default; +*/ +/*! + Ionicons, v2.0.1 + Created by Ben Sperry for the Ionic Framework, http://ionicons.com/ + https://twitter.com/benjsperry https://twitter.com/ionicframework + MIT License: https://github.com/driftyco/ionicons + + Android-style icons originally built by Google’s + Material Design Icons: https://github.com/google/material-design-icons + used under CC BY http://creativecommons.org/licenses/by/4.0/ + Modified icons to fit ionicon’s grid from original. +*/ +@font-face { + font-family: "Ionicons"; + src: url("../lib/ionic/fonts/ionicons.eot?v=2.0.1"); + src: url("../lib/ionic/fonts/ionicons.eot?v=2.0.1#iefix") format("embedded-opentype"), url("../lib/ionic/fonts/ionicons.ttf?v=2.0.1") format("truetype"), url("../lib/ionic/fonts/ionicons.woff?v=2.0.1") format("woff"), url("../lib/ionic/fonts/ionicons.woff") format("woff"), url("../lib/ionic/fonts/ionicons.svg?v=2.0.1#Ionicons") format("svg"); + font-weight: normal; + font-style: normal; } + +.ion, .ionicons, +.ion-alert:before, +.ion-alert-circled:before, +.ion-android-add:before, +.ion-android-add-circle:before, +.ion-android-alarm-clock:before, +.ion-android-alert:before, +.ion-android-apps:before, +.ion-android-archive:before, +.ion-android-arrow-back:before, +.ion-android-arrow-down:before, +.ion-android-arrow-dropdown:before, +.ion-android-arrow-dropdown-circle:before, +.ion-android-arrow-dropleft:before, +.ion-android-arrow-dropleft-circle:before, +.ion-android-arrow-dropright:before, +.ion-android-arrow-dropright-circle:before, +.ion-android-arrow-dropup:before, +.ion-android-arrow-dropup-circle:before, +.ion-android-arrow-forward:before, +.ion-android-arrow-up:before, +.ion-android-attach:before, +.ion-android-bar:before, +.ion-android-bicycle:before, +.ion-android-boat:before, +.ion-android-bookmark:before, +.ion-android-bulb:before, +.ion-android-bus:before, +.ion-android-calendar:before, +.ion-android-call:before, +.ion-android-camera:before, +.ion-android-cancel:before, +.ion-android-car:before, +.ion-android-cart:before, +.ion-android-chat:before, +.ion-android-checkbox:before, +.ion-android-checkbox-blank:before, +.ion-android-checkbox-outline:before, +.ion-android-checkbox-outline-blank:before, +.ion-android-checkmark-circle:before, +.ion-android-clipboard:before, +.ion-android-close:before, +.ion-android-cloud:before, +.ion-android-cloud-circle:before, +.ion-android-cloud-done:before, +.ion-android-cloud-outline:before, +.ion-android-color-palette:before, +.ion-android-compass:before, +.ion-android-contact:before, +.ion-android-contacts:before, +.ion-android-contract:before, +.ion-android-create:before, +.ion-android-delete:before, +.ion-android-desktop:before, +.ion-android-document:before, +.ion-android-done:before, +.ion-android-done-all:before, +.ion-android-download:before, +.ion-android-drafts:before, +.ion-android-exit:before, +.ion-android-expand:before, +.ion-android-favorite:before, +.ion-android-favorite-outline:before, +.ion-android-film:before, +.ion-android-folder:before, +.ion-android-folder-open:before, +.ion-android-funnel:before, +.ion-android-globe:before, +.ion-android-hand:before, +.ion-android-hangout:before, +.ion-android-happy:before, +.ion-android-home:before, +.ion-android-image:before, +.ion-android-laptop:before, +.ion-android-list:before, +.ion-android-locate:before, +.ion-android-lock:before, +.ion-android-mail:before, +.ion-android-map:before, +.ion-android-menu:before, +.ion-android-microphone:before, +.ion-android-microphone-off:before, +.ion-android-more-horizontal:before, +.ion-android-more-vertical:before, +.ion-android-navigate:before, +.ion-android-notifications:before, +.ion-android-notifications-none:before, +.ion-android-notifications-off:before, +.ion-android-open:before, +.ion-android-options:before, +.ion-android-people:before, +.ion-android-person:before, +.ion-android-person-add:before, +.ion-android-phone-landscape:before, +.ion-android-phone-portrait:before, +.ion-android-pin:before, +.ion-android-plane:before, +.ion-android-playstore:before, +.ion-android-print:before, +.ion-android-radio-button-off:before, +.ion-android-radio-button-on:before, +.ion-android-refresh:before, +.ion-android-remove:before, +.ion-android-remove-circle:before, +.ion-android-restaurant:before, +.ion-android-sad:before, +.ion-android-search:before, +.ion-android-send:before, +.ion-android-settings:before, +.ion-android-share:before, +.ion-android-share-alt:before, +.ion-android-star:before, +.ion-android-star-half:before, +.ion-android-star-outline:before, +.ion-android-stopwatch:before, +.ion-android-subway:before, +.ion-android-sunny:before, +.ion-android-sync:before, +.ion-android-textsms:before, +.ion-android-time:before, +.ion-android-train:before, +.ion-android-unlock:before, +.ion-android-upload:before, +.ion-android-volume-down:before, +.ion-android-volume-mute:before, +.ion-android-volume-off:before, +.ion-android-volume-up:before, +.ion-android-walk:before, +.ion-android-warning:before, +.ion-android-watch:before, +.ion-android-wifi:before, +.ion-aperture:before, +.ion-archive:before, +.ion-arrow-down-a:before, +.ion-arrow-down-b:before, +.ion-arrow-down-c:before, +.ion-arrow-expand:before, +.ion-arrow-graph-down-left:before, +.ion-arrow-graph-down-right:before, +.ion-arrow-graph-up-left:before, +.ion-arrow-graph-up-right:before, +.ion-arrow-left-a:before, +.ion-arrow-left-b:before, +.ion-arrow-left-c:before, +.ion-arrow-move:before, +.ion-arrow-resize:before, +.ion-arrow-return-left:before, +.ion-arrow-return-right:before, +.ion-arrow-right-a:before, +.ion-arrow-right-b:before, +.ion-arrow-right-c:before, +.ion-arrow-shrink:before, +.ion-arrow-swap:before, +.ion-arrow-up-a:before, +.ion-arrow-up-b:before, +.ion-arrow-up-c:before, +.ion-asterisk:before, +.ion-at:before, +.ion-backspace:before, +.ion-backspace-outline:before, +.ion-bag:before, +.ion-battery-charging:before, +.ion-battery-empty:before, +.ion-battery-full:before, +.ion-battery-half:before, +.ion-battery-low:before, +.ion-beaker:before, +.ion-beer:before, +.ion-bluetooth:before, +.ion-bonfire:before, +.ion-bookmark:before, +.ion-bowtie:before, +.ion-briefcase:before, +.ion-bug:before, +.ion-calculator:before, +.ion-calendar:before, +.ion-camera:before, +.ion-card:before, +.ion-cash:before, +.ion-chatbox:before, +.ion-chatbox-working:before, +.ion-chatboxes:before, +.ion-chatbubble:before, +.ion-chatbubble-working:before, +.ion-chatbubbles:before, +.ion-checkmark:before, +.ion-checkmark-circled:before, +.ion-checkmark-round:before, +.ion-chevron-down:before, +.ion-chevron-left:before, +.ion-chevron-right:before, +.ion-chevron-up:before, +.ion-clipboard:before, +.ion-clock:before, +.ion-close:before, +.ion-close-circled:before, +.ion-close-round:before, +.ion-closed-captioning:before, +.ion-cloud:before, +.ion-code:before, +.ion-code-download:before, +.ion-code-working:before, +.ion-coffee:before, +.ion-compass:before, +.ion-compose:before, +.ion-connection-bars:before, +.ion-contrast:before, +.ion-crop:before, +.ion-cube:before, +.ion-disc:before, +.ion-document:before, +.ion-document-text:before, +.ion-drag:before, +.ion-earth:before, +.ion-easel:before, +.ion-edit:before, +.ion-egg:before, +.ion-eject:before, +.ion-email:before, +.ion-email-unread:before, +.ion-erlenmeyer-flask:before, +.ion-erlenmeyer-flask-bubbles:before, +.ion-eye:before, +.ion-eye-disabled:before, +.ion-female:before, +.ion-filing:before, +.ion-film-marker:before, +.ion-fireball:before, +.ion-flag:before, +.ion-flame:before, +.ion-flash:before, +.ion-flash-off:before, +.ion-folder:before, +.ion-fork:before, +.ion-fork-repo:before, +.ion-forward:before, +.ion-funnel:before, +.ion-gear-a:before, +.ion-gear-b:before, +.ion-grid:before, +.ion-hammer:before, +.ion-happy:before, +.ion-happy-outline:before, +.ion-headphone:before, +.ion-heart:before, +.ion-heart-broken:before, +.ion-help:before, +.ion-help-buoy:before, +.ion-help-circled:before, +.ion-home:before, +.ion-icecream:before, +.ion-image:before, +.ion-images:before, +.ion-information:before, +.ion-information-circled:before, +.ion-ionic:before, +.ion-ios-alarm:before, +.ion-ios-alarm-outline:before, +.ion-ios-albums:before, +.ion-ios-albums-outline:before, +.ion-ios-americanfootball:before, +.ion-ios-americanfootball-outline:before, +.ion-ios-analytics:before, +.ion-ios-analytics-outline:before, +.ion-ios-arrow-back:before, +.ion-ios-arrow-down:before, +.ion-ios-arrow-forward:before, +.ion-ios-arrow-left:before, +.ion-ios-arrow-right:before, +.ion-ios-arrow-thin-down:before, +.ion-ios-arrow-thin-left:before, +.ion-ios-arrow-thin-right:before, +.ion-ios-arrow-thin-up:before, +.ion-ios-arrow-up:before, +.ion-ios-at:before, +.ion-ios-at-outline:before, +.ion-ios-barcode:before, +.ion-ios-barcode-outline:before, +.ion-ios-baseball:before, +.ion-ios-baseball-outline:before, +.ion-ios-basketball:before, +.ion-ios-basketball-outline:before, +.ion-ios-bell:before, +.ion-ios-bell-outline:before, +.ion-ios-body:before, +.ion-ios-body-outline:before, +.ion-ios-bolt:before, +.ion-ios-bolt-outline:before, +.ion-ios-book:before, +.ion-ios-book-outline:before, +.ion-ios-bookmarks:before, +.ion-ios-bookmarks-outline:before, +.ion-ios-box:before, +.ion-ios-box-outline:before, +.ion-ios-briefcase:before, +.ion-ios-briefcase-outline:before, +.ion-ios-browsers:before, +.ion-ios-browsers-outline:before, +.ion-ios-calculator:before, +.ion-ios-calculator-outline:before, +.ion-ios-calendar:before, +.ion-ios-calendar-outline:before, +.ion-ios-camera:before, +.ion-ios-camera-outline:before, +.ion-ios-cart:before, +.ion-ios-cart-outline:before, +.ion-ios-chatboxes:before, +.ion-ios-chatboxes-outline:before, +.ion-ios-chatbubble:before, +.ion-ios-chatbubble-outline:before, +.ion-ios-checkmark:before, +.ion-ios-checkmark-empty:before, +.ion-ios-checkmark-outline:before, +.ion-ios-circle-filled:before, +.ion-ios-circle-outline:before, +.ion-ios-clock:before, +.ion-ios-clock-outline:before, +.ion-ios-close:before, +.ion-ios-close-empty:before, +.ion-ios-close-outline:before, +.ion-ios-cloud:before, +.ion-ios-cloud-download:before, +.ion-ios-cloud-download-outline:before, +.ion-ios-cloud-outline:before, +.ion-ios-cloud-upload:before, +.ion-ios-cloud-upload-outline:before, +.ion-ios-cloudy:before, +.ion-ios-cloudy-night:before, +.ion-ios-cloudy-night-outline:before, +.ion-ios-cloudy-outline:before, +.ion-ios-cog:before, +.ion-ios-cog-outline:before, +.ion-ios-color-filter:before, +.ion-ios-color-filter-outline:before, +.ion-ios-color-wand:before, +.ion-ios-color-wand-outline:before, +.ion-ios-compose:before, +.ion-ios-compose-outline:before, +.ion-ios-contact:before, +.ion-ios-contact-outline:before, +.ion-ios-copy:before, +.ion-ios-copy-outline:before, +.ion-ios-crop:before, +.ion-ios-crop-strong:before, +.ion-ios-download:before, +.ion-ios-download-outline:before, +.ion-ios-drag:before, +.ion-ios-email:before, +.ion-ios-email-outline:before, +.ion-ios-eye:before, +.ion-ios-eye-outline:before, +.ion-ios-fastforward:before, +.ion-ios-fastforward-outline:before, +.ion-ios-filing:before, +.ion-ios-filing-outline:before, +.ion-ios-film:before, +.ion-ios-film-outline:before, +.ion-ios-flag:before, +.ion-ios-flag-outline:before, +.ion-ios-flame:before, +.ion-ios-flame-outline:before, +.ion-ios-flask:before, +.ion-ios-flask-outline:before, +.ion-ios-flower:before, +.ion-ios-flower-outline:before, +.ion-ios-folder:before, +.ion-ios-folder-outline:before, +.ion-ios-football:before, +.ion-ios-football-outline:before, +.ion-ios-game-controller-a:before, +.ion-ios-game-controller-a-outline:before, +.ion-ios-game-controller-b:before, +.ion-ios-game-controller-b-outline:before, +.ion-ios-gear:before, +.ion-ios-gear-outline:before, +.ion-ios-glasses:before, +.ion-ios-glasses-outline:before, +.ion-ios-grid-view:before, +.ion-ios-grid-view-outline:before, +.ion-ios-heart:before, +.ion-ios-heart-outline:before, +.ion-ios-help:before, +.ion-ios-help-empty:before, +.ion-ios-help-outline:before, +.ion-ios-home:before, +.ion-ios-home-outline:before, +.ion-ios-infinite:before, +.ion-ios-infinite-outline:before, +.ion-ios-information:before, +.ion-ios-information-empty:before, +.ion-ios-information-outline:before, +.ion-ios-ionic-outline:before, +.ion-ios-keypad:before, +.ion-ios-keypad-outline:before, +.ion-ios-lightbulb:before, +.ion-ios-lightbulb-outline:before, +.ion-ios-list:before, +.ion-ios-list-outline:before, +.ion-ios-location:before, +.ion-ios-location-outline:before, +.ion-ios-locked:before, +.ion-ios-locked-outline:before, +.ion-ios-loop:before, +.ion-ios-loop-strong:before, +.ion-ios-medical:before, +.ion-ios-medical-outline:before, +.ion-ios-medkit:before, +.ion-ios-medkit-outline:before, +.ion-ios-mic:before, +.ion-ios-mic-off:before, +.ion-ios-mic-outline:before, +.ion-ios-minus:before, +.ion-ios-minus-empty:before, +.ion-ios-minus-outline:before, +.ion-ios-monitor:before, +.ion-ios-monitor-outline:before, +.ion-ios-moon:before, +.ion-ios-moon-outline:before, +.ion-ios-more:before, +.ion-ios-more-outline:before, +.ion-ios-musical-note:before, +.ion-ios-musical-notes:before, +.ion-ios-navigate:before, +.ion-ios-navigate-outline:before, +.ion-ios-nutrition:before, +.ion-ios-nutrition-outline:before, +.ion-ios-paper:before, +.ion-ios-paper-outline:before, +.ion-ios-paperplane:before, +.ion-ios-paperplane-outline:before, +.ion-ios-partlysunny:before, +.ion-ios-partlysunny-outline:before, +.ion-ios-pause:before, +.ion-ios-pause-outline:before, +.ion-ios-paw:before, +.ion-ios-paw-outline:before, +.ion-ios-people:before, +.ion-ios-people-outline:before, +.ion-ios-person:before, +.ion-ios-person-outline:before, +.ion-ios-personadd:before, +.ion-ios-personadd-outline:before, +.ion-ios-photos:before, +.ion-ios-photos-outline:before, +.ion-ios-pie:before, +.ion-ios-pie-outline:before, +.ion-ios-pint:before, +.ion-ios-pint-outline:before, +.ion-ios-play:before, +.ion-ios-play-outline:before, +.ion-ios-plus:before, +.ion-ios-plus-empty:before, +.ion-ios-plus-outline:before, +.ion-ios-pricetag:before, +.ion-ios-pricetag-outline:before, +.ion-ios-pricetags:before, +.ion-ios-pricetags-outline:before, +.ion-ios-printer:before, +.ion-ios-printer-outline:before, +.ion-ios-pulse:before, +.ion-ios-pulse-strong:before, +.ion-ios-rainy:before, +.ion-ios-rainy-outline:before, +.ion-ios-recording:before, +.ion-ios-recording-outline:before, +.ion-ios-redo:before, +.ion-ios-redo-outline:before, +.ion-ios-refresh:before, +.ion-ios-refresh-empty:before, +.ion-ios-refresh-outline:before, +.ion-ios-reload:before, +.ion-ios-reverse-camera:before, +.ion-ios-reverse-camera-outline:before, +.ion-ios-rewind:before, +.ion-ios-rewind-outline:before, +.ion-ios-rose:before, +.ion-ios-rose-outline:before, +.ion-ios-search:before, +.ion-ios-search-strong:before, +.ion-ios-settings:before, +.ion-ios-settings-strong:before, +.ion-ios-shuffle:before, +.ion-ios-shuffle-strong:before, +.ion-ios-skipbackward:before, +.ion-ios-skipbackward-outline:before, +.ion-ios-skipforward:before, +.ion-ios-skipforward-outline:before, +.ion-ios-snowy:before, +.ion-ios-speedometer:before, +.ion-ios-speedometer-outline:before, +.ion-ios-star:before, +.ion-ios-star-half:before, +.ion-ios-star-outline:before, +.ion-ios-stopwatch:before, +.ion-ios-stopwatch-outline:before, +.ion-ios-sunny:before, +.ion-ios-sunny-outline:before, +.ion-ios-telephone:before, +.ion-ios-telephone-outline:before, +.ion-ios-tennisball:before, +.ion-ios-tennisball-outline:before, +.ion-ios-thunderstorm:before, +.ion-ios-thunderstorm-outline:before, +.ion-ios-time:before, +.ion-ios-time-outline:before, +.ion-ios-timer:before, +.ion-ios-timer-outline:before, +.ion-ios-toggle:before, +.ion-ios-toggle-outline:before, +.ion-ios-trash:before, +.ion-ios-trash-outline:before, +.ion-ios-undo:before, +.ion-ios-undo-outline:before, +.ion-ios-unlocked:before, +.ion-ios-unlocked-outline:before, +.ion-ios-upload:before, +.ion-ios-upload-outline:before, +.ion-ios-videocam:before, +.ion-ios-videocam-outline:before, +.ion-ios-volume-high:before, +.ion-ios-volume-low:before, +.ion-ios-wineglass:before, +.ion-ios-wineglass-outline:before, +.ion-ios-world:before, +.ion-ios-world-outline:before, +.ion-ipad:before, +.ion-iphone:before, +.ion-ipod:before, +.ion-jet:before, +.ion-key:before, +.ion-knife:before, +.ion-laptop:before, +.ion-leaf:before, +.ion-levels:before, +.ion-lightbulb:before, +.ion-link:before, +.ion-load-a:before, +.ion-load-b:before, +.ion-load-c:before, +.ion-load-d:before, +.ion-location:before, +.ion-lock-combination:before, +.ion-locked:before, +.ion-log-in:before, +.ion-log-out:before, +.ion-loop:before, +.ion-magnet:before, +.ion-male:before, +.ion-man:before, +.ion-map:before, +.ion-medkit:before, +.ion-merge:before, +.ion-mic-a:before, +.ion-mic-b:before, +.ion-mic-c:before, +.ion-minus:before, +.ion-minus-circled:before, +.ion-minus-round:before, +.ion-model-s:before, +.ion-monitor:before, +.ion-more:before, +.ion-mouse:before, +.ion-music-note:before, +.ion-navicon:before, +.ion-navicon-round:before, +.ion-navigate:before, +.ion-network:before, +.ion-no-smoking:before, +.ion-nuclear:before, +.ion-outlet:before, +.ion-paintbrush:before, +.ion-paintbucket:before, +.ion-paper-airplane:before, +.ion-paperclip:before, +.ion-pause:before, +.ion-person:before, +.ion-person-add:before, +.ion-person-stalker:before, +.ion-pie-graph:before, +.ion-pin:before, +.ion-pinpoint:before, +.ion-pizza:before, +.ion-plane:before, +.ion-planet:before, +.ion-play:before, +.ion-playstation:before, +.ion-plus:before, +.ion-plus-circled:before, +.ion-plus-round:before, +.ion-podium:before, +.ion-pound:before, +.ion-power:before, +.ion-pricetag:before, +.ion-pricetags:before, +.ion-printer:before, +.ion-pull-request:before, +.ion-qr-scanner:before, +.ion-quote:before, +.ion-radio-waves:before, +.ion-record:before, +.ion-refresh:before, +.ion-reply:before, +.ion-reply-all:before, +.ion-ribbon-a:before, +.ion-ribbon-b:before, +.ion-sad:before, +.ion-sad-outline:before, +.ion-scissors:before, +.ion-search:before, +.ion-settings:before, +.ion-share:before, +.ion-shuffle:before, +.ion-skip-backward:before, +.ion-skip-forward:before, +.ion-social-android:before, +.ion-social-android-outline:before, +.ion-social-angular:before, +.ion-social-angular-outline:before, +.ion-social-apple:before, +.ion-social-apple-outline:before, +.ion-social-bitcoin:before, +.ion-social-bitcoin-outline:before, +.ion-social-buffer:before, +.ion-social-buffer-outline:before, +.ion-social-chrome:before, +.ion-social-chrome-outline:before, +.ion-social-codepen:before, +.ion-social-codepen-outline:before, +.ion-social-css3:before, +.ion-social-css3-outline:before, +.ion-social-designernews:before, +.ion-social-designernews-outline:before, +.ion-social-dribbble:before, +.ion-social-dribbble-outline:before, +.ion-social-dropbox:before, +.ion-social-dropbox-outline:before, +.ion-social-euro:before, +.ion-social-euro-outline:before, +.ion-social-facebook:before, +.ion-social-facebook-outline:before, +.ion-social-foursquare:before, +.ion-social-foursquare-outline:before, +.ion-social-freebsd-devil:before, +.ion-social-github:before, +.ion-social-github-outline:before, +.ion-social-google:before, +.ion-social-google-outline:before, +.ion-social-googleplus:before, +.ion-social-googleplus-outline:before, +.ion-social-hackernews:before, +.ion-social-hackernews-outline:before, +.ion-social-html5:before, +.ion-social-html5-outline:before, +.ion-social-instagram:before, +.ion-social-instagram-outline:before, +.ion-social-javascript:before, +.ion-social-javascript-outline:before, +.ion-social-linkedin:before, +.ion-social-linkedin-outline:before, +.ion-social-markdown:before, +.ion-social-nodejs:before, +.ion-social-octocat:before, +.ion-social-pinterest:before, +.ion-social-pinterest-outline:before, +.ion-social-python:before, +.ion-social-reddit:before, +.ion-social-reddit-outline:before, +.ion-social-rss:before, +.ion-social-rss-outline:before, +.ion-social-sass:before, +.ion-social-skype:before, +.ion-social-skype-outline:before, +.ion-social-snapchat:before, +.ion-social-snapchat-outline:before, +.ion-social-tumblr:before, +.ion-social-tumblr-outline:before, +.ion-social-tux:before, +.ion-social-twitch:before, +.ion-social-twitch-outline:before, +.ion-social-twitter:before, +.ion-social-twitter-outline:before, +.ion-social-usd:before, +.ion-social-usd-outline:before, +.ion-social-vimeo:before, +.ion-social-vimeo-outline:before, +.ion-social-whatsapp:before, +.ion-social-whatsapp-outline:before, +.ion-social-windows:before, +.ion-social-windows-outline:before, +.ion-social-wordpress:before, +.ion-social-wordpress-outline:before, +.ion-social-yahoo:before, +.ion-social-yahoo-outline:before, +.ion-social-yen:before, +.ion-social-yen-outline:before, +.ion-social-youtube:before, +.ion-social-youtube-outline:before, +.ion-soup-can:before, +.ion-soup-can-outline:before, +.ion-speakerphone:before, +.ion-speedometer:before, +.ion-spoon:before, +.ion-star:before, +.ion-stats-bars:before, +.ion-steam:before, +.ion-stop:before, +.ion-thermometer:before, +.ion-thumbsdown:before, +.ion-thumbsup:before, +.ion-toggle:before, +.ion-toggle-filled:before, +.ion-transgender:before, +.ion-trash-a:before, +.ion-trash-b:before, +.ion-trophy:before, +.ion-tshirt:before, +.ion-tshirt-outline:before, +.ion-umbrella:before, +.ion-university:before, +.ion-unlocked:before, +.ion-upload:before, +.ion-usb:before, +.ion-videocamera:before, +.ion-volume-high:before, +.ion-volume-low:before, +.ion-volume-medium:before, +.ion-volume-mute:before, +.ion-wand:before, +.ion-waterdrop:before, +.ion-wifi:before, +.ion-wineglass:before, +.ion-woman:before, +.ion-wrench:before, +.ion-xbox:before { + display: inline-block; + font-family: "Ionicons"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + text-rendering: auto; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + +.ion-alert:before { + content: "ï„"; } + +.ion-alert-circled:before { + content: "ï„€"; } + +.ion-android-add:before { + content: ""; } + +.ion-android-add-circle:before { + content: "ï™"; } + +.ion-android-alarm-clock:before { + content: "ïš"; } + +.ion-android-alert:before { + content: "ï›"; } + +.ion-android-apps:before { + content: "ïœ"; } + +.ion-android-archive:before { + content: ""; } + +.ion-android-arrow-back:before { + content: ""; } + +.ion-android-arrow-down:before { + content: "ï"; } + +.ion-android-arrow-dropdown:before { + content: "ïŸ"; } + +.ion-android-arrow-dropdown-circle:before { + content: "ïž"; } + +.ion-android-arrow-dropleft:before { + content: "ï¡"; } + +.ion-android-arrow-dropleft-circle:before { + content: "ï "; } + +.ion-android-arrow-dropright:before { + content: "ï£"; } + +.ion-android-arrow-dropright-circle:before { + content: "ï¢"; } + +.ion-android-arrow-dropup:before { + content: "ï¥"; } + +.ion-android-arrow-dropup-circle:before { + content: "ï¤"; } + +.ion-android-arrow-forward:before { + content: "ïŒ"; } + +.ion-android-arrow-up:before { + content: "ï¦"; } + +.ion-android-attach:before { + content: "ï§"; } + +.ion-android-bar:before { + content: "ï¨"; } + +.ion-android-bicycle:before { + content: "ï©"; } + +.ion-android-boat:before { + content: "ïª"; } + +.ion-android-bookmark:before { + content: "ï«"; } + +.ion-android-bulb:before { + content: "ï¬"; } + +.ion-android-bus:before { + content: "ï"; } + +.ion-android-calendar:before { + content: "ï‹‘"; } + +.ion-android-call:before { + content: "ï‹’"; } + +.ion-android-camera:before { + content: "ï‹“"; } + +.ion-android-cancel:before { + content: "ï®"; } + +.ion-android-car:before { + content: "ï¯"; } + +.ion-android-cart:before { + content: "ï°"; } + +.ion-android-chat:before { + content: "ï‹”"; } + +.ion-android-checkbox:before { + content: "ï´"; } + +.ion-android-checkbox-blank:before { + content: "ï±"; } + +.ion-android-checkbox-outline:before { + content: "ï³"; } + +.ion-android-checkbox-outline-blank:before { + content: "ï²"; } + +.ion-android-checkmark-circle:before { + content: "ïµ"; } + +.ion-android-clipboard:before { + content: "ï¶"; } + +.ion-android-close:before { + content: "ï‹—"; } + +.ion-android-cloud:before { + content: "ïº"; } + +.ion-android-cloud-circle:before { + content: "ï·"; } + +.ion-android-cloud-done:before { + content: "ï¸"; } + +.ion-android-cloud-outline:before { + content: "ï¹"; } + +.ion-android-color-palette:before { + content: "ï»"; } + +.ion-android-compass:before { + content: "ï¼"; } + +.ion-android-contact:before { + content: ""; } + +.ion-android-contacts:before { + content: "ï‹™"; } + +.ion-android-contract:before { + content: "ï½"; } + +.ion-android-create:before { + content: "ï¾"; } + +.ion-android-delete:before { + content: "ï¿"; } + +.ion-android-desktop:before { + content: ""; } + +.ion-android-document:before { + content: "ïŽ"; } + +.ion-android-done:before { + content: ""; } + +.ion-android-done-all:before { + content: ""; } + +.ion-android-download:before { + content: "ï‹"; } + +.ion-android-drafts:before { + content: ""; } + +.ion-android-exit:before { + content: ""; } + +.ion-android-expand:before { + content: ""; } + +.ion-android-favorite:before { + content: ""; } + +.ion-android-favorite-outline:before { + content: ""; } + +.ion-android-film:before { + content: ""; } + +.ion-android-folder:before { + content: "ï‹ "; } + +.ion-android-folder-open:before { + content: ""; } + +.ion-android-funnel:before { + content: ""; } + +.ion-android-globe:before { + content: ""; } + +.ion-android-hand:before { + content: "ï‹£"; } + +.ion-android-hangout:before { + content: "ïŽ"; } + +.ion-android-happy:before { + content: ""; } + +.ion-android-home:before { + content: "ïŽ"; } + +.ion-android-image:before { + content: ""; } + +.ion-android-laptop:before { + content: "ïŽ"; } + +.ion-android-list:before { + content: ""; } + +.ion-android-locate:before { + content: "ï‹©"; } + +.ion-android-lock:before { + content: ""; } + +.ion-android-mail:before { + content: "ï‹«"; } + +.ion-android-map:before { + content: ""; } + +.ion-android-menu:before { + content: ""; } + +.ion-android-microphone:before { + content: ""; } + +.ion-android-microphone-off:before { + content: ""; } + +.ion-android-more-horizontal:before { + content: ""; } + +.ion-android-more-vertical:before { + content: ""; } + +.ion-android-navigate:before { + content: ""; } + +.ion-android-notifications:before { + content: ""; } + +.ion-android-notifications-none:before { + content: ""; } + +.ion-android-notifications-off:before { + content: ""; } + +.ion-android-open:before { + content: ""; } + +.ion-android-options:before { + content: "ïŽ"; } + +.ion-android-people:before { + content: ""; } + +.ion-android-person:before { + content: "ïŽ "; } + +.ion-android-person-add:before { + content: ""; } + +.ion-android-phone-landscape:before { + content: ""; } + +.ion-android-phone-portrait:before { + content: ""; } + +.ion-android-pin:before { + content: ""; } + +.ion-android-plane:before { + content: ""; } + +.ion-android-playstore:before { + content: "ï‹°"; } + +.ion-android-print:before { + content: ""; } + +.ion-android-radio-button-off:before { + content: ""; } + +.ion-android-radio-button-on:before { + content: ""; } + +.ion-android-refresh:before { + content: ""; } + +.ion-android-remove:before { + content: "ï‹´"; } + +.ion-android-remove-circle:before { + content: ""; } + +.ion-android-restaurant:before { + content: ""; } + +.ion-android-sad:before { + content: ""; } + +.ion-android-search:before { + content: ""; } + +.ion-android-send:before { + content: "ï‹¶"; } + +.ion-android-settings:before { + content: "ï‹·"; } + +.ion-android-share:before { + content: ""; } + +.ion-android-share-alt:before { + content: ""; } + +.ion-android-star:before { + content: ""; } + +.ion-android-star-half:before { + content: "ïŽ"; } + +.ion-android-star-outline:before { + content: ""; } + +.ion-android-stopwatch:before { + content: ""; } + +.ion-android-subway:before { + content: ""; } + +.ion-android-sunny:before { + content: ""; } + +.ion-android-sync:before { + content: ""; } + +.ion-android-textsms:before { + content: ""; } + +.ion-android-time:before { + content: ""; } + +.ion-android-train:before { + content: ""; } + +.ion-android-unlock:before { + content: ""; } + +.ion-android-upload:before { + content: ""; } + +.ion-android-volume-down:before { + content: ""; } + +.ion-android-volume-mute:before { + content: ""; } + +.ion-android-volume-off:before { + content: ""; } + +.ion-android-volume-up:before { + content: ""; } + +.ion-android-walk:before { + content: ""; } + +.ion-android-warning:before { + content: ""; } + +.ion-android-watch:before { + content: ""; } + +.ion-android-wifi:before { + content: ""; } + +.ion-aperture:before { + content: ""; } + +.ion-archive:before { + content: "ï„‚"; } + +.ion-arrow-down-a:before { + content: ""; } + +.ion-arrow-down-b:before { + content: "ï„„"; } + +.ion-arrow-down-c:before { + content: "ï„…"; } + +.ion-arrow-expand:before { + content: ""; } + +.ion-arrow-graph-down-left:before { + content: ""; } + +.ion-arrow-graph-down-right:before { + content: "ï‰ "; } + +.ion-arrow-graph-up-left:before { + content: ""; } + +.ion-arrow-graph-up-right:before { + content: ""; } + +.ion-arrow-left-a:before { + content: ""; } + +.ion-arrow-left-b:before { + content: ""; } + +.ion-arrow-left-c:before { + content: ""; } + +.ion-arrow-move:before { + content: ""; } + +.ion-arrow-resize:before { + content: ""; } + +.ion-arrow-return-left:before { + content: ""; } + +.ion-arrow-return-right:before { + content: ""; } + +.ion-arrow-right-a:before { + content: ""; } + +.ion-arrow-right-b:before { + content: ""; } + +.ion-arrow-right-c:before { + content: "ï„‹"; } + +.ion-arrow-shrink:before { + content: ""; } + +.ion-arrow-swap:before { + content: ""; } + +.ion-arrow-up-a:before { + content: ""; } + +.ion-arrow-up-b:before { + content: "ï„"; } + +.ion-arrow-up-c:before { + content: ""; } + +.ion-asterisk:before { + content: ""; } + +.ion-at:before { + content: "ï„"; } + +.ion-backspace:before { + content: ""; } + +.ion-backspace-outline:before { + content: ""; } + +.ion-bag:before { + content: "ï„"; } + +.ion-battery-charging:before { + content: "ï„‘"; } + +.ion-battery-empty:before { + content: "ï„’"; } + +.ion-battery-full:before { + content: "ï„“"; } + +.ion-battery-half:before { + content: "ï„”"; } + +.ion-battery-low:before { + content: "ï„•"; } + +.ion-beaker:before { + content: ""; } + +.ion-beer:before { + content: ""; } + +.ion-bluetooth:before { + content: "ï„–"; } + +.ion-bonfire:before { + content: ""; } + +.ion-bookmark:before { + content: ""; } + +.ion-bowtie:before { + content: "ï€"; } + +.ion-briefcase:before { + content: ""; } + +.ion-bug:before { + content: ""; } + +.ion-calculator:before { + content: "ï‰"; } + +.ion-calendar:before { + content: "ï„—"; } + +.ion-camera:before { + content: ""; } + +.ion-card:before { + content: "ï„™"; } + +.ion-cash:before { + content: ""; } + +.ion-chatbox:before { + content: "ï„›"; } + +.ion-chatbox-working:before { + content: ""; } + +.ion-chatboxes:before { + content: ""; } + +.ion-chatbubble:before { + content: ""; } + +.ion-chatbubble-working:before { + content: "ï„"; } + +.ion-chatbubbles:before { + content: ""; } + +.ion-checkmark:before { + content: "ï„¢"; } + +.ion-checkmark-circled:before { + content: "ï„ "; } + +.ion-checkmark-round:before { + content: "ï„¡"; } + +.ion-chevron-down:before { + content: "ï„£"; } + +.ion-chevron-left:before { + content: ""; } + +.ion-chevron-right:before { + content: "ï„¥"; } + +.ion-chevron-up:before { + content: ""; } + +.ion-clipboard:before { + content: "ï„§"; } + +.ion-clock:before { + content: ""; } + +.ion-close:before { + content: ""; } + +.ion-close-circled:before { + content: ""; } + +.ion-close-round:before { + content: "ï„©"; } + +.ion-closed-captioning:before { + content: ""; } + +.ion-cloud:before { + content: "ï„«"; } + +.ion-code:before { + content: ""; } + +.ion-code-download:before { + content: ""; } + +.ion-code-working:before { + content: ""; } + +.ion-coffee:before { + content: ""; } + +.ion-compass:before { + content: ""; } + +.ion-compose:before { + content: ""; } + +.ion-connection-bars:before { + content: ""; } + +.ion-contrast:before { + content: ""; } + +.ion-crop:before { + content: "ï"; } + +.ion-cube:before { + content: ""; } + +.ion-disc:before { + content: "ï„"; } + +.ion-document:before { + content: ""; } + +.ion-document-text:before { + content: "ï„®"; } + +.ion-drag:before { + content: "ï„°"; } + +.ion-earth:before { + content: ""; } + +.ion-easel:before { + content: "ï‚"; } + +.ion-edit:before { + content: ""; } + +.ion-egg:before { + content: ""; } + +.ion-eject:before { + content: ""; } + +.ion-email:before { + content: ""; } + +.ion-email-unread:before { + content: "ïƒ"; } + +.ion-erlenmeyer-flask:before { + content: "ï…"; } + +.ion-erlenmeyer-flask-bubbles:before { + content: "ï„"; } + +.ion-eye:before { + content: ""; } + +.ion-eye-disabled:before { + content: ""; } + +.ion-female:before { + content: ""; } + +.ion-filing:before { + content: "ï„´"; } + +.ion-film-marker:before { + content: ""; } + +.ion-fireball:before { + content: ""; } + +.ion-flag:before { + content: ""; } + +.ion-flame:before { + content: ""; } + +.ion-flash:before { + content: "ï„·"; } + +.ion-flash-off:before { + content: "ï„¶"; } + +.ion-folder:before { + content: ""; } + +.ion-fork:before { + content: ""; } + +.ion-fork-repo:before { + content: "ï‹€"; } + +.ion-forward:before { + content: ""; } + +.ion-funnel:before { + content: ""; } + +.ion-gear-a:before { + content: ""; } + +.ion-gear-b:before { + content: ""; } + +.ion-grid:before { + content: "ï„¿"; } + +.ion-hammer:before { + content: ""; } + +.ion-happy:before { + content: ""; } + +.ion-happy-outline:before { + content: "ï†"; } + +.ion-headphone:before { + content: "ï…€"; } + +.ion-heart:before { + content: "ï…"; } + +.ion-heart-broken:before { + content: "ïŒ"; } + +.ion-help:before { + content: "ï…ƒ"; } + +.ion-help-buoy:before { + content: ""; } + +.ion-help-circled:before { + content: "ï…‚"; } + +.ion-home:before { + content: "ï…„"; } + +.ion-icecream:before { + content: ""; } + +.ion-image:before { + content: "ï…‡"; } + +.ion-images:before { + content: "ï…ˆ"; } + +.ion-information:before { + content: "ï…Š"; } + +.ion-information-circled:before { + content: "ï…‰"; } + +.ion-ionic:before { + content: "ï…‹"; } + +.ion-ios-alarm:before { + content: "ïˆ"; } + +.ion-ios-alarm-outline:before { + content: "ï‡"; } + +.ion-ios-albums:before { + content: "ïŠ"; } + +.ion-ios-albums-outline:before { + content: "ï‰"; } + +.ion-ios-americanfootball:before { + content: "ïŒ"; } + +.ion-ios-americanfootball-outline:before { + content: "ï‹"; } + +.ion-ios-analytics:before { + content: "ïŽ"; } + +.ion-ios-analytics-outline:before { + content: "ï"; } + +.ion-ios-arrow-back:before { + content: "ï"; } + +.ion-ios-arrow-down:before { + content: "ï"; } + +.ion-ios-arrow-forward:before { + content: "ï‘"; } + +.ion-ios-arrow-left:before { + content: "ï’"; } + +.ion-ios-arrow-right:before { + content: "ï“"; } + +.ion-ios-arrow-thin-down:before { + content: "ï”"; } + +.ion-ios-arrow-thin-left:before { + content: "ï•"; } + +.ion-ios-arrow-thin-right:before { + content: "ï–"; } + +.ion-ios-arrow-thin-up:before { + content: "ï—"; } + +.ion-ios-arrow-up:before { + content: "ï˜"; } + +.ion-ios-at:before { + content: "ïš"; } + +.ion-ios-at-outline:before { + content: "ï™"; } + +.ion-ios-barcode:before { + content: "ïœ"; } + +.ion-ios-barcode-outline:before { + content: "ï›"; } + +.ion-ios-baseball:before { + content: "ïž"; } + +.ion-ios-baseball-outline:before { + content: "ï"; } + +.ion-ios-basketball:before { + content: "ï "; } + +.ion-ios-basketball-outline:before { + content: "ïŸ"; } + +.ion-ios-bell:before { + content: "ï¢"; } + +.ion-ios-bell-outline:before { + content: "ï¡"; } + +.ion-ios-body:before { + content: "ï¤"; } + +.ion-ios-body-outline:before { + content: "ï£"; } + +.ion-ios-bolt:before { + content: "ï¦"; } + +.ion-ios-bolt-outline:before { + content: "ï¥"; } + +.ion-ios-book:before { + content: "ï¨"; } + +.ion-ios-book-outline:before { + content: "ï§"; } + +.ion-ios-bookmarks:before { + content: "ïª"; } + +.ion-ios-bookmarks-outline:before { + content: "ï©"; } + +.ion-ios-box:before { + content: "ï¬"; } + +.ion-ios-box-outline:before { + content: "ï«"; } + +.ion-ios-briefcase:before { + content: "ï®"; } + +.ion-ios-briefcase-outline:before { + content: "ï"; } + +.ion-ios-browsers:before { + content: "ï°"; } + +.ion-ios-browsers-outline:before { + content: "ï¯"; } + +.ion-ios-calculator:before { + content: "ï²"; } + +.ion-ios-calculator-outline:before { + content: "ï±"; } + +.ion-ios-calendar:before { + content: "ï´"; } + +.ion-ios-calendar-outline:before { + content: "ï³"; } + +.ion-ios-camera:before { + content: "ï¶"; } + +.ion-ios-camera-outline:before { + content: "ïµ"; } + +.ion-ios-cart:before { + content: "ï¸"; } + +.ion-ios-cart-outline:before { + content: "ï·"; } + +.ion-ios-chatboxes:before { + content: "ïº"; } + +.ion-ios-chatboxes-outline:before { + content: "ï¹"; } + +.ion-ios-chatbubble:before { + content: "ï¼"; } + +.ion-ios-chatbubble-outline:before { + content: "ï»"; } + +.ion-ios-checkmark:before { + content: "ï¿"; } + +.ion-ios-checkmark-empty:before { + content: "ï½"; } + +.ion-ios-checkmark-outline:before { + content: "ï¾"; } + +.ion-ios-circle-filled:before { + content: "ï€"; } + +.ion-ios-circle-outline:before { + content: "ï"; } + +.ion-ios-clock:before { + content: "ïƒ"; } + +.ion-ios-clock-outline:before { + content: "ï‚"; } + +.ion-ios-close:before { + content: "ï†"; } + +.ion-ios-close-empty:before { + content: "ï„"; } + +.ion-ios-close-outline:before { + content: "ï…"; } + +.ion-ios-cloud:before { + content: "ïŒ"; } + +.ion-ios-cloud-download:before { + content: "ïˆ"; } + +.ion-ios-cloud-download-outline:before { + content: "ï‡"; } + +.ion-ios-cloud-outline:before { + content: "ï‰"; } + +.ion-ios-cloud-upload:before { + content: "ï‹"; } + +.ion-ios-cloud-upload-outline:before { + content: "ïŠ"; } + +.ion-ios-cloudy:before { + content: "ï"; } + +.ion-ios-cloudy-night:before { + content: "ïŽ"; } + +.ion-ios-cloudy-night-outline:before { + content: "ï"; } + +.ion-ios-cloudy-outline:before { + content: "ï"; } + +.ion-ios-cog:before { + content: "ï’"; } + +.ion-ios-cog-outline:before { + content: "ï‘"; } + +.ion-ios-color-filter:before { + content: "ï”"; } + +.ion-ios-color-filter-outline:before { + content: "ï“"; } + +.ion-ios-color-wand:before { + content: "ï–"; } + +.ion-ios-color-wand-outline:before { + content: "ï•"; } + +.ion-ios-compose:before { + content: "ï˜"; } + +.ion-ios-compose-outline:before { + content: "ï—"; } + +.ion-ios-contact:before { + content: "ïš"; } + +.ion-ios-contact-outline:before { + content: "ï™"; } + +.ion-ios-copy:before { + content: "ïœ"; } + +.ion-ios-copy-outline:before { + content: "ï›"; } + +.ion-ios-crop:before { + content: "ïž"; } + +.ion-ios-crop-strong:before { + content: "ï"; } + +.ion-ios-download:before { + content: "ï "; } + +.ion-ios-download-outline:before { + content: "ïŸ"; } + +.ion-ios-drag:before { + content: "ï¡"; } + +.ion-ios-email:before { + content: "ï£"; } + +.ion-ios-email-outline:before { + content: "ï¢"; } + +.ion-ios-eye:before { + content: "ï¥"; } + +.ion-ios-eye-outline:before { + content: "ï¤"; } + +.ion-ios-fastforward:before { + content: "ï§"; } + +.ion-ios-fastforward-outline:before { + content: "ï¦"; } + +.ion-ios-filing:before { + content: "ï©"; } + +.ion-ios-filing-outline:before { + content: "ï¨"; } + +.ion-ios-film:before { + content: "ï«"; } + +.ion-ios-film-outline:before { + content: "ïª"; } + +.ion-ios-flag:before { + content: "ï"; } + +.ion-ios-flag-outline:before { + content: "ï¬"; } + +.ion-ios-flame:before { + content: "ï¯"; } + +.ion-ios-flame-outline:before { + content: "ï®"; } + +.ion-ios-flask:before { + content: "ï±"; } + +.ion-ios-flask-outline:before { + content: "ï°"; } + +.ion-ios-flower:before { + content: "ï³"; } + +.ion-ios-flower-outline:before { + content: "ï²"; } + +.ion-ios-folder:before { + content: "ïµ"; } + +.ion-ios-folder-outline:before { + content: "ï´"; } + +.ion-ios-football:before { + content: "ï·"; } + +.ion-ios-football-outline:before { + content: "ï¶"; } + +.ion-ios-game-controller-a:before { + content: "ï¹"; } + +.ion-ios-game-controller-a-outline:before { + content: "ï¸"; } + +.ion-ios-game-controller-b:before { + content: "ï»"; } + +.ion-ios-game-controller-b-outline:before { + content: "ïº"; } + +.ion-ios-gear:before { + content: "ï½"; } + +.ion-ios-gear-outline:before { + content: "ï¼"; } + +.ion-ios-glasses:before { + content: "ï¿"; } + +.ion-ios-glasses-outline:before { + content: "ï¾"; } + +.ion-ios-grid-view:before { + content: "ï‘"; } + +.ion-ios-grid-view-outline:before { + content: "ï‘€"; } + +.ion-ios-heart:before { + content: ""; } + +.ion-ios-heart-outline:before { + content: "ï‘‚"; } + +.ion-ios-help:before { + content: ""; } + +.ion-ios-help-empty:before { + content: "ï‘„"; } + +.ion-ios-help-outline:before { + content: "ï‘…"; } + +.ion-ios-home:before { + content: ""; } + +.ion-ios-home-outline:before { + content: ""; } + +.ion-ios-infinite:before { + content: ""; } + +.ion-ios-infinite-outline:before { + content: ""; } + +.ion-ios-information:before { + content: "ï‘"; } + +.ion-ios-information-empty:before { + content: "ï‘‹"; } + +.ion-ios-information-outline:before { + content: ""; } + +.ion-ios-ionic-outline:before { + content: ""; } + +.ion-ios-keypad:before { + content: "ï‘"; } + +.ion-ios-keypad-outline:before { + content: "ï‘"; } + +.ion-ios-lightbulb:before { + content: "ï‘’"; } + +.ion-ios-lightbulb-outline:before { + content: "ï‘‘"; } + +.ion-ios-list:before { + content: "ï‘”"; } + +.ion-ios-list-outline:before { + content: "ï‘“"; } + +.ion-ios-location:before { + content: "ï‘–"; } + +.ion-ios-location-outline:before { + content: "ï‘•"; } + +.ion-ios-locked:before { + content: ""; } + +.ion-ios-locked-outline:before { + content: "ï‘—"; } + +.ion-ios-loop:before { + content: ""; } + +.ion-ios-loop-strong:before { + content: "ï‘™"; } + +.ion-ios-medical:before { + content: ""; } + +.ion-ios-medical-outline:before { + content: "ï‘›"; } + +.ion-ios-medkit:before { + content: ""; } + +.ion-ios-medkit-outline:before { + content: "ï‘"; } + +.ion-ios-mic:before { + content: "ï‘¡"; } + +.ion-ios-mic-off:before { + content: ""; } + +.ion-ios-mic-outline:before { + content: "ï‘ "; } + +.ion-ios-minus:before { + content: ""; } + +.ion-ios-minus-empty:before { + content: "ï‘¢"; } + +.ion-ios-minus-outline:before { + content: "ï‘£"; } + +.ion-ios-monitor:before { + content: ""; } + +.ion-ios-monitor-outline:before { + content: "ï‘¥"; } + +.ion-ios-moon:before { + content: ""; } + +.ion-ios-moon-outline:before { + content: "ï‘§"; } + +.ion-ios-more:before { + content: ""; } + +.ion-ios-more-outline:before { + content: "ï‘©"; } + +.ion-ios-musical-note:before { + content: "ï‘«"; } + +.ion-ios-musical-notes:before { + content: ""; } + +.ion-ios-navigate:before { + content: "ï‘®"; } + +.ion-ios-navigate-outline:before { + content: "ï‘"; } + +.ion-ios-nutrition:before { + content: "ï‘°"; } + +.ion-ios-nutrition-outline:before { + content: ""; } + +.ion-ios-paper:before { + content: ""; } + +.ion-ios-paper-outline:before { + content: ""; } + +.ion-ios-paperplane:before { + content: "ï‘´"; } + +.ion-ios-paperplane-outline:before { + content: ""; } + +.ion-ios-partlysunny:before { + content: "ï‘¶"; } + +.ion-ios-partlysunny-outline:before { + content: ""; } + +.ion-ios-pause:before { + content: ""; } + +.ion-ios-pause-outline:before { + content: "ï‘·"; } + +.ion-ios-paw:before { + content: ""; } + +.ion-ios-paw-outline:before { + content: ""; } + +.ion-ios-people:before { + content: ""; } + +.ion-ios-people-outline:before { + content: "ï‘»"; } + +.ion-ios-person:before { + content: ""; } + +.ion-ios-person-outline:before { + content: ""; } + +.ion-ios-personadd:before { + content: "ï’€"; } + +.ion-ios-personadd-outline:before { + content: "ï‘¿"; } + +.ion-ios-photos:before { + content: "ï’‚"; } + +.ion-ios-photos-outline:before { + content: "ï’"; } + +.ion-ios-pie:before { + content: "ï’„"; } + +.ion-ios-pie-outline:before { + content: "ï’ƒ"; } + +.ion-ios-pint:before { + content: "ï’†"; } + +.ion-ios-pint-outline:before { + content: "ï’…"; } + +.ion-ios-play:before { + content: "ï’ˆ"; } + +.ion-ios-play-outline:before { + content: "ï’‡"; } + +.ion-ios-plus:before { + content: "ï’‹"; } + +.ion-ios-plus-empty:before { + content: "ï’‰"; } + +.ion-ios-plus-outline:before { + content: "ï’Š"; } + +.ion-ios-pricetag:before { + content: "ï’"; } + +.ion-ios-pricetag-outline:before { + content: "ï’Œ"; } + +.ion-ios-pricetags:before { + content: "ï’"; } + +.ion-ios-pricetags-outline:before { + content: "ï’Ž"; } + +.ion-ios-printer:before { + content: "ï’‘"; } + +.ion-ios-printer-outline:before { + content: "ï’"; } + +.ion-ios-pulse:before { + content: "ï’“"; } + +.ion-ios-pulse-strong:before { + content: "ï’’"; } + +.ion-ios-rainy:before { + content: "ï’•"; } + +.ion-ios-rainy-outline:before { + content: "ï’”"; } + +.ion-ios-recording:before { + content: "ï’—"; } + +.ion-ios-recording-outline:before { + content: "ï’–"; } + +.ion-ios-redo:before { + content: "ï’™"; } + +.ion-ios-redo-outline:before { + content: "ï’˜"; } + +.ion-ios-refresh:before { + content: "ï’œ"; } + +.ion-ios-refresh-empty:before { + content: "ï’š"; } + +.ion-ios-refresh-outline:before { + content: "ï’›"; } + +.ion-ios-reload:before { + content: "ï’"; } + +.ion-ios-reverse-camera:before { + content: "ï’Ÿ"; } + +.ion-ios-reverse-camera-outline:before { + content: "ï’ž"; } + +.ion-ios-rewind:before { + content: "ï’¡"; } + +.ion-ios-rewind-outline:before { + content: "ï’ "; } + +.ion-ios-rose:before { + content: "ï’£"; } + +.ion-ios-rose-outline:before { + content: "ï’¢"; } + +.ion-ios-search:before { + content: "ï’¥"; } + +.ion-ios-search-strong:before { + content: "ï’¤"; } + +.ion-ios-settings:before { + content: "ï’§"; } + +.ion-ios-settings-strong:before { + content: "ï’¦"; } + +.ion-ios-shuffle:before { + content: "ï’©"; } + +.ion-ios-shuffle-strong:before { + content: "ï’¨"; } + +.ion-ios-skipbackward:before { + content: "ï’«"; } + +.ion-ios-skipbackward-outline:before { + content: "ï’ª"; } + +.ion-ios-skipforward:before { + content: "ï’"; } + +.ion-ios-skipforward-outline:before { + content: "ï’¬"; } + +.ion-ios-snowy:before { + content: "ï’®"; } + +.ion-ios-speedometer:before { + content: "ï’°"; } + +.ion-ios-speedometer-outline:before { + content: "ï’¯"; } + +.ion-ios-star:before { + content: "ï’³"; } + +.ion-ios-star-half:before { + content: "ï’±"; } + +.ion-ios-star-outline:before { + content: "ï’²"; } + +.ion-ios-stopwatch:before { + content: "ï’µ"; } + +.ion-ios-stopwatch-outline:before { + content: "ï’´"; } + +.ion-ios-sunny:before { + content: "ï’·"; } + +.ion-ios-sunny-outline:before { + content: "ï’¶"; } + +.ion-ios-telephone:before { + content: "ï’¹"; } + +.ion-ios-telephone-outline:before { + content: "ï’¸"; } + +.ion-ios-tennisball:before { + content: "ï’»"; } + +.ion-ios-tennisball-outline:before { + content: "ï’º"; } + +.ion-ios-thunderstorm:before { + content: "ï’½"; } + +.ion-ios-thunderstorm-outline:before { + content: "ï’¼"; } + +.ion-ios-time:before { + content: "ï’¿"; } + +.ion-ios-time-outline:before { + content: "ï’¾"; } + +.ion-ios-timer:before { + content: "ï“"; } + +.ion-ios-timer-outline:before { + content: "ï“€"; } + +.ion-ios-toggle:before { + content: ""; } + +.ion-ios-toggle-outline:before { + content: "ï“‚"; } + +.ion-ios-trash:before { + content: "ï“…"; } + +.ion-ios-trash-outline:before { + content: "ï“„"; } + +.ion-ios-undo:before { + content: ""; } + +.ion-ios-undo-outline:before { + content: ""; } + +.ion-ios-unlocked:before { + content: ""; } + +.ion-ios-unlocked-outline:before { + content: ""; } + +.ion-ios-upload:before { + content: "ï“‹"; } + +.ion-ios-upload-outline:before { + content: ""; } + +.ion-ios-videocam:before { + content: "ï“"; } + +.ion-ios-videocam-outline:before { + content: ""; } + +.ion-ios-volume-high:before { + content: ""; } + +.ion-ios-volume-low:before { + content: "ï“"; } + +.ion-ios-wineglass:before { + content: "ï“‘"; } + +.ion-ios-wineglass-outline:before { + content: "ï“"; } + +.ion-ios-world:before { + content: "ï““"; } + +.ion-ios-world-outline:before { + content: "ï“’"; } + +.ion-ipad:before { + content: ""; } + +.ion-iphone:before { + content: ""; } + +.ion-ipod:before { + content: ""; } + +.ion-jet:before { + content: ""; } + +.ion-key:before { + content: ""; } + +.ion-knife:before { + content: ""; } + +.ion-laptop:before { + content: ""; } + +.ion-leaf:before { + content: ""; } + +.ion-levels:before { + content: ""; } + +.ion-lightbulb:before { + content: ""; } + +.ion-link:before { + content: ""; } + +.ion-load-a:before { + content: ""; } + +.ion-load-b:before { + content: ""; } + +.ion-load-c:before { + content: ""; } + +.ion-load-d:before { + content: "ïŠ"; } + +.ion-location:before { + content: ""; } + +.ion-lock-combination:before { + content: "ï“”"; } + +.ion-locked:before { + content: ""; } + +.ion-log-in:before { + content: ""; } + +.ion-log-out:before { + content: ""; } + +.ion-loop:before { + content: "ïˆ"; } + +.ion-magnet:before { + content: "ïŠ "; } + +.ion-male:before { + content: ""; } + +.ion-man:before { + content: ""; } + +.ion-map:before { + content: ""; } + +.ion-medkit:before { + content: ""; } + +.ion-merge:before { + content: ""; } + +.ion-mic-a:before { + content: ""; } + +.ion-mic-b:before { + content: ""; } + +.ion-mic-c:before { + content: ""; } + +.ion-minus:before { + content: ""; } + +.ion-minus-circled:before { + content: ""; } + +.ion-minus-round:before { + content: ""; } + +.ion-model-s:before { + content: "ï‹"; } + +.ion-monitor:before { + content: ""; } + +.ion-more:before { + content: ""; } + +.ion-mouse:before { + content: "ï€"; } + +.ion-music-note:before { + content: ""; } + +.ion-navicon:before { + content: ""; } + +.ion-navicon-round:before { + content: "ïˆ"; } + +.ion-navigate:before { + content: ""; } + +.ion-network:before { + content: "ï"; } + +.ion-no-smoking:before { + content: "ï‹‚"; } + +.ion-nuclear:before { + content: ""; } + +.ion-outlet:before { + content: "ï‚"; } + +.ion-paintbrush:before { + content: "ï“•"; } + +.ion-paintbucket:before { + content: "ï“–"; } + +.ion-paper-airplane:before { + content: ""; } + +.ion-paperclip:before { + content: "ïˆ"; } + +.ion-pause:before { + content: "ïˆ"; } + +.ion-person:before { + content: ""; } + +.ion-person-add:before { + content: ""; } + +.ion-person-stalker:before { + content: ""; } + +.ion-pie-graph:before { + content: ""; } + +.ion-pin:before { + content: ""; } + +.ion-pinpoint:before { + content: ""; } + +.ion-pizza:before { + content: ""; } + +.ion-plane:before { + content: ""; } + +.ion-planet:before { + content: "ïƒ"; } + +.ion-play:before { + content: ""; } + +.ion-playstation:before { + content: ""; } + +.ion-plus:before { + content: ""; } + +.ion-plus-circled:before { + content: ""; } + +.ion-plus-round:before { + content: ""; } + +.ion-podium:before { + content: "ï„"; } + +.ion-pound:before { + content: ""; } + +.ion-power:before { + content: ""; } + +.ion-pricetag:before { + content: ""; } + +.ion-pricetags:before { + content: ""; } + +.ion-printer:before { + content: ""; } + +.ion-pull-request:before { + content: "ï…"; } + +.ion-qr-scanner:before { + content: "ï†"; } + +.ion-quote:before { + content: "ï‡"; } + +.ion-radio-waves:before { + content: ""; } + +.ion-record:before { + content: ""; } + +.ion-refresh:before { + content: ""; } + +.ion-reply:before { + content: ""; } + +.ion-reply-all:before { + content: "ïˆ"; } + +.ion-ribbon-a:before { + content: "ïˆ"; } + +.ion-ribbon-b:before { + content: "ï‰"; } + +.ion-sad:before { + content: "ïŠ"; } + +.ion-sad-outline:before { + content: "ï“—"; } + +.ion-scissors:before { + content: "ï‹"; } + +.ion-search:before { + content: ""; } + +.ion-settings:before { + content: "ïŠ"; } + +.ion-share:before { + content: "ïˆ "; } + +.ion-shuffle:before { + content: ""; } + +.ion-skip-backward:before { + content: ""; } + +.ion-skip-forward:before { + content: ""; } + +.ion-social-android:before { + content: ""; } + +.ion-social-android-outline:before { + content: ""; } + +.ion-social-angular:before { + content: "ï“™"; } + +.ion-social-angular-outline:before { + content: ""; } + +.ion-social-apple:before { + content: ""; } + +.ion-social-apple-outline:before { + content: ""; } + +.ion-social-bitcoin:before { + content: ""; } + +.ion-social-bitcoin-outline:before { + content: ""; } + +.ion-social-buffer:before { + content: ""; } + +.ion-social-buffer-outline:before { + content: ""; } + +.ion-social-chrome:before { + content: "ï“›"; } + +.ion-social-chrome-outline:before { + content: ""; } + +.ion-social-codepen:before { + content: "ï“"; } + +.ion-social-codepen-outline:before { + content: ""; } + +.ion-social-css3:before { + content: ""; } + +.ion-social-css3-outline:before { + content: ""; } + +.ion-social-designernews:before { + content: ""; } + +.ion-social-designernews-outline:before { + content: ""; } + +.ion-social-dribbble:before { + content: "ïˆ"; } + +.ion-social-dribbble-outline:before { + content: ""; } + +.ion-social-dropbox:before { + content: ""; } + +.ion-social-dropbox-outline:before { + content: ""; } + +.ion-social-euro:before { + content: "ï“¡"; } + +.ion-social-euro-outline:before { + content: "ï“ "; } + +.ion-social-facebook:before { + content: ""; } + +.ion-social-facebook-outline:before { + content: ""; } + +.ion-social-foursquare:before { + content: "ï"; } + +.ion-social-foursquare-outline:before { + content: "ïŒ"; } + +.ion-social-freebsd-devil:before { + content: "ï‹„"; } + +.ion-social-github:before { + content: ""; } + +.ion-social-github-outline:before { + content: ""; } + +.ion-social-google:before { + content: "ï"; } + +.ion-social-google-outline:before { + content: "ïŽ"; } + +.ion-social-googleplus:before { + content: ""; } + +.ion-social-googleplus-outline:before { + content: ""; } + +.ion-social-hackernews:before { + content: ""; } + +.ion-social-hackernews-outline:before { + content: ""; } + +.ion-social-html5:before { + content: "ï“£"; } + +.ion-social-html5-outline:before { + content: "ï“¢"; } + +.ion-social-instagram:before { + content: "ï‘"; } + +.ion-social-instagram-outline:before { + content: "ï"; } + +.ion-social-javascript:before { + content: "ï“¥"; } + +.ion-social-javascript-outline:before { + content: ""; } + +.ion-social-linkedin:before { + content: ""; } + +.ion-social-linkedin-outline:before { + content: ""; } + +.ion-social-markdown:before { + content: ""; } + +.ion-social-nodejs:before { + content: "ï“§"; } + +.ion-social-octocat:before { + content: ""; } + +.ion-social-pinterest:before { + content: ""; } + +.ion-social-pinterest-outline:before { + content: ""; } + +.ion-social-python:before { + content: "ï“©"; } + +.ion-social-reddit:before { + content: ""; } + +.ion-social-reddit-outline:before { + content: ""; } + +.ion-social-rss:before { + content: ""; } + +.ion-social-rss-outline:before { + content: ""; } + +.ion-social-sass:before { + content: ""; } + +.ion-social-skype:before { + content: ""; } + +.ion-social-skype-outline:before { + content: ""; } + +.ion-social-snapchat:before { + content: ""; } + +.ion-social-snapchat-outline:before { + content: "ï“«"; } + +.ion-social-tumblr:before { + content: "ï‰"; } + +.ion-social-tumblr-outline:before { + content: ""; } + +.ion-social-tux:before { + content: "ï‹…"; } + +.ion-social-twitch:before { + content: "ï“®"; } + +.ion-social-twitch-outline:before { + content: "ï“"; } + +.ion-social-twitter:before { + content: ""; } + +.ion-social-twitter-outline:before { + content: ""; } + +.ion-social-usd:before { + content: "ï“"; } + +.ion-social-usd-outline:before { + content: "ï’"; } + +.ion-social-vimeo:before { + content: ""; } + +.ion-social-vimeo-outline:before { + content: ""; } + +.ion-social-whatsapp:before { + content: "ï“°"; } + +.ion-social-whatsapp-outline:before { + content: ""; } + +.ion-social-windows:before { + content: ""; } + +.ion-social-windows-outline:before { + content: ""; } + +.ion-social-wordpress:before { + content: ""; } + +.ion-social-wordpress-outline:before { + content: ""; } + +.ion-social-yahoo:before { + content: ""; } + +.ion-social-yahoo-outline:before { + content: ""; } + +.ion-social-yen:before { + content: ""; } + +.ion-social-yen-outline:before { + content: ""; } + +.ion-social-youtube:before { + content: "ï‰"; } + +.ion-social-youtube-outline:before { + content: ""; } + +.ion-soup-can:before { + content: "ï“´"; } + +.ion-soup-can-outline:before { + content: ""; } + +.ion-speakerphone:before { + content: ""; } + +.ion-speedometer:before { + content: ""; } + +.ion-spoon:before { + content: ""; } + +.ion-star:before { + content: ""; } + +.ion-stats-bars:before { + content: ""; } + +.ion-steam:before { + content: ""; } + +.ion-stop:before { + content: "ï‰"; } + +.ion-thermometer:before { + content: ""; } + +.ion-thumbsdown:before { + content: "ï‰"; } + +.ion-thumbsup:before { + content: ""; } + +.ion-toggle:before { + content: "ï•"; } + +.ion-toggle-filled:before { + content: "ï”"; } + +.ion-transgender:before { + content: ""; } + +.ion-trash-a:before { + content: ""; } + +.ion-trash-b:before { + content: ""; } + +.ion-trophy:before { + content: "ï–"; } + +.ion-tshirt:before { + content: "ï“·"; } + +.ion-tshirt-outline:before { + content: "ï“¶"; } + +.ion-umbrella:before { + content: ""; } + +.ion-university:before { + content: "ï—"; } + +.ion-unlocked:before { + content: ""; } + +.ion-upload:before { + content: ""; } + +.ion-usb:before { + content: ""; } + +.ion-videocamera:before { + content: ""; } + +.ion-volume-high:before { + content: ""; } + +.ion-volume-low:before { + content: ""; } + +.ion-volume-medium:before { + content: ""; } + +.ion-volume-mute:before { + content: ""; } + +.ion-wand:before { + content: "ï˜"; } + +.ion-waterdrop:before { + content: ""; } + +.ion-wifi:before { + content: ""; } + +.ion-wineglass:before { + content: ""; } + +.ion-woman:before { + content: "ï‰"; } + +.ion-wrench:before { + content: ""; } + +.ion-xbox:before { + content: ""; } + +/** + * Resets + * -------------------------------------------------- + * Adapted from normalize.css and some reset.css. We don't care even one + * bit about old IE, so we don't need any hacks for that in here. + * + * There are probably other things we could remove here, as well. + * + * normalize.css v2.1.2 | MIT License | git.io/normalize + + * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) + * http://cssreset.com + */ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, i, u, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, fieldset, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + vertical-align: baseline; + font: inherit; + font-size: 100%; } + +ol, ul { + list-style: none; } + +blockquote, q { + quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; } + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Hide the `template` element in IE, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +script { + display: none !important; } + +/* ========================================================================== + Base + ========================================================================== */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ +html { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + font-family: sans-serif; + /* 1 */ + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; + line-height: 1; } + +/** + * Remove default outlines. + */ +a, +button, +:focus, +a:focus, +button:focus, +a:active, +a:hover { + outline: 0; } + +/* * + * Remove tap highlight color + */ +a { + -webkit-user-drag: none; + -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: transparent; } + a[href]:hover { + cursor: pointer; } + +/* ========================================================================== + Typography + ========================================================================== */ +/** + * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari 5 and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Correct font family set oddly in Safari 5 and Chrome. + */ +code, +kbd, +pre, +samp { + font-size: 1em; + font-family: monospace, serif; } + +/** + * Improve readability of pre-formatted text in all browsers. + */ +pre { + white-space: pre-wrap; } + +/** + * Set consistent quote types. + */ +q { + quotes: "\201C" "\201D" "\2018" "\2019"; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + position: relative; + vertical-align: baseline; + font-size: 75%; + line-height: 0; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; + border: 1px solid #c0c0c0; } + +/** + * 1. Correct `color` not being inherited in IE 8/9. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ +legend { + padding: 0; + /* 2 */ + border: 0; + /* 1 */ } + +/** + * 1. Correct font family not being inherited in all browsers. + * 2. Correct font size not being inherited in all browsers. + * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. + * 4. Remove any default :focus styles + * 5. Make sure webkit font smoothing is being inherited + * 6. Remove default gradient in Android Firefox / FirefoxOS + */ +button, +input, +select, +textarea { + margin: 0; + /* 3 */ + font-size: 100%; + /* 2 */ + font-family: inherit; + /* 1 */ + outline-offset: 0; + /* 4 */ + outline-style: none; + /* 4 */ + outline-width: 0; + /* 4 */ + -webkit-font-smoothing: inherit; + /* 5 */ + background-image: none; + /* 6 */ } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `importnt` in + * the UA stylesheet. + */ +button, +input { + line-height: normal; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. + * Correct `select` style inheritance in Firefox 4+ and Opera. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + /* 3 */ + -webkit-appearance: button; + /* 2 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: default; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-box-sizing: content-box; + /* 2 */ + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; + /* 1 */ } + +/** + * Remove inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; } + +/** + * 1. Remove default vertical scrollbar in IE 8/9. + * 2. Improve readability and alignment in all browsers. + */ +textarea { + overflow: auto; + /* 1 */ + vertical-align: top; + /* 2 */ } + +img { + -webkit-user-drag: none; } + +/* ========================================================================== + Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-spacing: 0; + border-collapse: collapse; } + +/** + * Scaffolding + * -------------------------------------------------- + */ +*, +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + +html { + overflow: hidden; + -ms-touch-action: pan-y; + touch-action: pan-y; } + +body, +.ionic-body { + -webkit-touch-callout: none; + -webkit-font-smoothing: antialiased; + font-smoothing: antialiased; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + text-size-adjust: none; + -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: transparent; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + margin: 0; + padding: 0; + color: #000; + word-wrap: break-word; + font-size: 14px; + font-family: -apple-system; + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; + line-height: 20px; + text-rendering: optimizeLegibility; + -webkit-backface-visibility: hidden; + -webkit-user-drag: none; + -ms-content-zooming: none; } + +body.grade-b, +body.grade-c { + text-rendering: auto; } + +.content { + position: relative; } + +.scroll-content { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + margin-top: -1px; + padding-top: 1px; + margin-bottom: -1px; + width: auto; + height: auto; } + +.menu .scroll-content.scroll-content-false { + z-index: 11; } + +.scroll-view { + position: relative; + display: block; + overflow: hidden; + margin-top: -1px; } + .scroll-view.overflow-scroll { + position: relative; } + .scroll-view.scroll-x { + overflow-x: scroll; + overflow-y: hidden; } + .scroll-view.scroll-y { + overflow-x: hidden; + overflow-y: scroll; } + .scroll-view.scroll-xy { + overflow-x: scroll; + overflow-y: scroll; } + +/** + * Scroll is the scroll view component available for complex and custom + * scroll view functionality. + */ +.scroll { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-touch-callout: none; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + text-size-adjust: none; + -webkit-transform-origin: left top; + transform-origin: left top; } + +/** + * Set ms-viewport to prevent MS "page squish" and allow fluid scrolling + * https://msdn.microsoft.com/en-us/library/ie/hh869615(v=vs.85).aspx + */ +@-ms-viewport { + width: device-width; } + +.scroll-bar { + position: absolute; + z-index: 9999; } + +.ng-animate .scroll-bar { + visibility: hidden; } + +.scroll-bar-h { + right: 2px; + bottom: 3px; + left: 2px; + height: 3px; } + .scroll-bar-h .scroll-bar-indicator { + height: 100%; } + +.scroll-bar-v { + top: 2px; + right: 3px; + bottom: 2px; + width: 3px; } + .scroll-bar-v .scroll-bar-indicator { + width: 100%; } + +.scroll-bar-indicator { + position: absolute; + border-radius: 4px; + background: rgba(0, 0, 0, 0.3); + opacity: 1; + -webkit-transition: opacity 0.3s linear; + transition: opacity 0.3s linear; } + .scroll-bar-indicator.scroll-bar-fade-out { + opacity: 0; } + +.platform-android .scroll-bar-indicator { + border-radius: 0; } + +.grade-b .scroll-bar-indicator, +.grade-c .scroll-bar-indicator { + background: #aaa; } + .grade-b .scroll-bar-indicator.scroll-bar-fade-out, + .grade-c .scroll-bar-indicator.scroll-bar-fade-out { + -webkit-transition: none; + transition: none; } + +ion-infinite-scroll { + height: 60px; + width: 100%; + display: block; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-direction: normal; + -webkit-box-orient: horizontal; + -webkit-flex-direction: row; + -moz-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + -moz-justify-content: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; } + ion-infinite-scroll .icon { + color: #666666; + font-size: 30px; + color: #666666; } + ion-infinite-scroll:not(.active) .spinner, + ion-infinite-scroll:not(.active) .icon:before { + display: none; } + +.overflow-scroll { + overflow-x: hidden; + overflow-y: scroll; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + top: 0; + right: 0; + bottom: 0; + left: 0; + position: absolute; } + .overflow-scroll.pane { + overflow-x: hidden; + overflow-y: scroll; } + .overflow-scroll .scroll { + position: static; + height: 100%; + -webkit-transform: translate3d(0, 0, 0); } + .overflow-scroll.keyboard-up:not(.keyboard-up-confirm) { + overflow: hidden; } + +/* If you change these, change platform.scss as well */ +.has-header { + top: 44px; } + +.no-header { + top: 0; } + +.has-subheader { + top: 88px; } + +.has-tabs-top { + top: 93px; } + +.has-header.has-subheader.has-tabs-top { + top: 137px; } + +.has-footer { + bottom: 44px; } + +.has-subfooter { + bottom: 88px; } + +.has-tabs, +.bar-footer.has-tabs { + bottom: 49px; } + .has-tabs.pane, + .bar-footer.has-tabs.pane { + bottom: 49px; + height: auto; } + +.bar-subfooter.has-tabs { + bottom: 93px; } + +.has-footer.has-tabs { + bottom: 93px; } + +.pane { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition-duration: 0; + transition-duration: 0; + z-index: 1; } + +.view { + z-index: 1; } + +.pane, +.view { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #fff; + overflow: hidden; } + +.view-container { + position: absolute; + display: block; + width: 100%; + height: 100%; } + +/** + * Typography + * -------------------------------------------------- + */ +p { + margin: 0 0 10px; } + +small { + font-size: 85%; } + +cite { + font-style: normal; } + +.text-left { + text-align: left; } + +.text-right { + text-align: right; } + +.text-center { + text-align: center; } + +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { + color: #000; + font-weight: 500; + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; + line-height: 1.2; } + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, + .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small { + font-weight: normal; + line-height: 1; } + +h1, .h1, +h2, .h2, +h3, .h3 { + margin-top: 20px; + margin-bottom: 10px; } + h1:first-child, .h1:first-child, + h2:first-child, .h2:first-child, + h3:first-child, .h3:first-child { + margin-top: 0; } + h1 + h1, h1 + .h1, + h1 + h2, h1 + .h2, + h1 + h3, h1 + .h3, .h1 + h1, .h1 + .h1, + .h1 + h2, .h1 + .h2, + .h1 + h3, .h1 + .h3, + h2 + h1, + h2 + .h1, + h2 + h2, + h2 + .h2, + h2 + h3, + h2 + .h3, .h2 + h1, .h2 + .h1, + .h2 + h2, .h2 + .h2, + .h2 + h3, .h2 + .h3, + h3 + h1, + h3 + .h1, + h3 + h2, + h3 + .h2, + h3 + h3, + h3 + .h3, .h3 + h1, .h3 + .h1, + .h3 + h2, .h3 + .h2, + .h3 + h3, .h3 + .h3 { + margin-top: 10px; } + +h4, .h4, +h5, .h5, +h6, .h6 { + margin-top: 10px; + margin-bottom: 10px; } + +h1, .h1 { + font-size: 36px; } + +h2, .h2 { + font-size: 30px; } + +h3, .h3 { + font-size: 24px; } + +h4, .h4 { + font-size: 18px; } + +h5, .h5 { + font-size: 14px; } + +h6, .h6 { + font-size: 12px; } + +h1 small, .h1 small { + font-size: 24px; } + +h2 small, .h2 small { + font-size: 18px; } + +h3 small, .h3 small, +h4 small, .h4 small { + font-size: 14px; } + +dl { + margin-bottom: 20px; } + +dt, +dd { + line-height: 1.42857; } + +dt { + font-weight: bold; } + +blockquote { + margin: 0 0 20px; + padding: 10px 20px; + border-left: 5px solid gray; } + blockquote p { + font-weight: 300; + font-size: 17.5px; + line-height: 1.25; } + blockquote p:last-child { + margin-bottom: 0; } + blockquote small { + display: block; + line-height: 1.42857; } + blockquote small:before { + content: '\2014 \00A0'; } + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; } + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857; } + +a { + color: #387ef5; } + +a.subdued { + padding-right: 10px; + color: #888; + text-decoration: none; } + a.subdued:hover { + text-decoration: none; } + a.subdued:last-child { + padding-right: 0; } + +/** + * Action Sheets + * -------------------------------------------------- + */ +.action-sheet-backdrop { + -webkit-transition: background-color 150ms ease-in-out; + transition: background-color 150ms ease-in-out; + position: fixed; + top: 0; + left: 0; + z-index: 11; + width: 100%; + height: 100%; + background-color: transparent; } + .action-sheet-backdrop.active { + background-color: rgba(0, 0, 0, 0.4); } + +.action-sheet-wrapper { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + -webkit-transition: all cubic-bezier(0.36, 0.66, 0.04, 1) 500ms; + transition: all cubic-bezier(0.36, 0.66, 0.04, 1) 500ms; + position: absolute; + bottom: 0; + left: 0; + right: 0; + width: 100%; + max-width: 500px; + margin: auto; } + +.action-sheet-up { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.action-sheet { + margin-left: 8px; + margin-right: 8px; + width: auto; + z-index: 11; + overflow: hidden; } + .action-sheet .button { + display: block; + padding: 1px; + width: 100%; + border-radius: 0; + border-color: #d1d3d6; + background-color: transparent; + color: #007aff; + font-size: 21px; } + .action-sheet .button:hover { + color: #007aff; } + .action-sheet .button.destructive { + color: #ff3b30; } + .action-sheet .button.destructive:hover { + color: #ff3b30; } + .action-sheet .button.active, .action-sheet .button.activated { + box-shadow: none; + border-color: #d1d3d6; + color: #007aff; + background: #e4e5e7; } + +.action-sheet-has-icons .icon { + position: absolute; + left: 16px; } + +.action-sheet-title { + padding: 16px; + color: #8f8f8f; + text-align: center; + font-size: 13px; } + +.action-sheet-group { + margin-bottom: 8px; + border-radius: 4px; + background-color: #fff; + overflow: hidden; } + .action-sheet-group .button { + border-width: 1px 0px 0px 0px; } + .action-sheet-group .button:first-child:last-child { + border-width: 0; } + +.action-sheet-options { + background: #f1f2f3; } + +.action-sheet-cancel .button { + font-weight: 500; } + +.action-sheet-open { + pointer-events: none; } + .action-sheet-open.modal-open .modal { + pointer-events: none; } + .action-sheet-open .action-sheet-backdrop { + pointer-events: auto; } + +.platform-android .action-sheet-backdrop.active { + background-color: rgba(0, 0, 0, 0.2); } + +.platform-android .action-sheet { + margin: 0; } + .platform-android .action-sheet .action-sheet-title, + .platform-android .action-sheet .button { + text-align: left; + border-color: transparent; + font-size: 16px; + color: inherit; } + .platform-android .action-sheet .action-sheet-title { + font-size: 14px; + padding: 16px; + color: #666; } + .platform-android .action-sheet .button.active, + .platform-android .action-sheet .button.activated { + background: #e8e8e8; } + +.platform-android .action-sheet-group { + margin: 0; + border-radius: 0; + background-color: #fafafa; } + +.platform-android .action-sheet-cancel { + display: none; } + +.platform-android .action-sheet-has-icons .button { + padding-left: 56px; } + +.backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 11; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.4); + visibility: hidden; + opacity: 0; + -webkit-transition: 0.1s opacity linear; + transition: 0.1s opacity linear; } + .backdrop.visible { + visibility: visible; } + .backdrop.active { + opacity: 1; } + +/** + * Bar (Headers and Footers) + * -------------------------------------------------- + */ +.bar { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: absolute; + right: 0; + left: 0; + z-index: 9; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 5px; + width: 100%; + height: 44px; + border-width: 0; + border-style: solid; + border-top: 1px solid transparent; + border-bottom: 1px solid #ddd; + background-color: white; + /* border-width: 1px will actually create 2 device pixels on retina */ + /* this nifty trick sets an actual 1px border on hi-res displays */ + background-size: 0; } + @media (min--moz-device-pixel-ratio: 1.5), (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5), (min-resolution: 144dpi), (min-resolution: 1.5dppx) { + .bar { + border: none; + background-image: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%); + background-position: bottom; + background-size: 100% 1px; + background-repeat: no-repeat; } } + .bar.bar-clear { + border: none; + background: none; + color: #fff; } + .bar.bar-clear .button { + color: #fff; } + .bar.bar-clear .title { + color: #fff; } + .bar.item-input-inset .item-input-wrapper { + margin-top: -1px; } + .bar.item-input-inset .item-input-wrapper input { + padding-left: 8px; + width: 94%; + height: 28px; + background: transparent; } + .bar.bar-light { + border-color: #ddd; + background-color: white; + background-image: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%); + color: #444; } + .bar.bar-light .title { + color: #444; } + .bar.bar-light.bar-footer { + background-image: linear-gradient(180deg, #ddd, #ddd 50%, transparent 50%); } + .bar.bar-stable { + border-color: #b2b2b2; + background-color: #f8f8f8; + background-image: linear-gradient(0deg, #b2b2b2, #b2b2b2 50%, transparent 50%); + color: #444; } + .bar.bar-stable .title { + color: #444; } + .bar.bar-stable.bar-footer { + background-image: linear-gradient(180deg, #b2b2b2, #b2b2b2 50%, transparent 50%); } + .bar.bar-positive { + border-color: #0c60ee; + background-color: #387ef5; + background-image: linear-gradient(0deg, #0c60ee, #0c60ee 50%, transparent 50%); + color: #fff; } + .bar.bar-positive .title { + color: #fff; } + .bar.bar-positive.bar-footer { + background-image: linear-gradient(180deg, #0c60ee, #0c60ee 50%, transparent 50%); } + .bar.bar-calm { + border-color: #0a9dc7; + background-color: #11c1f3; + background-image: linear-gradient(0deg, #0a9dc7, #0a9dc7 50%, transparent 50%); + color: #fff; } + .bar.bar-calm .title { + color: #fff; } + .bar.bar-calm.bar-footer { + background-image: linear-gradient(180deg, #0a9dc7, #0a9dc7 50%, transparent 50%); } + .bar.bar-assertive { + border-color: #e42112; + background-color: #ef473a; + background-image: linear-gradient(0deg, #e42112, #e42112 50%, transparent 50%); + color: #fff; } + .bar.bar-assertive .title { + color: #fff; } + .bar.bar-assertive.bar-footer { + background-image: linear-gradient(180deg, #e42112, #e42112 50%, transparent 50%); } + .bar.bar-balanced { + border-color: #28a54c; + background-color: #33cd5f; + background-image: linear-gradient(0deg, #28a54c, #28a54c 50%, transparent 50%); + color: #fff; } + .bar.bar-balanced .title { + color: #fff; } + .bar.bar-balanced.bar-footer { + background-image: linear-gradient(180deg, #28a54c, #0c60ee 50%, transparent 50%); } + .bar.bar-energized { + border-color: #e6b500; + background-color: #ffc900; + background-image: linear-gradient(0deg, #e6b500, #e6b500 50%, transparent 50%); + color: #fff; } + .bar.bar-energized .title { + color: #fff; } + .bar.bar-energized.bar-footer { + background-image: linear-gradient(180deg, #e6b500, #e6b500 50%, transparent 50%); } + .bar.bar-royal { + border-color: #6b46e5; + background-color: #886aea; + background-image: linear-gradient(0deg, #6b46e5, #6b46e5 50%, transparent 50%); + color: #fff; } + .bar.bar-royal .title { + color: #fff; } + .bar.bar-royal.bar-footer { + background-image: linear-gradient(180deg, #6b46e5, #6b46e5 50%, transparent 50%); } + .bar.bar-dark { + border-color: #111; + background-color: #444444; + background-image: linear-gradient(0deg, #111, #111 50%, transparent 50%); + color: #fff; } + .bar.bar-dark .title { + color: #fff; } + .bar.bar-dark.bar-footer { + background-image: linear-gradient(180deg, #111, #111 50%, transparent 50%); } + .bar .title { + display: block; + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 0; + overflow: hidden; + margin: 0 10px; + min-width: 30px; + height: 43px; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 17px; + font-weight: 500; + line-height: 44px; } + .bar .title.title-left { + text-align: left; } + .bar .title.title-right { + text-align: right; } + .bar .title a { + color: inherit; } + .bar .button, .bar button { + z-index: 1; + padding: 0 8px; + min-width: initial; + min-height: 31px; + font-weight: 400; + font-size: 13px; + line-height: 32px; } + .bar .button.button-icon:before, + .bar .button .icon:before, .bar .button.icon:before, .bar .button.icon-left:before, .bar .button.icon-right:before, .bar button.button-icon:before, + .bar button .icon:before, .bar button.icon:before, .bar button.icon-left:before, .bar button.icon-right:before { + padding-right: 2px; + padding-left: 2px; + font-size: 20px; + line-height: 32px; } + .bar .button.button-icon, .bar button.button-icon { + font-size: 17px; } + .bar .button.button-icon .icon:before, .bar .button.button-icon:before, .bar .button.button-icon.icon-left:before, .bar .button.button-icon.icon-right:before, .bar button.button-icon .icon:before, .bar button.button-icon:before, .bar button.button-icon.icon-left:before, .bar button.button-icon.icon-right:before { + vertical-align: top; + font-size: 32px; + line-height: 32px; } + .bar .button.button-clear, .bar button.button-clear { + padding-right: 2px; + padding-left: 2px; + font-weight: 300; + font-size: 17px; } + .bar .button.button-clear .icon:before, .bar .button.button-clear.icon:before, .bar .button.button-clear.icon-left:before, .bar .button.button-clear.icon-right:before, .bar button.button-clear .icon:before, .bar button.button-clear.icon:before, .bar button.button-clear.icon-left:before, .bar button.button-clear.icon-right:before { + font-size: 32px; + line-height: 32px; } + .bar .button.back-button, .bar button.back-button { + display: block; + margin-right: 5px; + padding: 0; + white-space: nowrap; + font-weight: 400; } + .bar .button.back-button.active, .bar .button.back-button.activated, .bar button.back-button.active, .bar button.back-button.activated { + opacity: 0.2; } + .bar .button-bar > .button, + .bar .buttons > .button { + min-height: 31px; + line-height: 32px; } + .bar .button-bar + .button, + .bar .button + .button-bar { + margin-left: 5px; } + .bar .buttons, + .bar .buttons.primary-buttons, + .bar .buttons.secondary-buttons { + display: inherit; } + .bar .buttons span { + display: inline-block; } + .bar .buttons-left span { + margin-right: 5px; + display: inherit; } + .bar .buttons-right span { + margin-left: 5px; + display: inherit; } + .bar .title + .button:last-child, + .bar > .button + .button:last-child, + .bar > .button.pull-right, + .bar .buttons.pull-right, + .bar .title + .buttons { + position: absolute; + top: 5px; + right: 5px; + bottom: 5px; } + +.platform-android .nav-bar-has-subheader .bar { + background-image: none; } + +.platform-android .bar .back-button .icon:before { + font-size: 24px; } + +.platform-android .bar .title { + font-size: 19px; + line-height: 44px; } + +.bar-light .button { + border-color: transparent; + background-color: white; + color: #444; } + .bar-light .button:hover { + color: #444; + text-decoration: none; } + .bar-light .button.active, .bar-light .button.activated { + background-color: #fafafa; } + .bar-light .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #444; + font-size: 17px; } + .bar-light .button.button-icon { + border-color: transparent; + background: none; } + +.bar-stable .button { + border-color: transparent; + background-color: #f8f8f8; + color: #444; } + .bar-stable .button:hover { + color: #444; + text-decoration: none; } + .bar-stable .button.active, .bar-stable .button.activated { + background-color: #e5e5e5; } + .bar-stable .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #444; + font-size: 17px; } + .bar-stable .button.button-icon { + border-color: transparent; + background: none; } + +.bar-positive .button { + border-color: transparent; + background-color: #387ef5; + color: #fff; } + .bar-positive .button:hover { + color: #fff; + text-decoration: none; } + .bar-positive .button.active, .bar-positive .button.activated { + background-color: #0c60ee; } + .bar-positive .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #fff; + font-size: 17px; } + .bar-positive .button.button-icon { + border-color: transparent; + background: none; } + +.bar-calm .button { + border-color: transparent; + background-color: #11c1f3; + color: #fff; } + .bar-calm .button:hover { + color: #fff; + text-decoration: none; } + .bar-calm .button.active, .bar-calm .button.activated { + background-color: #0a9dc7; } + .bar-calm .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #fff; + font-size: 17px; } + .bar-calm .button.button-icon { + border-color: transparent; + background: none; } + +.bar-assertive .button { + border-color: transparent; + background-color: #ef473a; + color: #fff; } + .bar-assertive .button:hover { + color: #fff; + text-decoration: none; } + .bar-assertive .button.active, .bar-assertive .button.activated { + background-color: #e42112; } + .bar-assertive .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #fff; + font-size: 17px; } + .bar-assertive .button.button-icon { + border-color: transparent; + background: none; } + +.bar-balanced .button { + border-color: transparent; + background-color: #33cd5f; + color: #fff; } + .bar-balanced .button:hover { + color: #fff; + text-decoration: none; } + .bar-balanced .button.active, .bar-balanced .button.activated { + background-color: #28a54c; } + .bar-balanced .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #fff; + font-size: 17px; } + .bar-balanced .button.button-icon { + border-color: transparent; + background: none; } + +.bar-energized .button { + border-color: transparent; + background-color: #ffc900; + color: #fff; } + .bar-energized .button:hover { + color: #fff; + text-decoration: none; } + .bar-energized .button.active, .bar-energized .button.activated { + background-color: #e6b500; } + .bar-energized .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #fff; + font-size: 17px; } + .bar-energized .button.button-icon { + border-color: transparent; + background: none; } + +.bar-royal .button { + border-color: transparent; + background-color: #886aea; + color: #fff; } + .bar-royal .button:hover { + color: #fff; + text-decoration: none; } + .bar-royal .button.active, .bar-royal .button.activated { + background-color: #6b46e5; } + .bar-royal .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #fff; + font-size: 17px; } + .bar-royal .button.button-icon { + border-color: transparent; + background: none; } + +.bar-dark .button { + border-color: transparent; + background-color: #444444; + color: #fff; } + .bar-dark .button:hover { + color: #fff; + text-decoration: none; } + .bar-dark .button.active, .bar-dark .button.activated { + background-color: #262626; } + .bar-dark .button.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #fff; + font-size: 17px; } + .bar-dark .button.button-icon { + border-color: transparent; + background: none; } + +.bar-header { + top: 0; + border-top-width: 0; + border-bottom-width: 1px; } + .bar-header.has-tabs-top { + border-bottom-width: 0px; + background-image: none; } + +.tabs-top .bar-header { + border-bottom-width: 0px; + background-image: none; } + +.bar-footer { + bottom: 0; + border-top-width: 1px; + border-bottom-width: 0; + background-position: top; + height: 44px; } + .bar-footer.item-input-inset { + position: absolute; } + +.bar-tabs { + padding: 0; } + +.bar-subheader { + top: 44px; + display: block; + height: 44px; } + +.bar-subfooter { + bottom: 44px; + display: block; + height: 44px; } + +.nav-bar-block { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 9; } + +.bar .back-button.hide, +.bar .buttons .hide { + display: none; } + +.nav-bar-tabs-top .bar { + background-image: none; } + +/** + * Tabs + * -------------------------------------------------- + * A navigation bar with any number of tab items supported. + */ +.tabs { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-direction: normal; + -webkit-box-orient: horizontal; + -webkit-flex-direction: horizontal; + -moz-flex-direction: horizontal; + -ms-flex-direction: horizontal; + flex-direction: horizontal; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + -moz-justify-content: center; + justify-content: center; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + border-color: #b2b2b2; + background-color: #f8f8f8; + background-image: linear-gradient(0deg, #b2b2b2, #b2b2b2 50%, transparent 50%); + color: #444; + position: absolute; + bottom: 0; + z-index: 5; + width: 100%; + height: 49px; + border-style: solid; + border-top-width: 1px; + background-size: 0; + line-height: 49px; } + .tabs .tab-item .badge { + background-color: #444; + color: #f8f8f8; } + @media (min--moz-device-pixel-ratio: 1.5), (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5), (min-resolution: 144dpi), (min-resolution: 1.5dppx) { + .tabs { + padding-top: 2px; + border-top: none !important; + border-bottom: none; + background-position: top; + background-size: 100% 1px; + background-repeat: no-repeat; } } + +/* Allow parent element of tabs to define color, or just the tab itself */ +.tabs-light > .tabs, +.tabs.tabs-light { + border-color: #ddd; + background-color: #fff; + background-image: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%); + color: #444; } + .tabs-light > .tabs .tab-item .badge, + .tabs.tabs-light .tab-item .badge { + background-color: #444; + color: #fff; } + +.tabs-stable > .tabs, +.tabs.tabs-stable { + border-color: #b2b2b2; + background-color: #f8f8f8; + background-image: linear-gradient(0deg, #b2b2b2, #b2b2b2 50%, transparent 50%); + color: #444; } + .tabs-stable > .tabs .tab-item .badge, + .tabs.tabs-stable .tab-item .badge { + background-color: #444; + color: #f8f8f8; } + +.tabs-positive > .tabs, +.tabs.tabs-positive { + border-color: #0c60ee; + background-color: #387ef5; + background-image: linear-gradient(0deg, #0c60ee, #0c60ee 50%, transparent 50%); + color: #fff; } + .tabs-positive > .tabs .tab-item .badge, + .tabs.tabs-positive .tab-item .badge { + background-color: #fff; + color: #387ef5; } + +.tabs-calm > .tabs, +.tabs.tabs-calm { + border-color: #0a9dc7; + background-color: #11c1f3; + background-image: linear-gradient(0deg, #0a9dc7, #0a9dc7 50%, transparent 50%); + color: #fff; } + .tabs-calm > .tabs .tab-item .badge, + .tabs.tabs-calm .tab-item .badge { + background-color: #fff; + color: #11c1f3; } + +.tabs-assertive > .tabs, +.tabs.tabs-assertive { + border-color: #e42112; + background-color: #ef473a; + background-image: linear-gradient(0deg, #e42112, #e42112 50%, transparent 50%); + color: #fff; } + .tabs-assertive > .tabs .tab-item .badge, + .tabs.tabs-assertive .tab-item .badge { + background-color: #fff; + color: #ef473a; } + +.tabs-balanced > .tabs, +.tabs.tabs-balanced { + border-color: #28a54c; + background-color: #33cd5f; + background-image: linear-gradient(0deg, #28a54c, #28a54c 50%, transparent 50%); + color: #fff; } + .tabs-balanced > .tabs .tab-item .badge, + .tabs.tabs-balanced .tab-item .badge { + background-color: #fff; + color: #33cd5f; } + +.tabs-energized > .tabs, +.tabs.tabs-energized { + border-color: #e6b500; + background-color: #ffc900; + background-image: linear-gradient(0deg, #e6b500, #e6b500 50%, transparent 50%); + color: #fff; } + .tabs-energized > .tabs .tab-item .badge, + .tabs.tabs-energized .tab-item .badge { + background-color: #fff; + color: #ffc900; } + +.tabs-royal > .tabs, +.tabs.tabs-royal { + border-color: #6b46e5; + background-color: #886aea; + background-image: linear-gradient(0deg, #6b46e5, #6b46e5 50%, transparent 50%); + color: #fff; } + .tabs-royal > .tabs .tab-item .badge, + .tabs.tabs-royal .tab-item .badge { + background-color: #fff; + color: #886aea; } + +.tabs-dark > .tabs, +.tabs.tabs-dark { + border-color: #111; + background-color: #444; + background-image: linear-gradient(0deg, #111, #111 50%, transparent 50%); + color: #fff; } + .tabs-dark > .tabs .tab-item .badge, + .tabs.tabs-dark .tab-item .badge { + background-color: #fff; + color: #444; } + +.tabs-striped .tabs { + background-color: white; + background-image: none; + border: none; + border-bottom: 1px solid #ddd; + padding-top: 2px; } + +.tabs-striped .tab-item.tab-item-active, .tabs-striped .tab-item.active, .tabs-striped .tab-item.activated { + margin-top: -2px; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #444; } + .tabs-striped .tab-item.tab-item-active .badge, .tabs-striped .tab-item.active .badge, .tabs-striped .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-light .tabs { + background-color: #fff; } + +.tabs-striped.tabs-light .tab-item { + color: rgba(68, 68, 68, 0.4); + opacity: 1; } + .tabs-striped.tabs-light .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-light .tab-item.tab-item-active, .tabs-striped.tabs-light .tab-item.active, .tabs-striped.tabs-light .tab-item.activated { + margin-top: -2px; + color: #444; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #444; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-stable .tabs { + background-color: #f8f8f8; } + +.tabs-striped.tabs-stable .tab-item { + color: rgba(68, 68, 68, 0.4); + opacity: 1; } + .tabs-striped.tabs-stable .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-stable .tab-item.tab-item-active, .tabs-striped.tabs-stable .tab-item.active, .tabs-striped.tabs-stable .tab-item.activated { + margin-top: -2px; + color: #444; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #444; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-positive .tabs { + background-color: #387ef5; } + +.tabs-striped.tabs-positive .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-positive .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-positive .tab-item.tab-item-active, .tabs-striped.tabs-positive .tab-item.active, .tabs-striped.tabs-positive .tab-item.activated { + margin-top: -2px; + color: #fff; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #fff; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-calm .tabs { + background-color: #11c1f3; } + +.tabs-striped.tabs-calm .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-calm .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-calm .tab-item.tab-item-active, .tabs-striped.tabs-calm .tab-item.active, .tabs-striped.tabs-calm .tab-item.activated { + margin-top: -2px; + color: #fff; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #fff; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-assertive .tabs { + background-color: #ef473a; } + +.tabs-striped.tabs-assertive .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-assertive .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-assertive .tab-item.tab-item-active, .tabs-striped.tabs-assertive .tab-item.active, .tabs-striped.tabs-assertive .tab-item.activated { + margin-top: -2px; + color: #fff; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #fff; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-balanced .tabs { + background-color: #33cd5f; } + +.tabs-striped.tabs-balanced .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-balanced .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-balanced .tab-item.tab-item-active, .tabs-striped.tabs-balanced .tab-item.active, .tabs-striped.tabs-balanced .tab-item.activated { + margin-top: -2px; + color: #fff; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #fff; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-energized .tabs { + background-color: #ffc900; } + +.tabs-striped.tabs-energized .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-energized .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-energized .tab-item.tab-item-active, .tabs-striped.tabs-energized .tab-item.active, .tabs-striped.tabs-energized .tab-item.activated { + margin-top: -2px; + color: #fff; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #fff; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-royal .tabs { + background-color: #886aea; } + +.tabs-striped.tabs-royal .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-royal .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-royal .tab-item.tab-item-active, .tabs-striped.tabs-royal .tab-item.active, .tabs-striped.tabs-royal .tab-item.activated { + margin-top: -2px; + color: #fff; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #fff; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-dark .tabs { + background-color: #444; } + +.tabs-striped.tabs-dark .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-dark .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-dark .tab-item.tab-item-active, .tabs-striped.tabs-dark .tab-item.active, .tabs-striped.tabs-dark .tab-item.activated { + margin-top: -2px; + color: #fff; + border-style: solid; + border-width: 2px 0 0 0; + border-color: #fff; } + +.tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-striped.tabs-background-light .tabs { + background-color: #fff; + background-image: none; } + +.tabs-striped.tabs-background-stable .tabs { + background-color: #f8f8f8; + background-image: none; } + +.tabs-striped.tabs-background-positive .tabs { + background-color: #387ef5; + background-image: none; } + +.tabs-striped.tabs-background-calm .tabs { + background-color: #11c1f3; + background-image: none; } + +.tabs-striped.tabs-background-assertive .tabs { + background-color: #ef473a; + background-image: none; } + +.tabs-striped.tabs-background-balanced .tabs { + background-color: #33cd5f; + background-image: none; } + +.tabs-striped.tabs-background-energized .tabs { + background-color: #ffc900; + background-image: none; } + +.tabs-striped.tabs-background-royal .tabs { + background-color: #886aea; + background-image: none; } + +.tabs-striped.tabs-background-dark .tabs { + background-color: #444; + background-image: none; } + +.tabs-striped.tabs-color-light .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-light .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-light .tab-item.tab-item-active, .tabs-striped.tabs-color-light .tab-item.active, .tabs-striped.tabs-color-light .tab-item.activated { + margin-top: -2px; + color: #fff; + border: 0 solid #fff; + border-top-width: 2px; } + .tabs-striped.tabs-color-light .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-light .tab-item.active .badge, .tabs-striped.tabs-color-light .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-stable .tab-item { + color: rgba(248, 248, 248, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-stable .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-stable .tab-item.tab-item-active, .tabs-striped.tabs-color-stable .tab-item.active, .tabs-striped.tabs-color-stable .tab-item.activated { + margin-top: -2px; + color: #f8f8f8; + border: 0 solid #f8f8f8; + border-top-width: 2px; } + .tabs-striped.tabs-color-stable .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-stable .tab-item.active .badge, .tabs-striped.tabs-color-stable .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-positive .tab-item { + color: rgba(56, 126, 245, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-positive .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-positive .tab-item.tab-item-active, .tabs-striped.tabs-color-positive .tab-item.active, .tabs-striped.tabs-color-positive .tab-item.activated { + margin-top: -2px; + color: #387ef5; + border: 0 solid #387ef5; + border-top-width: 2px; } + .tabs-striped.tabs-color-positive .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-positive .tab-item.active .badge, .tabs-striped.tabs-color-positive .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-calm .tab-item { + color: rgba(17, 193, 243, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-calm .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-calm .tab-item.tab-item-active, .tabs-striped.tabs-color-calm .tab-item.active, .tabs-striped.tabs-color-calm .tab-item.activated { + margin-top: -2px; + color: #11c1f3; + border: 0 solid #11c1f3; + border-top-width: 2px; } + .tabs-striped.tabs-color-calm .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-calm .tab-item.active .badge, .tabs-striped.tabs-color-calm .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-assertive .tab-item { + color: rgba(239, 71, 58, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-assertive .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-assertive .tab-item.tab-item-active, .tabs-striped.tabs-color-assertive .tab-item.active, .tabs-striped.tabs-color-assertive .tab-item.activated { + margin-top: -2px; + color: #ef473a; + border: 0 solid #ef473a; + border-top-width: 2px; } + .tabs-striped.tabs-color-assertive .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-assertive .tab-item.active .badge, .tabs-striped.tabs-color-assertive .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-balanced .tab-item { + color: rgba(51, 205, 95, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-balanced .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-balanced .tab-item.tab-item-active, .tabs-striped.tabs-color-balanced .tab-item.active, .tabs-striped.tabs-color-balanced .tab-item.activated { + margin-top: -2px; + color: #33cd5f; + border: 0 solid #33cd5f; + border-top-width: 2px; } + .tabs-striped.tabs-color-balanced .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-balanced .tab-item.active .badge, .tabs-striped.tabs-color-balanced .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-energized .tab-item { + color: rgba(255, 201, 0, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-energized .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-energized .tab-item.tab-item-active, .tabs-striped.tabs-color-energized .tab-item.active, .tabs-striped.tabs-color-energized .tab-item.activated { + margin-top: -2px; + color: #ffc900; + border: 0 solid #ffc900; + border-top-width: 2px; } + .tabs-striped.tabs-color-energized .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-energized .tab-item.active .badge, .tabs-striped.tabs-color-energized .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-royal .tab-item { + color: rgba(136, 106, 234, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-royal .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-royal .tab-item.tab-item-active, .tabs-striped.tabs-color-royal .tab-item.active, .tabs-striped.tabs-color-royal .tab-item.activated { + margin-top: -2px; + color: #886aea; + border: 0 solid #886aea; + border-top-width: 2px; } + .tabs-striped.tabs-color-royal .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-royal .tab-item.active .badge, .tabs-striped.tabs-color-royal .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-striped.tabs-color-dark .tab-item { + color: rgba(68, 68, 68, 0.4); + opacity: 1; } + .tabs-striped.tabs-color-dark .tab-item .badge { + opacity: 0.4; } + .tabs-striped.tabs-color-dark .tab-item.tab-item-active, .tabs-striped.tabs-color-dark .tab-item.active, .tabs-striped.tabs-color-dark .tab-item.activated { + margin-top: -2px; + color: #444; + border: 0 solid #444; + border-top-width: 2px; } + .tabs-striped.tabs-color-dark .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-dark .tab-item.active .badge, .tabs-striped.tabs-color-dark .tab-item.activated .badge { + top: 2px; + opacity: 1; } + +.tabs-background-light .tabs, +.tabs-background-light > .tabs { + background-color: #fff; + background-image: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%); + border-color: #ddd; } + +.tabs-background-stable .tabs, +.tabs-background-stable > .tabs { + background-color: #f8f8f8; + background-image: linear-gradient(0deg, #b2b2b2, #b2b2b2 50%, transparent 50%); + border-color: #b2b2b2; } + +.tabs-background-positive .tabs, +.tabs-background-positive > .tabs { + background-color: #387ef5; + background-image: linear-gradient(0deg, #0c60ee, #0c60ee 50%, transparent 50%); + border-color: #0c60ee; } + +.tabs-background-calm .tabs, +.tabs-background-calm > .tabs { + background-color: #11c1f3; + background-image: linear-gradient(0deg, #0a9dc7, #0a9dc7 50%, transparent 50%); + border-color: #0a9dc7; } + +.tabs-background-assertive .tabs, +.tabs-background-assertive > .tabs { + background-color: #ef473a; + background-image: linear-gradient(0deg, #e42112, #e42112 50%, transparent 50%); + border-color: #e42112; } + +.tabs-background-balanced .tabs, +.tabs-background-balanced > .tabs { + background-color: #33cd5f; + background-image: linear-gradient(0deg, #28a54c, #28a54c 50%, transparent 50%); + border-color: #28a54c; } + +.tabs-background-energized .tabs, +.tabs-background-energized > .tabs { + background-color: #ffc900; + background-image: linear-gradient(0deg, #e6b500, #e6b500 50%, transparent 50%); + border-color: #e6b500; } + +.tabs-background-royal .tabs, +.tabs-background-royal > .tabs { + background-color: #886aea; + background-image: linear-gradient(0deg, #6b46e5, #6b46e5 50%, transparent 50%); + border-color: #6b46e5; } + +.tabs-background-dark .tabs, +.tabs-background-dark > .tabs { + background-color: #444; + background-image: linear-gradient(0deg, #111, #111 50%, transparent 50%); + border-color: #111; } + +.tabs-color-light .tab-item { + color: rgba(255, 255, 255, 0.4); + opacity: 1; } + .tabs-color-light .tab-item .badge { + opacity: 0.4; } + .tabs-color-light .tab-item.tab-item-active, .tabs-color-light .tab-item.active, .tabs-color-light .tab-item.activated { + color: #fff; + border: 0 solid #fff; } + .tabs-color-light .tab-item.tab-item-active .badge, .tabs-color-light .tab-item.active .badge, .tabs-color-light .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-stable .tab-item { + color: rgba(248, 248, 248, 0.4); + opacity: 1; } + .tabs-color-stable .tab-item .badge { + opacity: 0.4; } + .tabs-color-stable .tab-item.tab-item-active, .tabs-color-stable .tab-item.active, .tabs-color-stable .tab-item.activated { + color: #f8f8f8; + border: 0 solid #f8f8f8; } + .tabs-color-stable .tab-item.tab-item-active .badge, .tabs-color-stable .tab-item.active .badge, .tabs-color-stable .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-positive .tab-item { + color: rgba(56, 126, 245, 0.4); + opacity: 1; } + .tabs-color-positive .tab-item .badge { + opacity: 0.4; } + .tabs-color-positive .tab-item.tab-item-active, .tabs-color-positive .tab-item.active, .tabs-color-positive .tab-item.activated { + color: #387ef5; + border: 0 solid #387ef5; } + .tabs-color-positive .tab-item.tab-item-active .badge, .tabs-color-positive .tab-item.active .badge, .tabs-color-positive .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-calm .tab-item { + color: rgba(17, 193, 243, 0.4); + opacity: 1; } + .tabs-color-calm .tab-item .badge { + opacity: 0.4; } + .tabs-color-calm .tab-item.tab-item-active, .tabs-color-calm .tab-item.active, .tabs-color-calm .tab-item.activated { + color: #11c1f3; + border: 0 solid #11c1f3; } + .tabs-color-calm .tab-item.tab-item-active .badge, .tabs-color-calm .tab-item.active .badge, .tabs-color-calm .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-assertive .tab-item { + color: rgba(239, 71, 58, 0.4); + opacity: 1; } + .tabs-color-assertive .tab-item .badge { + opacity: 0.4; } + .tabs-color-assertive .tab-item.tab-item-active, .tabs-color-assertive .tab-item.active, .tabs-color-assertive .tab-item.activated { + color: #ef473a; + border: 0 solid #ef473a; } + .tabs-color-assertive .tab-item.tab-item-active .badge, .tabs-color-assertive .tab-item.active .badge, .tabs-color-assertive .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-balanced .tab-item { + color: rgba(51, 205, 95, 0.4); + opacity: 1; } + .tabs-color-balanced .tab-item .badge { + opacity: 0.4; } + .tabs-color-balanced .tab-item.tab-item-active, .tabs-color-balanced .tab-item.active, .tabs-color-balanced .tab-item.activated { + color: #33cd5f; + border: 0 solid #33cd5f; } + .tabs-color-balanced .tab-item.tab-item-active .badge, .tabs-color-balanced .tab-item.active .badge, .tabs-color-balanced .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-energized .tab-item { + color: rgba(255, 201, 0, 0.4); + opacity: 1; } + .tabs-color-energized .tab-item .badge { + opacity: 0.4; } + .tabs-color-energized .tab-item.tab-item-active, .tabs-color-energized .tab-item.active, .tabs-color-energized .tab-item.activated { + color: #ffc900; + border: 0 solid #ffc900; } + .tabs-color-energized .tab-item.tab-item-active .badge, .tabs-color-energized .tab-item.active .badge, .tabs-color-energized .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-royal .tab-item { + color: rgba(136, 106, 234, 0.4); + opacity: 1; } + .tabs-color-royal .tab-item .badge { + opacity: 0.4; } + .tabs-color-royal .tab-item.tab-item-active, .tabs-color-royal .tab-item.active, .tabs-color-royal .tab-item.activated { + color: #886aea; + border: 0 solid #886aea; } + .tabs-color-royal .tab-item.tab-item-active .badge, .tabs-color-royal .tab-item.active .badge, .tabs-color-royal .tab-item.activated .badge { + opacity: 1; } + +.tabs-color-dark .tab-item { + color: rgba(68, 68, 68, 0.4); + opacity: 1; } + .tabs-color-dark .tab-item .badge { + opacity: 0.4; } + .tabs-color-dark .tab-item.tab-item-active, .tabs-color-dark .tab-item.active, .tabs-color-dark .tab-item.activated { + color: #444; + border: 0 solid #444; } + .tabs-color-dark .tab-item.tab-item-active .badge, .tabs-color-dark .tab-item.active .badge, .tabs-color-dark .tab-item.activated .badge { + opacity: 1; } + +ion-tabs.tabs-color-active-light .tab-item { + color: #444; } + ion-tabs.tabs-color-active-light .tab-item.tab-item-active, ion-tabs.tabs-color-active-light .tab-item.active, ion-tabs.tabs-color-active-light .tab-item.activated { + color: #fff; } + +ion-tabs.tabs-color-active-stable .tab-item { + color: #444; } + ion-tabs.tabs-color-active-stable .tab-item.tab-item-active, ion-tabs.tabs-color-active-stable .tab-item.active, ion-tabs.tabs-color-active-stable .tab-item.activated { + color: #f8f8f8; } + +ion-tabs.tabs-color-active-positive .tab-item { + color: #444; } + ion-tabs.tabs-color-active-positive .tab-item.tab-item-active, ion-tabs.tabs-color-active-positive .tab-item.active, ion-tabs.tabs-color-active-positive .tab-item.activated { + color: #387ef5; } + +ion-tabs.tabs-color-active-calm .tab-item { + color: #444; } + ion-tabs.tabs-color-active-calm .tab-item.tab-item-active, ion-tabs.tabs-color-active-calm .tab-item.active, ion-tabs.tabs-color-active-calm .tab-item.activated { + color: #11c1f3; } + +ion-tabs.tabs-color-active-assertive .tab-item { + color: #444; } + ion-tabs.tabs-color-active-assertive .tab-item.tab-item-active, ion-tabs.tabs-color-active-assertive .tab-item.active, ion-tabs.tabs-color-active-assertive .tab-item.activated { + color: #ef473a; } + +ion-tabs.tabs-color-active-balanced .tab-item { + color: #444; } + ion-tabs.tabs-color-active-balanced .tab-item.tab-item-active, ion-tabs.tabs-color-active-balanced .tab-item.active, ion-tabs.tabs-color-active-balanced .tab-item.activated { + color: #33cd5f; } + +ion-tabs.tabs-color-active-energized .tab-item { + color: #444; } + ion-tabs.tabs-color-active-energized .tab-item.tab-item-active, ion-tabs.tabs-color-active-energized .tab-item.active, ion-tabs.tabs-color-active-energized .tab-item.activated { + color: #ffc900; } + +ion-tabs.tabs-color-active-royal .tab-item { + color: #444; } + ion-tabs.tabs-color-active-royal .tab-item.tab-item-active, ion-tabs.tabs-color-active-royal .tab-item.active, ion-tabs.tabs-color-active-royal .tab-item.activated { + color: #886aea; } + +ion-tabs.tabs-color-active-dark .tab-item { + color: #fff; } + ion-tabs.tabs-color-active-dark .tab-item.tab-item-active, ion-tabs.tabs-color-active-dark .tab-item.active, ion-tabs.tabs-color-active-dark .tab-item.activated { + color: #444; } + +.tabs-top.tabs-striped { + padding-bottom: 0; } + .tabs-top.tabs-striped .tab-item { + background: transparent; + -webkit-transition: color .1s ease; + -moz-transition: color .1s ease; + -ms-transition: color .1s ease; + -o-transition: color .1s ease; + transition: color .1s ease; } + .tabs-top.tabs-striped .tab-item.tab-item-active, .tabs-top.tabs-striped .tab-item.active, .tabs-top.tabs-striped .tab-item.activated { + margin-top: 1px; + border-width: 0px 0px 2px 0px !important; + border-style: solid; } + .tabs-top.tabs-striped .tab-item.tab-item-active > .badge, .tabs-top.tabs-striped .tab-item.tab-item-active > i, .tabs-top.tabs-striped .tab-item.active > .badge, .tabs-top.tabs-striped .tab-item.active > i, .tabs-top.tabs-striped .tab-item.activated > .badge, .tabs-top.tabs-striped .tab-item.activated > i { + margin-top: -1px; } + .tabs-top.tabs-striped .tab-item .badge { + -webkit-transition: color .2s ease; + -moz-transition: color .2s ease; + -ms-transition: color .2s ease; + -o-transition: color .2s ease; + transition: color .2s ease; } + .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active .tab-title, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active i, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active .tab-title, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active i, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated .tab-title, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated i { + display: block; + margin-top: -1px; } + .tabs-top.tabs-striped.tabs-icon-left .tab-item { + margin-top: 1px; } + .tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active .tab-title, .tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active i, .tabs-top.tabs-striped.tabs-icon-left .tab-item.active .tab-title, .tabs-top.tabs-striped.tabs-icon-left .tab-item.active i, .tabs-top.tabs-striped.tabs-icon-left .tab-item.activated .tab-title, .tabs-top.tabs-striped.tabs-icon-left .tab-item.activated i { + margin-top: -0.1em; } + +/* Allow parent element to have tabs-top */ +/* If you change this, change platform.scss as well */ +.tabs-top > .tabs, +.tabs.tabs-top { + top: 44px; + padding-top: 0; + background-position: bottom; + border-top-width: 0; + border-bottom-width: 1px; } + .tabs-top > .tabs .tab-item.tab-item-active .badge, .tabs-top > .tabs .tab-item.active .badge, .tabs-top > .tabs .tab-item.activated .badge, + .tabs.tabs-top .tab-item.tab-item-active .badge, + .tabs.tabs-top .tab-item.active .badge, + .tabs.tabs-top .tab-item.activated .badge { + top: 4%; } + +.tabs-top ~ .bar-header { + border-bottom-width: 0; } + +.tab-item { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + display: block; + overflow: hidden; + max-width: 150px; + height: 100%; + color: inherit; + text-align: center; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + font-weight: 400; + font-size: 14px; + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; + opacity: 0.7; } + .tab-item:hover { + cursor: pointer; } + .tab-item.tab-hidden { + display: none; } + +.tabs-item-hide > .tabs, +.tabs.tabs-item-hide { + display: none; } + +.tabs-icon-top > .tabs .tab-item, +.tabs-icon-top.tabs .tab-item, +.tabs-icon-bottom > .tabs .tab-item, +.tabs-icon-bottom.tabs .tab-item { + font-size: 10px; + line-height: 14px; } + +.tab-item .icon { + display: block; + margin: 0 auto; + height: 32px; + font-size: 32px; } + +.tabs-icon-left.tabs .tab-item, +.tabs-icon-left > .tabs .tab-item, +.tabs-icon-right.tabs .tab-item, +.tabs-icon-right > .tabs .tab-item { + font-size: 10px; } + .tabs-icon-left.tabs .tab-item .icon, .tabs-icon-left.tabs .tab-item .tab-title, + .tabs-icon-left > .tabs .tab-item .icon, + .tabs-icon-left > .tabs .tab-item .tab-title, + .tabs-icon-right.tabs .tab-item .icon, + .tabs-icon-right.tabs .tab-item .tab-title, + .tabs-icon-right > .tabs .tab-item .icon, + .tabs-icon-right > .tabs .tab-item .tab-title { + display: inline-block; + vertical-align: top; + margin-top: -.1em; } + .tabs-icon-left.tabs .tab-item .icon:before, .tabs-icon-left.tabs .tab-item .tab-title:before, + .tabs-icon-left > .tabs .tab-item .icon:before, + .tabs-icon-left > .tabs .tab-item .tab-title:before, + .tabs-icon-right.tabs .tab-item .icon:before, + .tabs-icon-right.tabs .tab-item .tab-title:before, + .tabs-icon-right > .tabs .tab-item .icon:before, + .tabs-icon-right > .tabs .tab-item .tab-title:before { + font-size: 24px; + line-height: 49px; } + +.tabs-icon-left > .tabs .tab-item .icon, +.tabs-icon-left.tabs .tab-item .icon { + padding-right: 3px; } + +.tabs-icon-right > .tabs .tab-item .icon, +.tabs-icon-right.tabs .tab-item .icon { + padding-left: 3px; } + +.tabs-icon-only > .tabs .icon, +.tabs-icon-only.tabs .icon { + line-height: inherit; } + +.tab-item.has-badge { + position: relative; } + +.tab-item .badge { + position: absolute; + top: 4%; + right: 33%; + right: calc(50% - 26px); + padding: 1px 6px; + height: auto; + font-size: 12px; + line-height: 16px; } + +/* Navigational tab */ +/* Active state for tab */ +.tab-item.tab-item-active, +.tab-item.active, +.tab-item.activated { + opacity: 1; } + .tab-item.tab-item-active.tab-item-light, + .tab-item.active.tab-item-light, + .tab-item.activated.tab-item-light { + color: #fff; } + .tab-item.tab-item-active.tab-item-stable, + .tab-item.active.tab-item-stable, + .tab-item.activated.tab-item-stable { + color: #f8f8f8; } + .tab-item.tab-item-active.tab-item-positive, + .tab-item.active.tab-item-positive, + .tab-item.activated.tab-item-positive { + color: #387ef5; } + .tab-item.tab-item-active.tab-item-calm, + .tab-item.active.tab-item-calm, + .tab-item.activated.tab-item-calm { + color: #11c1f3; } + .tab-item.tab-item-active.tab-item-assertive, + .tab-item.active.tab-item-assertive, + .tab-item.activated.tab-item-assertive { + color: #ef473a; } + .tab-item.tab-item-active.tab-item-balanced, + .tab-item.active.tab-item-balanced, + .tab-item.activated.tab-item-balanced { + color: #33cd5f; } + .tab-item.tab-item-active.tab-item-energized, + .tab-item.active.tab-item-energized, + .tab-item.activated.tab-item-energized { + color: #ffc900; } + .tab-item.tab-item-active.tab-item-royal, + .tab-item.active.tab-item-royal, + .tab-item.activated.tab-item-royal { + color: #886aea; } + .tab-item.tab-item-active.tab-item-dark, + .tab-item.active.tab-item-dark, + .tab-item.activated.tab-item-dark { + color: #444; } + +.item.tabs { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + padding: 0; } + .item.tabs .icon:before { + position: relative; } + +.tab-item.disabled, +.tab-item[disabled] { + opacity: .4; + cursor: default; + pointer-events: none; } + +.nav-bar-tabs-top.hide ~ .view-container .tabs-top .tabs { + top: 0; } + +.pane[hide-nav-bar="true"] .has-tabs-top { + top: 49px; } + +/** + * Menus + * -------------------------------------------------- + * Side panel structure + */ +.menu { + position: absolute; + top: 0; + bottom: 0; + z-index: 0; + overflow: hidden; + min-height: 100%; + max-height: 100%; + width: 275px; + background-color: #fff; } + .menu .scroll-content { + z-index: 10; } + .menu .bar-header { + z-index: 11; } + +.menu-content { + -webkit-transform: none; + transform: none; + box-shadow: -1px 0px 2px rgba(0, 0, 0, 0.2), 1px 0px 2px rgba(0, 0, 0, 0.2); } + +.menu-open .menu-content .pane, +.menu-open .menu-content .scroll-content { + pointer-events: none; } + +.menu-open .menu-content .scroll-content .scroll { + pointer-events: none; } + +.menu-open .menu-content .scroll-content:not(.overflow-scroll) { + overflow: hidden; } + +.grade-b .menu-content, +.grade-c .menu-content { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + right: -1px; + left: -1px; + border-right: 1px solid #ccc; + border-left: 1px solid #ccc; + box-shadow: none; } + +.menu-left { + left: 0; } + +.menu-right { + right: 0; } + +.aside-open.aside-resizing .menu-right { + display: none; } + +.menu-animated { + -webkit-transition: -webkit-transform 200ms ease; + transition: transform 200ms ease; } + +/** + * Modals + * -------------------------------------------------- + * Modals are independent windows that slide in from off-screen. + */ +.modal-backdrop, +.modal-backdrop-bg { + position: fixed; + top: 0; + left: 0; + z-index: 10; + width: 100%; + height: 100%; } + +.modal-backdrop-bg { + pointer-events: none; } + +.modal { + display: block; + position: absolute; + top: 0; + z-index: 10; + overflow: hidden; + min-height: 100%; + width: 100%; + background-color: #fff; } + +@media (min-width: 680px) { + .modal { + top: 20%; + right: 20%; + bottom: 20%; + left: 20%; + min-height: 240px; + width: 60%; } + .modal.ng-leave-active { + bottom: 0; } + .platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader) { + height: 44px; } + .platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader) > * { + margin-top: 0; } + .platform-ios.platform-cordova .modal-wrapper .modal .tabs-top > .tabs, + .platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top { + top: 44px; } + .platform-ios.platform-cordova .modal-wrapper .modal .has-header, + .platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader { + top: 44px; } + .platform-ios.platform-cordova .modal-wrapper .modal .has-subheader { + top: 88px; } + .platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-tabs-top { + top: 93px; } + .platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-subheader.has-tabs-top { + top: 137px; } + .modal-backdrop-bg { + -webkit-transition: opacity 300ms ease-in-out; + transition: opacity 300ms ease-in-out; + background-color: #000; + opacity: 0; } + .active .modal-backdrop-bg { + opacity: 0.5; } } + +.modal-open { + pointer-events: none; } + .modal-open .modal, + .modal-open .modal-backdrop { + pointer-events: auto; } + .modal-open.loading-active .modal, + .modal-open.loading-active .modal-backdrop { + pointer-events: none; } + +/** + * Popovers + * -------------------------------------------------- + * Popovers are independent views which float over content + */ +.popover-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 10; + width: 100%; + height: 100%; + background-color: transparent; } + .popover-backdrop.active { + background-color: rgba(0, 0, 0, 0.1); } + +.popover { + position: absolute; + top: 25%; + left: 50%; + z-index: 10; + display: block; + margin-top: 12px; + margin-left: -110px; + height: 280px; + width: 220px; + background-color: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4); + opacity: 0; } + .popover .item:first-child { + border-top: 0; } + .popover .item:last-child { + border-bottom: 0; } + .popover.popover-bottom { + margin-top: -12px; } + +.popover, +.popover .bar-header { + border-radius: 2px; } + +.popover .scroll-content { + z-index: 1; + margin: 2px 0; } + +.popover .bar-header { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + +.popover .has-header { + border-top-right-radius: 0; + border-top-left-radius: 0; } + +.popover-arrow { + display: none; } + +.platform-ios .popover { + box-shadow: 0 0 40px rgba(0, 0, 0, 0.08); + border-radius: 10px; } + +.platform-ios .popover .bar-header { + -webkit-border-top-right-radius: 10px; + border-top-right-radius: 10px; + -webkit-border-top-left-radius: 10px; + border-top-left-radius: 10px; } + +.platform-ios .popover .scroll-content { + margin: 8px 0; + border-radius: 10px; } + +.platform-ios .popover .scroll-content.has-header { + margin-top: 0; } + +.platform-ios .popover-arrow { + position: absolute; + display: block; + top: -17px; + width: 30px; + height: 19px; + overflow: hidden; } + .platform-ios .popover-arrow:after { + position: absolute; + top: 12px; + left: 5px; + width: 20px; + height: 20px; + background-color: #fff; + border-radius: 3px; + content: ''; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); } + +.platform-ios .popover-bottom .popover-arrow { + top: auto; + bottom: -10px; } + .platform-ios .popover-bottom .popover-arrow:after { + top: -6px; } + +.platform-android .popover { + margin-top: -32px; + background-color: #fafafa; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35); } + .platform-android .popover .item { + border-color: #fafafa; + background-color: #fafafa; + color: #4d4d4d; } + .platform-android .popover.popover-bottom { + margin-top: 32px; } + +.platform-android .popover-backdrop, +.platform-android .popover-backdrop.active { + background-color: transparent; } + +.popover-open { + pointer-events: none; } + .popover-open .popover, + .popover-open .popover-backdrop { + pointer-events: auto; } + .popover-open.loading-active .popover, + .popover-open.loading-active .popover-backdrop { + pointer-events: none; } + +@media (min-width: 680px) { + .popover { + width: 360px; + margin-left: -180px; } } + +/** + * Popups + * -------------------------------------------------- + */ +.popup-container { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: transparent; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + -moz-justify-content: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + z-index: 12; + visibility: hidden; } + .popup-container.popup-showing { + visibility: visible; } + .popup-container.popup-hidden .popup { + -webkit-animation-name: scaleOut; + animation-name: scaleOut; + -webkit-animation-duration: 0.1s; + animation-duration: 0.1s; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; } + .popup-container.active .popup { + -webkit-animation-name: superScaleIn; + animation-name: superScaleIn; + -webkit-animation-duration: 0.2s; + animation-duration: 0.2s; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; } + .popup-container .popup { + width: 250px; + max-width: 100%; + max-height: 90%; + border-radius: 0px; + background-color: rgba(255, 255, 255, 0.9); + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-direction: normal; + -webkit-box-orient: vertical; + -webkit-flex-direction: column; + -moz-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; } + .popup-container input, + .popup-container textarea { + width: 100%; } + +.popup-head { + padding: 15px 10px; + border-bottom: 1px solid #eee; + text-align: center; } + +.popup-title { + margin: 0; + padding: 0; + font-size: 15px; } + +.popup-sub-title { + margin: 5px 0 0 0; + padding: 0; + font-weight: normal; + font-size: 11px; } + +.popup-body { + padding: 10px; + overflow: auto; } + +.popup-buttons { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-direction: normal; + -webkit-box-orient: horizontal; + -webkit-flex-direction: row; + -moz-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + padding: 10px; + min-height: 65px; } + .popup-buttons .button { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + display: block; + min-height: 45px; + border-radius: 2px; + line-height: 20px; + margin-right: 5px; } + .popup-buttons .button:last-child { + margin-right: 0px; } + +.popup-open { + pointer-events: none; } + .popup-open.modal-open .modal { + pointer-events: none; } + .popup-open .popup-backdrop, .popup-open .popup { + pointer-events: auto; } + +/** + * Loading + * -------------------------------------------------- + */ +.loading-container { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + z-index: 13; + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + -moz-justify-content: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + -webkit-transition: 0.2s opacity linear; + transition: 0.2s opacity linear; + visibility: hidden; + opacity: 0; } + .loading-container:not(.visible) .icon, + .loading-container:not(.visible) .spinner { + display: none; } + .loading-container.visible { + visibility: visible; } + .loading-container.active { + opacity: 1; } + .loading-container .loading { + padding: 20px; + border-radius: 5px; + background-color: rgba(0, 0, 0, 0.7); + color: #fff; + text-align: center; + text-overflow: ellipsis; + font-size: 15px; } + .loading-container .loading h1, .loading-container .loading h2, .loading-container .loading h3, .loading-container .loading h4, .loading-container .loading h5, .loading-container .loading h6 { + color: #fff; } + +/** + * Items + * -------------------------------------------------- + */ +.item { + border-color: #ddd; + background-color: #fff; + color: #444; + position: relative; + z-index: 2; + display: block; + margin: -1px; + padding: 16px; + border-width: 1px; + border-style: solid; + font-size: 16px; } + .item h2 { + margin: 0 0 2px 0; + font-size: 16px; + font-weight: normal; } + .item h3 { + margin: 0 0 4px 0; + font-size: 14px; } + .item h4 { + margin: 0 0 4px 0; + font-size: 12px; } + .item h5, .item h6 { + margin: 0 0 3px 0; + font-size: 10px; } + .item p { + color: #666; + font-size: 14px; + margin-bottom: 2px; } + .item h1:last-child, + .item h2:last-child, + .item h3:last-child, + .item h4:last-child, + .item h5:last-child, + .item h6:last-child, + .item p:last-child { + margin-bottom: 0; } + .item .badge { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + position: absolute; + top: 16px; + right: 32px; } + .item.item-button-right .badge { + right: 67px; } + .item.item-divider .badge { + top: 8px; } + .item .badge + .badge { + margin-right: 5px; } + .item.item-light { + border-color: #ddd; + background-color: #fff; + color: #444; } + .item.item-stable { + border-color: #b2b2b2; + background-color: #f8f8f8; + color: #444; } + .item.item-positive { + border-color: #0c60ee; + background-color: #387ef5; + color: #fff; } + .item.item-calm { + border-color: #0a9dc7; + background-color: #11c1f3; + color: #fff; } + .item.item-assertive { + border-color: #e42112; + background-color: #ef473a; + color: #fff; } + .item.item-balanced { + border-color: #28a54c; + background-color: #33cd5f; + color: #fff; } + .item.item-energized { + border-color: #e6b500; + background-color: #ffc900; + color: #fff; } + .item.item-royal { + border-color: #6b46e5; + background-color: #886aea; + color: #fff; } + .item.item-dark { + border-color: #111; + background-color: #444; + color: #fff; } + .item[ng-click]:hover { + cursor: pointer; } + +.list-borderless .item, +.item-borderless { + border-width: 0; } + +.item.active, +.item.activated, +.item-complex.active .item-content, +.item-complex.activated .item-content, +.item .item-content.active, +.item .item-content.activated { + border-color: #ccc; + background-color: #D9D9D9; } + .item.active.item-complex > .item-content, + .item.activated.item-complex > .item-content, + .item-complex.active .item-content.item-complex > .item-content, + .item-complex.activated .item-content.item-complex > .item-content, + .item .item-content.active.item-complex > .item-content, + .item .item-content.activated.item-complex > .item-content { + border-color: #ccc; + background-color: #D9D9D9; } + .item.active.item-light, + .item.activated.item-light, + .item-complex.active .item-content.item-light, + .item-complex.activated .item-content.item-light, + .item .item-content.active.item-light, + .item .item-content.activated.item-light { + border-color: #ccc; + background-color: #fafafa; } + .item.active.item-light.item-complex > .item-content, + .item.activated.item-light.item-complex > .item-content, + .item-complex.active .item-content.item-light.item-complex > .item-content, + .item-complex.activated .item-content.item-light.item-complex > .item-content, + .item .item-content.active.item-light.item-complex > .item-content, + .item .item-content.activated.item-light.item-complex > .item-content { + border-color: #ccc; + background-color: #fafafa; } + .item.active.item-stable, + .item.activated.item-stable, + .item-complex.active .item-content.item-stable, + .item-complex.activated .item-content.item-stable, + .item .item-content.active.item-stable, + .item .item-content.activated.item-stable { + border-color: #a2a2a2; + background-color: #e5e5e5; } + .item.active.item-stable.item-complex > .item-content, + .item.activated.item-stable.item-complex > .item-content, + .item-complex.active .item-content.item-stable.item-complex > .item-content, + .item-complex.activated .item-content.item-stable.item-complex > .item-content, + .item .item-content.active.item-stable.item-complex > .item-content, + .item .item-content.activated.item-stable.item-complex > .item-content { + border-color: #a2a2a2; + background-color: #e5e5e5; } + .item.active.item-positive, + .item.activated.item-positive, + .item-complex.active .item-content.item-positive, + .item-complex.activated .item-content.item-positive, + .item .item-content.active.item-positive, + .item .item-content.activated.item-positive { + border-color: #0c60ee; + background-color: #0c60ee; } + .item.active.item-positive.item-complex > .item-content, + .item.activated.item-positive.item-complex > .item-content, + .item-complex.active .item-content.item-positive.item-complex > .item-content, + .item-complex.activated .item-content.item-positive.item-complex > .item-content, + .item .item-content.active.item-positive.item-complex > .item-content, + .item .item-content.activated.item-positive.item-complex > .item-content { + border-color: #0c60ee; + background-color: #0c60ee; } + .item.active.item-calm, + .item.activated.item-calm, + .item-complex.active .item-content.item-calm, + .item-complex.activated .item-content.item-calm, + .item .item-content.active.item-calm, + .item .item-content.activated.item-calm { + border-color: #0a9dc7; + background-color: #0a9dc7; } + .item.active.item-calm.item-complex > .item-content, + .item.activated.item-calm.item-complex > .item-content, + .item-complex.active .item-content.item-calm.item-complex > .item-content, + .item-complex.activated .item-content.item-calm.item-complex > .item-content, + .item .item-content.active.item-calm.item-complex > .item-content, + .item .item-content.activated.item-calm.item-complex > .item-content { + border-color: #0a9dc7; + background-color: #0a9dc7; } + .item.active.item-assertive, + .item.activated.item-assertive, + .item-complex.active .item-content.item-assertive, + .item-complex.activated .item-content.item-assertive, + .item .item-content.active.item-assertive, + .item .item-content.activated.item-assertive { + border-color: #e42112; + background-color: #e42112; } + .item.active.item-assertive.item-complex > .item-content, + .item.activated.item-assertive.item-complex > .item-content, + .item-complex.active .item-content.item-assertive.item-complex > .item-content, + .item-complex.activated .item-content.item-assertive.item-complex > .item-content, + .item .item-content.active.item-assertive.item-complex > .item-content, + .item .item-content.activated.item-assertive.item-complex > .item-content { + border-color: #e42112; + background-color: #e42112; } + .item.active.item-balanced, + .item.activated.item-balanced, + .item-complex.active .item-content.item-balanced, + .item-complex.activated .item-content.item-balanced, + .item .item-content.active.item-balanced, + .item .item-content.activated.item-balanced { + border-color: #28a54c; + background-color: #28a54c; } + .item.active.item-balanced.item-complex > .item-content, + .item.activated.item-balanced.item-complex > .item-content, + .item-complex.active .item-content.item-balanced.item-complex > .item-content, + .item-complex.activated .item-content.item-balanced.item-complex > .item-content, + .item .item-content.active.item-balanced.item-complex > .item-content, + .item .item-content.activated.item-balanced.item-complex > .item-content { + border-color: #28a54c; + background-color: #28a54c; } + .item.active.item-energized, + .item.activated.item-energized, + .item-complex.active .item-content.item-energized, + .item-complex.activated .item-content.item-energized, + .item .item-content.active.item-energized, + .item .item-content.activated.item-energized { + border-color: #e6b500; + background-color: #e6b500; } + .item.active.item-energized.item-complex > .item-content, + .item.activated.item-energized.item-complex > .item-content, + .item-complex.active .item-content.item-energized.item-complex > .item-content, + .item-complex.activated .item-content.item-energized.item-complex > .item-content, + .item .item-content.active.item-energized.item-complex > .item-content, + .item .item-content.activated.item-energized.item-complex > .item-content { + border-color: #e6b500; + background-color: #e6b500; } + .item.active.item-royal, + .item.activated.item-royal, + .item-complex.active .item-content.item-royal, + .item-complex.activated .item-content.item-royal, + .item .item-content.active.item-royal, + .item .item-content.activated.item-royal { + border-color: #6b46e5; + background-color: #6b46e5; } + .item.active.item-royal.item-complex > .item-content, + .item.activated.item-royal.item-complex > .item-content, + .item-complex.active .item-content.item-royal.item-complex > .item-content, + .item-complex.activated .item-content.item-royal.item-complex > .item-content, + .item .item-content.active.item-royal.item-complex > .item-content, + .item .item-content.activated.item-royal.item-complex > .item-content { + border-color: #6b46e5; + background-color: #6b46e5; } + .item.active.item-dark, + .item.activated.item-dark, + .item-complex.active .item-content.item-dark, + .item-complex.activated .item-content.item-dark, + .item .item-content.active.item-dark, + .item .item-content.activated.item-dark { + border-color: #000; + background-color: #262626; } + .item.active.item-dark.item-complex > .item-content, + .item.activated.item-dark.item-complex > .item-content, + .item-complex.active .item-content.item-dark.item-complex > .item-content, + .item-complex.activated .item-content.item-dark.item-complex > .item-content, + .item .item-content.active.item-dark.item-complex > .item-content, + .item .item-content.activated.item-dark.item-complex > .item-content { + border-color: #000; + background-color: #262626; } + +.item, +.item h1, +.item h2, +.item h3, +.item h4, +.item h5, +.item h6, +.item p, +.item-content, +.item-content h1, +.item-content h2, +.item-content h3, +.item-content h4, +.item-content h5, +.item-content h6, +.item-content p { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + +a.item { + color: inherit; + text-decoration: none; } + a.item:hover, a.item:focus { + text-decoration: none; } + +/** + * Complex Items + * -------------------------------------------------- + * Adding .item-complex allows the .item to be slidable and + * have options underneath the button, but also requires an + * additional .item-content element inside .item. + * Basically .item-complex removes any default settings which + * .item added, so that .item-content looks them as just .item. + */ +.item-complex, +a.item.item-complex, +button.item.item-complex { + padding: 0; } + +.item-complex .item-content, +.item-radio .item-content { + position: relative; + z-index: 2; + padding: 16px 49px 16px 16px; + border: none; + background-color: #fff; } + +a.item-content { + display: block; + color: inherit; + text-decoration: none; } + +.item-text-wrap .item, +.item-text-wrap .item-content, +.item-text-wrap, +.item-text-wrap h1, +.item-text-wrap h2, +.item-text-wrap h3, +.item-text-wrap h4, +.item-text-wrap h5, +.item-text-wrap h6, +.item-text-wrap p, +.item-complex.item-text-wrap .item-content, +.item-body h1, +.item-body h2, +.item-body h3, +.item-body h4, +.item-body h5, +.item-body h6, +.item-body p { + overflow: visible; + white-space: normal; } + +.item-complex.item-text-wrap, +.item-complex.item-text-wrap h1, +.item-complex.item-text-wrap h2, +.item-complex.item-text-wrap h3, +.item-complex.item-text-wrap h4, +.item-complex.item-text-wrap h5, +.item-complex.item-text-wrap h6, +.item-complex.item-text-wrap p { + overflow: visible; + white-space: normal; } + +.item-complex.item-light > .item-content { + border-color: #ddd; + background-color: #fff; + color: #444; } + .item-complex.item-light > .item-content.active, .item-complex.item-light > .item-content:active { + border-color: #ccc; + background-color: #fafafa; } + .item-complex.item-light > .item-content.active.item-complex > .item-content, .item-complex.item-light > .item-content:active.item-complex > .item-content { + border-color: #ccc; + background-color: #fafafa; } + +.item-complex.item-stable > .item-content { + border-color: #b2b2b2; + background-color: #f8f8f8; + color: #444; } + .item-complex.item-stable > .item-content.active, .item-complex.item-stable > .item-content:active { + border-color: #a2a2a2; + background-color: #e5e5e5; } + .item-complex.item-stable > .item-content.active.item-complex > .item-content, .item-complex.item-stable > .item-content:active.item-complex > .item-content { + border-color: #a2a2a2; + background-color: #e5e5e5; } + +.item-complex.item-positive > .item-content { + border-color: #0c60ee; + background-color: #387ef5; + color: #fff; } + .item-complex.item-positive > .item-content.active, .item-complex.item-positive > .item-content:active { + border-color: #0c60ee; + background-color: #0c60ee; } + .item-complex.item-positive > .item-content.active.item-complex > .item-content, .item-complex.item-positive > .item-content:active.item-complex > .item-content { + border-color: #0c60ee; + background-color: #0c60ee; } + +.item-complex.item-calm > .item-content { + border-color: #0a9dc7; + background-color: #11c1f3; + color: #fff; } + .item-complex.item-calm > .item-content.active, .item-complex.item-calm > .item-content:active { + border-color: #0a9dc7; + background-color: #0a9dc7; } + .item-complex.item-calm > .item-content.active.item-complex > .item-content, .item-complex.item-calm > .item-content:active.item-complex > .item-content { + border-color: #0a9dc7; + background-color: #0a9dc7; } + +.item-complex.item-assertive > .item-content { + border-color: #e42112; + background-color: #ef473a; + color: #fff; } + .item-complex.item-assertive > .item-content.active, .item-complex.item-assertive > .item-content:active { + border-color: #e42112; + background-color: #e42112; } + .item-complex.item-assertive > .item-content.active.item-complex > .item-content, .item-complex.item-assertive > .item-content:active.item-complex > .item-content { + border-color: #e42112; + background-color: #e42112; } + +.item-complex.item-balanced > .item-content { + border-color: #28a54c; + background-color: #33cd5f; + color: #fff; } + .item-complex.item-balanced > .item-content.active, .item-complex.item-balanced > .item-content:active { + border-color: #28a54c; + background-color: #28a54c; } + .item-complex.item-balanced > .item-content.active.item-complex > .item-content, .item-complex.item-balanced > .item-content:active.item-complex > .item-content { + border-color: #28a54c; + background-color: #28a54c; } + +.item-complex.item-energized > .item-content { + border-color: #e6b500; + background-color: #ffc900; + color: #fff; } + .item-complex.item-energized > .item-content.active, .item-complex.item-energized > .item-content:active { + border-color: #e6b500; + background-color: #e6b500; } + .item-complex.item-energized > .item-content.active.item-complex > .item-content, .item-complex.item-energized > .item-content:active.item-complex > .item-content { + border-color: #e6b500; + background-color: #e6b500; } + +.item-complex.item-royal > .item-content { + border-color: #6b46e5; + background-color: #886aea; + color: #fff; } + .item-complex.item-royal > .item-content.active, .item-complex.item-royal > .item-content:active { + border-color: #6b46e5; + background-color: #6b46e5; } + .item-complex.item-royal > .item-content.active.item-complex > .item-content, .item-complex.item-royal > .item-content:active.item-complex > .item-content { + border-color: #6b46e5; + background-color: #6b46e5; } + +.item-complex.item-dark > .item-content { + border-color: #111; + background-color: #444; + color: #fff; } + .item-complex.item-dark > .item-content.active, .item-complex.item-dark > .item-content:active { + border-color: #000; + background-color: #262626; } + .item-complex.item-dark > .item-content.active.item-complex > .item-content, .item-complex.item-dark > .item-content:active.item-complex > .item-content { + border-color: #000; + background-color: #262626; } + +/** + * Item Icons + * -------------------------------------------------- + */ +.item-icon-left .icon, +.item-icon-right .icon { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + position: absolute; + top: 0; + height: 100%; + font-size: 32px; } + .item-icon-left .icon:before, + .item-icon-right .icon:before { + display: block; + width: 32px; + text-align: center; } + +.item .fill-icon { + min-width: 30px; + min-height: 30px; + font-size: 28px; } + +.item-icon-left { + padding-left: 54px; } + .item-icon-left .icon { + left: 11px; } + +.item-complex.item-icon-left { + padding-left: 0; } + .item-complex.item-icon-left .item-content { + padding-left: 54px; } + +.item-icon-right { + padding-right: 54px; } + .item-icon-right .icon { + right: 11px; } + +.item-complex.item-icon-right { + padding-right: 0; } + .item-complex.item-icon-right .item-content { + padding-right: 54px; } + +.item-icon-left.item-icon-right .icon:first-child { + right: auto; } + +.item-icon-left.item-icon-right .icon:last-child, +.item-icon-left .item-delete .icon { + left: auto; } + +.item-icon-left .icon-accessory, +.item-icon-right .icon-accessory { + color: #ccc; + font-size: 16px; } + +.item-icon-left .icon-accessory { + left: 3px; } + +.item-icon-right .icon-accessory { + right: 3px; } + +/** + * Item Button + * -------------------------------------------------- + * An item button is a child button inside an .item (not the entire .item) + */ +.item-button-left { + padding-left: 72px; } + +.item-button-left > .button, +.item-button-left .item-content > .button { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + position: absolute; + top: 8px; + left: 11px; + min-width: 34px; + min-height: 34px; + font-size: 18px; + line-height: 32px; } + .item-button-left > .button .icon:before, + .item-button-left .item-content > .button .icon:before { + position: relative; + left: auto; + width: auto; + line-height: 31px; } + .item-button-left > .button > .button, + .item-button-left .item-content > .button > .button { + margin: 0px 2px; + min-height: 34px; + font-size: 18px; + line-height: 32px; } + +.item-button-right, +a.item.item-button-right, +button.item.item-button-right { + padding-right: 80px; } + +.item-button-right > .button, +.item-button-right .item-content > .button, +.item-button-right > .buttons, +.item-button-right .item-content > .buttons { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + position: absolute; + top: 8px; + right: 16px; + min-width: 34px; + min-height: 34px; + font-size: 18px; + line-height: 32px; } + .item-button-right > .button .icon:before, + .item-button-right .item-content > .button .icon:before, + .item-button-right > .buttons .icon:before, + .item-button-right .item-content > .buttons .icon:before { + position: relative; + left: auto; + width: auto; + line-height: 31px; } + .item-button-right > .button > .button, + .item-button-right .item-content > .button > .button, + .item-button-right > .buttons > .button, + .item-button-right .item-content > .buttons > .button { + margin: 0px 2px; + min-width: 34px; + min-height: 34px; + font-size: 18px; + line-height: 32px; } + +.item-avatar, +.item-avatar .item-content, +.item-avatar-left, +.item-avatar-left .item-content { + padding-left: 72px; + min-height: 72px; } + .item-avatar > img:first-child, + .item-avatar .item-image, + .item-avatar .item-content > img:first-child, + .item-avatar .item-content .item-image, + .item-avatar-left > img:first-child, + .item-avatar-left .item-image, + .item-avatar-left .item-content > img:first-child, + .item-avatar-left .item-content .item-image { + position: absolute; + top: 16px; + left: 16px; + max-width: 40px; + max-height: 40px; + width: 100%; + height: 100%; + border-radius: 50%; } + +.item-avatar-right, +.item-avatar-right .item-content { + padding-right: 72px; + min-height: 72px; } + .item-avatar-right > img:first-child, + .item-avatar-right .item-image, + .item-avatar-right .item-content > img:first-child, + .item-avatar-right .item-content .item-image { + position: absolute; + top: 16px; + right: 16px; + max-width: 40px; + max-height: 40px; + width: 100%; + height: 100%; + border-radius: 50%; } + +.item-thumbnail-left, +.item-thumbnail-left .item-content { + padding-top: 8px; + padding-left: 106px; + min-height: 100px; } + .item-thumbnail-left > img:first-child, + .item-thumbnail-left .item-image, + .item-thumbnail-left .item-content > img:first-child, + .item-thumbnail-left .item-content .item-image { + position: absolute; + top: 10px; + left: 10px; + max-width: 80px; + max-height: 80px; + width: 100%; + height: 100%; } + +.item-avatar.item-complex, +.item-avatar-left.item-complex, +.item-thumbnail-left.item-complex { + padding-top: 0; + padding-left: 0; } + +.item-thumbnail-right, +.item-thumbnail-right .item-content { + padding-top: 8px; + padding-right: 106px; + min-height: 100px; } + .item-thumbnail-right > img:first-child, + .item-thumbnail-right .item-image, + .item-thumbnail-right .item-content > img:first-child, + .item-thumbnail-right .item-content .item-image { + position: absolute; + top: 10px; + right: 10px; + max-width: 80px; + max-height: 80px; + width: 100%; + height: 100%; } + +.item-avatar-right.item-complex, +.item-thumbnail-right.item-complex { + padding-top: 0; + padding-right: 0; } + +.item-image { + padding: 0; + text-align: center; } + .item-image img:first-child, .item-image .list-img { + width: 100%; + vertical-align: middle; } + +.item-body { + overflow: auto; + padding: 16px; + text-overflow: inherit; + white-space: normal; } + .item-body h1, .item-body h2, .item-body h3, .item-body h4, .item-body h5, .item-body h6, .item-body p { + margin-top: 16px; + margin-bottom: 16px; } + +.item-divider { + padding-top: 8px; + padding-bottom: 8px; + min-height: 30px; + background-color: #f5f5f5; + color: #222; + font-weight: 500; } + +.platform-ios .item-divider-platform, +.item-divider-ios { + padding-top: 26px; + text-transform: uppercase; + font-weight: 300; + font-size: 13px; + background-color: #efeff4; + color: #555; } + +.platform-android .item-divider-platform, +.item-divider-android { + font-weight: 300; + font-size: 13px; } + +.item-note { + float: right; + color: #aaa; + font-size: 14px; } + +.item-left-editable .item-content, +.item-right-editable .item-content { + -webkit-transition-duration: 250ms; + transition-duration: 250ms; + -webkit-transition-timing-function: ease-in-out; + transition-timing-function: ease-in-out; + -webkit-transition-property: -webkit-transform; + -moz-transition-property: -moz-transform; + transition-property: transform; } + +.list-left-editing .item-left-editable .item-content, +.item-left-editing.item-left-editable .item-content { + -webkit-transform: translate3d(50px, 0, 0); + transform: translate3d(50px, 0, 0); } + +.item-remove-animate.ng-leave { + -webkit-transition-duration: 300ms; + transition-duration: 300ms; } + +.item-remove-animate.ng-leave .item-content, .item-remove-animate.ng-leave:last-of-type { + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + -webkit-transition-timing-function: ease-in; + transition-timing-function: ease-in; + -webkit-transition-property: all; + transition-property: all; } + +.item-remove-animate.ng-leave.ng-leave-active .item-content { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0) !important; + transform: translate3d(-100%, 0, 0) !important; } + +.item-remove-animate.ng-leave.ng-leave-active:last-of-type { + opacity: 0; } + +.item-remove-animate.ng-leave.ng-leave-active ~ ion-item:not(.ng-leave) { + -webkit-transform: translate3d(0, -webkit-calc(-100% + 1px), 0); + transform: translate3d(0, calc(-100% + 1px), 0); + -webkit-transition-duration: 300ms; + transition-duration: 300ms; + -webkit-transition-timing-function: cubic-bezier(0.25, 0.81, 0.24, 1); + transition-timing-function: cubic-bezier(0.25, 0.81, 0.24, 1); + -webkit-transition-property: all; + transition-property: all; } + +.item-left-edit { + -webkit-transition: all ease-in-out 125ms; + transition: all ease-in-out 125ms; + position: absolute; + top: 0; + left: 0; + z-index: 0; + width: 50px; + height: 100%; + line-height: 100%; + display: none; + opacity: 0; + -webkit-transform: translate3d(-21px, 0, 0); + transform: translate3d(-21px, 0, 0); } + .item-left-edit .button { + height: 100%; } + .item-left-edit .button.icon { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + position: absolute; + top: 0; + height: 100%; } + .item-left-edit.visible { + display: block; } + .item-left-edit.visible.active { + opacity: 1; + -webkit-transform: translate3d(8px, 0, 0); + transform: translate3d(8px, 0, 0); } + +.list-left-editing .item-left-edit { + -webkit-transition-delay: 125ms; + transition-delay: 125ms; } + +.item-delete .button.icon { + color: #ef473a; + font-size: 24px; } + .item-delete .button.icon:hover { + opacity: .7; } + +.item-right-edit { + -webkit-transition: all ease-in-out 250ms; + transition: all ease-in-out 250ms; + position: absolute; + top: 0; + right: 0; + z-index: 3; + width: 75px; + height: 100%; + background: inherit; + padding-left: 20px; + display: block; + opacity: 0; + -webkit-transform: translate3d(75px, 0, 0); + transform: translate3d(75px, 0, 0); } + .item-right-edit .button { + min-width: 50px; + height: 100%; } + .item-right-edit .button.icon { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + position: absolute; + top: 0; + height: 100%; + font-size: 32px; } + .item-right-edit.visible { + display: block; } + .item-right-edit.visible.active { + opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.item-reorder .button.icon { + color: #444; + font-size: 32px; } + +.item-reordering { + position: absolute; + left: 0; + top: 0; + z-index: 9; + width: 100%; + box-shadow: 0px 0px 10px 0px #aaa; } + .item-reordering .item-reorder { + z-index: 9; } + +.item-placeholder { + opacity: 0.7; } + +/** + * The hidden right-side buttons that can be exposed under a list item + * with dragging. + */ +.item-options { + position: absolute; + top: 0; + right: 0; + z-index: 1; + height: 100%; } + .item-options .button { + height: 100%; + border: none; + border-radius: 0; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -moz-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; } + .item-options .button:before { + margin: 0 auto; } + +/** + * Lists + * -------------------------------------------------- + */ +.list { + position: relative; + padding-top: 1px; + padding-bottom: 1px; + padding-left: 0; + margin-bottom: 20px; } + +.list:last-child { + margin-bottom: 0px; } + .list:last-child.card { + margin-bottom: 40px; } + +/** + * List Header + * -------------------------------------------------- + */ +.list-header { + margin-top: 20px; + padding: 5px 15px; + background-color: transparent; + color: #222; + font-weight: bold; } + +.card.list .list-item { + padding-right: 1px; + padding-left: 1px; } + +/** + * Cards and Inset Lists + * -------------------------------------------------- + * A card and list-inset are close to the same thing, except a card as a box shadow. + */ +.card, +.list-inset { + overflow: hidden; + margin: 20px 10px; + border-radius: 2px; + background-color: #fff; } + +.card { + padding-top: 1px; + padding-bottom: 1px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } + .card .item { + border-left: 0; + border-right: 0; } + .card .item:first-child { + border-top: 0; } + .card .item:last-child { + border-bottom: 0; } + +.padding .card, .padding .list-inset { + margin-left: 0; + margin-right: 0; } + +.card .item:first-child, +.list-inset .item:first-child, +.padding > .list .item:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; } + .card .item:first-child .item-content, + .list-inset .item:first-child .item-content, + .padding > .list .item:first-child .item-content { + border-top-left-radius: 2px; + border-top-right-radius: 2px; } + +.card .item:last-child, +.list-inset .item:last-child, +.padding > .list .item:last-child { + border-bottom-right-radius: 2px; + border-bottom-left-radius: 2px; } + .card .item:last-child .item-content, + .list-inset .item:last-child .item-content, + .padding > .list .item:last-child .item-content { + border-bottom-right-radius: 2px; + border-bottom-left-radius: 2px; } + +.card .item:last-child, +.list-inset .item:last-child { + margin-bottom: -1px; } + +.card .item, +.list-inset .item, +.padding > .list .item, +.padding-horizontal > .list .item { + margin-right: 0; + margin-left: 0; } + .card .item.item-input input, + .list-inset .item.item-input input, + .padding > .list .item.item-input input, + .padding-horizontal > .list .item.item-input input { + padding-right: 44px; } + +.padding-left > .list .item { + margin-left: 0; } + +.padding-right > .list .item { + margin-right: 0; } + +/** + * Badges + * -------------------------------------------------- + */ +.badge { + background-color: transparent; + color: #AAAAAA; + z-index: 1; + display: inline-block; + padding: 3px 8px; + min-width: 10px; + border-radius: 10px; + vertical-align: baseline; + text-align: center; + white-space: nowrap; + font-weight: bold; + font-size: 14px; + line-height: 16px; } + .badge:empty { + display: none; } + +.tabs .tab-item .badge.badge-light, +.badge.badge-light { + background-color: #fff; + color: #444; } + +.tabs .tab-item .badge.badge-stable, +.badge.badge-stable { + background-color: #f8f8f8; + color: #444; } + +.tabs .tab-item .badge.badge-positive, +.badge.badge-positive { + background-color: #387ef5; + color: #fff; } + +.tabs .tab-item .badge.badge-calm, +.badge.badge-calm { + background-color: #11c1f3; + color: #fff; } + +.tabs .tab-item .badge.badge-assertive, +.badge.badge-assertive { + background-color: #ef473a; + color: #fff; } + +.tabs .tab-item .badge.badge-balanced, +.badge.badge-balanced { + background-color: #33cd5f; + color: #fff; } + +.tabs .tab-item .badge.badge-energized, +.badge.badge-energized { + background-color: #ffc900; + color: #fff; } + +.tabs .tab-item .badge.badge-royal, +.badge.badge-royal { + background-color: #886aea; + color: #fff; } + +.tabs .tab-item .badge.badge-dark, +.badge.badge-dark { + background-color: #444; + color: #fff; } + +.button .badge { + position: relative; + top: -1px; } + +/** + * Slide Box + * -------------------------------------------------- + */ +.slider { + position: relative; + visibility: hidden; + overflow: hidden; } + +.slider-slides { + position: relative; + height: 100%; } + +.slider-slide { + position: relative; + display: block; + float: left; + width: 100%; + height: 100%; + vertical-align: top; } + +.slider-slide-image > img { + width: 100%; } + +.slider-pager { + position: absolute; + bottom: 20px; + z-index: 1; + width: 100%; + height: 15px; + text-align: center; } + .slider-pager .slider-pager-page { + display: inline-block; + margin: 0px 3px; + width: 15px; + color: #000; + text-decoration: none; + opacity: 0.3; } + .slider-pager .slider-pager-page.active { + -webkit-transition: opacity 0.4s ease-in; + transition: opacity 0.4s ease-in; + opacity: 1; } + +.slider-slide.ng-enter, .slider-slide.ng-leave, .slider-slide.ng-animate, +.slider-pager-page.ng-enter, +.slider-pager-page.ng-leave, +.slider-pager-page.ng-animate { + -webkit-transition: none !important; + transition: none !important; } + +.slider-slide.ng-animate, +.slider-pager-page.ng-animate { + -webkit-animation: none 0s; + animation: none 0s; } + +/** + * Swiper 3.2.7 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/swiper/ + * + * Copyright 2015, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: December 7, 2015 + */ +.swiper-container { + margin: 0 auto; + position: relative; + overflow: hidden; + /* Fix of Webkit flickering */ + z-index: 1; } + +.swiper-container-no-flexbox .swiper-slide { + float: left; } + +.swiper-container-vertical > .swiper-wrapper { + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; } + +.swiper-wrapper { + position: relative; + width: 100%; + height: 100%; + z-index: 1; + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -webkit-transition-property: -webkit-transform; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; } + +.swiper-container-android .swiper-slide, +.swiper-wrapper { + -webkit-transform: translate3d(0px, 0, 0); + -moz-transform: translate3d(0px, 0, 0); + -o-transform: translate(0px, 0px); + -ms-transform: translate3d(0px, 0, 0); + transform: translate3d(0px, 0, 0); } + +.swiper-container-multirow > .swiper-wrapper { + -webkit-box-lines: multiple; + -moz-box-lines: multiple; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; } + +.swiper-container-free-mode > .swiper-wrapper { + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; + margin: 0 auto; } + +.swiper-slide { + display: block; + -webkit-flex-shrink: 0; + -ms-flex: 0 0 auto; + flex-shrink: 0; + width: 100%; + height: 100%; + position: relative; } + +/* Auto Height */ +.swiper-container-autoheight, +.swiper-container-autoheight .swiper-slide { + height: auto; } + +.swiper-container-autoheight .swiper-wrapper { + -webkit-box-align: start; + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + -webkit-transition-property: -webkit-transform, height; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform, height; } + +/* a11y */ +.swiper-container .swiper-notification { + position: absolute; + left: 0; + top: 0; + pointer-events: none; + opacity: 0; + z-index: -1000; } + +/* IE10 Windows Phone 8 Fixes */ +.swiper-wp8-horizontal { + -ms-touch-action: pan-y; + touch-action: pan-y; } + +.swiper-wp8-vertical { + -ms-touch-action: pan-x; + touch-action: pan-x; } + +/* Arrows */ +.swiper-button-prev, +.swiper-button-next { + position: absolute; + top: 50%; + width: 27px; + height: 44px; + margin-top: -22px; + z-index: 10; + cursor: pointer; + -moz-background-size: 27px 44px; + -webkit-background-size: 27px 44px; + background-size: 27px 44px; + background-position: center; + background-repeat: no-repeat; } + +.swiper-button-prev.swiper-button-disabled, +.swiper-button-next.swiper-button-disabled { + opacity: 0.35; + cursor: auto; + pointer-events: none; } + +.swiper-button-prev, +.swiper-container-rtl .swiper-button-next { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); + left: 10px; + right: auto; } + +.swiper-button-prev.swiper-button-black, +.swiper-container-rtl .swiper-button-next.swiper-button-black { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E"); } + +.swiper-button-prev.swiper-button-white, +.swiper-container-rtl .swiper-button-next.swiper-button-white { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E"); } + +.swiper-button-next, +.swiper-container-rtl .swiper-button-prev { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); + right: 10px; + left: auto; } + +.swiper-button-next.swiper-button-black, +.swiper-container-rtl .swiper-button-prev.swiper-button-black { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E"); } + +.swiper-button-next.swiper-button-white, +.swiper-container-rtl .swiper-button-prev.swiper-button-white { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E"); } + +/* Pagination Styles */ +.swiper-pagination { + position: absolute; + text-align: center; + -webkit-transition: 300ms; + -moz-transition: 300ms; + -o-transition: 300ms; + transition: 300ms; + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + z-index: 10; } + +.swiper-pagination.swiper-pagination-hidden { + opacity: 0; } + +.swiper-pagination-bullet { + width: 8px; + height: 8px; + display: inline-block; + border-radius: 100%; + background: #000; + opacity: 0.2; } + +button.swiper-pagination-bullet { + border: none; + margin: 0; + padding: 0; + box-shadow: none; + -moz-appearance: none; + -ms-appearance: none; + -webkit-appearance: none; + appearance: none; } + +.swiper-pagination-clickable .swiper-pagination-bullet { + cursor: pointer; } + +.swiper-pagination-white .swiper-pagination-bullet { + background: #fff; } + +.swiper-pagination-bullet-active { + opacity: 1; } + +.swiper-pagination-white .swiper-pagination-bullet-active { + background: #fff; } + +.swiper-pagination-black .swiper-pagination-bullet-active { + background: #000; } + +.swiper-container-vertical > .swiper-pagination { + right: 10px; + top: 50%; + -webkit-transform: translate3d(0px, -50%, 0); + -moz-transform: translate3d(0px, -50%, 0); + -o-transform: translate(0px, -50%); + -ms-transform: translate3d(0px, -50%, 0); + transform: translate3d(0px, -50%, 0); } + +.swiper-container-vertical > .swiper-pagination .swiper-pagination-bullet { + margin: 5px 0; + display: block; } + +.swiper-container-horizontal > .swiper-pagination { + bottom: 10px; + left: 0; + width: 100%; } + +.swiper-container-horizontal > .swiper-pagination .swiper-pagination-bullet { + margin: 0 5px; } + +/* 3D Container */ +.swiper-container-3d { + -webkit-perspective: 1200px; + -moz-perspective: 1200px; + -o-perspective: 1200px; + perspective: 1200px; } + +.swiper-container-3d .swiper-wrapper, +.swiper-container-3d .swiper-slide, +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top, +.swiper-container-3d .swiper-slide-shadow-bottom, +.swiper-container-3d .swiper-cube-shadow { + -webkit-transform-style: preserve-3d; + -moz-transform-style: preserve-3d; + -ms-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top, +.swiper-container-3d .swiper-slide-shadow-bottom { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 10; } + +.swiper-container-3d .swiper-slide-shadow-left { + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +.swiper-container-3d .swiper-slide-shadow-right { + background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +.swiper-container-3d .swiper-slide-shadow-top { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +.swiper-container-3d .swiper-slide-shadow-bottom { + background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +/* Coverflow */ +.swiper-container-coverflow .swiper-wrapper { + /* Windows 8 IE 10 fix */ + -ms-perspective: 1200px; } + +/* Fade */ +.swiper-container-fade.swiper-container-free-mode .swiper-slide { + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; } + +.swiper-container-fade .swiper-slide { + pointer-events: none; } + +.swiper-container-fade .swiper-slide .swiper-slide { + pointer-events: none; } + +.swiper-container-fade .swiper-slide-active, +.swiper-container-fade .swiper-slide-active .swiper-slide-active { + pointer-events: auto; } + +/* Cube */ +.swiper-container-cube { + overflow: visible; } + +.swiper-container-cube .swiper-slide { + pointer-events: none; + visibility: hidden; + -webkit-transform-origin: 0 0; + -moz-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; + width: 100%; + height: 100%; + z-index: 1; } + +.swiper-container-cube.swiper-container-rtl .swiper-slide { + -webkit-transform-origin: 100% 0; + -moz-transform-origin: 100% 0; + -ms-transform-origin: 100% 0; + transform-origin: 100% 0; } + +.swiper-container-cube .swiper-slide-active, +.swiper-container-cube .swiper-slide-next, +.swiper-container-cube .swiper-slide-prev, +.swiper-container-cube .swiper-slide-next + .swiper-slide { + pointer-events: auto; + visibility: visible; } + +.swiper-container-cube .swiper-slide-shadow-top, +.swiper-container-cube .swiper-slide-shadow-bottom, +.swiper-container-cube .swiper-slide-shadow-left, +.swiper-container-cube .swiper-slide-shadow-right { + z-index: 0; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; } + +.swiper-container-cube .swiper-cube-shadow { + position: absolute; + left: 0; + bottom: 0px; + width: 100%; + height: 100%; + background: #000; + opacity: 0.6; + -webkit-filter: blur(50px); + filter: blur(50px); + z-index: 0; } + +/* Scrollbar */ +.swiper-scrollbar { + border-radius: 10px; + position: relative; + -ms-touch-action: none; + background: rgba(0, 0, 0, 0.1); } + +.swiper-container-horizontal > .swiper-scrollbar { + position: absolute; + left: 1%; + bottom: 3px; + z-index: 50; + height: 5px; + width: 98%; } + +.swiper-container-vertical > .swiper-scrollbar { + position: absolute; + right: 3px; + top: 1%; + z-index: 50; + width: 5px; + height: 98%; } + +.swiper-scrollbar-drag { + height: 100%; + width: 100%; + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 10px; + left: 0; + top: 0; } + +.swiper-scrollbar-cursor-drag { + cursor: move; } + +/* Preloader */ +.swiper-lazy-preloader { + width: 42px; + height: 42px; + position: absolute; + left: 50%; + top: 50%; + margin-left: -21px; + margin-top: -21px; + z-index: 10; + -webkit-transform-origin: 50%; + -moz-transform-origin: 50%; + transform-origin: 50%; + -webkit-animation: swiper-preloader-spin 1s steps(12, end) infinite; + -moz-animation: swiper-preloader-spin 1s steps(12, end) infinite; + animation: swiper-preloader-spin 1s steps(12, end) infinite; } + +.swiper-lazy-preloader:after { + display: block; + content: ""; + width: 100%; + height: 100%; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + background-position: 50%; + -webkit-background-size: 100%; + background-size: 100%; + background-repeat: no-repeat; } + +.swiper-lazy-preloader-white:after { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); } + +@-webkit-keyframes swiper-preloader-spin { + 100% { + -webkit-transform: rotate(360deg); } } + +@keyframes swiper-preloader-spin { + 100% { + transform: rotate(360deg); } } + +ion-slides { + width: 100%; + height: 100%; + display: block; } + +.slide-zoom { + display: block; + width: 100%; + text-align: center; } + +.swiper-container { + width: 100%; + height: 100%; + padding: 0; + overflow: hidden; } + +.swiper-wrapper { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + padding: 0; } + +.swiper-slide { + width: 100%; + height: 100%; + box-sizing: border-box; + /* Center slide text vertically */ } + .swiper-slide img { + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; } + +.scroll-refresher { + position: absolute; + top: -60px; + right: 0; + left: 0; + overflow: hidden; + margin: auto; + height: 60px; } + .scroll-refresher .ionic-refresher-content { + position: absolute; + bottom: 15px; + left: 0; + width: 100%; + color: #666666; + text-align: center; + font-size: 30px; } + .scroll-refresher .ionic-refresher-content .text-refreshing, + .scroll-refresher .ionic-refresher-content .text-pulling { + font-size: 16px; + line-height: 16px; } + .scroll-refresher .ionic-refresher-content.ionic-refresher-with-text { + bottom: 10px; } + .scroll-refresher .icon-refreshing, + .scroll-refresher .icon-pulling { + width: 100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + .scroll-refresher .icon-pulling { + -webkit-animation-name: refresh-spin-back; + animation-name: refresh-spin-back; + -webkit-animation-duration: 200ms; + animation-duration: 200ms; + -webkit-animation-timing-function: linear; + animation-timing-function: linear; + -webkit-animation-fill-mode: none; + animation-fill-mode: none; + -webkit-transform: translate3d(0, 0, 0) rotate(0deg); + transform: translate3d(0, 0, 0) rotate(0deg); } + .scroll-refresher .icon-refreshing, + .scroll-refresher .text-refreshing { + display: none; } + .scroll-refresher .icon-refreshing { + -webkit-animation-duration: 1.5s; + animation-duration: 1.5s; } + .scroll-refresher.active .icon-pulling:not(.pulling-rotation-disabled) { + -webkit-animation-name: refresh-spin; + animation-name: refresh-spin; + -webkit-transform: translate3d(0, 0, 0) rotate(-180deg); + transform: translate3d(0, 0, 0) rotate(-180deg); } + .scroll-refresher.active.refreshing { + -webkit-transition: -webkit-transform 0.2s; + transition: -webkit-transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + -webkit-transform: scale(1, 1); + transform: scale(1, 1); } + .scroll-refresher.active.refreshing .icon-pulling, + .scroll-refresher.active.refreshing .text-pulling { + display: none; } + .scroll-refresher.active.refreshing .icon-refreshing, + .scroll-refresher.active.refreshing .text-refreshing { + display: block; } + .scroll-refresher.active.refreshing.refreshing-tail { + -webkit-transform: scale(0, 0); + transform: scale(0, 0); } + +.overflow-scroll > .scroll { + -webkit-overflow-scrolling: touch; + width: 100%; } + .overflow-scroll > .scroll.overscroll { + position: fixed; + right: 0; + left: 0; } + +.overflow-scroll.padding > .scroll.overscroll { + padding: 10px; } + +@-webkit-keyframes refresh-spin { + 0% { + -webkit-transform: translate3d(0, 0, 0) rotate(0); } + 100% { + -webkit-transform: translate3d(0, 0, 0) rotate(180deg); } } + +@keyframes refresh-spin { + 0% { + transform: translate3d(0, 0, 0) rotate(0); } + 100% { + transform: translate3d(0, 0, 0) rotate(180deg); } } + +@-webkit-keyframes refresh-spin-back { + 0% { + -webkit-transform: translate3d(0, 0, 0) rotate(180deg); } + 100% { + -webkit-transform: translate3d(0, 0, 0) rotate(0); } } + +@keyframes refresh-spin-back { + 0% { + transform: translate3d(0, 0, 0) rotate(180deg); } + 100% { + transform: translate3d(0, 0, 0) rotate(0); } } + +/** + * Spinners + * -------------------------------------------------- + */ +.spinner { + stroke: #444; + fill: #444; } + .spinner svg { + width: 28px; + height: 28px; } + .spinner.spinner-light { + stroke: #fff; + fill: #fff; } + .spinner.spinner-stable { + stroke: #f8f8f8; + fill: #f8f8f8; } + .spinner.spinner-positive { + stroke: #387ef5; + fill: #387ef5; } + .spinner.spinner-calm { + stroke: #11c1f3; + fill: #11c1f3; } + .spinner.spinner-balanced { + stroke: #33cd5f; + fill: #33cd5f; } + .spinner.spinner-assertive { + stroke: #ef473a; + fill: #ef473a; } + .spinner.spinner-energized { + stroke: #ffc900; + fill: #ffc900; } + .spinner.spinner-royal { + stroke: #886aea; + fill: #886aea; } + .spinner.spinner-dark { + stroke: #444; + fill: #444; } + +.spinner-android { + stroke: #4b8bf4; } + +.spinner-ios, +.spinner-ios-small { + stroke: #69717d; } + +.spinner-spiral .stop1 { + stop-color: #fff; + stop-opacity: 0; } + +.spinner-spiral.spinner-light .stop1 { + stop-color: #444; } + +.spinner-spiral.spinner-light .stop2 { + stop-color: #fff; } + +.spinner-spiral.spinner-stable .stop2 { + stop-color: #f8f8f8; } + +.spinner-spiral.spinner-positive .stop2 { + stop-color: #387ef5; } + +.spinner-spiral.spinner-calm .stop2 { + stop-color: #11c1f3; } + +.spinner-spiral.spinner-balanced .stop2 { + stop-color: #33cd5f; } + +.spinner-spiral.spinner-assertive .stop2 { + stop-color: #ef473a; } + +.spinner-spiral.spinner-energized .stop2 { + stop-color: #ffc900; } + +.spinner-spiral.spinner-royal .stop2 { + stop-color: #886aea; } + +.spinner-spiral.spinner-dark .stop2 { + stop-color: #444; } + +/** + * Forms + * -------------------------------------------------- + */ +form { + margin: 0 0 1.42857; } + +legend { + display: block; + margin-bottom: 1.42857; + padding: 0; + width: 100%; + border: 1px solid #ddd; + color: #444; + font-size: 21px; + line-height: 2.85714; } + legend small { + color: #f8f8f8; + font-size: 1.07143; } + +label, +input, +button, +select, +textarea { + font-weight: normal; + font-size: 14px; + line-height: 1.42857; } + +input, +button, +select, +textarea { + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; } + +.item-input { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + position: relative; + overflow: hidden; + padding: 6px 0 5px 16px; } + .item-input input { + -webkit-border-radius: 0; + border-radius: 0; + -webkit-box-flex: 1; + -webkit-flex: 1 220px; + -moz-box-flex: 1; + -moz-flex: 1 220px; + -ms-flex: 1 220px; + flex: 1 220px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + margin: 0; + padding-right: 24px; + background-color: transparent; } + .item-input .button .icon { + -webkit-box-flex: 0; + -webkit-flex: 0 0 24px; + -moz-box-flex: 0; + -moz-flex: 0 0 24px; + -ms-flex: 0 0 24px; + flex: 0 0 24px; + position: static; + display: inline-block; + height: auto; + text-align: center; + font-size: 16px; } + .item-input .button-bar { + -webkit-border-radius: 0; + border-radius: 0; + -webkit-box-flex: 1; + -webkit-flex: 1 0 220px; + -moz-box-flex: 1; + -moz-flex: 1 0 220px; + -ms-flex: 1 0 220px; + flex: 1 0 220px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } + .item-input .icon { + min-width: 14px; } + +.platform-windowsphone .item-input input { + flex-shrink: 1; } + +.item-input-inset { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + position: relative; + overflow: hidden; + padding: 10.66667px; } + +.item-input-wrapper { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -webkit-flex: 1 0; + -moz-box-flex: 1; + -moz-flex: 1 0; + -ms-flex: 1 0; + flex: 1 0; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + -webkit-border-radius: 4px; + border-radius: 4px; + padding-right: 8px; + padding-left: 8px; + background: #eee; } + +.item-input-inset .item-input-wrapper input { + padding-left: 4px; + height: 29px; + background: transparent; + line-height: 18px; } + +.item-input-wrapper ~ .button { + margin-left: 10.66667px; } + +.input-label { + display: table; + padding: 7px 10px 7px 0px; + max-width: 200px; + width: 35%; + color: #444; + font-size: 16px; } + +.placeholder-icon { + color: #aaa; } + .placeholder-icon:first-child { + padding-right: 6px; } + .placeholder-icon:last-child { + padding-left: 6px; } + +.item-stacked-label { + display: block; + background-color: transparent; + box-shadow: none; } + .item-stacked-label .input-label, .item-stacked-label .icon { + display: inline-block; + padding: 4px 0 0 0px; + vertical-align: middle; } + +.item-stacked-label input, +.item-stacked-label textarea { + -webkit-border-radius: 2px; + border-radius: 2px; + padding: 4px 8px 3px 0; + border: none; + background-color: #fff; } + +.item-stacked-label input { + overflow: hidden; + height: 46px; } + +.item-select.item-stacked-label select { + position: relative; + padding: 0px; + max-width: 90%; + direction: ltr; + white-space: pre-wrap; + margin: -3px; } + +.item-floating-label { + display: block; + background-color: transparent; + box-shadow: none; } + .item-floating-label .input-label { + position: relative; + padding: 5px 0 0 0; + opacity: 0; + top: 10px; + -webkit-transition: opacity 0.15s ease-in, top 0.2s linear; + transition: opacity 0.15s ease-in, top 0.2s linear; } + .item-floating-label .input-label.has-input { + opacity: 1; + top: 0; + -webkit-transition: opacity 0.15s ease-in, top 0.2s linear; + transition: opacity 0.15s ease-in, top 0.2s linear; } + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"] { + display: block; + padding-top: 2px; + padding-left: 0; + height: 34px; + color: #111; + vertical-align: middle; + font-size: 14px; + line-height: 16px; } + +.platform-ios input[type="datetime-local"], +.platform-ios input[type="date"], +.platform-ios input[type="month"], +.platform-ios input[type="time"], +.platform-ios input[type="week"], +.platform-android input[type="datetime-local"], +.platform-android input[type="date"], +.platform-android input[type="month"], +.platform-android input[type="time"], +.platform-android input[type="week"] { + padding-top: 8px; } + +.item-input input, +.item-input textarea { + width: 100%; } + +textarea { + padding-left: 0; } + textarea::-moz-placeholder { + color: #aaaaaa; } + textarea:-ms-input-placeholder { + color: #aaaaaa; } + textarea::-webkit-input-placeholder { + color: #aaaaaa; + text-indent: -3px; } + +textarea { + height: auto; } + +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"] { + border: 0; } + +input[type="radio"], +input[type="checkbox"] { + margin: 0; + line-height: normal; } + +.item-input input[type="file"], +.item-input input[type="image"], +.item-input input[type="submit"], +.item-input input[type="reset"], +.item-input input[type="button"], +.item-input input[type="radio"], +.item-input input[type="checkbox"] { + width: auto; } + +input[type="file"] { + line-height: 34px; } + +.previous-input-focus, +.cloned-text-input + input, +.cloned-text-input + textarea { + position: absolute !important; + left: -9999px; + width: 200px; } + +input::-moz-placeholder, +textarea::-moz-placeholder { + color: #aaaaaa; } + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + color: #aaaaaa; } + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { + color: #aaaaaa; + text-indent: 0; } + +input[disabled], +select[disabled], +textarea[disabled], +input[readonly]:not(.cloned-text-input), +textarea[readonly]:not(.cloned-text-input), +select[readonly] { + background-color: #f8f8f8; + cursor: not-allowed; } + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { + background-color: transparent; } + +/** + * Checkbox + * -------------------------------------------------- + */ +.checkbox { + position: relative; + display: inline-block; + padding: 7px 7px; + cursor: pointer; } + .checkbox input:before, + .checkbox .checkbox-icon:before { + border-color: #ddd; } + .checkbox input:checked:before, + .checkbox input:checked + .checkbox-icon:before { + background: #387ef5; + border-color: #387ef5; } + +.checkbox-light input:before, +.checkbox-light .checkbox-icon:before { + border-color: #ddd; } + +.checkbox-light input:checked:before, +.checkbox-light input:checked + .checkbox-icon:before { + background: #ddd; + border-color: #ddd; } + +.checkbox-stable input:before, +.checkbox-stable .checkbox-icon:before { + border-color: #b2b2b2; } + +.checkbox-stable input:checked:before, +.checkbox-stable input:checked + .checkbox-icon:before { + background: #b2b2b2; + border-color: #b2b2b2; } + +.checkbox-positive input:before, +.checkbox-positive .checkbox-icon:before { + border-color: #387ef5; } + +.checkbox-positive input:checked:before, +.checkbox-positive input:checked + .checkbox-icon:before { + background: #387ef5; + border-color: #387ef5; } + +.checkbox-calm input:before, +.checkbox-calm .checkbox-icon:before { + border-color: #11c1f3; } + +.checkbox-calm input:checked:before, +.checkbox-calm input:checked + .checkbox-icon:before { + background: #11c1f3; + border-color: #11c1f3; } + +.checkbox-assertive input:before, +.checkbox-assertive .checkbox-icon:before { + border-color: #ef473a; } + +.checkbox-assertive input:checked:before, +.checkbox-assertive input:checked + .checkbox-icon:before { + background: #ef473a; + border-color: #ef473a; } + +.checkbox-balanced input:before, +.checkbox-balanced .checkbox-icon:before { + border-color: #33cd5f; } + +.checkbox-balanced input:checked:before, +.checkbox-balanced input:checked + .checkbox-icon:before { + background: #33cd5f; + border-color: #33cd5f; } + +.checkbox-energized input:before, +.checkbox-energized .checkbox-icon:before { + border-color: #ffc900; } + +.checkbox-energized input:checked:before, +.checkbox-energized input:checked + .checkbox-icon:before { + background: #ffc900; + border-color: #ffc900; } + +.checkbox-royal input:before, +.checkbox-royal .checkbox-icon:before { + border-color: #886aea; } + +.checkbox-royal input:checked:before, +.checkbox-royal input:checked + .checkbox-icon:before { + background: #886aea; + border-color: #886aea; } + +.checkbox-dark input:before, +.checkbox-dark .checkbox-icon:before { + border-color: #444; } + +.checkbox-dark input:checked:before, +.checkbox-dark input:checked + .checkbox-icon:before { + background: #444; + border-color: #444; } + +.checkbox input:disabled:before, +.checkbox input:disabled + .checkbox-icon:before { + border-color: #ddd; } + +.checkbox input:disabled:checked:before, +.checkbox input:disabled:checked + .checkbox-icon:before { + background: #ddd; } + +.checkbox.checkbox-input-hidden input { + display: none !important; } + +.checkbox input, +.checkbox-icon { + position: relative; + width: 28px; + height: 28px; + display: block; + border: 0; + background: transparent; + cursor: pointer; + -webkit-appearance: none; } + .checkbox input:before, + .checkbox-icon:before { + display: table; + width: 100%; + height: 100%; + border-width: 1px; + border-style: solid; + border-radius: 28px; + background: #fff; + content: ' '; + -webkit-transition: background-color 20ms ease-in-out; + transition: background-color 20ms ease-in-out; } + +.checkbox input:checked:before, +input:checked + .checkbox-icon:before { + border-width: 2px; } + +.checkbox input:after, +.checkbox-icon:after { + -webkit-transition: opacity 0.05s ease-in-out; + transition: opacity 0.05s ease-in-out; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + position: absolute; + top: 33%; + left: 25%; + display: table; + width: 14px; + height: 6px; + border: 1px solid #fff; + border-top: 0; + border-right: 0; + content: ' '; + opacity: 0; } + +.platform-android .checkbox-platform input:before, +.platform-android .checkbox-platform .checkbox-icon:before, +.checkbox-square input:before, +.checkbox-square .checkbox-icon:before { + border-radius: 2px; + width: 72%; + height: 72%; + margin-top: 14%; + margin-left: 14%; + border-width: 2px; } + +.platform-android .checkbox-platform input:after, +.platform-android .checkbox-platform .checkbox-icon:after, +.checkbox-square input:after, +.checkbox-square .checkbox-icon:after { + border-width: 2px; + top: 19%; + left: 25%; + width: 13px; + height: 7px; } + +.platform-android .item-checkbox-right .checkbox-square .checkbox-icon::after { + top: 31%; } + +.grade-c .checkbox input:after, +.grade-c .checkbox-icon:after { + -webkit-transform: rotate(0); + transform: rotate(0); + top: 3px; + left: 4px; + border: none; + color: #fff; + content: '\2713'; + font-weight: bold; + font-size: 20px; } + +.checkbox input:checked:after, +input:checked + .checkbox-icon:after { + opacity: 1; } + +.item-checkbox { + padding-left: 60px; } + .item-checkbox.active { + box-shadow: none; } + +.item-checkbox .checkbox { + position: absolute; + top: 50%; + right: 8px; + left: 8px; + z-index: 3; + margin-top: -21px; } + +.item-checkbox.item-checkbox-right { + padding-right: 60px; + padding-left: 16px; } + +.item-checkbox-right .checkbox input, +.item-checkbox-right .checkbox-icon { + float: right; } + +/** + * Toggle + * -------------------------------------------------- + */ +.item-toggle { + pointer-events: none; } + +.toggle { + position: relative; + display: inline-block; + pointer-events: auto; + margin: -5px; + padding: 5px; } + .toggle input:checked + .track { + border-color: #4cd964; + background-color: #4cd964; } + .toggle.dragging .handle { + background-color: #f2f2f2 !important; } + +.toggle.toggle-light input:checked + .track { + border-color: #ddd; + background-color: #ddd; } + +.toggle.toggle-stable input:checked + .track { + border-color: #b2b2b2; + background-color: #b2b2b2; } + +.toggle.toggle-positive input:checked + .track { + border-color: #387ef5; + background-color: #387ef5; } + +.toggle.toggle-calm input:checked + .track { + border-color: #11c1f3; + background-color: #11c1f3; } + +.toggle.toggle-assertive input:checked + .track { + border-color: #ef473a; + background-color: #ef473a; } + +.toggle.toggle-balanced input:checked + .track { + border-color: #33cd5f; + background-color: #33cd5f; } + +.toggle.toggle-energized input:checked + .track { + border-color: #ffc900; + background-color: #ffc900; } + +.toggle.toggle-royal input:checked + .track { + border-color: #886aea; + background-color: #886aea; } + +.toggle.toggle-dark input:checked + .track { + border-color: #444; + background-color: #444; } + +.toggle input { + display: none; } + +/* the track appearance when the toggle is "off" */ +.toggle .track { + -webkit-transition-timing-function: ease-in-out; + transition-timing-function: ease-in-out; + -webkit-transition-duration: 0.3s; + transition-duration: 0.3s; + -webkit-transition-property: background-color, border; + transition-property: background-color, border; + display: inline-block; + box-sizing: border-box; + width: 51px; + height: 31px; + border: solid 2px #e6e6e6; + border-radius: 20px; + background-color: #fff; + content: ' '; + cursor: pointer; + pointer-events: none; } + +/* Fix to avoid background color bleeding */ +/* (occured on (at least) Android 4.2, Asus MeMO Pad HD7 ME173X) */ +.platform-android4_2 .toggle .track { + -webkit-background-clip: padding-box; } + +/* the handle (circle) thats inside the toggle's track area */ +/* also the handle's appearance when it is "off" */ +.toggle .handle { + -webkit-transition: 0.3s cubic-bezier(0, 1.1, 1, 1.1); + transition: 0.3s cubic-bezier(0, 1.1, 1, 1.1); + -webkit-transition-property: background-color, transform; + transition-property: background-color, transform; + position: absolute; + display: block; + width: 27px; + height: 27px; + border-radius: 27px; + background-color: #fff; + top: 7px; + left: 7px; + box-shadow: 0 2px 7px rgba(0, 0, 0, 0.35), 0 1px 1px rgba(0, 0, 0, 0.15); } + .toggle .handle:before { + position: absolute; + top: -4px; + left: -21.5px; + padding: 18.5px 34px; + content: " "; } + +.toggle input:checked + .track .handle { + -webkit-transform: translate3d(20px, 0, 0); + transform: translate3d(20px, 0, 0); + background-color: #fff; } + +.item-toggle.active { + box-shadow: none; } + +.item-toggle, +.item-toggle.item-complex .item-content { + padding-right: 99px; } + +.item-toggle.item-complex { + padding-right: 0; } + +.item-toggle .toggle { + position: absolute; + top: 10px; + right: 16px; + z-index: 3; } + +.toggle input:disabled + .track { + opacity: .6; } + +.toggle-small .track { + border: 0; + width: 34px; + height: 15px; + background: #9e9e9e; } + +.toggle-small input:checked + .track { + background: rgba(0, 150, 137, 0.5); } + +.toggle-small .handle { + top: 2px; + left: 4px; + width: 21px; + height: 21px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25); } + +.toggle-small input:checked + .track .handle { + -webkit-transform: translate3d(16px, 0, 0); + transform: translate3d(16px, 0, 0); + background: #009689; } + +.toggle-small.item-toggle .toggle { + top: 19px; } + +.toggle-small .toggle-light input:checked + .track { + background-color: rgba(221, 221, 221, 0.5); } + +.toggle-small .toggle-light input:checked + .track .handle { + background-color: #ddd; } + +.toggle-small .toggle-stable input:checked + .track { + background-color: rgba(178, 178, 178, 0.5); } + +.toggle-small .toggle-stable input:checked + .track .handle { + background-color: #b2b2b2; } + +.toggle-small .toggle-positive input:checked + .track { + background-color: rgba(56, 126, 245, 0.5); } + +.toggle-small .toggle-positive input:checked + .track .handle { + background-color: #387ef5; } + +.toggle-small .toggle-calm input:checked + .track { + background-color: rgba(17, 193, 243, 0.5); } + +.toggle-small .toggle-calm input:checked + .track .handle { + background-color: #11c1f3; } + +.toggle-small .toggle-assertive input:checked + .track { + background-color: rgba(239, 71, 58, 0.5); } + +.toggle-small .toggle-assertive input:checked + .track .handle { + background-color: #ef473a; } + +.toggle-small .toggle-balanced input:checked + .track { + background-color: rgba(51, 205, 95, 0.5); } + +.toggle-small .toggle-balanced input:checked + .track .handle { + background-color: #33cd5f; } + +.toggle-small .toggle-energized input:checked + .track { + background-color: rgba(255, 201, 0, 0.5); } + +.toggle-small .toggle-energized input:checked + .track .handle { + background-color: #ffc900; } + +.toggle-small .toggle-royal input:checked + .track { + background-color: rgba(136, 106, 234, 0.5); } + +.toggle-small .toggle-royal input:checked + .track .handle { + background-color: #886aea; } + +.toggle-small .toggle-dark input:checked + .track { + background-color: rgba(68, 68, 68, 0.5); } + +.toggle-small .toggle-dark input:checked + .track .handle { + background-color: #444; } + +/** + * Radio Button Inputs + * -------------------------------------------------- + */ +.item-radio { + padding: 0; } + .item-radio:hover { + cursor: pointer; } + +.item-radio .item-content { + /* give some room to the right for the checkmark icon */ + padding-right: 64px; } + +.item-radio .radio-icon { + /* checkmark icon will be hidden by default */ + position: absolute; + top: 0; + right: 0; + z-index: 3; + visibility: hidden; + padding: 14px; + height: 100%; + font-size: 24px; } + +.item-radio input { + /* hide any radio button inputs elements (the ugly circles) */ + position: absolute; + left: -9999px; } + .item-radio input:checked + .radio-content .item-content { + /* style the item content when its checked */ + background: #f7f7f7; } + .item-radio input:checked + .radio-content .radio-icon { + /* show the checkmark icon when its checked */ + visibility: visible; } + +/** + * Range + * -------------------------------------------------- + */ +.range input { + display: inline-block; + overflow: hidden; + margin-top: 5px; + margin-bottom: 5px; + padding-right: 2px; + padding-left: 1px; + width: auto; + height: 43px; + outline: none; + background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ccc), color-stop(100%, #ccc)); + background: linear-gradient(to right, #ccc 0%, #ccc 100%); + background-position: center; + background-size: 99% 2px; + background-repeat: no-repeat; + -webkit-appearance: none; + /* + &::-ms-track{ + background: transparent; + border-color: transparent; + border-width: 11px 0 16px; + color:transparent; + margin-top:20px; + } + &::-ms-thumb { + width: $range-slider-width; + height: $range-slider-height; + border-radius: $range-slider-border-radius; + background-color: $toggle-handle-off-bg-color; + border-color:$toggle-handle-off-bg-color; + box-shadow: $range-slider-box-shadow; + margin-left:1px; + margin-right:1px; + outline:none; + } + &::-ms-fill-upper { + height: $range-track-height; + background:$range-default-track-bg; + } + */ } + .range input::-moz-focus-outer { + /* hide the focus outline in Firefox */ + border: 0; } + .range input::-webkit-slider-thumb { + position: relative; + width: 28px; + height: 28px; + border-radius: 50%; + background-color: #fff; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2); + cursor: pointer; + -webkit-appearance: none; + border: 0; } + .range input::-webkit-slider-thumb:before { + /* what creates the colorful line on the left side of the slider */ + position: absolute; + top: 13px; + left: -2001px; + width: 2000px; + height: 2px; + background: #444; + content: ' '; } + .range input::-webkit-slider-thumb:after { + /* create a larger (but hidden) hit area */ + position: absolute; + top: -15px; + left: -15px; + padding: 30px; + content: ' '; } + .range input::-ms-fill-lower { + height: 2px; + background: #444; } + +.range { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; + padding: 2px 11px; } + .range.range-light input::-webkit-slider-thumb:before { + background: #ddd; } + .range.range-light input::-ms-fill-lower { + background: #ddd; } + .range.range-stable input::-webkit-slider-thumb:before { + background: #b2b2b2; } + .range.range-stable input::-ms-fill-lower { + background: #b2b2b2; } + .range.range-positive input::-webkit-slider-thumb:before { + background: #387ef5; } + .range.range-positive input::-ms-fill-lower { + background: #387ef5; } + .range.range-calm input::-webkit-slider-thumb:before { + background: #11c1f3; } + .range.range-calm input::-ms-fill-lower { + background: #11c1f3; } + .range.range-balanced input::-webkit-slider-thumb:before { + background: #33cd5f; } + .range.range-balanced input::-ms-fill-lower { + background: #33cd5f; } + .range.range-assertive input::-webkit-slider-thumb:before { + background: #ef473a; } + .range.range-assertive input::-ms-fill-lower { + background: #ef473a; } + .range.range-energized input::-webkit-slider-thumb:before { + background: #ffc900; } + .range.range-energized input::-ms-fill-lower { + background: #ffc900; } + .range.range-royal input::-webkit-slider-thumb:before { + background: #886aea; } + .range.range-royal input::-ms-fill-lower { + background: #886aea; } + .range.range-dark input::-webkit-slider-thumb:before { + background: #444; } + .range.range-dark input::-ms-fill-lower { + background: #444; } + +.range .icon { + -webkit-box-flex: 0; + -webkit-flex: 0; + -moz-box-flex: 0; + -moz-flex: 0; + -ms-flex: 0; + flex: 0; + display: block; + min-width: 24px; + text-align: center; + font-size: 24px; } + +.range input { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + display: block; + margin-right: 10px; + margin-left: 10px; } + +.range-label { + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -moz-box-flex: 0; + -moz-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + display: block; + white-space: nowrap; } + +.range-label:first-child { + padding-left: 5px; } + +.range input + .range-label { + padding-right: 5px; + padding-left: 0; } + +.platform-windowsphone .range input { + height: auto; } + +/** + * Select + * -------------------------------------------------- + */ +.item-select { + position: relative; } + .item-select select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: absolute; + top: 0; + bottom: 0; + right: 0; + padding: 0 48px 0 16px; + max-width: 65%; + border: none; + background: #fff; + color: #333; + text-indent: .01px; + text-overflow: ''; + white-space: nowrap; + font-size: 14px; + cursor: pointer; + direction: rtl; } + .item-select select::-ms-expand { + display: none; } + .item-select option { + direction: ltr; } + .item-select:after { + position: absolute; + top: 50%; + right: 16px; + margin-top: -3px; + width: 0; + height: 0; + border-top: 5px solid; + border-right: 5px solid transparent; + border-left: 5px solid transparent; + color: #999; + content: ""; + pointer-events: none; } + .item-select.item-light select { + background: #fff; + color: #444; } + .item-select.item-stable select { + background: #f8f8f8; + color: #444; } + .item-select.item-stable:after, .item-select.item-stable .input-label { + color: #666666; } + .item-select.item-positive select { + background: #387ef5; + color: #fff; } + .item-select.item-positive:after, .item-select.item-positive .input-label { + color: #fff; } + .item-select.item-calm select { + background: #11c1f3; + color: #fff; } + .item-select.item-calm:after, .item-select.item-calm .input-label { + color: #fff; } + .item-select.item-assertive select { + background: #ef473a; + color: #fff; } + .item-select.item-assertive:after, .item-select.item-assertive .input-label { + color: #fff; } + .item-select.item-balanced select { + background: #33cd5f; + color: #fff; } + .item-select.item-balanced:after, .item-select.item-balanced .input-label { + color: #fff; } + .item-select.item-energized select { + background: #ffc900; + color: #fff; } + .item-select.item-energized:after, .item-select.item-energized .input-label { + color: #fff; } + .item-select.item-royal select { + background: #886aea; + color: #fff; } + .item-select.item-royal:after, .item-select.item-royal .input-label { + color: #fff; } + .item-select.item-dark select { + background: #444; + color: #fff; } + .item-select.item-dark:after, .item-select.item-dark .input-label { + color: #fff; } + +select[multiple], select[size] { + height: auto; } + +/** + * Progress + * -------------------------------------------------- + */ +progress { + display: block; + margin: 15px auto; + width: 100%; } + +/** + * Buttons + * -------------------------------------------------- + */ +.button { + border-color: transparent; + background-color: #f8f8f8; + color: #444; + position: relative; + display: inline-block; + margin: 0; + padding: 0 12px; + min-width: 52px; + min-height: 47px; + border-width: 1px; + border-style: solid; + border-radius: 4px; + vertical-align: top; + text-align: center; + text-overflow: ellipsis; + font-size: 16px; + line-height: 42px; + cursor: pointer; } + .button:hover { + color: #444; + text-decoration: none; } + .button.active, .button.activated { + background-color: #e5e5e5; } + .button:after { + position: absolute; + top: -6px; + right: -6px; + bottom: -6px; + left: -6px; + content: ' '; } + .button .icon { + vertical-align: top; + pointer-events: none; } + .button .icon:before, .button.icon:before, .button.icon-left:before, .button.icon-right:before { + display: inline-block; + padding: 0 0 1px 0; + vertical-align: inherit; + font-size: 24px; + line-height: 41px; + pointer-events: none; } + .button.icon-left:before { + float: left; + padding-right: .2em; + padding-left: 0; } + .button.icon-right:before { + float: right; + padding-right: 0; + padding-left: .2em; } + .button.button-block, .button.button-full { + margin-top: 10px; + margin-bottom: 10px; } + .button.button-light { + border-color: transparent; + background-color: #fff; + color: #444; } + .button.button-light:hover { + color: #444; + text-decoration: none; } + .button.button-light.active, .button.button-light.activated { + background-color: #fafafa; } + .button.button-light.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #ddd; } + .button.button-light.button-icon { + border-color: transparent; + background: none; } + .button.button-light.button-outline { + border-color: #ddd; + background: transparent; + color: #ddd; } + .button.button-light.button-outline.active, .button.button-light.button-outline.activated { + background-color: #ddd; + box-shadow: none; + color: #fff; } + .button.button-stable { + border-color: transparent; + background-color: #f8f8f8; + color: #444; } + .button.button-stable:hover { + color: #444; + text-decoration: none; } + .button.button-stable.active, .button.button-stable.activated { + background-color: #e5e5e5; } + .button.button-stable.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #b2b2b2; } + .button.button-stable.button-icon { + border-color: transparent; + background: none; } + .button.button-stable.button-outline { + border-color: #b2b2b2; + background: transparent; + color: #b2b2b2; } + .button.button-stable.button-outline.active, .button.button-stable.button-outline.activated { + background-color: #b2b2b2; + box-shadow: none; + color: #fff; } + .button.button-positive { + border-color: transparent; + background-color: #387ef5; + color: #fff; } + .button.button-positive:hover { + color: #fff; + text-decoration: none; } + .button.button-positive.active, .button.button-positive.activated { + background-color: #0c60ee; } + .button.button-positive.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #387ef5; } + .button.button-positive.button-icon { + border-color: transparent; + background: none; } + .button.button-positive.button-outline { + border-color: #387ef5; + background: transparent; + color: #387ef5; } + .button.button-positive.button-outline.active, .button.button-positive.button-outline.activated { + background-color: #387ef5; + box-shadow: none; + color: #fff; } + .button.button-calm { + border-color: transparent; + background-color: #11c1f3; + color: #fff; } + .button.button-calm:hover { + color: #fff; + text-decoration: none; } + .button.button-calm.active, .button.button-calm.activated { + background-color: #0a9dc7; } + .button.button-calm.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #11c1f3; } + .button.button-calm.button-icon { + border-color: transparent; + background: none; } + .button.button-calm.button-outline { + border-color: #11c1f3; + background: transparent; + color: #11c1f3; } + .button.button-calm.button-outline.active, .button.button-calm.button-outline.activated { + background-color: #11c1f3; + box-shadow: none; + color: #fff; } + .button.button-assertive { + border-color: transparent; + background-color: #ef473a; + color: #fff; } + .button.button-assertive:hover { + color: #fff; + text-decoration: none; } + .button.button-assertive.active, .button.button-assertive.activated { + background-color: #e42112; } + .button.button-assertive.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #ef473a; } + .button.button-assertive.button-icon { + border-color: transparent; + background: none; } + .button.button-assertive.button-outline { + border-color: #ef473a; + background: transparent; + color: #ef473a; } + .button.button-assertive.button-outline.active, .button.button-assertive.button-outline.activated { + background-color: #ef473a; + box-shadow: none; + color: #fff; } + .button.button-balanced { + border-color: transparent; + background-color: #33cd5f; + color: #fff; } + .button.button-balanced:hover { + color: #fff; + text-decoration: none; } + .button.button-balanced.active, .button.button-balanced.activated { + background-color: #28a54c; } + .button.button-balanced.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #33cd5f; } + .button.button-balanced.button-icon { + border-color: transparent; + background: none; } + .button.button-balanced.button-outline { + border-color: #33cd5f; + background: transparent; + color: #33cd5f; } + .button.button-balanced.button-outline.active, .button.button-balanced.button-outline.activated { + background-color: #33cd5f; + box-shadow: none; + color: #fff; } + .button.button-energized { + border-color: transparent; + background-color: #ffc900; + color: #fff; } + .button.button-energized:hover { + color: #fff; + text-decoration: none; } + .button.button-energized.active, .button.button-energized.activated { + background-color: #e6b500; } + .button.button-energized.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #ffc900; } + .button.button-energized.button-icon { + border-color: transparent; + background: none; } + .button.button-energized.button-outline { + border-color: #ffc900; + background: transparent; + color: #ffc900; } + .button.button-energized.button-outline.active, .button.button-energized.button-outline.activated { + background-color: #ffc900; + box-shadow: none; + color: #fff; } + .button.button-royal { + border-color: transparent; + background-color: #886aea; + color: #fff; } + .button.button-royal:hover { + color: #fff; + text-decoration: none; } + .button.button-royal.active, .button.button-royal.activated { + background-color: #6b46e5; } + .button.button-royal.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #886aea; } + .button.button-royal.button-icon { + border-color: transparent; + background: none; } + .button.button-royal.button-outline { + border-color: #886aea; + background: transparent; + color: #886aea; } + .button.button-royal.button-outline.active, .button.button-royal.button-outline.activated { + background-color: #886aea; + box-shadow: none; + color: #fff; } + .button.button-dark { + border-color: transparent; + background-color: #444; + color: #fff; } + .button.button-dark:hover { + color: #fff; + text-decoration: none; } + .button.button-dark.active, .button.button-dark.activated { + background-color: #262626; } + .button.button-dark.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #444; } + .button.button-dark.button-icon { + border-color: transparent; + background: none; } + .button.button-dark.button-outline { + border-color: #444; + background: transparent; + color: #444; } + .button.button-dark.button-outline.active, .button.button-dark.button-outline.activated { + background-color: #444; + box-shadow: none; + color: #fff; } + +.button-small { + padding: 2px 4px 1px; + min-width: 28px; + min-height: 30px; + font-size: 12px; + line-height: 26px; } + .button-small .icon:before, .button-small.icon:before, .button-small.icon-left:before, .button-small.icon-right:before { + font-size: 16px; + line-height: 19px; + margin-top: 3px; } + +.button-large { + padding: 0 16px; + min-width: 68px; + min-height: 59px; + font-size: 20px; + line-height: 53px; } + .button-large .icon:before, .button-large.icon:before, .button-large.icon-left:before, .button-large.icon-right:before { + padding-bottom: 2px; + font-size: 32px; + line-height: 51px; } + +.button-icon { + -webkit-transition: opacity 0.1s; + transition: opacity 0.1s; + padding: 0 6px; + min-width: initial; + border-color: transparent; + background: none; } + .button-icon.button.active, .button-icon.button.activated { + border-color: transparent; + background: none; + box-shadow: none; + opacity: 0.3; } + .button-icon .icon:before, .button-icon.icon:before { + font-size: 32px; } + +.button-clear { + -webkit-transition: opacity 0.1s; + transition: opacity 0.1s; + padding: 0 6px; + max-height: 42px; + border-color: transparent; + background: none; + box-shadow: none; } + .button-clear.button-clear { + border-color: transparent; + background: none; + box-shadow: none; + color: #b2b2b2; } + .button-clear.button-icon { + border-color: transparent; + background: none; } + .button-clear.active, .button-clear.activated { + opacity: 0.3; } + +.button-outline { + -webkit-transition: opacity 0.1s; + transition: opacity 0.1s; + background: none; + box-shadow: none; } + .button-outline.button-outline { + border-color: #b2b2b2; + background: transparent; + color: #b2b2b2; } + .button-outline.button-outline.active, .button-outline.button-outline.activated { + background-color: #b2b2b2; + box-shadow: none; + color: #fff; } + +.padding > .button.button-block:first-child { + margin-top: 0; } + +.button-block { + display: block; + clear: both; } + .button-block:after { + clear: both; } + +.button-full, +.button-full > .button { + display: block; + margin-right: 0; + margin-left: 0; + border-right-width: 0; + border-left-width: 0; + border-radius: 0; } + +button.button-block, +button.button-full, +.button-full > button.button, +input.button.button-block { + width: 100%; } + +a.button { + text-decoration: none; } + a.button .icon:before, a.button.icon:before, a.button.icon-left:before, a.button.icon-right:before { + margin-top: 2px; } + +.button.disabled, +.button[disabled] { + opacity: .4; + cursor: default !important; + pointer-events: none; } + +/** + * Button Bar + * -------------------------------------------------- + */ +.button-bar { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + width: 100%; } + .button-bar.button-bar-inline { + display: block; + width: auto; + *zoom: 1; } + .button-bar.button-bar-inline:before, .button-bar.button-bar-inline:after { + display: table; + content: ""; + line-height: 0; } + .button-bar.button-bar-inline:after { + clear: both; } + .button-bar.button-bar-inline > .button { + width: auto; + display: inline-block; + float: left; } + +.button-bar > .button { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + display: block; + overflow: hidden; + padding: 0 16px; + width: 0; + border-width: 1px 0px 1px 1px; + border-radius: 0; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; } + .button-bar > .button:before, + .button-bar > .button .icon:before { + line-height: 44px; } + .button-bar > .button:first-child { + border-radius: 4px 0px 0px 4px; } + .button-bar > .button:last-child { + border-right-width: 1px; + border-radius: 0px 4px 4px 0px; } + .button-bar > .button:only-child { + border-radius: 4px; } + +.button-bar > .button-small:before, +.button-bar > .button-small .icon:before { + line-height: 28px; } + +/** + * Grid + * -------------------------------------------------- + * Using flexbox for the grid, inspired by Philip Walton: + * http://philipwalton.github.io/solved-by-flexbox/demos/grids/ + * By default each .col within a .row will evenly take up + * available width, and the height of each .col with take + * up the height of the tallest .col in the same .row. + */ +.row { + display: -webkit-box; + display: -webkit-flex; + display: -moz-box; + display: -moz-flex; + display: -ms-flexbox; + display: flex; + padding: 5px; + width: 100%; } + +.row-wrap { + -webkit-flex-wrap: wrap; + -moz-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + +.row-no-padding { + padding: 0; } + .row-no-padding > .col { + padding: 0; } + +.row + .row { + margin-top: -5px; + padding-top: 0; } + +.col { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + display: block; + padding: 5px; + width: 100%; } + +/* Vertically Align Columns */ +/* .row-* vertically aligns every .col in the .row */ +.row-top { + -webkit-box-align: start; + -ms-flex-align: start; + -webkit-align-items: flex-start; + -moz-align-items: flex-start; + align-items: flex-start; } + +.row-bottom { + -webkit-box-align: end; + -ms-flex-align: end; + -webkit-align-items: flex-end; + -moz-align-items: flex-end; + align-items: flex-end; } + +.row-center { + -webkit-box-align: center; + -ms-flex-align: center; + -webkit-align-items: center; + -moz-align-items: center; + align-items: center; } + +.row-stretch { + -webkit-box-align: stretch; + -ms-flex-align: stretch; + -webkit-align-items: stretch; + -moz-align-items: stretch; + align-items: stretch; } + +.row-baseline { + -webkit-box-align: baseline; + -ms-flex-align: baseline; + -webkit-align-items: baseline; + -moz-align-items: baseline; + align-items: baseline; } + +/* .col-* vertically aligns an individual .col */ +.col-top { + -webkit-align-self: flex-start; + -moz-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; } + +.col-bottom { + -webkit-align-self: flex-end; + -moz-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; } + +.col-center { + -webkit-align-self: center; + -moz-align-self: center; + -ms-flex-item-align: center; + align-self: center; } + +/* Column Offsets */ +.col-offset-10 { + margin-left: 10%; } + +.col-offset-20 { + margin-left: 20%; } + +.col-offset-25 { + margin-left: 25%; } + +.col-offset-33, .col-offset-34 { + margin-left: 33.3333%; } + +.col-offset-50 { + margin-left: 50%; } + +.col-offset-66, .col-offset-67 { + margin-left: 66.6666%; } + +.col-offset-75 { + margin-left: 75%; } + +.col-offset-80 { + margin-left: 80%; } + +.col-offset-90 { + margin-left: 90%; } + +/* Explicit Column Percent Sizes */ +/* By default each grid column will evenly distribute */ +/* across the grid. However, you can specify individual */ +/* columns to take up a certain size of the available area */ +.col-10 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 10%; + -moz-box-flex: 0; + -moz-flex: 0 0 10%; + -ms-flex: 0 0 10%; + flex: 0 0 10%; + max-width: 10%; } + +.col-20 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 20%; + -moz-box-flex: 0; + -moz-flex: 0 0 20%; + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; } + +.col-25 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 25%; + -moz-box-flex: 0; + -moz-flex: 0 0 25%; + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; } + +.col-33, .col-34 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 33.3333%; + -moz-box-flex: 0; + -moz-flex: 0 0 33.3333%; + -ms-flex: 0 0 33.3333%; + flex: 0 0 33.3333%; + max-width: 33.3333%; } + +.col-40 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 40%; + -moz-box-flex: 0; + -moz-flex: 0 0 40%; + -ms-flex: 0 0 40%; + flex: 0 0 40%; + max-width: 40%; } + +.col-50 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 50%; + -moz-box-flex: 0; + -moz-flex: 0 0 50%; + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; } + +.col-60 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 60%; + -moz-box-flex: 0; + -moz-flex: 0 0 60%; + -ms-flex: 0 0 60%; + flex: 0 0 60%; + max-width: 60%; } + +.col-66, .col-67 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 66.6666%; + -moz-box-flex: 0; + -moz-flex: 0 0 66.6666%; + -ms-flex: 0 0 66.6666%; + flex: 0 0 66.6666%; + max-width: 66.6666%; } + +.col-75 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 75%; + -moz-box-flex: 0; + -moz-flex: 0 0 75%; + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; } + +.col-80 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 80%; + -moz-box-flex: 0; + -moz-flex: 0 0 80%; + -ms-flex: 0 0 80%; + flex: 0 0 80%; + max-width: 80%; } + +.col-90 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 90%; + -moz-box-flex: 0; + -moz-flex: 0 0 90%; + -ms-flex: 0 0 90%; + flex: 0 0 90%; + max-width: 90%; } + +/* Responsive Grid Classes */ +/* Adding a class of responsive-X to a row */ +/* will trigger the flex-direction to */ +/* change to column and add some margin */ +/* to any columns in the row for clearity */ +@media (max-width: 567px) { + .responsive-sm { + -webkit-box-direction: normal; + -moz-box-direction: normal; + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; } + .responsive-sm .col, .responsive-sm .col-10, .responsive-sm .col-20, .responsive-sm .col-25, .responsive-sm .col-33, .responsive-sm .col-34, .responsive-sm .col-50, .responsive-sm .col-66, .responsive-sm .col-67, .responsive-sm .col-75, .responsive-sm .col-80, .responsive-sm .col-90 { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + margin-bottom: 15px; + margin-left: 0; + max-width: 100%; + width: 100%; } } + +@media (max-width: 767px) { + .responsive-md { + -webkit-box-direction: normal; + -moz-box-direction: normal; + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; } + .responsive-md .col, .responsive-md .col-10, .responsive-md .col-20, .responsive-md .col-25, .responsive-md .col-33, .responsive-md .col-34, .responsive-md .col-50, .responsive-md .col-66, .responsive-md .col-67, .responsive-md .col-75, .responsive-md .col-80, .responsive-md .col-90 { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + margin-bottom: 15px; + margin-left: 0; + max-width: 100%; + width: 100%; } } + +@media (max-width: 1023px) { + .responsive-lg { + -webkit-box-direction: normal; + -moz-box-direction: normal; + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; } + .responsive-lg .col, .responsive-lg .col-10, .responsive-lg .col-20, .responsive-lg .col-25, .responsive-lg .col-33, .responsive-lg .col-34, .responsive-lg .col-50, .responsive-lg .col-66, .responsive-lg .col-67, .responsive-lg .col-75, .responsive-lg .col-80, .responsive-lg .col-90 { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-box-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; + margin-bottom: 15px; + margin-left: 0; + max-width: 100%; + width: 100%; } } + +/** + * Utility Classes + * -------------------------------------------------- + */ +.hide { + display: none; } + +.opacity-hide { + opacity: 0; } + +.grade-b .opacity-hide, +.grade-c .opacity-hide { + opacity: 1; + display: none; } + +.show { + display: block; } + +.opacity-show { + opacity: 1; } + +.invisible { + visibility: hidden; } + +.keyboard-open .hide-on-keyboard-open { + display: none; } + +.keyboard-open .tabs.hide-on-keyboard-open + .pane .has-tabs, +.keyboard-open .bar-footer.hide-on-keyboard-open + .pane .has-footer { + bottom: 0; } + +.inline { + display: inline-block; } + +.disable-pointer-events { + pointer-events: none; } + +.enable-pointer-events { + pointer-events: auto; } + +.disable-user-behavior { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-touch-callout: none; + -webkit-tap-highlight-color: transparent; + -webkit-tap-highlight-color: transparent; + -webkit-user-drag: none; + -ms-touch-action: none; + -ms-content-zooming: none; } + +.click-block { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + opacity: 0; + z-index: 99999; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + overflow: hidden; } + +.click-block-hide { + -webkit-transform: translate3d(-9999px, 0, 0); + transform: translate3d(-9999px, 0, 0); } + +.no-resize { + resize: none; } + +.block { + display: block; + clear: both; } + .block:after { + display: block; + visibility: hidden; + clear: both; + height: 0; + content: "."; } + +.full-image { + width: 100%; } + +.clearfix { + *zoom: 1; } + .clearfix:before, .clearfix:after { + display: table; + content: ""; + line-height: 0; } + .clearfix:after { + clear: both; } + +/** + * Content Padding + * -------------------------------------------------- + */ +.padding { + padding: 10px; } + +.padding-top, +.padding-vertical { + padding-top: 10px; } + +.padding-right, +.padding-horizontal { + padding-right: 10px; } + +.padding-bottom, +.padding-vertical { + padding-bottom: 10px; } + +.padding-left, +.padding-horizontal { + padding-left: 10px; } + +/** + * Scrollable iFrames + * -------------------------------------------------- + */ +.iframe-wrapper { + position: fixed; + -webkit-overflow-scrolling: touch; + overflow: scroll; } + .iframe-wrapper iframe { + height: 100%; + width: 100%; } + +/** + * Rounded + * -------------------------------------------------- + */ +.rounded { + border-radius: 4px; } + +/** + * Utility Colors + * -------------------------------------------------- + * Utility colors are added to help set a naming convention. You'll + * notice we purposely do not use words like "red" or "blue", but + * instead have colors which represent an emotion or generic theme. + */ +.light, a.light { + color: #fff; } + +.light-bg { + background-color: #fff; } + +.light-border { + border-color: #ddd; } + +.stable, a.stable { + color: #f8f8f8; } + +.stable-bg { + background-color: #f8f8f8; } + +.stable-border { + border-color: #b2b2b2; } + +.positive, a.positive { + color: #387ef5; } + +.positive-bg { + background-color: #387ef5; } + +.positive-border { + border-color: #0c60ee; } + +.calm, a.calm { + color: #11c1f3; } + +.calm-bg { + background-color: #11c1f3; } + +.calm-border { + border-color: #0a9dc7; } + +.assertive, a.assertive { + color: #ef473a; } + +.assertive-bg { + background-color: #ef473a; } + +.assertive-border { + border-color: #e42112; } + +.balanced, a.balanced { + color: #33cd5f; } + +.balanced-bg { + background-color: #33cd5f; } + +.balanced-border { + border-color: #28a54c; } + +.energized, a.energized { + color: #ffc900; } + +.energized-bg { + background-color: #ffc900; } + +.energized-border { + border-color: #e6b500; } + +.royal, a.royal { + color: #886aea; } + +.royal-bg { + background-color: #886aea; } + +.royal-border { + border-color: #6b46e5; } + +.dark, a.dark { + color: #444; } + +.dark-bg { + background-color: #444; } + +.dark-border { + border-color: #111; } + +[collection-repeat] { + /* Position is set by transforms */ + left: 0 !important; + top: 0 !important; + position: absolute !important; + z-index: 1; } + +.collection-repeat-container { + position: relative; + z-index: 1; } + +.collection-repeat-after-container { + z-index: 0; + display: block; + /* when scrolling horizontally, make sure the after container doesn't take up 100% width */ } + .collection-repeat-after-container.horizontal { + display: inline-block; } + +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, +.x-ng-cloak, .ng-hide:not(.ng-hide-animate) { + display: none !important; } + +/** + * Platform + * -------------------------------------------------- + * Platform specific tweaks + */ +.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) { + height: 64px; } + .platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper { + margin-top: 19px !important; } + .platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) > * { + margin-top: 20px; } + +.platform-ios.platform-cordova:not(.fullscreen) .tabs-top > .tabs, +.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top { + top: 64px; } + +.platform-ios.platform-cordova:not(.fullscreen) .has-header, +.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader { + top: 64px; } + +.platform-ios.platform-cordova:not(.fullscreen) .has-subheader { + top: 108px; } + +.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top { + top: 113px; } + +.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top { + top: 157px; } + +.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader) { + height: 44px; } + .platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper { + margin-top: -1px; } + .platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader) > * { + margin-top: 0; } + +.platform-ios.platform-cordova .popover .has-header, +.platform-ios.platform-cordova .popover .bar-subheader { + top: 44px; } + +.platform-ios.platform-cordova .popover .has-subheader { + top: 88px; } + +.platform-ios.platform-cordova.status-bar-hide { + margin-bottom: 20px; } + +@media (orientation: landscape) { + .platform-ios.platform-browser.platform-ipad { + position: fixed; } } + +.platform-c:not(.enable-transitions) * { + -webkit-transition: none !important; + transition: none !important; } + +.slide-in-up { + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); } + +.slide-in-up.ng-enter, +.slide-in-up > .ng-enter { + -webkit-transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms; + transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms; } + +.slide-in-up.ng-enter-active, +.slide-in-up > .ng-enter-active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.slide-in-up.ng-leave, +.slide-in-up > .ng-leave { + -webkit-transition: all ease-in-out 250ms; + transition: all ease-in-out 250ms; } + +@-webkit-keyframes scaleOut { + from { + -webkit-transform: scale(1); + opacity: 1; } + to { + -webkit-transform: scale(0.8); + opacity: 0; } } + +@keyframes scaleOut { + from { + transform: scale(1); + opacity: 1; } + to { + transform: scale(0.8); + opacity: 0; } } + +@-webkit-keyframes superScaleIn { + from { + -webkit-transform: scale(1.2); + opacity: 0; } + to { + -webkit-transform: scale(1); + opacity: 1; } } + +@keyframes superScaleIn { + from { + transform: scale(1.2); + opacity: 0; } + to { + transform: scale(1); + opacity: 1; } } + +[nav-view-transition="ios"] [nav-view="entering"], +[nav-view-transition="ios"] [nav-view="leaving"] { + -webkit-transition-duration: 500ms; + transition-duration: 500ms; + -webkit-transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); + transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); + -webkit-transition-property: opacity, -webkit-transform, box-shadow; + transition-property: opacity, transform, box-shadow; } + +[nav-view-transition="ios"][nav-view-direction="forward"], [nav-view-transition="ios"][nav-view-direction="back"] { + background-color: #000; } + +[nav-view-transition="ios"] [nav-view="active"], +[nav-view-transition="ios"][nav-view-direction="forward"] [nav-view="entering"], +[nav-view-transition="ios"][nav-view-direction="back"] [nav-view="leaving"] { + z-index: 3; } + +[nav-view-transition="ios"][nav-view-direction="back"] [nav-view="entering"], +[nav-view-transition="ios"][nav-view-direction="forward"] [nav-view="leaving"] { + z-index: 2; } + +[nav-bar-transition="ios"] .title, +[nav-bar-transition="ios"] .buttons, +[nav-bar-transition="ios"] .back-text { + -webkit-transition-duration: 500ms; + transition-duration: 500ms; + -webkit-transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); + transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); + -webkit-transition-property: opacity, -webkit-transform; + transition-property: opacity, transform; } + +[nav-bar-transition="ios"] [nav-bar="active"], +[nav-bar-transition="ios"] [nav-bar="entering"] { + z-index: 10; } + [nav-bar-transition="ios"] [nav-bar="active"] .bar, + [nav-bar-transition="ios"] [nav-bar="entering"] .bar { + background: transparent; } + +[nav-bar-transition="ios"] [nav-bar="cached"] { + display: block; } + [nav-bar-transition="ios"] [nav-bar="cached"] .header-item { + display: none; } + +[nav-view-transition="android"] [nav-view="entering"], +[nav-view-transition="android"] [nav-view="leaving"] { + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + -webkit-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); + -webkit-transition-property: -webkit-transform; + transition-property: transform; } + +[nav-view-transition="android"] [nav-view="active"], +[nav-view-transition="android"][nav-view-direction="forward"] [nav-view="entering"], +[nav-view-transition="android"][nav-view-direction="back"] [nav-view="leaving"] { + z-index: 3; } + +[nav-view-transition="android"][nav-view-direction="back"] [nav-view="entering"], +[nav-view-transition="android"][nav-view-direction="forward"] [nav-view="leaving"] { + z-index: 2; } + +[nav-bar-transition="android"] .title, +[nav-bar-transition="android"] .buttons { + -webkit-transition-duration: 200ms; + transition-duration: 200ms; + -webkit-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); + transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); + -webkit-transition-property: opacity; + transition-property: opacity; } + +[nav-bar-transition="android"] [nav-bar="active"], +[nav-bar-transition="android"] [nav-bar="entering"] { + z-index: 10; } + [nav-bar-transition="android"] [nav-bar="active"] .bar, + [nav-bar-transition="android"] [nav-bar="entering"] .bar { + background: transparent; } + +[nav-bar-transition="android"] [nav-bar="cached"] { + display: block; } + [nav-bar-transition="android"] [nav-bar="cached"] .header-item { + display: none; } + +[nav-swipe="fast"] [nav-view], +[nav-swipe="fast"] .title, +[nav-swipe="fast"] .buttons, +[nav-swipe="fast"] .back-text { + -webkit-transition-duration: 50ms; + transition-duration: 50ms; + -webkit-transition-timing-function: linear; + transition-timing-function: linear; } + +[nav-swipe="slow"] [nav-view], +[nav-swipe="slow"] .title, +[nav-swipe="slow"] .buttons, +[nav-swipe="slow"] .back-text { + -webkit-transition-duration: 160ms; + transition-duration: 160ms; + -webkit-transition-timing-function: linear; + transition-timing-function: linear; } + +[nav-view="cached"], +[nav-bar="cached"] { + display: none; } + +[nav-view="stage"] { + opacity: 0; + -webkit-transition-duration: 0; + transition-duration: 0; } + +[nav-bar="stage"] .title, +[nav-bar="stage"] .buttons, +[nav-bar="stage"] .back-text { + position: absolute; + opacity: 0; + -webkit-transition-duration: 0s; + transition-duration: 0s; } + +/* BEGIN Thin */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.ttf?v=1.1.0") format("truetype"); + font-weight: 100; + font-style: normal; } + +/* END Thin */ +/* BEGIN Light */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.ttf?v=1.1.0") format("truetype"); + font-weight: 300; + font-style: normal; } + +/* END Light */ +/* BEGIN Regular */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0") format("truetype"); + font-weight: 400; + font-style: normal; } + +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0") format("truetype"); + font-weight: normal; + font-style: normal; } + +/* END Regular */ +/* BEGIN Italic */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0") format("truetype"); + font-weight: 400; + font-style: italic; } + +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0") format("truetype"); + font-weight: normal; + font-style: italic; } + +/* END Italic */ +/* BEGIN Medium */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.ttf?v=1.1.0") format("truetype"); + font-weight: 500; + font-style: normal; } + +/* END Medium */ +/* BEGIN Bold */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0") format("truetype"); + font-weight: 700; + font-style: normal; } + +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0") format("truetype"); + font-weight: bold; + font-style: normal; } + +/* END Bold */ +/* BEGIN Bold Italic */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0") format("truetype"); + font-weight: 700; + font-style: italic; } + +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0") format("truetype"); + font-weight: bold; + font-style: italic; } + +/* END Bold Italic */ +/* BEGIN Black */ +@font-face { + font-family: RobotoDraft; + src: url("../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff2?v=1.1.0") format("woff2"), url("../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff?v=1.1.0") format("woff"), url("../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.ttf?v=1.1.0") format("truetype"); + font-weight: 900; + font-style: normal; } + +/* END Black */ +/* Directives : MD Label +==================================*/ +.item-md-label { + display: block; + background: transparent; + box-shadow: none; + margin-left: 12px; + margin-right: 12px; + padding: 30px 0 0; } + +.item-md-label .input-label { + position: absolute; + padding: 5px 0 0; + z-index: 2; + -webkit-transform: translate3d(0, -30px, 0) scale(1); + transform: translate3d(0, -30px, 0) scale(1); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + color: #fff; + opacity: 0.5; + filter: alpha(opacity=50); + -webkit-transform-origin: 0; + -ms-transform-origin: 0; + transform-origin: 0; } + +.item-md-label input { + background-color: rgba(0, 0, 0, 0.6); + bottom: 0; + color: #fff; + letter-spacing: 0.25rem; + padding: 20px 10px; + position: relative; + z-index: 1; } + +.item-md-label .highlight { + position: absolute; + bottom: 0; + height: 2px; + left: 0; + width: 100%; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + -webkit-transition: all 0.15s ease; + transition: all 0.15s ease; + z-index: 1; } + +.item-md-label .highlight-light { + background: #fff; } + +.item-md-label .highlight-stable { + background: #f8f8f8; } + +.item-md-label .highlight-positive { + background: #387ef5; } + +.item-md-label .highlight-calm { + background: #11c1f3; } + +.item-md-label .highlight-balanced { + background: #33cd5f; } + +.item-md-label .highlight-energized { + background: #ffc900; } + +.item-md-label .highlight-assertive { + background: #ef473a; } + +.item-md-label .highlight-royal { + background: #886aea; } + +.item-md-label .highlight-dark { + background: #444; } + +.item-md-label .input-label { + letter-spacing: 0.25rem; + padding: 0 10px; } + +.item-md-label input:focus ~ .input-label, .item-md-label input.used ~ .input-label { + font-weight: bold; + opacity: 0.7; + filter: alpha(opacity=70); + padding: 0; + text-transform: uppercase; + -webkit-transform: translate3d(0, -60px, 0) scale(0.9); + transform: translate3d(0, -60px, 0) scale(0.9); } + +.item-md-label input:focus ~ .highlight { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +/* Bar - Header - Expanded +==================================*/ +.expanded .bar.bar-header, +.bar.bar-header.expanded { + height: 75px; } + +.expanded.bar.bar-header .title, +.bar.bar-header.expanded .title { + bottom: 0; + top: initial; + padding-left: 16px; } + +.expanded .bar.bar-header .title.fab-left, +.bar.bar-header.expanded .title.fab-left { + bottom: 0; + left: 90px; + position: absolute; + right: initial; + top: initial; } + +.expanded .bar.bar-header .title.fab-right, +.bar.bar-header.expanded .title.fab-right { + bottom: 0; + left: 4px; + position: absolute; + top: initial; + right: initial; } + +.expanded .bar.bar-header + .button-fab, +.bar.bar-header.expanded + .button-fab { + top: 50px; } + +.expanded .bar.bar-header.push-down, +.bar.bar-header.expanded.push-down { + height: 44px; + overflow: hidden; } + +.expanded .bar.bar-header, +.bar.bar-header.expanded { + -webkit-transition: height 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: height 1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.expanded .bar.bar-header + .button-fab, +.bar.bar-header.expanded + .button-fab { + -webkit-transition: all 1.1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1.1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0) scale(1); + transform: translate3d(0, 0, 0) scale(1); } + +.expanded .bar.bar-header.push-down + .button-fab, +.bar.bar-header.expanded.push-down + .button-fab { + top: 0; + -webkit-transform: translate3d(-100px, -100px, 0) scale(2.5); + transform: translate3d(-100px, -100px, 0) scale(2.5); } + +.expanded .bar.bar-header.push-down .title, +.bar.bar-header.expanded.push-down .title { + opacity: 0; + filter: alpha(opacity=0); + left: initial; + right: initial; } + +.expanded .bar.bar-header .title, +.bar.bar-header.expanded .title { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transition: all 2s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 2s cubic-bezier(0.55, 0, 0.1, 1); } + +.expanded .bar.bar-header .title, .bar.bar-header.expanded .title { + bottom: 0; + left: 42px !important; + top: initial; } + +.expanded.has-header-fab-left .bar.bar-header .title, .bar.bar-header.expanded.has-header-fab-left .title { + left: 76px !important; } + +/* Bar +==================================*/ +.bar { + z-index: 2; + font-size: 1.3em; + width: 100%; + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); } + +.bar .button { + min-width: 38px; + z-index: 3; } + +.bar .no-text span.back-text { + display: none; } + +.bar .title sup { + opacity: 0.7; } + +.bar.bar-header .button + .title { + text-align: left; + left: 35px; + line-height: 46px; } + +/* Button Bar +==================================*/ +.button-bar { + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15); } + +.button-bar > .button { + box-shadow: none; + /* line-height: initial; */ } + +.button-bar > .button .icon:before, +.button-bar > .button:before { + line-height: initial; } + +.bar-footer .button-fab { + position: absolute; + top: -26px; + bottom: initial; } + +.bar-footer .buttons-left .button-fab { + left: 8px; } + +.bar-footer .buttons-right .button-fab { + right: 8px; } + +.bar .button.button-clear { + box-shadow: none; } + +.left-buttons .button-fab { + left: 8px; + top: 16px; } + +.right-buttons .button-fab { + right: 8px; + top: 16px; } + +.fab-left.title-left, +.fab-left.title.title-left { + left: 68px; } + +/* Button : FAB +==================================*/ +.button.button-fab, +.bar .button.button-fab { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + z-index: 9999; + width: 56px; + height: 56px; + max-height: initial; + max-width: initial; + border-radius: 50%; + border-radius: 50%; + overflow: hidden; + padding: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition: 0.3s fade-in-out; + transition: 0.3s fade-in-out; + -webkit-transition-property: -webkit-transform, box-shadow; + transition-property: transform, box-shadow; } + +.button.button-fab.button-fab-bottom-right, +.bar .button.button-fab.button-fab-bottom-right { + top: auto; + right: 16px; + bottom: 16px; + left: auto; + position: absolute; } + +.button.button-fab.button-fab-bottom-left, +.bar .button.button-fab.button-fab-bottom-left { + top: auto; + right: auto; + bottom: 16px; + left: 16px; + position: absolute; } + +.button.button-fab.button-fab-top-right, +.bar .button.button-fab.button-fab-top-right { + top: 32px; + right: 16px; + bottom: auto; + left: auto; + position: absolute; } + +.button.button-fab.button-fab-top-left, +.bar .button.button-fab.button-fab-top-left { + top: 32px; + right: auto; + bottom: auto; + left: 16px; + position: absolute; } + +.button.button-fab.button-fab-top-left.expanded, +.button.button-fab.button-fab-top-right.expanded, +.bar .button.button-fab.button-fab-top-left.expanded, +.bar .button.button-fab.button-fab-top-right.expanded { + top: 48px; } + +.button.button-fab i, +.bar .button.button-fab i { + font-size: 2.5rem; + margin-top: 0; } + +.button.button-fab.mini, +.bar .button.button-fab.mini { + width: 40px; + height: 40px; } + +.button.button-fab.mini i, +.bar .button.button-fab.mini i { + font-size: 2rem; } + +/* Motion */ +.motion { + -webkit-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; } + +.fade { + opacity: 0; + filter: alpha(opacity=0); + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spin-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) !important; + transform: translateZ(0) rotate(360deg) scale(0) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.menu-open .avatar { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transform: translateZ(0) rotate(0) scale(1) !important; + transform: translateZ(0) rotate(0) scale(1) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.button.button-fab.button-fab-top-left.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(-120px, 60px, 0); + transform: translate3d(-120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.button.button-fab.button-fab-top-right.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(120px, 60px, 0); + transform: translate3d(120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.button.button-fab.button-fab-bottom-left.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(-120px, 60px, 0); + transform: translate3d(-120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.button.button-fab.button-fab-bottom-right.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(120px, 60px, 0); + transform: translate3d(120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.spin { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(0) scale(0) !important; + transform: translateZ(0) rotate(0) scale(0) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.spin.on { + -webkit-transform: translateZ(0) rotate(-360deg) scale(1) !important; + transform: translateZ(0) rotate(-360deg) scale(1) !important; } + +.flap { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flap.on { + -webkit-transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) scale(3) !important; + transform: translateZ(0) scale(3) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop.on { + -webkit-transform: translateZ(0) scale(1) !important; + transform: translateZ(0) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateY(0) scale(0) !important; + transform: translateZ(0) rotateY(0) scale(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip.on { + -webkit-transform: translateZ(0) rotateY(-720deg) scale(1) !important; + transform: translateZ(0) rotateY(-720deg) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +/* Button : Floating +==================================*/ +.button.button-floating, .bar .button.button-floating { + display: inline-block; + color: #FFF; + position: relative; + z-index: 1; + width: 37px; + height: 37px; + line-height: 37px; + padding: 0; + border-radius: 50%; + background-clip: padding-box; + -webkit-transition: 0.3s; + transition: 0.3s; + cursor: pointer; } + +.button.button-floating i, .bar .button.button-floating i { + width: inherit; + display: inline-block; + text-align: center; + color: #FFF; + font-size: 1.6rem; + line-height: 37px; } + +.button.button-floating.button-large, .bar .button.button-floating.button-large { + width: 55.5px; + height: 55.5px; } + +.button.button-floating.button-large i, .bar .button.button-floating.button-large i { + line-height: 55.5px; } + +/* Button +==================================*/ +.button, +.button.button-large, +.button.button-flat, +.bar .button, +.bar .button.button-large, +.bar .button.button-flat { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + display: inline-block; + height: 36px; + padding: 0 2rem; + border-radius: 2px; + background-clip: padding-box; + text-transform: uppercase; + border: none; + outline: 0; + -webkit-tap-highlight-color: transparent; } + +.button.disabled, +.button.disabled.button-large, +.button.button-floating.disabled, +.button.button-large.disabled, +.button.button:disabled, +.button.button-large:disabled, +.button.button-large:disabled, +.button.button-floating:disabled, +.bar .button.disabled, +.bar .button.disabled.button-large, +.bar .button.button-floating.disabled, +.bar .button.button-large.disabled, +.bar .button.button:disabled, +.bar .button.button-large:disabled, +.bar .button.button-large:disabled, +.bar .button.button-floating:disabled { + background-color: #DFDFDF; + box-shadow: none; + color: #9F9F9F; } + +.button.disabled:hover, +.button.disabled.button-large:hover, +.button.button-floating.disabled:hover, +.button.button-large.disabled:hover, +.button.button:disabled:hover, +.button.button-large:disabled:hover, +.button.button-large:disabled:hover, +.button.button-floating:disabled:hover, +.bar .button.disabled:hover, +.bar .button.disabled.button-large:hover, +.bar .button.button-floating.disabled:hover, +.bar .button.button-large.disabled:hover, +.bar .button.button:disabled:hover, +.bar .button.button-large:disabled:hover, +.bar .button.button-large:disabled:hover, +.bar .button.button-floating:disabled:hover { + background-color: #DFDFDF; + color: #9F9F9F; } + +.button i, +.button.button-large i, +.button.button-floating i, +.button.button-large i, +.button.button-flat i, +.bar .button i, +.bar .button.button-large i, +.bar .button.button-floating i, +.bar .button.button-large i, +.bar .button.button-flat i { + font-size: 1.3rem; } + +.button-bar .button { + border-radius: 0; } + +.button, +.button-large, +.bar .button, +.bar .button-large { + text-decoration: none; + text-align: center; + letter-spacing: 0.5px; + -webkit-transition: 0.2s ease-out; + transition: 0.2s ease-out; + cursor: pointer; } + +.button { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + outline: none; + margin: 0; + /* background: transparent; */ + white-space: nowrap; + text-align: center; + text-transform: uppercase; + font-weight: 500; + font-style: inherit; + font-variant: inherit; + font-size: inherit; + text-decoration: none; + cursor: pointer; + overflow: hidden; + -webkit-transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); + transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); } + +.button:focus { + outline: none; } + +.button.ng-hide { + -webkit-transition: none; + transition: none; } + +.button.cornered { + border-radius: 0; } + +.button.raised { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.button-outline, +.button-outline:hover, +.button-outline:active { + border-style: solid; + border-width: 1px; } + +.button.button-outline.button-assertive, +.button.button-outline.button-balanced, +.button.button-outline.button-calm, +.button.button-outline.button-dark, +.button.button-outline.button-energized, +.button.button-outline.button-light, +.button.button-outline.button-positive, +.button.button-outline.button-royal, +.button.button-outline.button-stable, +.button.button-outline { + border-color: rgba(0, 0, 0, 0.1); } + +.button-flat, +.bar .button-flat { + box-shadow: none; + background-color: transparent; + color: #343434; + cursor: pointer; } + +.button.button-flat.disabled, +.bar .button.button-flat.disabled { + color: #b3b3b3; } + +.button.button-large i, +.bar .button.button-large i { + font-size: 1.6rem; } + +.button-pin-header.button-floating { + position: absolute; + z-index: 1000; } + +.button-pin-header.button-pin-left { + left: 24px; + top: -24px; } + +.button-pin-header.button-pin-right { + right: 24px; + top: -24px; } + +.button:not([disabled]).raised:focus, +.button:not([disabled]).raised:hover, +.button:not([disabled]).floating:focus, +.button:not([disabled]).floating:hover { + -webkit-transform: translate3d(0, -1px, 0); + transform: translate3d(0, -1px, 0); } + +.button.button-flat { + box-shadow: none; + /* background: transparent; */ + color: inherit; } + +.button.button-flat:hover { + color: inherit; } + +.button.button-flat, +.button.button-flat:hover, +.button.button-flat:active { + color: #fff; } + +.button.button-clear, +.button.button-clear:hover, +.button.button-clear:active { + background: transparent; } + +.button-full.ink, +.button-block.ink { + display: block; } + +/* Card +==================================*/ +.card-item.item { + border: none; + padding-bottom: 4px; + padding-top: 4px; } + +.card-item.item:first-child { + padding-top: 16px; } + +.card { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); + display: block; + margin: 8px; + padding: 0; + position: relative; } + +.card .image { + display: block; + margin-top: 10px; + margin-bottom: 5px; } + +.card img { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); + display: block; + max-width: 100%; + max-height: initial; + position: static; } + +.card.card-gallery img { + border: none; + box-shadow: none; + display: block; } + +.card .card-footer { + font-size: 90%; + opacity: 0.8; + filter: alpha(opacity=80); + padding-top: 10px; } + +.card > .item { + border: none; } + +.card.card-gallery > .item { + background: inherit; } + +.card .icon + .icon { + padding-left: 1rem; } + +.card.animate-fade-in { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transform: translate3d(-30px, 1px, 0); + -webkit-transition: all 1s ease-in-out; } + +.card.animate-fade-in.done { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transform: translate3d(0, 0, 0); } + +.card .item.item-avatar { + min-height: 88px; + padding-left: 88px; } + +/* Hero +==================================*/ +.hero { + background-size: cover; + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); + color: #fff; + height: 200px; + position: relative; + text-align: center; + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + width: 100%; } + +.hero > * { + -webkit-transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 1; + filter: alpha(opacity=100); } + +.hero + .mid-bar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + height: initial; + opacity: 1; + filter: alpha(opacity=100); } + +.hero .hero-icon { + box-shadow: 0px 0 2px 0 rgba(0, 0, 0, 0.26); + border-radius: 50%; + display: inline-block; + font-size: 65px; + height: 150px; + padding: 10px 30px; + line-height: 136px; + width: 150px; } + +.hero.no-header { + height: 244px; } + +.hero > .content { + bottom: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: 1; } + +.hero > .content > .avatar { + background-position: center; + background-size: cover; + border: solid 1px rgba(255, 255, 255, 0.8); + border-radius: 50%; + display: inline-block; + height: 88px; + left: auto; + margin-bottom: 10px; + position: relative; + width: 88px; } + +.hero h1 .hero h2, .hero h3, .hero h4, .hero h5, .hero h6 { + color: #fff; + margin: 0; } + +.hero h4 { + color: rgba(255, 255, 255, 0.7); + margin: 3px 0 16px; } + +.hero h1 > a, .hero h2 > a, .hero h3 > a, .hero h4 > a, .hero h5 > a, .hero h6 > a { + text-decoration: none; } + +.hero + .button-bar { + border-radius: 0; + margin-top: 0; } + +.hero + .button-bar > .button:first-child, .hero + .button-bar > .button:last-child { + border-radius: 0; } + +.hero .hero-icon { + color: #fff; + font-size: 96px; } + +.hero .hero-icon + h1 { + color: white; + letter-spacing: 0.15rem; } + +.hero .button, .hero .button.button-large, .hero .button.button-flat { + margin: 0; } + +.hero h1.title { + color: #fff; + font-size: 23px; + margin: 0; + text-align: left; + padding-left: 80px; + line-height: 59px; } + +.hero + .mid-bar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + height: initial; + opacity: 1; + filter: alpha(opacity=100); } + +.hero > * { + -webkit-transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 1; + filter: alpha(opacity=100); } + +/* Item +==================================*/ +.item { + font-size: 14px; + width: 100%; } + +.item-icon-left .icon { + left: 16px; } + +.item-icon-right .icon { + right: 16px; } + +/* +.list .item.item-icon-right { + padding-right: 60px; +} +*/ +.item-thumbnail-left > img:first-child, .item-thumbnail-left .item-image, .item-thumbnail-left .item-content > img:first-child, .item-thumbnail-left .item-content .item-image { + border-radius: 50%; } + +.tab-item.activated { + height: calc(100% + 3px); + /* Stretch */ } + +/* List +==================================*/ +.content + .list { + padding-top: 0; } + +.list .item { + border: none; + /* + padding-left: 16px; + padding-right: 16px; + */ + min-height: 48px; + text-align: left; } + +.list .item.tabs { + padding: initial; } + +.list .item.item-bg-image { + max-height: 150px; + min-height: 150px; } + +.list .item.item-bg-image > img { + height: 100%; + left: 0; + max-width: initial; + opacity: 0.65; + filter: alpha(opacity=65); + position: absolute; + top: 0; + width: 100%; + z-index: 0; } + +.list a.item { + opacity: 1; + filter: alpha(opacity=100); } + +.list .item.item-bg-image h1, .list .item.item-bg-image h2, .list .item.item-bg-image h3, .list .item.item-bg-image h4, .list .item.item-bg-image h5, .list .item.item-bg-image h6 { + color: #fff; + font-weight: bold; + position: relative; + text-shadow: 0 0 3px rgba(0, 0, 0, 0.95); + z-index: 1; } + +.list .item.item-bg-image h2 { + font-size: 24px; } + +.list .item.item-bg-image h2 { + font-size: 24px; } + +.list .item.item-bg-image p { + color: white; + font-size: 17px; + position: relative; + text-shadow: 0 0 4px rgba(0, 0, 0, 0.95); + z-index: 1; } + +.item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content { + min-height: 80px; } + +/* List: Thumbnails +==================================*/ +.item-thumbnail-left, .card > .item.item-thumbnail-left, .item-thumbnail-left .item-content { + padding-left: 106px; } + +.item-thumbnail-right, .card > .item.item-thumbnail-right, .item-thumbnail-right .item-content { + padding-right: 106px; } + +/* List: Avatar +==================================*/ +.item-avatar > img:first-child, .item-avatar .item-image, .item-avatar .item-content > img:first-child, .item-avatar .item-content .item-image, .item-avatar-left > img:first-child, .item-avatar-left .item-image, .item-avatar-left .item-content > img:first-child, .item-avatar-left .item-content .item-image { + border-radius: 50%; + left: 16px; + max-height: 40px; + max-width: 40px; } + +/* +.item-avatar, .list .item-avatar { + padding-left: 100px; +} +*/ +.avatar, .item-avatar .avatar { + background-position: center; + background-size: cover; + border-radius: 50%; + display: inline-block; + height: 56px; + left: 16px; + position: absolute; + width: 56px; } + +/* List: Gallery +==================================*/ +.list.half { + display: inline-block; + float: left; + margin: 0; + padding: 0; + width: 50%; } + +.list.half:first-child { + padding: 16px 8px 16px 16px; } + +.list.half:last-child { + padding: 16px 16px 16px 8px; } + +.list.half:first-child .card.card-gallery { + margin-left: 0; + margin-right: 0; } + +.list.half:last-child .card.card-gallery { + margin-left: 0; + margin-right: 0; } + +.list.condensed-space > .card, .list.condensed-space > .item { + margin: 0px 0px 2px; } + +.list .card.card-gallery { + display: block; + float: left; + margin: 0 0 0 13px; + padding: 0; + width: auto; } + +.list.half .item { + width: 100%; } + +.list.half .item.card { + margin-bottom: 16px; } + +.list .card.card-gallery.item h2 { + padding: 12px; } + +.list .item.item-gallery img { + width: 100%; } + +.item.item-divider { + border-top: solid 1px rgba(0, 0, 0, 0.12); + font-size: 14px; + font-weight: bold; + height: 48px; + line-height: 48px; + color: rgba(0, 0, 0, 0.54); } + .item.item-divider:first-child { + border: none; } + +.item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content, .card > .item-avatar { + padding-left: 72px; } + +.item.active, .item.activated, .item-complex.active .item-content, .item-complex.activated .item-content, .item .item-content.active, .item .item-content.activated { + background-color: transparent; } + +.list-inset { + margin: 20px 30px; + border-left: solid 1px #ccc; + border-radius: 0; + background-color: #fff; } + +.list .item.item-floating-label, +.item-floating-label { + border-bottom: solid 1px #ccc; } + +.loader { + position: relative; + margin: 0px auto; + width: 100px; + height: 100px; + zoom: 1.7; } + +.circular { + -webkit-animation: rotate 2s linear infinite; + animation: rotate 2s linear infinite; + height: 100px; + position: relative; + width: 100px; } + +.path { + stroke-dasharray: 1,200; + stroke-dashoffset: 0; + -webkit-animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; + animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; + stroke-linecap: round; } + +@-webkit-keyframes rotate { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes rotate { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@-webkit-keyframes dash { + 0% { + stroke-dasharray: 1,200; + stroke-dashoffset: 0; } + 50% { + stroke-dasharray: 89,200; + stroke-dashoffset: -35; } + 100% { + stroke-dasharray: 89,200; + stroke-dashoffset: -124; } } + +@keyframes dash { + 0% { + stroke-dasharray: 1,200; + stroke-dashoffset: 0; } + 50% { + stroke-dasharray: 89,200; + stroke-dashoffset: -35; } + 100% { + stroke-dasharray: 89,200; + stroke-dashoffset: -124; } } + +@-webkit-keyframes color { + 100%, 0% { + stroke: #d62d20; } + 40% { + stroke: #0057e7; } + 66% { + stroke: #008744; } + 80%, 90% { + stroke: #ffa700; } } + +@keyframes color { + 100%, 0% { + stroke: #d62d20; } + 40% { + stroke: #0057e7; } + 66% { + stroke: #008744; } + 80%, 90% { + stroke: #ffa700; } } + +/* Layouts: Login +==================================*/ +.login { + background-position: 25% 25%; + background-size: 180% 180%; + height: 100%; + -webkit-transition: all 1.5s ease-in-out; + transition: all 1.5s ease-in-out; } + +.login .item { + margin: 0 12px; + padding-left: 0; + padding-right: 0; + width: initial; } + +.login .button-bar { + bottom: 0; + margin: 28px 12px 0; + width: initial; } + +.login .light-bg { + background-color: #fff; } + +.icon.hero-icon:before { + line-height: 130px; } + +/* Mask +==================================*/ +.hero.has-mask:after, .item.has-mask:after, .card.has-mask:after { + content: ''; + background: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.6) 100%); + height: 100%; + left: 0; + position: absolute; + top: 0; + z-index: 0; + width: 100%; } + +.hero.has-mask-reverse:after, .item.has-mask-reverse:after, .card.has-mask-reverse:after { + content: ''; + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.6) 0%, transparent 100%); + height: 100%; + left: 0; + position: absolute; + top: 0; + z-index: 0; + width: 100%; } + +/* Menu */ +.menu-bottom { + bottom: 16px; + left: 16px; + right: 16px; + position: absolute; } + +.menu-top { + top: 16px; + left: 16px; + right: 16px; + position: absolute; } + +.menu .avatar { + top: 16px; + left: 16px; + height: 65px; + width: 65px; } + +.menu .bar.bar-header.expanded { + box-shadow: none; + min-height: 150px; + color: #fff; } + +.menu-open .bar.bar-header.expanded { + background-position: 0; + background-size: 100%; } + +.has-expanded-header { + top: 150px !important; } + +.motion { + -webkit-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; } + +.fade { + opacity: 0; + filter: alpha(opacity=0); + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spin-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) !important; + transform: translateZ(0) rotate(360deg) scale(0) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.menu-open .avatar { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transform: translateZ(0) rotate(0) scale(1) !important; + transform: translateZ(0) rotate(0) scale(1) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.spin { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(0) scale(0) !important; + transform: translateZ(0) rotate(0) scale(0) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.spin.on { + -webkit-transform: translateZ(0) rotate(-360deg) scale(1) !important; + transform: translateZ(0) rotate(-360deg) scale(1) !important; } + +.flap { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flap.on { + -webkit-transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) scale(3) !important; + transform: translateZ(0) scale(3) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop.on { + -webkit-transform: translateZ(0) scale(1) !important; + transform: translateZ(0) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateY(0) scale(0) !important; + transform: translateZ(0) rotateY(0) scale(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip.on { + -webkit-transform: translateZ(0) rotateY(-720deg) scale(1) !important; + transform: translateZ(0) rotateY(-720deg) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +/* Utilities +==================================*/ +.bold { + font-weight: bold; } + +.static { + position: static; } + +.pull-left { + float: left; } + +.pull-right { + float: right; } + +.double-padding, .ionic-content.double-padding { + padding: 16px; } + +.double-padding-x { + padding-left: 16px; + padding-right: 16px; } + +.double-padding-y { + padding-top: 16px; + padding-bottom: 16px; } + +.outline { + border-style: solid; + border-width: 1px; } + +.border-top { + border-top: solid 1px #ccc; + padding-top: 30px; } + +.no-border { + border: none; } + +.circle { + border-radius: 50%; } + +.no-padding, .list.no-padding, .bar.no-padding, .button-bar.no-padding, .card.no-padding, .button.no-padding, .item.no-padding { + padding: 0; } + +.flat, .flat.tabs, .flat.button, .flat.button.icon, .flat.hero { + box-shadow: none; + -webkit-box-shadow: none; } + +/* Utilities : Padding +==================================*/ +.im-wrapper, .padding { + padding: 16px !important; } + +.padding-bottom { + padding-bottom: 16px !important; } + +.padding-top { + padding-top: 16px !important; } + +.padding-left { + padding-left: 16px !important; } + +.padding-right { + padding-right: 16px !important; } + +.no-padding-bottom { + padding-bottom: 0 !important; } + +.no-padding-top { + padding-top: 0 !important; } + +.no-padding-left { + padding-left: 0 !important; } + +.no-padding-right { + padding-right: 0 !important; } + +/* Utilities : Depth +==================================*/ +.z1 { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); } + +/* Utilities : Color +==================================*/ +.bar.bar-positive.darker { + background-color: #164FAB; } + +/* TODO: Expand to other colors */ +.bar.bar-positive.dark-positive-bg { + background-color: #2C5CAD; } + +/* TODO: Expand to other colors */ +.muted { + color: #C3C3C3; } + +.clear-bg { + background: transparent; } + +/* Motion: Blinds +==================================*/ +.animate-blinds .item, +.animate-blinds .item { + visibility: hidden; } + +.animate-blinds .item, +.animate-blinds .item { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-blinds .item-bg-image > img.background, +.animate-blinds .item-bg-image > img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-blinds .in, +.animate-blinds.done > *, +.animate-blinds .in, +.animate-blinds.done > * { + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.animate-blinds .in, +.animate-blinds.done .item, +.animate-blinds .in, +.animate-blinds.done .item { + visibility: visible; } + +.animate-blinds .item, +.animate-blinds .item { + visibility: hidden; } + +.animate-blinds .item, +.animate-blinds .item { + opacity: 0; + filter: alpha(opacity=0); } + +.animate-blinds .in, +.animate-blinds.done, +.animate-blinds .in, +.animate-blinds.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + opacity: 1; + filter: alpha(opacity=100); } + +.animate-blinds .in, +.animate-blinds.done, +.animate-blinds .in, +.animate-blinds.done { + visibility: visible; } + +.animate-blinds.done .in, +.animate-blinds.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-blinds .has-mask-reverse:after, +.animate-blinds .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-blinds.done .has-mask-reverse:after, +.animate-blinds.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-blinds .out, +.animate-blinds .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Pan In Left +==================================*/ +.animate-pan-in-left, +.animate-pan-in-left { + background-position: 0% 0%; } + +/* Motion: Ripple +==================================*/ +.animate-ripple .done, +.animate-ripple .done { + visibility: hidden; } + +.animate-ripple .done, +.animate-ripple .done { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-ripple .item-bg-image img.background, +.animate-ripple .item-bg-image img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-ripple .in, .animate-ripple.done, +.animate-ripple .in, .animate-ripple.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-ripple .in, .animate-ripple.done, +.animate-ripple .in, .animate-ripple.done { + visibility: visible; } + +.animate-ripple .item { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); + opacity: 0; + filter: alpha(opacity=0); } + +.animate-ripple .item.in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-ripple .done { + visibility: hidden; } + +.animate-ripple .done, +.animate-ripple .done { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +/* Uncomment if you want images to fade in after the card + + .animate-ripple .in .item-bg-image img:last-child, + .animate-ripple .in .item-bg-image img:last-child { + opacity: 0; + } + + .animate-ripple.done .item-bg-image img:last-child, + .animate-ripple.done .item-bg-image img:last-child { + opacity: 1; + -moz-transition: all 1s ease-in-out; + -o-transition: all 1s ease-in-out; + -webkit-transition: all 1s ease-in-out; + transition: all 1s ease-in-out; + } + + .animate-ripple .item-bg-image img:last-child, + .animate-ripple .item-bg-image img:last-child { + box-shadow: none; + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + .animate-ripple .in .item-bg-image img:last-child, + .animate-ripple .in .item-bg-image img:last-child { + opacity: 0; + } + +.animate-ripple.done .item-bg-image img:last-child, +.animate-ripple.done .item-bg-image img:last-child { + opacity: 1; + -moz-transition: all 0.3s ease-in-out; + -o-transition: all 0.3s ease-in-out; + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; +} + +.animate-ripple .in, +.animate-ripple .in { + opacity: 0.6; +} +*/ +.animate-ripple .in, .animate-ripple.done, .animate-ripple .in, .animate-ripple.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-ripple .in, .animate-ripple.done, .animate-ripple .in, .animate-ripple.done { + visibility: visible; } + +.animate-ripple.done .in, .animate-ripple.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-ripple .has-mask-reverse:after, .animate-ripple .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-ripple.done .has-mask-reverse:after, .animate-ripple.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-ripple .out, .animate-ripple .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Slide / Fade In +==================================*/ +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + visibility: hidden; } + +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-fade-slide-in .item-bg-image img.background, +.animate-fade-slide-in .item-bg-image img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item { + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item { + visibility: visible; } + +.list .item.item-bg-image, +.list .item.item-bg-image { + max-height: 150px; } + +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + visibility: hidden; } + +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + -ms-transform: translate3d(-250px, 250px, 0); + -webkit-transform: translate3d(-250px, 250px, 0); + transform: translate3d(-250px, 250px, 0); + -webkit-transition: -webkit-transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 0; + filter: alpha(opacity=0); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done { + visibility: visible; } + +.animate-fade-slide-in.done .in, +.animate-fade-slide-in.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in .has-mask-reverse:after, +.animate-fade-slide-in .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-fade-slide-in.done .has-mask-reverse:after, +.animate-fade-slide-in.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in .out, +.animate-fade-slide-in .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Slide In Right +==================================*/ +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + visibility: hidden; } + +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-fade-slide-in-right .item-bg-image > img.background, +.animate-fade-slide-in-right .item-bg-image > img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done > *, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done > * { + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done .item, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done .item { + visibility: visible; } + +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + visibility: hidden; } + +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + -ms-transform: translate3d(250px, 250px, 0); + -webkit-transform: translate3d(250px, 250px, 0); + transform: translate3d(250px, 250px, 0); + -webkit-transition: -webkit-transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 0; + filter: alpha(opacity=0); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done { + visibility: visible; } + +.animate-fade-slide-in-right.done .in, +.animate-fade-slide-in-right.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in-right .has-mask-reverse:after, +.animate-fade-slide-in-right .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-fade-slide-in-right.done .has-mask-reverse:after, +.animate-fade-slide-in-right.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in-right .out, +.animate-fade-slide-in-right .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Slide Up +==================================*/ +.slide-up, +.slide-up, +.hero.slide-up { + height: 100%; + overflow: hidden; + text-align: center; } + +.slide-up { + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.slide-up *, +.slide-up *, +.hero.slide-up * { + opacity: 0; + filter: alpha(opacity=0); } + +.hero.slide-up + .mid-bar, +.slide-up + .mid-bar, +.slide-up + .mid-bar { + height: 100%; + opacity: 0.7; + filter: alpha(opacity=70); + -webkit-transform: translate3d(100%, -240px, 0); + transform: translate3d(100%, -240px, 0); } + +/*! + * Waves v0.5.4 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Forked by Zach Fitzgerald and other contributors for Ionic Material + * + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + * + */ +.ink, .button-fab, .button-flat, .button-raised, .button-clear, .popup .button { + position: relative; + cursor: pointer; + /*display: inline-block;*/ + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; } + +.ink-ripple { + position: absolute; + border-radius: 50%; + width: 100px; + height: 100px; + margin-top: -50px; + margin-left: -50px; + opacity: 0; + background-color: rgba(255, 255, 255, 0.4); + -webkit-transition: all 0.5s ease-out; + -moz-transition: all 0.5s ease-out; + -o-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; + -webkit-transition-property: -webkit-transform, opacity; + -moz-transition-property: -moz-transform, opacity; + -o-transition-property: -o-transform, opacity; + transition-property: transform, opacity; + -webkit-transform: scale(0); + -moz-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + pointer-events: none; } + +.ink-notransition { + -webkit-transition: none !important; + -moz-transition: none !important; + -o-transition: none !important; + transition: none !important; } + +.button-fab, +.button-flat, +.button-clear, +.button-raised, +.ink-button, +.ink-circle { + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); } + +.button-fab.activated, +.button-flat.activated, +.button-raised.activated, +.button-clear.activated, +.ink-button.activated, +.ink.activated, +.ink-circle.activated, +.popup .button.activated, +.button-fab:active, +.button-flat:active, +.button-raised:active, +.button-clear:active, +.ink-button:active, +.ink:active, +.ink-circle:active, +.popup .button:active { + -webkit-mask-image: -webkit-radial-gradient(circle, #ffffff 100%, #000000 100%); } + +.ink-button, +.ink-button:visited, +.ink-button:link, +.button-fab, +.button-fab:visited, +.button-fab:link, +.button-flat, +.button-flat:visited, +.button-flat:link, +.button-raised, +.button-raised:visited, +.button-raised:link, +.button-clear, +.button-clear:visited, +.button-clear:link, +.ink-button-input { + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + border: none; + outline: none; + /* color: inherit; */ + /* background-color: rgba(0, 0, 0, 0); */ + font-size: 14px; + text-align: center; + text-decoration: none; + z-index: 1; } + +.ink-button { + padding: 10px 15px; + border-radius: 2px; } + +.ink-button-input { + margin: 0; + padding: 10px 15px; } + +.ink-input-wrapper { + border-radius: 2px; + vertical-align: bottom; } + +.ink-input-wrapper.ink-button { + padding: 0; } + +.ink-input-wrapper .ink-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1; } + +.ink-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; } + +.ink-float { + -webkit-mask-image: none; + -webkit-box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); + box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); } + +.ink-float:active { + -webkit-box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); + box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); } + +.ink-block { + display: block; } + +.ink-ripple { + z-index: 0; + /* Firefox Bug: link not triggered unless -1 z-index */ } + +/* Handled elsewhere +.button-fab,.button-raised,.button-flat,.ink-circle,.list a.item { + -webkit-mask-image: none; +} +*/ +.button-clear .ink-ripple, +*[class$="-clear"] > .ink-ripple, +*[class$="-light"] > .ink-ripple, +*[class$="-stable"] > .ink-ripple, +*[class$="-100"] > .ink-ripple, +.list .ink-ripple, +.ink-dark .ink-ripple { + background-color: rgba(0, 0, 0, 0.2); } + +.tab-item { + position: relative; + /* for Ink */ } + +/* Ionic Overrides +==================================*/ +* { + font-family: "RobotoDraft","Roboto","Helvetica Neue", "Segoe UI", sans-serif; } + +.rounded { + border-radius: 4px; } + +a { + cursor: pointer; } + +.has-header.expanded { + /* Expanded modifier */ + top: 76px; } + +/* Bar Overrides +==================================*/ +.bar { + border-bottom: none; + padding: 0; } + +.bar .button { + min-height: 44px; + min-width: 44px; + max-width: 48px; + margin-bottom: 0; + max-height: 44px; + width: 48px; } + +.bar .title + .buttons.buttons-right { + right: 0; + top: 0; } + +/* Title Overrides +==================================*/ +.title-left, +.title.title-left { + left: 48px; } + +.title-right, +.title.title-right { + left: 48px; } + +/* Background Colors +==================================*/ +.positive-bg, +.button-positive, +.bar .button-positive, +.header-positive, +.button-bar-positive, +.bar-positive, +.positive-border, +.positive-bg:hover, +.bar .button-positive:hover, +.button-positive:hover, +.header-positive:hover, +.button-bar-positive:hover, +.bar-positive:hover, +.positive-border:hover, +.positive-bg:active, +.bar .button-positive:active, +.button-positive:active, +.header-positive:active, +.button-bar-positive:active, +.bar-positive:active, +.positive-border:active, +.positive-bg.activated, +.bar .button-positive.activated, +.button-positive.activated, +.header-positive.activated, +.button-bar-positive.activated, +.bar-positive.activated, +.positive-border.activated { + background-color: #3F51B5; + color: #fff; } + +.positive-900-bg, +.button-positive-900, +.bar .button-positive-900, +.header-positive-900, +.button-bar-positive-900, +.bar-positive-900, +.positive-900-border, +.positive-900-bg:hover, +.button-positive-900:hover, +.bar .button-positive-900:hover, +.header-positive-900:hover, +.button-bar-positive-900:hover, +.bar-positive-900:hover, +.positive-900-border:hover, +.positive-900-bg:active, +.bar .button-positive-900:active, +.button-positive-900:active, +.header-positive-900:active, +.button-bar-positive-900:active, +.bar-positive-900:active, +.positive-900-border:active, +.positive-900-bg.activated, +.button-positive-900.activated, +.bar .button-positive-900.activated, +.header-positive-900.activated, +.button-bar-positive-900.activated, +.bar-positive-900.activated, +.positive-900-border.activated { + background-color: #1A237E; + color: #fff; } + +.positive-100-bg, +.button-positive-100, +.bar .button-positive-100, +.header-positive-100, +.button-bar-positive-100, +.bar-positive-100, +.positive-100-border, +.positive-100-bg:hover, +.button-positive-100:hover, +.bar .button-positive-100:hover, +.header-positive-100:hover, +.button-bar-positive-100:hover, +.bar-positive-100:hover, +.positive-100-border:hover, +.positive-100-bg:active, +.button-positive-100:active, +.bar .button-positive-100:active, +.header-positive-100:active, +.button-bar-positive-100:active, +.bar-positive-100:active, +.positive-100-border:active, +.positive-100-bg.activated, +.button-positive-100.activated, +.bar .button-positive-100.activated, +.header-positive-100.activated, +.button-bar-positive-100.activated, +.bar-positive-100.activated, +.positive-100-border.activated { + background-color: #C5CAE9; + color: #fff; } + +.calm-bg, +.button-calm, +.bar .button-calm, +.header-calm, +.button-bar-calm, +.bar-calm, +.calm-border, +.calm-bg:hover, +.button-calm:hover, +.bar .button-calm:hover, +.header-calm:hover, +.button-bar-calm:hover, +.bar-calm:hover, +.calm-border:hover, +.calm-bg:active, +.button-calm:active, +.bar .button-calm:active, +.header-calm:active, +.button-bar-calm:active, +.bar-calm:active, +.calm-border:active, +.calm-bg.activated, +.button-calm.activated, +.bar .button-calm.activated, +.header-calm.activated, +.button-bar-calm.activated, +.bar-calm.activated, +.calm-border.activated { + background-color: #2196F3; + color: #fff; } + +.calm-900-bg, +.button-calm-900, +.bar .button-calm-900, +.header-calm-900, +.button-bar-calm-900, +.bar-calm-900, +.calm-900-border, +.calm-900-bg:hover, +.button-calm-900:hover, +.bar .button-calm-900:hover, +.header-calm-900:hover, +.button-bar-calm-900:hover, +.bar-calm-900:hover, +.calm-900-border:hover, +.calm-900-bg:active, +.button-calm-900:active, +.bar .button-calm-900:active, +.header-calm-900:active, +.button-bar-calm-900:active, +.bar-calm-900:active, +.calm-900-border:active, +.calm-900-bg.activated, +.button-calm-900.activated, +.bar .button-calm-900.activated, +.header-calm-900.activated, +.button-bar-calm-900.activated, +.bar-calm-900.activated, +.calm-900-border.activated { + background-color: #0D47A1; + color: #fff; } + +.calm-100-bg, +.button-calm-100, +.bar .button-calm-100, +.header-calm-100, +.button-bar-calm-100, +.bar-calm-100, +.calm-100-border, +.calm-100-bg:hover, +.button-calm-100:hover, +.bar .button-calm-100:hover, +.header-calm-100:hover, +.button-bar-calm-100:hover, +.bar-calm-100:hover, +.calm-100-border:hover, +.calm-100-bg:active, +.button-calm-100:active, +.bar .button-calm-100:active, +.header-calm-100:active, +.button-bar-calm-100:active, +.bar-calm-100:active, +.calm-100-border:active, +.calm-100-bg.activated, +.button-calm-100.activated, +.bar .button-calm-100.activated, +.header-calm-100.activated, +.button-bar-calm-100.activated, +.bar-calm-100.activated, +.calm-100-border.activated { + background-color: #BBDEFB; + color: #fff; } + +.royal-bg, +.button-royal, +.bar .button-royal, +.header-royal, +.button-bar-royal, +.bar-royal, +.royal-border, +.royal-bg:hover, +.button-royal:hover, +.bar .button-royal:hover, +.header-royal:hover, +.button-bar-royal:hover, +.bar-royal:hover, +.royal-border:hover, +.royal-bg:active, +.button-royal:active, +.bar .button-royal:active, +.header-royal:active, +.button-bar-royal:active, +.bar-royal:active, +.royal-border:active, +.royal-bg.activated, +.button-royal.activated, +.bar .button-royal.activated, +.header-royal.activated, +.button-bar-royal.activated, +.bar-royal.activated, +.royal-border.activated { + background-color: #673AB7; + color: #fff; } + +.royal-900-bg, +.button-royal-900, +.bar .button-royal-900, +.header-royal-900, +.button-bar-royal-900, +.bar-royal-900, +.royal-900-border, +.royal-900-bg:hover, +.button-royal-900:hover, +.bar .button-royal-900:hover, +.header-royal-900:hover, +.button-bar-royal-900:hover, +.bar-royal-900:hover, +.royal-900-border:hover, +.royal-900-bg:active, +.button-royal-900:active, +.bar .button-royal-900:active, +.header-royal-900:active, +.button-bar-royal-900:active, +.bar-royal-900:active, +.royal-900-border:active, +.royal-900-bg.activated, +.button-royal-900.activated, +.bar .button-royal-900.activated, +.header-royal-900.activated, +.button-bar-royal-900.activated, +.bar-royal-900.activated, +.royal-900-border.activated { + background-color: #311B92; + color: #fff; } + +.royal-100-bg, +.button-royal-100, +.bar .button-royal-100, +.header-royal-100, +.button-bar-royal-100, +.bar-royal-100, +.royal-100-border, +.royal-100-bg:hover, +.button-royal-100:hover, +.bar .button-royal-100:hover, +.header-royal-100:hover, +.button-bar-royal-100:hover, +.bar-royal-100:hover, +.royal-100-border:hover, +.royal-100-bg:active, +.button-royal-100:active, +.bar .button-royal-100:active, +.header-royal-100:active, +.button-bar-royal-100:active, +.bar-royal-100:active, +.royal-100-border:active, +.royal-100-bg.activated, +.button-royal-100.activated, +.bar .button-royal-100.activated, +.header-royal-100.activated, +.button-bar-royal-100.activated, +.bar-royal-100.activated, +.royal-100-border.activated { + background-color: #D1C4E9; + color: #fff; } + +.balanced-bg, +.button-balanced, +.bar .button-balanced, +.header-balanced, +.button-bar-balanced, +.bar-balanced, +.balanced-border, +.balanced-bg:hover, +.button-balanced:hover, +.bar .button-balanced:hover, +.header-balanced:hover, +.button-bar-balanced:hover, +.bar-balanced:hover, +.balanced-border:hover, +.balanced-bg:active, +.button-balanced:active, +.bar .button-balanced:active, +.header-balanced:active, +.button-bar-balanced:active, +.bar-balanced:active, +.balanced-border:active, +.balanced-bg.activated, +.button-balanced.activated, +.bar .button-balanced.activated, +.header-balanced.activated, +.button-bar-balanced.activated, +.bar-balanced.activated, +.balanced-border.activated { + background-color: #4CAF50; + color: #fff; } + +.balanced-900-bg, +.button-balanced-900, +.bar .button-balanced-900, +.header-balanced-900, +.button-bar-balanced-900, +.bar-balanced-900, +.balanced-900-border, +.balanced-900-bg:hover, +.button-balanced-900:hover, +.bar .button-balanced-900:hover, +.header-balanced-900:hover, +.button-bar-balanced-900:hover, +.bar-balanced-900:hover, +.balanced-900-border:hover, +.balanced-900-bg:active, +.button-balanced-900:active, +.bar .button-balanced-900:active, +.header-balanced-900:active, +.button-bar-balanced-900:active, +.bar-balanced-900:active, +.balanced-900-border:active, +.balanced-900-bg.activated, +.button-balanced-900.activated, +.bar .button-balanced-900.activated, +.header-balanced-900.activated, +.button-bar-balanced-900.activated, +.bar-balanced-900.activated, +.balanced-900-border.activated { + background-color: #1B5E20; + color: #fff; } + +.balanced-100-bg, +.button-balanced-100, +.bar .button-balanced-100, +.header-balanced-100, +.button-bar-balanced-100, +.bar-balanced-100, +.balanced-100-border, +.balanced-100-bg:hover, +.button-balanced-100:hover, +.bar .balanced-100-bg:hover, +.header-balanced-100:hover, +.button-bar-balanced-100:hover, +.bar-balanced-100:hover, +.balanced-100-border:hover, +.balanced-100-bg:active, +.button-balanced-100:active, +.bar .button-balanced-100:active, +.header-balanced-100:active, +.button-bar-balanced-100:active, +.bar-balanced-100:active, +.balanced-100-border:active, +.balanced-100-bg.activated, +.button-balanced-100.activated, +.bar .button-balanced-100.activated, +.header-balanced-100.activated, +.button-bar-balanced-100.activated, +.bar-balanced-100.activated, +.balanced-100-border.activated { + background-color: #C8E6C9; + color: #fff; } + +.energized-bg, +.button-energized, +.bar .button-energized, +.header-energized, +.button-bar-energized, +.bar-energized, +.energized-border, +.energized-bg:hover, +.button-energized:hover, +.bar .button-energized:hover, +.header-energized:hover, +.button-bar-energized:hover, +.bar-energized:hover, +.energized-border:hover, +.energized-bg:active, +.button-energized:active, +.bar .button-energized:active, +.header-energized:active, +.button-bar-energized:active, +.bar-energized:active, +.energized-border:active, +.energized-bg.activated, +.button-energized.activated, +.bar .button-energized.activated, +.header-energized.activated, +.button-bar-energized.activated, +.bar-energized.activated, +.energized-border.activated { + background-color: #FF9800; + color: #fff; } + +.energized-900-bg, +.button-energized-900, +.bar .button-energized-900, +.header-energized-900, +.button-bar-energized-900, +.bar-energized-900, +.energized-900-border, +.energized-900-bg:hover, +.button-energized-900:hover, +.bar .button-energized-900:hover, +.header-energized-900:hover, +.button-bar-energized-900:hover, +.bar-energized-900:hover, +.energized-900-border:hover, +.energized-900-bg:active, +.button-energized-900:active, +.bar .button-energized-900:active, +.header-energized-900:active, +.button-bar-energized-900:active, +.bar-energized-900:active, +.energized-900-border:active, +.energized-900-bg.activated, +.button-energized-900.activated, +.bar .button-energized-900.activated, +.header-energized-900.activated, +.button-bar-energized-900.activated, +.bar-energized-900.activated, +.energized-900-border.activated { + background-color: #E65100; + color: #fff; } + +.energized-100-bg, +.button-energized-100, +.bar .button-energized-100, +.header-energized-100, +.button-bar-energized-100, +.bar-energized-100, +.energized-100-border, +.energized-100-bg:hover, +.button-energized-100:hover, +.bar .button-energized-100:hover, +.header-energized-100:hover, +.button-bar-energized-100:hover, +.bar-energized-100:hover, +.energized-100-border:hover, +.energized-100-bg:active, +.button-energized-100:active, +.bar .button-energized-100:active, +.header-energized-100:active, +.button-bar-energized-100:active, +.bar-energized-100:active, +.energized-100-border:active, +.energized-100-bg.activated, +.button-energized-100.activated, +.bar .button-energized-100.activated, +.header-energized-100.activated, +.button-bar-energized-100.activated, +.bar-energized-100.activated, +.energized-100-border.activated { + background-color: #FFE0B2; } + +.assertive-bg, +.button-assertive, +.bar .button-assertive, +.header-assertive, +.button-bar-assertive, +.bar-assertive, +.assertive-border, +.assertive-bg:hover, +.button-assertive:hover, +.bar .button-assertive:hover, +.header-assertive:hover, +.button-bar-assertive:hover, +.bar-assertive:hover, +.assertive-border:hover, +.assertive-bg:active, +.button-assertive:active, +.bar .button-assertive:active, +.header-assertive:active, +.button-bar-assertive:active, +.bar-assertive:active, +.assertive-border:active, +.assertive-bg.activated, +.button-assertive.activated, +.bar .button-assertive.activated, +.header-assertive.activated, +.button-bar-assertive.activated, +.bar-assertive.activated, +.assertive-border.activated { + background-color: #F44336; + color: #fff; } + +.assertive-900-bg, +.button-assertive-900, +.bar .button-assertive-900, +.header-assertive-900, +.button-bar-assertive-900, +.bar-assertive-900, +.assertive-900-border, +.assertive-900-bg:hover, +.button-assertive-900:hover, +.bar .button-assertive-900:hover, +.header-assertive-900:hover, +.button-bar-assertive-900:hover, +.bar-assertive-900:hover, +.assertive-900-border:hover, +.assertive-900-bg:active, +.button-assertive-900:active, +.bar .button-assertive-900:active, +.header-assertive-900:active, +.button-bar-assertive-900:active, +.bar-assertive-900:active, +.assertive-900-border:active, +.assertive-900-bg.activated, +.button-assertive-900.activated, +.bar .button-assertive-900.activated, +.header-assertive-900.activated, +.button-bar-assertive-900.activated, +.bar-assertive-900.activated, +.assertive-900-border.activated { + background-color: #B71C1C; + color: #fff; } + +.assertive-100-bg, +.button-assertive-100, +.bar .button-assertive-100, +.header-assertive-100, +.button-bar-assertive-100, +.bar-assertive-100, +.assertive-100-border, +.assertive-100-bg:hover, +.button-assertive-100:hover, +.bar .button-assertive-100:hover, +.header-assertive-100:hover, +.button-bar-assertive-100:hover, +.bar-assertive-100:hover, +.assertive-100-border:hover, +.assertive-100-bg:active, +.button-assertive-100:active, +.bar .button-assertive-100:active, +.header-assertive-100:active, +.button-bar-assertive-100:active, +.bar-assertive-100:active, +.assertive-100-border:active, +.assertive-100-bg.activated, +.bar .button-assertive-100.activated, +.button-assertive-100.activated, +.header-assertive-100.activated, +.button-bar-assertive-100.activated, +.bar-assertive-100.activated, +.assertive-100-border.activated { + background-color: #FFCDD2; + color: #fff; } + +.stable-bg, +.button-stable, +.bar .button-stable, +.header-stable, +.button-bar-stable, +.bar-stable, +.stable-border, +.stable-bg:hover, +.button-stable:hover, +.bar .button-stable:hover, +.header-stable:hover, +.button-bar-stable:hover, +.bar-stable:hover, +.stable-border:hover, +.stable-bg:active, +.button-stable:active, +.bar .button-stable:active, +.header-stable:active, +.button-bar-stable:active, +.bar-stable:active, +.stable-border:active, +.stable-bg.activated, +.button-stable.activated, +.bar .button-stable.activated, +.header-stable.activated, +.button-bar-stable.activated, +.bar-stable.activated, +.stable-border.activated { + background-color: #E0E0E0; + color: #fff; } + +/* Text Colors +==================================*/ +.positive, +.positive *, +*.positive, +.positive:hover, +.positive:hover *, +*.positive:hover, +.positive:active, +.positive:active *, +*.positive:active { + color: #3F51B5; } + +.positive-900, +.positive-900 *, +*.positive-900, +.positive-900:hover, +.positive-900:hover *, +*.positive-900:hover, +.positive-900:active, +.positive-900:active *, +*.positive-900:active { + color: #3F51B5; } + +.positive-100, +.positive-100 *, +*.positive-100, +.positive-100:hover, +.positive-100:hover *, +*.positive-100:hover, +.positive-100:active, +.positive-100:active *, +*.positive-100:active { + color: #C5CAE9; } + +.calm-100, +.calm-100 *, +*.calm-100, +.calm-100:hover, +.calm-100:hover *, +*.calm-100:hover, +.calm-100:active, +.calm-100:active *, +*.calm-100:active { + color: #2196F3; } + +.calm-900, +.calm-900 *, +*.calm-900, +.calm-900:hover, +.calm-900:hover *, +*.calm-900:hover, +.calm-900:active, +.calm-900:active *, +*.calm-900:active { + color: #0D47A1; } + +.calm-100, +.calm-100 *, +*.calm-100, +.calm-100:hover, +.calm-100:hover *, +*.calm-100:hover, +.calm-100:active, +.calm-100:active *, +*.calm-100:active { + color: #BBDEFB; } + +.royal, +.royal *, +*.royal, +.royal:hover, +.royal:hover *, +*.royal:hover, +.royal:active, +.royal:active *, +*.royal:active { + color: #673AB7; } + +.royal-900, +.royal-900 *, +*.royal-900, +.royal-900:hover, +.royal-900:hover *, +*.royal-900:hover, +.royal-900:active, +.royal-900:active *, +*.royal-900:active { + color: #311B92; } + +.royal-100, +.royal-100 *, +*.royal-100, +.royal-100:hover, +.royal-100:hover *, +*.royal-100:hover, +.royal-100:active, +.royal-100:active *, +*.royal-100:active { + color: #D1C4E9; } + +.balanced, +.balanced *, +*.balanced, +.balanced:hover, +.balanced:hover *, +*.balanced:hover, +.balanced:active, +.balanced:active *, +*.balanced:active { + color: #4CAF50; } + +.balanced-900, +.balanced-900 *, +*.balanced-900, +.balanced-900:hover, +.balanced-900:hover *, +*.balanced-900:hover, +.balanced-900:active, +.balanced-900:active *, +*.balanced-900:active { + color: #1B5E20; } + +.balanced-100, +.balanced-100 *, +*.balanced-100, +.balanced-100:hover, +.balanced-100:hover *, +*.balanced-100:hover, +.balanced-100:active, +.balanced-100:active *, +*.balanced-100:active { + color: #C8E6C9; } + +.energized, +.energized *, +*.energized, +.energized:hover, +.energized:hover *, +*.energized:hover, +.energized:active, +.energized:active *, +*.energized:active { + color: #FF9800; } + +.energized-900, +.energized-900 *, +*.energized-900, +.energized-900:hover, +.energized-900:hover *, +*.energized-900:hover, +.energized-900:active, +.energized-900:active *, +*.energized-900:active { + color: #E65100; } + +.energized-100, +.energized-100 *, +*.energized-100, +.energized-100:hover, +.energized-100:hover *, +*.energized-100:hover, +.energized-100:active, +.energized-100:active *, +*.energized-100:active { + color: #FFE0B2; } + +.assertive, +.assertive *, +*.assertive, +.assertive:hover, +.assertive:hover *, +*.assertive:hover, +.assertive:active, +.assertive:active *, +*.assertive:active { + color: #F44336; } + +.assertive-900, +.assertive-900 *, +*.assertive-900, +.assertive-900:hover, +.assertive-900:hover *, +*.assertive-900:hover, +.assertive-900:active, +.assertive-900:active *, +*.assertive-900:active { + color: #B71C1C; } + +.assertive-100, +.assertive-100 *, +*.assertive-100, +.assertive-100:hover, +.assertive-100:hover *, +*.assertive-100:hover, +.assertive-100:active, +.assertive-100:active *, +*.assertive-100:active { + color: #FFCDD2; } + +.stable, +.stable *, +*.stable, +.stable:hover, +.stable:hover *, +*.stable:hover, +.stable:active, +.stable:active *, +*.stable:active { + color: #E0E0E0; } + +.light, +.light *, +*.light, +.light:hover, +.light:hover *, +*.light:hover, +.light:active, +.light:active *, +*.light:active { + color: #fff; } + +.dark, +.dark *, +*.dark, +.dark:hover, +.dark:hover *, +*.dark:hover, +.dark:active, +.dark:active *, +*.dark:active { + color: #444; } + +.light-border { + border-color: #ddd; } + +.navbar-default .navbar-nav > li > a { + margin: 0; + padding-right: 26px; + padding-left: 26px; + border-top: 3px solid transparent; + color: #BFD5C9; + opacity: 1; } + +/* Mid-Bar +==================================*/ +.mid-bar { + padding: 16px; } + +.mid-bar h1, +.mid-bar h2, +.mid-bar h3, +.mid-bar h4, +.mid-bar h5, +.mid-bar h6 { + color: #fff; + margin-bottom: 5px; } + +.mid-bar p { + color: rgba(255, 255, 255, 0.5); + margin-bottom: 0; } + +/* Item +==================================*/ +.item-avatar, +.item-avatar .item-content, +.item-avatar-left, +.item-avatar-left .item-content, +.card > .item-avatar { + padding-left: 95px; } + +.item, +.item-complex .item-content, +.item-radio .item-content { + background-color: transparent; } + +.dark-bg h2, +.item.dark-bg h2 { + color: #fff; } + +.tabs-striped .tabs { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); } + +.bar .button.button-clear { + color: #fff; } + +.bar .button.button-icon .icon:before, +.bar .button.button-icon.icon-left:before, +.bar .button.button-icon.icon-right:before, +.bar .button.button-icon:before { + vertical-align: top; + font-size: 24px; } + +.menu { + background-color: transparent; } + +.button-icon.button.active, +.button-icon.button.activated { + opacity: initial; } + +/* Popover +==================================*/ +.popover { + opacity: 0; + position: absolute; + right: 8px; + transform: translate(50%, -50%) scale(0, 0); + transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; + top: 8px; } + +.popover.ng-enter { + opacity: 1; + transform: translate(0, -14px) scale(1, 1); + transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; } + +.popover.ng-leave { + opacity: 0; + transform: translate(50%, -50%) scale(0, 0); + transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; } + +/* Button +==================================*/ +.button { + overflow: hidden !important; } + +@media screen and (max-width: 400px) { + @-ms-viewport { + width: 320px; } } + +@media screen and (max-width: 747px) { + .hidden-xs { + display: none !important; + visibility: hidden !important; } } + +@media screen and (min-width: 748px) { + .hidden-xs { + display: inherited; + visibility: visible !important; } } + +@media screen and (max-width: 747px) { + .visible-xs { + display: inherited; + visibility: visible !important; } } + +@media screen and (min-width: 748px) { + .visible-xs { + display: none !important; + visibility: hidden !important; } } + +@media screen and (max-width: 747px) { + .no-padding-xs { + padding: 0px !important; } } + +@media screen and (min-width: 748px) { + .no-padding-xs { + padding: inherited; } } + +@media screen and (max-width: 747px) { + .no-margin-xs { + margin: 0px !important; } } + +@media screen and (min-width: 748px) { + .no-margin-xs { + margin: inherited; } } + +@media screen and (max-width: 991px) and (min-width: 748px) { + .hidden-sm { + display: none !important; + visibility: hidden !important; } } + +@media screen and (min-width: 992px) { + .hidden-sm { + display: inherited; + visibility: visible !important; } } + +@media screen and (max-width: 747px) { + .hidden-sm { + display: inherited; + visibility: visible !important; } } + +@media screen and (max-width: 991px) { + .visible-sm { + display: inherited; + visibility: visible !important; } } + +@media screen and (min-width: 992px) { + .visible-sm { + display: none !important; + visibility: hidden !important; } } + +@media screen and (max-width: 747px) { + .visible-sm { + display: none !important; + visibility: hidden !important; } } + +@media screen and (max-width: 991px) { + body { + cursor: url("http://ionicframework.com/img/finger.png"), auto; } } + +@media screen and (min-width: 992px) { + body { + cursor: inherit; } } + +@media screen and (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + visibility: hidden !important; } } + +@media screen and (min-width: 1200px) { + .hidden-md { + display: inherit; + visibility: visible; } } + +@media screen and (max-width: 991px) { + .hidden-md { + display: inherit; + visibility: visible; } } + +@media screen and (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: inherit; + visibility: visible !important; } } + +@media screen and (min-width: 1200px) { + .visible-md { + display: none; + visibility: hidden; } } + +@media screen and (max-width: 991px) { + .visible-md { + display: none; + visibility: hidden; } } + +@media screen and (min-width: 1200px) { + .hidden-lg { + display: none !important; + visibility: hidden !important; } } + +@media screen and (max-width: 1199px) { + .hidden-lg { + display: inherited; + visibility: visible; } } + +@media screen and (min-width: 1200px) { + .visible-lg { + display: inherited; + visibility: visible !important; } } + +@media screen and (max-width: 1199px) { + .visible-lg { + display: none; + visibility: hidden; } } diff --git a/www/css/ionic.app.min.css b/www/css/ionic.app.min.css new file mode 100644 index 0000000000000000000000000000000000000000..f87a04d714ecf7ba94d6729bf0a64edae86cfcd9 --- /dev/null +++ b/www/css/ionic.app.min.css @@ -0,0 +1 @@ +@charset "UTF-8";@font-face{font-family:Ionicons;src:url(../lib/ionic/fonts/ionicons.eot?v=2.0.1);src:url(../lib/ionic/fonts/ionicons.eot?v=2.0.1#iefix) format("embedded-opentype"),url(../lib/ionic/fonts/ionicons.ttf?v=2.0.1) format("truetype"),url(../lib/ionic/fonts/ionicons.woff?v=2.0.1) format("woff"),url(../lib/ionic/fonts/ionicons.woff) format("woff"),url(../lib/ionic/fonts/ionicons.svg?v=2.0.1#Ionicons) format("svg");font-weight:400;font-style:normal}.ion,.ion-alert-circled:before,.ion-alert:before,.ion-android-add-circle:before,.ion-android-add:before,.ion-android-alarm-clock:before,.ion-android-alert:before,.ion-android-apps:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down:before,.ion-android-arrow-dropdown-circle:before,.ion-android-arrow-dropdown:before,.ion-android-arrow-dropleft-circle:before,.ion-android-arrow-dropleft:before,.ion-android-arrow-dropright-circle:before,.ion-android-arrow-dropright:before,.ion-android-arrow-dropup-circle:before,.ion-android-arrow-dropup:before,.ion-android-arrow-forward:before,.ion-android-arrow-up:before,.ion-android-attach:before,.ion-android-bar:before,.ion-android-bicycle:before,.ion-android-boat:before,.ion-android-bookmark:before,.ion-android-bulb:before,.ion-android-bus:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-cancel:before,.ion-android-car:before,.ion-android-cart:before,.ion-android-chat:before,.ion-android-checkbox-blank:before,.ion-android-checkbox-outline-blank:before,.ion-android-checkbox-outline:before,.ion-android-checkbox:before,.ion-android-checkmark-circle:before,.ion-android-clipboard:before,.ion-android-close:before,.ion-android-cloud-circle:before,.ion-android-cloud-done:before,.ion-android-cloud-outline:before,.ion-android-cloud:before,.ion-android-color-palette:before,.ion-android-compass:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-contract:before,.ion-android-create:before,.ion-android-delete:before,.ion-android-desktop:before,.ion-android-document:before,.ion-android-done-all:before,.ion-android-done:before,.ion-android-download:before,.ion-android-drafts:before,.ion-android-exit:before,.ion-android-expand:before,.ion-android-favorite-outline:before,.ion-android-favorite:before,.ion-android-film:before,.ion-android-folder-open:before,.ion-android-folder:before,.ion-android-funnel:before,.ion-android-globe:before,.ion-android-hand:before,.ion-android-hangout:before,.ion-android-happy:before,.ion-android-home:before,.ion-android-image:before,.ion-android-laptop:before,.ion-android-list:before,.ion-android-locate:before,.ion-android-lock:before,.ion-android-mail:before,.ion-android-map:before,.ion-android-menu:before,.ion-android-microphone-off:before,.ion-android-microphone:before,.ion-android-more-horizontal:before,.ion-android-more-vertical:before,.ion-android-navigate:before,.ion-android-notifications-none:before,.ion-android-notifications-off:before,.ion-android-notifications:before,.ion-android-open:before,.ion-android-options:before,.ion-android-people:before,.ion-android-person-add:before,.ion-android-person:before,.ion-android-phone-landscape:before,.ion-android-phone-portrait:before,.ion-android-pin:before,.ion-android-plane:before,.ion-android-playstore:before,.ion-android-print:before,.ion-android-radio-button-off:before,.ion-android-radio-button-on:before,.ion-android-refresh:before,.ion-android-remove-circle:before,.ion-android-remove:before,.ion-android-restaurant:before,.ion-android-sad:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share-alt:before,.ion-android-share:before,.ion-android-star-half:before,.ion-android-star-outline:before,.ion-android-star:before,.ion-android-stopwatch:before,.ion-android-subway:before,.ion-android-sunny:before,.ion-android-sync:before,.ion-android-textsms:before,.ion-android-time:before,.ion-android-train:before,.ion-android-unlock:before,.ion-android-upload:before,.ion-android-volume-down:before,.ion-android-volume-mute:before,.ion-android-volume-off:before,.ion-android-volume-up:before,.ion-android-walk:before,.ion-android-warning:before,.ion-android-watch:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-backspace-outline:before,.ion-backspace:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-bowtie:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox-working:before,.ion-chatbox:before,.ion-chatboxes:before,.ion-chatbubble-working:before,.ion-chatbubble:before,.ion-chatbubbles:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-checkmark:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close-circled:before,.ion-close-round:before,.ion-close:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code-download:before,.ion-code-working:before,.ion-code:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-crop:before,.ion-cube:before,.ion-disc:before,.ion-document-text:before,.ion-document:before,.ion-drag:before,.ion-earth:before,.ion-easel:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email-unread:before,.ion-email:before,.ion-erlenmeyer-flask-bubbles:before,.ion-erlenmeyer-flask:before,.ion-eye-disabled:before,.ion-eye:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash-off:before,.ion-flash:before,.ion-folder:before,.ion-fork-repo:before,.ion-fork:before,.ion-forward:before,.ion-funnel:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy-outline:before,.ion-happy:before,.ion-headphone:before,.ion-heart-broken:before,.ion-heart:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-help:before,.ion-home:before,.ion-icecream:before,.ion-image:before,.ion-images:before,.ion-information-circled:before,.ion-information:before,.ion-ionic:before,.ion-ios-alarm-outline:before,.ion-ios-alarm:before,.ion-ios-albums-outline:before,.ion-ios-albums:before,.ion-ios-americanfootball-outline:before,.ion-ios-americanfootball:before,.ion-ios-analytics-outline:before,.ion-ios-analytics:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-left:before,.ion-ios-arrow-right:before,.ion-ios-arrow-thin-down:before,.ion-ios-arrow-thin-left:before,.ion-ios-arrow-thin-right:before,.ion-ios-arrow-thin-up:before,.ion-ios-arrow-up:before,.ion-ios-at-outline:before,.ion-ios-at:before,.ion-ios-barcode-outline:before,.ion-ios-barcode:before,.ion-ios-baseball-outline:before,.ion-ios-baseball:before,.ion-ios-basketball-outline:before,.ion-ios-basketball:before,.ion-ios-bell-outline:before,.ion-ios-bell:before,.ion-ios-body-outline:before,.ion-ios-body:before,.ion-ios-bolt-outline:before,.ion-ios-bolt:before,.ion-ios-book-outline:before,.ion-ios-book:before,.ion-ios-bookmarks-outline:before,.ion-ios-bookmarks:before,.ion-ios-box-outline:before,.ion-ios-box:before,.ion-ios-briefcase-outline:before,.ion-ios-briefcase:before,.ion-ios-browsers-outline:before,.ion-ios-browsers:before,.ion-ios-calculator-outline:before,.ion-ios-calculator:before,.ion-ios-calendar-outline:before,.ion-ios-calendar:before,.ion-ios-camera-outline:before,.ion-ios-camera:before,.ion-ios-cart-outline:before,.ion-ios-cart:before,.ion-ios-chatboxes-outline:before,.ion-ios-chatboxes:before,.ion-ios-chatbubble-outline:before,.ion-ios-chatbubble:before,.ion-ios-checkmark-empty:before,.ion-ios-checkmark-outline:before,.ion-ios-checkmark:before,.ion-ios-circle-filled:before,.ion-ios-circle-outline:before,.ion-ios-clock-outline:before,.ion-ios-clock:before,.ion-ios-close-empty:before,.ion-ios-close-outline:before,.ion-ios-close:before,.ion-ios-cloud-download-outline:before,.ion-ios-cloud-download:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloud:before,.ion-ios-cloudy-night-outline:before,.ion-ios-cloudy-night:before,.ion-ios-cloudy-outline:before,.ion-ios-cloudy:before,.ion-ios-cog-outline:before,.ion-ios-cog:before,.ion-ios-color-filter-outline:before,.ion-ios-color-filter:before,.ion-ios-color-wand-outline:before,.ion-ios-color-wand:before,.ion-ios-compose-outline:before,.ion-ios-compose:before,.ion-ios-contact-outline:before,.ion-ios-contact:before,.ion-ios-copy-outline:before,.ion-ios-copy:before,.ion-ios-crop-strong:before,.ion-ios-crop:before,.ion-ios-download-outline:before,.ion-ios-download:before,.ion-ios-drag:before,.ion-ios-email-outline:before,.ion-ios-email:before,.ion-ios-eye-outline:before,.ion-ios-eye:before,.ion-ios-fastforward-outline:before,.ion-ios-fastforward:before,.ion-ios-filing-outline:before,.ion-ios-filing:before,.ion-ios-film-outline:before,.ion-ios-film:before,.ion-ios-flag-outline:before,.ion-ios-flag:before,.ion-ios-flame-outline:before,.ion-ios-flame:before,.ion-ios-flask-outline:before,.ion-ios-flask:before,.ion-ios-flower-outline:before,.ion-ios-flower:before,.ion-ios-folder-outline:before,.ion-ios-folder:before,.ion-ios-football-outline:before,.ion-ios-football:before,.ion-ios-game-controller-a-outline:before,.ion-ios-game-controller-a:before,.ion-ios-game-controller-b-outline:before,.ion-ios-game-controller-b:before,.ion-ios-gear-outline:before,.ion-ios-gear:before,.ion-ios-glasses-outline:before,.ion-ios-glasses:before,.ion-ios-grid-view-outline:before,.ion-ios-grid-view:before,.ion-ios-heart-outline:before,.ion-ios-heart:before,.ion-ios-help-empty:before,.ion-ios-help-outline:before,.ion-ios-help:before,.ion-ios-home-outline:before,.ion-ios-home:before,.ion-ios-infinite-outline:before,.ion-ios-infinite:before,.ion-ios-information-empty:before,.ion-ios-information-outline:before,.ion-ios-information:before,.ion-ios-ionic-outline:before,.ion-ios-keypad-outline:before,.ion-ios-keypad:before,.ion-ios-lightbulb-outline:before,.ion-ios-lightbulb:before,.ion-ios-list-outline:before,.ion-ios-list:before,.ion-ios-location-outline:before,.ion-ios-location:before,.ion-ios-locked-outline:before,.ion-ios-locked:before,.ion-ios-loop-strong:before,.ion-ios-loop:before,.ion-ios-medical-outline:before,.ion-ios-medical:before,.ion-ios-medkit-outline:before,.ion-ios-medkit:before,.ion-ios-mic-off:before,.ion-ios-mic-outline:before,.ion-ios-mic:before,.ion-ios-minus-empty:before,.ion-ios-minus-outline:before,.ion-ios-minus:before,.ion-ios-monitor-outline:before,.ion-ios-monitor:before,.ion-ios-moon-outline:before,.ion-ios-moon:before,.ion-ios-more-outline:before,.ion-ios-more:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate-outline:before,.ion-ios-navigate:before,.ion-ios-nutrition-outline:before,.ion-ios-nutrition:before,.ion-ios-paper-outline:before,.ion-ios-paper:before,.ion-ios-paperplane-outline:before,.ion-ios-paperplane:before,.ion-ios-partlysunny-outline:before,.ion-ios-partlysunny:before,.ion-ios-pause-outline:before,.ion-ios-pause:before,.ion-ios-paw-outline:before,.ion-ios-paw:before,.ion-ios-people-outline:before,.ion-ios-people:before,.ion-ios-person-outline:before,.ion-ios-person:before,.ion-ios-personadd-outline:before,.ion-ios-personadd:before,.ion-ios-photos-outline:before,.ion-ios-photos:before,.ion-ios-pie-outline:before,.ion-ios-pie:before,.ion-ios-pint-outline:before,.ion-ios-pint:before,.ion-ios-play-outline:before,.ion-ios-play:before,.ion-ios-plus-empty:before,.ion-ios-plus-outline:before,.ion-ios-plus:before,.ion-ios-pricetag-outline:before,.ion-ios-pricetag:before,.ion-ios-pricetags-outline:before,.ion-ios-pricetags:before,.ion-ios-printer-outline:before,.ion-ios-printer:before,.ion-ios-pulse-strong:before,.ion-ios-pulse:before,.ion-ios-rainy-outline:before,.ion-ios-rainy:before,.ion-ios-recording-outline:before,.ion-ios-recording:before,.ion-ios-redo-outline:before,.ion-ios-redo:before,.ion-ios-refresh-empty:before,.ion-ios-refresh-outline:before,.ion-ios-refresh:before,.ion-ios-reload:before,.ion-ios-reverse-camera-outline:before,.ion-ios-reverse-camera:before,.ion-ios-rewind-outline:before,.ion-ios-rewind:before,.ion-ios-rose-outline:before,.ion-ios-rose:before,.ion-ios-search-strong:before,.ion-ios-search:before,.ion-ios-settings-strong:before,.ion-ios-settings:before,.ion-ios-shuffle-strong:before,.ion-ios-shuffle:before,.ion-ios-skipbackward-outline:before,.ion-ios-skipbackward:before,.ion-ios-skipforward-outline:before,.ion-ios-skipforward:before,.ion-ios-snowy:before,.ion-ios-speedometer-outline:before,.ion-ios-speedometer:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-star:before,.ion-ios-stopwatch-outline:before,.ion-ios-stopwatch:before,.ion-ios-sunny-outline:before,.ion-ios-sunny:before,.ion-ios-telephone-outline:before,.ion-ios-telephone:before,.ion-ios-tennisball-outline:before,.ion-ios-tennisball:before,.ion-ios-thunderstorm-outline:before,.ion-ios-thunderstorm:before,.ion-ios-time-outline:before,.ion-ios-time:before,.ion-ios-timer-outline:before,.ion-ios-timer:before,.ion-ios-toggle-outline:before,.ion-ios-toggle:before,.ion-ios-trash-outline:before,.ion-ios-trash:before,.ion-ios-undo-outline:before,.ion-ios-undo:before,.ion-ios-unlocked-outline:before,.ion-ios-unlocked:before,.ion-ios-upload-outline:before,.ion-ios-upload:before,.ion-ios-videocam-outline:before,.ion-ios-videocam:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-wineglass-outline:before,.ion-ios-wineglass:before,.ion-ios-world-outline:before,.ion-ios-world:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-lock-combination:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-minus:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon-round:before,.ion-navicon:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paintbrush:before,.ion-paintbucket:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person-add:before,.ion-person-stalker:before,.ion-person:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-plus:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply-all:before,.ion-reply:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad-outline:before,.ion-sad:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android-outline:before,.ion-social-android:before,.ion-social-angular-outline:before,.ion-social-angular:before,.ion-social-apple-outline:before,.ion-social-apple:before,.ion-social-bitcoin-outline:before,.ion-social-bitcoin:before,.ion-social-buffer-outline:before,.ion-social-buffer:before,.ion-social-chrome-outline:before,.ion-social-chrome:before,.ion-social-codepen-outline:before,.ion-social-codepen:before,.ion-social-css3-outline:before,.ion-social-css3:before,.ion-social-designernews-outline:before,.ion-social-designernews:before,.ion-social-dribbble-outline:before,.ion-social-dribbble:before,.ion-social-dropbox-outline:before,.ion-social-dropbox:before,.ion-social-euro-outline:before,.ion-social-euro:before,.ion-social-facebook-outline:before,.ion-social-facebook:before,.ion-social-foursquare-outline:before,.ion-social-foursquare:before,.ion-social-freebsd-devil:before,.ion-social-github-outline:before,.ion-social-github:before,.ion-social-google-outline:before,.ion-social-google:before,.ion-social-googleplus-outline:before,.ion-social-googleplus:before,.ion-social-hackernews-outline:before,.ion-social-hackernews:before,.ion-social-html5-outline:before,.ion-social-html5:before,.ion-social-instagram-outline:before,.ion-social-instagram:before,.ion-social-javascript-outline:before,.ion-social-javascript:before,.ion-social-linkedin-outline:before,.ion-social-linkedin:before,.ion-social-markdown:before,.ion-social-nodejs:before,.ion-social-octocat:before,.ion-social-pinterest-outline:before,.ion-social-pinterest:before,.ion-social-python:before,.ion-social-reddit-outline:before,.ion-social-reddit:before,.ion-social-rss-outline:before,.ion-social-rss:before,.ion-social-sass:before,.ion-social-skype-outline:before,.ion-social-skype:before,.ion-social-snapchat-outline:before,.ion-social-snapchat:before,.ion-social-tumblr-outline:before,.ion-social-tumblr:before,.ion-social-tux:before,.ion-social-twitch-outline:before,.ion-social-twitch:before,.ion-social-twitter-outline:before,.ion-social-twitter:before,.ion-social-usd-outline:before,.ion-social-usd:before,.ion-social-vimeo-outline:before,.ion-social-vimeo:before,.ion-social-whatsapp-outline:before,.ion-social-whatsapp:before,.ion-social-windows-outline:before,.ion-social-windows:before,.ion-social-wordpress-outline:before,.ion-social-wordpress:before,.ion-social-yahoo-outline:before,.ion-social-yahoo:before,.ion-social-yen-outline:before,.ion-social-yen:before,.ion-social-youtube-outline:before,.ion-social-youtube:before,.ion-soup-can-outline:before,.ion-soup-can:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle-filled:before,.ion-toggle:before,.ion-transgender:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-tshirt-outline:before,.ion-tshirt:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before,.ionicons{display:inline-block;font-family:Ionicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-alert:before{content:"ï„"}.ion-alert-circled:before{content:"ï„€"}.ion-android-add:before{content:""}.ion-android-add-circle:before{content:"ï™"}.ion-android-alarm-clock:before{content:"ïš"}.ion-android-alert:before{content:"ï›"}.ion-android-apps:before{content:"ïœ"}.ion-android-archive:before{content:""}.ion-android-arrow-back:before{content:""}.ion-android-arrow-down:before{content:"ï"}.ion-android-arrow-dropdown:before{content:"ïŸ"}.ion-android-arrow-dropdown-circle:before{content:"ïž"}.ion-android-arrow-dropleft:before{content:"ï¡"}.ion-android-arrow-dropleft-circle:before{content:"ï "}.ion-android-arrow-dropright:before{content:"ï£"}.ion-android-arrow-dropright-circle:before{content:"ï¢"}.ion-android-arrow-dropup:before{content:"ï¥"}.ion-android-arrow-dropup-circle:before{content:"ï¤"}.ion-android-arrow-forward:before{content:"ïŒ"}.ion-android-arrow-up:before{content:"ï¦"}.ion-android-attach:before{content:"ï§"}.ion-android-bar:before{content:"ï¨"}.ion-android-bicycle:before{content:"ï©"}.ion-android-boat:before{content:"ïª"}.ion-android-bookmark:before{content:"ï«"}.ion-android-bulb:before{content:"ï¬"}.ion-android-bus:before{content:"ï"}.ion-android-calendar:before{content:"ï‹‘"}.ion-android-call:before{content:"ï‹’"}.ion-android-camera:before{content:"ï‹“"}.ion-android-cancel:before{content:"ï®"}.ion-android-car:before{content:"ï¯"}.ion-android-cart:before{content:"ï°"}.ion-android-chat:before{content:"ï‹”"}.ion-android-checkbox:before{content:"ï´"}.ion-android-checkbox-blank:before{content:"ï±"}.ion-android-checkbox-outline:before{content:"ï³"}.ion-android-checkbox-outline-blank:before{content:"ï²"}.ion-android-checkmark-circle:before{content:"ïµ"}.ion-android-clipboard:before{content:"ï¶"}.ion-android-close:before{content:"ï‹—"}.ion-android-cloud:before{content:"ïº"}.ion-android-cloud-circle:before{content:"ï·"}.ion-android-cloud-done:before{content:"ï¸"}.ion-android-cloud-outline:before{content:"ï¹"}.ion-android-color-palette:before{content:"ï»"}.ion-android-compass:before{content:"ï¼"}.ion-android-contact:before{content:""}.ion-android-contacts:before{content:"ï‹™"}.ion-android-contract:before{content:"ï½"}.ion-android-create:before{content:"ï¾"}.ion-android-delete:before{content:"ï¿"}.ion-android-desktop:before{content:""}.ion-android-document:before{content:"ïŽ"}.ion-android-done:before{content:""}.ion-android-done-all:before{content:""}.ion-android-download:before{content:"ï‹"}.ion-android-drafts:before{content:""}.ion-android-exit:before{content:""}.ion-android-expand:before{content:""}.ion-android-favorite:before{content:""}.ion-android-favorite-outline:before{content:""}.ion-android-film:before{content:""}.ion-android-folder:before{content:"ï‹ "}.ion-android-folder-open:before{content:""}.ion-android-funnel:before{content:""}.ion-android-globe:before{content:""}.ion-android-hand:before{content:"ï‹£"}.ion-android-hangout:before{content:"ïŽ"}.ion-android-happy:before{content:""}.ion-android-home:before{content:"ïŽ"}.ion-android-image:before{content:""}.ion-android-laptop:before{content:"ïŽ"}.ion-android-list:before{content:""}.ion-android-locate:before{content:"ï‹©"}.ion-android-lock:before{content:""}.ion-android-mail:before{content:"ï‹«"}.ion-android-map:before{content:""}.ion-android-menu:before{content:""}.ion-android-microphone:before{content:""}.ion-android-microphone-off:before{content:""}.ion-android-more-horizontal:before{content:""}.ion-android-more-vertical:before{content:""}.ion-android-navigate:before{content:""}.ion-android-notifications:before{content:""}.ion-android-notifications-none:before{content:""}.ion-android-notifications-off:before{content:""}.ion-android-open:before{content:""}.ion-android-options:before{content:"ïŽ"}.ion-android-people:before{content:""}.ion-android-person:before{content:"ïŽ "}.ion-android-person-add:before{content:""}.ion-android-phone-landscape:before{content:""}.ion-android-phone-portrait:before{content:""}.ion-android-pin:before{content:""}.ion-android-plane:before{content:""}.ion-android-playstore:before{content:"ï‹°"}.ion-android-print:before{content:""}.ion-android-radio-button-off:before{content:""}.ion-android-radio-button-on:before{content:""}.ion-android-refresh:before{content:""}.ion-android-remove:before{content:"ï‹´"}.ion-android-remove-circle:before{content:""}.ion-android-restaurant:before{content:""}.ion-android-sad:before{content:""}.ion-android-search:before{content:""}.ion-android-send:before{content:"ï‹¶"}.ion-android-settings:before{content:"ï‹·"}.ion-android-share:before{content:""}.ion-android-share-alt:before{content:""}.ion-android-star:before{content:""}.ion-android-star-half:before{content:"ïŽ"}.ion-android-star-outline:before{content:""}.ion-android-stopwatch:before{content:""}.ion-android-subway:before{content:""}.ion-android-sunny:before{content:""}.ion-android-sync:before{content:""}.ion-android-textsms:before{content:""}.ion-android-time:before{content:""}.ion-android-train:before{content:""}.ion-android-unlock:before{content:""}.ion-android-upload:before{content:""}.ion-android-volume-down:before{content:""}.ion-android-volume-mute:before{content:""}.ion-android-volume-off:before{content:""}.ion-android-volume-up:before{content:""}.ion-android-walk:before{content:""}.ion-android-warning:before{content:""}.ion-android-watch:before{content:""}.ion-android-wifi:before{content:""}.ion-aperture:before{content:""}.ion-archive:before{content:"ï„‚"}.ion-arrow-down-a:before{content:""}.ion-arrow-down-b:before{content:"ï„„"}.ion-arrow-down-c:before{content:"ï„…"}.ion-arrow-expand:before{content:""}.ion-arrow-graph-down-left:before{content:""}.ion-arrow-graph-down-right:before{content:"ï‰ "}.ion-arrow-graph-up-left:before{content:""}.ion-arrow-graph-up-right:before{content:""}.ion-arrow-left-a:before{content:""}.ion-arrow-left-b:before{content:""}.ion-arrow-left-c:before{content:""}.ion-arrow-move:before{content:""}.ion-arrow-resize:before{content:""}.ion-arrow-return-left:before{content:""}.ion-arrow-return-right:before{content:""}.ion-arrow-right-a:before{content:""}.ion-arrow-right-b:before{content:""}.ion-arrow-right-c:before{content:"ï„‹"}.ion-arrow-shrink:before{content:""}.ion-arrow-swap:before{content:""}.ion-arrow-up-a:before{content:""}.ion-arrow-up-b:before{content:"ï„"}.ion-arrow-up-c:before{content:""}.ion-asterisk:before{content:""}.ion-at:before{content:"ï„"}.ion-backspace:before{content:""}.ion-backspace-outline:before{content:""}.ion-bag:before{content:"ï„"}.ion-battery-charging:before{content:"ï„‘"}.ion-battery-empty:before{content:"ï„’"}.ion-battery-full:before{content:"ï„“"}.ion-battery-half:before{content:"ï„”"}.ion-battery-low:before{content:"ï„•"}.ion-beaker:before{content:""}.ion-beer:before{content:""}.ion-bluetooth:before{content:"ï„–"}.ion-bonfire:before{content:""}.ion-bookmark:before{content:""}.ion-bowtie:before{content:"ï€"}.ion-briefcase:before{content:""}.ion-bug:before{content:""}.ion-calculator:before{content:"ï‰"}.ion-calendar:before{content:"ï„—"}.ion-camera:before{content:""}.ion-card:before{content:"ï„™"}.ion-cash:before{content:""}.ion-chatbox:before{content:"ï„›"}.ion-chatbox-working:before{content:""}.ion-chatboxes:before{content:""}.ion-chatbubble:before{content:""}.ion-chatbubble-working:before{content:"ï„"}.ion-chatbubbles:before{content:""}.ion-checkmark:before{content:"ï„¢"}.ion-checkmark-circled:before{content:"ï„ "}.ion-checkmark-round:before{content:"ï„¡"}.ion-chevron-down:before{content:"ï„£"}.ion-chevron-left:before{content:""}.ion-chevron-right:before{content:"ï„¥"}.ion-chevron-up:before{content:""}.ion-clipboard:before{content:"ï„§"}.ion-clock:before{content:""}.ion-close:before{content:""}.ion-close-circled:before{content:""}.ion-close-round:before{content:"ï„©"}.ion-closed-captioning:before{content:""}.ion-cloud:before{content:"ï„«"}.ion-code:before{content:""}.ion-code-download:before{content:""}.ion-code-working:before{content:""}.ion-coffee:before{content:""}.ion-compass:before{content:""}.ion-compose:before{content:""}.ion-connection-bars:before{content:""}.ion-contrast:before{content:""}.ion-crop:before{content:"ï"}.ion-cube:before{content:""}.ion-disc:before{content:"ï„"}.ion-document:before{content:""}.ion-document-text:before{content:"ï„®"}.ion-drag:before{content:"ï„°"}.ion-earth:before{content:""}.ion-easel:before{content:"ï‚"}.ion-edit:before{content:""}.ion-egg:before{content:""}.ion-eject:before{content:""}.ion-email:before{content:""}.ion-email-unread:before{content:"ïƒ"}.ion-erlenmeyer-flask:before{content:"ï…"}.ion-erlenmeyer-flask-bubbles:before{content:"ï„"}.ion-eye:before{content:""}.ion-eye-disabled:before{content:""}.ion-female:before{content:""}.ion-filing:before{content:"ï„´"}.ion-film-marker:before{content:""}.ion-fireball:before{content:""}.ion-flag:before{content:""}.ion-flame:before{content:""}.ion-flash:before{content:"ï„·"}.ion-flash-off:before{content:"ï„¶"}.ion-folder:before{content:""}.ion-fork:before{content:""}.ion-fork-repo:before{content:"ï‹€"}.ion-forward:before{content:""}.ion-funnel:before{content:""}.ion-gear-a:before{content:""}.ion-gear-b:before{content:""}.ion-grid:before{content:"ï„¿"}.ion-hammer:before{content:""}.ion-happy:before{content:""}.ion-happy-outline:before{content:"ï†"}.ion-headphone:before{content:"ï…€"}.ion-heart:before{content:"ï…"}.ion-heart-broken:before{content:"ïŒ"}.ion-help:before{content:"ï…ƒ"}.ion-help-buoy:before{content:""}.ion-help-circled:before{content:"ï…‚"}.ion-home:before{content:"ï…„"}.ion-icecream:before{content:""}.ion-image:before{content:"ï…‡"}.ion-images:before{content:"ï…ˆ"}.ion-information:before{content:"ï…Š"}.ion-information-circled:before{content:"ï…‰"}.ion-ionic:before{content:"ï…‹"}.ion-ios-alarm:before{content:"ïˆ"}.ion-ios-alarm-outline:before{content:"ï‡"}.ion-ios-albums:before{content:"ïŠ"}.ion-ios-albums-outline:before{content:"ï‰"}.ion-ios-americanfootball:before{content:"ïŒ"}.ion-ios-americanfootball-outline:before{content:"ï‹"}.ion-ios-analytics:before{content:"ïŽ"}.ion-ios-analytics-outline:before{content:"ï"}.ion-ios-arrow-back:before{content:"ï"}.ion-ios-arrow-down:before{content:"ï"}.ion-ios-arrow-forward:before{content:"ï‘"}.ion-ios-arrow-left:before{content:"ï’"}.ion-ios-arrow-right:before{content:"ï“"}.ion-ios-arrow-thin-down:before{content:"ï”"}.ion-ios-arrow-thin-left:before{content:"ï•"}.ion-ios-arrow-thin-right:before{content:"ï–"}.ion-ios-arrow-thin-up:before{content:"ï—"}.ion-ios-arrow-up:before{content:"ï˜"}.ion-ios-at:before{content:"ïš"}.ion-ios-at-outline:before{content:"ï™"}.ion-ios-barcode:before{content:"ïœ"}.ion-ios-barcode-outline:before{content:"ï›"}.ion-ios-baseball:before{content:"ïž"}.ion-ios-baseball-outline:before{content:"ï"}.ion-ios-basketball:before{content:"ï "}.ion-ios-basketball-outline:before{content:"ïŸ"}.ion-ios-bell:before{content:"ï¢"}.ion-ios-bell-outline:before{content:"ï¡"}.ion-ios-body:before{content:"ï¤"}.ion-ios-body-outline:before{content:"ï£"}.ion-ios-bolt:before{content:"ï¦"}.ion-ios-bolt-outline:before{content:"ï¥"}.ion-ios-book:before{content:"ï¨"}.ion-ios-book-outline:before{content:"ï§"}.ion-ios-bookmarks:before{content:"ïª"}.ion-ios-bookmarks-outline:before{content:"ï©"}.ion-ios-box:before{content:"ï¬"}.ion-ios-box-outline:before{content:"ï«"}.ion-ios-briefcase:before{content:"ï®"}.ion-ios-briefcase-outline:before{content:"ï"}.ion-ios-browsers:before{content:"ï°"}.ion-ios-browsers-outline:before{content:"ï¯"}.ion-ios-calculator:before{content:"ï²"}.ion-ios-calculator-outline:before{content:"ï±"}.ion-ios-calendar:before{content:"ï´"}.ion-ios-calendar-outline:before{content:"ï³"}.ion-ios-camera:before{content:"ï¶"}.ion-ios-camera-outline:before{content:"ïµ"}.ion-ios-cart:before{content:"ï¸"}.ion-ios-cart-outline:before{content:"ï·"}.ion-ios-chatboxes:before{content:"ïº"}.ion-ios-chatboxes-outline:before{content:"ï¹"}.ion-ios-chatbubble:before{content:"ï¼"}.ion-ios-chatbubble-outline:before{content:"ï»"}.ion-ios-checkmark:before{content:"ï¿"}.ion-ios-checkmark-empty:before{content:"ï½"}.ion-ios-checkmark-outline:before{content:"ï¾"}.ion-ios-circle-filled:before{content:"ï€"}.ion-ios-circle-outline:before{content:"ï"}.ion-ios-clock:before{content:"ïƒ"}.ion-ios-clock-outline:before{content:"ï‚"}.ion-ios-close:before{content:"ï†"}.ion-ios-close-empty:before{content:"ï„"}.ion-ios-close-outline:before{content:"ï…"}.ion-ios-cloud:before{content:"ïŒ"}.ion-ios-cloud-download:before{content:"ïˆ"}.ion-ios-cloud-download-outline:before{content:"ï‡"}.ion-ios-cloud-outline:before{content:"ï‰"}.ion-ios-cloud-upload:before{content:"ï‹"}.ion-ios-cloud-upload-outline:before{content:"ïŠ"}.ion-ios-cloudy:before{content:"ï"}.ion-ios-cloudy-night:before{content:"ïŽ"}.ion-ios-cloudy-night-outline:before{content:"ï"}.ion-ios-cloudy-outline:before{content:"ï"}.ion-ios-cog:before{content:"ï’"}.ion-ios-cog-outline:before{content:"ï‘"}.ion-ios-color-filter:before{content:"ï”"}.ion-ios-color-filter-outline:before{content:"ï“"}.ion-ios-color-wand:before{content:"ï–"}.ion-ios-color-wand-outline:before{content:"ï•"}.ion-ios-compose:before{content:"ï˜"}.ion-ios-compose-outline:before{content:"ï—"}.ion-ios-contact:before{content:"ïš"}.ion-ios-contact-outline:before{content:"ï™"}.ion-ios-copy:before{content:"ïœ"}.ion-ios-copy-outline:before{content:"ï›"}.ion-ios-crop:before{content:"ïž"}.ion-ios-crop-strong:before{content:"ï"}.ion-ios-download:before{content:"ï "}.ion-ios-download-outline:before{content:"ïŸ"}.ion-ios-drag:before{content:"ï¡"}.ion-ios-email:before{content:"ï£"}.ion-ios-email-outline:before{content:"ï¢"}.ion-ios-eye:before{content:"ï¥"}.ion-ios-eye-outline:before{content:"ï¤"}.ion-ios-fastforward:before{content:"ï§"}.ion-ios-fastforward-outline:before{content:"ï¦"}.ion-ios-filing:before{content:"ï©"}.ion-ios-filing-outline:before{content:"ï¨"}.ion-ios-film:before{content:"ï«"}.ion-ios-film-outline:before{content:"ïª"}.ion-ios-flag:before{content:"ï"}.ion-ios-flag-outline:before{content:"ï¬"}.ion-ios-flame:before{content:"ï¯"}.ion-ios-flame-outline:before{content:"ï®"}.ion-ios-flask:before{content:"ï±"}.ion-ios-flask-outline:before{content:"ï°"}.ion-ios-flower:before{content:"ï³"}.ion-ios-flower-outline:before{content:"ï²"}.ion-ios-folder:before{content:"ïµ"}.ion-ios-folder-outline:before{content:"ï´"}.ion-ios-football:before{content:"ï·"}.ion-ios-football-outline:before{content:"ï¶"}.ion-ios-game-controller-a:before{content:"ï¹"}.ion-ios-game-controller-a-outline:before{content:"ï¸"}.ion-ios-game-controller-b:before{content:"ï»"}.ion-ios-game-controller-b-outline:before{content:"ïº"}.ion-ios-gear:before{content:"ï½"}.ion-ios-gear-outline:before{content:"ï¼"}.ion-ios-glasses:before{content:"ï¿"}.ion-ios-glasses-outline:before{content:"ï¾"}.ion-ios-grid-view:before{content:"ï‘"}.ion-ios-grid-view-outline:before{content:"ï‘€"}.ion-ios-heart:before{content:""}.ion-ios-heart-outline:before{content:"ï‘‚"}.ion-ios-help:before{content:""}.ion-ios-help-empty:before{content:"ï‘„"}.ion-ios-help-outline:before{content:"ï‘…"}.ion-ios-home:before{content:""}.ion-ios-home-outline:before{content:""}.ion-ios-infinite:before{content:""}.ion-ios-infinite-outline:before{content:""}.ion-ios-information:before{content:"ï‘"}.ion-ios-information-empty:before{content:"ï‘‹"}.ion-ios-information-outline:before{content:""}.ion-ios-ionic-outline:before{content:""}.ion-ios-keypad:before{content:"ï‘"}.ion-ios-keypad-outline:before{content:"ï‘"}.ion-ios-lightbulb:before{content:"ï‘’"}.ion-ios-lightbulb-outline:before{content:"ï‘‘"}.ion-ios-list:before{content:"ï‘”"}.ion-ios-list-outline:before{content:"ï‘“"}.ion-ios-location:before{content:"ï‘–"}.ion-ios-location-outline:before{content:"ï‘•"}.ion-ios-locked:before{content:""}.ion-ios-locked-outline:before{content:"ï‘—"}.ion-ios-loop:before{content:""}.ion-ios-loop-strong:before{content:"ï‘™"}.ion-ios-medical:before{content:""}.ion-ios-medical-outline:before{content:"ï‘›"}.ion-ios-medkit:before{content:""}.ion-ios-medkit-outline:before{content:"ï‘"}.ion-ios-mic:before{content:"ï‘¡"}.ion-ios-mic-off:before{content:""}.ion-ios-mic-outline:before{content:"ï‘ "}.ion-ios-minus:before{content:""}.ion-ios-minus-empty:before{content:"ï‘¢"}.ion-ios-minus-outline:before{content:"ï‘£"}.ion-ios-monitor:before{content:""}.ion-ios-monitor-outline:before{content:"ï‘¥"}.ion-ios-moon:before{content:""}.ion-ios-moon-outline:before{content:"ï‘§"}.ion-ios-more:before{content:""}.ion-ios-more-outline:before{content:"ï‘©"}.ion-ios-musical-note:before{content:"ï‘«"}.ion-ios-musical-notes:before{content:""}.ion-ios-navigate:before{content:"ï‘®"}.ion-ios-navigate-outline:before{content:"ï‘"}.ion-ios-nutrition:before{content:"ï‘°"}.ion-ios-nutrition-outline:before{content:""}.ion-ios-paper:before{content:""}.ion-ios-paper-outline:before{content:""}.ion-ios-paperplane:before{content:"ï‘´"}.ion-ios-paperplane-outline:before{content:""}.ion-ios-partlysunny:before{content:"ï‘¶"}.ion-ios-partlysunny-outline:before{content:""}.ion-ios-pause:before{content:""}.ion-ios-pause-outline:before{content:"ï‘·"}.ion-ios-paw:before{content:""}.ion-ios-paw-outline:before{content:""}.ion-ios-people:before{content:""}.ion-ios-people-outline:before{content:"ï‘»"}.ion-ios-person:before{content:""}.ion-ios-person-outline:before{content:""}.ion-ios-personadd:before{content:"ï’€"}.ion-ios-personadd-outline:before{content:"ï‘¿"}.ion-ios-photos:before{content:"ï’‚"}.ion-ios-photos-outline:before{content:"ï’"}.ion-ios-pie:before{content:"ï’„"}.ion-ios-pie-outline:before{content:"ï’ƒ"}.ion-ios-pint:before{content:"ï’†"}.ion-ios-pint-outline:before{content:"ï’…"}.ion-ios-play:before{content:"ï’ˆ"}.ion-ios-play-outline:before{content:"ï’‡"}.ion-ios-plus:before{content:"ï’‹"}.ion-ios-plus-empty:before{content:"ï’‰"}.ion-ios-plus-outline:before{content:"ï’Š"}.ion-ios-pricetag:before{content:"ï’"}.ion-ios-pricetag-outline:before{content:"ï’Œ"}.ion-ios-pricetags:before{content:"ï’"}.ion-ios-pricetags-outline:before{content:"ï’Ž"}.ion-ios-printer:before{content:"ï’‘"}.ion-ios-printer-outline:before{content:"ï’"}.ion-ios-pulse:before{content:"ï’“"}.ion-ios-pulse-strong:before{content:"ï’’"}.ion-ios-rainy:before{content:"ï’•"}.ion-ios-rainy-outline:before{content:"ï’”"}.ion-ios-recording:before{content:"ï’—"}.ion-ios-recording-outline:before{content:"ï’–"}.ion-ios-redo:before{content:"ï’™"}.ion-ios-redo-outline:before{content:"ï’˜"}.ion-ios-refresh:before{content:"ï’œ"}.ion-ios-refresh-empty:before{content:"ï’š"}.ion-ios-refresh-outline:before{content:"ï’›"}.ion-ios-reload:before{content:"ï’"}.ion-ios-reverse-camera:before{content:"ï’Ÿ"}.ion-ios-reverse-camera-outline:before{content:"ï’ž"}.ion-ios-rewind:before{content:"ï’¡"}.ion-ios-rewind-outline:before{content:"ï’ "}.ion-ios-rose:before{content:"ï’£"}.ion-ios-rose-outline:before{content:"ï’¢"}.ion-ios-search:before{content:"ï’¥"}.ion-ios-search-strong:before{content:"ï’¤"}.ion-ios-settings:before{content:"ï’§"}.ion-ios-settings-strong:before{content:"ï’¦"}.ion-ios-shuffle:before{content:"ï’©"}.ion-ios-shuffle-strong:before{content:"ï’¨"}.ion-ios-skipbackward:before{content:"ï’«"}.ion-ios-skipbackward-outline:before{content:"ï’ª"}.ion-ios-skipforward:before{content:"ï’"}.ion-ios-skipforward-outline:before{content:"ï’¬"}.ion-ios-snowy:before{content:"ï’®"}.ion-ios-speedometer:before{content:"ï’°"}.ion-ios-speedometer-outline:before{content:"ï’¯"}.ion-ios-star:before{content:"ï’³"}.ion-ios-star-half:before{content:"ï’±"}.ion-ios-star-outline:before{content:"ï’²"}.ion-ios-stopwatch:before{content:"ï’µ"}.ion-ios-stopwatch-outline:before{content:"ï’´"}.ion-ios-sunny:before{content:"ï’·"}.ion-ios-sunny-outline:before{content:"ï’¶"}.ion-ios-telephone:before{content:"ï’¹"}.ion-ios-telephone-outline:before{content:"ï’¸"}.ion-ios-tennisball:before{content:"ï’»"}.ion-ios-tennisball-outline:before{content:"ï’º"}.ion-ios-thunderstorm:before{content:"ï’½"}.ion-ios-thunderstorm-outline:before{content:"ï’¼"}.ion-ios-time:before{content:"ï’¿"}.ion-ios-time-outline:before{content:"ï’¾"}.ion-ios-timer:before{content:"ï“"}.ion-ios-timer-outline:before{content:"ï“€"}.ion-ios-toggle:before{content:""}.ion-ios-toggle-outline:before{content:"ï“‚"}.ion-ios-trash:before{content:"ï“…"}.ion-ios-trash-outline:before{content:"ï“„"}.ion-ios-undo:before{content:""}.ion-ios-undo-outline:before{content:""}.ion-ios-unlocked:before{content:""}.ion-ios-unlocked-outline:before{content:""}.ion-ios-upload:before{content:"ï“‹"}.ion-ios-upload-outline:before{content:""}.ion-ios-videocam:before{content:"ï“"}.ion-ios-videocam-outline:before{content:""}.ion-ios-volume-high:before{content:""}.ion-ios-volume-low:before{content:"ï“"}.ion-ios-wineglass:before{content:"ï“‘"}.ion-ios-wineglass-outline:before{content:"ï“"}.ion-ios-world:before{content:"ï““"}.ion-ios-world-outline:before{content:"ï“’"}.ion-ipad:before{content:""}.ion-iphone:before{content:""}.ion-ipod:before{content:""}.ion-jet:before{content:""}.ion-key:before{content:""}.ion-knife:before{content:""}.ion-laptop:before{content:""}.ion-leaf:before{content:""}.ion-levels:before{content:""}.ion-lightbulb:before{content:""}.ion-link:before{content:""}.ion-load-a:before{content:""}.ion-load-b:before{content:""}.ion-load-c:before{content:""}.ion-load-d:before{content:"ïŠ"}.ion-location:before{content:""}.ion-lock-combination:before{content:"ï“”"}.ion-locked:before{content:""}.ion-log-in:before{content:""}.ion-log-out:before{content:""}.ion-loop:before{content:"ïˆ"}.ion-magnet:before{content:"ïŠ "}.ion-male:before{content:""}.ion-man:before{content:""}.ion-map:before{content:""}.ion-medkit:before{content:""}.ion-merge:before{content:""}.ion-mic-a:before{content:""}.ion-mic-b:before{content:""}.ion-mic-c:before{content:""}.ion-minus:before{content:""}.ion-minus-circled:before{content:""}.ion-minus-round:before{content:""}.ion-model-s:before{content:"ï‹"}.ion-monitor:before{content:""}.ion-more:before{content:""}.ion-mouse:before{content:"ï€"}.ion-music-note:before{content:""}.ion-navicon:before{content:""}.ion-navicon-round:before{content:"ïˆ"}.ion-navigate:before{content:""}.ion-network:before{content:"ï"}.ion-no-smoking:before{content:"ï‹‚"}.ion-nuclear:before{content:""}.ion-outlet:before{content:"ï‚"}.ion-paintbrush:before{content:"ï“•"}.ion-paintbucket:before{content:"ï“–"}.ion-paper-airplane:before{content:""}.ion-paperclip:before{content:"ïˆ"}.ion-pause:before{content:"ïˆ"}.ion-person:before{content:""}.ion-person-add:before{content:""}.ion-person-stalker:before{content:""}.ion-pie-graph:before{content:""}.ion-pin:before{content:""}.ion-pinpoint:before{content:""}.ion-pizza:before{content:""}.ion-plane:before{content:""}.ion-planet:before{content:"ïƒ"}.ion-play:before{content:""}.ion-playstation:before{content:""}.ion-plus:before{content:""}.ion-plus-circled:before{content:""}.ion-plus-round:before{content:""}.ion-podium:before{content:"ï„"}.ion-pound:before{content:""}.ion-power:before{content:""}.ion-pricetag:before{content:""}.ion-pricetags:before{content:""}.ion-printer:before{content:""}.ion-pull-request:before{content:"ï…"}.ion-qr-scanner:before{content:"ï†"}.ion-quote:before{content:"ï‡"}.ion-radio-waves:before{content:""}.ion-record:before{content:""}.ion-refresh:before{content:""}.ion-reply:before{content:""}.ion-reply-all:before{content:"ïˆ"}.ion-ribbon-a:before{content:"ïˆ"}.ion-ribbon-b:before{content:"ï‰"}.ion-sad:before{content:"ïŠ"}.ion-sad-outline:before{content:"ï“—"}.ion-scissors:before{content:"ï‹"}.ion-search:before{content:""}.ion-settings:before{content:"ïŠ"}.ion-share:before{content:"ïˆ "}.ion-shuffle:before{content:""}.ion-skip-backward:before{content:""}.ion-skip-forward:before{content:""}.ion-social-android:before{content:""}.ion-social-android-outline:before{content:""}.ion-social-angular:before{content:"ï“™"}.ion-social-angular-outline:before{content:""}.ion-social-apple:before{content:""}.ion-social-apple-outline:before{content:""}.ion-social-bitcoin:before{content:""}.ion-social-bitcoin-outline:before{content:""}.ion-social-buffer:before{content:""}.ion-social-buffer-outline:before{content:""}.ion-social-chrome:before{content:"ï“›"}.ion-social-chrome-outline:before{content:""}.ion-social-codepen:before{content:"ï“"}.ion-social-codepen-outline:before{content:""}.ion-social-css3:before{content:""}.ion-social-css3-outline:before{content:""}.ion-social-designernews:before{content:""}.ion-social-designernews-outline:before{content:""}.ion-social-dribbble:before{content:"ïˆ"}.ion-social-dribbble-outline:before{content:""}.ion-social-dropbox:before{content:""}.ion-social-dropbox-outline:before{content:""}.ion-social-euro:before{content:"ï“¡"}.ion-social-euro-outline:before{content:"ï“ "}.ion-social-facebook:before{content:""}.ion-social-facebook-outline:before{content:""}.ion-social-foursquare:before{content:"ï"}.ion-social-foursquare-outline:before{content:"ïŒ"}.ion-social-freebsd-devil:before{content:"ï‹„"}.ion-social-github:before{content:""}.ion-social-github-outline:before{content:""}.ion-social-google:before{content:"ï"}.ion-social-google-outline:before{content:"ïŽ"}.ion-social-googleplus:before{content:""}.ion-social-googleplus-outline:before{content:""}.ion-social-hackernews:before{content:""}.ion-social-hackernews-outline:before{content:""}.ion-social-html5:before{content:"ï“£"}.ion-social-html5-outline:before{content:"ï“¢"}.ion-social-instagram:before{content:"ï‘"}.ion-social-instagram-outline:before{content:"ï"}.ion-social-javascript:before{content:"ï“¥"}.ion-social-javascript-outline:before{content:""}.ion-social-linkedin:before{content:""}.ion-social-linkedin-outline:before{content:""}.ion-social-markdown:before{content:""}.ion-social-nodejs:before{content:"ï“§"}.ion-social-octocat:before{content:""}.ion-social-pinterest:before{content:""}.ion-social-pinterest-outline:before{content:""}.ion-social-python:before{content:"ï“©"}.ion-social-reddit:before{content:""}.ion-social-reddit-outline:before{content:""}.ion-social-rss:before{content:""}.ion-social-rss-outline:before{content:""}.ion-social-sass:before{content:""}.ion-social-skype:before{content:""}.ion-social-skype-outline:before{content:""}.ion-social-snapchat:before{content:""}.ion-social-snapchat-outline:before{content:"ï“«"}.ion-social-tumblr:before{content:"ï‰"}.ion-social-tumblr-outline:before{content:""}.ion-social-tux:before{content:"ï‹…"}.ion-social-twitch:before{content:"ï“®"}.ion-social-twitch-outline:before{content:"ï“"}.ion-social-twitter:before{content:""}.ion-social-twitter-outline:before{content:""}.ion-social-usd:before{content:"ï“"}.ion-social-usd-outline:before{content:"ï’"}.ion-social-vimeo:before{content:""}.ion-social-vimeo-outline:before{content:""}.ion-social-whatsapp:before{content:"ï“°"}.ion-social-whatsapp-outline:before{content:""}.ion-social-windows:before{content:""}.ion-social-windows-outline:before{content:""}.ion-social-wordpress:before{content:""}.ion-social-wordpress-outline:before{content:""}.ion-social-yahoo:before{content:""}.ion-social-yahoo-outline:before{content:""}.ion-social-yen:before{content:""}.ion-social-yen-outline:before{content:""}.ion-social-youtube:before{content:"ï‰"}.ion-social-youtube-outline:before{content:""}.ion-soup-can:before{content:"ï“´"}.ion-soup-can-outline:before{content:""}.ion-speakerphone:before{content:""}.ion-speedometer:before{content:""}.ion-spoon:before{content:""}.ion-star:before{content:""}.ion-stats-bars:before{content:""}.ion-steam:before{content:""}.ion-stop:before{content:"ï‰"}.ion-thermometer:before{content:""}.ion-thumbsdown:before{content:"ï‰"}.ion-thumbsup:before{content:""}.ion-toggle:before{content:"ï•"}.ion-toggle-filled:before{content:"ï”"}.ion-transgender:before{content:""}.ion-trash-a:before{content:""}.ion-trash-b:before{content:""}.ion-trophy:before{content:"ï–"}.ion-tshirt:before{content:"ï“·"}.ion-tshirt-outline:before{content:"ï“¶"}.ion-umbrella:before{content:""}.ion-university:before{content:"ï—"}.ion-unlocked:before{content:""}.ion-upload:before{content:""}.ion-usb:before{content:""}.ion-videocamera:before{content:""}.ion-volume-high:before{content:""}.ion-volume-low:before{content:""}.ion-volume-medium:before{content:""}.ion-volume-mute:before{content:""}.ion-wand:before{content:"ï˜"}.ion-waterdrop:before{content:""}.ion-wifi:before{content:""}.ion-wineglass:before{content:""}.ion-woman:before{content:"ï‰"}.ion-wrench:before{content:""}.ion-xbox:before{content:""}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;vertical-align:baseline;font:inherit;font-size:100%}ol,ul{list-style:none}blockquote,q{quotes:none}audio:not([controls]){display:none;height:0}[hidden],template{display:none}script{display:none!important}html{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}:focus,a,a:active,a:focus,a:hover,button,button:focus{outline:0}a{-webkit-user-drag:none;-webkit-tap-highlight-color:transparent}a[href]:hover{cursor:pointer}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}code,kbd,pre,samp{font-size:1em;font-family:monospace,serif}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{position:relative;vertical-align:baseline;font-size:75%;line-height:0}sup{top:-.5em}sub{bottom:-.25em}fieldset{margin:0 2px;padding:.35em .625em .75em;border:1px solid silver}button,input,select,textarea{margin:0;outline-offset:0;outline-style:none;outline-width:0;-webkit-font-smoothing:inherit;background-image:none}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto}img{-webkit-user-drag:none}table{border-spacing:0;border-collapse:collapse}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{overflow:hidden;-ms-touch-action:pan-y;touch-action:pan-y}.ionic-body,body{-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;top:0;right:0;bottom:0;left:0;overflow:hidden;margin:0;padding:0;color:#000;word-wrap:break-word;font-size:14px;font-family:-apple-system;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:20px;text-rendering:optimizeLegibility;-webkit-backface-visibility:hidden;-webkit-user-drag:none;-ms-content-zooming:none}body.grade-b,body.grade-c{text-rendering:auto}.content{position:relative}.scroll-content{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;margin-top:-1px;padding-top:1px;margin-bottom:-1px;width:auto;height:auto}.menu .scroll-content.scroll-content-false{z-index:11}.scroll-view{position:relative;display:block;overflow:hidden;margin-top:-1px}.scroll-view.overflow-scroll{position:relative}.scroll-view.scroll-x{overflow-x:scroll;overflow-y:hidden}.scroll-view.scroll-y{overflow-x:hidden;overflow-y:scroll}.scroll-view.scroll-xy{overflow-x:scroll;overflow-y:scroll}.scroll{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-transform-origin:left top;transform-origin:left top}@-ms-viewport{width:device-width}.scroll-bar{position:absolute;z-index:9999}.ng-animate .scroll-bar{visibility:hidden}.scroll-bar-h{right:2px;bottom:3px;left:2px;height:3px}.scroll-bar-h .scroll-bar-indicator{height:100%}.scroll-bar-v{top:2px;right:3px;bottom:2px;width:3px}.scroll-bar-v .scroll-bar-indicator{width:100%}.scroll-bar-indicator{position:absolute;border-radius:4px;background:rgba(0,0,0,.3);opacity:1;-webkit-transition:opacity .3s linear;transition:opacity .3s linear}.scroll-bar-indicator.scroll-bar-fade-out{opacity:0}.platform-android .scroll-bar-indicator{border-radius:0}.grade-b .scroll-bar-indicator,.grade-c .scroll-bar-indicator{background:#aaa}.grade-b .scroll-bar-indicator.scroll-bar-fade-out,.grade-c .scroll-bar-indicator.scroll-bar-fade-out{-webkit-transition:none;transition:none}ion-infinite-scroll{height:60px;width:100%;display:block;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}ion-infinite-scroll .icon{font-size:30px;color:#666}ion-infinite-scroll:not(.active) .icon:before,ion-infinite-scroll:not(.active) .spinner{display:none}.overflow-scroll{overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;top:0;right:0;bottom:0;left:0;position:absolute}.overflow-scroll.pane{overflow-x:hidden;overflow-y:scroll}.overflow-scroll .scroll{position:static;height:100%;-webkit-transform:translate3d(0,0,0)}.overflow-scroll.keyboard-up:not(.keyboard-up-confirm){overflow:hidden}.has-header{top:44px}.no-header{top:0}.has-subheader{top:88px}.has-tabs-top{top:93px}.has-header.has-subheader.has-tabs-top{top:137px}.has-footer{bottom:44px}.has-subfooter{bottom:88px}.bar-footer.has-tabs,.has-tabs{bottom:49px}.bar-footer.has-tabs.pane,.has-tabs.pane{bottom:49px;height:auto}.bar-subfooter.has-tabs,.has-footer.has-tabs{bottom:93px}.pane{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:0;transition-duration:0;z-index:1}.view{z-index:1}.pane,.view{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:#fff;overflow:hidden}.view-container{position:absolute;display:block;width:100%;height:100%}p{margin:0 0 10px}small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{color:#000;font-weight:500;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:1.2}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1:first-child,.h2:first-child,.h3:first-child,h1:first-child,h2:first-child,h3:first-child{margin-top:0}.h1+.h1,.h1+.h2,.h1+.h3,.h1+h1,.h1+h2,.h1+h3,.h2+.h1,.h2+.h2,.h2+.h3,.h2+h1,.h2+h2,.h2+h3,.h3+.h1,.h3+.h2,.h3+.h3,.h3+h1,.h3+h2,.h3+h3,h1+.h1,h1+.h2,h1+.h3,h1+h1,h1+h2,h1+h3,h2+.h1,h2+.h2,h2+.h3,h2+h1,h2+h2,h2+h3,h3+.h1,h3+.h2,h3+.h3,h3+h1,h3+h2,h3+h3{margin-top:10px}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}.h1 small,h1 small{font-size:24px}.h2 small,h2 small{font-size:18px}.h3 small,.h4 small,h3 small,h4 small{font-size:14px}dl{margin-bottom:20px}dd,dt{line-height:1.42857}dt{font-weight:700}blockquote{margin:0 0 20px;padding:10px 20px;border-left:5px solid gray}blockquote p{font-weight:300;font-size:17.5px;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.42857}blockquote small:before{content:'\2014 \00A0'}blockquote:after,blockquote:before,q:after,q:before{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.42857}a{color:#387ef5}a.subdued{padding-right:10px;color:#888;text-decoration:none}a.subdued:hover{text-decoration:none}a.subdued:last-child{padding-right:0}.action-sheet-backdrop{-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:transparent}.action-sheet-backdrop.active{background-color:rgba(0,0,0,.4)}.action-sheet-wrapper{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition:all cubic-bezier(.36,.66,.04,1) 500ms;transition:all cubic-bezier(.36,.66,.04,1) 500ms;position:absolute;bottom:0;left:0;right:0;width:100%;max-width:500px;margin:auto}.action-sheet-up{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.action-sheet{margin-left:8px;margin-right:8px;width:auto;z-index:11;overflow:hidden}.action-sheet .button{display:block;padding:1px;width:100%;border-radius:0;border-color:#d1d3d6;background-color:transparent;color:#007aff;font-size:21px}.action-sheet .button:hover{color:#007aff}.action-sheet .button.destructive,.action-sheet .button.destructive:hover{color:#ff3b30}.action-sheet .button.activated,.action-sheet .button.active{box-shadow:none;border-color:#d1d3d6;color:#007aff;background:#e4e5e7}.action-sheet-has-icons .icon{position:absolute;left:16px}.action-sheet-title{padding:16px;color:#8f8f8f;text-align:center;font-size:13px}.action-sheet-group{margin-bottom:8px;border-radius:4px;background-color:#fff;overflow:hidden}.action-sheet-group .button{border-width:1px 0 0}.action-sheet-group .button:first-child:last-child{border-width:0}.action-sheet-options{background:#f1f2f3}.action-sheet-cancel .button{font-weight:500}.action-sheet-open,.action-sheet-open.modal-open .modal{pointer-events:none}.action-sheet-open .action-sheet-backdrop{pointer-events:auto}.platform-android .action-sheet-backdrop.active{background-color:rgba(0,0,0,.2)}.platform-android .action-sheet{margin:0}.platform-android .action-sheet .action-sheet-title,.platform-android .action-sheet .button{text-align:left;border-color:transparent;font-size:16px;color:inherit}.platform-android .action-sheet .action-sheet-title{font-size:14px;padding:16px;color:#666}.platform-android .action-sheet .button.activated,.platform-android .action-sheet .button.active{background:#e8e8e8}.platform-android .action-sheet-group{margin:0;border-radius:0;background-color:#fafafa}.platform-android .action-sheet-cancel{display:none}.platform-android .action-sheet-has-icons .button{padding-left:56px}.backdrop{position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:rgba(0,0,0,.4);visibility:hidden;opacity:0;-webkit-transition:.1s opacity linear;transition:.1s opacity linear}.backdrop.visible{visibility:visible}.backdrop.active{opacity:1}.bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:absolute;right:0;left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:44px;border-width:0;border-style:solid;border-top:1px solid transparent;background-color:#fff;background-size:0}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.bar{border:none;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);background-position:bottom;background-size:100% 1px;background-repeat:no-repeat}}.bar.bar-clear{border:none;background:0 0;color:#fff}.bar.bar-clear .button,.bar.bar-clear .title{color:#fff}.bar.item-input-inset .item-input-wrapper{margin-top:-1px}.bar.item-input-inset .item-input-wrapper input{padding-left:8px;width:94%;height:28px;background:0 0}.bar.bar-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.bar.bar-light .title{color:#444}.bar.bar-light.bar-footer{background-image:linear-gradient(180deg,#ddd,#ddd 50%,transparent 50%)}.bar.bar-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.bar.bar-stable .title{color:#444}.bar.bar-stable.bar-footer{background-image:linear-gradient(180deg,#b2b2b2,#b2b2b2 50%,transparent 50%)}.bar.bar-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.bar.bar-positive .title{color:#fff}.bar.bar-positive.bar-footer{background-image:linear-gradient(180deg,#0c60ee,#0c60ee 50%,transparent 50%)}.bar.bar-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.bar.bar-calm .title{color:#fff}.bar.bar-calm.bar-footer{background-image:linear-gradient(180deg,#0a9dc7,#0a9dc7 50%,transparent 50%)}.bar.bar-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.bar.bar-assertive .title{color:#fff}.bar.bar-assertive.bar-footer{background-image:linear-gradient(180deg,#e42112,#e42112 50%,transparent 50%)}.bar.bar-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.bar.bar-balanced .title{color:#fff}.bar.bar-balanced.bar-footer{background-image:linear-gradient(180deg,#28a54c,#0c60ee 50%,transparent 50%)}.bar.bar-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.bar.bar-energized .title{color:#fff}.bar.bar-energized.bar-footer{background-image:linear-gradient(180deg,#e6b500,#e6b500 50%,transparent 50%)}.bar.bar-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.bar.bar-royal .title{color:#fff}.bar.bar-royal.bar-footer{background-image:linear-gradient(180deg,#6b46e5,#6b46e5 50%,transparent 50%)}.bar.bar-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.bar.bar-dark .title{color:#fff}.bar.bar-dark.bar-footer{background-image:linear-gradient(180deg,#111,#111 50%,transparent 50%)}.bar .title{display:block;position:absolute;top:0;right:0;left:0;z-index:0;overflow:hidden;margin:0 10px;min-width:30px;height:43px;text-align:center;text-overflow:ellipsis;white-space:nowrap;font-size:17px;font-weight:500;line-height:44px}.bar .title.title-left{text-align:left}.bar .title.title-right{text-align:right}.bar .title a{color:inherit}.bar .button,.bar button{z-index:1;padding:0 8px;min-width:initial;min-height:31px;font-weight:400;font-size:13px;line-height:32px}.bar .button .icon:before,.bar .button.button-icon:before,.bar .button.icon-left:before,.bar .button.icon-right:before,.bar .button.icon:before,.bar button .icon:before,.bar button.button-icon:before,.bar button.icon-left:before,.bar button.icon-right:before,.bar button.icon:before{padding-right:2px;padding-left:2px;font-size:20px;line-height:32px}.bar .button.button-icon,.bar button.button-icon{font-size:17px}.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before,.bar button.button-icon .icon:before,.bar button.button-icon.icon-left:before,.bar button.button-icon.icon-right:before,.bar button.button-icon:before{vertical-align:top;font-size:32px;line-height:32px}.bar .button.button-clear,.bar button.button-clear{padding-right:2px;padding-left:2px;font-weight:300;font-size:17px}.bar .button.button-clear .icon:before,.bar .button.button-clear.icon-left:before,.bar .button.button-clear.icon-right:before,.bar .button.button-clear.icon:before,.bar button.button-clear .icon:before,.bar button.button-clear.icon-left:before,.bar button.button-clear.icon-right:before,.bar button.button-clear.icon:before{font-size:32px;line-height:32px}.bar .button.back-button,.bar button.back-button{display:block;margin-right:5px;padding:0;white-space:nowrap;font-weight:400}.bar .button.back-button.activated,.bar .button.back-button.active,.bar button.back-button.activated,.bar button.back-button.active{opacity:.2}.bar .button-bar>.button,.bar .buttons>.button{min-height:31px;line-height:32px}.bar .button+.button-bar,.bar .button-bar+.button{margin-left:5px}.bar .buttons,.bar .buttons.primary-buttons,.bar .buttons.secondary-buttons{display:inherit}.bar .buttons span{display:inline-block}.bar .buttons-left span{margin-right:5px;display:inherit}.bar .buttons-right span{margin-left:5px;display:inherit}.bar .buttons.pull-right,.bar .title+.button:last-child,.bar .title+.buttons,.bar>.button+.button:last-child,.bar>.button.pull-right{position:absolute;top:5px;right:5px;bottom:5px}.platform-android .nav-bar-has-subheader .bar{background-image:none}.platform-android .bar .back-button .icon:before{font-size:24px}.platform-android .bar .title{font-size:19px;line-height:44px}.bar-light .button{border-color:transparent;background-color:#fff;color:#444}.bar-light .button:hover{color:#444;text-decoration:none}.bar-light .button.activated,.bar-light .button.active{background-color:#fafafa}.bar-light .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-light .button.button-icon{border-color:transparent;background:0 0}.bar-stable .button{border-color:transparent;background-color:#f8f8f8;color:#444}.bar-stable .button:hover{color:#444;text-decoration:none}.bar-stable .button.activated,.bar-stable .button.active{background-color:#e5e5e5}.bar-stable .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-stable .button.button-icon{border-color:transparent;background:0 0}.bar-positive .button{border-color:transparent;background-color:#387ef5;color:#fff}.bar-positive .button:hover{color:#fff;text-decoration:none}.bar-positive .button.activated,.bar-positive .button.active{background-color:#0c60ee}.bar-positive .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-positive .button.button-icon{border-color:transparent;background:0 0}.bar-calm .button{border-color:transparent;background-color:#11c1f3;color:#fff}.bar-calm .button:hover{color:#fff;text-decoration:none}.bar-calm .button.activated,.bar-calm .button.active{background-color:#0a9dc7}.bar-calm .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-calm .button.button-icon{border-color:transparent;background:0 0}.bar-assertive .button{border-color:transparent;background-color:#ef473a;color:#fff}.bar-assertive .button:hover{color:#fff;text-decoration:none}.bar-assertive .button.activated,.bar-assertive .button.active{background-color:#e42112}.bar-assertive .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-assertive .button.button-icon{border-color:transparent;background:0 0}.bar-balanced .button{border-color:transparent;background-color:#33cd5f;color:#fff}.bar-balanced .button:hover{color:#fff;text-decoration:none}.bar-balanced .button.activated,.bar-balanced .button.active{background-color:#28a54c}.bar-balanced .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-balanced .button.button-icon{border-color:transparent;background:0 0}.bar-energized .button{border-color:transparent;background-color:#ffc900;color:#fff}.bar-energized .button:hover{color:#fff;text-decoration:none}.bar-energized .button.activated,.bar-energized .button.active{background-color:#e6b500}.bar-energized .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-energized .button.button-icon{border-color:transparent;background:0 0}.bar-royal .button{border-color:transparent;background-color:#886aea;color:#fff}.bar-royal .button:hover{color:#fff;text-decoration:none}.bar-royal .button.activated,.bar-royal .button.active{background-color:#6b46e5}.bar-royal .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-royal .button.button-icon{border-color:transparent;background:0 0}.bar-dark .button{border-color:transparent;background-color:#444;color:#fff}.bar-dark .button:hover{color:#fff;text-decoration:none}.bar-dark .button.activated,.bar-dark .button.active{background-color:#262626}.bar-dark .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-dark .button.button-icon{border-color:transparent;background:0 0}.bar-header{top:0;border-top-width:0;border-bottom-width:1px}.bar-header.has-tabs-top,.tabs-top .bar-header{border-bottom-width:0;background-image:none}.bar-footer{bottom:0;border-top-width:1px;border-bottom-width:0;background-position:top;height:44px}.bar-footer.item-input-inset{position:absolute}.bar-tabs{padding:0}.bar-subheader{top:44px;display:block;height:44px}.bar-subfooter{bottom:44px;display:block;height:44px}.nav-bar-block{position:absolute;top:0;right:0;left:0;z-index:9}.bar .back-button.hide,.bar .buttons .hide{display:none}.nav-bar-tabs-top .bar{background-image:none}.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:horizontal;-moz-flex-direction:horizontal;-ms-flex-direction:horizontal;flex-direction:horizontal;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444;position:absolute;bottom:0;z-index:5;width:100%;height:49px;border-style:solid;border-top-width:1px;background-size:0;line-height:49px}.tabs .tab-item .badge{background-color:#444;color:#f8f8f8}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.tabs{padding-top:2px;border-top:none!important;border-bottom:none;background-position:top;background-size:100% 1px;background-repeat:no-repeat}}.tabs-light>.tabs,.tabs.tabs-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.tabs-light>.tabs .tab-item .badge,.tabs.tabs-light .tab-item .badge{background-color:#444;color:#fff}.tabs-stable>.tabs,.tabs.tabs-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.tabs-stable>.tabs .tab-item .badge,.tabs.tabs-stable .tab-item .badge{background-color:#444;color:#f8f8f8}.tabs-positive>.tabs,.tabs.tabs-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.tabs-positive>.tabs .tab-item .badge,.tabs.tabs-positive .tab-item .badge{background-color:#fff;color:#387ef5}.tabs-calm>.tabs,.tabs.tabs-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.tabs-calm>.tabs .tab-item .badge,.tabs.tabs-calm .tab-item .badge{background-color:#fff;color:#11c1f3}.tabs-assertive>.tabs,.tabs.tabs-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.tabs-assertive>.tabs .tab-item .badge,.tabs.tabs-assertive .tab-item .badge{background-color:#fff;color:#ef473a}.tabs-balanced>.tabs,.tabs.tabs-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.tabs-balanced>.tabs .tab-item .badge,.tabs.tabs-balanced .tab-item .badge{background-color:#fff;color:#33cd5f}.tabs-energized>.tabs,.tabs.tabs-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.tabs-energized>.tabs .tab-item .badge,.tabs.tabs-energized .tab-item .badge{background-color:#fff;color:#ffc900}.tabs-royal>.tabs,.tabs.tabs-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.tabs-royal>.tabs .tab-item .badge,.tabs.tabs-royal .tab-item .badge{background-color:#fff;color:#886aea}.tabs-dark>.tabs,.tabs.tabs-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.tabs-dark>.tabs .tab-item .badge,.tabs.tabs-dark .tab-item .badge{background-color:#fff;color:#444}.tabs-striped .tabs{background-color:#fff;background-image:none;border:none;border-bottom:1px solid #ddd;padding-top:2px}.tabs-striped .tab-item.activated,.tabs-striped .tab-item.active,.tabs-striped .tab-item.tab-item-active{margin-top:-2px;border-style:solid;border-width:2px 0 0;border-color:#444}.tabs-striped .tab-item.activated .badge,.tabs-striped .tab-item.active .badge,.tabs-striped .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-light .tabs{background-color:#fff}.tabs-striped.tabs-light .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-light .tab-item.activated,.tabs-striped.tabs-light .tab-item.active,.tabs-striped.tabs-light .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0;border-color:#444}.tabs-striped.tabs-stable .tabs{background-color:#f8f8f8}.tabs-striped.tabs-stable .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-stable .tab-item.activated,.tabs-striped.tabs-stable .tab-item.active,.tabs-striped.tabs-stable .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0;border-color:#444}.tabs-striped.tabs-positive .tabs{background-color:#387ef5}.tabs-striped.tabs-positive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-positive .tab-item.activated,.tabs-striped.tabs-positive .tab-item.active,.tabs-striped.tabs-positive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-calm .tabs{background-color:#11c1f3}.tabs-striped.tabs-calm .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-calm .tab-item.activated,.tabs-striped.tabs-calm .tab-item.active,.tabs-striped.tabs-calm .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-assertive .tabs{background-color:#ef473a}.tabs-striped.tabs-assertive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-assertive .tab-item.activated,.tabs-striped.tabs-assertive .tab-item.active,.tabs-striped.tabs-assertive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-balanced .tabs{background-color:#33cd5f}.tabs-striped.tabs-balanced .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-balanced .tab-item.activated,.tabs-striped.tabs-balanced .tab-item.active,.tabs-striped.tabs-balanced .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-energized .tabs{background-color:#ffc900}.tabs-striped.tabs-energized .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-energized .tab-item.activated,.tabs-striped.tabs-energized .tab-item.active,.tabs-striped.tabs-energized .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-royal .tabs{background-color:#886aea}.tabs-striped.tabs-royal .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-royal .tab-item.activated,.tabs-striped.tabs-royal .tab-item.active,.tabs-striped.tabs-royal .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-dark .tabs{background-color:#444}.tabs-striped.tabs-dark .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-dark .tab-item.activated,.tabs-striped.tabs-dark .tab-item.active,.tabs-striped.tabs-dark .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-background-light .tabs{background-color:#fff;background-image:none}.tabs-striped.tabs-background-stable .tabs{background-color:#f8f8f8;background-image:none}.tabs-striped.tabs-background-positive .tabs{background-color:#387ef5;background-image:none}.tabs-striped.tabs-background-calm .tabs{background-color:#11c1f3;background-image:none}.tabs-striped.tabs-background-assertive .tabs{background-color:#ef473a;background-image:none}.tabs-striped.tabs-background-balanced .tabs{background-color:#33cd5f;background-image:none}.tabs-striped.tabs-background-energized .tabs{background-color:#ffc900;background-image:none}.tabs-striped.tabs-background-royal .tabs{background-color:#886aea;background-image:none}.tabs-striped.tabs-background-dark .tabs{background-color:#444;background-image:none}.tabs-striped.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-color-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-light .tab-item.activated,.tabs-striped.tabs-color-light .tab-item.active,.tabs-striped.tabs-color-light .tab-item.tab-item-active{margin-top:-2px;color:#fff;border:0 solid #fff;border-top-width:2px}.tabs-striped.tabs-color-light .tab-item.activated .badge,.tabs-striped.tabs-color-light .tab-item.active .badge,.tabs-striped.tabs-color-light .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-striped.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-stable .tab-item.activated,.tabs-striped.tabs-color-stable .tab-item.active,.tabs-striped.tabs-color-stable .tab-item.tab-item-active{margin-top:-2px;color:#f8f8f8;border:0 solid #f8f8f8;border-top-width:2px}.tabs-striped.tabs-color-stable .tab-item.activated .badge,.tabs-striped.tabs-color-stable .tab-item.active .badge,.tabs-striped.tabs-color-stable .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-striped.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-positive .tab-item.activated,.tabs-striped.tabs-color-positive .tab-item.active,.tabs-striped.tabs-color-positive .tab-item.tab-item-active{margin-top:-2px;color:#387ef5;border:0 solid #387ef5;border-top-width:2px}.tabs-striped.tabs-color-positive .tab-item.activated .badge,.tabs-striped.tabs-color-positive .tab-item.active .badge,.tabs-striped.tabs-color-positive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-striped.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-calm .tab-item.activated,.tabs-striped.tabs-color-calm .tab-item.active,.tabs-striped.tabs-color-calm .tab-item.tab-item-active{margin-top:-2px;color:#11c1f3;border:0 solid #11c1f3;border-top-width:2px}.tabs-striped.tabs-color-calm .tab-item.activated .badge,.tabs-striped.tabs-color-calm .tab-item.active .badge,.tabs-striped.tabs-color-calm .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-striped.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-assertive .tab-item.activated,.tabs-striped.tabs-color-assertive .tab-item.active,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active{margin-top:-2px;color:#ef473a;border:0 solid #ef473a;border-top-width:2px}.tabs-striped.tabs-color-assertive .tab-item.activated .badge,.tabs-striped.tabs-color-assertive .tab-item.active .badge,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-striped.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-balanced .tab-item.activated,.tabs-striped.tabs-color-balanced .tab-item.active,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active{margin-top:-2px;color:#33cd5f;border:0 solid #33cd5f;border-top-width:2px}.tabs-striped.tabs-color-balanced .tab-item.activated .badge,.tabs-striped.tabs-color-balanced .tab-item.active .badge,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-striped.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-energized .tab-item.activated,.tabs-striped.tabs-color-energized .tab-item.active,.tabs-striped.tabs-color-energized .tab-item.tab-item-active{margin-top:-2px;color:#ffc900;border:0 solid #ffc900;border-top-width:2px}.tabs-striped.tabs-color-energized .tab-item.activated .badge,.tabs-striped.tabs-color-energized .tab-item.active .badge,.tabs-striped.tabs-color-energized .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-striped.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-royal .tab-item.activated,.tabs-striped.tabs-color-royal .tab-item.active,.tabs-striped.tabs-color-royal .tab-item.tab-item-active{margin-top:-2px;color:#886aea;border:0 solid #886aea;border-top-width:2px}.tabs-striped.tabs-color-royal .tab-item.activated .badge,.tabs-striped.tabs-color-royal .tab-item.active .badge,.tabs-striped.tabs-color-royal .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-dark .tab-item.activated,.tabs-striped.tabs-color-dark .tab-item.active,.tabs-striped.tabs-color-dark .tab-item.tab-item-active{margin-top:-2px;color:#444;border:0 solid #444;border-top-width:2px}.tabs-striped.tabs-color-dark .tab-item.activated .badge,.tabs-striped.tabs-color-dark .tab-item.active .badge,.tabs-striped.tabs-color-dark .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-background-light .tabs,.tabs-background-light>.tabs{background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);border-color:#ddd}.tabs-background-stable .tabs,.tabs-background-stable>.tabs{background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);border-color:#b2b2b2}.tabs-background-positive .tabs,.tabs-background-positive>.tabs{background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);border-color:#0c60ee}.tabs-background-calm .tabs,.tabs-background-calm>.tabs{background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);border-color:#0a9dc7}.tabs-background-assertive .tabs,.tabs-background-assertive>.tabs{background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);border-color:#e42112}.tabs-background-balanced .tabs,.tabs-background-balanced>.tabs{background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);border-color:#28a54c}.tabs-background-energized .tabs,.tabs-background-energized>.tabs{background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);border-color:#e6b500}.tabs-background-royal .tabs,.tabs-background-royal>.tabs{background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);border-color:#6b46e5}.tabs-background-dark .tabs,.tabs-background-dark>.tabs{background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);border-color:#111}.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-color-light .tab-item .badge{opacity:.4}.tabs-color-light .tab-item.activated,.tabs-color-light .tab-item.active,.tabs-color-light .tab-item.tab-item-active{color:#fff;border:0 solid #fff}.tabs-color-light .tab-item.activated .badge,.tabs-color-light .tab-item.active .badge,.tabs-color-light .tab-item.tab-item-active .badge{opacity:1}.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-color-stable .tab-item.activated,.tabs-color-stable .tab-item.active,.tabs-color-stable .tab-item.tab-item-active{color:#f8f8f8;border:0 solid #f8f8f8}.tabs-color-stable .tab-item.activated .badge,.tabs-color-stable .tab-item.active .badge,.tabs-color-stable .tab-item.tab-item-active .badge{opacity:1}.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-color-positive .tab-item.activated,.tabs-color-positive .tab-item.active,.tabs-color-positive .tab-item.tab-item-active{color:#387ef5;border:0 solid #387ef5}.tabs-color-positive .tab-item.activated .badge,.tabs-color-positive .tab-item.active .badge,.tabs-color-positive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-color-calm .tab-item.activated,.tabs-color-calm .tab-item.active,.tabs-color-calm .tab-item.tab-item-active{color:#11c1f3;border:0 solid #11c1f3}.tabs-color-calm .tab-item.activated .badge,.tabs-color-calm .tab-item.active .badge,.tabs-color-calm .tab-item.tab-item-active .badge{opacity:1}.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-color-assertive .tab-item.activated,.tabs-color-assertive .tab-item.active,.tabs-color-assertive .tab-item.tab-item-active{color:#ef473a;border:0 solid #ef473a}.tabs-color-assertive .tab-item.activated .badge,.tabs-color-assertive .tab-item.active .badge,.tabs-color-assertive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-color-balanced .tab-item.activated,.tabs-color-balanced .tab-item.active,.tabs-color-balanced .tab-item.tab-item-active{color:#33cd5f;border:0 solid #33cd5f}.tabs-color-balanced .tab-item.activated .badge,.tabs-color-balanced .tab-item.active .badge,.tabs-color-balanced .tab-item.tab-item-active .badge{opacity:1}.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-color-energized .tab-item.activated,.tabs-color-energized .tab-item.active,.tabs-color-energized .tab-item.tab-item-active{color:#ffc900;border:0 solid #ffc900}.tabs-color-energized .tab-item.activated .badge,.tabs-color-energized .tab-item.active .badge,.tabs-color-energized .tab-item.tab-item-active .badge{opacity:1}.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-color-royal .tab-item.activated,.tabs-color-royal .tab-item.active,.tabs-color-royal .tab-item.tab-item-active{color:#886aea;border:0 solid #886aea}.tabs-color-royal .tab-item.activated .badge,.tabs-color-royal .tab-item.active .badge,.tabs-color-royal .tab-item.tab-item-active .badge{opacity:1}.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-color-dark .tab-item.activated,.tabs-color-dark .tab-item.active,.tabs-color-dark .tab-item.tab-item-active{color:#444;border:0 solid #444}.tabs-color-dark .tab-item.activated .badge,.tabs-color-dark .tab-item.active .badge,.tabs-color-dark .tab-item.tab-item-active .badge{opacity:1}ion-tabs.tabs-color-active-light .tab-item{color:#444}ion-tabs.tabs-color-active-light .tab-item.activated,ion-tabs.tabs-color-active-light .tab-item.active,ion-tabs.tabs-color-active-light .tab-item.tab-item-active{color:#fff}ion-tabs.tabs-color-active-stable .tab-item{color:#444}ion-tabs.tabs-color-active-stable .tab-item.activated,ion-tabs.tabs-color-active-stable .tab-item.active,ion-tabs.tabs-color-active-stable .tab-item.tab-item-active{color:#f8f8f8}ion-tabs.tabs-color-active-positive .tab-item{color:#444}ion-tabs.tabs-color-active-positive .tab-item.activated,ion-tabs.tabs-color-active-positive .tab-item.active,ion-tabs.tabs-color-active-positive .tab-item.tab-item-active{color:#387ef5}ion-tabs.tabs-color-active-calm .tab-item{color:#444}ion-tabs.tabs-color-active-calm .tab-item.activated,ion-tabs.tabs-color-active-calm .tab-item.active,ion-tabs.tabs-color-active-calm .tab-item.tab-item-active{color:#11c1f3}ion-tabs.tabs-color-active-assertive .tab-item{color:#444}ion-tabs.tabs-color-active-assertive .tab-item.activated,ion-tabs.tabs-color-active-assertive .tab-item.active,ion-tabs.tabs-color-active-assertive .tab-item.tab-item-active{color:#ef473a}ion-tabs.tabs-color-active-balanced .tab-item{color:#444}ion-tabs.tabs-color-active-balanced .tab-item.activated,ion-tabs.tabs-color-active-balanced .tab-item.active,ion-tabs.tabs-color-active-balanced .tab-item.tab-item-active{color:#33cd5f}ion-tabs.tabs-color-active-energized .tab-item{color:#444}ion-tabs.tabs-color-active-energized .tab-item.activated,ion-tabs.tabs-color-active-energized .tab-item.active,ion-tabs.tabs-color-active-energized .tab-item.tab-item-active{color:#ffc900}ion-tabs.tabs-color-active-royal .tab-item{color:#444}ion-tabs.tabs-color-active-royal .tab-item.activated,ion-tabs.tabs-color-active-royal .tab-item.active,ion-tabs.tabs-color-active-royal .tab-item.tab-item-active{color:#886aea}ion-tabs.tabs-color-active-dark .tab-item{color:#fff}ion-tabs.tabs-color-active-dark .tab-item.activated,ion-tabs.tabs-color-active-dark .tab-item.active,ion-tabs.tabs-color-active-dark .tab-item.tab-item-active{color:#444}.tabs-top.tabs-striped{padding-bottom:0}.tabs-top.tabs-striped .tab-item{background:0 0;-webkit-transition:color .1s ease;-moz-transition:color .1s ease;-ms-transition:color .1s ease;-o-transition:color .1s ease;transition:color .1s ease}.tabs-top.tabs-striped .tab-item.activated,.tabs-top.tabs-striped .tab-item.active,.tabs-top.tabs-striped .tab-item.tab-item-active{margin-top:1px;border-width:0 0 2px!important;border-style:solid}.tabs-top.tabs-striped .tab-item.activated>.badge,.tabs-top.tabs-striped .tab-item.activated>i,.tabs-top.tabs-striped .tab-item.active>.badge,.tabs-top.tabs-striped .tab-item.active>i,.tabs-top.tabs-striped .tab-item.tab-item-active>.badge,.tabs-top.tabs-striped .tab-item.tab-item-active>i{margin-top:-1px}.tabs-top.tabs-striped .tab-item .badge{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease}.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active i{display:block;margin-top:-1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item{margin-top:1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active i{margin-top:-.1em}.tabs-top>.tabs,.tabs.tabs-top{top:44px;padding-top:0;background-position:bottom;border-top-width:0;border-bottom-width:1px}.tabs-top>.tabs .tab-item.activated .badge,.tabs-top>.tabs .tab-item.active .badge,.tabs-top>.tabs .tab-item.tab-item-active .badge,.tabs.tabs-top .tab-item.activated .badge,.tabs.tabs-top .tab-item.active .badge,.tabs.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-top~.bar-header{border-bottom-width:0}.tab-item{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;max-width:150px;height:100%;color:inherit;text-align:center;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;font-weight:400;font-size:14px;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;opacity:.7}.tab-item:hover{cursor:pointer}.tab-item.tab-hidden,.tabs-item-hide>.tabs,.tabs.tabs-item-hide{display:none}.tabs-icon-bottom.tabs .tab-item,.tabs-icon-bottom>.tabs .tab-item,.tabs-icon-top.tabs .tab-item,.tabs-icon-top>.tabs .tab-item{font-size:10px;line-height:14px}.tab-item .icon{display:block;margin:0 auto;height:32px;font-size:32px}.tabs-icon-left.tabs .tab-item,.tabs-icon-left>.tabs .tab-item,.tabs-icon-right.tabs .tab-item,.tabs-icon-right>.tabs .tab-item{font-size:10px}.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left.tabs .tab-item .tab-title,.tabs-icon-left>.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .tab-title,.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right.tabs .tab-item .tab-title,.tabs-icon-right>.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .tab-title{display:inline-block;vertical-align:top;margin-top:-.1em}.tabs-icon-left.tabs .tab-item .icon:before,.tabs-icon-left.tabs .tab-item .tab-title:before,.tabs-icon-left>.tabs .tab-item .icon:before,.tabs-icon-left>.tabs .tab-item .tab-title:before,.tabs-icon-right.tabs .tab-item .icon:before,.tabs-icon-right.tabs .tab-item .tab-title:before,.tabs-icon-right>.tabs .tab-item .icon:before,.tabs-icon-right>.tabs .tab-item .tab-title:before{font-size:24px;line-height:49px}.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .icon{padding-right:3px}.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .icon{padding-left:3px}.tabs-icon-only.tabs .icon,.tabs-icon-only>.tabs .icon{line-height:inherit}.tab-item.has-badge{position:relative}.tab-item .badge{position:absolute;top:4%;right:33%;right:calc(50% - 26px);padding:1px 6px;height:auto;font-size:12px;line-height:16px}.tab-item.activated,.tab-item.active,.tab-item.tab-item-active{opacity:1}.tab-item.activated.tab-item-light,.tab-item.active.tab-item-light,.tab-item.tab-item-active.tab-item-light{color:#fff}.tab-item.activated.tab-item-stable,.tab-item.active.tab-item-stable,.tab-item.tab-item-active.tab-item-stable{color:#f8f8f8}.tab-item.activated.tab-item-positive,.tab-item.active.tab-item-positive,.tab-item.tab-item-active.tab-item-positive{color:#387ef5}.tab-item.activated.tab-item-calm,.tab-item.active.tab-item-calm,.tab-item.tab-item-active.tab-item-calm{color:#11c1f3}.tab-item.activated.tab-item-assertive,.tab-item.active.tab-item-assertive,.tab-item.tab-item-active.tab-item-assertive{color:#ef473a}.tab-item.activated.tab-item-balanced,.tab-item.active.tab-item-balanced,.tab-item.tab-item-active.tab-item-balanced{color:#33cd5f}.tab-item.activated.tab-item-energized,.tab-item.active.tab-item-energized,.tab-item.tab-item-active.tab-item-energized{color:#ffc900}.tab-item.activated.tab-item-royal,.tab-item.active.tab-item-royal,.tab-item.tab-item-active.tab-item-royal{color:#886aea}.tab-item.activated.tab-item-dark,.tab-item.active.tab-item-dark,.tab-item.tab-item-active.tab-item-dark{color:#444}.item.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:0}.item.tabs .icon:before{position:relative}.tab-item.disabled,.tab-item[disabled]{opacity:.4;cursor:default;pointer-events:none}.nav-bar-tabs-top.hide~.view-container .tabs-top .tabs{top:0}.pane[hide-nav-bar=true] .has-tabs-top{top:49px}.menu{position:absolute;top:0;bottom:0;z-index:0;overflow:hidden;min-height:100%;max-height:100%;width:275px}.menu .scroll-content{z-index:10}.menu .bar-header{z-index:11}.menu-content{-webkit-transform:none;transform:none;box-shadow:-1px 0 2px rgba(0,0,0,.2),1px 0 2px rgba(0,0,0,.2)}.menu-open .menu-content .pane,.menu-open .menu-content .scroll-content,.menu-open .menu-content .scroll-content .scroll{pointer-events:none}.menu-open .menu-content .scroll-content:not(.overflow-scroll){overflow:hidden}.grade-b .menu-content,.grade-c .menu-content{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;right:-1px;left:-1px;border-right:1px solid #ccc;border-left:1px solid #ccc;box-shadow:none}.menu-left{left:0}.menu-right{right:0}.aside-open.aside-resizing .menu-right{display:none}.menu-animated{-webkit-transition:-webkit-transform 200ms ease;transition:transform 200ms ease}.modal-backdrop,.modal-backdrop-bg{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%}.modal-backdrop-bg{pointer-events:none}.modal{display:block;position:absolute;top:0;z-index:10;overflow:hidden;min-height:100%;width:100%;background-color:#fff}@media (min-width:680px){.modal{top:20%;right:20%;bottom:20%;left:20%;min-height:240px;width:60%}.modal.ng-leave-active{bottom:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader,.platform-ios.platform-cordova .modal-wrapper .modal .has-header,.platform-ios.platform-cordova .modal-wrapper .modal .tabs-top>.tabs,.platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top{top:44px}.platform-ios.platform-cordova .modal-wrapper .modal .has-subheader{top:88px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-tabs-top{top:93px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-subheader.has-tabs-top{top:137px}.modal-backdrop-bg{-webkit-transition:opacity 300ms ease-in-out;transition:opacity 300ms ease-in-out;background-color:#000;opacity:0}.active .modal-backdrop-bg{opacity:.5}}.modal-open{pointer-events:none}.modal-open .modal,.modal-open .modal-backdrop{pointer-events:auto}.modal-open.loading-active .modal,.modal-open.loading-active .modal-backdrop{pointer-events:none}.popover-backdrop{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%;background-color:transparent}.popover-backdrop.active{background-color:rgba(0,0,0,.1)}.popover{left:50%;z-index:10;display:block;margin-top:12px;margin-left:-110px;height:280px;width:220px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4)}.popover .item:first-child{border-top:0}.popover .item:last-child{border-bottom:0}.popover.popover-bottom{margin-top:-12px}.popover,.popover .bar-header{border-radius:2px}.popover .scroll-content{z-index:1;margin:2px 0}.popover .bar-header{border-bottom-right-radius:0;border-bottom-left-radius:0}.popover .has-header{border-top-right-radius:0;border-top-left-radius:0}.popover-arrow{display:none}.platform-ios .popover{box-shadow:0 0 40px rgba(0,0,0,.08);border-radius:10px}.platform-ios .popover .bar-header{-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-webkit-border-top-left-radius:10px;border-top-left-radius:10px}.platform-ios .popover .scroll-content{margin:8px 0;border-radius:10px}.platform-ios .popover .scroll-content.has-header{margin-top:0}.platform-ios .popover-arrow{position:absolute;display:block;top:-17px;width:30px;height:19px;overflow:hidden}.platform-ios .popover-arrow:after{position:absolute;top:12px;left:5px;width:20px;height:20px;background-color:#fff;border-radius:3px;content:'';-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.platform-ios .popover-bottom .popover-arrow{top:auto;bottom:-10px}.platform-ios .popover-bottom .popover-arrow:after{top:-6px}.platform-android .popover{margin-top:-32px;background-color:#fafafa;box-shadow:0 2px 6px rgba(0,0,0,.35)}.platform-android .popover .item{border-color:#fafafa;background-color:#fafafa;color:#4d4d4d}.platform-android .popover.popover-bottom{margin-top:32px}.platform-android .popover-backdrop,.platform-android .popover-backdrop.active{background-color:transparent}.popover-open{pointer-events:none}.popover-open .popover,.popover-open .popover-backdrop{pointer-events:auto}.popover-open.loading-active .popover,.popover-open.loading-active .popover-backdrop{pointer-events:none}@media (min-width:680px){.popover{width:360px;margin-left:-180px}}.popup-container{position:absolute;top:0;left:0;bottom:0;right:0;background:0 0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;z-index:12;visibility:hidden}.popup-container.popup-showing{visibility:visible}.popup-container.popup-hidden .popup{-webkit-animation-name:scaleOut;animation-name:scaleOut;-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container.active .popup{-webkit-animation-name:superScaleIn;animation-name:superScaleIn;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container .popup{width:250px;max-width:100%;max-height:90%;border-radius:0;background-color:rgba(255,255,255,.9);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.popup-container input,.popup-container textarea{width:100%}.popup-head{padding:15px 10px;border-bottom:1px solid #eee;text-align:center}.popup-title{margin:0;padding:0;font-size:15px}.popup-sub-title{margin:5px 0 0;padding:0;font-weight:400;font-size:11px}.popup-body{padding:10px;overflow:auto}.popup-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding:10px;min-height:65px}.popup-buttons .button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;min-height:45px;border-radius:2px;line-height:20px;margin-right:5px}.popup-buttons .button:last-child{margin-right:0}.popup-open,.popup-open.modal-open .modal{pointer-events:none}.popup-open .popup,.popup-open .popup-backdrop{pointer-events:auto}.loading-container{position:absolute;left:0;top:0;right:0;bottom:0;z-index:13;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-transition:.2s opacity linear;transition:.2s opacity linear;visibility:hidden;opacity:0}.loading-container:not(.visible) .icon,.loading-container:not(.visible) .spinner{display:none}.loading-container.visible{visibility:visible}.loading-container.active{opacity:1}.loading-container .loading{padding:20px;border-radius:5px;background-color:rgba(0,0,0,.7);color:#fff;text-align:center;text-overflow:ellipsis;font-size:15px}.loading-container .loading h1,.loading-container .loading h2,.loading-container .loading h3,.loading-container .loading h4,.loading-container .loading h5,.loading-container .loading h6{color:#fff}.item{border-color:#ddd;color:#444;position:relative;z-index:2;display:block;margin:-1px;padding:16px;border-width:1px;border-style:solid}.item h2{margin:0 0 2px;font-size:16px;font-weight:400}.item h3{margin:0 0 4px;font-size:14px}.item h4{margin:0 0 4px;font-size:12px}.item h5,.item h6{margin:0 0 3px;font-size:10px}.item p{color:#666;font-size:14px;margin-bottom:2px}.item h1:last-child,.item h2:last-child,.item h3:last-child,.item h4:last-child,.item h5:last-child,.item h6:last-child,.item p:last-child{margin-bottom:0}.item .badge{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;position:absolute;top:16px;right:32px}.item.item-button-right .badge{right:67px}.item.item-divider .badge{top:8px}.item .badge+.badge{margin-right:5px}.item.item-light{border-color:#ddd;background-color:#fff;color:#444}.item.item-stable{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item.item-positive{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item.item-calm{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item.item-assertive{border-color:#e42112;background-color:#ef473a;color:#fff}.item.item-balanced{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item.item-energized{border-color:#e6b500;background-color:#ffc900;color:#fff}.item.item-royal{border-color:#6b46e5;background-color:#886aea;color:#fff}.item.item-dark{border-color:#111;background-color:#444;color:#fff}.item[ng-click]:hover{cursor:pointer}.item-borderless,.list-borderless .item{border-width:0}.item .item-content.activated,.item .item-content.activated.item-complex>.item-content,.item .item-content.active,.item .item-content.active.item-complex>.item-content,.item-complex.activated .item-content,.item-complex.activated .item-content.item-complex>.item-content,.item-complex.active .item-content,.item-complex.active .item-content.item-complex>.item-content,.item.activated,.item.activated.item-complex>.item-content,.item.active,.item.active.item-complex>.item-content{border-color:#ccc;background-color:#D9D9D9}.item .item-content.activated.item-light,.item .item-content.activated.item-light.item-complex>.item-content,.item .item-content.active.item-light,.item .item-content.active.item-light.item-complex>.item-content,.item-complex.activated .item-content.item-light,.item-complex.activated .item-content.item-light.item-complex>.item-content,.item-complex.active .item-content.item-light,.item-complex.active .item-content.item-light.item-complex>.item-content,.item.activated.item-light,.item.activated.item-light.item-complex>.item-content,.item.active.item-light,.item.active.item-light.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item .item-content.activated.item-stable,.item .item-content.activated.item-stable.item-complex>.item-content,.item .item-content.active.item-stable,.item .item-content.active.item-stable.item-complex>.item-content,.item-complex.activated .item-content.item-stable,.item-complex.activated .item-content.item-stable.item-complex>.item-content,.item-complex.active .item-content.item-stable,.item-complex.active .item-content.item-stable.item-complex>.item-content,.item.activated.item-stable,.item.activated.item-stable.item-complex>.item-content,.item.active.item-stable,.item.active.item-stable.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item .item-content.activated.item-positive,.item .item-content.activated.item-positive.item-complex>.item-content,.item .item-content.active.item-positive,.item .item-content.active.item-positive.item-complex>.item-content,.item-complex.activated .item-content.item-positive,.item-complex.activated .item-content.item-positive.item-complex>.item-content,.item-complex.active .item-content.item-positive,.item-complex.active .item-content.item-positive.item-complex>.item-content,.item.activated.item-positive,.item.activated.item-positive.item-complex>.item-content,.item.active.item-positive,.item.active.item-positive.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item .item-content.activated.item-calm,.item .item-content.activated.item-calm.item-complex>.item-content,.item .item-content.active.item-calm,.item .item-content.active.item-calm.item-complex>.item-content,.item-complex.activated .item-content.item-calm,.item-complex.activated .item-content.item-calm.item-complex>.item-content,.item-complex.active .item-content.item-calm,.item-complex.active .item-content.item-calm.item-complex>.item-content,.item.activated.item-calm,.item.activated.item-calm.item-complex>.item-content,.item.active.item-calm,.item.active.item-calm.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item .item-content.activated.item-assertive,.item .item-content.activated.item-assertive.item-complex>.item-content,.item .item-content.active.item-assertive,.item .item-content.active.item-assertive.item-complex>.item-content,.item-complex.activated .item-content.item-assertive,.item-complex.activated .item-content.item-assertive.item-complex>.item-content,.item-complex.active .item-content.item-assertive,.item-complex.active .item-content.item-assertive.item-complex>.item-content,.item.activated.item-assertive,.item.activated.item-assertive.item-complex>.item-content,.item.active.item-assertive,.item.active.item-assertive.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item .item-content.activated.item-balanced,.item .item-content.activated.item-balanced.item-complex>.item-content,.item .item-content.active.item-balanced,.item .item-content.active.item-balanced.item-complex>.item-content,.item-complex.activated .item-content.item-balanced,.item-complex.activated .item-content.item-balanced.item-complex>.item-content,.item-complex.active .item-content.item-balanced,.item-complex.active .item-content.item-balanced.item-complex>.item-content,.item.activated.item-balanced,.item.activated.item-balanced.item-complex>.item-content,.item.active.item-balanced,.item.active.item-balanced.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item .item-content.activated.item-energized,.item .item-content.activated.item-energized.item-complex>.item-content,.item .item-content.active.item-energized,.item .item-content.active.item-energized.item-complex>.item-content,.item-complex.activated .item-content.item-energized,.item-complex.activated .item-content.item-energized.item-complex>.item-content,.item-complex.active .item-content.item-energized,.item-complex.active .item-content.item-energized.item-complex>.item-content,.item.activated.item-energized,.item.activated.item-energized.item-complex>.item-content,.item.active.item-energized,.item.active.item-energized.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item .item-content.activated.item-royal,.item .item-content.activated.item-royal.item-complex>.item-content,.item .item-content.active.item-royal,.item .item-content.active.item-royal.item-complex>.item-content,.item-complex.activated .item-content.item-royal,.item-complex.activated .item-content.item-royal.item-complex>.item-content,.item-complex.active .item-content.item-royal,.item-complex.active .item-content.item-royal.item-complex>.item-content,.item.activated.item-royal,.item.activated.item-royal.item-complex>.item-content,.item.active.item-royal,.item.active.item-royal.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item .item-content.activated.item-dark,.item .item-content.activated.item-dark.item-complex>.item-content,.item .item-content.active.item-dark,.item .item-content.active.item-dark.item-complex>.item-content,.item-complex.activated .item-content.item-dark,.item-complex.activated .item-content.item-dark.item-complex>.item-content,.item-complex.active .item-content.item-dark,.item-complex.active .item-content.item-dark.item-complex>.item-content,.item.activated.item-dark,.item.activated.item-dark.item-complex>.item-content,.item.active.item-dark,.item.active.item-dark.item-complex>.item-content{border-color:#000;background-color:#262626}.item,.item h1,.item h2,.item h3,.item h4,.item h5,.item h6,.item p,.item-content,.item-content h1,.item-content h2,.item-content h3,.item-content h4,.item-content h5,.item-content h6,.item-content p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a.item{color:inherit;text-decoration:none}a.item:focus,a.item:hover{text-decoration:none}.item-complex,a.item.item-complex,button.item.item-complex{padding:0}.item-complex .item-content,.item-radio .item-content{position:relative;z-index:2;padding:16px 49px 16px 16px;border:none}a.item-content{display:block;color:inherit;text-decoration:none}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p,.item-complex.item-text-wrap,.item-complex.item-text-wrap .item-content,.item-complex.item-text-wrap h1,.item-complex.item-text-wrap h2,.item-complex.item-text-wrap h3,.item-complex.item-text-wrap h4,.item-complex.item-text-wrap h5,.item-complex.item-text-wrap h6,.item-complex.item-text-wrap p,.item-text-wrap,.item-text-wrap .item,.item-text-wrap .item-content,.item-text-wrap h1,.item-text-wrap h2,.item-text-wrap h3,.item-text-wrap h4,.item-text-wrap h5,.item-text-wrap h6,.item-text-wrap p{overflow:visible;white-space:normal}.item-complex.item-light>.item-content{border-color:#ddd;background-color:#fff;color:#444}.item-complex.item-light>.item-content.active,.item-complex.item-light>.item-content.active.item-complex>.item-content,.item-complex.item-light>.item-content:active,.item-complex.item-light>.item-content:active.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item-complex.item-stable>.item-content{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item-complex.item-stable>.item-content.active,.item-complex.item-stable>.item-content.active.item-complex>.item-content,.item-complex.item-stable>.item-content:active,.item-complex.item-stable>.item-content:active.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item-complex.item-positive>.item-content{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item-complex.item-positive>.item-content.active,.item-complex.item-positive>.item-content.active.item-complex>.item-content,.item-complex.item-positive>.item-content:active,.item-complex.item-positive>.item-content:active.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item-complex.item-calm>.item-content{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item-complex.item-calm>.item-content.active,.item-complex.item-calm>.item-content.active.item-complex>.item-content,.item-complex.item-calm>.item-content:active,.item-complex.item-calm>.item-content:active.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item-complex.item-assertive>.item-content{border-color:#e42112;background-color:#ef473a;color:#fff}.item-complex.item-assertive>.item-content.active,.item-complex.item-assertive>.item-content.active.item-complex>.item-content,.item-complex.item-assertive>.item-content:active,.item-complex.item-assertive>.item-content:active.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item-complex.item-balanced>.item-content{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item-complex.item-balanced>.item-content.active,.item-complex.item-balanced>.item-content.active.item-complex>.item-content,.item-complex.item-balanced>.item-content:active,.item-complex.item-balanced>.item-content:active.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item-complex.item-energized>.item-content{border-color:#e6b500;background-color:#ffc900;color:#fff}.item-complex.item-energized>.item-content.active,.item-complex.item-energized>.item-content.active.item-complex>.item-content,.item-complex.item-energized>.item-content:active,.item-complex.item-energized>.item-content:active.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item-complex.item-royal>.item-content{border-color:#6b46e5;background-color:#886aea;color:#fff}.item-complex.item-royal>.item-content.active,.item-complex.item-royal>.item-content.active.item-complex>.item-content,.item-complex.item-royal>.item-content:active,.item-complex.item-royal>.item-content:active.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item-complex.item-dark>.item-content{border-color:#111;background-color:#444;color:#fff}.item-complex.item-dark>.item-content.active,.item-complex.item-dark>.item-content.active.item-complex>.item-content,.item-complex.item-dark>.item-content:active,.item-complex.item-dark>.item-content:active.item-complex>.item-content{border-color:#000;background-color:#262626}.item-icon-left .icon,.item-icon-right .icon{display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-icon-left .icon:before,.item-icon-right .icon:before{display:block;width:32px;text-align:center}.item .fill-icon{min-width:30px;min-height:30px;font-size:28px}.item-icon-left{padding-left:54px}.item-complex.item-icon-left{padding-left:0}.item-complex.item-icon-left .item-content{padding-left:54px}.item-icon-right{padding-right:54px}.item-complex.item-icon-right{padding-right:0}.item-complex.item-icon-right .item-content{padding-right:54px}.item-icon-left.item-icon-right .icon:first-child{right:auto}.item-icon-left .item-delete .icon,.item-icon-left.item-icon-right .icon:last-child{left:auto}.item-icon-left .icon-accessory,.item-icon-right .icon-accessory{color:#ccc;font-size:16px}.item-icon-left .icon-accessory{left:3px}.item-icon-right .icon-accessory{right:3px}.item-button-left{padding-left:72px}.item-button-left .item-content>.button,.item-button-left>.button{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;left:11px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-left .item-content>.button .icon:before,.item-button-left>.button .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-left .item-content>.button>.button,.item-button-left>.button>.button{margin:0 2px;min-height:34px;font-size:18px;line-height:32px}.item-button-right,a.item.item-button-right,button.item.item-button-right{padding-right:80px}.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.button,.item-button-right>.buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;right:16px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-right .item-content>.button .icon:before,.item-button-right .item-content>.buttons .icon:before,.item-button-right>.button .icon:before,.item-button-right>.buttons .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-right .item-content>.button>.button,.item-button-right .item-content>.buttons>.button,.item-button-right>.button>.button,.item-button-right>.buttons>.button{margin:0 2px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{position:absolute;top:16px;width:100%;height:100%}.item-avatar-right,.item-avatar-right .item-content{padding-right:72px;min-height:72px}.item-avatar-right .item-content .item-image,.item-avatar-right .item-content>img:first-child,.item-avatar-right .item-image,.item-avatar-right>img:first-child{position:absolute;top:16px;right:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-thumbnail-left,.item-thumbnail-left .item-content{padding-top:8px;min-height:100px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{position:absolute;top:10px;left:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-left.item-complex,.item-avatar.item-complex,.item-thumbnail-left.item-complex{padding-top:0;padding-left:0}.item-thumbnail-right,.item-thumbnail-right .item-content{padding-top:8px;min-height:100px}.item-thumbnail-right .item-content .item-image,.item-thumbnail-right .item-content>img:first-child,.item-thumbnail-right .item-image,.item-thumbnail-right>img:first-child{position:absolute;top:10px;right:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-right.item-complex,.item-thumbnail-right.item-complex{padding-top:0;padding-right:0}.item-image{padding:0;text-align:center}.item-image .list-img,.item-image img:first-child{width:100%;vertical-align:middle}.item-body{overflow:auto;padding:16px;text-overflow:inherit;white-space:normal}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p{margin-top:16px;margin-bottom:16px}.item-divider{padding-top:8px;padding-bottom:8px;min-height:30px;background-color:#f5f5f5;color:#222;font-weight:500}.item-divider-ios,.platform-ios .item-divider-platform{padding-top:26px;text-transform:uppercase;font-weight:300;font-size:13px;background-color:#efeff4;color:#555}.item-divider-android,.platform-android .item-divider-platform{font-weight:300;font-size:13px}.item-note{float:right;color:#aaa;font-size:14px}.item-left-editable .item-content,.item-right-editable .item-content{-webkit-transition-duration:250ms;transition-duration:250ms;-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform}.item-left-editing.item-left-editable .item-content,.list-left-editing .item-left-editable .item-content{-webkit-transform:translate3d(50px,0,0);transform:translate3d(50px,0,0)}.item-remove-animate.ng-leave{-webkit-transition-duration:300ms;transition-duration:300ms}.item-remove-animate.ng-leave .item-content,.item-remove-animate.ng-leave:last-of-type{-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;-webkit-transition-property:all;transition-property:all}.item-remove-animate.ng-leave.ng-leave-active .item-content{opacity:0;-webkit-transform:translate3d(-100%,0,0)!important;transform:translate3d(-100%,0,0)!important}.item-remove-animate.ng-leave.ng-leave-active:last-of-type{opacity:0}.item-remove-animate.ng-leave.ng-leave-active~ion-item:not(.ng-leave){-webkit-transform:translate3d(0,-webkit-calc(-100% + 1px),0);transform:translate3d(0,calc(-100% + 1px),0);-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transition-timing-function:cubic-bezier(.25,.81,.24,1);transition-timing-function:cubic-bezier(.25,.81,.24,1);-webkit-transition-property:all;transition-property:all}.item-left-edit{-webkit-transition:all ease-in-out 125ms;transition:all ease-in-out 125ms;position:absolute;top:0;left:0;z-index:0;width:50px;height:100%;line-height:100%;display:none;opacity:0;-webkit-transform:translate3d(-21px,0,0);transform:translate3d(-21px,0,0)}.item-left-edit .button{height:100%}.item-left-edit .button.icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%}.item-left-edit.visible{display:block}.item-left-edit.visible.active{opacity:1;-webkit-transform:translate3d(8px,0,0);transform:translate3d(8px,0,0)}.list-left-editing .item-left-edit{-webkit-transition-delay:125ms;transition-delay:125ms}.item-delete .button.icon{color:#ef473a;font-size:24px}.item-delete .button.icon:hover{opacity:.7}.item-right-edit{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms;position:absolute;top:0;right:0;z-index:3;width:75px;height:100%;background:inherit;padding-left:20px;display:block;opacity:0;-webkit-transform:translate3d(75px,0,0);transform:translate3d(75px,0,0)}.item-right-edit .button{min-width:50px;height:100%}.item-right-edit .button.icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-right-edit.visible{display:block}.item-right-edit.visible.active{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.item-reorder .button.icon{color:#444;font-size:32px}.item-reordering{position:absolute;left:0;top:0;z-index:9;width:100%;box-shadow:0 0 10px 0 #aaa}.item-reordering .item-reorder{z-index:9}.item-placeholder{opacity:.7}.item-options{position:absolute;top:0;right:0;z-index:1;height:100%}.item-options .button{height:100%;border:none;border-radius:0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.item-options .button:before{margin:0 auto}.list{position:relative;padding-top:1px;padding-bottom:1px;padding-left:0;margin-bottom:20px}.list:last-child{margin-bottom:0}.list:last-child.card{margin-bottom:40px}.list-header{margin-top:20px;padding:5px 15px;background-color:transparent;color:#222;font-weight:700}.card.list .list-item{padding-right:1px;padding-left:1px}.card,.list-inset{overflow:hidden;margin:20px 10px;border-radius:2px;background-color:#fff}.card .item{border-left:0;border-right:0}.card .item:first-child{border-top:0}.card .item:last-child{border-bottom:0}.padding .card,.padding .list-inset{margin-left:0;margin-right:0}.card .item:first-child,.card .item:first-child .item-content,.list-inset .item:first-child,.list-inset .item:first-child .item-content,.padding>.list .item:first-child,.padding>.list .item:first-child .item-content{border-top-left-radius:2px;border-top-right-radius:2px}.card .item:last-child,.card .item:last-child .item-content,.list-inset .item:last-child,.list-inset .item:last-child .item-content,.padding>.list .item:last-child,.padding>.list .item:last-child .item-content{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.card .item:last-child,.list-inset .item:last-child{margin-bottom:-1px}.card .item,.list-inset .item,.padding-horizontal>.list .item,.padding>.list .item{margin-right:0;margin-left:0}.card .item.item-input input,.list-inset .item.item-input input,.padding-horizontal>.list .item.item-input input,.padding>.list .item.item-input input{padding-right:44px}.padding-left>.list .item{margin-left:0}.padding-right>.list .item{margin-right:0}.badge{background-color:transparent;color:#AAA;z-index:1;display:inline-block;padding:3px 8px;min-width:10px;border-radius:10px;vertical-align:baseline;text-align:center;white-space:nowrap;font-weight:700;font-size:14px;line-height:16px}.badge:empty{display:none}.badge.badge-light,.tabs .tab-item .badge.badge-light{background-color:#fff;color:#444}.badge.badge-stable,.tabs .tab-item .badge.badge-stable{background-color:#f8f8f8;color:#444}.badge.badge-positive,.tabs .tab-item .badge.badge-positive{background-color:#387ef5;color:#fff}.badge.badge-calm,.tabs .tab-item .badge.badge-calm{background-color:#11c1f3;color:#fff}.badge.badge-assertive,.tabs .tab-item .badge.badge-assertive{background-color:#ef473a;color:#fff}.badge.badge-balanced,.tabs .tab-item .badge.badge-balanced{background-color:#33cd5f;color:#fff}.badge.badge-energized,.tabs .tab-item .badge.badge-energized{background-color:#ffc900;color:#fff}.badge.badge-royal,.tabs .tab-item .badge.badge-royal{background-color:#886aea;color:#fff}.badge.badge-dark,.tabs .tab-item .badge.badge-dark{background-color:#444;color:#fff}.button .badge{position:relative;top:-1px}.slider{position:relative;visibility:hidden;overflow:hidden}.slider-slides{position:relative;height:100%}.slider-slide{position:relative;display:block;float:left;width:100%;height:100%;vertical-align:top}.slider-slide-image>img{width:100%}.slider-pager{position:absolute;bottom:20px;z-index:1;width:100%;height:15px;text-align:center}.slider-pager .slider-pager-page{display:inline-block;margin:0 3px;width:15px;color:#000;text-decoration:none;opacity:.3}.slider-pager .slider-pager-page.active{-webkit-transition:opacity .4s ease-in;transition:opacity .4s ease-in;opacity:1}.slider-pager-page.ng-animate,.slider-pager-page.ng-enter,.slider-pager-page.ng-leave,.slider-slide.ng-animate,.slider-slide.ng-enter,.slider-slide.ng-leave{-webkit-transition:none!important;transition:none!important}.slider-pager-page.ng-animate,.slider-slide.ng-animate{-webkit-animation:none 0s;animation:none 0s}.swiper-container{margin:0 auto;position:relative;z-index:1}.swiper-container-no-flexbox .swiper-slide{float:left}.swiper-container-vertical>.swiper-wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.swiper-wrapper{z-index:1;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate(0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.swiper-container-multirow>.swiper-wrapper{-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{display:block;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;position:relative}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform,height}.swiper-container .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-wp8-horizontal{-ms-touch-action:pan-y;touch-action:pan-y}.swiper-wp8-vertical{-ms-touch-action:pan-x;touch-action:pan-x}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:27px;height:44px;margin-top:-22px;z-index:10;cursor:pointer;-moz-background-size:27px 44px;-webkit-background-size:27px 44px;background-size:27px 44px;background-position:center;background-repeat:no-repeat}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-prev,.swiper-container-rtl .swiper-button-next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");left:10px;right:auto}.swiper-button-prev.swiper-button-black,.swiper-container-rtl .swiper-button-next.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-prev.swiper-button-white,.swiper-container-rtl .swiper-button-next.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next,.swiper-container-rtl .swiper-button-prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");right:10px;left:auto}.swiper-button-next.swiper-button-black,.swiper-container-rtl .swiper-button-prev.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next.swiper-button-white,.swiper-container-rtl .swiper-button-prev.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-pagination{position:absolute;text-align:center;-webkit-transition:300ms;-moz-transition:300ms;-o-transition:300ms;transition:300ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2}button.swiper-pagination-bullet{border:none;margin:0;padding:0;box-shadow:none;-moz-appearance:none;-ms-appearance:none;-webkit-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-white .swiper-pagination-bullet{background:#fff}.swiper-pagination-bullet-active{opacity:1}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);-moz-transform:translate3d(0,-50%,0);-o-transform:translate(0,-50%);-ms-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination{bottom:10px;left:0;width:100%}.swiper-container-horizontal>.swiper-pagination .swiper-pagination-bullet{margin:0 5px}.swiper-container-3d{-webkit-perspective:1200px;-moz-perspective:1200px;-o-perspective:1200px;perspective:1200px}.swiper-container-3d .swiper-cube-shadow,.swiper-container-3d .swiper-slide,.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top,.swiper-container-3d .swiper-wrapper{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d}.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-container-3d .swiper-slide-shadow-left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to left,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-right{background-image:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to right,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-top{background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to top,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-bottom{background-image:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to bottom,rgba(0,0,0,.5),transparent)}.swiper-container-coverflow .swiper-wrapper{-ms-perspective:1200px}.swiper-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide,.swiper-container-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide-active,.swiper-container-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube{overflow:visible}.swiper-container-cube .swiper-slide{pointer-events:none;visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;width:100%;height:100%;z-index:1}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-next,.swiper-container-cube .swiper-slide-next+.swiper-slide,.swiper-container-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-container-cube .swiper-slide-shadow-bottom,.swiper-container-cube .swiper-slide-shadow-left,.swiper-container-cube .swiper-slide-shadow-right,.swiper-container-cube .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0;width:100%;height:100%;background:#000;opacity:.6;-webkit-filter:blur(50px);filter:blur(50px);z-index:0}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-container-horizontal>.swiper-scrollbar{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-container-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;-webkit-transform-origin:50%;-moz-transform-origin:50%;transform-origin:50%;-webkit-animation:swiper-preloader-spin 1s steps(12,end) infinite;-moz-animation:swiper-preloader-spin 1s steps(12,end) infinite;animation:swiper-preloader-spin 1s steps(12,end) infinite}.swiper-lazy-preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");background-position:50%;-webkit-background-size:100%;background-size:100%;background-repeat:no-repeat}.swiper-lazy-preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}@-webkit-keyframes swiper-preloader-spin{100%{-webkit-transform:rotate(360deg)}}@keyframes swiper-preloader-spin{100%{transform:rotate(360deg)}}ion-slides{width:100%;height:100%;display:block}.slide-zoom{display:block;width:100%;text-align:center}.swiper-container{width:100%;height:100%;padding:0;overflow:hidden}.swiper-wrapper{position:absolute;left:0;top:0;width:100%;height:100%;padding:0}.swiper-slide{width:100%;height:100%;box-sizing:border-box}.swiper-slide img{width:auto;height:auto;max-width:100%;max-height:100%}.scroll-refresher{position:absolute;top:-60px;right:0;left:0;overflow:hidden;margin:auto;height:60px}.scroll-refresher .ionic-refresher-content{position:absolute;bottom:15px;left:0;width:100%;color:#666;text-align:center;font-size:30px}.scroll-refresher .ionic-refresher-content .text-pulling,.scroll-refresher .ionic-refresher-content .text-refreshing{font-size:16px;line-height:16px}.scroll-refresher .ionic-refresher-content.ionic-refresher-with-text{bottom:10px}.scroll-refresher .icon-pulling,.scroll-refresher .icon-refreshing{width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.scroll-refresher .icon-pulling{-webkit-animation-name:refresh-spin-back;animation-name:refresh-spin-back;-webkit-animation-duration:200ms;animation-duration:200ms;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-transform:translate3d(0,0,0) rotate(0deg);transform:translate3d(0,0,0) rotate(0deg)}.scroll-refresher .icon-refreshing,.scroll-refresher .text-refreshing{display:none}.scroll-refresher .icon-refreshing{-webkit-animation-duration:1.5s;animation-duration:1.5s}.scroll-refresher.active .icon-pulling:not(.pulling-rotation-disabled){-webkit-animation-name:refresh-spin;animation-name:refresh-spin;-webkit-transform:translate3d(0,0,0) rotate(-180deg);transform:translate3d(0,0,0) rotate(-180deg)}.scroll-refresher.active.refreshing{-webkit-transition:transform .2s;transition:transform .2s;-webkit-transform:scale(1,1);transform:scale(1,1)}.scroll-refresher.active.refreshing .icon-pulling,.scroll-refresher.active.refreshing .text-pulling{display:none}.scroll-refresher.active.refreshing .icon-refreshing,.scroll-refresher.active.refreshing .text-refreshing{display:block}.scroll-refresher.active.refreshing.refreshing-tail{-webkit-transform:scale(0,0);transform:scale(0,0)}.overflow-scroll>.scroll{-webkit-overflow-scrolling:touch;width:100%}.overflow-scroll>.scroll.overscroll{position:fixed;right:0;left:0}.overflow-scroll.padding>.scroll.overscroll{padding:10px}@-webkit-keyframes refresh-spin{0%{-webkit-transform:translate3d(0,0,0) rotate(0)}100%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}}@keyframes refresh-spin{0%{transform:translate3d(0,0,0) rotate(0)}100%{transform:translate3d(0,0,0) rotate(180deg)}}@-webkit-keyframes refresh-spin-back{0%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}100%{-webkit-transform:translate3d(0,0,0) rotate(0)}}@keyframes refresh-spin-back{0%{transform:translate3d(0,0,0) rotate(180deg)}100%{transform:translate3d(0,0,0) rotate(0)}}.spinner{stroke:#444;fill:#444}.spinner svg{width:28px;height:28px}.spinner.spinner-light{stroke:#fff;fill:#fff}.spinner.spinner-stable{stroke:#f8f8f8;fill:#f8f8f8}.spinner.spinner-positive{stroke:#387ef5;fill:#387ef5}.spinner.spinner-calm{stroke:#11c1f3;fill:#11c1f3}.spinner.spinner-balanced{stroke:#33cd5f;fill:#33cd5f}.spinner.spinner-assertive{stroke:#ef473a;fill:#ef473a}.spinner.spinner-energized{stroke:#ffc900;fill:#ffc900}.spinner.spinner-royal{stroke:#886aea;fill:#886aea}.spinner.spinner-dark{stroke:#444;fill:#444}.spinner-android{stroke:#4b8bf4}.spinner-ios,.spinner-ios-small{stroke:#69717d}.spinner-spiral .stop1{stop-color:#fff;stop-opacity:0}.spinner-spiral.spinner-light .stop1{stop-color:#444}.spinner-spiral.spinner-light .stop2{stop-color:#fff}.spinner-spiral.spinner-stable .stop2{stop-color:#f8f8f8}.spinner-spiral.spinner-positive .stop2{stop-color:#387ef5}.spinner-spiral.spinner-calm .stop2{stop-color:#11c1f3}.spinner-spiral.spinner-balanced .stop2{stop-color:#33cd5f}.spinner-spiral.spinner-assertive .stop2{stop-color:#ef473a}.spinner-spiral.spinner-energized .stop2{stop-color:#ffc900}.spinner-spiral.spinner-royal .stop2{stop-color:#886aea}.spinner-spiral.spinner-dark .stop2{stop-color:#444}form{margin:0 0 1.42857}legend{display:block;margin-bottom:1.42857;padding:0;width:100%;border:1px solid #ddd;color:#444;font-size:21px;line-height:2.85714}legend small{color:#f8f8f8;font-size:1.07143}button,input,label,select,textarea{font-weight:400;font-size:14px;line-height:1.42857}button,input,select,textarea{font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif}.item-input{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:6px 0 5px 16px}.item-input input{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 220px;-moz-box-flex:1;-moz-flex:1 220px;-ms-flex:1 220px;flex:1 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;padding-right:24px;background-color:transparent}.item-input .button .icon{-webkit-box-flex:0;-webkit-flex:0 0 24px;-moz-box-flex:0;-moz-flex:0 0 24px;-ms-flex:0 0 24px;flex:0 0 24px;position:static;display:inline-block;height:auto;text-align:center;font-size:16px}.item-input .button-bar{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 0 220px;-moz-box-flex:1;-moz-flex:1 0 220px;-ms-flex:1 0 220px;flex:1 0 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.item-input .icon{min-width:14px}.platform-windowsphone .item-input input{flex-shrink:1}.item-input-inset{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:10.67px}.item-input-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-moz-flex:1 0;-ms-flex:1 0;flex:1 0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-border-radius:4px;border-radius:4px;padding-right:8px;padding-left:8px;background:#eee}.item-input-inset .item-input-wrapper input{padding-left:4px;height:29px;background:0 0;line-height:18px}.item-input-wrapper~.button{margin-left:10.67px}.input-label{display:table;padding:7px 10px 7px 0;max-width:200px;width:35%;color:#444;font-size:16px}.placeholder-icon{color:#aaa}.placeholder-icon:first-child{padding-right:6px}.placeholder-icon:last-child{padding-left:6px}.item-stacked-label{display:block;background-color:transparent;box-shadow:none}.item-stacked-label .icon,.item-stacked-label .input-label{display:inline-block;padding:4px 0 0;vertical-align:middle}.item-stacked-label input,.item-stacked-label textarea{-webkit-border-radius:2px;border-radius:2px;padding:4px 8px 3px 0;border:none;background-color:#fff}.item-stacked-label input{overflow:hidden;height:46px}.item-select.item-stacked-label select{position:relative;padding:0;max-width:90%;direction:ltr;white-space:pre-wrap;margin:-3px}.item-floating-label{display:block;background-color:transparent;box-shadow:none}.item-floating-label .input-label{position:relative;padding:5px 0 0;opacity:0;top:10px;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}.item-floating-label .input-label.has-input{opacity:1;top:0;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}input[type=search],input[type=text],input[type=password],input[type=datetime],input[type=datetime-local],input[type=date],input[type=month],input[type=time],input[type=week],input[type=number],input[type=email],input[type=url],input[type=tel],input[type=color],textarea{display:block;padding-top:2px;padding-left:0;height:34px;color:#111;vertical-align:middle;font-size:14px;line-height:16px}.platform-android input[type=datetime-local],.platform-android input[type=date],.platform-android input[type=month],.platform-android input[type=time],.platform-android input[type=week],.platform-ios input[type=datetime-local],.platform-ios input[type=date],.platform-ios input[type=month],.platform-ios input[type=time],.platform-ios input[type=week]{padding-top:8px}.item-input input,.item-input textarea{width:100%}textarea{padding-left:0}textarea::-moz-placeholder{color:#aaa}textarea:-ms-input-placeholder{color:#aaa}textarea::-webkit-input-placeholder{color:#aaa;text-indent:-3px}textarea{height:auto}input[type=search],input[type=text],input[type=password],input[type=datetime],input[type=datetime-local],input[type=date],input[type=month],input[type=time],input[type=week],input[type=number],input[type=email],input[type=url],input[type=tel],input[type=color],textarea{border:0}input[type=radio],input[type=checkbox]{margin:0;line-height:normal}.item-input input[type=button],.item-input input[type=reset],.item-input input[type=submit],.item-input input[type=radio],.item-input input[type=checkbox],.item-input input[type=file],.item-input input[type=image]{width:auto}input[type=file]{line-height:34px}.cloned-text-input+input,.cloned-text-input+textarea,.previous-input-focus{position:absolute!important;left:-9999px;width:200px}input::-moz-placeholder,textarea::-moz-placeholder{color:#aaa}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#aaa}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#aaa;text-indent:0}input[disabled],input[readonly]:not(.cloned-text-input),select[disabled],select[readonly],textarea[disabled],textarea[readonly]:not(.cloned-text-input){background-color:#f8f8f8;cursor:not-allowed}input[type=radio][disabled],input[type=radio][readonly],input[type=checkbox][disabled],input[type=checkbox][readonly]{background-color:transparent}.checkbox{position:relative;display:inline-block;padding:7px;cursor:pointer}.checkbox .checkbox-icon:before,.checkbox input:before{border-color:#ddd}.checkbox input:checked+.checkbox-icon:before,.checkbox input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-light .checkbox-icon:before,.checkbox-light input:before{border-color:#ddd}.checkbox-light input:checked+.checkbox-icon:before,.checkbox-light input:checked:before{background:#ddd;border-color:#ddd}.checkbox-stable .checkbox-icon:before,.checkbox-stable input:before{border-color:#b2b2b2}.checkbox-stable input:checked+.checkbox-icon:before,.checkbox-stable input:checked:before{background:#b2b2b2;border-color:#b2b2b2}.checkbox-positive .checkbox-icon:before,.checkbox-positive input:before{border-color:#387ef5}.checkbox-positive input:checked+.checkbox-icon:before,.checkbox-positive input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-calm .checkbox-icon:before,.checkbox-calm input:before{border-color:#11c1f3}.checkbox-calm input:checked+.checkbox-icon:before,.checkbox-calm input:checked:before{background:#11c1f3;border-color:#11c1f3}.checkbox-assertive .checkbox-icon:before,.checkbox-assertive input:before{border-color:#ef473a}.checkbox-assertive input:checked+.checkbox-icon:before,.checkbox-assertive input:checked:before{background:#ef473a;border-color:#ef473a}.checkbox-balanced .checkbox-icon:before,.checkbox-balanced input:before{border-color:#33cd5f}.checkbox-balanced input:checked+.checkbox-icon:before,.checkbox-balanced input:checked:before{background:#33cd5f;border-color:#33cd5f}.checkbox-energized .checkbox-icon:before,.checkbox-energized input:before{border-color:#ffc900}.checkbox-energized input:checked+.checkbox-icon:before,.checkbox-energized input:checked:before{background:#ffc900;border-color:#ffc900}.checkbox-royal .checkbox-icon:before,.checkbox-royal input:before{border-color:#886aea}.checkbox-royal input:checked+.checkbox-icon:before,.checkbox-royal input:checked:before{background:#886aea;border-color:#886aea}.checkbox-dark .checkbox-icon:before,.checkbox-dark input:before{border-color:#444}.checkbox-dark input:checked+.checkbox-icon:before,.checkbox-dark input:checked:before{background:#444;border-color:#444}.checkbox input:disabled+.checkbox-icon:before,.checkbox input:disabled:before{border-color:#ddd}.checkbox input:disabled:checked+.checkbox-icon:before,.checkbox input:disabled:checked:before{background:#ddd}.checkbox.checkbox-input-hidden input{display:none!important}.checkbox input,.checkbox-icon{position:relative;width:28px;height:28px;display:block;border:0;background:0 0;cursor:pointer;-webkit-appearance:none}.checkbox input:before,.checkbox-icon:before{display:table;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:28px;background:#fff;content:' ';-webkit-transition:background-color 20ms ease-in-out;transition:background-color 20ms ease-in-out}.checkbox input:checked:before,input:checked+.checkbox-icon:before{border-width:2px}.checkbox input:after,.checkbox-icon:after{-webkit-transition:opacity .05s ease-in-out;transition:opacity .05s ease-in-out;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);position:absolute;top:33%;left:25%;display:table;width:14px;height:6px;border:1px solid #fff;border-top:0;border-right:0;content:' ';opacity:0}.checkbox-square .checkbox-icon:before,.checkbox-square input:before,.platform-android .checkbox-platform .checkbox-icon:before,.platform-android .checkbox-platform input:before{border-radius:2px;width:72%;height:72%;margin-top:14%;margin-left:14%;border-width:2px}.checkbox-square .checkbox-icon:after,.checkbox-square input:after,.platform-android .checkbox-platform .checkbox-icon:after,.platform-android .checkbox-platform input:after{border-width:2px;top:19%;left:25%;width:13px;height:7px}.platform-android .item-checkbox-right .checkbox-square .checkbox-icon::after{top:31%}.grade-c .checkbox input:after,.grade-c .checkbox-icon:after{-webkit-transform:rotate(0);transform:rotate(0);top:3px;left:4px;border:none;color:#fff;content:'\2713';font-weight:700;font-size:20px}.checkbox input:checked:after,input:checked+.checkbox-icon:after{opacity:1}.item-checkbox{padding-left:60px}.item-checkbox.active{box-shadow:none}.item-checkbox .checkbox{position:absolute;top:50%;right:8px;left:8px;z-index:3;margin-top:-21px}.item-checkbox.item-checkbox-right{padding-right:60px;padding-left:16px}.item-checkbox-right .checkbox input,.item-checkbox-right .checkbox-icon{float:right}.item-toggle{pointer-events:none}.toggle{position:relative;display:inline-block;pointer-events:auto;margin:-5px;padding:5px}.toggle input:checked+.track{border-color:#4cd964;background-color:#4cd964}.toggle.dragging .handle{background-color:#f2f2f2!important}.toggle.toggle-light input:checked+.track{border-color:#ddd;background-color:#ddd}.toggle.toggle-stable input:checked+.track{border-color:#b2b2b2;background-color:#b2b2b2}.toggle.toggle-positive input:checked+.track{border-color:#387ef5;background-color:#387ef5}.toggle.toggle-calm input:checked+.track{border-color:#11c1f3;background-color:#11c1f3}.toggle.toggle-assertive input:checked+.track{border-color:#ef473a;background-color:#ef473a}.toggle.toggle-balanced input:checked+.track{border-color:#33cd5f;background-color:#33cd5f}.toggle.toggle-energized input:checked+.track{border-color:#ffc900;background-color:#ffc900}.toggle.toggle-royal input:checked+.track{border-color:#886aea;background-color:#886aea}.toggle.toggle-dark input:checked+.track{border-color:#444;background-color:#444}.toggle input{display:none}.toggle .track{-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:background-color,border;transition-property:background-color,border;display:inline-block;box-sizing:border-box;width:51px;height:31px;border:2px solid #e6e6e6;border-radius:20px;background-color:#fff;content:' ';cursor:pointer;pointer-events:none}.platform-android4_2 .toggle .track{-webkit-background-clip:padding-box}.toggle .handle{-webkit-transition:.3s cubic-bezier(0,1.1,1,1.1);transition:.3s cubic-bezier(0,1.1,1,1.1);-webkit-transition-property:background-color,transform;transition-property:background-color,transform;position:absolute;display:block;width:27px;height:27px;border-radius:27px;background-color:#fff;top:7px;left:7px;box-shadow:0 2px 7px rgba(0,0,0,.35),0 1px 1px rgba(0,0,0,.15)}.toggle .handle:before{position:absolute;top:-4px;left:-21.5px;padding:18.5px 34px;content:" "}.toggle input:checked+.track .handle{-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0);background-color:#fff}.item-toggle.active{box-shadow:none}.item-toggle,.item-toggle.item-complex .item-content{padding-right:99px}.item-toggle.item-complex{padding-right:0}.item-toggle .toggle{position:absolute;top:10px;right:16px;z-index:3}.toggle input:disabled+.track{opacity:.6}.toggle-small .track{border:0;width:34px;height:15px;background:#9e9e9e}.toggle-small input:checked+.track{background:rgba(0,150,137,.5)}.toggle-small .handle{top:2px;left:4px;width:21px;height:21px;box-shadow:0 2px 5px rgba(0,0,0,.25)}.toggle-small input:checked+.track .handle{-webkit-transform:translate3d(16px,0,0);transform:translate3d(16px,0,0);background:#009689}.toggle-small.item-toggle .toggle{top:19px}.toggle-small .toggle-light input:checked+.track{background-color:rgba(221,221,221,.5)}.toggle-small .toggle-light input:checked+.track .handle{background-color:#ddd}.toggle-small .toggle-stable input:checked+.track{background-color:rgba(178,178,178,.5)}.toggle-small .toggle-stable input:checked+.track .handle{background-color:#b2b2b2}.toggle-small .toggle-positive input:checked+.track{background-color:rgba(56,126,245,.5)}.toggle-small .toggle-positive input:checked+.track .handle{background-color:#387ef5}.toggle-small .toggle-calm input:checked+.track{background-color:rgba(17,193,243,.5)}.toggle-small .toggle-calm input:checked+.track .handle{background-color:#11c1f3}.toggle-small .toggle-assertive input:checked+.track{background-color:rgba(239,71,58,.5)}.toggle-small .toggle-assertive input:checked+.track .handle{background-color:#ef473a}.toggle-small .toggle-balanced input:checked+.track{background-color:rgba(51,205,95,.5)}.toggle-small .toggle-balanced input:checked+.track .handle{background-color:#33cd5f}.toggle-small .toggle-energized input:checked+.track{background-color:rgba(255,201,0,.5)}.toggle-small .toggle-energized input:checked+.track .handle{background-color:#ffc900}.toggle-small .toggle-royal input:checked+.track{background-color:rgba(136,106,234,.5)}.toggle-small .toggle-royal input:checked+.track .handle{background-color:#886aea}.toggle-small .toggle-dark input:checked+.track{background-color:rgba(68,68,68,.5)}.toggle-small .toggle-dark input:checked+.track .handle{background-color:#444}.item-radio{padding:0}.item-radio:hover{cursor:pointer}.item-radio .item-content{padding-right:64px}.item-radio .radio-icon{position:absolute;top:0;right:0;z-index:3;visibility:hidden;padding:14px;height:100%;font-size:24px}.item-radio input{position:absolute;left:-9999px}.item-radio input:checked+.radio-content .item-content{background:#f7f7f7}.item-radio input:checked+.radio-content .radio-icon{visibility:visible}.range input{overflow:hidden;margin-top:5px;margin-bottom:5px;padding-right:2px;padding-left:1px;width:auto;height:43px;outline:0;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(0,#ccc),color-stop(100%,#ccc)) center no-repeat;background:linear-gradient(to right,#ccc 0,#ccc 100%) center no-repeat;background-size:99% 2px;-webkit-appearance:none}.range input::-moz-focus-outer{border:0}.range input::-webkit-slider-thumb{position:relative;width:28px;height:28px;border-radius:50%;background-color:#fff;box-shadow:0 0 2px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2);cursor:pointer;-webkit-appearance:none;border:0}.range input::-webkit-slider-thumb:before{position:absolute;top:13px;left:-2001px;width:2000px;height:2px;background:#444;content:' '}.range input::-webkit-slider-thumb:after{position:absolute;top:-15px;left:-15px;padding:30px;content:' '}.range input::-ms-fill-lower{height:2px;background:#444}.range{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;padding:2px 11px}.range.range-light input::-webkit-slider-thumb:before{background:#ddd}.range.range-light input::-ms-fill-lower{background:#ddd}.range.range-stable input::-webkit-slider-thumb:before{background:#b2b2b2}.range.range-stable input::-ms-fill-lower{background:#b2b2b2}.range.range-positive input::-webkit-slider-thumb:before{background:#387ef5}.range.range-positive input::-ms-fill-lower{background:#387ef5}.range.range-calm input::-webkit-slider-thumb:before{background:#11c1f3}.range.range-calm input::-ms-fill-lower{background:#11c1f3}.range.range-balanced input::-webkit-slider-thumb:before{background:#33cd5f}.range.range-balanced input::-ms-fill-lower{background:#33cd5f}.range.range-assertive input::-webkit-slider-thumb:before{background:#ef473a}.range.range-assertive input::-ms-fill-lower{background:#ef473a}.range.range-energized input::-webkit-slider-thumb:before{background:#ffc900}.range.range-energized input::-ms-fill-lower{background:#ffc900}.range.range-royal input::-webkit-slider-thumb:before{background:#886aea}.range.range-royal input::-ms-fill-lower{background:#886aea}.range.range-dark input::-webkit-slider-thumb:before{background:#444}.range.range-dark input::-ms-fill-lower{background:#444}.range .icon{-webkit-box-flex:0;-webkit-flex:0;-moz-box-flex:0;-moz-flex:0;-ms-flex:0;flex:0;display:block;min-width:24px;text-align:center;font-size:24px}.range input{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;margin-right:10px;margin-left:10px}.range-label{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-moz-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;display:block;white-space:nowrap}.range-label:first-child{padding-left:5px}.range input+.range-label{padding-right:5px;padding-left:0}.platform-windowsphone .range input{height:auto}.item-select{position:relative}.item-select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:absolute;top:0;bottom:0;right:0;padding:0 48px 0 16px;max-width:65%;border:none;background:#fff;color:#333;text-indent:.01px;text-overflow:'';white-space:nowrap;font-size:14px;cursor:pointer;direction:rtl}.item-select select::-ms-expand{display:none}.item-select option{direction:ltr}.item-select:after{position:absolute;top:50%;right:16px;margin-top:-3px;width:0;height:0;border-top:5px solid;border-right:5px solid transparent;border-left:5px solid transparent;color:#999;content:"";pointer-events:none}.item-select.item-light select{background:#fff;color:#444}.item-select.item-stable select{background:#f8f8f8;color:#444}.item-select.item-stable .input-label,.item-select.item-stable:after{color:#666}.item-select.item-positive select{background:#387ef5;color:#fff}.item-select.item-positive .input-label,.item-select.item-positive:after{color:#fff}.item-select.item-calm select{background:#11c1f3;color:#fff}.item-select.item-calm .input-label,.item-select.item-calm:after{color:#fff}.item-select.item-assertive select{background:#ef473a;color:#fff}.item-select.item-assertive .input-label,.item-select.item-assertive:after{color:#fff}.item-select.item-balanced select{background:#33cd5f;color:#fff}.item-select.item-balanced .input-label,.item-select.item-balanced:after{color:#fff}.item-select.item-energized select{background:#ffc900;color:#fff}.item-select.item-energized .input-label,.item-select.item-energized:after{color:#fff}.item-select.item-royal select{background:#886aea;color:#fff}.item-select.item-royal .input-label,.item-select.item-royal:after{color:#fff}.item-select.item-dark select{background:#444;color:#fff}.item-select.item-dark .input-label,.item-select.item-dark:after{color:#fff}select[multiple],select[size]{height:auto}progress{display:block;margin:15px auto;width:100%}.button{background-color:#f8f8f8;color:#444;min-width:52px;min-height:47px;vertical-align:top;text-overflow:ellipsis;line-height:42px}.button:hover{color:#444;text-decoration:none}.button.activated,.button.active{background-color:#e5e5e5}.button:after{position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px;content:' '}.button .icon{vertical-align:top;pointer-events:none}.button .icon:before,.button.icon-left:before,.button.icon-right:before,.button.icon:before{display:inline-block;padding:0 0 1px;vertical-align:inherit;font-size:24px;line-height:41px;pointer-events:none}.button.icon-left:before{float:left;padding-right:.2em;padding-left:0}.button.icon-right:before{float:right;padding-right:0;padding-left:.2em}.button.button-block,.button.button-full{margin-top:10px;margin-bottom:10px}.button.button-light{border-color:transparent;background-color:#fff;color:#444}.button.button-light:hover{color:#444;text-decoration:none}.button.button-light.activated,.button.button-light.active{background-color:#fafafa}.button.button-light.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ddd}.button.button-light.button-icon{border-color:transparent;background:0 0}.button.button-light.button-outline{border-color:#ddd;background:0 0;color:#ddd}.button.button-light.button-outline.activated,.button.button-light.button-outline.active{background-color:#ddd;box-shadow:none;color:#fff}.button.button-stable{border-color:transparent;background-color:#f8f8f8;color:#444}.button.button-stable:hover{color:#444;text-decoration:none}.button.button-stable.activated,.button.button-stable.active{background-color:#e5e5e5}.button.button-stable.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button.button-stable.button-icon{border-color:transparent;background:0 0}.button.button-stable.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button.button-stable.button-outline.activated,.button.button-stable.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.button.button-positive{border-color:transparent;background-color:#387ef5;color:#fff}.button.button-positive:hover{color:#fff;text-decoration:none}.button.button-positive.activated,.button.button-positive.active{background-color:#0c60ee}.button.button-positive.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#387ef5}.button.button-positive.button-icon{border-color:transparent;background:0 0}.button.button-positive.button-outline{border-color:#387ef5;background:0 0;color:#387ef5}.button.button-positive.button-outline.activated,.button.button-positive.button-outline.active{background-color:#387ef5;box-shadow:none;color:#fff}.button.button-calm{border-color:transparent;background-color:#11c1f3;color:#fff}.button.button-calm:hover{color:#fff;text-decoration:none}.button.button-calm.activated,.button.button-calm.active{background-color:#0a9dc7}.button.button-calm.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#11c1f3}.button.button-calm.button-icon{border-color:transparent;background:0 0}.button.button-calm.button-outline{border-color:#11c1f3;background:0 0;color:#11c1f3}.button.button-calm.button-outline.activated,.button.button-calm.button-outline.active{background-color:#11c1f3;box-shadow:none;color:#fff}.button.button-assertive{border-color:transparent;background-color:#ef473a;color:#fff}.button.button-assertive:hover{color:#fff;text-decoration:none}.button.button-assertive.activated,.button.button-assertive.active{background-color:#e42112}.button.button-assertive.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ef473a}.button.button-assertive.button-icon{border-color:transparent;background:0 0}.button.button-assertive.button-outline{border-color:#ef473a;background:0 0;color:#ef473a}.button.button-assertive.button-outline.activated,.button.button-assertive.button-outline.active{background-color:#ef473a;box-shadow:none;color:#fff}.button.button-balanced{border-color:transparent;background-color:#33cd5f;color:#fff}.button.button-balanced:hover{color:#fff;text-decoration:none}.button.button-balanced.activated,.button.button-balanced.active{background-color:#28a54c}.button.button-balanced.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#33cd5f}.button.button-balanced.button-icon{border-color:transparent;background:0 0}.button.button-balanced.button-outline{border-color:#33cd5f;background:0 0;color:#33cd5f}.button.button-balanced.button-outline.activated,.button.button-balanced.button-outline.active{background-color:#33cd5f;box-shadow:none;color:#fff}.button.button-energized{border-color:transparent;background-color:#ffc900;color:#fff}.button.button-energized:hover{color:#fff;text-decoration:none}.button.button-energized.activated,.button.button-energized.active{background-color:#e6b500}.button.button-energized.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ffc900}.button.button-energized.button-icon{border-color:transparent;background:0 0}.button.button-energized.button-outline{border-color:#ffc900;background:0 0;color:#ffc900}.button.button-energized.button-outline.activated,.button.button-energized.button-outline.active{background-color:#ffc900;box-shadow:none;color:#fff}.button.button-royal{border-color:transparent;background-color:#886aea;color:#fff}.button.button-royal:hover{color:#fff;text-decoration:none}.button.button-royal.activated,.button.button-royal.active{background-color:#6b46e5}.button.button-royal.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#886aea}.button.button-royal.button-icon{border-color:transparent;background:0 0}.button.button-royal.button-outline{border-color:#886aea;background:0 0;color:#886aea}.button.button-royal.button-outline.activated,.button.button-royal.button-outline.active{background-color:#886aea;box-shadow:none;color:#fff}.button.button-dark{border-color:transparent;background-color:#444;color:#fff}.button.button-dark:hover{color:#fff;text-decoration:none}.button.button-dark.activated,.button.button-dark.active{background-color:#262626}.button.button-dark.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444}.button.button-dark.button-icon{border-color:transparent;background:0 0}.button.button-dark.button-outline{border-color:#444;background:0 0;color:#444}.button.button-dark.button-outline.activated,.button.button-dark.button-outline.active{background-color:#444;box-shadow:none;color:#fff}.button-small{padding:2px 4px 1px;min-width:28px;min-height:30px;font-size:12px;line-height:26px}.button-small .icon:before,.button-small.icon-left:before,.button-small.icon-right:before,.button-small.icon:before{font-size:16px;line-height:19px;margin-top:3px}.button-large{padding:0 16px;min-width:68px;min-height:59px;font-size:20px;line-height:53px}.button-large .icon:before,.button-large.icon-left:before,.button-large.icon-right:before,.button-large.icon:before{padding-bottom:2px;font-size:32px;line-height:51px}.button-icon{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;min-width:initial;border-color:transparent;background:0 0}.button-icon.button.activated,.button-icon.button.active{border-color:transparent;background:0 0;box-shadow:none}.button-icon .icon:before,.button-icon.icon:before{font-size:32px}.button-clear{padding:0 6px;max-height:42px;background:0 0;box-shadow:none}.button-clear.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button-clear.button-icon{border-color:transparent;background:0 0}.button-clear.activated,.button-clear.active{opacity:.3}.button-outline{-webkit-transition:opacity .1s;transition:opacity .1s;background:0 0;box-shadow:none}.button-outline.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button-outline.button-outline.activated,.button-outline.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.padding>.button.button-block:first-child{margin-top:0}.button-block{display:block;clear:both}.button-block:after{clear:both}.button-full,.button-full>.button{display:block;margin-right:0;margin-left:0;border-right-width:0;border-left-width:0;border-radius:0}.button-full>button.button,button.button-block,button.button-full,input.button.button-block{width:100%}a.button{text-decoration:none}a.button .icon:before,a.button.icon-left:before,a.button.icon-right:before,a.button.icon:before{margin-top:2px}.button.disabled,.button[disabled]{opacity:.4;cursor:default!important;pointer-events:none}.button-bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;width:100%}.button-bar.button-bar-inline{display:block;width:auto}.button-bar.button-bar-inline:after,.button-bar.button-bar-inline:before{display:table;content:"";line-height:0}.button-bar.button-bar-inline:after{clear:both}.button-bar.button-bar-inline>.button{width:auto;display:inline-block;float:left}.button-bar>.button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;padding:0 16px;width:0;border-width:1px 0 1px 1px;border-radius:0;text-align:center;text-overflow:ellipsis;white-space:nowrap}.button-bar>.button:first-child{border-radius:4px 0 0 4px}.button-bar>.button:last-child{border-right-width:1px;border-radius:0 4px 4px 0}.button-bar>.button:only-child{border-radius:4px}.button-bar>.button-small .icon:before,.button-bar>.button-small:before{line-height:28px}.row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:5px;width:100%}.row-wrap{-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.row-no-padding,.row-no-padding>.col{padding:0}.row+.row{margin-top:-5px;padding-top:0}.col{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;padding:5px;width:100%}.row-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;-moz-align-items:flex-start;align-items:flex-start}.row-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;-moz-align-items:flex-end;align-items:flex-end}.row-center{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.row-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;-moz-align-items:stretch;align-items:stretch}.row-baseline{-webkit-box-align:baseline;-ms-flex-align:baseline;-webkit-align-items:baseline;-moz-align-items:baseline;align-items:baseline}.col-top{-webkit-align-self:flex-start;-moz-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.col-bottom{-webkit-align-self:flex-end;-moz-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.col-center{-webkit-align-self:center;-moz-align-self:center;-ms-flex-item-align:center;align-self:center}.col-offset-10{margin-left:10%}.col-offset-20{margin-left:20%}.col-offset-25{margin-left:25%}.col-offset-33,.col-offset-34{margin-left:33.3333%}.col-offset-50{margin-left:50%}.col-offset-66,.col-offset-67{margin-left:66.6666%}.col-offset-75{margin-left:75%}.col-offset-80{margin-left:80%}.col-offset-90{margin-left:90%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 10%;-moz-box-flex:0;-moz-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%;max-width:10%}.col-20{-webkit-box-flex:0;-webkit-flex:0 0 20%;-moz-box-flex:0;-moz-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.col-25{-webkit-box-flex:0;-webkit-flex:0 0 25%;-moz-box-flex:0;-moz-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-33,.col-34{-webkit-box-flex:0;-webkit-flex:0 0 33.3333%;-moz-box-flex:0;-moz-flex:0 0 33.3333%;-ms-flex:0 0 33.3333%;flex:0 0 33.3333%;max-width:33.3333%}.col-40{-webkit-box-flex:0;-webkit-flex:0 0 40%;-moz-box-flex:0;-moz-flex:0 0 40%;-ms-flex:0 0 40%;flex:0 0 40%;max-width:40%}.col-50{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-moz-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-60{-webkit-box-flex:0;-webkit-flex:0 0 60%;-moz-box-flex:0;-moz-flex:0 0 60%;-ms-flex:0 0 60%;flex:0 0 60%;max-width:60%}.col-66,.col-67{-webkit-box-flex:0;-webkit-flex:0 0 66.6666%;-moz-box-flex:0;-moz-flex:0 0 66.6666%;-ms-flex:0 0 66.6666%;flex:0 0 66.6666%;max-width:66.6666%}.col-75{-webkit-box-flex:0;-webkit-flex:0 0 75%;-moz-box-flex:0;-moz-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-80{-webkit-box-flex:0;-webkit-flex:0 0 80%;-moz-box-flex:0;-moz-flex:0 0 80%;-ms-flex:0 0 80%;flex:0 0 80%;max-width:80%}.col-90{-webkit-box-flex:0;-webkit-flex:0 0 90%;-moz-box-flex:0;-moz-flex:0 0 90%;-ms-flex:0 0 90%;flex:0 0 90%;max-width:90%}@media (max-width:567px){.responsive-sm{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-sm .col,.responsive-sm .col-10,.responsive-sm .col-20,.responsive-sm .col-25,.responsive-sm .col-33,.responsive-sm .col-34,.responsive-sm .col-50,.responsive-sm .col-66,.responsive-sm .col-67,.responsive-sm .col-75,.responsive-sm .col-80,.responsive-sm .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:767px){.responsive-md{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-md .col,.responsive-md .col-10,.responsive-md .col-20,.responsive-md .col-25,.responsive-md .col-33,.responsive-md .col-34,.responsive-md .col-50,.responsive-md .col-66,.responsive-md .col-67,.responsive-md .col-75,.responsive-md .col-80,.responsive-md .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:1023px){.responsive-lg{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-lg .col,.responsive-lg .col-10,.responsive-lg .col-20,.responsive-lg .col-25,.responsive-lg .col-33,.responsive-lg .col-34,.responsive-lg .col-50,.responsive-lg .col-66,.responsive-lg .col-67,.responsive-lg .col-75,.responsive-lg .col-80,.responsive-lg .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}.hide{display:none}.opacity-hide{opacity:0}.grade-b .opacity-hide,.grade-c .opacity-hide{opacity:1;display:none}.show{display:block}.opacity-show{opacity:1}.invisible{visibility:hidden}.keyboard-open .hide-on-keyboard-open{display:none}.keyboard-open .bar-footer.hide-on-keyboard-open+.pane .has-footer,.keyboard-open .tabs.hide-on-keyboard-open+.pane .has-tabs{bottom:0}.inline{display:inline-block}.disable-pointer-events{pointer-events:none}.enable-pointer-events{pointer-events:auto}.disable-user-behavior{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-ms-touch-action:none;-ms-content-zooming:none}.click-block{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;z-index:99999;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);overflow:hidden}.click-block-hide{-webkit-transform:translate3d(-9999px,0,0);transform:translate3d(-9999px,0,0)}.no-resize{resize:none}.block{display:block;clear:both}.block:after{display:block;visibility:hidden;clear:both;height:0;content:"."}.full-image{width:100%}.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}.padding-top,.padding-vertical{padding-top:10px}.padding-horizontal,.padding-right{padding-right:10px}.padding-bottom,.padding-vertical{padding-bottom:10px}.padding-horizontal,.padding-left{padding-left:10px}.iframe-wrapper{position:fixed;-webkit-overflow-scrolling:touch;overflow:scroll}.iframe-wrapper iframe{height:100%;width:100%}.light,a.light{color:#fff}.light-bg{background-color:#fff}.stable,a.stable{color:#f8f8f8}.stable-border{border-color:#b2b2b2}.positive,a.positive{color:#387ef5}.positive-border{border-color:#0c60ee}.calm,a.calm{color:#11c1f3}.calm-border{border-color:#0a9dc7}.assertive,a.assertive{color:#ef473a}.assertive-border{border-color:#e42112}.balanced,a.balanced{color:#33cd5f}.balanced-border{border-color:#28a54c}.energized,a.energized{color:#ffc900}.energized-border{border-color:#e6b500}.royal,a.royal{color:#886aea}.royal-border{border-color:#6b46e5}.dark,a.dark{color:#444}.dark-bg{background-color:#444}.dark-border{border-color:#111}[collection-repeat]{left:0!important;top:0!important;position:absolute!important;z-index:1}.collection-repeat-container{position:relative;z-index:1}.collection-repeat-after-container{z-index:0;display:block}.collection-repeat-after-container.horizontal{display:inline-block}.ng-cloak,.ng-hide:not(.ng-hide-animate),.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader){height:64px}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:19px!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader)>*{margin-top:20px}.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader,.platform-ios.platform-cordova:not(.fullscreen) .has-header,.platform-ios.platform-cordova:not(.fullscreen) .tabs-top>.tabs,.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top{top:64px}.platform-ios.platform-cordova:not(.fullscreen) .has-subheader{top:108px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top{top:113px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top{top:157px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:-1px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .popover .bar-subheader,.platform-ios.platform-cordova .popover .has-header{top:44px}.platform-ios.platform-cordova .popover .has-subheader{top:88px}.platform-ios.platform-cordova.status-bar-hide{margin-bottom:20px}@media (orientation:landscape){.platform-ios.platform-browser.platform-ipad{position:fixed}}.platform-c:not(.enable-transitions) *{-webkit-transition:none!important;transition:none!important}.slide-in-up{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.slide-in-up.ng-enter,.slide-in-up>.ng-enter{-webkit-transition:all cubic-bezier(.1,.7,.1,1) 400ms;transition:all cubic-bezier(.1,.7,.1,1) 400ms}.slide-in-up.ng-enter-active,.slide-in-up>.ng-enter-active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slide-in-up.ng-leave,.slide-in-up>.ng-leave{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms}@-webkit-keyframes scaleOut{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@keyframes scaleOut{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}@-webkit-keyframes superScaleIn{from{-webkit-transform:scale(1.2);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@keyframes superScaleIn{from{transform:scale(1.2);opacity:0}to{transform:scale(1);opacity:1}}[nav-view-transition=ios] [nav-view=entering],[nav-view-transition=ios] [nav-view=leaving]{-webkit-transition-duration:500ms;transition-duration:500ms;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform,box-shadow;transition-property:opacity,transform,box-shadow}[nav-view-transition=ios][nav-view-direction=forward],[nav-view-transition=ios][nav-view-direction=back]{background-color:#000}[nav-view-transition=ios] [nav-view=active],[nav-view-transition=ios][nav-view-direction=forward] [nav-view=entering],[nav-view-transition=ios][nav-view-direction=back] [nav-view=leaving]{z-index:3}[nav-view-transition=ios][nav-view-direction=forward] [nav-view=leaving],[nav-view-transition=ios][nav-view-direction=back] [nav-view=entering]{z-index:2}[nav-bar-transition=ios] .back-text,[nav-bar-transition=ios] .buttons,[nav-bar-transition=ios] .title{-webkit-transition-duration:500ms;transition-duration:500ms;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,transform}[nav-bar-transition=ios] [nav-bar=entering],[nav-bar-transition=ios] [nav-bar=active]{z-index:10}[nav-bar-transition=ios] [nav-bar=entering] .bar,[nav-bar-transition=ios] [nav-bar=active] .bar{background:0 0}[nav-bar-transition=ios] [nav-bar=cached]{display:block}[nav-bar-transition=ios] [nav-bar=cached] .header-item{display:none}[nav-view-transition=android] [nav-view=entering],[nav-view-transition=android] [nav-view=leaving]{-webkit-transition-duration:200ms;transition-duration:200ms;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:-webkit-transform;transition-property:transform}[nav-view-transition=android] [nav-view=active],[nav-view-transition=android][nav-view-direction=forward] [nav-view=entering],[nav-view-transition=android][nav-view-direction=back] [nav-view=leaving]{z-index:3}[nav-view-transition=android][nav-view-direction=forward] [nav-view=leaving],[nav-view-transition=android][nav-view-direction=back] [nav-view=entering]{z-index:2}[nav-bar-transition=android] .buttons,[nav-bar-transition=android] .title{-webkit-transition-duration:200ms;transition-duration:200ms;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:opacity;transition-property:opacity}[nav-bar-transition=android] [nav-bar=entering],[nav-bar-transition=android] [nav-bar=active]{z-index:10}[nav-bar-transition=android] [nav-bar=entering] .bar,[nav-bar-transition=android] [nav-bar=active] .bar{background:0 0}[nav-bar-transition=android] [nav-bar=cached]{display:block}[nav-bar-transition=android] [nav-bar=cached] .header-item{display:none}[nav-swipe=fast] .back-text,[nav-swipe=fast] .buttons,[nav-swipe=fast] .title,[nav-swipe=fast] [nav-view]{-webkit-transition-duration:50ms;transition-duration:50ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-swipe=slow] .back-text,[nav-swipe=slow] .buttons,[nav-swipe=slow] .title,[nav-swipe=slow] [nav-view]{-webkit-transition-duration:160ms;transition-duration:160ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-bar=cached],[nav-view=cached]{display:none}[nav-view=stage]{opacity:0;-webkit-transition-duration:0;transition-duration:0}[nav-bar=stage] .back-text,[nav-bar=stage] .buttons,[nav-bar=stage] .title{position:absolute;opacity:0;-webkit-transition-duration:0s;transition-duration:0s}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.ttf?v=1.1.0) format("truetype");font-weight:100;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.ttf?v=1.1.0) format("truetype");font-weight:300;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf?v=1.1.0) format("truetype");font-weight:400;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.ttf?v=1.1.0) format("truetype");font-weight:500;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:normal}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf?v=1.1.0) format("truetype");font-weight:700;font-style:italic}@font-face{font-family:RobotoDraft;src:url(../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff2?v=1.1.0) format("woff2"),url(../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff?v=1.1.0) format("woff"),url(../lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.ttf?v=1.1.0) format("truetype");font-weight:900;font-style:normal}.item-md-label{display:block;background:0 0;box-shadow:none;margin-left:12px;margin-right:12px;padding:30px 0 0}.item-md-label .input-label{position:absolute;z-index:2;-webkit-transform:translate3d(0,-30px,0) scale(1);transform:translate3d(0,-30px,0) scale(1);-webkit-transition:all .2s ease;transition:all .2s ease;color:#fff;opacity:.5;filter:alpha(opacity=50);-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0}.item-md-label input{background-color:rgba(0,0,0,.6);bottom:0;color:#fff;letter-spacing:.25rem;padding:20px 10px;position:relative;z-index:1}.item-md-label .highlight{position:absolute;bottom:0;height:2px;left:0;width:100%;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);-webkit-transition:all .15s ease;transition:all .15s ease;z-index:1}.item-md-label .highlight-light{background:#fff}.item-md-label .highlight-stable{background:#f8f8f8}.item-md-label .highlight-positive{background:#387ef5}.item-md-label .highlight-calm{background:#11c1f3}.item-md-label .highlight-balanced{background:#33cd5f}.item-md-label .highlight-energized{background:#ffc900}.item-md-label .highlight-assertive{background:#ef473a}.item-md-label .highlight-royal{background:#886aea}.item-md-label .highlight-dark{background:#444}.item-md-label .input-label{letter-spacing:.25rem;padding:0 10px}.item-md-label input.used~.input-label,.item-md-label input:focus~.input-label{font-weight:700;opacity:.7;filter:alpha(opacity=70);padding:0;text-transform:uppercase;-webkit-transform:translate3d(0,-60px,0) scale(.9);transform:translate3d(0,-60px,0) scale(.9)}.item-md-label input:focus~.highlight{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded,.expanded .bar.bar-header{height:75px}.bar.bar-header.expanded .title,.expanded.bar.bar-header .title{bottom:0;top:initial;padding-left:16px}.bar.bar-header.expanded .title.fab-left,.expanded .bar.bar-header .title.fab-left{bottom:0;left:90px;position:absolute;right:initial;top:initial}.bar.bar-header.expanded .title.fab-right,.expanded .bar.bar-header .title.fab-right{bottom:0;left:4px;position:absolute;top:initial;right:initial}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{top:50px}.bar.bar-header.expanded.push-down,.expanded .bar.bar-header.push-down{height:44px;overflow:hidden}.bar.bar-header.expanded,.expanded .bar.bar-header{-webkit-transition:height 1s cubic-bezier(.55,0,.1,1);transition:height 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{-webkit-transition:all 1.1s cubic-bezier(.55,0,.1,1);transition:all 1.1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0) scale(1);transform:translate3d(0,0,0) scale(1)}.bar.bar-header.expanded.push-down+.button-fab,.expanded .bar.bar-header.push-down+.button-fab{top:0;-webkit-transform:translate3d(-100px,-100px,0) scale(2.5);transform:translate3d(-100px,-100px,0) scale(2.5)}.bar.bar-header.expanded.push-down .title,.expanded .bar.bar-header.push-down .title{opacity:0;filter:alpha(opacity=0);left:initial;right:initial}.bar.bar-header.expanded .title,.expanded .bar.bar-header .title{opacity:1;filter:alpha(opacity=100);-webkit-transition:all 2s cubic-bezier(.55,0,.1,1);transition:all 2s cubic-bezier(.55,0,.1,1);bottom:0;left:42px!important;top:initial}.bar.bar-header.expanded.has-header-fab-left .title,.expanded.has-header-fab-left .bar.bar-header .title{left:76px!important}.bar{z-index:2;font-size:1.3em;width:100%;box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button{z-index:3}.bar .no-text span.back-text{display:none}.bar .title sup{opacity:.7}.bar.bar-header .button+.title{text-align:left;left:35px;line-height:46px}.button-bar{box-shadow:0 1px 3px rgba(0,0,0,.15)}.button-bar>.button{box-shadow:none}.button-bar>.button .icon:before,.button-bar>.button:before{line-height:initial}.bar-footer .button-fab{position:absolute;top:-26px;bottom:initial}.bar-footer .buttons-left .button-fab{left:8px}.bar-footer .buttons-right .button-fab{right:8px}.bar .button.button-clear{box-shadow:none}.left-buttons .button-fab{left:8px;top:16px}.right-buttons .button-fab{right:8px;top:16px}.fab-left.title-left,.fab-left.title.title-left{left:68px}.bar .button.button-fab,.button.button-fab{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);z-index:9999;width:56px;height:56px;max-height:initial;max-width:initial;border-radius:50%;overflow:hidden;padding:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:.3s fade-in-out;transition:.3s fade-in-out;-webkit-transition-property:-webkit-transform,box-shadow;transition-property:transform,box-shadow}.bar .button.button-fab.button-fab-bottom-right,.button.button-fab.button-fab-bottom-right{top:auto;right:16px;bottom:16px;left:auto;position:absolute}.bar .button.button-fab.button-fab-bottom-left,.button.button-fab.button-fab-bottom-left{top:auto;right:auto;bottom:16px;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-right,.button.button-fab.button-fab-top-right{top:32px;right:16px;bottom:auto;left:auto;position:absolute}.bar .button.button-fab.button-fab-top-left,.button.button-fab.button-fab-top-left{top:32px;right:auto;bottom:auto;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-left.expanded,.bar .button.button-fab.button-fab-top-right.expanded,.button.button-fab.button-fab-top-left.expanded,.button.button-fab.button-fab-top-right.expanded{top:48px}.bar .button.button-fab i,.button.button-fab i{font-size:2.5rem;margin-top:0}.bar .button.button-fab.mini,.button.button-fab.mini{width:40px;height:40px}.bar .button.button-fab.mini i,.button.button-fab.mini i{font-size:2rem}.button.button-fab.button-fab-top-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-top-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.bar .button.button-floating,.button.button-floating{display:inline-block;color:#FFF;position:relative;z-index:1;width:37px;height:37px;line-height:37px;padding:0;border-radius:50%;background-clip:padding-box;-webkit-transition:.3s;transition:.3s;cursor:pointer}.bar .button.button-floating i,.button.button-floating i{width:inherit;display:inline-block;text-align:center;color:#FFF;line-height:37px}.bar .button.button-floating.button-large,.button.button-floating.button-large{width:55.5px;height:55.5px}.bar .button.button-floating.button-large i,.button.button-floating.button-large i{line-height:55.5px}.bar .button,.bar .button.button-flat,.bar .button.button-large,.button,.button.button-flat,.button.button-large{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);display:inline-block;height:36px;padding:0 2rem;border-radius:2px;background-clip:padding-box;text-transform:uppercase;border:none;outline:0;-webkit-tap-highlight-color:transparent}.bar .button.button-floating.disabled,.bar .button.button-floating:disabled,.bar .button.button-large.disabled,.bar .button.button-large:disabled,.bar .button.button:disabled,.bar .button.disabled,.bar .button.disabled.button-large,.button.button-floating.disabled,.button.button-floating:disabled,.button.button-large.disabled,.button.button-large:disabled,.button.button:disabled,.button.disabled,.button.disabled.button-large{background-color:#DFDFDF;box-shadow:none;color:#9F9F9F}.bar .button.button-floating.disabled:hover,.bar .button.button-floating:disabled:hover,.bar .button.button-large.disabled:hover,.bar .button.button-large:disabled:hover,.bar .button.button:disabled:hover,.bar .button.disabled.button-large:hover,.bar .button.disabled:hover,.button.button-floating.disabled:hover,.button.button-floating:disabled:hover,.button.button-large.disabled:hover,.button.button-large:disabled:hover,.button.button:disabled:hover,.button.disabled.button-large:hover,.button.disabled:hover{background-color:#DFDFDF;color:#9F9F9F}.bar .button i,.bar .button.button-flat i,.bar .button.button-floating i,.bar .button.button-large i,.button i,.button.button-flat i,.button.button-floating i,.button.button-large i{font-size:1.3rem}.button-bar .button{border-radius:0}.bar .button,.bar .button-large,.button,.button-large{text-decoration:none;text-align:center;letter-spacing:.5px;-webkit-transition:.2s ease-out;transition:.2s ease-out;cursor:pointer}.button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;outline:0;margin:0;white-space:nowrap;text-align:center;text-transform:uppercase;font-weight:500;font-style:inherit;font-variant:inherit;font-size:inherit;text-decoration:none;cursor:pointer;-webkit-transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1);transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),transform .4s cubic-bezier(.25,.8,.25,1)}.button:focus{outline:0}.button.ng-hide{-webkit-transition:none;transition:none}.button.cornered{border-radius:0}.button.raised{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.button-outline,.button-outline:active,.button-outline:hover{border-style:solid;border-width:1px}.button.button-outline,.button.button-outline.button-assertive,.button.button-outline.button-balanced,.button.button-outline.button-calm,.button.button-outline.button-dark,.button.button-outline.button-energized,.button.button-outline.button-light,.button.button-outline.button-positive,.button.button-outline.button-royal,.button.button-outline.button-stable{border-color:rgba(0,0,0,.1)}.bar .button-flat,.button-flat{box-shadow:none;background-color:transparent;color:#343434;cursor:pointer}.bar .button.button-flat.disabled,.button.button-flat.disabled{color:#b3b3b3}.bar .button.button-large i,.button.button-large i{font-size:1.6rem}.button-pin-header.button-floating{position:absolute;z-index:1000}.button-pin-header.button-pin-left{left:24px;top:-24px}.button-pin-header.button-pin-right{right:24px;top:-24px}.button:not([disabled]).floating:focus,.button:not([disabled]).floating:hover,.button:not([disabled]).raised:focus,.button:not([disabled]).raised:hover{-webkit-transform:translate3d(0,-1px,0);transform:translate3d(0,-1px,0)}.button.button-flat{box-shadow:none}.button.button-flat,.button.button-flat:active,.button.button-flat:hover{color:#fff}.button.button-clear,.button.button-clear:active,.button.button-clear:hover{background:0 0}.button-block.ink,.button-full.ink{display:block}.card-item.item{border:none;padding-bottom:4px;padding-top:4px}.card-item.item:first-child{padding-top:16px}.card{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;margin:8px;padding:0;position:relative}.card .image{display:block;margin-top:10px;margin-bottom:5px}.card img{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;max-width:100%;max-height:initial;position:static}.card.card-gallery img{border:none;box-shadow:none;display:block}.card .card-footer{font-size:90%;opacity:.8;filter:alpha(opacity=80);padding-top:10px}.card>.item{border:none}.card.card-gallery>.item{background:inherit}.card .icon+.icon{padding-left:1rem}.card.animate-fade-in{opacity:0;filter:alpha(opacity=0);-webkit-transform:translate3d(-30px,1px,0);-webkit-transition:all 1s ease-in-out}.card.animate-fade-in.done{opacity:1;filter:alpha(opacity=100);-webkit-transform:translate3d(0,0,0)}.card .item.item-avatar{min-height:88px;padding-left:88px}.hero{background-size:cover;box-shadow:0 2px 5px 0 rgba(0,0,0,.26);color:#fff;height:200px;position:relative;text-align:center;-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);width:100%}.hero .hero-icon{box-shadow:0 0 2px 0 rgba(0,0,0,.26);border-radius:50%;display:inline-block;height:150px;padding:10px 30px;line-height:136px;width:150px}.hero.no-header{height:244px}.hero>.content{bottom:0;position:absolute;text-align:center;width:100%;z-index:1}.hero>.content>.avatar{background-position:center;background-size:cover;border:1px solid rgba(255,255,255,.8);border-radius:50%;display:inline-block;height:88px;left:auto;margin-bottom:10px;position:relative;width:88px}.hero h1 .hero h2,.hero h3,.hero h4,.hero h5,.hero h6{color:#fff;margin:0}.hero h4{color:rgba(255,255,255,.7);margin:3px 0 16px}.hero h1>a,.hero h2>a,.hero h3>a,.hero h4>a,.hero h5>a,.hero h6>a{text-decoration:none}.hero+.button-bar{border-radius:0;margin-top:0}.hero+.button-bar>.button:first-child,.hero+.button-bar>.button:last-child{border-radius:0}.hero .hero-icon{color:#fff;font-size:96px}.hero .hero-icon+h1{color:#fff;letter-spacing:.15rem}.hero .button,.hero .button.button-flat,.hero .button.button-large{margin:0}.hero h1.title{color:#fff;font-size:23px;margin:0;text-align:left;padding-left:80px;line-height:59px}.hero+.mid-bar{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);height:initial;opacity:1;filter:alpha(opacity=100)}.hero>*{-webkit-transition:opacity 2.5s cubic-bezier(.55,0,.1,1);transition:opacity 2.5s cubic-bezier(.55,0,.1,1);opacity:1;filter:alpha(opacity=100)}.item{font-size:14px;width:100%}.item-icon-left .icon{left:16px}.item-icon-right .icon{right:16px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{border-radius:50%}.tab-item.activated{height:calc(100% + 3px)}.content+.list{padding-top:0}.list .item{border:none;min-height:48px;text-align:left}.list .item.tabs{padding:initial}.list .item.item-bg-image{min-height:150px}.list .item.item-bg-image>img{height:100%;left:0;max-width:initial;opacity:.65;filter:alpha(opacity=65);position:absolute;top:0;width:100%;z-index:0}.list a.item{opacity:1;filter:alpha(opacity=100)}.list .item.item-bg-image h1,.list .item.item-bg-image h2,.list .item.item-bg-image h3,.list .item.item-bg-image h4,.list .item.item-bg-image h5,.list .item.item-bg-image h6{color:#fff;font-weight:700;position:relative;text-shadow:0 0 3px rgba(0,0,0,.95);z-index:1}.list .item.item-bg-image h2{font-size:24px}.list .item.item-bg-image p{color:#fff;font-size:17px;position:relative;text-shadow:0 0 4px rgba(0,0,0,.95);z-index:1}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{min-height:80px}.card>.item.item-thumbnail-left,.item-thumbnail-left,.item-thumbnail-left .item-content{padding-left:106px}.card>.item.item-thumbnail-right,.item-thumbnail-right,.item-thumbnail-right .item-content{padding-right:106px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{border-radius:50%;left:16px;max-height:40px;max-width:40px}.avatar,.item-avatar .avatar{background-position:center;background-size:cover;border-radius:50%;display:inline-block;height:56px;left:16px;position:absolute;width:56px}.list.half{display:inline-block;float:left;margin:0;padding:0;width:50%}.list.half:first-child{padding:16px 8px 16px 16px}.list.half:last-child{padding:16px 16px 16px 8px}.list.half:first-child .card.card-gallery,.list.half:last-child .card.card-gallery{margin-left:0;margin-right:0}.list.condensed-space>.card,.list.condensed-space>.item{margin:0 0 2px}.list .card.card-gallery{display:block;float:left;margin:0 0 0 13px;padding:0;width:auto}.list.half .item{width:100%}.list.half .item.card{margin-bottom:16px}.list .card.card-gallery.item h2{padding:12px}.list .item.item-gallery img{width:100%}.item.item-divider{border-top:solid 1px rgba(0,0,0,.12);font-size:14px;font-weight:700;height:48px;line-height:48px;color:rgba(0,0,0,.54)}.item.item-divider:first-child{border:none}.item .item-content.activated,.item .item-content.active,.item-complex.activated .item-content,.item-complex.active .item-content,.item.activated,.item.active{background-color:transparent}.list-inset{margin:20px 30px;border-left:solid 1px #ccc;border-radius:0;background-color:#fff}.item-floating-label,.list .item.item-floating-label{border-bottom:solid 1px #ccc}.loader{position:relative;margin:0 auto;width:100px;height:100px;zoom:1.7}.circular{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;height:100px;position:relative;width:100px}.path{stroke-dasharray:1,200;stroke-dashoffset:0;-webkit-animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;stroke-linecap:round}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@-webkit-keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}@keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}.login{background-position:25% 25%;background-size:180% 180%;height:100%;-webkit-transition:all 1.5s ease-in-out;transition:all 1.5s ease-in-out}.login .item{margin:0 12px;padding-left:0;padding-right:0;width:initial}.login .button-bar{bottom:0;margin:28px 12px 0;width:initial}.login .light-bg{background-color:#fff}.icon.hero-icon:before{line-height:130px}.card.has-mask:after,.hero.has-mask:after,.item.has-mask:after{content:'';background:-webkit-linear-gradient(top,transparent 0,rgba(0,0,0,.6) 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.card.has-mask-reverse:after,.hero.has-mask-reverse:after,.item.has-mask-reverse:after{content:'';background:-webkit-linear-gradient(top,rgba(0,0,0,.6) 0,transparent 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.menu-bottom{bottom:16px;left:16px;right:16px;position:absolute}.menu-top{top:16px;left:16px;right:16px;position:absolute}.menu .avatar{top:16px;left:16px;height:65px;width:65px}.menu .bar.bar-header.expanded{box-shadow:none;min-height:150px;color:#fff}.menu-open .bar.bar-header.expanded{background-position:0;background-size:100%}.has-expanded-header{top:150px!important}.motion{-webkit-transition:all .5s ease-out;transition:all .5s ease-out}.fade{opacity:0;filter:alpha(opacity=0);-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spin-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0)!important;transform:translateZ(0) rotate(360deg) scale(0)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.menu-open .avatar{opacity:1;filter:alpha(opacity=100);-webkit-transform:translateZ(0) rotate(0) scale(1)!important;transform:translateZ(0) rotate(0) scale(1)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(0) scale(0)!important;transform:translateZ(0) rotate(0) scale(0)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin.on{-webkit-transform:translateZ(0) rotate(-360deg) scale(1)!important;transform:translateZ(0) rotate(-360deg) scale(1)!important}.flap{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flap.on{-webkit-transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) scale(3)!important;transform:translateZ(0) scale(3)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop.on{-webkit-transform:translateZ(0) scale(1)!important;transform:translateZ(0) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateY(0) scale(0)!important;transform:translateZ(0) rotateY(0) scale(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip.on{-webkit-transform:translateZ(0) rotateY(-720deg) scale(1)!important;transform:translateZ(0) rotateY(-720deg) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.bold{font-weight:700}.static{position:static}.pull-left{float:left}.pull-right{float:right}.double-padding,.ionic-content.double-padding{padding:16px}.double-padding-x{padding-left:16px;padding-right:16px}.double-padding-y{padding-top:16px;padding-bottom:16px}.outline{border-style:solid;border-width:1px}.border-top{border-top:solid 1px #ccc;padding-top:30px}.no-border{border:none}.circle{border-radius:50%}.bar.no-padding,.button-bar.no-padding,.button.no-padding,.card.no-padding,.item.no-padding,.list.no-padding,.no-padding{padding:0}.flat,.flat.button,.flat.button.icon,.flat.hero,.flat.tabs{box-shadow:none;-webkit-box-shadow:none}.im-wrapper,.padding{padding:16px!important}.padding-bottom{padding-bottom:16px!important}.padding-top{padding-top:16px!important}.padding-left{padding-left:16px!important}.padding-right{padding-right:16px!important}.no-padding-bottom{padding-bottom:0!important}.no-padding-top{padding-top:0!important}.no-padding-left{padding-left:0!important}.no-padding-right{padding-right:0!important}.z1{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar.bar-positive.darker{background-color:#164FAB}.bar.bar-positive.dark-positive-bg{background-color:#2C5CAD}.muted{color:#C3C3C3}.clear-bg{background:0 0}.animate-blinds .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-blinds .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-blinds .in,.animate-blinds.done>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-blinds .in,.animate-blinds.done .item{visibility:visible}.animate-blinds .item{visibility:hidden;opacity:0;filter:alpha(opacity=0)}.animate-blinds .in,.animate-blinds.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1;filter:alpha(opacity=100);visibility:visible}.animate-blinds.done .in{opacity:1;filter:alpha(opacity=100)}.animate-blinds .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-blinds.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-blinds .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-pan-in-left{background-position:0 0}.animate-ripple .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-ripple .item{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1);opacity:0;filter:alpha(opacity=0)}.animate-ripple .item.in{opacity:1;filter:alpha(opacity=100)}.animate-ripple .done{visibility:hidden;-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-ripple .in,.animate-ripple.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;visibility:visible}.animate-ripple.done .in{opacity:1;filter:alpha(opacity=100)}.animate-ripple .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-ripple.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-ripple .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1)}.animate-fade-slide-in .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .in,.animate-fade-slide-in.done .item{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);visibility:visible}.list .item.item-bg-image{max-height:150px}.animate-fade-slide-in .item{visibility:hidden;-ms-transform:translate3d(-250px,250px,0);-webkit-transform:translate3d(-250px,250px,0);transform:translate3d(-250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0;filter:alpha(opacity=0)}.animate-fade-slide-in .in,.animate-fade-slide-in.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .5s ease-in-out;transition:all .5s ease-in-out;opacity:1;filter:alpha(opacity=100);visibility:visible}.animate-fade-slide-in.done .in{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in-right .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1)}.animate-fade-slide-in-right .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done .item{visibility:visible}.animate-fade-slide-in-right .item{visibility:hidden;-ms-transform:translate3d(250px,250px,0);-webkit-transform:translate3d(250px,250px,0);transform:translate3d(250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0;filter:alpha(opacity=0)}.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1;filter:alpha(opacity=100);visibility:visible}.animate-fade-slide-in-right.done .in{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in-right .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in-right.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in-right .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.hero.slide-up,.slide-up{height:100%;overflow:hidden;text-align:center}.slide-up{-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.hero.slide-up *,.slide-up *{opacity:0;filter:alpha(opacity=0)}.hero.slide-up+.mid-bar,.slide-up+.mid-bar{height:100%;opacity:.7;filter:alpha(opacity=70);-webkit-transform:translate3d(100%,-240px,0);transform:translate3d(100%,-240px,0)}.button-clear,.button-fab,.button-flat,.button-raised,.ink,.popup .button{position:relative;cursor:pointer;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.ink-ripple{position:absolute;border-radius:50%;width:100px;height:100px;margin-top:-50px;margin-left:-50px;opacity:0;background-color:rgba(255,255,255,.4);-webkit-transition:all .5s ease-out;-moz-transition:all .5s ease-out;-o-transition:all .5s ease-out;transition:all .5s ease-out;-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform,opacity;-o-transition-property:-o-transform,opacity;transition-property:transform,opacity;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ink-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.button-clear,.button-fab,.button-flat,.button-raised,.ink-button,.ink-circle{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.button-clear.activated,.button-clear:active,.button-fab.activated,.button-fab:active,.button-flat.activated,.button-flat:active,.button-raised.activated,.button-raised:active,.ink-button.activated,.ink-button:active,.ink-circle.activated,.ink-circle:active,.ink.activated,.ink:active,.popup .button.activated,.popup .button:active{-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.button-clear,.button-clear:link,.button-clear:visited,.button-fab,.button-fab:link,.button-fab:visited,.button-flat,.button-flat:link,.button-flat:visited,.button-raised,.button-raised:link,.button-raised:visited,.ink-button,.ink-button-input,.ink-button:link,.ink-button:visited{white-space:nowrap;vertical-align:middle;cursor:pointer;border:none;outline:0;font-size:14px;text-align:center;text-decoration:none;z-index:1}.ink-button{padding:10px 15px;border-radius:2px}.ink-button-input{margin:0;padding:10px 15px}.ink-input-wrapper{border-radius:2px;vertical-align:bottom}.ink-input-wrapper.ink-button{padding:0}.ink-input-wrapper .ink-button-input{position:relative;top:0;left:0;z-index:1}.ink-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%}.ink-float{-webkit-mask-image:none;-webkit-box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12)}.ink-float:active{-webkit-box-shadow:0 8px 20px 1px rgba(0,0,0,.3);box-shadow:0 8px 20px 1px rgba(0,0,0,.3)}.ink-block{display:block}.ink-ripple{z-index:0}.button-clear .ink-ripple,.ink-dark .ink-ripple,.list .ink-ripple,[class$="-clear"]>.ink-ripple,[class$="-light"]>.ink-ripple,[class$="-stable"]>.ink-ripple,[class$="-100"]>.ink-ripple{background-color:rgba(0,0,0,.2)}.tab-item{position:relative}*{font-family:RobotoDraft,Roboto,"Helvetica Neue","Segoe UI",sans-serif}.rounded{border-radius:4px}a{cursor:pointer}.has-header.expanded{top:76px}.bar{border-bottom:none;padding:0}.bar .button{min-height:44px;min-width:44px;max-width:48px;margin-bottom:0;max-height:44px;width:48px}.bar .title+.buttons.buttons-right{right:0;top:0}.title-left,.title-right,.title.title-left,.title.title-right{left:48px}.bar .button-positive,.bar .button-positive.activated,.bar .button-positive:active,.bar .button-positive:hover,.bar-positive,.bar-positive.activated,.bar-positive:active,.bar-positive:hover,.button-bar-positive,.button-bar-positive.activated,.button-bar-positive:active,.button-bar-positive:hover,.button-positive,.button-positive.activated,.button-positive:active,.button-positive:hover,.header-positive,.header-positive.activated,.header-positive:active,.header-positive:hover,.positive-bg,.positive-bg.activated,.positive-bg:active,.positive-bg:hover,.positive-border,.positive-border.activated,.positive-border:active,.positive-border:hover{background-color:#3F51B5;color:#fff}.bar .button-positive-900,.bar .button-positive-900.activated,.bar .button-positive-900:active,.bar .button-positive-900:hover,.bar-positive-900,.bar-positive-900.activated,.bar-positive-900:active,.bar-positive-900:hover,.button-bar-positive-900,.button-bar-positive-900.activated,.button-bar-positive-900:active,.button-bar-positive-900:hover,.button-positive-900,.button-positive-900.activated,.button-positive-900:active,.button-positive-900:hover,.header-positive-900,.header-positive-900.activated,.header-positive-900:active,.header-positive-900:hover,.positive-900-bg,.positive-900-bg.activated,.positive-900-bg:active,.positive-900-bg:hover,.positive-900-border,.positive-900-border.activated,.positive-900-border:active,.positive-900-border:hover{background-color:#1A237E;color:#fff}.bar .button-positive-100,.bar .button-positive-100.activated,.bar .button-positive-100:active,.bar .button-positive-100:hover,.bar-positive-100,.bar-positive-100.activated,.bar-positive-100:active,.bar-positive-100:hover,.button-bar-positive-100,.button-bar-positive-100.activated,.button-bar-positive-100:active,.button-bar-positive-100:hover,.button-positive-100,.button-positive-100.activated,.button-positive-100:active,.button-positive-100:hover,.header-positive-100,.header-positive-100.activated,.header-positive-100:active,.header-positive-100:hover,.positive-100-bg,.positive-100-bg.activated,.positive-100-bg:active,.positive-100-bg:hover,.positive-100-border,.positive-100-border.activated,.positive-100-border:active,.positive-100-border:hover{background-color:#C5CAE9;color:#fff}.bar .button-calm,.bar .button-calm.activated,.bar .button-calm:active,.bar .button-calm:hover,.bar-calm,.bar-calm.activated,.bar-calm:active,.bar-calm:hover,.button-bar-calm,.button-bar-calm.activated,.button-bar-calm:active,.button-bar-calm:hover,.button-calm,.button-calm.activated,.button-calm:active,.button-calm:hover,.calm-bg,.calm-bg.activated,.calm-bg:active,.calm-bg:hover,.calm-border,.calm-border.activated,.calm-border:active,.calm-border:hover,.header-calm,.header-calm.activated,.header-calm:active,.header-calm:hover{background-color:#2196F3;color:#fff}.bar .button-calm-900,.bar .button-calm-900.activated,.bar .button-calm-900:active,.bar .button-calm-900:hover,.bar-calm-900,.bar-calm-900.activated,.bar-calm-900:active,.bar-calm-900:hover,.button-bar-calm-900,.button-bar-calm-900.activated,.button-bar-calm-900:active,.button-bar-calm-900:hover,.button-calm-900,.button-calm-900.activated,.button-calm-900:active,.button-calm-900:hover,.calm-900-bg,.calm-900-bg.activated,.calm-900-bg:active,.calm-900-bg:hover,.calm-900-border,.calm-900-border.activated,.calm-900-border:active,.calm-900-border:hover,.header-calm-900,.header-calm-900.activated,.header-calm-900:active,.header-calm-900:hover{background-color:#0D47A1;color:#fff}.bar .button-calm-100,.bar .button-calm-100.activated,.bar .button-calm-100:active,.bar .button-calm-100:hover,.bar-calm-100,.bar-calm-100.activated,.bar-calm-100:active,.bar-calm-100:hover,.button-bar-calm-100,.button-bar-calm-100.activated,.button-bar-calm-100:active,.button-bar-calm-100:hover,.button-calm-100,.button-calm-100.activated,.button-calm-100:active,.button-calm-100:hover,.calm-100-bg,.calm-100-bg.activated,.calm-100-bg:active,.calm-100-bg:hover,.calm-100-border,.calm-100-border.activated,.calm-100-border:active,.calm-100-border:hover,.header-calm-100,.header-calm-100.activated,.header-calm-100:active,.header-calm-100:hover{background-color:#BBDEFB;color:#fff}.bar .button-royal,.bar .button-royal.activated,.bar .button-royal:active,.bar .button-royal:hover,.bar-royal,.bar-royal.activated,.bar-royal:active,.bar-royal:hover,.button-bar-royal,.button-bar-royal.activated,.button-bar-royal:active,.button-bar-royal:hover,.button-royal,.button-royal.activated,.button-royal:active,.button-royal:hover,.header-royal,.header-royal.activated,.header-royal:active,.header-royal:hover,.royal-bg,.royal-bg.activated,.royal-bg:active,.royal-bg:hover,.royal-border,.royal-border.activated,.royal-border:active,.royal-border:hover{background-color:#673AB7;color:#fff}.bar .button-royal-900,.bar .button-royal-900.activated,.bar .button-royal-900:active,.bar .button-royal-900:hover,.bar-royal-900,.bar-royal-900.activated,.bar-royal-900:active,.bar-royal-900:hover,.button-bar-royal-900,.button-bar-royal-900.activated,.button-bar-royal-900:active,.button-bar-royal-900:hover,.button-royal-900,.button-royal-900.activated,.button-royal-900:active,.button-royal-900:hover,.header-royal-900,.header-royal-900.activated,.header-royal-900:active,.header-royal-900:hover,.royal-900-bg,.royal-900-bg.activated,.royal-900-bg:active,.royal-900-bg:hover,.royal-900-border,.royal-900-border.activated,.royal-900-border:active,.royal-900-border:hover{background-color:#311B92;color:#fff}.bar .button-royal-100,.bar .button-royal-100.activated,.bar .button-royal-100:active,.bar .button-royal-100:hover,.bar-royal-100,.bar-royal-100.activated,.bar-royal-100:active,.bar-royal-100:hover,.button-bar-royal-100,.button-bar-royal-100.activated,.button-bar-royal-100:active,.button-bar-royal-100:hover,.button-royal-100,.button-royal-100.activated,.button-royal-100:active,.button-royal-100:hover,.header-royal-100,.header-royal-100.activated,.header-royal-100:active,.header-royal-100:hover,.royal-100-bg,.royal-100-bg.activated,.royal-100-bg:active,.royal-100-bg:hover,.royal-100-border,.royal-100-border.activated,.royal-100-border:active,.royal-100-border:hover{background-color:#D1C4E9;color:#fff}.balanced-bg,.balanced-bg.activated,.balanced-bg:active,.balanced-bg:hover,.balanced-border,.balanced-border.activated,.balanced-border:active,.balanced-border:hover,.bar .button-balanced,.bar .button-balanced.activated,.bar .button-balanced:active,.bar .button-balanced:hover,.bar-balanced,.bar-balanced.activated,.bar-balanced:active,.bar-balanced:hover,.button-balanced,.button-balanced.activated,.button-balanced:active,.button-balanced:hover,.button-bar-balanced,.button-bar-balanced.activated,.button-bar-balanced:active,.button-bar-balanced:hover,.header-balanced,.header-balanced.activated,.header-balanced:active,.header-balanced:hover{background-color:#4CAF50;color:#fff}.balanced-900-bg,.balanced-900-bg.activated,.balanced-900-bg:active,.balanced-900-bg:hover,.balanced-900-border,.balanced-900-border.activated,.balanced-900-border:active,.balanced-900-border:hover,.bar .button-balanced-900,.bar .button-balanced-900.activated,.bar .button-balanced-900:active,.bar .button-balanced-900:hover,.bar-balanced-900,.bar-balanced-900.activated,.bar-balanced-900:active,.bar-balanced-900:hover,.button-balanced-900,.button-balanced-900.activated,.button-balanced-900:active,.button-balanced-900:hover,.button-bar-balanced-900,.button-bar-balanced-900.activated,.button-bar-balanced-900:active,.button-bar-balanced-900:hover,.header-balanced-900,.header-balanced-900.activated,.header-balanced-900:active,.header-balanced-900:hover{background-color:#1B5E20;color:#fff}.balanced-100-bg,.balanced-100-bg.activated,.balanced-100-bg:active,.balanced-100-bg:hover,.balanced-100-border,.balanced-100-border.activated,.balanced-100-border:active,.balanced-100-border:hover,.bar .balanced-100-bg:hover,.bar .button-balanced-100,.bar .button-balanced-100.activated,.bar .button-balanced-100:active,.bar-balanced-100,.bar-balanced-100.activated,.bar-balanced-100:active,.bar-balanced-100:hover,.button-balanced-100,.button-balanced-100.activated,.button-balanced-100:active,.button-balanced-100:hover,.button-bar-balanced-100,.button-bar-balanced-100.activated,.button-bar-balanced-100:active,.button-bar-balanced-100:hover,.header-balanced-100,.header-balanced-100.activated,.header-balanced-100:active,.header-balanced-100:hover{background-color:#C8E6C9;color:#fff}.bar .button-energized,.bar .button-energized.activated,.bar .button-energized:active,.bar .button-energized:hover,.bar-energized,.bar-energized.activated,.bar-energized:active,.bar-energized:hover,.button-bar-energized,.button-bar-energized.activated,.button-bar-energized:active,.button-bar-energized:hover,.button-energized,.button-energized.activated,.button-energized:active,.button-energized:hover,.energized-bg,.energized-bg.activated,.energized-bg:active,.energized-bg:hover,.energized-border,.energized-border.activated,.energized-border:active,.energized-border:hover,.header-energized,.header-energized.activated,.header-energized:active,.header-energized:hover{background-color:#FF9800;color:#fff}.bar .button-energized-900,.bar .button-energized-900.activated,.bar .button-energized-900:active,.bar .button-energized-900:hover,.bar-energized-900,.bar-energized-900.activated,.bar-energized-900:active,.bar-energized-900:hover,.button-bar-energized-900,.button-bar-energized-900.activated,.button-bar-energized-900:active,.button-bar-energized-900:hover,.button-energized-900,.button-energized-900.activated,.button-energized-900:active,.button-energized-900:hover,.energized-900-bg,.energized-900-bg.activated,.energized-900-bg:active,.energized-900-bg:hover,.energized-900-border,.energized-900-border.activated,.energized-900-border:active,.energized-900-border:hover,.header-energized-900,.header-energized-900.activated,.header-energized-900:active,.header-energized-900:hover{background-color:#E65100;color:#fff}.bar .button-energized-100,.bar .button-energized-100.activated,.bar .button-energized-100:active,.bar .button-energized-100:hover,.bar-energized-100,.bar-energized-100.activated,.bar-energized-100:active,.bar-energized-100:hover,.button-bar-energized-100,.button-bar-energized-100.activated,.button-bar-energized-100:active,.button-bar-energized-100:hover,.button-energized-100,.button-energized-100.activated,.button-energized-100:active,.button-energized-100:hover,.energized-100-bg,.energized-100-bg.activated,.energized-100-bg:active,.energized-100-bg:hover,.energized-100-border,.energized-100-border.activated,.energized-100-border:active,.energized-100-border:hover,.header-energized-100,.header-energized-100.activated,.header-energized-100:active,.header-energized-100:hover{background-color:#FFE0B2}.assertive-bg,.assertive-bg.activated,.assertive-bg:active,.assertive-bg:hover,.assertive-border,.assertive-border.activated,.assertive-border:active,.assertive-border:hover,.bar .button-assertive,.bar .button-assertive.activated,.bar .button-assertive:active,.bar .button-assertive:hover,.bar-assertive,.bar-assertive.activated,.bar-assertive:active,.bar-assertive:hover,.button-assertive,.button-assertive.activated,.button-assertive:active,.button-assertive:hover,.button-bar-assertive,.button-bar-assertive.activated,.button-bar-assertive:active,.button-bar-assertive:hover,.header-assertive,.header-assertive.activated,.header-assertive:active,.header-assertive:hover{background-color:#F44336;color:#fff}.assertive-900-bg,.assertive-900-bg.activated,.assertive-900-bg:active,.assertive-900-bg:hover,.assertive-900-border,.assertive-900-border.activated,.assertive-900-border:active,.assertive-900-border:hover,.bar .button-assertive-900,.bar .button-assertive-900.activated,.bar .button-assertive-900:active,.bar .button-assertive-900:hover,.bar-assertive-900,.bar-assertive-900.activated,.bar-assertive-900:active,.bar-assertive-900:hover,.button-assertive-900,.button-assertive-900.activated,.button-assertive-900:active,.button-assertive-900:hover,.button-bar-assertive-900,.button-bar-assertive-900.activated,.button-bar-assertive-900:active,.button-bar-assertive-900:hover,.header-assertive-900,.header-assertive-900.activated,.header-assertive-900:active,.header-assertive-900:hover{background-color:#B71C1C;color:#fff}.assertive-100-bg,.assertive-100-bg.activated,.assertive-100-bg:active,.assertive-100-bg:hover,.assertive-100-border,.assertive-100-border.activated,.assertive-100-border:active,.assertive-100-border:hover,.bar .button-assertive-100,.bar .button-assertive-100.activated,.bar .button-assertive-100:active,.bar .button-assertive-100:hover,.bar-assertive-100,.bar-assertive-100.activated,.bar-assertive-100:active,.bar-assertive-100:hover,.button-assertive-100,.button-assertive-100.activated,.button-assertive-100:active,.button-assertive-100:hover,.button-bar-assertive-100,.button-bar-assertive-100.activated,.button-bar-assertive-100:active,.button-bar-assertive-100:hover,.header-assertive-100,.header-assertive-100.activated,.header-assertive-100:active,.header-assertive-100:hover{background-color:#FFCDD2;color:#fff}.bar .button-stable,.bar .button-stable.activated,.bar .button-stable:active,.bar .button-stable:hover,.bar-stable,.bar-stable.activated,.bar-stable:active,.bar-stable:hover,.button-bar-stable,.button-bar-stable.activated,.button-bar-stable:active,.button-bar-stable:hover,.button-stable,.button-stable.activated,.button-stable:active,.button-stable:hover,.header-stable,.header-stable.activated,.header-stable:active,.header-stable:hover,.stable-bg,.stable-bg.activated,.stable-bg:active,.stable-bg:hover,.stable-border,.stable-border.activated,.stable-border:active,.stable-border:hover{background-color:#E0E0E0;color:#fff}.positive,.positive *,.positive-900,.positive-900 *,.positive-900:active,.positive-900:active *,.positive-900:hover,.positive-900:hover *,.positive:active,.positive:active *,.positive:hover,.positive:hover *{color:#3F51B5}.positive-100,.positive-100 *,.positive-100:active,.positive-100:active *,.positive-100:hover,.positive-100:hover *{color:#C5CAE9}.calm-900,.calm-900 *,.calm-900:active,.calm-900:active *,.calm-900:hover,.calm-900:hover *{color:#0D47A1}.calm-100,.calm-100 *,.calm-100:active,.calm-100:active *,.calm-100:hover,.calm-100:hover *{color:#BBDEFB}.royal,.royal *,.royal:active,.royal:active *,.royal:hover,.royal:hover *{color:#673AB7}.royal-900,.royal-900 *,.royal-900:active,.royal-900:active *,.royal-900:hover,.royal-900:hover *{color:#311B92}.royal-100,.royal-100 *,.royal-100:active,.royal-100:active *,.royal-100:hover,.royal-100:hover *{color:#D1C4E9}.balanced,.balanced *,.balanced:active,.balanced:active *,.balanced:hover,.balanced:hover *{color:#4CAF50}.balanced-900,.balanced-900 *,.balanced-900:active,.balanced-900:active *,.balanced-900:hover,.balanced-900:hover *{color:#1B5E20}.balanced-100,.balanced-100 *,.balanced-100:active,.balanced-100:active *,.balanced-100:hover,.balanced-100:hover *{color:#C8E6C9}.energized,.energized *,.energized:active,.energized:active *,.energized:hover,.energized:hover *{color:#FF9800}.energized-900,.energized-900 *,.energized-900:active,.energized-900:active *,.energized-900:hover,.energized-900:hover *{color:#E65100}.energized-100,.energized-100 *,.energized-100:active,.energized-100:active *,.energized-100:hover,.energized-100:hover *{color:#FFE0B2}.assertive,.assertive *,.assertive:active,.assertive:active *,.assertive:hover,.assertive:hover *{color:#F44336}.assertive-900,.assertive-900 *,.assertive-900:active,.assertive-900:active *,.assertive-900:hover,.assertive-900:hover *{color:#B71C1C}.assertive-100,.assertive-100 *,.assertive-100:active,.assertive-100:active *,.assertive-100:hover,.assertive-100:hover *{color:#FFCDD2}.stable,.stable *,.stable:active,.stable:active *,.stable:hover,.stable:hover *{color:#E0E0E0}.light,.light *,.light:active,.light:active *,.light:hover,.light:hover *{color:#fff}.dark,.dark *,.dark:active,.dark:active *,.dark:hover,.dark:hover *{color:#444}.light-border{border-color:#ddd}.navbar-default .navbar-nav>li>a{margin:0;padding-right:26px;padding-left:26px;border-top:3px solid transparent;color:#BFD5C9;opacity:1}.mid-bar{padding:16px}.mid-bar h1,.mid-bar h2,.mid-bar h3,.mid-bar h4,.mid-bar h5,.mid-bar h6{color:#fff;margin-bottom:5px}.mid-bar p{color:rgba(255,255,255,.5);margin-bottom:0}.card>.item-avatar,.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:95px}.item,.item-complex .item-content,.item-radio .item-content{background-color:transparent}.dark-bg h2,.item.dark-bg h2{color:#fff}.tabs-striped .tabs{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button.button-clear{color:#fff}.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before{vertical-align:top;font-size:24px}.menu{background-color:transparent}.button-icon.button.activated,.button-icon.button.active{opacity:initial}.popover{opacity:0;position:absolute;right:8px;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out;top:8px}.popover.ng-enter{opacity:1;transform:translate(0,-14px) scale(1,1);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.popover.ng-leave{opacity:0;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.button{overflow:hidden!important}@media screen and (max-width:400px){@-ms-viewport{width:320px}}@media screen and (max-width:747px){.hidden-xs{display:none!important;visibility:hidden!important}}@media screen and (min-width:748px){.hidden-xs{display:inherited;visibility:visible!important}}@media screen and (max-width:747px){.visible-xs{display:inherited;visibility:visible!important}}@media screen and (min-width:748px){.visible-xs{display:none!important;visibility:hidden!important}}@media screen and (max-width:747px){.no-padding-xs{padding:0!important}}@media screen and (min-width:748px){.no-padding-xs{padding:inherited}}@media screen and (max-width:747px){.no-margin-xs{margin:0!important}}@media screen and (min-width:748px){.no-margin-xs{margin:inherited}}@media screen and (max-width:991px) and (min-width:748px){.hidden-sm{display:none!important;visibility:hidden!important}}@media screen and (min-width:992px){.hidden-sm{display:inherited;visibility:visible!important}}@media screen and (max-width:747px){.hidden-sm{display:inherited;visibility:visible!important}}@media screen and (max-width:991px){.visible-sm{display:inherited;visibility:visible!important}}@media screen and (min-width:992px){.visible-sm{display:none!important;visibility:hidden!important}}@media screen and (max-width:747px){.visible-sm{display:none!important;visibility:hidden!important}}@media screen and (max-width:991px){body{cursor:url(http://ionicframework.com/img/finger.png),auto}}@media screen and (min-width:992px){body{cursor:inherit}}@media screen and (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important;visibility:hidden!important}}@media screen and (min-width:1200px){.hidden-md{display:inherit;visibility:visible}}@media screen and (max-width:991px){.hidden-md{display:inherit;visibility:visible}}@media screen and (min-width:992px) and (max-width:1199px){.visible-md{display:inherit;visibility:visible!important}}@media screen and (min-width:1200px){.visible-md{display:none;visibility:hidden}}@media screen and (max-width:991px){.visible-md{display:none;visibility:hidden}}@media screen and (min-width:1200px){.hidden-lg{display:none!important;visibility:hidden!important}}@media screen and (max-width:1199px){.hidden-lg{display:inherited;visibility:visible}}@media screen and (min-width:1200px){.visible-lg{display:inherited;visibility:visible!important}}@media screen and (max-width:1199px){.visible-lg{display:none;visibility:hidden}} \ No newline at end of file diff --git a/www/css/style.css b/www/css/style.css index bfe19f0fe931d93b6efc392c87a1161b088f06a5..d54c3826730c9ee5eca8db093d05ce3c6f2b2dbd 100644 --- a/www/css/style.css +++ b/www/css/style.css @@ -1,16 +1,4 @@ -body { - cursor: url('http://ionicframework.com/img/finger.png'), auto; -} - -.homeMessage { - text-align: center; - font-size: 18px; -} -.selected { - background-color: steelblue !important; - color: white !important; -} #newAccount h1 { font-size: 25px; @@ -36,6 +24,11 @@ body { padding-top: 15px; padding-bottom: 15px; text-align: center; + color: #fff; +} + +#home h4 { + color: #fff; } #home button, #home a { @@ -43,13 +36,83 @@ body { height: 40px; } +.bar .button.button-clear { + font-size: 12px !important; + font-weight: 300 !important; + width: initial !important; + min-width: 38px !important; + max-width: 90px !important; +} + +.bar .title + .button.button-clear.button-icon.icon { + min-height: 30px; +} + + + +#transfer .list .item { + border-bottom: solid 1px #ccc; +} + +#wallet .item h4 .comment{ + font-style: italic !important; +} + +#wallet .item h3 .gray{ + font-size: 11px ! important; +} + +.list .item-input { + border-bottom: solid 1px #ccc; +} + +.item.item-thumbnail-left { + min-height: 100px !important; +} + +.gallery .card-gallery img{ + max-height: 150px; +} + +.gallery .card.card-gallery{ + margin-bottom: 15px !important; + float: left; + display: block; +} + +#menu .item.item-divider { + min-height: 5px; + height: 5px; +} + +.menu .avatar { + height: 88px; + width: 88px; +} + +.avatar-member { + background-image: url('../img/person.png'); +} + +.avatar-wallet { + background-image: url('../img/card.png'); +} + .center { text-align: center; } -.light { - color: grey; +.gray { + color: grey !important; +} +.no-padding { + padding: 0px !important; +} + +.col-pubkey { + min-width: 130px !important; } + /*.button {*/ /*height: 50px !important;*/ /*font-size: 18px !important;*/ @@ -93,6 +156,11 @@ body { border-bottom: 2px solid red; } +.item em { + font-weight: bold !important; +} + + /********** MODAL **********/ @@ -139,4 +207,4 @@ body { .peer-item .badge { top: 14px; -} \ No newline at end of file +} diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json index a55c55cc08bcb4a00d4d50cd10c1f92fd22afb79..2f5dcd25cad399e7e71041d52e403a8afd0bb4fb 100644 --- a/www/i18n/locale-en.json +++ b/www/i18n/locale-en.json @@ -4,36 +4,49 @@ "PUBKEY": "Public key", "BTN_OK": "OK", "BTN_SHOW": "Show", + "BTN_SHOW_PUBKEY": "Show key", "BTN_RELATIVE_UNIT": "Use relative unit", "BTN_BACK": " Back", "BTN_CANCEL": "Cancel", - "BTN_LOGIN": "Login", + "BTN_LOGIN": "Sign In", "BTN_LOGOUT": " Logout", - "BTN_ADD_ACCOUNT": "Register" + "BTN_ADD_ACCOUNT": "New Account", + "NO_ACCOUNT_QUESTION": "No a member ? Register now !", + "SEARCH_NO_RESULT": "No result found", + "LOADING": "Loading...", + "FROM": "From", + "TO": "To", + "COPY": "Copy" + }, + "SYSTEM": { + "PICTURE_CHOOSE_TYPE": "Choose picture source :", + "BTN_PICTURE_GALLERY": "Gallery", + "BTN_PICTURE_CAMERA": "<b>Camera</b>" }, "MENU": { - "TITLE": "Cesium", + "TITLE": "Duniter", "HOME": "Home", "REGISTRY": "Registry", "MARKET": "Market place", - "CURRENCIES": "Expore currencies", - "ACCOUNT": "My Account" + "CURRENCIES": "Currencies", + "ACCOUNT": "My Account", + "SETTINGS": "Settings" }, "HOME": { - "TITLE": "Home", - "WELCOME": "Welcome", - "MESSAGE": "<b>Cesium</b> is still in development phase. There is not much to see right now. :-)", + "TITLE": "Duniter", + "WELCOME": "Duniter", + "MESSAGE": "Welcome to Cesium App for Duniter !<br/>See your Duniter wallets in real time.", "BTN_REGISTRY": "Registry", "BTN_MARKET": "Market place", "BTN_CURRENCIES": "Explore currencies" }, "CURRENCY": { "SELECT": { - "TITLE": "Explore", + "TITLE": "Currencies", "CURRENCIES": "Known currencies" }, "VIEW": { - "TITLE": "Explore", + "TITLE": "Currency", "TAB_CURRENCY": "Currency", "TAB_WOT": "Community", "TAB_NETWORK": "Network", @@ -59,6 +72,10 @@ }, "WOT": { "SEARCH_HELP": "Search (member or public key)", + "REGISTERED_SINCE": "Registered since ", + "REGISTERED_SINCE_BLOCK": "Registered since block #", + "BTN_SEND_MONEY": "Send money", + "BTN_CERTIFY": "Certify", "MODAL": { "TITLE": "Search" } @@ -72,12 +89,18 @@ }, "ACCOUNT": { "TITLE": "My Account", + "MENU_TITLE": "Wallet actions", "BALANCE": "Balance", "LAST_TX": "Last transactions", + "NO_TX": "No transaction", "BTN_SEND_MONEY": "Send money", - "BTN_REGISTER": "Register as member", + "BTN_MEMBERSHIP_IN": "Register as member", + "BTN_MEMBERSHIP_RENEW": "Renew membership", + "BTN_MEMBERSHIP_OUT": "Revoke membership", + "BTN_SEND_IDENTITY": "Publish pseudonym (without register)", "NEW": { - "TITLE": "Register", + "TITLE": "New Account", + "SLIDE_1_TITLE": "Select a money:", "SLIDE_2_TITLE": "Kind of account:", "MEMBER_ACCOUNT": "Member account", "WALLET_ACCOUNT": "Simple wallet account", @@ -85,7 +108,7 @@ "PSEUDO_HELP": "joe123", "PASSWORD_CONFIRM": "Confirm Password", "PASSWORD_CONFIRM_HELP": "Confirm Password", - "MSG_UID_ALREADY_USED": "This pseudonym is alreadey used by an existing member.<br/>Please choose another one." + "MSG_UID_ALREADY_USED": "This pseudonym is already used by an existing member.<br/>Please choose another one." }, "POPUP_REGISTER": { "TITLE": "Enter a pseudonym", @@ -98,10 +121,44 @@ "TO": "To", "AMOUNT": "Amount", "AMOUNT_HELP": "Amount", - "COMMENTS": "Comments", - "COMMENTS_HELP": "Comments" + "COMMENTS": "Reference", + "COMMENTS_HELP": "Reference (optional)", + "BTN_SEND": "Send", + "BTN_RELATIVE_UNIT": "Amount in relative unit ?", + "MODAL": { + "TITLE": "Transfer" + } + }, + "ERROR": { + "POPUP_TITLE": "Error", + "UNKNOWN_ERROR": "Unknown error", + "CRYPTO_UNKNOWN_ERROR": "Your browser is not compatible with cryptographic features.", + "FIELD_REQUIRED": "This field is required.", + "FIELD_TOO_SHORT": "This field is too short.", + "PASSWORD_NOT_CONFIRMED": "Must match previous password", + "SEND_IDENTITY_FAILED": "Error while trying to register", + "SEND_CERTIFICATION_FAILED": "Could not certify identity", + "LOGIN_FAILED": "Error while sign in", + "LOAD_IDENTITY_FAILED": "Could not load identity", + "SEND_MEMBERSHIP_IN_FAILED": "Error while registering as member", + "SEND_MEMBERSHIP_OUT_FAILED": "Error while registering out", + "REFRESH_WALLET_DATA": "Could not refresh wallet", + "GET_CURRENCY_PARAMETER": "Could not get currency parameters", + "GET_CURRENCIES_FAILED": "Could not load currencies", + "GET_CURRENCY_FAILED": "Could not load currency", + "SEND_TX_FAILED": "Could not send transaction", + "ALL_SOURCES_USED": "Please wait the next block computation (All transaction sources has been used).", + "NOT_ENOUGH_SOURCES": "Please wait the next block computation (Not enough transaction sources).", + "ACCOUNT_CREATION_FAILED": "Error while creating your member account", + "LOAD_WALLET_DATA_ERROR": "Error while loading wallet data", + "COPY_CLIPBOARD_FAILED": "Could not copy to clipboard", + "TAKE_PICTURE_FAILED": "Could not get picture", + "SCAN_FAILED": "Could not scan QR code" }, "INFO": { - "POPUP_TITLE": "Information" + "POPUP_TITLE": "Information", + "CERTIFICATION_DONE": "Identity successfully signed", + "NOT_ENOUGH_CREDIT": "Not enough credit.", + "TRANSFER_SENT": "Transaction successfully sent." } } diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json new file mode 100644 index 0000000000000000000000000000000000000000..4a3dd19d90ce91324ac9996f326abef16fd69df2 --- /dev/null +++ b/www/i18n/locale-fr-FR.json @@ -0,0 +1,235 @@ +{ + "COMMON": { + "APP_NAME": "Cesium", + "PUBKEY": "Clé publique", + "BTN_OK": "OK", + "BTN_SHOW": "Voir", + "BTN_SHOW_PUBKEY": "Voir la clé", + "BTN_RELATIVE_UNIT": "Afficher en unité relative ?", + "BTN_BACK": "Retour", + "BTN_CANCEL": "Annuler", + "BTN_LOGIN": "Se connecter", + "BTN_LOGOUT": "Déconnexion", + "BTN_ADD_ACCOUNT": "Nouveau compte", + "NO_ACCOUNT_QUESTION": "Pas de encore membre ? Créer un compte !", + "SEARCH_NO_RESULT": "Aucun résultat trouvé", + "LOADING": "Veuillez patienter...", + "FROM": "De", + "TO": "A", + "COPY": "Copier" + }, + "SYSTEM": { + "PICTURE_CHOOSE_TYPE": "Choisir la source :", + "BTN_PICTURE_GALLERY": "Gallerie", + "BTN_PICTURE_CAMERA": "<b>Caméra</b>" + }, + "MENU": { + "TITLE": "Duniter", + "HOME": "Accueil", + "REGISTRY": "Annuaire", + "MARKET": "Annonces", + "CURRENCIES": "Monnaies", + "ACCOUNT": "Mon compte", + "SETTINGS": "Configuration" + }, + "HOME": { + "TITLE": "Duniter", + "WELCOME": "Duniter", + "MESSAGE": "Bienvenue dans l'application Cesium !<br/>Regardez l'état de vos comptes Duniter en temps réel.", + "BTN_REGISTRY": "Annuaire", + "BTN_MARKET": "Offres/demandes", + "BTN_CURRENCIES": "Explorer les monnaies" + }, + "CURRENCY": { + "SELECT": { + "TITLE": "Monnaies", + "CURRENCIES": "Monnaies connues" + }, + "VIEW": { + "TITLE": "Monnaie", + "TAB_CURRENCY": "Monnaie", + "TAB_WOT": "Communauté", + "TAB_NETWORK": "Réseau", + "CURRENCY_NAME": "Nom de la monnaie", + "MEMBERS": "Membres", + "INCOMING_MEMBERS": "Nouveaux membres", + "MONEY_DIVIDER": "Monnaie", + "MASS": "Masse monétaire", + "SHARE": "Masse par membre", + "UD": "Dividend universel", + "C_ACTUAL": "c<sub>actuel</sub>", + "BLOCKCHAIN_DIVIDER": "Blockchain", + "TIME": "Heure de la blockchain", + "POW_MIN": "Niveau de difficulté", + "RULES_DIVIDER": "Règles", + "C_RULE": "c" + } + }, + "PEER": { + "PEERS": "Noeuds", + "KNOWN_PEERS": "Noeuds connus", + "SIGNED_ON_BLOCK": "Signé sur le bloc" + }, + "WOT": { + "SEARCH_HELP": "Recherche (pseudo ou clé publique)", + "REGISTERED_SINCE": "Inscrit depuis le ", + "REGISTERED_SINCE_BLOCK": "Inscrit au block #", + "BTN_SEND_MONEY": "Payer", + "BTN_CERTIFY": "Certifier", + "MODAL": { + "TITLE": "Recherche" + } + }, + "LOGIN": { + "TITLE": "<i class=\"icon ion-locked\"></i> Connexion", + "USERNAME": "Adresse email", + "USERNAME_HELP": "dupond@domaine.com", + "PASSWORD": "Mot de passe", + "PASSWORD_HELP": "Mot de passe" + }, + "ACCOUNT": { + "TITLE": "Mon compte", + "MENU_TITLE": "Options du portefeuille", + "BALANCE": "Solde", + "LAST_TX": "Dernières transactions", + "NO_TX": "Aucune transaction", + "BTN_SEND_MONEY": "Payer", + "BTN_MEMBERSHIP_IN": "Devenir membre", + "BTN_MEMBERSHIP_RENEW": "Renouveller son adhésion comme membre", + "BTN_MEMBERSHIP_OUT": "Arrêter son adhésion", + "BTN_SEND_IDENTITY": "Publier le pseudonyme", + "NEW": { + "TITLE": "Inscription", + "SLIDE_1_TITLE": "Choix de la monnaie :", + "SLIDE_2_TITLE": "Type de compte :", + "MEMBER_ACCOUNT": "Compte membre", + "WALLET_ACCOUNT": "Portefeuille anonyme", + "PSEUDO": "Pseudonyme", + "PSEUDO_HELP": "Pseudonyme", + "PASSWORD_CONFIRM": "Confirmation", + "PASSWORD_CONFIRM_HELP": "Confirmation du mot de passe", + "MSG_UID_ALREADY_USED": "Pseudonyme déjà pris par quelqu'un d'autre.<br/>Veuillez en choisir un autre." + }, + "POPUP_REGISTER": { + "TITLE": "Choisissez un pseudonyme", + "HELP": "Un pseudonyme est obligatoire pour devenir membre." + } + }, + "TRANSFER": { + "TITLE": "Payer", + "FROM": "De", + "TO": "A", + "AMOUNT": "Montant", + "AMOUNT_HELP": "Montant", + "COMMENTS": "Référence", + "COMMENTS_HELP": "Référence (optionnelle)", + "BTN_SEND": "Envoyer", + "BTN_RELATIVE_UNIT": "Montant en unité relative ?", + "MODAL": { + "TITLE": "Paiement" + } + }, + "MARKET": { + "COMMON": { + "CATEGORY": "Catégorie", + "CATEGORIES": "Catégories", + "ISSUER": "Soumis par", + "PRICE": "Prix", + "BTN_BUY": "Acheter" + }, + "SEARCH": { + "TITLE": "Annonces", + "SEARCH_HELP": "Recherche (voiture, livre...)", + "BTN_ADD": "Nouveau", + "BTN_OPTIONS": "Recherche avancée", + "BTN_AROUND_ME": "Autour de moi", + "LOCATION": "Localisation", + "LOCATION_HELP": "Ville" + }, + "VIEW": { + "TITLE": "Annonce" + }, + "EDIT": { + "TITLE": "Edition", + "BTN_ADD_PICTURES": "Ajouter des photos", + "RECORD_TITLE": "Titre", + "RECORD_TITLE_HELP": "Titre", + "RECORD_DESCRIPTION": "Description", + "RECORD_DESCRIPTION_HELP": "Description", + "RECORD_PRICE": "Prix", + "RECORD_PRICE_HELP": "Prix (optionnel)", + "RECORD_LOCATION": "Ville", + "RECORD_LOCATION_HELP": "Adresse, Ville" + } + }, + "REGISTRY": { + "COMMON": { + "CATEGORY": "Catégorie", + "CATEGORIES": "Catégories", + "ISSUER": "Soumis par" + }, + "SEARCH": { + "TITLE": "Annuaire", + "SEARCH_HELP": "Recherche (nom, pseudo, clé publique...)", + "BTN_ADD": "Nouveau", + "BTN_OPTIONS": "Recherche avancée", + "LOCATION": "Localisation", + "LOCATION_HELP": "Ville" + }, + "VIEW": { + "TITLE": "" + }, + "NEW": { + "TITLE": "Nouveau", + "SELECT_TYPE": "Type d'ajout :", + "TYPE_PARTICULAR": "Particulier", + "TYPE_COMPANY": "Entreprise, organisme ou institution" + }, + "EDIT": { + "TITLE": "Edition", + "BTN_ADD_PICTURES": "Ajouter des photos", + "RECORD_TITLE": "Nom", + "RECORD_TITLE_HELP": "Nom", + "RECORD_DESCRIPTION": "À propos de moi", + "RECORD_DESCRIPTION_HELP": "À propos de moi", + "RECORD_PRICE": "Prix", + "RECORD_PRICE_HELP": "Prix (optionnel)", + "RECORD_LOCATION": "Localisation", + "RECORD_LOCATION_HELP": "Localisation (adresse, ville)", + "RECORD_SOCIAL_NETWORKS": "Réseaux sociaux", + "RECORD_PUBKEY": "Clé publique" + } + }, + "ERROR": { + "POPUP_TITLE": "Erreur", + "UNKNOWN_ERROR": "Erreur inconnue", + "CRYPTO_UNKNOWN_ERROR": "Votre navigateur ne semble pas compatible avec les fonctionnalités de cryptographie.", + "FIELD_REQUIRED": "Champ obligatoire.", + "FIELD_TOO_SHORT": "Valeur trop courte.", + "PASSWORD_NOT_CONFIRMED": "Ne correspond pas au mot de passe", + "SEND_IDENTITY_FAILED": "Erreur pendant l'inscription.", + "SEND_CERTIFICATION_FAILED": "Erreur lors de la certification de l'identité", + "LOGIN_FAILED": "Erreur lors de l'authentification", + "LOAD_IDENTITY_FAILED": "Erreur de chargement de l'identité", + "SEND_MEMBERSHIP_IN_FAILED": "Echec de la tentative d'entrée dans la communauté", + "SEND_MEMBERSHIP_OUT_FAILED": "Echec de l'arret de l'adhésion.", + "REFRESH_WALLET_DATA": "Echec du rafraichissement du portefeuille", + "GET_CURRENCY_PARAMETER": "Echec de la récupération des règles de la monnaie", + "GET_CURRENCIES_FAILED": "Impossible de chargement la liste des monnaies", + "GET_CURRENCY_FAILED": "Chargement de la monnaie impossible", + "SEND_TX_FAILED": "Echec du paiement", + "ALL_SOURCES_USED": "Veuillez attendre le cacul du prochain bloc (Toutes vos sources de monnaie ont été utilisées).", + "NOT_ENOUGH_SOURCES": "Veuillez attendre le cacul du prochain bloc (Pas assez de sources de monnaie).", + "ACCOUNT_CREATION_FAILED": "Echec de la création du compte membre", + "LOAD_WALLET_DATA_ERROR": "Echec du chargement des données du portefeuille", + "COPY_CLIPBOARD_FAILED": "Copie de la valeur impossible", + "TAKE_PICTURE_FAILED": "Echec de la récupération de la photo", + "SCAN_FAILED": "Echec du scan de QR Code" + }, + "INFO": { + "POPUP_TITLE": "Information", + "CERTIFICATION_DONE": "Certification envoyée", + "NOT_ENOUGH_CREDIT": "Credit insuffisant.", + "TRANSFER_SENT": "La transaction a été envoyée avec succès." + } +} diff --git a/www/i18n/locale-fr.json b/www/i18n/locale-fr.json deleted file mode 100644 index e3df7eb8359e25c62ebe4b7dd0310964f8322db1..0000000000000000000000000000000000000000 --- a/www/i18n/locale-fr.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "COMMON": { - "APP_NAME": "Cesium", - "PUBKEY": "Clé publique", - "BTN_OK": "OK", - "BTN_SHOW": "Voir", - "BTN_RELATIVE_UNIT": "Afficher en unité relative ?", - "BTN_BACK": "Retour", - "BTN_CANCEL": "Annuler", - "BTN_LOGIN": "Se connecter", - "BTN_LOGOUT": "Déconnecter", - "BTN_ADD_ACCOUNT": "S'inscrire" - }, - "MENU": { - "TITLE": "Cesium", - "HOME": "Accueil", - "REGISTRY": "Annuaire", - "MARKET": "Offres/Demandes", - "CURRENCIES": "Monnaies", - "ACCOUNT": "Mon compte" - }, - "HOME": { - "TITLE": "Accueil", - "WELCOME": "Bienvenu.", - "MESSAGE": "<b>Cesium</b> est toujours en développement. Il n'y a pas encore grand chose à voir ! :-)", - "BTN_REGISTRY": "Annuaire", - "BTN_MARKET": "Offres/demandes", - "BTN_CURRENCIES": "Explorer les monnaies" - }, - "CURRENCY": { - "SELECT": { - "TITLE": "Explorer", - "CURRENCIES": "Monnaies connues" - }, - "VIEW": { - "TITLE": "Explorer", - "TAB_CURRENCY": "Monnaie", - "TAB_WOT": "Communauté", - "TAB_NETWORK": "Réseau", - "CURRENCY_NAME": "Nom de la monnaie", - "MEMBERS": "Membres", - "INCOMING_MEMBERS": "Nouveaux membres", - "MONEY_DIVIDER": "Monnaie", - "MASS": "Masse monétaire", - "SHARE": "Masse par membre", - "UD": "Dividend universel", - "C_ACTUAL": "c<sub>actuel</sub>", - "BLOCKCHAIN_DIVIDER": "Blockchain", - "TIME": "Heure de la blockchain", - "POW_MIN": "Niveau de difficulté", - "RULES_DIVIDER": "Règles", - "C_RULE": "c" - } - }, - "PEER": { - "PEERS": "Noeuds", - "KNOWN_PEERS": "Noeuds connus", - "SIGNED_ON_BLOCK": "Signé sur le bloc" - }, - "WOT": { - "SEARCH_HELP": "recherche (membre ou clé publique)", - "MODAL": { - "TITLE": "Recherche" - } - }, - "LOGIN": { - "TITLE": "Connexion", - "USERNAME": "Email (ou phrase)", - "USERNAME_HELP": "dupond@domaine.com", - "PASSWORD": "Mot de passe", - "PASSWORD_HELP": "Mot de passe" - }, - "ACCOUNT": { - "TITLE": "Mon compte", - "BALANCE": "Solde", - "LAST_TX": "Dernières transactions", - "BTN_SEND_MONEY": "Payer", - "BTN_REGISTER": "S'inscrire comme membre", - "NEW": { - "TITLE": "Inscription", - "SLIDE_2_TITLE": "Type de compte :", - "MEMBER_ACCOUNT": "Compte membre", - "WALLET_ACCOUNT": "Simple protefeuille anonyme", - "PSEUDO": "Pseudonyme", - "PSEUDO_HELP": "Pseudonyme", - "PASSWORD_CONFIRM": "Confirmation du mot de passe", - "PASSWORD_CONFIRM_HELP": "Confirmation du mot de passe" - } - }, - "TRANSFER": { - "TITLE": "Payer", - "FROM": "De", - "TO": "A", - "AMOUNT": "Montant", - "AMOUNT_HELP": "Montant", - "COMMENTS": "Commentaires", - "COMMENTS_HELP": "Commentaires" - }, - "ERROR": { - "POPUP_TITLE": "Erreur", - "UNKNOWN_ERROR": "Erreur inconnue", - "CRYPTO_UNKNOWN_ERROR": "Votre navigateur ne semble pas compatible avec les fonctionnalités de cryptographie." - }, - "INFO": { - "POPUP_TITLE": "Information" - } -} diff --git a/www/img/card.png b/www/img/card.png new file mode 100644 index 0000000000000000000000000000000000000000..894a7e9e135fb503317f91eef5ac48abff47e5eb Binary files /dev/null and b/www/img/card.png differ diff --git a/www/img/logo.png b/www/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d8082c7a685930cc9119698d7e4a2b0a3c7ed423 Binary files /dev/null and b/www/img/logo.png differ diff --git a/www/img/person.png b/www/img/person.png new file mode 100644 index 0000000000000000000000000000000000000000..c7da1ece9ad5056d5863b8e5a13f6e60ef96d7e7 Binary files /dev/null and b/www/img/person.png differ diff --git a/www/index.html b/www/index.html index 5b6c183818d36a3899debdde28aa9f578bc60fe8..6219fa3e2a99d99d1e27274cca4688ea7a3008c4 100644 --- a/www/index.html +++ b/www/index.html @@ -1,61 +1,72 @@ <!DOCTYPE html> <html> - <head> - <meta charset="utf-8"> - <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> - <title></title> - - <link href="lib/ionic/css/ionic.css" rel="stylesheet"> - <link href="css/style.css" rel="stylesheet"> - - <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above - <link href="css/ionic.app.css" rel="stylesheet"> - --> - - <!-- ionic/angularjs js --> - <script src="lib/ionic/js/ionic.bundle.js"></script> - <script src="lib/ionic/js/angular/angular-resource.min.js"></script> - <script src="lib/ionic/js/angular/angular-sanitize.min.js"></script> - <script src="lib/ionic/js/angular/angular-translate.min.js"></script> - <script src="lib/ionic/js/angular/angular-translate-loader-static-files.min.js"></script> - <script src="lib/ionic/js/angular/angular-messages.min.js"></script> - <script src="js/vendor/moment.min.js"></script> - <script src="js/vendor/numeral.js"></script> - <script src="js/vendor/socket-io.js"></script> - <script src="js/vendor/underscore.js"></script> - - <!-- crypto libs --> - <script src="js/vendor/scrypt-em.js" ></script> - <script src="js/vendor/nacl_factory.js" ></script> - <script src="js/vendor/base58.js" ></script> - <script src="js/vendor/base64.js" ></script> - - <!-- cordova script (this will be a 404 during development) --> - <script src="cordova.js"></script> - - <!-- services --> - <script src="js/services/crypto-services.js"></script> - <script src="js/services/utils-services.js"></script> - <script src="js/services/wallet-services.js"></script> - <script src="js/services/bma-services.js"></script> - - <!-- entities --> - <script src="js/entity/peer.js"></script> - - <!-- controllers --> - <script src="js/controllers/home-controllers.js"></script> - <script src="js/controllers/wot-controllers.js"></script> - <script src="js/controllers/peer-controllers.js"></script> - <script src="js/controllers/currency-controllers.js"></script> - <script src="js/controllers/wallet-controllers.js"></script> - - <!-- App --> - <script src="js/app.js"></script> - <script src="js/services.js"></script> - <script src="js/controllers.js"></script> - - </head> - <body ng-app="cesium"> - <ion-nav-view></ion-nav-view> - </body> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> + <title></title> + + + <link href="lib/ionic/css/ionic.css" rel="stylesheet"> + + <!-- compiled css output --> + <link href="css/ionic.app.css" rel="stylesheet"> + + <link href="css/style.css" rel="stylesheet"> + <link href="css/style.market.css" rel="stylesheet"> + + <!-- ionic/angularjs js --> + <script src="lib/ionic/js/ionic.bundle.js"></script> + <script src="lib/ionic/js/ionic.material.min.js"></script> + <script src="lib/ionic/js/angular/angular-resource.min.js"></script> + <script src="lib/ionic/js/angular/angular-translate.min.js"></script> + <script src="lib/ionic/js/angular/angular-translate-loader-static-files.min.js"></script> + <script src="lib/ionic/js/angular/angular-messages.min.js"></script> + <script src="js/vendor/moment.min.js"></script> + <script src="js/vendor/numeral.js"></script> + <script src="js/vendor/socket-io.js"></script> + <script src="js/vendor/underscore.js"></script> + + + <!-- crypto libs --> + <script src="js/vendor/scrypt-em.js"></script> + <script src="js/vendor/nacl_factory.js"></script> + <script src="js/vendor/base58.js"></script> + <script src="js/vendor/base64.js"></script> + <script src="lib/crypto-js/crypto-js.js"></script> + + <!-- cordova script (this will be a 404 during development) --> + <script src="js/vendor/ng-cordova.min.js"></script> + <script src="cordova.js"></script> + + <!-- config --> + <script src="js/config.js"></script> + + <!-- services --> + <script src="js/services/crypto-services.js"></script> + <script src="js/services/utils-services.js"></script> + <script src="js/services/wallet-services.js"></script> + <script src="js/services/bma-services.js"></script> + <script src="js/services.js"></script> + + <!-- entities --> + <script src="js/entity/peer.js"></script> + + <!-- controllers --> + <script src="js/controllers/app-controllers.js"></script> + <script src="js/controllers/home-controllers.js"></script> + <script src="js/controllers/wot-controllers.js"></script> + <script src="js/controllers/peer-controllers.js"></script> + <script src="js/controllers/currency-controllers.js"></script> + <script src="js/controllers/wallet-controllers.js"></script> + <script src="js/controllers/transfer-controllers.js"></script> + <script src="js/controllers/settings-controllers.js"></script> + <script src="js/controllers.js"></script> + + <!-- App --> + <script src="js/app.js"></script> + +</head> +<body ng-app="cesium" class="platform-android"> +<ion-nav-view></ion-nav-view> +</body> </html> diff --git a/www/js/app.js b/www/js/app.js index c06b42d84c766c3bbe67875e694bc86d074b795e..ab117ea81fa976752dac02dbc9d31c0e75ce59ff 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -4,25 +4,33 @@ // 'starter' is the name of this angular module example (also set in a <body> attribute in index.html) // the 2nd parameter is an array of 'requires' // 'starter.controllers' is found in controllers.js -angular.module('cesium', ['ionic', 'ngMessages', 'pascalprecht.translate', 'cesium.controllers']) +angular.module('cesium', ['ionic', 'ngCordova', 'ionic-material', 'ngMessages', 'pascalprecht.translate', 'cesium.controllers']) .filter('formatInteger', function() { return function(input) { - return input ? numeral(input).format('0,0') : ''; - } + return input ? numeral(input).format('0,0').replace(',', ' ') : '0'; + }; }) .filter('formatDecimal', function() { return function(input) { + if (!input) return '0'; if (Math.abs(input) < 0.0001) return '~ 0'; - return Math.floor(input * 10000) / 10000; - } + return numeral(input).format('0,0.0000').replace(',', ' '); + }; }) .filter('formatDate', function() { return function(input) { - return input ? moment(parseInt(input)*1000).format('YYYY-MM-DD HH:mm') : ''; - } + // TODO: use local format + return input ? moment(parseInt(input)*1000).local().format('YYYY-MM-DD HH:mm') : ''; + }; + }) + + .filter('formatFromNow', function() { + return function(input) { + return input ? moment(parseInt(input)*1000).startOf('minute').fromNow() : ''; + }; }) .filter('abbreviate', function() { @@ -30,18 +38,35 @@ angular.module('cesium', ['ionic', 'ngMessages', 'pascalprecht.translate', 'cesi var unit = '', sepChars = ['-', '_', ' '], currency = input || ''; for (var i = 0; i < currency.length; i++) { var c = currency[i]; - if (i == 0 || (i > 0 && sepChars.indexOf(currency[i-1]) != -1)) { + if (i === 0 || (i > 0 && sepChars.indexOf(currency[i-1]) != -1)) { unit += c; } } return unit.toUpperCase(); - } + }; }) .filter('formatPubkey', function() { return function(input) { return input ? input.substr(0,8) : ''; - } + }; + }) + + .filter('formatCategory', function() { + return function(input) { + return input && input.length > 28 ? input.substr(0,25)+'...' : input; + }; + }) + + // Convert to user friendly URL (e.g. "Like - This" -> "like-this") + .filter('formatSlug', function() { + return function(input) { + return input ? encodeURIComponent(input + .toLowerCase() + .replace(/[^\w ]+/g,'') + .replace(/ +/g,'-')) + : ''; + }; }) // Translation i18n @@ -52,10 +77,11 @@ angular.module('cesium', ['ionic', 'ngMessages', 'pascalprecht.translate', 'cesi }) .uniformLanguageTag('bcp47') .determinePreferredLanguage() - .useSanitizeValueStrategy('sanitize') - .fallbackLanguage(['en', 'fr']) + // Cela fait bugger les placeholder (pb d'affichage des accents en FR) + //.useSanitizeValueStrategy('sanitize') + .useSanitizeValueStrategy(null) + .fallbackLanguage(['en']) .useLoaderCache(true); - }) // Add new compare-to directive (need for form validation) @@ -78,7 +104,6 @@ angular.module('cesium', ['ionic', 'ngMessages', 'pascalprecht.translate', 'cesi }; }) - .run(function($ionicPlatform) { $ionicPlatform.ready(function() { // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard @@ -92,6 +117,4 @@ angular.module('cesium', ['ionic', 'ngMessages', 'pascalprecht.translate', 'cesi } }); }) - - ; diff --git a/www/js/config.js b/www/js/config.js new file mode 100644 index 0000000000000000000000000000000000000000..833a34d7b7194702ecc085facee903dd70a096f0 --- /dev/null +++ b/www/js/config.js @@ -0,0 +1,18 @@ +/****** +* !! WARNING: This is a generated file !! +* +* PLEASE DO NOT MODIFY DIRECTLY +* +* => Changes should be done on file 'app/config.json'. +******/ + +angular.module("cesium.config", []) + +.constant("APP_CONFIG", { + "UCOIN_NODE": "twiced.fr:9330", + "UCOIN_NODE_ES": "es.ucoin.fr", + "VERSION": "0.0.1", + "BUILD_DATE": "2016-04-16T16:07:33.159Z" +}) + +; \ No newline at end of file diff --git a/www/js/controllers.js b/www/js/controllers.js index 0d217aaafe891f05ccaee098e1a8cec11a7da1bb..5560427335bbeabcc6012005f46c8c2385341045 100644 --- a/www/js/controllers.js +++ b/www/js/controllers.js @@ -1,9 +1,14 @@ angular.module('cesium.controllers', [ + 'cesium.app.controllers', 'cesium.home.controllers', 'cesium.wallet.controllers', 'cesium.currency.controllers', - 'cesium.wot.controllers' + 'cesium.wot.controllers', + 'cesium.transfer.controllers', + 'cesium.settings.controllers', + 'cesium.market.controllers', + 'cesium.registry.controllers' ]) .config(function($httpProvider) { diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..8a0155c198290fbc0a083cee931969193a2cc1e4 --- /dev/null +++ b/www/js/controllers/app-controllers.js @@ -0,0 +1,337 @@ + +angular.module('cesium.app.controllers', ['cesium.services']) + + .config(function($httpProvider) { + //Enable cross domain calls + $httpProvider.defaults.useXDomain = true; + + //Remove the header used to identify ajax call that would prevent CORS from working + delete $httpProvider.defaults.headers.common['X-Requested-With']; + }) + + .config(function($stateProvider, $urlRouterProvider) { + $stateProvider + + .state('app', { + url: "/app", + abstract: true, + templateUrl: "templates/menu.html", + controller: 'AppCtrl' + }) + ; + + // if none of the above states are matched, use this as the fallback + $urlRouterProvider.otherwise('/app/home'); + + }) + + .controller('AppCtrl', AppController) + + //.controller('LoginCtrl', LoginController) + +// .factory('AppModals', ['ModalService', function(ModalService){ +// function showLogin(walletData){ +// return ModalService.show('templates/login.html', 'LoginCtrl', walletData); +// } +// +// // all app modals here +// return { +// showLogin: showLogin +// }; +// +// }]) +; + +function LoginModalController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate, $ionicHistory) { + // Login modal + $scope.loginModal = "undefined"; + $scope.loginData = {}; + + // Create the login modal that we will use later + $ionicModal.fromTemplateUrl('templates/login.html', { + scope: $scope, + focusFirstInput: true + }).then(function(modal) { + $scope.loginModal = modal; + $scope.loginModal.hide(); + }); + + $scope.setLoginForm = function(loginForm) { + $scope.loginForm = loginForm; + }; + + // Open login modal + $scope.login = function(callback) { + if ($scope.loginModal) { + $scope.loginModal.show(); + $scope.loginData.callback = callback; + UIUtils.loading.hide(); + } + else{ + $timeout($scope.login, 2000); + } + }; + + // Login and load wallet + $scope.loadWallet = function() { + return $q(function(resolve, reject){ + if (!Wallet.isLogin()) { + $scope.login(function() { + Wallet.loadData() + .then(function(walletData){ + resolve(walletData); + }) + .catch(UIUtils.onError('ERROR.LOAD_WALLET_DATA_ERROR', reject)); + }); + } + else if (!Wallet.data.loaded) { + Wallet.loadData() + .then(function(walletData){ + resolve(walletData); + }) + .catch(UIUtils.onError('ERROR.LOAD_WALLET_DATA_ERROR', reject)); + } + else { + resolve(Wallet.data); + } + }); + }; + + // Triggered in the login modal to close it + $scope.cancelLogin = function() { + $scope.loginData = {}; // Reset login data + $scope.loginForm.$setPristine(); // Reset form + $scope.loginModal.hide(); + }; + + // Login form submit + $scope.doLogin = function() { + if(!$scope.loginForm.$valid) { + return; + } + UIUtils.loading.show(); + + $scope.loginModal.hide() + .then(function(){ + // Call wallet login, then execute callback function + Wallet.login($scope.loginData.username, $scope.loginData.password) + .then(function(){ + var callback = $scope.loginData.callback; + $scope.loginData = {}; // Reset login data + $scope.loginForm.$setPristine(); // Reset form + if (!!callback) { + callback(); + } + // Default: redirect to wallet view + else { + $state.go('app.view_wallet'); + } + }) + .catch(function(err) { + $scope.loginData = {}; // Reset login data + $scope.loginForm.$setPristine(); // Reset form + UIUtils.loading.hide(); + console.error('>>>>>>>' , err); + UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); + }); + }); + }; + + $scope.loginDataChanged = function() { + $scope.loginData.computing=false; + $scope.loginData.pubkey=null; + }; + + $scope.showLoginPubkey = function() { + $scope.loginData.computing=true; + CryptoUtils.connect($scope.loginData.username, $scope.loginData.password).then( + function(keypair) { + $scope.loginData.pubkey = CryptoUtils.util.encode_base58(keypair.signPk); + $scope.loginData.computing=false; + } + ) + .catch(function(err) { + $scope.loginData.computing=false; + UIUtils.loading.hide(); + console.error('>>>>>>>' , err); + UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); + }); + }; + + // Logout + $scope.logout = function() { + UIUtils.loading.show(); + Wallet.logout().then( + function() { + UIUtils.loading.hide(); + $ionicSideMenuDelegate.toggleLeft(); + $state.go('app.home'); + } + ); + }; + + // Open new account + $scope.openNewAccount = function() { + $scope.cancelLogin(); + $ionicHistory.nextViewOptions({ + disableBack: true + }); + $state.go('app.join'); + }; + + // Is connected + $scope.isLogged = function() { + return Wallet.isLogin(); + }; + + // Is not connected + $scope.isNotLogged = function() { + return !Wallet.isLogin(); + }; +} + + +function AppController($scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, + CryptoUtils, BMA, Wallet, Registry, Market, APP_CONFIG, $ionicHistory, System + ) { + + $scope.knownCurrencies = null; + $scope.search = { text: '', results: {} }; + $scope.isExpanded = false; + $scope.hasHeaderFabLeft = false; + $scope.hasHeaderFabRight = false; + $scope.system = System; + $scope.options = { + market: { + enable: !!Market + }, + registry: { + enable: !!Registry + } + }; + + LoginModalController.call(this, $scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate, $ionicHistory); + + TransferModalController.call(this, $scope, $ionicModal, $state, BMA, Wallet, UIUtils, $timeout, System); + + ionic.Platform.ready(function() { + //System.init(navigator); + }); + + //////////////////////////////////////// + // Load currencies + //////////////////////////////////////// + + $scope.loadCurrencies = function() { + return $q(function (resolve, reject){ + if (!!$scope.knownCurrencies) { + resolve($scope.knownCurrencies); + return; + } + if (!!Registry) { + Registry.currency.all() + .then(function (res) { + if (!!res.hits && res.hits.total > 0) { + $scope.knownCurrencies = res.hits.hits.reduce(function(res, hit) { + var peer = hit._source.peers.reduce(function(peers, peer){ + return peers.concat(new Peer(peer)); + }, [])[0]; + return res.concat({id: hit._id, peer: peer.host+':'+peer.port}); + }, []); + } + $scope.search.looking = false; + resolve($scope.knownCurrencies); + }) + .catch(UIUtils.onError('ERROR.GET_CURRENCIES_FAILED')); + } + else { + $scope.knownCurrencies = []; + BMA.currency.parameters() + .then(function(params) { + $scope.knownCurrencies.push({ + id: params.currency, + peer: APP_CONFIG.UCOIN_NODE} + ); + $scope.search.looking = false; + resolve($scope.knownCurrencies); + }) + .catch(UIUtils.onError('ERROR.GET_CURRENCY_PARAMETER')); + } + }); + }; + + //////////////////////////////////////// + // Layout Methods + //////////////////////////////////////// + /*var navIcons = document.getElementsByClassName('ion-navicon'); + for (var i = 0; i < navIcons.length; i++) { + navIcons.addEventListener('click', function() { + this.classList.toggle('active'); + }); + }*/ + + $scope.hideNavBar = function() { + document.getElementsByTagName('ion-nav-bar')[0].style.display = 'none'; + }; + + $scope.showNavBar = function() { + document.getElementsByTagName('ion-nav-bar')[0].style.display = 'block'; + }; + + $scope.noHeader = function() { + var content = document.getElementsByTagName('ion-content'); + for (var i = 0; i < content.length; i++) { + if (content[i].classList.contains('has-header')) { + content[i].classList.toggle('has-header'); + } + } + }; + + $scope.setExpanded = function(bool) { + $scope.isExpanded = bool; + }; + + $scope.setHeaderFab = function(location) { + var hasHeaderFabLeft = false; + var hasHeaderFabRight = false; + + switch (location) { + case 'left': + hasHeaderFabLeft = true; + break; + case 'right': + hasHeaderFabRight = true; + break; + } + + $scope.hasHeaderFabLeft = hasHeaderFabLeft; + $scope.hasHeaderFabRight = hasHeaderFabRight; + }; + + $scope.hasHeader = function() { + var content = document.getElementsByTagName('ion-content'); + for (var i = 0; i < content.length; i++) { + if (!content[i].classList.contains('has-header')) { + content[i].classList.toggle('has-header'); + } + } + }; + + $scope.hideHeader = function() { + $scope.hideNavBar(); + $scope.noHeader(); + }; + + $scope.showHeader = function() { + $scope.showNavBar(); + $scope.hasHeader(); + }; + + $scope.clearFabs = function() { + var fabs = document.getElementsByClassName('button-fab'); + if (fabs.length && fabs.length > 1) { + fabs[0].remove(); + } + }; +} + diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js index 7c8bed42b7170be8234be806b03d63b5aebbc10c..9a416e9cecc337d1cce2ceefc535f2c3b13f49ae 100644 --- a/www/js/controllers/currency-controllers.js +++ b/www/js/controllers/currency-controllers.js @@ -4,22 +4,32 @@ angular.module('cesium.currency.controllers', ['cesium.services']) .config(function($stateProvider, $urlRouterProvider) { $stateProvider - .state('app.explore_currency', { + .state('app.currency_lookup', { url: "/currency", views: { 'menuContent': { - templateUrl: "templates/explore/explore_currency.html", - controller: 'CurrenciesCtrl' + templateUrl: "templates/currency/lookup.html", + controller: 'CurrencyLookupCtrl' } } }) - .state('app.explore_tabs', { - url: "/currency/view", + .state('app.currency_view', { + url: "/currency/view/:id", views: { 'menuContent': { - templateUrl: "templates/explore/explore_tabs.html", - controller: 'ExploreCtrl' + templateUrl: "templates/currency/view_currency.html", + controller: 'CurrencyViewCtrl' + } + } + }) + + .state('app.currency_view_lg', { + url: "/currency/view/lg/:id", + views: { + 'menuContent': { + templateUrl: "templates/currency/view_currency_lg.html", + controller: 'CurrencyViewCtrl' } } }) @@ -28,65 +38,126 @@ angular.module('cesium.currency.controllers', ['cesium.services']) url: "/peer/:server", views: { 'menuContent': { - templateUrl: "templates/explore/view_peer.html", + templateUrl: "templates/currency/view_peer.html", controller: 'PeerCtrl' } } - }) + }); }) -.controller('CurrenciesCtrl', CurrenciesController) +.controller('CurrencyLookupCtrl', CurrencyLookupController) -.controller('ExploreCtrl', ExploreController) +.controller('CurrencyViewCtrl', CurrencyViewController) .controller('PeerCtrl', PeerController) ; -function CurrenciesController($scope, $state) { +function CurrencyLookupController($scope, $state, $q, $timeout, UIUtils, APP_CONFIG, BMA, Registry, ionicMaterialInk) { $scope.selectedCurrency = ''; - $scope.knownCurrencies = ['meta_brouzouf']; + $scope.knownCurrencies = []; + $scope.search.looking = true; + + $scope.$on('$ionicView.enter', function(e, $state) { + $scope.loadCurrencies() + .then(function (res) { + $scope.knownCurrencies = res; + $scope.search.looking = false; + if (!!res && res.length == 1) { + $scope.selectedCurrency = res[0].id; + } + // Set Ink + ionicMaterialInk.displayEffect({selector: 'a.item'}); + }); + }); // Called to navigate to the main app - $scope.selectCurrency = function(currency) { - $scope.selectedCurrency = currency; - $state.go('app.explore_tabs'); + $scope.selectCurrency = function(id, large) { + $scope.selectedCurrency = id; + if (large) { + $state.go('app.currency_view_lg', {id: id}); + } + else { + $state.go('app.currency_view', {id: id}); + } }; } -function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interval, $timeout) { +function CurrencyViewController($scope, $rootScope, $state, BMA, $q, UIUtils, $interval, $timeout, Registry) { var USE_RELATIVE_DEFAULT = true; - CurrenciesController.call(this, $scope, $state); - WotLookupController.call(this, $scope, BMA, $state); + WotLookupController.call(this, $scope, BMA, $state, UIUtils, $timeout); PeersController.call(this, $scope, $rootScope, BMA, UIUtils, $q, $interval, $timeout); - $scope.accountTypeMember = null; - $scope.accounts = []; - $scope.search = { text: '', results: {} }; - $scope.knownCurrencies = ['meta_brouzouf']; + $scope.search = { + text: '', + results: {}, + options: { + listInset: true + } + }; $scope.formData = { useRelative: false }; $scope.knownBlocks = []; - $scope.entered = false; + $scope.id = null; + $scope.node = null; $scope.$on('$ionicView.enter', function(e, $state) { - if (!$scope.entered) { - $scope.entered = true; - $scope.startListeningOnSocket(); + if (!!$scope.node) { + $scope.node.websocket.block().close(); + $scope.node = null; + } + if ($state.stateParams && $state.stateParams.id) { // Load by id + $scope.id = $state.stateParams.id; + $scope.load($scope.id); + } + else { + $state.go('app.currency_lookup'); + return; } - $timeout(function() { - if ((!$scope.search.peers || $scope.search.peers.length == 0) && $scope.search.lookingForPeers){ - $scope.updateExploreView(); - } - }, 2000); }); + $scope.$on('$ionicView.beforeLeave', function(){ + $scope.closeNode(); + }); + + $scope.load = function(id) { + $scope.closeNode(); + + if (!!Registry) { + Registry.currency.get({ id: id }) + .then(function(currency) { + if (!!currency.peers && currency.peers.length > 0) { + var peer = currency.peers.reduce(function (peers, peer){ + return peers.concat(peer.host + ':' + peer.port); + }, [])[0]; + $scope.node = BMA.instance(peer); + } + else { + $scope.node = BMA; + } + $scope.startListeningOnSocket(); + }) + .catch(UIUtils.onError('ERROR.GET_CURRENCY_FAILED')); + } + else { + $scope.node = BMA; + $scope.startListeningOnSocket(); + $timeout(function() { + if ((!$scope.search.peers || $scope.search.peers.length === 0) && $scope.search.lookingForPeers){ + $scope.updateExploreView(); + } + }, 2000); + } + }; + $scope.startListeningOnSocket = function() { + if (!$scope.node) { + return; + } - // Currency OK - BMA.websocket.block().on('block', function(block) { + $scope.node.websocket.block().on('block', function(block) { var theFPR = fpr(block); if ($scope.knownBlocks.indexOf(theFPR) === -1) { $scope.knownBlocks.push(theFPR); @@ -97,9 +168,17 @@ function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interv }, wait); } }); - BMA.websocket.peer().on('peer', function(peer) { + /*$scope.node.websocket.peer().on('peer', function(peer) { console.log(peer); - }); + });*/ + }; + + $scope.closeNode = function() { + if (!$scope.node) { + return; + } + $scope.node.websocket.close(); + $scope.node = null; }; $scope.$watch('formData.useRelative', function() { @@ -123,6 +202,9 @@ function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interv }; $scope.updateExploreView = function() { + if (!$scope.node) { + return; + } UIUtils.loading.show(); $scope.formData.useRelative = false; @@ -130,7 +212,7 @@ function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interv $q.all([ // Get the currency parameters - BMA.currency.parameters() + $scope.node.currency.parameters() .then(function(json){ $scope.c = json.c; $scope.baseUnit = json.currency; @@ -138,7 +220,7 @@ function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interv }), // Get the current block informations - BMA.blockchain.current() + $scope.node.blockchain.current() .then(function(block){ $scope.M = block.monetaryMass; $scope.N = block.membersCount; @@ -147,11 +229,11 @@ function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interv }), // Get the UD informations - BMA.blockchain.stats.ud() + $scope.node.blockchain.stats.ud() .then(function(res){ if (res.result.blocks.length) { var lastBlockWithUD = res.result.blocks[res.result.blocks.length - 1]; - return BMA.blockchain.block({ block: lastBlockWithUD }) + return $scope.node.blockchain.block({ block: lastBlockWithUD }) .then(function(block){ $scope.currentUD = block.dividend; $scope.UD = block.dividend; @@ -167,6 +249,10 @@ function ExploreController($scope, $rootScope, $state, BMA, $q, UIUtils, $interv $scope.MoverN = $scope.M / $scope.Nprev; $scope.cactual = 100 * $scope.UD / $scope.MoverN; $scope.formData.useRelative = USE_RELATIVE_DEFAULT; + + // Set Ink + UIUtils.ink({selector: '.peer-item'}); + UIUtils.loading.hide(); }) .catch(function(err) { @@ -214,10 +300,10 @@ function PeersController($scope, $rootScope, BMA, UIUtils, $q, $interval, $timeo return peer.pubkey; }); $scope.search.peers = _.sortBy($scope.search.peers, function(p) { - var score = 1 - + 10000 * (p.online ? 1 : 0) - + 1000 * (p.hasMainConsensusBlock ? 1 : 0) + - + 100 * (p.uid ? 1 : 0); + var score = 1; + score += (10000 * (p.online ? 1 : 0)); + score += (1000 * (p.hasMainConsensusBlock ? 1 : 0)); + score += (100 * (p.uid ? 1 : 0)); return -score; }); }; @@ -279,19 +365,19 @@ function PeersController($scope, $rootScope, BMA, UIUtils, $q, $interval, $timeo } }) .catch(function(err) { - }) + }); } } - }) + }); })) - .then(function(){ - $scope.search.lookingForPeers = false; - }) + .then(function(){ + $scope.search.lookingForPeers = false; + }); }) .catch(function(err) { //console.log(err); //UIUtils.alert.error('Could get peers from remote uCoin node.'); - //$scope.search.lookingForPeers = false; + $scope.search.lookingForPeers = false; }); }; diff --git a/www/js/controllers/home-controllers.js b/www/js/controllers/home-controllers.js index 34d490c1a8e597d63586393ca97f72eea6c10fce..55f2790b2ed45f100086ae771a4f400f80698eb0 100644 --- a/www/js/controllers/home-controllers.js +++ b/www/js/controllers/home-controllers.js @@ -1,206 +1,53 @@ angular.module('cesium.home.controllers', ['cesium.services']) - .config(function($httpProvider) { - //Enable cross domain calls - $httpProvider.defaults.useXDomain = true; - - //Remove the header used to identify ajax call that would prevent CORS from working - delete $httpProvider.defaults.headers.common['X-Requested-With']; - }) - - .controller('HomeCtrl', HomeController) - .config(function($stateProvider, $urlRouterProvider) { $stateProvider - .state('app', { - url: "/app", - abstract: true, - templateUrl: "templates/menu.html", - controller: 'HomeCtrl' - }) - .state('app.home', { url: "/home", views: { 'menuContent': { - templateUrl: "templates/home.html", + templateUrl: "templates/home/home.html", controller: 'HomeCtrl' } } }) - // if none of the above states are matched, use this as the fallback - $urlRouterProvider.otherwise('/app/home'); - }) -; - -function LoginController($scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate) { - // Login modal - $scope.loginModal = "undefined"; - $scope.loginData = {}; - - // Create the login modal that we will use later - $ionicModal.fromTemplateUrl('templates/login.html', { - scope: $scope, - focusFirstInput: true - }).then(function(modal) { - $scope.loginModal = modal; - $scope.loginModal.hide(); - }); - - $scope.setLoginForm = function(loginForm) { - $scope.loginForm = loginForm; - } - - // Open login modal - $scope.login = function(callback) { - if ($scope.loginModal != "undefined" && $scope.loginModal != null) { - $scope.loginModal.show(); - $scope.loginData.callback = callback; - } - else{ - $timeout($scope.login, 2000); - } - }; - - // Login and load wallet - $scope.loadWallet = function() { - return $q(function(resolve, reject){ - if (!Wallet.isLogin()) { - $scope.login(function() { - Wallet.loadData() - .then(function(walletData){ - resolve(walletData); - }) - .catch(function(err) { - UIUtils.loading.hide(); - console.error('>>>>>>>' , err); - UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); - reject(err); - }); - }); - } - else if (!Wallet.data.loaded) { - Wallet.loadData() - .then(function(walletData){ - resolve(walletData); - }) - .catch(function(err) { - UIUtils.loading.hide(); - console.error('>>>>>>>' , err); - UIUtils.alert.error('Could not fetch wallet data from remote uCoin node.'); - reject(err); - }); - } - else { - resolve(Wallet.data); - } - }); - }; - - // Triggered in the login modal to close it - $scope.cancelLogin = function() { - $scope.loginData = {}; // Reset login data - $scope.loginForm.$setPristine(); // Reset form - $scope.loginModal.hide(); - }; - - // Login form submit - $scope.doLogin = function() { - if(!$scope.loginForm.$valid) { - return; - } - UIUtils.loading.show(); - - $scope.loginModal.hide() - .then(function(){ - // Call wallet login, then execute callback function - Wallet.login($scope.loginData.username, $scope.loginData.password) - .then(function(){ - var callback = $scope.loginData.callback; - $scope.loginData = {}; // Reset login data - $scope.loginForm.$setPristine(); // Reset form - if (callback != "undefined" && callback != null) { - callback(); - } - // Default: redirect to wallet view - else { - $state.go('app.view_wallet'); + .state('app.join', { + url: "/join", + views: { + 'menuContent': { + templateUrl: "templates/home/home.html", + controller: 'JoinCtrl' } - }) - .catch(function(err) { - $scope.loginData = {}; // Reset login data - $scope.loginForm.$setPristine(); // Reset form - UIUtils.loading.hide(); - console.error('>>>>>>>' , err); - UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); - }); - }) - }; - - $scope.loginDataChanged = function() { - $scope.loginData.computing=false; - $scope.loginData.pubkey=null; - }; - - $scope.showLoginPubkey = function() { - $scope.loginData.computing=true; - CryptoUtils.connect($scope.loginData.username, $scope.loginData.password).then( - function(keypair) { - $scope.loginData.pubkey = CryptoUtils.util.encode_base58(keypair.signPk); - $scope.loginData.computing=false; } - ) - .catch(function(err) { - $scope.loginData.computing=false; - UIUtils.loading.hide(); - console.error('>>>>>>>' , err); - UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); - }); - }; + }) + ; - // Logout - $scope.logout = function() { - UIUtils.loading.show(); - Wallet.logout().then( - function() { - UIUtils.loading.hide(); - $ionicSideMenuDelegate.toggleLeft(); - $state.go('app.home'); - } - ); - }; + // if none of the above states are matched, use this as the fallback + $urlRouterProvider.otherwise('/app/home'); - // Is connected - $scope.isLogged = function() { - return Wallet.isLogin(); - }; + }) - // Is not connected - $scope.isNotLogged = function() { - return !Wallet.isLogin(); - }; -} + .controller('HomeCtrl', HomeController) -function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA, UIUtils, $q, $timeout, Wallet, CryptoUtils, $ionicSideMenuDelegate) { + .controller('JoinCtrl', JoinController) +; - // With the new view caching in Ionic, Controllers are only called - // when they are recreated or on app start, instead of every page change. - // To listen for when this page is active (for example, to refresh data), - // listen for the $ionicView.enter event: - //$scope.$on('$ionicView.enter', function(e) { - //}); - LoginController.call(this, $scope, $ionicModal, Wallet, CryptoUtils, UIUtils, $q, $state, $timeout, $ionicSideMenuDelegate); +function NewAccountWizardController($scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, Registry) { - $scope.accounts = []; - $scope.search = { text: '', results: {} }; - $scope.knownCurrencies = ['meta_brouzouf']; - $scope.slideIndex = 0; $scope.accountData = {}; $scope.accountForm = {}; + $scope.slides = { + slider: null, + options: { + loop: false, + effect: 'slide', + speed: 500 + } + }; // Called to navigate to the main app $scope.cancel = function() { @@ -208,6 +55,8 @@ function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA $timeout(function(){ $scope.accountData = {}; $scope.accountForm = {}; + $scope.slides.slider.destroy(); + delete $scope.slides.slider; }, 200); }; @@ -215,46 +64,51 @@ function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA $scope.accountForm = accountForm; }; - // Called each time the slide changes - $scope.slide = function(index) { - $ionicSlideBoxDelegate.slide(index); - $scope.slideIndex = index; - $scope.nextStep = $scope.slideIndex == 2 ? 'Start' : 'Next'; + $scope.slidePrev = function() { + $scope.slides.slider.unlockSwipes(); + $scope.slides.slider.slidePrev(); + $scope.slides.slider.lockSwipes(); }; - $scope.next = function() { - $scope.slide($scope.slideIndex + 1); - }; - - $scope.previous = function() { - $scope.slide($scope.slideIndex - 1); - }; + $scope.slideNext = function() { + $scope.slides.slider.unlockSwipes(); + $scope.slides.slider.slideNext(); + $scope.slides.slider.lockSwipes(); + }; $scope.newAccount = function() { var showModal = function() { - $ionicSlideBoxDelegate.enableSlide(false); - $scope.slide(0); - $scope.newAccountModal.show(); - // TODO: remove default - /*$timeout(function() { - $scope.accountData.currency = $scope.knownCurrencies[0]; - $scope.accountData.isMember = true; - $scope.next(); - $scope.next(); - }, 300);*/ - } + $scope.slides.slider.lockSwipes(); + $scope.slides.slider.slideTo(0); + UIUtils.loading.hide(); + $scope.newAccountModal.show(); + // TODO: remove default + /*$timeout(function() { + $scope.accountData.currency = $scope.knownCurrencies[0]; + $scope.accountData.isMember = true; + $scope.next(); + $scope.next(); + }, 300);*/ + }; if (!$scope.newAccountModal) { UIUtils.loading.show(); // Create the account modal that we will use later - $ionicModal.fromTemplateUrl('templates/account/new_account.html', { + $ionicModal.fromTemplateUrl('templates/home/new_account_wizard.html', { scope: $scope }).then(function(modal) { $scope.newAccountModal = modal; $scope.newAccountModal.hide() .then(function(){ - UIUtils.loading.hide(); - showModal(); + $scope.loadCurrencies() + .then(function (res) { + $scope.knownCurrencies = res; + $scope.search.looking = false; + if (!!res && res.length == 1) { + $scope.selectedCurrency = res[0].id; + } + showModal(); + }); }); }); @@ -266,13 +120,12 @@ function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA $scope.selectCurrency = function(currency) { $scope.accountData.currency = currency; - $ionicSlideBoxDelegate.slide(1); - $scope.next(); + $scope.slideNext(); }; $scope.selectAccountTypeMember = function(bool) { $scope.accountData.isMember = bool; - $scope.next(); + $scope.slideNext(); }; $scope.showAccountPubkey = function() { @@ -301,18 +154,30 @@ function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA .then(function(){ Wallet.login($scope.accountData.username, $scope.accountData.password) .then(function() { - // Reset account data - delete $scope.accountForm; - $scope.accountData = {}; - UIUtils.loading.hide(); - $state.go('app.view_wallet'); + if (!$scope.accountData.isMember) { + return; + } + + // Send self + Wallet.self($scope.accountData.pseudo, false/*do NOT load membership here*/) + .then(function() { + // Send membership IN + Wallet.membership(true) + .then(function() { + // Reset account data, and open wallet view + $scope.cancel(); + $state.go('app.view_wallet'); + }) + .catch(UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')); + }) + .catch(UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')); }) .catch(function(err) { UIUtils.loading.hide(); console.error('>>>>>>>' , err); UIUtils.alert.error('ERROR.CRYPTO_UNKNOWN_ERROR'); }); - }) + }); }; // TODO: remove auto add account when done @@ -322,3 +187,19 @@ function HomeController($scope, $ionicSlideBoxDelegate, $ionicModal, $state, BMA */ } +function HomeController($scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, Registry, APP_CONFIG) { + + NewAccountWizardController.call(this, $scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, Registry); + +} + +function JoinController($scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, Registry, APP_CONFIG) { + + NewAccountWizardController.call(this, $scope, $ionicModal, $state, $ionicSideMenuDelegate, UIUtils, $q, $timeout, CryptoUtils, BMA, Wallet, Registry); + + // open new account wizard + $timeout(function() { + $scope.newAccount(); + }, 100); + +} diff --git a/www/js/controllers/peer-controllers.js b/www/js/controllers/peer-controllers.js index ee9d7a5745db571672fafd1fd2afdb8396f12199..54fe5bbbffb85298545571ef2d262707daa666d3 100644 --- a/www/js/controllers/peer-controllers.js +++ b/www/js/controllers/peer-controllers.js @@ -21,12 +21,12 @@ function PeerController($scope, $rootScope, $ionicSlideBoxDelegate, $ionicModal, return peer; }); $scope.peers = _.sortBy(peers, function(p) { - var score = 1 - + 10000 * (p.online ? 1 : 0) - + 1000 * (p.hasMainConsensusBlock ? 1 : 0) + - + 100 * (p.uid ? 1 : 0); + var score = 1; + score += 10000 * (p.online ? 1 : 0); + score += 1000 * (p.hasMainConsensusBlock ? 1 : 0); + score += 100 * (p.uid ? 1 : 0); return -score; }); - }) + }); }; } diff --git a/www/js/controllers/settings-controllers.js b/www/js/controllers/settings-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..a87261db3aa2c63e2ef1ca7c69d4131196563217 --- /dev/null +++ b/www/js/controllers/settings-controllers.js @@ -0,0 +1,38 @@ + +angular.module('cesium.settings.controllers', ['cesium.services', 'cesium.currency.controllers']) + + .config(function($stateProvider, $urlRouterProvider) { + $stateProvider + + .state('app.settings', { + url: "/settings", + views: { + 'menuContent': { + templateUrl: "templates/settings/settings.html", + controller: 'SettingsCtrl' + } + } + }) + ; + }) + + .controller('SettingsCtrl', SettingsController) +; + +function SettingsController($scope, $state, UIUtils) { + + $scope.walletData = {}; + + $scope.$on('$ionicView.enter', function(e, $state) { + $scope.loadWallet() + .then(function(wallet) { + $scope.walletData = wallet; + UIUtils.loading.hide(); + }); + }); + + $scope.setSettingsForm = function(settingsForm) { + $scope.settingsForm = settingsForm; + }; + +} diff --git a/www/js/controllers/transfer-controllers.js b/www/js/controllers/transfer-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..e6a574edb62379ba69a44f6fb121935f273eb6fa --- /dev/null +++ b/www/js/controllers/transfer-controllers.js @@ -0,0 +1,224 @@ +angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.currency.controllers']) + + .config(function($stateProvider, $urlRouterProvider) { + $stateProvider + + .state('app.new_transfer', { + url: "/transfer", + views: { + 'menuContent': { + templateUrl: "templates/wallet/new_transfer.html", + controller: 'TransferCtrl' + } + } + }) + + .state('app.new_transfer_pubkey_uid', { + url: "/transfer/:pubkey/:uid", + views: { + 'menuContent': { + templateUrl: "templates/wallet/new_transfer.html", + controller: 'TransferCtrl' + } + } + }) + + .state('app.new_transfer_pubkey', { + url: "/transfer/:pubkey", + views: { + 'menuContent': { + templateUrl: "templates/wallet/new_transfer.html", + controller: 'TransferCtrl' + } + } + }) + ; + }) + + .controller('TransferCtrl', TransferController) +; + +function TransferController($scope, $ionicModal, $state, BMA, Wallet, UIUtils, $timeout, System) { + + TransferModalController.call(this, $scope, $ionicModal, $state, BMA, Wallet, UIUtils, $timeout, System); + + $scope.$on('$ionicView.enter', function(e, $state) { + if (!!$state.stateParams && !!$state.stateParams.pubkey) { + $scope.formData.destPub = $state.stateParams.pubkey; + if (!!$state.stateParams.uid) { + $scope.dest = $state.stateParams.uid; + } + else { + $scope.dest = $scope.destPub; + } + } + + $scope.loadWallet() + .then(function(wallet) { + $scope.walletData = wallet; + $scope.onUseRelativeChanged(); + UIUtils.loading.hide(); + }); + }); +} + +function TransferModalController($scope, $ionicModal, $state, BMA, Wallet, UIUtils, $timeout, System) { + + $scope.walletData = {}; + $scope.transferForm = {}; + $scope.convertedBalance = 0; + $scope.formData = { + destPub: null, + amount: null, + comments: null + }; + $scope.dest = null; + $scope.udAmount = null; + + WotLookupController.call(this, $scope, BMA, $state, UIUtils, $timeout, System); + + // Create the login modal that we will use later + $ionicModal.fromTemplateUrl('templates/wallet/modal_transfer.html', { + scope: $scope, + focusFirstInput: true + }).then(function(modal) { + $scope.transferModal = modal; + $scope.transferModal.hide(); + + UIUtils.ink({selector: '.ink'}); + }); + + $ionicModal.fromTemplateUrl('templates/wot/modal_lookup.html', { + scope: $scope, + focusFirstInput: true + }).then(function(modal) { + $scope.lookupModal = modal; + $scope.lookupModal.hide(); + }); + + //Cleanup the modal when we're done with it! + $scope.$on('$destroy', function() { + if (!!$scope.transferModal) { + $scope.transferModal.remove(); + } + if (!!$scope.lookupModal) { + $scope.lookupModal.remove(); + } + }); + + $scope.setTransferForm = function(transferForm) { + $scope.transferForm = transferForm; + }; + + // Open transfer modal + $scope.transfer = function(destPub, dest, amount, callback) { + UIUtils.loading.show(); + if (!!$scope.transferModal) { + $scope.formData.destPub = destPub; + if(dest) { + $scope.dest = dest; + } + else { + $scope.dest = destPub; + } + if (amount && typeof amount === "function") { + callback = amount; + } + else { + $scope.formData.amount = amount; + } + $scope.formData.callback = callback; + $scope.loadWallet() + .then(function(walletData) { + UIUtils.loading.hide(); + $scope.walletData = walletData; + $scope.transferModal.show(); + }); + } + else{ + $timeout($scope.transfer, 2000); + } + }; + + // Triggered in the login modal to close it + $scope.closeTransfer = function() { + $scope.formData = {}; // Reset login data + $scope.transferForm.$setPristine(); // Reset form + $scope.transferModal.hide(); + }; + + // When changing use relative UD + $scope.onUseRelativeChanged = function() { + if ($scope.walletData.useRelative) { + $scope.convertedBalance = $scope.walletData.balance / $scope.walletData.currentUD; + $scope.udAmount = $scope.amount * $scope.walletData.currentUD; + $scope.unit = 'universal_dividend'; + $scope.udUnit = $scope.walletData.currency; + } else { + $scope.convertedBalance = $scope.walletData.balance; + // Convert to number + $scope.formData.amount = (!!$scope.formData.amount && typeof $scope.formData.amount == "string") ? + Math.floor(parseFloat($scope.formData.amount.replace(new RegExp('[,]'), '.'))) : + $scope.formData.amount; + // Compute UD + $scope.udAmount = (!!$scope.formData.amount && + typeof $scope.formData.amount == "number" && + !!$scope.walletData.currentUD && + typeof $scope.walletData.currentUD == "number") ? + $scope.formData.amount / $scope.walletData.currentUD :null; + $scope.unit = $scope.walletData.currency; + $scope.udUnit = ''; + } + }; + $scope.$watch('walletData.useRelative', $scope.onUseRelativeChanged, true); + $scope.$watch('walletData.balance', $scope.onUseRelativeChanged, true); + + $scope.openWotLookup = function() { + $scope.lookupModal.show(); + }; + + $scope.doTransfer = function() { + UIUtils.loading.show(); + + var amount = $scope.formData.amount; + if ($scope.walletData.useRelative && !!amount && + typeof amount == "string") { + amount = $scope.walletData.currentUD * + amount.replace(new RegExp('[.,]'), '.'); + } + + Wallet.transfer($scope.formData.destPub, amount, $scope.formData.comments) + .then(function() { + var callback = $scope.formData.callback; + $scope.formData = {}; // Reset form data + $scope.transferForm.$setPristine(); // Reset form + $scope.closeTransfer(); + if (!!callback) { + callback(); + } + // Default: redirect to wallet view + else { + UIUtils.loading.hide(); + UIUtils.alert.info('INFO.TRANSFER_SENT'); + $state.go('app.view_wallet'); + } + }) + .catch(UIUtils.onError('ERROR.SEND_TX_FAILED')); + }; + + $scope.closeLookup = function() { + $scope.lookupModal.hide(); + }; + + $scope.doSelectIdentity = function(pub, uid) { + if (uid) { + $scope.dest = uid; + } + else { + $scope.dest = pub; + } + $scope.formData.destPub = pub; + $scope.lookupModal.hide(); + }; +} + diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index 26594199cb4726ecb76e356b2dfb6a5fe478c7a9..8d3dbe6e3354558b1a2949f743cf1c4ea3123e12 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -8,45 +8,31 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency url: "/wallet", views: { 'menuContent': { - templateUrl: "templates/account/view_wallet.html", + templateUrl: "templates/wallet/view_wallet.html", controller: 'WalletCtrl' } } }) - - .state('app.view_transfer', { - url: "/transfer/:pubkey/:uid", - views: { - 'menuContent': { - templateUrl: "templates/account/view_transfer.html", - controller: 'TransferCtrl' - } - } - }) - - .state('app.view_transfer_pubkey', { - url: "/transfer/:pubkey", - views: { - 'menuContent': { - templateUrl: "templates/account/view_transfer.html", - controller: 'TransferCtrl' - } - } - }) ; }) .controller('WalletCtrl', WalletController) - - .controller('TransferCtrl', TransferController) ; -function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet, BMA, $translate) { +function WalletController($scope, $state, $q, $ionicPopup, $ionicActionSheet, $timeout, + ionicMaterialMotion, ionicMaterialInk, + UIUtils, Wallet, BMA, $translate, Registry) { $scope.walletData = {}; $scope.convertedBalance = 0; $scope.hasCredit = false; $scope.isMember = false; + // Set Header + $scope.$parent.showHeader(); + $scope.$parent.clearFabs(); + $scope.isExpanded = false; + $scope.$parent.setExpanded(false); + $scope.$parent.setHeaderFab(false); $scope.$on('$ionicView.enter', function(e, $state) { $scope.loadWallet() @@ -58,11 +44,14 @@ function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet, BMA, $scope.refreshConvertedBalance = function() { if ($scope.walletData.useRelative) { - $scope.convertedBalance = $scope.walletData.balance / $scope.walletData.currentUD; + $scope.convertedBalance = $scope.walletData.balance ? ($scope.walletData.balance / $scope.walletData.currentUD) : 0; $scope.unit = 'universal_dividend'; $scope.udUnit = $scope.walletData.currency; } else { $scope.convertedBalance = $scope.walletData.balance; + if (!$scope.convertedBalance) { + $scope.convertedBalance = 0; + } $scope.unit = $scope.walletData.currency; $scope.udUnit = ''; } @@ -73,193 +62,205 @@ function WalletController($scope, $state, $q, $ionicPopup, UIUtils, Wallet, BMA, // Update view $scope.updateWalletView = function(wallet) { $scope.walletData = wallet; - $scope.hasCredit = ($scope.walletData.balance != "undefined" && $scope.walletData.balance > 0); - $scope.isMember = ($scope.walletData.requirements != "undefined" && $scope.walletData.requirements != null - && $scope.walletData.requirements.uid != "undefined" && $scope.walletData.requirements.uid != null); - }; - - // Has credit - $scope.hasCredit= function() { - return $scope.balance > 0; + $scope.hasCredit = (!!$scope.walletData.balance && $scope.walletData.balance > 0); + if (!$scope.walletData.requirements || !$scope.walletData.requirements.uid) { + $scope.needSelf = true; + $scope.needMembership = true; + $scope.needMembershipOut = false; + $scope.needRenew = false; + } + else { + $scope.needSelf = false; + $scope.needMembership = ($scope.walletData.requirements.membershipExpiresIn === 0 && + $scope.walletData.requirements.membershipPendingExpiresIn <= 0 ); + $scope.needRenew = !$scope.needMembership && ($scope.walletData.requirements.membershipExpiresIn < 129600 && + $scope.walletData.requirements.membershipPendingExpiresIn <= 0 ); + $scope.needMembershipOut = ($scope.walletData.requirements.membershipExpiresIn > 0); + } + $scope.isMember = !$scope.needSelf && !$scope.needMembership; + // Set Motion + $timeout(function() { + ionicMaterialMotion.fadeSlideInRight({ + startVelocity: 3000 + }); + // Set Ink + ionicMaterialInk.displayEffect({selector: '.item'}); + }, 10); }; // Transfer click - $scope.transfer= function() { - $state.go('app.view_transfer'); + $scope.openTransfer = function() { + if (!$scope.hasCredit) { + UIUtils.alert.info('INFO.NOT_ENOUGH_CREDIT'); + return; + } + $scope.transfer(null,null, function() { + UIUtils.loading.hide(); + UIUtils.alert.info('INFO.TRANSFER_SENT'); + }); }; $scope.setRegisterForm = function(registerForm) { $scope.registerForm = registerForm; }; - // Self cert - $scope.self= function() { + // Ask uid + $scope.showUidPopup = function() { + return $q(function(resolve, reject) { + $translate(['ACCOUNT.NEW.TITLE', 'ACCOUNT.POPUP_REGISTER.TITLE', 'ACCOUNT.POPUP_REGISTER.HELP', 'COMMON.BTN_ADD_ACCOUNT', 'COMMON.BTN_CANCEL']) + .then(function (translations) { - $translate(['ACCOUNT.NEW.TITLE', 'ACCOUNT.POPUP_REGISTER.TITLE', 'ACCOUNT.POPUP_REGISTER.HELP', 'COMMON.BTN_ADD_ACCOUNT', 'COMMON.BTN_CANCEL']) - .then(function (translations) { - - // Choose UID popup - $ionicPopup.show({ - templateUrl: 'templates/account/popup_register.html', - title: translations['ACCOUNT.POPUP_REGISTER.TITLE'], - subTitle: translations['ACCOUNT.POPUP_REGISTER.HELP'], - scope: $scope, - buttons: [ - { text: translations['COMMON.BTN_CANCEL'] }, - { - text: translations['COMMON.BTN_ADD_ACCOUNT'] /*'<b>Send</b>'*/, - type: 'button-positive', - onTap: function(e) { - $scope.registerForm.$submitted=true; - if(!$scope.registerForm.$valid || !$scope.walletData.uid) { - //don't allow the user to close unless he enters a uid - e.preventDefault(); - } else { - return $scope.walletData.uid; + // Choose UID popup + $ionicPopup.show({ + templateUrl: 'templates/wallet/popup_register.html', + title: translations['ACCOUNT.POPUP_REGISTER.TITLE'], + subTitle: translations['ACCOUNT.POPUP_REGISTER.HELP'], + scope: $scope, + buttons: [ + { text: translations['COMMON.BTN_CANCEL'] }, + { + text: translations['COMMON.BTN_ADD_ACCOUNT'] /*'<b>Send</b>'*/, + type: 'button-positive', + onTap: function(e) { + $scope.registerForm.$submitted=true; + if(!$scope.registerForm.$valid || !$scope.walletData.uid) { + //don't allow the user to close unless he enters a uid + e.preventDefault(); + } else { + return $scope.walletData.uid; + } } } + ] + }) + .then(function(uid) { + if (!uid) { // user cancel + $scope.walletData.uid = null; + UIUtils.loading.hide(); + return; } - ] - }) - .then(function(uid) { - if (!uid) { // user cancel - $scope.walletData.uid = null; - UIUtils.loading.hide(); - return; - } - var doSendSelf = function() { - Wallet.self(uid) - .then(function() { + UIUtils.loading.show(); + BMA.wot.lookup({ search: uid }) + .then(function(res) { + var found = res.results && + res.results.length > 0 && + res.results.some(function(pub){ + return pub.pubkey !== $scope.walletData.pubkey && + pub.uids && pub.uids.length > 0 && + pub.uids.some(function(idty){ + return (idty.uid === uid); + }); + }); + if (found) { // uid is already used : display a message and reopen the popup UIUtils.loading.hide(); - }) - .catch(UIUtils.onError('ERROR.SEND_SELF_REGISTRATION')); - }; - // Check uid is not used by another member - UIUtils.loading.show(); - BMA.wot.lookup({ search: uid }) - .then(function(res) { - var found = typeof res.results != "undefined" && res.results != null && res.results.length > 0 - && res.results.some(function(pub){ - return typeof pub.uids != "undefined" && pub.uids != null && pub.uids.length > 0 - && pub.uids.some(function(idty){ - return (idty.uid == uid); - }); + UIUtils.alert.info('ACCOUNT.NEW.MSG_UID_ALREADY_USED') + .then(function(){ + $scope.showUidPopup(); // loop }); - if (found) { // uid is already used : display a message and reopen the popup - UIUtils.loading.hide(); - UIUtils.alert.info('ACCOUNT.NEW.MSG_UID_ALREADY_USED') - .then(function(){ - $scope.self(); - }); - } - else { - doSendSelf(); - } - }) - .catch(function() { - doSendSelf(); + } + else { + resolve(uid); + } + }) + .catch(function() { + resolve(uid); + }); }); }); }); }; -} -function TransferController($scope, $ionicModal, $state, $ionicHistory, BMA, Wallet, UIUtils) { - - $scope.walletData = {}; - $scope.formData = { - destPub: null, - amount: null, - comments: null + // Send self identity + $scope.self= function() { + $scope.showUidPopup() + .then(function(uid) { + Wallet.self(uid) + .then(function() { + $scope.doUpdate(); + }) + .catch(UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')); + }); }; - $scope.dest = null; - $scope.udAmount = null; - WotLookupController.call(this, $scope, BMA, $state); + // Send membership IN + $scope.membershipIn= function() { + var doMembershipIn = function() { + Wallet.membership(true) + .then(function() { + $scope.doUpdate(); + }) + .catch(UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')); + }; - $scope.$on('$ionicView.enter', function(e, $state) { - if ($state.stateParams != null - && $state.stateParams.pubkey != null - && $state.stateParams.pubkey != "undefined") { - $scope.destPub = $state.stateParams.pubkey; - if ($state.stateParams.uid != null - && $state.stateParams.uid != "undefined") { - $scope.dest = $state.stateParams.uid; + $scope.showUidPopup() + .then(function (uid) { + UIUtils.loading.show(); + if (!$scope.walletData.blockUid) { + Wallet.self(uid, false/*do NOT load membership here*/) + .then(function() { + doMembershipIn(); + }) + .catch(UIUtils.onError('ERROR.SEND_IDENTITY_FAILED')); } else { - $scope.dest = $scope.destPub; + doMembershipIn(); } - } - - // Login and load wallet - $scope.loadWallet() - .then(function(walletData) { - $scope.walletData = walletData; - $scope.onUseRelativeChanged(); - UIUtils.loading.hide(); - }); - }); - // When chaing use relative UD - $scope.onUseRelativeChanged = function() { - if ($scope.walletData.useRelative) { - $scope.udAmount = $scope.amount * $scope.walletData.currentUD; - $scope.unit = 'universal_dividend'; - $scope.udUnit = $scope.walletData.currency; - } else { - $scope.formData.amount = ($scope.formData.amount != "undefined" && $scope.formData.amount != null) - ? Math.floor(parseFloat($scope.formData.amount.replace(new RegExp('[,]'), '.'))) - : null; - $scope.udAmount = $scope.amount / $scope.walletData.currentUD; - $scope.unit = $scope.walletData.currency; - $scope.udUnit = ''; - } + }) + .catch(UIUtils.onError('ERROR.SEND_MEMBERSHIP_IN_FAILED')); }; - $scope.$watch('walletData.useRelative', $scope.onUseRelativeChanged, true); - - $ionicModal.fromTemplateUrl('templates/wot/modal_lookup.html', { - scope: $scope, - focusFirstInput: true - }).then(function(modal) { - $scope.lookupModal = modal; - $scope.lookupModal.hide(); - }); - - $scope.openSearch = function() { - $scope.lookupModal.show(); - } - $scope.doTransfer = function() { + // Send membership IN + $scope.membershipOut = function() { UIUtils.loading.show(); - - var amount = $scope.formData.amount; - if ($scope.walletData.useRelative - && amount != "undefined" - && amount != null) { - amount = $scope.walletData.currentUD - * amount.replace(new RegExp('[.,]'), '.'); - } - - Wallet.transfer($scope.formData.destPub, amount, $scope.formData.comments) + Wallet.membership(false) .then(function() { + $scope.doUpdate(); + }) + .catch(UIUtils.onError('ERROR.SEND_MEMBERSHIP_OUT_FAILED')); + }; + + // Updating wallet data + $scope.doUpdate = function() { + UIUtils.loading.show(); + Wallet.refreshData() + .then(function(wallet) { + $scope.updateWalletView(wallet); UIUtils.loading.hide(); - $ionicHistory.goBack() }) - .catch(UIUtils.onError('Could not send transaction')); + .catch(UIUtils.onError('ERROR.REFRESH_WALLET_DATA')); }; - $scope.closeLookup = function() { - $scope.lookupModal.hide(); - } + // Triggered on a button click, or some other target + $scope.showActionsheet = function() { - $scope.doSelectIdentity = function(pub, uid) { - if (uid != "undefined" && uid != null) { - $scope.dest = uid; - } - else { - $scope.dest = uid; - } - $scope.formData.destPub = pub; - $scope.lookupModal.hide(); - } + $translate(['ACCOUNT.MENU_TITLE', 'ACCOUNT.BTN_MEMBERSHIP_OUT', 'ACCOUNT.POPUP_REGISTER.HELP', 'COMMON.BTN_ADD_ACCOUNT', 'COMMON.BTN_CANCEL']) + .then(function (translations) { + + // Show the action sheet + var hideMenu = $ionicActionSheet.show({ + buttons: [ + { text: translations['ACCOUNT.BTN_MEMBERSHIP_OUT'] } + ], + titleText: translations['ACCOUNT.MENU_TITLE'], + cancelText: translations['COMMON.BTN_CANCEL'], + cancel: function() { + // add cancel code.. + }, + buttonClicked: function(index) { + if (index === 0) { + $scope.membershipOut(); + } + return true; + } + }); + + // For example's sake, hide the sheet after two seconds + $timeout(function() { + hideMenu(); + }, 2000); + }); + }; } + + diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js index fbe8e6429ebe36d02b15f43e6d31a38c69c2a280..4bb94c85b710fa104d98573747af53bb67a71d87 100644 --- a/www/js/controllers/wot-controllers.js +++ b/www/js/controllers/wot-controllers.js @@ -12,6 +12,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) } } }) + ; }) .controller('IdentityCtrl', IdentityController) @@ -19,41 +20,59 @@ angular.module('cesium.wot.controllers', ['cesium.services']) .controller('WotLookupCtrl', WotLookupController) ; -function WotLookupController($scope, BMA, $state) { +function WotLookupController($scope, BMA, $state, UIUtils, $timeout, System) { + + $scope.system.camera = System; $scope.searchChanged = function() { - $scope.search.text = $scope.search.text.toLowerCase(); - if ($scope.search.text.length > 1) { - $scope.search.looking = true; - return BMA.wot.lookup({ search: $scope.search.text }) + $scope.search.looking = true; + var text = $scope.search.text.toLowerCase().trim(); + if (text.length === 0) { + $scope.search.results = []; + $scope.search.looking = false; + } + else { + return BMA.wot.lookup({ search: text }) .then(function(res){ - $scope.search.looking = false; - $scope.search.results = res.results.reduce(function(idties, res) { + var idties = res.results.reduce(function(idties, res) { return idties.concat(res.uids.reduce(function(uids, idty) { + var blocUid = idty.meta.timestamp.split('-', 2); return uids.concat({ uid: idty.uid, pub: res.pubkey, - sigDate: idty.meta.timestamp - }) + number: blocUid[0], + hash: blocUid[1] + }); }, [])); }, []); + $scope.search.results = idties; + $scope.search.looking = false; }) .catch(function() { - $scope.search.looking = false; $scope.search.results = []; + $scope.search.looking = false; }); } - else { - $scope.search.results = []; - } }; $scope.doSelectIdentity = function(pub, uid) { $state.go('app.view_identity', {pub: pub}); }; + + $scope.scanQrCode = function(){ + if (System.camera.enable) { + System.camera.scan() + .then(function(result) { + if (!result) { + $scope.search.text = result.text; + } + }) + .catch(UIUtils.alert.error('ERROR.SCAN_FAILED')); + } + }; } -function IdentityController($scope, $state, BMA, Wallet, UIUtils, $q) { +function IdentityController($scope, $state, BMA, Wallet, UIUtils, $q, ionicMaterialMotion, $timeout, ionicMaterialInk) { $scope.identity = {}; $scope.hasSelf = false; @@ -68,20 +87,37 @@ function IdentityController($scope, $state, BMA, Wallet, UIUtils, $q) { .then(function(res){ $scope.identity = res.results.reduce(function(idties, res) { return idties.concat(res.uids.reduce(function(uids, idty) { + var blocUid = idty.meta.timestamp.split('-', 2); return uids.concat({ uid: idty.uid, pub: res.pubkey, - sigDate: idty.meta.timestamp, + number: blocUid[0], + hash: blocUid[1], + revoked: idty.revoked, + revokedSig: idty.revocation_sig, sig: idty.self - }) + }); }, [])); }, [])[0]; $scope.hasSelf = ($scope.identity.uid && $scope.identity.sigDate && $scope.identity.sig); - UIUtils.loading.hide(); + BMA.blockchain.block({block: $scope.identity.number}) + .then(function(block) { + $scope.identity.sigDate = block.time; + UIUtils.loading.hide(); + + // Set Motion + $timeout(function() { + ionicMaterialMotion.fadeSlideIn({ + selector: '.item' + }); + }, 10); + }) + .catch(UIUtils.onError('ERROR.LOAD_IDENTITY_FAILED')); }) - .catch(UIUtils.onError('Could not load identity')); + .catch(UIUtils.onError('ERROR.LOAD_IDENTITY_FAILED')); }; + // Sign click $scope.signIdentity = function(identity) { $scope.loadWallet() .then(function(walletData) { @@ -92,18 +128,15 @@ function IdentityController($scope, $state, BMA, Wallet, UIUtils, $q) { $scope.identity.sig) .then(function() { UIUtils.loading.hide(); - UIUtils.alertInfo('Identity successfully signed'); + UIUtils.alertInfo('INFO.CERTIFICATION_DONE'); }) - .catch(UIUtils.onError('Could not certify identity')); + .catch(UIUtils.onError('ERROR.SEND_CERTIFICATION_FAILED')); }) - .catch(UIUtils.onError('Error while login')); + .catch(UIUtils.onError('ERROR.LOGIN_FAILED')); }; - // Transfer click - $scope.transfer = function() { - $state.go('app.view_transfer', { - pubkey: $scope.identity.pubkey, - uid: $scope.identity.uid, - }); - }; -} \ No newline at end of file + $scope.$parent.clearFabs(); + + ionicMaterialInk.displayEffect(); + +} diff --git a/www/js/services.js b/www/js/services.js index 44821043a3a0394403c3405523ae03c7e11181ed..650bb8320419e8dfbff7c1f83fe591a1a8accb6a 100644 --- a/www/js/services.js +++ b/www/js/services.js @@ -1,6 +1,10 @@ angular.module('cesium.services', [ + 'cesium.config', 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services', - 'cesium.wallet.services']) + 'cesium.wallet.services', + 'cesium.market.services', + 'cesium.registry.services' + ]) ; diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js index 75d5fdb2f07e39169833626af1844b51d182da62..093e14151c79f2b7a97faf749cebf32f8b08f764 100644 --- a/www/js/services/bma-services.js +++ b/www/js/services/bma-services.js @@ -1,141 +1,168 @@ //var Base58, Base64, scrypt_module_factory = null, nacl_factory = null; -angular.module('cesium.bma.services', ['ngResource']) +angular.module('cesium.bma.services', ['ngResource', + 'cesium.config']) -.factory('BMA', function($http, $q) { +.factory('BMA', function($http, $q, APP_CONFIG) { - function BMA(server, wsServer) { - if (wsServer == "undefined" || wsServer == null) { - wsServer = server; - } + function BMA(server, wsServer) { + if (!wsServer) { + wsServer = server; + } + + var sockets = []; - function processError(reject, data) { - if (data != null && data.message != "undefined" && data.message != null) { - reject(data.ucode + ": " + data.message); + function processError(reject, data, uri) { + if (data && data.message) { + reject(data); + } + else { + if (uri) { + reject('Error from ucoin node (' + uri + ')'); } else { reject('Unknown error from ucoin node'); } } + } - function prepare(uri, params, config, callback) { - var pkeys = [], queryParams = {}, newUri = uri; - if (typeof params == 'object') { - pkeys = _.keys(params); - } - - pkeys.forEach(function(pkey){ - var prevURI = newUri; - newUri = newUri.replace(new RegExp(':' + pkey), params[pkey]); - if (prevURI == newUri) { - queryParams[pkey] = params[pkey]; - } - }); - config.params = queryParams; - callback(newUri, config); + function prepare(uri, params, config, callback) { + var pkeys = [], queryParams = {}, newUri = uri; + if (typeof params == 'object') { + pkeys = _.keys(params); } - function getResource(uri) { - return function(params) { - return $q(function(resolve, reject) { - var config = { - timeout: 4000 - }; - - prepare(uri, params, config, function(uri, config) { - $http.get(uri, config) - .success(function(data, status, headers, config) { - resolve(data); - }) - .error(function(data, status, headers, config) { - processError(reject, data); - }); - }); - }); + pkeys.forEach(function(pkey){ + var prevURI = newUri; + newUri = newUri.replace(new RegExp(':' + pkey), params[pkey]); + if (prevURI == newUri) { + queryParams[pkey] = params[pkey]; } - } + }); + config.params = queryParams; + callback(newUri, config); + } + + function getResource(uri) { + return function(params) { + return $q(function(resolve, reject) { + var config = { + timeout: 4000 + }; - function postResource(uri) { - return function(data, params) { - return $q(function(resolve, reject) { - var config = { - timeout: 4000, - headers : {'Content-Type' : 'application/json'} - }; - - prepare(uri, params, config, function(uri, config) { - $http.post(uri, data, config) - .success(function(data, status, headers, config) { - resolve(data); - }) - .error(function(data, status, headers, config) { - processError(reject, data); - }); - }); + prepare(uri, params, config, function(uri, config) { + $http.get(uri, config) + .success(function(data, status, headers, config) { + resolve(data); + }) + .error(function(data, status, headers, config) { + processError(reject, data, uri); + }); }); - } - } + }); + }; + } - function ws(uri) { - var sock = new WebSocket(uri); - return { - on: function(type, callback) { - sock.onmessage = function(e) { - callback(JSON.parse(e.data)); - }; - } - }; - } + function postResource(uri) { + return function(data, params) { + return $q(function(resolve, reject) { + var config = { + timeout: 4000, + headers : {'Content-Type' : 'application/json'} + }; - return { - wot: { - lookup: getResource('http://' + server + '/wot/lookup/:search'), - members: getResource('http://' + server + '/wot/members'), - requirements: getResource('http://' + server + '/wot/requirements/:pubkey'), - add: postResource('http://' + server + '/wot/add') - }, - network: { - peering: { - peers: getResource('http://' + server + '/network/peering/peers') - }, - peers: getResource('http://' + server + '/network/peers') - }, - currency: { - parameters: getResource('http://' + server + '/blockchain/parameters') - }, - blockchain: { - current: getResource('http://' + server + '/blockchain/current'), - block: getResource('http://' + server + '/blockchain/block/:block'), - membership: postResource('http://' + server + '/blockchain/membership'), - stats: { - ud: getResource('http://' + server + '/blockchain/with/ud'), - tx: getResource('http://' + server + '/blockchain/with/tx') - } - }, + prepare(uri, params, config, function(uri, config) { + $http.post(uri, data, config) + .success(function(data, status, headers, config) { + resolve(data); + }) + .error(function(data, status, headers, config) { + processError(reject, data); + }); + }); + }); + }; + } - tx: { - sources: getResource('http://' + server + '/tx/sources/:pubkey'), - process: postResource('http://' + server + '/tx/process'), - history: { - all: getResource('http://' + server + '/tx/history/:pubkey'), - times: getResource('http://' + server + '/tx/history/:pubkey/times/:from/:to'), - blocks: getResource('http://' + server + '/tx/history/:pubkey/blocks/:from/:to') + function ws(uri) { + var sock = null; + return { + on: function(type, callback) { + if (!sock) { + sock = new WebSocket(uri); + sockets.push(this); } + sock.onmessage = function(e) { + callback(JSON.parse(e.data)); + }; }, - websocket: { - block: function() { - return ws('ws://' + wsServer + '/ws/block'); - }, - peer: function() { - return ws('ws://' + wsServer + '/ws/peer'); + close: function(type, callback) { + if (!!sock) { + sock.close(); + sock = null; } } + }; + } + + function closeWs() { + if (sockets.length > 0) { + sockets.forEach(function(sock) { + sock.close(); + }); + sockets = []; // Reset socks list } } - //var service = BMA('metab.ucoin.fr', 'metab.ucoin.fr:9201'); - //var service = BMA('192.168.0.28:9201'); - var service = BMA('metab.ucoin.io'); - service.instance = BMA; + + return { + wot: { + lookup: getResource('http://' + server + '/wot/lookup/:search'), + members: getResource('http://' + server + '/wot/members'), + requirements: getResource('http://' + server + '/wot/requirements/:pubkey'), + add: postResource('http://' + server + '/wot/add') + }, + network: { + peering: { + peers: getResource('http://' + server + '/network/peering/peers') + }, + peers: getResource('http://' + server + '/network/peers') + }, + currency: { + parameters: getResource('http://' + server + '/blockchain/parameters') + }, + blockchain: { + current: getResource('http://' + server + '/blockchain/current'), + block: getResource('http://' + server + '/blockchain/block/:block'), + membership: postResource('http://' + server + '/blockchain/membership'), + stats: { + ud: getResource('http://' + server + '/blockchain/with/ud'), + tx: getResource('http://' + server + '/blockchain/with/tx') + } + }, + + tx: { + sources: getResource('http://' + server + '/tx/sources/:pubkey'), + process: postResource('http://' + server + '/tx/process'), + history: { + all: getResource('http://' + server + '/tx/history/:pubkey'), + times: getResource('http://' + server + '/tx/history/:pubkey/times/:from/:to'), + blocks: getResource('http://' + server + '/tx/history/:pubkey/blocks/:from/:to') + } + }, + websocket: { + block: function() { + return ws('ws://' + wsServer + '/ws/block'); + }, + peer: function() { + return ws('ws://' + wsServer + '/ws/peer'); + }, + close : closeWs + } + }; + } + + var service = BMA(APP_CONFIG.UCOIN_NODE, APP_CONFIG.UCOIN_NODE_WS); + service.instance = BMA; return service; }) ; diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js index 0026e026bd43aff8829de58cfa081a2c4eb1f74f..e7b6eb938e1cbe4898187677abc8bd90ab03bb8c 100644 --- a/www/js/services/crypto-services.js +++ b/www/js/services/crypto-services.js @@ -69,7 +69,7 @@ angular.module('cesium.crypto.services', ['ngResource']) "N":4096, "r":16, "p":1 - } + }, // load libraries scrypt = async_load_scrypt(), @@ -87,7 +87,8 @@ angular.module('cesium.crypto.services', ['ngResource']) hash_sha256 = function(s) { return $q(function(resolve, reject) { - var hash = nacl.crypto_hash_sha256(s); + var hash = CryptoJS.SHA256(s); + //var hash = nacl.crypto_hash_sha256(s); resolve(hash); }); }, @@ -104,7 +105,7 @@ angular.module('cesium.crypto.services', ['ngResource']) ); var keypair = nacl.crypto_sign_keypair_from_seed(seed); resolve(keypair); - }) + }); }, /** @@ -139,10 +140,8 @@ angular.module('cesium.crypto.services', ['ngResource']) for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; var signature = base64.encode(sig); resolve(signature); - }) - } - - ; + }); + }; // Service's exposed methods return { @@ -162,8 +161,9 @@ angular.module('cesium.crypto.services', ['ngResource']) sign: sign, verify: verify //,isCompatible: isCompatible - } + }; } + var service = CryptoUtils(); service.instance = CryptoUtils; return service; diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js index 2c209d31cbbee0241816cbda788182364a402905..ca0a357d183b18913df4d7f9d95cd6adc8deb134 100644 --- a/www/js/services/utils-services.js +++ b/www/js/services/utils-services.js @@ -2,15 +2,18 @@ angular.module('cesium.utils.services', ['ngResource']) -.factory('UIUtils', function($ionicLoading, $ionicPopup, $translate, $q) { +.factory('UIUtils', function($ionicLoading, $ionicPopup, $translate, $q, ionicMaterialInk, ionicMaterialMotion) { + + var loadingTextCache=null; + function alertError(err, subtitle) { - $translate([err, 'ERROR.POPUP_TITLE', 'ERROR.UNKNOWN_ERROR', 'COMMON.BTN_OK']) + $translate([err, subtitle, 'ERROR.POPUP_TITLE', 'ERROR.UNKNOWN_ERROR', 'COMMON.BTN_OK']) .then(function (translations) { var message = err.message || translations[err]; return $ionicPopup.show({ template: '<p>' + (message || translations['ERROR.UNKNOWN_ERROR']) + '</p>', title: translations['ERROR.POPUP_TITLE'], - subTitle: subtitle, + subTitle: translations[subtitle], buttons: [ { text: '<b>'+translations['COMMON.BTN_OK']+'</b>', @@ -23,12 +26,12 @@ angular.module('cesium.utils.services', ['ngResource']) function alertInfo(message, subtitle) { return $q(function(resolve, reject) { - $translate([message, 'INFO.POPUP_TITLE', 'COMMON.BTN_OK']) + $translate([message, subtitle, 'INFO.POPUP_TITLE', 'COMMON.BTN_OK']) .then(function (translations) { return $ionicPopup.show({ template: '<p>' + translations[message] + '</p>', title: translations['INFO.POPUP_TITLE'], - subTitle: subtitle, + subTitle: translations[subtitle], buttons: [ { text: '<b>'+translations['COMMON.BTN_OK']+'</b>', @@ -48,17 +51,37 @@ angular.module('cesium.utils.services', ['ngResource']) } function showLoading() { + if (!loadingTextCache) { + $translate(['COMMON.LOADING']) + .then(function(translations){ + loadingTextCache = translations['COMMON.LOADING']; + showLoading(); + }); + return; + } + $ionicLoading.show({ - template: 'Loading...' + template: loadingTextCache }); } - function onError(msg) { + function onError(msg, reject/*optional*/) { return function(err) { - console.error('>>>>>>>' , err); - hideLoading(); - alertError(msg + ': ' + err); - } + var fullMsg = msg; + if (!!err && !!err.message) { + fullMsg = msg + ': ' + err.message; + } + // If reject has been given, use it + if (!!reject) { + reject(fullMsg); + } + // Otherwise, log to console and display error + else { + console.error('>>>>>>>' , err); + hideLoading(); + alertError(fullMsg); + } + }; } return { @@ -70,7 +93,9 @@ angular.module('cesium.utils.services', ['ngResource']) show: showLoading, hide: hideLoading }, - onError: onError + onError: onError, + ink: ionicMaterialInk.displayEffect, + motion: ionicMaterialMotion }; }) @@ -88,7 +113,257 @@ angular.module('cesium.utils.services', ['ngResource']) getObject: function(key) { return JSON.parse($window.localStorage[key] || '{}'); } - } + }; }]) +// See http://plnkr.co/edit/vJQXtsZiX4EJ6Uvw9xtG?p=preview +.factory('$focus', function($timeout, $window) { + return function(id) { + // timeout makes sure that it is invoked after any other event has been triggered. + // e.g. click events that need to run before the focus or + // inputs elements that are in a disabled state but are enabled when those events + // are triggered. + $timeout(function() { + var element = $window.document.getElementById(id); + if(element) + element.focus(); + }); + }; +}) + +.factory('System', function($timeout, $window, UIUtils, $translate, $ionicPopup, $cordovaClipboard, $cordovaBarcodeScanner, $q) { + + var CONST = { + MAX_HEIGHT: 400, + MAX_WIDTH: 400 + }, + camera = { + enable: false + }, + scan = { + enable: false + }, + clipboard = { + enable: false + }; + + ionic.Platform.ready(function() { + // Check if camera AND scan is enable + camera.enable = !!navigator.camera /*&& !(!$cordovaBarcodeScanner || !$cordovaBarcodeScanner.scan)*/; + camera.handle = navigator.camera; + + // Check if clipboard is enable + clipboard.enable = !(!$cordovaClipboard || !$cordovaClipboard.copy); + }); + + function resizeImageFromFile(file) { + return $q(function(resolve, reject) { + + var reader = new FileReader(); + + reader.addEventListener("load", function () { + var img = document.createElement("img"); + img.src = reader.result; + + var width = img.width; + var height = img.height; + + if (width > height) { + if (width > CONST.MAX_WIDTH) { + height *= CONST.MAX_WIDTH / width; + width = CONST.MAX_WIDTH; + } + } else { + if (height > CONST.MAX_HEIGHT) { + width *= CONST.MAX_HEIGHT / height; + height = CONST.MAX_HEIGHT; + } + } + var canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + var ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0, width, height); + + var dataurl = canvas.toDataURL("image/png"); + + resolve(dataurl); + }, false); + + if (file) { + reader.readAsDataURL(file); + } + else { + reject("Not a file") + } + }); + + img.src = imageData; + reader.readAsDataURL(file); + + + } + + camera.takePicture = function(sourceType) { + return $q(function (resolve, reject) { + if (!camera.enable) { + reject('Camera not enable. Please check [system.camera.enable] before use.'); + return; + } + if (!sourceType) { + $translate(['SYSTEM.PICTURE_CHOOSE_TYPE', 'SYSTEM.BTN_PICTURE_GALLERY', 'SYSTEM.BTN_PICTURE_CAMERA']) + .then(function(translations){ + $ionicPopup.show({ + title: translations['SYSTEM.PICTURE_CHOOSE_TYPE'], + buttons: [ + { + text: translations['SYSTEM.BTN_PICTURE_GALLERY'], + type: 'button', + onTap: function(e) { + return navigator.camera.PictureSourceType.PHOTOLIBRARY; + } + }, + { + text: translations['SYSTEM.BTN_PICTURE_CAMERA'], + type: 'button button-positive', + onTap: function(e) { + return navigator.camera.PictureSourceType.CAMERA; + } + } + ] + }) + .then(function(sourceType){ + camera.takePicture(sourceType); + }); + }); + } + else { + var options = { + quality: 50, + destinationType: navigator.camera.DestinationType.DATA_URL, + sourceType: sourceType, + encodingType: navigator.camera.EncodingType.PNG, + targetWidth : CONST.MAX_WIDTH, + targetHeight : CONST.MAX_HEIGHT + }; + camera.handle.camera.getPicture( + function (imageData) {resolve(imageData);}, + function(err){reject(err);}, + options + ); + } + }); + }; + + camera.scan = function () { + return $q(function(resolve,reject){ + if (!scan.enable) { + reject('Camera not enable. Please check [system.camera.enable] before use.'); + return; + } + $cordovaBarcodeScanner.scan() + .then(function(result) { + if (!result.cancelled) { + resolve(result); + } + else { + resolve(); + } + }, + function(error) {reject(error);}); + }); + }; + + + + clipboard.copy = function (text, callback) { + if (!clipboard.enable) { + return; // Always to call copy, but do nothing if not available + } + $cordovaClipboard + .copy(text) + .then(function () { + // success + if (callback) { + callback(); + } + else { + console.log("Copy text to clipboard: " + text); + } + }, function () { + // error + UIUtils.alert.error('ERROR.COPY_CLIPBOARD'); + }); + }; + + return { + image: { + resize: resizeImageFromFile + }, + clipboard: { + enable: clipboard.enable, + copy: clipboard.copy + }, + camera: { + enable: camera.enable, + take: camera.takePicture, + scan: camera.scan + }, + }; +}) + +.service('ModalService', function($ionicModal, $rootScope, $q, $controllers) { + + var show = function(tpl, $scope) { + + var promise; + $scope = $scope || $rootScope.$new(); + + promise = $q(function(resolve, reject){ + $ionicModal.fromTemplateUrl(tpl, { + scope: $scope, + animation: 'slide-in-up' + }).then(function(modal) { + $scope.modal = modal; + $scope.modal.show(); + }); + }); + + $scope.openModal = function() { + $scope.modal.show(); + }; + $scope.closeModal = function(result) { + $scope.modal.hide(); + resolve(result); + }; + $scope.$on('$destroy', function() { + $scope.modal.remove(); + }); + + return promise; + }; + + return { + show: show + }; + +}) + + + +.directive('eventFocus', function(focus) { + return function(scope, elem, attr) { + elem.on(attr.eventFocus, function() { + focus(attr.eventFocusId); + }); + + // Removes bound events in the element itself + // when the scope is destroyed + scope.$on('$destroy', function() { + elem.off(attr.eventFocus); + }); + }; +}) + + ; diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index 6da5f8cdb017c28fa73cdf528bc899461c72c9d5..ac86b1f3a74b1772e9478e0a0eaa615f65dfde98 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -2,7 +2,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', 'cesium.crypto.services']) -.factory('Wallet', ['CryptoUtils', 'BMA', '$q', function(CryptoUtils, BMA, $q) { +.factory('Wallet', ['$q', 'CryptoUtils', 'BMA', function($q, CryptoUtils, BMA) { Wallet = function(id) { @@ -10,8 +10,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' USE_RELATIVE_DEFAULT = true, - createData = function() { - return { + data = { pubkey: null, keypair: { signSk: null, @@ -22,44 +21,85 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' useRelative: USE_RELATIVE_DEFAULT, currency: null, currentUD: null, + medianTime: null, history: {}, - requirements: null, - loaded: false - }; + requirements: {}, + loaded: false, + blockUid: null, + sigQty: null, + avatar: null }, - data = createData(), - - reduceTx = function(txArray) { - var list = []; - txArray.forEach(function(tx) { - var issuerIndex = -1; - var issuer = tx.issuers.reduce(function(issuer, res, index) { - issuerIndex = (res == data.pubkey) ? index : issuerIndex; - return issuer + ((res != data.pubkey) ? ', ' + res : ''); - }, ', ').substring(2); - var amount = - tx.inputs.reduce(function(sum, input) { - var inputArray = input.split(':',5); - return sum - ((inputArray[0] == issuerIndex) ? parseInt(inputArray[4]) : 0); - }, 0); - amount += tx.outputs.reduce(function(sum, output) { - var outputArray = output.split(':',2); - return sum + ((outputArray[0] == data.pubkey) ? parseInt(outputArray[1]) : 0); - }, 0); - - list.push({ - time: ((tx.time != null && tx.time != "undefined") ? tx.time : 9999999), - amount: amount, - issuer: issuer, - comments: 'comments', - isUD: false, - hash: tx.hash, - block_number: tx.block_number - }); - }); + resetData = function() { + data.pubkey= null; + data.keypair ={ + signSk: null, + signPk: null + }; + data.balance = 0; + data.sources = null; + data.useRelative = USE_RELATIVE_DEFAULT; + data.currency= null; + data.currentUD= null; + data.medianTime = null; + data.history= {}; + data.requirements= {}; + data.loaded= false; + data.blockUid= null; + data.sigQty = null; + data.avatar = null; + }, - return list; + reduceTxAndPush = function(txArray, result) { + if (!txArray || txArray.length === 0) { + return; + } + txArray.forEach(function(tx) { + var walletIsIssuer = false; + var otherIssuer = tx.issuers.reduce(function(issuer, res, index) { + walletIsIssuer = (res === data.pubkey) ? true : walletIsIssuer; + return issuer + ((res !== data.pubkey) ? ', ' + res : ''); + }, ', ').substring(2); + var otherReceiver = (!walletIsIssuer) ? data.pubkey : ''; + var amount = tx.outputs.reduce(function(sum, output) { + var outputArray = output.split(':',3); + var outputAmount = parseInt(outputArray[0]); + var outputCondArray = outputArray[2].split('(', 3); + var outputPubkey = (outputCondArray.length == 2 && outputCondArray[0] == 'SIG') ? + outputCondArray[1].substring(0,outputCondArray[1].length-1) : ''; + if (outputPubkey == data.pubkey) { // output is for the wallet + if (!walletIsIssuer) { + return sum + outputAmount; + } + } + else { // output is for someone else + if (outputPubkey !== '') { + otherReceiver = outputPubkey; + } + if (walletIsIssuer) { + return sum - outputAmount; + } + } + return sum; + }, 0); + + var time = tx.time; + if (!time) { + time= Math.floor(moment().utc().valueOf() / 1000); + } + + result.push({ + time: time, + amount: amount, + issuer: otherIssuer, + receiver: otherReceiver, + comment: tx.comment, + isUD: false, + hash: tx.hash, + locktime: tx.locktime, + block_number: tx.block_number + }); + }); }, login = function(salt, password) { @@ -69,7 +109,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' // Copy result to properties data.pubkey = CryptoUtils.util.encode_base58(keypair.signPk); data.keypair = keypair; - resolve(); + resolve(data); } ); }); @@ -77,14 +117,13 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' logout = function(username, password) { return $q(function(resolve, reject) { - data = createData(); + resetData(); resolve(); }); }, isLogin = function() { - return data.pubkey != "undefined" - && data.pubkey != null; + return !!data.pubkey; }, getData = function() { @@ -92,10 +131,104 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' }, isSourceEquals = function(arg1, arg2) { - return arg1.type == arg2.type - && arg1.fingerprint == arg2.fingerprint - && arg1.number == arg2.number - && arg1.amount == arg2.amount; + return arg1.type == arg2.type && + arg1.fingerprint == arg2.fingerprint && + arg1.number == arg2.number && + arg1.amount == arg2.amount; + }, + + loadRequirements = function() { + return $q(function(resolve, reject) { + // Get requirements + BMA.wot.requirements({pubkey: data.pubkey}) + .then(function(res){ + if (!res.identities && res.identities.length != 1) { + data.requirements = null; + data.blockUid = null; + resolve(); + return; + } + var idty = res.identities[0]; + data.requirements = idty; + data.uid = idty.uid; + data.blockUid = idty.meta.timestamp; + // TODO + //data.requirements.needCertifications = (idty.certifications.length < data.sigQty); + resolve(); + }) + .catch(function(err) { + data.requirements = {}; + data.blockUid = null; + // If identity not publiched : continue + if (!!err && err.ucode == 2004) { + resolve(); + } + else { + reject(err); + } + }); + }); + }, + + loadSources = function(refresh) { + return $q(function(resolve, reject) { + // Get transactions + BMA.tx.sources({pubkey: data.pubkey}) + .then(function(res){ + if (!data.sources) { + data.sources=[]; + } + var sources = []; + var balance = 0; + if (!!res.sources && res.sources.length > 0) { + res.sources.forEach(function(src) { + var srcKey = src.type+':'+src.identifier+':'+src.noffset; + if (!!data.sources[srcKey]) { + src.consumed = data.sources[srcKey].consumed; + } + else { + src.consumed = false; + } + //if (!src.consumed) { + balance += src.amount; + //} + sources.push(src); + sources[srcKey] = src; + }); + } + data.sources = sources; + data.balance = balance; + resolve(); + }) + .catch(function(err) { + data.sources = []; + reject(err); + }); + }); + }, + + loadTransactions = function() { + return $q(function(resolve, reject) { + // Get transactions + BMA.tx.history.all({pubkey: data.pubkey}) + .then(function(res){ + var list = []; + reduceTxAndPush(res.history.sent, list); + reduceTxAndPush(res.history.received, list); + reduceTxAndPush(res.history.sending, list); + reduceTxAndPush(res.history.receiving, list); + reduceTxAndPush(res.history.pending, list); + + data.history = list.sort(function(tx1, tx2) { + return tx2.time - tx1.time; + }); + resolve(); + }) + .catch(function(err) { + data.history = []; + reject(err); + }); + }); }, loadData = function(refresh) { @@ -112,6 +245,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' BMA.currency.parameters() .then(function(json){ data.currency = json.currency; + data.sigQty = json.sigQty; }), // Get the UD informations @@ -127,59 +261,17 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' }), // Get sources - BMA.tx.sources({pubkey: data.pubkey}) - .then(function(res){ - data.sources = res.sources; - - var balance = 0; - if (res.sources.length) { - for (var i=0; i<res.sources.length; i++) { - balance += res.sources[i].amount; - res.sources[i].consumed = false; - } - } - data.balance = balance; - }), + loadSources(false), // Get requirements - BMA.wot.requirements({pubkey: data.pubkey}) - .then(function(res){ - if (res.identities != "undefined" - && res.identities != null - && res.identities.length == 1) { - data.requirements = res.identities[0]; - data.uid = res.identities[0].uid; - } - }) - .catch(function(err) { - data.requirements = null; - }), + loadRequirements(), // Get transactions - BMA.tx.history.all({pubkey: data.pubkey}) - .then(function(res){ - var list = reduceTx(res.history.sent); - list.push(reduceTx(res.history.received)); - list.push(reduceTx(res.history.sending)); - list.push(reduceTx(res.history.receiving)); - list.push(reduceTx(res.history.pending)); - - var history = []; - list.forEach(function(tx){ - history['T:'+ tx.block_number + tx.hash] = tx; - }); - var result = []; - _.keys(history).forEach(function(key) { - result.push(history[key]); - }) - data.history = result.sort(function(tx1, tx2) { - return tx2.time - tx1.time; - }); - }) + loadTransactions() ]) .then(function() { data.loaded = true; - resolve(data); + resolve(data); }) .catch(function(err) { data.loaded = false; @@ -205,54 +297,17 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' }), // Get requirements - BMA.wot.requirements({pubkey: data.pubkey}) - .then(function(res){ - if (res.identities != "undefined" - && res.identities != null - && res.identities.length == 1) { - data.requirements = res.identities[0]; - data.uid = res.identities[0].uid; - } - else { - data.requirements = null; - } - }) - .catch(function(err) { - data.requirements = null; - }), + loadRequirements(), // Get sources - BMA.tx.sources({pubkey: data.pubkey}) - .then(function(res){ + loadSources(true), - var balance = 0; - if (res.sources.length) { - for (var i=0; i<res.sources.length; i++) { - res.sources[i].consumed = false; - if (data.sources.length) { - for (var j=0; j<data.sources.length; j++) { - if (isSourceEquals(res.sources[i], data.sources[j]) - && data.sources[j].consumed){ - res.sources[i].consumed = true; - break; - } - } - } - if (!res.sources[i].consumed){ - balance += res.sources[i].amount; - } - } - data.sources = res.sources; - } - data.balance = balance; - }) + // Get transactions + loadTransactions() ]) .then(function() { resolve(data); - }) - .catch(function(err) { - reject(err); - }); + }).catch(function(err){reject(err);}); }); }, @@ -265,7 +320,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' if (!isLogin()){ reject('Wallet required to be login first.'); return; } - if (amount == null) { + if (!amount) { reject('amount must not be null'); return; } amount = Math.round(amount); @@ -276,21 +331,23 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' reject('Not enought credit'); return; } - var tx = "Version: 1\n" - + "Type: Transaction\n" - + "Currency: " + data.currency + "\n" - + "Issuers:\n" - + data.pubkey + "\n" - + "Inputs:\n"; - var sourceAmount = 0; + var tx = "Version: 2\n"; + tx += "Type: Transaction\n"; + tx += "Currency: " + data.currency + "\n"; + tx += "Locktime: 0" + "\n"; // no lock + tx += "Issuers:\n"; + tx += data.pubkey + "\n"; + tx += "Inputs:\n"; + var sourceAmount = 0; + var outputBase = 0; var inputs = []; - for (var i = 0; i<data.sources.length; i++) { + var i; + for (i = 0; i<data.sources.length; i++) { var input = data.sources[i]; - if (input.consumed == "undefined" || !input.consumed){ - // INDEX:SOURCE:NUMBER:FINGERPRINT:AMOUNT - tx += "0:"+input.type+":"+ input.number+":" - + input.fingerprint+":" - + input.amount+"\n"; + if (!input.consumed){ + // if D : D:PUBLIC_KEY:BLOCK_ID + // if T : T:T_HASH:T_INDEX + tx += input.type +":"+input.identifier+":"+input.noffset+"\n"; sourceAmount += input.amount; inputs.push(input); if (sourceAmount >= amount) { @@ -300,89 +357,114 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' } if (sourceAmount < amount) { - reject('Not enought sources (max amount: ' - +(data.useRelative ? (sourceAmount / data.currentUD)+' UD' : sourceAmount) - +'). Please wait next block computation.'); + if (sourceAmount === 0) { + reject('ERROR.ALL_SOURCES_USED'); + } + else { + console.error('Maximum transaction sources has been reached: ' + (data.useRelative ? (sourceAmount / data.currentUD)+' UD' : sourceAmount)); + reject('ERROR.NOT_ENOUGH_SOURCES'); + } return; } - tx += "Outputs:\n" - // ISSUERS:AMOUNT - + destPub +":" + amount + "\n"; - if (sourceAmount > amount) { - tx += data.pubkey+":"+(sourceAmount-amount)+"\n"; + tx += 'Unlocks:\n'; + for (i=0; i<inputs.length; i++) { + // INPUT_INDEX:UNLOCK_CONDITION + tx += i + ':SIG(0)\n'; } - tx += "Comment: "+ (comments!=null?comments:"") + "\n"; - + tx += 'Outputs:\n'; + // AMOUNT:BASE:CONDITIONS + tx += amount + ':'+outputBase+':SIG('+destPub+')\n'; + if (sourceAmount > amount) { + tx += (sourceAmount-amount)+':'+outputBase+':SIG('+data.pubkey+')\n'; + } + tx += "Comment: "+ (!!comments?comments:"") + "\n"; CryptoUtils.sign(tx, data.keypair) - .then(function(signature) { - var signedTx = tx + signature + "\n"; - BMA.tx.process({transaction: signedTx}) - .then(function(result) { - data.balance -= amount; - for(var i=0;i<inputs.length;i++)inputs[i].consumed=true; - resolve(result); - }) - .catch(function(err){ - reject(err); - }); - }) - .catch(function(err){ - reject(err); - }); + .then(function(signature) { + var signedTx = tx + signature + "\n"; + BMA.tx.process({transaction: signedTx}) + .then(function(result) { + data.balance -= amount; + for(var i=0;i<inputs.length;i++)inputs[i].consumed=true; + resolve(result); + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); }); }, /** - * Send self certification + * Send self identity */ - self = function(uid) { + self = function(uid, requirements) { return $q(function(resolve, reject) { BMA.blockchain.current() .then(function(block) { - // Create the self part to sign - var self = 'UID:' + uid + '\n' - + 'META:TS:' + (block.time+1) + '\n'; - - CryptoUtils.sign(self, data.keypair) + // Create identity to sign + var identity = 'Version: 2\n' + + 'Type: Identity\n' + + 'Currency: ' + data.currency + '\n' + + 'Issuer: ' + data.pubkey + '\n' + + 'UniqueID: ' + uid + '\n' + + 'Timestamp: ' + block.number + '-' + block.hash + '\n'; + + CryptoUtils.sign(identity, data.keypair) .then(function(signature) { - var signedSelf = self + signature + '\n'; - // Send self - BMA.wot.add({pubkey: data.pubkey, self: signedSelf, other: ''}) + var signedIdentity = identity + signature + '\n'; + // Send signed identity + BMA.wot.add({identity: signedIdentity}) .then(function(result) { - // Check requirements - BMA.wot.requirements({pubkey: data.pubkey}) - .then(function(res){ - if (res.identities != "undefined" - && res.identities != null - && res.identities.length == 1) { - data.requirements = res.identities[0]; - data.uid = uid; + if (!!requirements) { + // Refresh membership data + loadRequirements() + .then(function() { resolve(); - } - else{ - reject(); - } - }) - .catch(function(err) { - reject(); - }) - }) - .catch(function(err){ - reject(err); - }); - }) - .catch(function(err){ - reject(err); - }); - }) - .catch(function(err) { - reject(err); - }); + }).catch(function(err){reject(err);}); + } + else { + data.blockUid = block.number + '-' + block.hash; + resolve(); + } + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); + }); + }, + + /** + * Send membership (in) + */ + membership = function(sideIn) { + return $q(function(resolve, reject) { + BMA.blockchain.current() + .then(function(block) { + // Create membership to sign + var membership = 'Version: 2\n' + + 'Type: Membership\n' + + 'Currency: ' + data.currency + '\n' + + 'Issuer: ' + data.pubkey + '\n' + + 'Block: ' + block.number + '-' + block.hash + '\n' + + 'Membership: ' + (!!sideIn ? "IN" : "OUT" ) + '\n' + + 'UserID: ' + data.uid + '\n' + + 'CertTS: ' + data.blockUid + '\n'; + + CryptoUtils.sign(membership, data.keypair) + .then(function(signature) { + var signedMembership = membership + signature + '\n'; + // Send signed membership + BMA.blockchain.membership({membership: signedMembership}) + .then(function(result) { + // Refresh membership data + loadRequirements() + .then(function() { + resolve(); + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); }); }, @@ -395,34 +477,25 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' BMA.blockchain.current() .then(function(block) { // Create the self part to sign - var self = 'UID:' + uid + '\n' - + 'META:TS:' + timestamp + '\n' - + signature /*+"\n"*/; + var self = 'UID:' + uid + '\n' + + 'META:TS:' + timestamp + '\n' + + signature /*+"\n"*/; - var cert = self + '\n' - + 'META:TS:' + block.number + '-' + block.hash + '\n'; + var cert = self + '\n' + + 'META:TS:' + block.number + '-' + block.hash + '\n'; CryptoUtils.sign(cert, data.keypair) .then(function(signature) { - var inlineCert = data.pubkey - + ':' + pubkey - + ':' + block.number - + ':' + signature + '\n'; + var inlineCert = data.pubkey + + ':' + pubkey + + ':' + block.number + + ':' + signature + '\n'; BMA.wot.add({pubkey: pubkey, self: self, other: inlineCert}) .then(function(result) { resolve(result); - }) - .catch(function(err){ - reject(err); - }); - }) - .catch(function(err){ - reject(err); - }); - }) - .catch(function(err) { - reject(err); - }); + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); + }).catch(function(err){reject(err);}); }); }, @@ -431,9 +504,9 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' */ toJson = function() { return $q(function(resolve, reject) { - var json = JSON.stringify(data); - resolve(json); - }) + var json = JSON.stringify(data); + resolve(json); + }); }, /** @@ -441,50 +514,52 @@ angular.module('cesium.wallet.services', ['ngResource', 'cesium.bma.services', ' */ fromJson = function(json) { return $q(function(resolve, reject) { - var obj = JSON.parse(json || '{}'); - if (obj.keypair != "undefined" - && obj.keypair != null) { - var keypair = obj.keypair; + var obj = JSON.parse(json || '{}'); + if (obj.keypair) { + var keypair = obj.keypair; + var i; - // Convert to Uint8Array type - var signPk = new Uint8Array(32); - for (var i = 0; i < 32; i++) signPk[i] = keypair.signPk[i]; - keypair.signPk = signPk; + // Convert to Uint8Array type + var signPk = new Uint8Array(32); + for (i = 0; i < 32; i++) signPk[i] = keypair.signPk[i]; + keypair.signPk = signPk; - var signSk = new Uint8Array(64); - for (var i = 0; i < 64; i++) signSk[i] = keypair.signSk[i]; - keypair.signSk = signSk; + var signSk = new Uint8Array(64); + for (i = 0; i < 64; i++) signSk[i] = keypair.signSk[i]; + keypair.signSk = signSk; - data.pubkey = obj.pubkey; - data.keypair = keypair; + data.pubkey = obj.pubkey; + data.keypair = keypair; - resolve(); - } - else { - reject('Not a valid Wallet.data object'); - } - }) + resolve(); + } + else { + reject('Not a valid Wallet.data object'); + } + }); }; return { - id: id, - data: data, - // auth - login: login, - logout: logout, - isLogin: isLogin, - getData: getData, - loadData: loadData, - refreshData: refreshData, - // operations - transfer: transfer, - self: self, - sign: sign, - // serialization - toJson: toJson, - fromJson: fromJson - } - } + id: id, + data: data, + // auth + login: login, + logout: logout, + isLogin: isLogin, + getData: getData, + loadData: loadData, + refreshData: refreshData, + // operations + transfer: transfer, + self: self, + membership: membership, + sign: sign, + // serialization + toJson: toJson, + fromJson: fromJson + }; + }; + var service = Wallet('default'); service.instance = service; return service; diff --git a/www/js/vendor/base58.js b/www/js/vendor/base58.js index cc9be45841ad86685e5fe422db300be150d720dc..906362e4de9213ac1ae4f479c9e46b1c9f9785f6 100644 --- a/www/js/vendor/base58.js +++ b/www/js/vendor/base58.js @@ -2,11 +2,11 @@ (function() { var Base58 = (typeof module !== "undefined" && module !== null ? module.exports : void 0) || (window.Base58 = {}); - Base58.alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' - Base58.alphabetMap = {} + Base58.alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; + Base58.alphabetMap = {}; for(var i = 0; i < Base58.alphabet.length; i++) { - Base58.alphabetMap[Base58.alphabet.charAt(i)] = i + Base58.alphabetMap[Base58.alphabet.charAt(i)] = i; } Base58.encode = function(buffer) { @@ -52,7 +52,7 @@ Base58.decode = function(string) { var bytes, c, carry, j; if (string.length === 0) { - return new (typeof Uint8Array !== "undefined" && Uint8Array !== null ? Uint8Array : Buffer)(0); + return (typeof Uint8Array !== "undefined" && Uint8Array !== null ? new Uint8Array(0) : new Buffer(0)); } i = void 0; j = void 0; @@ -88,7 +88,7 @@ bytes.push(0); i++; } - return new (typeof Uint8Array !== "undefined" && Uint8Array !== null ? Uint8Array : Buffer)(bytes.reverse()); + return (typeof Uint8Array !== "undefined" && Uint8Array !== null ? new Uint8Array(bytes.reverse()) : new Buffer(bytes.reverse())); }; }).call(this); diff --git a/www/js/vendor/nacl_factory.js b/www/js/vendor/nacl_factory.js index a1a427c6c7b6284421d3fe9c690024235d4ceee0..a02727a30c9a5d4e2b79f5fcd2c11fa1036888aa 100644 --- a/www/js/vendor/nacl_factory.js +++ b/www/js/vendor/nacl_factory.js @@ -1,23 +1,24 @@ /* * #%L - * uCoinj :: UI Wicket + * Cesium * %% * Copyright (C) 2014 - 2016 EIS * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as - * published by the Free Software Foundation, either version 3 of the + * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public + * + * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% + * Source: https://github.com/tonyg/js-nacl/releases/tag/0.6.0 */ var nacl_factory = { instantiate: function (requested_total_memory) { @@ -441,747 +442,747 @@ var nb, ob, pb; nb = nb = F([0, 0, 0, 0, 0, 0, 0, 0], "i8", E); ob = ob = F([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", E); pb = pb = F([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", E); -F([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, -32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 36, 64, 0, 0, 0, 0, 0, 0, 89, 64, 0, 0, 0, 0, 0, 136, 195, 64, 0, 0, 0, 0, 132, 215, 151, 65, 0, 128, 224, 55, 121, 195, 65, 67, 23, 110, 5, 181, 181, 184, 147, 70, 245, 249, 63, 233, 3, 79, 56, 77, 50, 29, 48, 249, 72, 119, 130, 90, 60, 191, 115, 127, 221, 79, 21, 117, 16, 182, 1, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 100, 111, 101, -115, 110, 39, 116, 32, 116, 97, 107, 101, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 46, 42, 115, 0, 27, 0, 0, 0, 19, 0, 0, 0, 44, 0, 0, 0, 10, 0, 0, 0, 163, 0, 0, 0, 229, 0, 0, 0, 156, 0, 0, 0, 237, 0, 0, 0, 167, 0, 0, 0, 41, 0, 0, 0, 99, 0, 0, 0, 8, 0, 0, 0, 93, 0, 0, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 0, 0, 235, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, -0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 19, 0, 0, 0, 44, 0, 0, 0, 10, 0, 0, 0, 163, 0, 0, 0, 229, 0, 0, 0, 156, 0, 0, 0, 237, 0, 0, 0, 167, 0, 0, 0, 41, 0, 0, 0, 99, 0, 0, 0, 8, 0, 0, 0, 93, 0, 0, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 0, 0, 235, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, -0, 0, 0, 255, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 211, 0, 0, 0, 245, 0, 0, 0, 92, 0, 0, 0, 26, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 88, 0, 0, 0, 214, 0, 0, 0, 156, 0, 0, 0, 247, 0, 0, 0, 162, 0, 0, 0, 222, 0, 0, 0, 249, 0, 0, 0, 222, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 237, 0, 0, 0, 211, 0, 0, 0, 245, 0, 0, 0, 92, 0, 0, 0, 26, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 88, 0, 0, 0, 214, 0, 0, 0, 156, 0, 0, 0, 247, 0, 0, 0, 162, 0, 0, 0, 222, 0, 0, 0, 249, 0, 0, 0, 222, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 106, 9, 230, 103, 243, 188, 201, -8, 187, 103, 174, 133, 132, 202, 167, 59, 60, 110, 243, 114, 254, 148, 248, 43, 165, 79, 245, 58, 95, 29, 54, 241, 81, 14, 82, 127, 173, 230, 130, 209, 155, 5, 104, 140, 43, 62, 108, 31, 31, 131, 217, 171, 251, 65, 189, 107, 91, 224, 205, 25, 19, 126, 33, 121, 106, 9, 230, 103, 187, 103, 174, 133, 60, 110, 243, 114, 165, 79, 245, 58, 81, 14, 82, 127, 155, 5, 104, 140, 31, 131, 217, 171, 91, 224, 205, 25, 106, 9, 230, 103, 243, 188, 201, 8, 187, 103, 174, 133, 132, 202, 167, 59, 60, 110, 243, 114, -254, 148, 248, 43, 165, 79, 245, 58, 95, 29, 54, 241, 81, 14, 82, 127, 173, 230, 130, 209, 155, 5, 104, 140, 43, 62, 108, 31, 31, 131, 217, 171, 251, 65, 189, 107, 91, 224, 205, 25, 19, 126, 33, 121, 106, 9, 230, 103, 187, 103, 174, 133, 60, 110, 243, 114, 165, 79, 245, 58, 81, 14, 82, 127, 155, 5, 104, 140, 31, 131, 217, 171, 91, 224, 205, 25, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -63, 117, 110, 107, 110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 117, 110, 107, 110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 176, 0, 0, 0, 160, 0, 0, 0, 14, 0, 0, 0, 74, 0, 0, 0, 39, 0, 0, 0, 27, 0, 0, 0, 238, 0, 0, 0, 196, 0, 0, 0, 120, 0, 0, 0, 228, 0, 0, 0, 47, 0, 0, 0, 173, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 67, 0, 0, 0, 47, 0, 0, 0, 167, 0, 0, 0, 215, 0, 0, 0, 251, 0, 0, 0, -61, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 43, 0, 0, 0, 11, 0, 0, 0, 223, 0, 0, 0, 193, 0, 0, 0, 79, 0, 0, 0, 128, 0, 0, 0, 36, 0, 0, 0, 131, 0, 0, 0, 43, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 0, 0, 0, 120, 0, 0, 0, 89, 0, 0, 0, 19, 0, 0, 0, 202, 0, 0, 0, 77, 0, 0, 0, 235, 0, 0, 0, 117, 0, 0, 0, 171, 0, 0, 0, 216, 0, 0, 0, -65, 0, 0, 0, 65, 0, 0, 0, 77, 0, 0, 0, 10, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 232, 0, 0, 0, 121, 0, 0, 0, 119, 0, 0, 0, 121, 0, 0, 0, 64, 0, 0, 0, 199, 0, 0, 0, 140, 0, 0, 0, 115, 0, 0, 0, 254, 0, 0, 0, 111, 0, 0, 0, 43, 0, 0, 0, 238, 0, 0, 0, 108, 0, 0, 0, 3, 0, 0, 0, 82, 0, 0, 0, 89, 0, 0, 0, 241, 0, 0, 0, 178, 0, 0, 0, 38, 0, 0, 0, 148, 0, 0, 0, 155, 0, 0, 0, 214, 0, 0, 0, 235, 0, 0, 0, 86, 0, 0, 0, 177, 0, 0, 0, 131, 0, 0, 0, 130, 0, 0, 0, 154, 0, 0, 0, 20, 0, 0, 0, 224, 0, 0, 0, -0, 0, 0, 0, 48, 0, 0, 0, 209, 0, 0, 0, 243, 0, 0, 0, 238, 0, 0, 0, 242, 0, 0, 0, 128, 0, 0, 0, 142, 0, 0, 0, 25, 0, 0, 0, 231, 0, 0, 0, 252, 0, 0, 0, 223, 0, 0, 0, 86, 0, 0, 0, 220, 0, 0, 0, 217, 0, 0, 0, 6, 0, 0, 0, 36, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 26, 213, 37, 143, -96, 45, 86, 201, 178, 167, 37, 149, 96, 199, 44, 105, 92, 220, 214, 253, 49, 226, 164, 192, 254, 83, 110, 205, 211, 54, 105, 33, 163, 221, 183, 165, 179, 138, 222, 109, 245, 82, 81, 119, 128, 159, 240, 32, 125, 227, 171, 100, 142, 78, 234, 102, 101, 118, 139, 215, 15, 95, 135, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 213, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 96, 0, 0, 0, 45, 0, 0, 0, 86, 0, 0, 0, 201, 0, 0, 0, 178, 0, 0, 0, 167, 0, 0, 0, 37, 0, 0, 0, 149, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 92, 0, 0, 0, 220, 0, 0, 0, 214, 0, 0, 0, 253, 0, 0, 0, 49, 0, 0, 0, 226, 0, 0, 0, 164, 0, 0, 0, 192, 0, 0, 0, 254, 0, 0, 0, 83, 0, 0, 0, 110, 0, 0, 0, 205, 0, 0, 0, 211, 0, 0, 0, 54, 0, 0, 0, 105, 0, 0, 0, 33, 0, 0, 0, 88, 0, 0, 0, 102, -0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 14, 0, 0, 0, 206, 0, 0, 0, 67, 0, 0, 0, 40, 0, 0, 0, 78, 0, 0, 0, 161, 0, -0, 0, 197, 0, 0, 0, 131, 0, 0, 0, 95, 0, 0, 0, 164, 0, 0, 0, 215, 0, 0, 0, 21, 0, 0, 0, 69, 0, 0, 0, 142, 0, 0, 0, 13, 0, 0, 0, 8, 0, 0, 0, 172, 0, 0, 0, 231, 0, 0, 0, 51, 0, 0, 0, 24, 0, 0, 0, 125, 0, 0, 0, 59, 0, 0, 0, 4, 0, 0, 0, 61, 0, 0, 0, 108, 0, 0, 0, 4, 0, 0, 0, 90, 0, 0, 0, 159, 0, 0, 0, 76, 0, 0, 0, 56, 0, 0, 0, 171, 0, 0, 0, 54, 0, 0, 0, 201, 0, 0, 0, 163, 0, 0, 0, 248, 0, 0, 0, 106, 0, 0, 0, 174, 0, 0, 0, 70, 0, 0, 0, 95, 0, 0, 0, 14, 0, 0, 0, 86, 0, 0, 0, 81, 0, 0, 0, 56, 0, 0, 0, 100, -0, 0, 0, 81, 0, 0, 0, 15, 0, 0, 0, 57, 0, 0, 0, 151, 0, 0, 0, 86, 0, 0, 0, 31, 0, 0, 0, 162, 0, 0, 0, 201, 0, 0, 0, 232, 0, 0, 0, 94, 0, 0, 0, 162, 0, 0, 0, 29, 0, 0, 0, 194, 0, 0, 0, 41, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0, 243, 0, 0, 0, 205, 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0, 226, 0, 0, 0, 248, 0, 0, 0, 211, 0, 0, 0, 95, 0, 0, 0, 72, 0, 0, 0, 98, 0, 0, 0, 172, 0, 0, 0, 134, 0, 0, 0, 72, 0, 0, 0, 98, 0, 0, 0, 129, 0, 0, 0, 25, 0, 0, 0, 152, 0, 0, 0, 67, 0, 0, 0, 99, 0, 0, 0, 58, 0, 0, -0, 200, 0, 0, 0, 218, 0, 0, 0, 62, 0, 0, 0, 116, 0, 0, 0, 174, 0, 0, 0, 244, 0, 0, 0, 31, 0, 0, 0, 73, 0, 0, 0, 143, 0, 0, 0, 146, 0, 0, 0, 34, 0, 0, 0, 74, 0, 0, 0, 156, 0, 0, 0, 174, 0, 0, 0, 103, 0, 0, 0, 212, 0, 0, 0, 180, 0, 0, 0, 245, 0, 0, 0, 120, 0, 0, 0, 72, 0, 0, 0, 104, 0, 0, 0, 195, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 103, 0, 0, 0, 23, 0, 0, 0, 236, 0, 0, 0, 22, 0, 0, 0, 159, 0, 0, 0, 247, 0, 0, 0, 158, 0, 0, 0, 38, 0, 0, 0, 96, 0, 0, 0, 142, 0, 0, 0, 161, 0, 0, -0, 38, 0, 0, 0, 161, 0, 0, 0, 171, 0, 0, 0, 105, 0, 0, 0, 238, 0, 0, 0, 119, 0, 0, 0, 209, 0, 0, 0, 177, 0, 0, 0, 103, 0, 0, 0, 18, 0, 0, 0, 112, 0, 0, 0, 248, 0, 0, 0, 201, 0, 0, 0, 196, 0, 0, 0, 87, 0, 0, 0, 166, 0, 0, 0, 58, 0, 0, 0, 73, 0, 0, 0, 71, 0, 0, 0, 21, 0, 0, 0, 206, 0, 0, 0, 147, 0, 0, 0, 193, 0, 0, 0, 158, 0, 0, 0, 115, 0, 0, 0, 26, 0, 0, 0, 249, 0, 0, 0, 32, 0, 0, 0, 53, 0, 0, 0, 122, 0, 0, 0, 184, 0, 0, 0, 212, 0, 0, 0, 37, 0, 0, 0, 131, 0, 0, 0, 70, 0, 0, 0, 241, 0, 0, 0, 207, 0, -0, 0, 86, 0, 0, 0, 219, 0, 0, 0, 168, 0, 0, 0, 61, 0, 0, 0, 32, 0, 0, 0, 47, 0, 0, 0, 17, 0, 0, 0, 50, 0, 0, 0, 202, 0, 0, 0, 97, 0, 0, 0, 171, 0, 0, 0, 56, 0, 0, 0, 223, 0, 0, 0, 240, 0, 0, 0, 15, 0, 0, 0, 47, 0, 0, 0, 234, 0, 0, 0, 50, 0, 0, 0, 40, 0, 0, 0, 242, 0, 0, 0, 76, 0, 0, 0, 108, 0, 0, 0, 113, 0, 0, 0, 213, 0, 0, 0, 128, 0, 0, 0, 133, 0, 0, 0, 184, 0, 0, 0, 14, 0, 0, 0, 71, 0, 0, 0, 225, 0, 0, 0, 149, 0, 0, 0, 21, 0, 0, 0, 203, 0, 0, 0, 39, 0, 0, 0, 232, 0, 0, 0, 208, 0, 0, 0, 71, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 132, 0, 0, 0, 165, 0, 0, 0, 8, 0, 0, 0, 188, 0, 0, 0, 253, 0, 0, 0, 135, 0, 0, 0, 59, 0, 0, 0, 153, 0, 0, 0, 139, 0, 0, 0, 105, 0, 0, 0, 128, 0, 0, 0, 123, 0, 0, 0, 198, 0, 0, 0, 58, 0, 0, 0, 235, 0, 0, 0, 147, 0, 0, -0, 207, 0, 0, 0, 78, 0, 0, 0, 248, 0, 0, 0, 92, 0, 0, 0, 45, 0, 0, 0, 134, 0, 0, 0, 66, 0, 0, 0, 182, 0, 0, 0, 113, 0, 0, 0, 215, 0, 0, 0, 151, 0, 0, 0, 95, 0, 0, 0, 225, 0, 0, 0, 66, 0, 0, 0, 103, 0, 0, 0, 180, 0, 0, 0, 185, 0, 0, 0, 55, 0, 0, 0, 252, 0, 0, 0, 169, 0, 0, 0, 91, 0, 0, 0, 47, 0, 0, 0, 30, 0, 0, 0, 147, 0, 0, 0, 228, 0, 0, 0, 30, 0, 0, 0, 98, 0, 0, 0, 252, 0, 0, 0, 60, 0, 0, 0, 120, 0, 0, 0, 129, 0, 0, 0, 143, 0, 0, 0, 243, 0, 0, 0, 138, 0, 0, 0, 102, 0, 0, 0, 9, 0, 0, 0, 111, 0, 0, -0, 173, 0, 0, 0, 110, 0, 0, 0, 121, 0, 0, 0, 115, 0, 0, 0, 229, 0, 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 211, 0, 0, 0, 33, 0, 0, 0, 248, 0, 0, 0, 249, 0, 0, 0, 40, 0, 0, 0, 108, 0, 0, 0, 109, 0, 0, 0, 89, 0, 0, 0, 178, 0, 0, 0, 89, 0, 0, 0, 116, 0, 0, 0, 35, 0, 0, 0, 191, 0, 0, 0, 231, 0, 0, 0, 51, 0, 0, 0, 141, 0, 0, 0, 87, 0, 0, 0, 9, 0, 0, 0, 145, 0, 0, 0, 156, 0, 0, 0, 36, 0, 0, 0, 8, 0, 0, 0, 21, 0, 0, 0, 43, 0, 0, 0, 226, 0, 0, 0, 184, 0, 0, 0, 238, 0, 0, 0, 58, 0, 0, 0, 229, 0, 0, 0, -39, 0, 0, 0, 6, 0, 0, 0, 134, 0, 0, 0, 164, 0, 0, 0, 35, 0, 0, 0, 235, 0, 0, 0, 39, 0, 0, 0, 103, 0, 0, 0, 193, 0, 0, 0, 55, 0, 0, 0, 171, 0, 0, 0, 122, 0, 0, 0, 216, 0, 0, 0, 39, 0, 0, 0, 156, 0, 0, 0, 7, 0, 0, 0, 142, 0, 0, 0, 255, 0, 0, 0, 17, 0, 0, 0, 106, 0, 0, 0, 176, 0, 0, 0, 120, 0, 0, 0, 110, 0, 0, 0, 173, 0, 0, 0, 58, 0, 0, 0, 46, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 159, 0, 0, 0, 114, 0, 0, 0, 195, 0, 0, 0, 127, 0, 0, 0, 130, 0, 0, 0, 242, 0, 0, 0, 150, 0, 0, 0, 150, 0, 0, 0, 112, 0, 0, -0, 129, 0, 0, 0, 107, 0, 0, 0, 136, 0, 0, 0, 232, 0, 0, 0, 30, 0, 0, 0, 199, 0, 0, 0, 119, 0, 0, 0, 150, 0, 0, 0, 14, 0, 0, 0, 161, 0, 0, 0, 169, 0, 0, 0, 82, 0, 0, 0, 224, 0, 0, 0, 216, 0, 0, 0, 14, 0, 0, 0, 97, 0, 0, 0, 158, 0, 0, 0, 121, 0, 0, 0, 45, 0, 0, 0, 149, 0, 0, 0, 156, 0, 0, 0, 141, 0, 0, 0, 150, 0, 0, 0, 224, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 93, 0, 0, 0, 135, 0, 0, 0, 40, 0, 0, 0, 95, 0, 0, 0, 152, 0, 0, 0, 112, 0, 0, 0, 241, 0, 0, 0, 121, 0, 0, 0, 123, 0, 0, 0, 237, 0, 0, 0, 79, 0, -0, 0, 68, 0, 0, 0, 178, 0, 0, 0, 231, 0, 0, 0, 8, 0, 0, 0, 13, 0, 0, 0, 194, 0, 0, 0, 8, 0, 0, 0, 18, 0, 0, 0, 210, 0, 0, 0, 159, 0, 0, 0, 223, 0, 0, 0, 205, 0, 0, 0, 147, 0, 0, 0, 32, 0, 0, 0, 138, 0, 0, 0, 207, 0, 0, 0, 51, 0, 0, 0, 202, 0, 0, 0, 109, 0, 0, 0, 137, 0, 0, 0, 185, 0, 0, 0, 119, 0, 0, 0, 200, 0, 0, 0, 147, 0, 0, 0, 27, 0, 0, 0, 78, 0, 0, 0, 96, 0, 0, 0, 38, 0, 0, 0, 79, 0, 0, 0, 126, 0, 0, 0, 151, 0, 0, 0, 246, 0, 0, 0, 64, 0, 0, 0, 221, 0, 0, 0, 79, 0, 0, 0, 252, 0, 0, 0, 82, 0, -0, 0, 120, 0, 0, 0, 249, 0, 0, 0, 144, 0, 0, 0, 49, 0, 0, 0, 3, 0, 0, 0, 230, 0, 0, 0, 125, 0, 0, 0, 86, 0, 0, 0, 57, 0, 0, 0, 11, 0, 0, 0, 29, 0, 0, 0, 86, 0, 0, 0, 130, 0, 0, 0, 133, 0, 0, 0, 249, 0, 0, 0, 26, 0, 0, 0, 66, 0, 0, 0, 23, 0, 0, 0, 105, 0, 0, 0, 108, 0, 0, 0, 207, 0, 0, 0, 57, 0, 0, 0, 105, 0, 0, 0, 210, 0, 0, 0, 6, 0, 0, 0, 58, 0, 0, 0, 79, 0, 0, 0, 57, 0, 0, 0, 45, 0, 0, 0, 249, 0, 0, 0, 56, 0, 0, 0, 64, 0, 0, 0, 140, 0, 0, 0, 76, 0, 0, 0, 231, 0, 0, 0, 5, 0, 0, 0, 18, 0, 0, 0, 180, -0, 0, 0, 120, 0, 0, 0, 139, 0, 0, 0, 248, 0, 0, 0, 192, 0, 0, 0, 236, 0, 0, 0, 147, 0, 0, 0, 222, 0, 0, 0, 122, 0, 0, 0, 107, 0, 0, 0, 206, 0, 0, 0, 44, 0, 0, 0, 225, 0, 0, 0, 14, 0, 0, 0, 169, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, -0, 0, 164, 0, 0, 0, 60, 0, 0, 0, 176, 0, 0, 0, 15, 0, 0, 0, 122, 0, 0, 0, 81, 0, 0, 0, 241, 0, 0, 0, 120, 0, 0, 0, 214, 0, 0, 0, 217, 0, 0, 0, 106, 0, 0, 0, 253, 0, 0, 0, 70, 0, 0, 0, 232, 0, 0, 0, 184, 0, 0, 0, 168, 0, 0, 0, 121, 0, 0, 0, 29, 0, 0, 0, 135, 0, 0, 0, 249, 0, 0, 0, 144, 0, 0, 0, 242, 0, 0, 0, 156, 0, 0, 0, 19, 0, 0, 0, 41, 0, 0, 0, 248, 0, 0, 0, 11, 0, 0, 0, 32, 0, 0, 0, 100, 0, 0, 0, 250, 0, 0, 0, 5, 0, 0, 0, 38, 0, 0, 0, 9, 0, 0, 0, 218, 0, 0, 0, 23, 0, 0, 0, 175, 0, 0, 0, 149, 0, -0, 0, 214, 0, 0, 0, 251, 0, 0, 0, 106, 0, 0, 0, 25, 0, 0, 0, 13, 0, 0, 0, 110, 0, 0, 0, 94, 0, 0, 0, 18, 0, 0, 0, 241, 0, 0, 0, 153, 0, 0, 0, 76, 0, 0, 0, 170, 0, 0, 0, 168, 0, 0, 0, 111, 0, 0, 0, 121, 0, 0, 0, 134, 0, 0, 0, 244, 0, 0, 0, 114, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 249, 0, 0, 0, 234, 0, 0, 0, 158, 0, 0, 0, 25, 0, 0, 0, 61, 0, 0, 0, 135, 0, 0, 0, 221, 0, 0, 0, 207, 0, 0, 0, 240, 0, 0, 0, 91, 0, 0, 0, 73, 0, 0, 0, 162, 0, 0, 0, 93, 0, 0, 0, 64, 0, 0, 0, 122, 0, 0, 0, 35, 0, -0, 0, 38, 0, 0, 0, 164, 0, 0, 0, 122, 0, 0, 0, 131, 0, 0, 0, 138, 0, 0, 0, 183, 0, 0, 0, 139, 0, 0, 0, 210, 0, 0, 0, 26, 0, 0, 0, 191, 0, 0, 0, 234, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, 8, 0, 0, 0, 95, 0, 0, 0, 123, 0, 0, 0, 169, 0, 0, 0, 177, 0, 0, 0, 190, 0, 0, 0, 157, 0, 0, 0, 55, 0, 0, 0, 252, 0, 0, 0, 134, 0, 0, 0, 75, 0, 0, 0, 8, 0, 0, 0, 238, 0, 0, 0, 231, 0, 0, 0, 160, 0, 0, 0, 253, 0, 0, 0, 33, 0, 0, 0, 69, 0, 0, 0, 9, 0, 0, 0, 52, 0, 0, 0, 193, 0, 0, 0, 97, 0, 0, 0, 50, 0, 0, 0, 35, 0, 0, -0, 252, 0, 0, 0, 155, 0, 0, 0, 85, 0, 0, 0, 72, 0, 0, 0, 83, 0, 0, 0, 153, 0, 0, 0, 247, 0, 0, 0, 99, 0, 0, 0, 208, 0, 0, 0, 153, 0, 0, 0, 206, 0, 0, 0, 1, 0, 0, 0, 224, 0, 0, 0, 159, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 71, 0, 0, 0, 252, 0, 0, 0, 171, 0, 0, 0, 90, 0, 0, 0, 23, 0, 0, 0, 240, 0, 0, 0, 133, 0, 0, 0, 86, 0, 0, 0, 58, 0, 0, 0, 48, 0, 0, 0, 134, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 75, 0, 0, 0, 142, 0, 0, 0, 68, 0, 0, 0, 116, 0, 0, 0, 58, 0, 0, 0, 110, 0, 0, 0, 2, 0, 0, 0, 241, 0, 0, 0, -50, 0, 0, 0, 143, 0, 0, 0, 159, 0, 0, 0, 63, 0, 0, 0, 8, 0, 0, 0, 53, 0, 0, 0, 233, 0, 0, 0, 202, 0, 0, 0, 22, 0, 0, 0, 95, 0, 0, 0, 110, 0, 0, 0, 28, 0, 0, 0, 89, 0, 0, 0, 28, 0, 0, 0, 101, 0, 0, 0, 93, 0, 0, 0, 52, 0, 0, 0, 164, 0, 0, 0, 9, 0, 0, 0, 205, 0, 0, 0, 19, 0, 0, 0, 156, 0, 0, 0, 112, 0, 0, 0, 125, 0, 0, 0, 177, 0, 0, 0, 42, 0, 0, 0, 197, 0, 0, 0, 136, 0, 0, 0, 175, 0, 0, 0, 11, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 159, 0, 0, 0, 52, 0, 0, 0, 141, 0, 0, 0, 214, 0, 0, 0, 183, 0, 0, 0, 127, -0, 0, 0, 234, 0, 0, 0, 120, 0, 0, 0, 101, 0, 0, 0, 141, 0, 0, 0, 119, 0, 0, 0, 86, 0, 0, 0, 165, 0, 0, 0, 194, 0, 0, 0, 12, 0, 0, 0, 221, 0, 0, 0, 188, 0, 0, 0, 184, 0, 0, 0, 32, 0, 0, 0, 109, 0, 0, 0, 87, 0, 0, 0, 97, 0, 0, 0, 181, 0, 0, 0, 251, 0, 0, 0, 120, 0, 0, 0, 181, 0, 0, 0, 212, 0, 0, 0, 73, 0, 0, 0, 84, 0, 0, 0, 144, 0, 0, 0, 38, 0, 0, 0, 193, 0, 0, 0, 203, 0, 0, 0, 233, 0, 0, 0, 230, 0, 0, 0, 191, 0, 0, 0, 236, 0, 0, 0, 29, 0, 0, 0, 78, 0, 0, 0, 237, 0, 0, 0, 7, 0, 0, 0, 126, 0, 0, 0, -94, 0, 0, 0, 199, 0, 0, 0, 246, 0, 0, 0, 108, 0, 0, 0, 86, 0, 0, 0, 49, 0, 0, 0, 32, 0, 0, 0, 20, 0, 0, 0, 14, 0, 0, 0, 168, 0, 0, 0, 217, 0, 0, 0, 39, 0, 0, 0, 193, 0, 0, 0, 154, 0, 0, 0, 61, 0, 0, 0, 27, 0, 0, 0, 125, 0, 0, 0, 14, 0, 0, 0, 38, 0, 0, 0, 211, 0, 0, 0, 129, 0, 0, 0, 170, 0, 0, 0, 235, 0, 0, 0, 245, 0, 0, 0, 107, 0, 0, 0, 121, 0, 0, 0, 2, 0, 0, 0, 241, 0, 0, 0, 81, 0, 0, 0, 92, 0, 0, 0, 117, 0, 0, 0, 85, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 52, 0, 0, 0, 205, 0, 0, 0, 130, 0, 0, 0, 60, 0, 0, 0, 51, 0, 0, 0, 9, 0, 0, 0, 84, 0, 0, 0, 210, 0, 0, 0, 97, 0, 0, 0, 57, 0, 0, 0, 48, 0, 0, 0, 155, 0, 0, 0, 253, 0, 0, 0, 239, 0, 0, 0, 33, 0, 0, 0, 38, 0, 0, 0, 212, 0, 0, 0, 112, 0, 0, 0, 250, 0, 0, 0, 238, 0, 0, 0, 249, 0, 0, -0, 49, 0, 0, 0, 51, 0, 0, 0, 115, 0, 0, 0, 132, 0, 0, 0, 208, 0, 0, 0, 179, 0, 0, 0, 129, 0, 0, 0, 191, 0, 0, 0, 236, 0, 0, 0, 46, 0, 0, 0, 232, 0, 0, 0, 147, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 247, 0, 0, 0, 156, 0, 0, 0, 184, 0, 0, 0, 116, 0, 0, 0, 224, 0, 0, 0, 230, 0, 0, 0, 73, 0, 0, 0, 72, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 72, 0, 0, 0, 182, 0, 0, 0, 25, 0, 0, 0, 161, 0, 0, 0, 64, 0, 0, 0, 183, 0, 0, 0, 217, 0, 0, 0, 50, 0, 0, 0, 65, 0, 0, 0, 124, 0, 0, 0, 130, 0, 0, 0, 55, 0, 0, -0, 161, 0, 0, 0, 45, 0, 0, 0, 220, 0, 0, 0, 210, 0, 0, 0, 84, 0, 0, 0, 104, 0, 0, 0, 43, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 213, 0, 0, 0, 199, 0, 0, 0, 81, 0, 0, 0, 145, 0, 0, 0, 29, 0, 0, 0, 225, 0, 0, 0, 42, 0, 0, 0, 75, 0, 0, 0, 196, 0, 0, 0, 71, 0, 0, 0, 241, 0, 0, 0, 188, 0, 0, 0, 122, 0, 0, 0, 179, 0, 0, 0, 203, 0, 0, 0, 200, 0, 0, 0, 182, 0, 0, 0, 124, 0, 0, 0, 172, 0, 0, 0, 144, 0, 0, 0, 5, 0, 0, 0, 253, 0, 0, 0, 243, 0, 0, 0, 249, 0, 0, 0, 82, 0, 0, 0, 58, 0, 0, 0, 17, 0, 0, 0, 107, 0, 0, -0, 61, 0, 0, 0, 193, 0, 0, 0, 39, 0, 0, 0, 243, 0, 0, 0, 89, 0, 0, 0, 67, 0, 0, 0, 149, 0, 0, 0, 144, 0, 0, 0, 197, 0, 0, 0, 150, 0, 0, 0, 121, 0, 0, 0, 245, 0, 0, 0, 244, 0, 0, 0, 149, 0, 0, 0, 101, 0, 0, 0, 41, 0, 0, 0, 6, 0, 0, 0, 156, 0, 0, 0, 81, 0, 0, 0, 5, 0, 0, 0, 24, 0, 0, 0, 218, 0, 0, 0, 184, 0, 0, 0, 46, 0, 0, 0, 121, 0, 0, 0, 126, 0, 0, 0, 105, 0, 0, 0, 89, 0, 0, 0, 113, 0, 0, 0, 1, 0, 0, 0, 235, 0, 0, 0, 26, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, 0, 73, 0, 0, 0, 182, 0, 0, 0, 138, 0, 0, 0, -60, 0, 0, 0, 234, 0, 0, 0, 47, 0, 0, 0, 52, 0, 0, 0, 32, 0, 0, 0, 20, 0, 0, 0, 195, 0, 0, 0, 170, 0, 0, 0, 214, 0, 0, 0, 175, 0, 0, 0, 44, 0, 0, 0, 62, 0, 0, 0, 189, 0, 0, 0, 101, 0, 0, 0, 32, 0, 0, 0, 226, 0, 0, 0, 77, 0, 0, 0, 75, 0, 0, 0, 59, 0, 0, 0, 235, 0, 0, 0, 159, 0, 0, 0, 74, 0, 0, 0, 195, 0, 0, 0, 173, 0, 0, 0, 164, 0, 0, 0, 59, 0, 0, 0, 96, 0, 0, 0, 188, 0, 0, 0, 88, 0, 0, 0, 230, 0, 0, 0, 192, 0, 0, 0, 149, 0, 0, 0, 42, 0, 0, 0, 42, 0, 0, 0, 129, 0, 0, 0, 154, 0, 0, 0, 122, 0, 0, 0, -243, 0, 0, 0, 210, 0, 0, 0, 6, 0, 0, 0, 190, 0, 0, 0, 72, 0, 0, 0, 188, 0, 0, 0, 12, 0, 0, 0, 197, 0, 0, 0, 70, 0, 0, 0, 224, 0, 0, 0, 106, 0, 0, 0, 212, 0, 0, 0, 172, 0, 0, 0, 15, 0, 0, 0, 217, 0, 0, 0, 204, 0, 0, 0, 130, 0, 0, 0, 52, 0, 0, 0, 44, 0, 0, 0, 175, 0, 0, 0, 219, 0, 0, 0, 31, 0, 0, 0, 247, 0, 0, 0, 23, 0, 0, 0, 19, 0, 0, 0, 189, 0, 0, 0, 251, 0, 0, 0, 188, 0, 0, 0, 210, 0, 0, 0, 236, 0, 0, 0, 69, 0, 0, 0, 179, 0, 0, 0, 21, 0, 0, 0, 49, 0, 0, 0, 233, 0, 0, 0, 175, 0, 0, 0, 130, 0, 0, -0, 132, 0, 0, 0, 61, 0, 0, 0, 40, 0, 0, 0, 198, 0, 0, 0, 252, 0, 0, 0, 17, 0, 0, 0, 245, 0, 0, 0, 65, 0, 0, 0, 181, 0, 0, 0, 139, 0, 0, 0, 211, 0, 0, 0, 18, 0, 0, 0, 118, 0, 0, 0, 82, 0, 0, 0, 231, 0, 0, 0, 26, 0, 0, 0, 60, 0, 0, 0, 78, 0, 0, 0, 54, 0, 0, 0, 17, 0, 0, 0, 7, 0, 0, 0, 162, 0, 0, 0, 21, 0, 0, 0, 32, 0, 0, 0, 81, 0, 0, 0, 196, 0, 0, 0, 42, 0, 0, 0, 195, 0, 0, 0, 98, 0, 0, 0, 139, 0, 0, 0, 94, 0, 0, 0, 127, 0, 0, 0, 166, 0, 0, 0, 15, 0, 0, 0, 249, 0, 0, 0, 69, 0, 0, 0, 133, 0, 0, 0, 108, -0, 0, 0, 17, 0, 0, 0, 134, 0, 0, 0, 183, 0, 0, 0, 126, 0, 0, 0, 229, 0, 0, 0, 215, 0, 0, 0, 249, 0, 0, 0, 195, 0, 0, 0, 145, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 214, 0, 0, 0, 222, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, -0, 185, 0, 0, 0, 2, 0, 0, 0, 89, 0, 0, 0, 203, 0, 0, 0, 38, 0, 0, 0, 196, 0, 0, 0, 186, 0, 0, 0, 153, 0, 0, 0, 177, 0, 0, 0, 151, 0, 0, 0, 47, 0, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 38, 0, 0, 0, 79, 0, 0, 0, 82, 0, 0, 0, 235, 0, 0, 0, 71, 0, 0, 0, 27, 0, 0, 0, 137, 0, 0, 0, 139, 0, 0, 0, 36, 0, 0, 0, 192, 0, 0, 0, 19, 0, 0, 0, 125, 0, 0, 0, 213, 0, 0, 0, 32, 0, 0, 0, 91, 0, 0, 0, 128, 0, 0, 0, 166, 0, 0, 0, 128, 0, 0, 0, 32, 0, 0, 0, 149, 0, 0, 0, 195, 0, 0, 0, 233, 0, 0, 0, 159, 0, 0, -0, 142, 0, 0, 0, 135, 0, 0, 0, 158, 0, 0, 0, 30, 0, 0, 0, 158, 0, 0, 0, 122, 0, 0, 0, 199, 0, 0, 0, 204, 0, 0, 0, 117, 0, 0, 0, 108, 0, 0, 0, 165, 0, 0, 0, 241, 0, 0, 0, 145, 0, 0, 0, 26, 0, 0, 0, 168, 0, 0, 0, 1, 0, 0, 0, 44, 0, 0, 0, 171, 0, 0, 0, 118, 0, 0, 0, 169, 0, 0, 0, 89, 0, 0, 0, 222, 0, 0, 0, 201, 0, 0, 0, 177, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 170, 0, 0, 0, 53, 0, 0, 0, 20, 0, 0, 0, 106, 0, 0, 0, 212, 0, 0, 0, 181, 0, 0, 0, 52, 0, 0, 0, 130, 0, 0, 0, 113, 0, 0, 0, 210, 0, -0, 0, 74, 0, 0, 0, 93, 0, 0, 0, 154, 0, 0, 0, 31, 0, 0, 0, 83, 0, 0, 0, 38, 0, 0, 0, 60, 0, 0, 0, 229, 0, 0, 0, 142, 0, 0, 0, 141, 0, 0, 0, 51, 0, 0, 0, 127, 0, 0, 0, 255, 0, 0, 0, 169, 0, 0, 0, 213, 0, 0, 0, 23, 0, 0, 0, 137, 0, 0, 0, 175, 0, 0, 0, 246, 0, 0, 0, 164, 0, 0, 0, 100, 0, 0, 0, 213, 0, 0, 0, 16, 0, 0, 0, 224, 0, 0, 0, 29, 0, 0, 0, 173, 0, 0, 0, 239, 0, 0, 0, 68, 0, 0, 0, 189, 0, 0, 0, 218, 0, 0, 0, 131, 0, 0, 0, 172, 0, 0, 0, 122, 0, 0, 0, 168, 0, 0, 0, 240, 0, 0, 0, 28, 0, 0, 0, 7, -0, 0, 0, 249, 0, 0, 0, 195, 0, 0, 0, 67, 0, 0, 0, 108, 0, 0, 0, 63, 0, 0, 0, 183, 0, 0, 0, 211, 0, 0, 0, 135, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 115, 0, 0, 0, 100, 0, 0, 0, 29, 0, 0, 0, 73, 0, 0, 0, 19, 0, 0, 0, 47, 0, 0, 0, 113, 0, 0, 0, 236, 0, 0, 0, 105, 0, 0, 0, 135, 0, 0, 0, 208, 0, 0, 0, 66, 0, 0, 0, 238, 0, 0, 0, 19, 0, 0, 0, 236, 0, 0, 0, 227, 0, 0, 0, 237, 0, 0, 0, 86, 0, 0, 0, 123, 0, 0, 0, 191, 0, 0, 0, 189, 0, 0, 0, 140, 0, 0, 0, 47, 0, 0, 0, 125, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 40, -0, 0, 0, 236, 0, 0, 0, 142, 0, 0, 0, 118, 0, 0, 0, 47, 0, 0, 0, 111, 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 245, 0, 0, 0, 95, 0, 0, 0, 77, 0, 0, 0, 21, 0, 0, 0, 239, 0, 0, 0, 252, 0, 0, 0, 78, 0, 0, 0, 87, 0, 0, 0, 3, 0, 0, 0, 54, 0, 0, 0, 137, 0, 0, 0, 240, 0, 0, 0, 235, 0, 0, 0, 91, 0, 0, 0, 145, 0, 0, 0, 214, 0, 0, 0, 226, 0, 0, 0, 202, 0, 0, 0, 1, 0, 0, 0, 165, 0, 0, 0, 238, 0, 0, 0, 82, 0, 0, 0, 236, 0, 0, 0, 160, 0, 0, 0, 60, 0, 0, 0, 143, 0, 0, 0, 51, 0, 0, 0, 144, 0, 0, 0, 90, 0, 0, 0, 148, 0, -0, 0, 114, 0, 0, 0, 138, 0, 0, 0, 75, 0, 0, 0, 231, 0, 0, 0, 56, 0, 0, 0, 188, 0, 0, 0, 218, 0, 0, 0, 194, 0, 0, 0, 176, 0, 0, 0, 133, 0, 0, 0, 225, 0, 0, 0, 74, 0, 0, 0, 254, 0, 0, 0, 45, 0, 0, 0, 68, 0, 0, 0, 132, 0, 0, 0, 203, 0, 0, 0, 32, 0, 0, 0, 107, 0, 0, 0, 45, 0, 0, 0, 191, 0, 0, 0, 17, 0, 0, 0, 156, 0, 0, 0, 215, 0, 0, 0, 190, 0, 0, 0, 211, 0, 0, 0, 62, 0, 0, 0, 95, 0, 0, 0, 191, 0, 0, 0, 104, 0, 0, 0, 188, 0, 0, 0, 168, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 137, 0, 0, 0, 40, 0, 0, 0, 34, 0, -0, 0, 106, 0, 0, 0, 120, 0, 0, 0, 170, 0, 0, 0, 41, 0, 0, 0, 3, 0, 0, 0, 200, 0, 0, 0, 116, 0, 0, 0, 149, 0, 0, 0, 3, 0, 0, 0, 62, 0, 0, 0, 220, 0, 0, 0, 189, 0, 0, 0, 7, 0, 0, 0, 19, 0, 0, 0, 168, 0, 0, 0, 162, 0, 0, 0, 32, 0, 0, 0, 45, 0, 0, 0, 179, 0, 0, 0, 24, 0, 0, 0, 112, 0, 0, 0, 66, 0, 0, 0, 253, 0, 0, 0, 122, 0, 0, 0, 196, 0, 0, 0, 215, 0, 0, 0, 73, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 50, 0, 0, 0, 43, 0, 0, 0, 92, 0, 0, 0, 147, 0, 0, 0, 84, 0, 0, 0, 50, 0, 0, 0, 232, 0, 0, 0, 87, 0, 0, 0, 84, 0, 0, 0, 26, 0, 0, 0, 139, 0, 0, 0, 51, 0, 0, 0, 96, 0, 0, 0, 101, 0, 0, 0, 211, 0, 0, 0, 103, 0, 0, 0, 164, 0, 0, 0, 193, 0, 0, 0, 38, 0, 0, 0, 196, 0, 0, 0, 164, 0, 0, 0, 52, 0, 0, 0, 31, 0, 0, 0, 155, 0, 0, 0, 167, -0, 0, 0, 169, 0, 0, 0, 244, 0, 0, 0, 217, 0, 0, 0, 79, 0, 0, 0, 91, 0, 0, 0, 70, 0, 0, 0, 141, 0, 0, 0, 176, 0, 0, 0, 51, 0, 0, 0, 84, 0, 0, 0, 38, 0, 0, 0, 91, 0, 0, 0, 104, 0, 0, 0, 223, 0, 0, 0, 187, 0, 0, 0, 197, 0, 0, 0, 236, 0, 0, 0, 194, 0, 0, 0, 249, 0, 0, 0, 60, 0, 0, 0, 90, 0, 0, 0, 55, 0, 0, 0, 193, 0, 0, 0, 142, 0, 0, 0, 39, 0, 0, 0, 71, 0, 0, 0, 170, 0, 0, 0, 73, 0, 0, 0, 90, 0, 0, 0, 248, 0, 0, 0, 251, 0, 0, 0, 104, 0, 0, 0, 4, 0, 0, 0, 35, 0, 0, 0, 209, 0, 0, 0, 235, 0, 0, 0, 64, 0, -0, 0, 101, 0, 0, 0, 165, 0, 0, 0, 17, 0, 0, 0, 132, 0, 0, 0, 138, 0, 0, 0, 103, 0, 0, 0, 157, 0, 0, 0, 158, 0, 0, 0, 209, 0, 0, 0, 68, 0, 0, 0, 104, 0, 0, 0, 122, 0, 0, 0, 52, 0, 0, 0, 225, 0, 0, 0, 159, 0, 0, 0, 163, 0, 0, 0, 84, 0, 0, 0, 205, 0, 0, 0, 7, 0, 0, 0, 202, 0, 0, 0, 121, 0, 0, 0, 31, 0, 0, 0, 84, 0, 0, 0, 47, 0, 0, 0, 19, 0, 0, 0, 112, 0, 0, 0, 78, 0, 0, 0, 238, 0, 0, 0, 162, 0, 0, 0, 250, 0, 0, 0, 231, 0, 0, 0, 93, 0, 0, 0, 54, 0, 0, 0, 236, 0, 0, 0, 84, 0, 0, 0, 248, 0, 0, 0, 206, -0, 0, 0, 228, 0, 0, 0, 133, 0, 0, 0, 223, 0, 0, 0, 246, 0, 0, 0, 111, 0, 0, 0, 29, 0, 0, 0, 144, 0, 0, 0, 8, 0, 0, 0, 188, 0, 0, 0, 232, 0, 0, 0, 192, 0, 0, 0, 146, 0, 0, 0, 45, 0, 0, 0, 67, 0, 0, 0, 107, 0, 0, 0, 146, 0, 0, 0, 169, 0, 0, 0, 142, 0, 0, 0, 171, 0, 0, 0, 10, 0, 0, 0, 46, 0, 0, 0, 28, 0, 0, 0, 30, 0, 0, 0, 100, 0, 0, 0, 35, 0, 0, 0, 159, 0, 0, 0, 44, 0, 0, 0, 167, 0, 0, 0, 214, 0, 0, 0, 46, 0, 0, 0, 213, 0, 0, 0, 204, 0, 0, 0, 212, 0, 0, 0, 203, 0, 0, 0, 90, 0, 0, 0, 59, 0, 0, 0, 167, -0, 0, 0, 249, 0, 0, 0, 70, 0, 0, 0, 3, 0, 0, 0, 29, 0, 0, 0, 173, 0, 0, 0, 43, 0, 0, 0, 52, 0, 0, 0, 49, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 8, 0, 0, 0, 130, 0, 0, 0, 20, 0, 0, 0, 196, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 240, 0, 0, 0, 227, 0, 0, 0, 85, 0, 0, 0, 67, 0, 0, 0, 49, 0, 0, 0, 96, 0, 0, 0, 214, 0, 0, 0, 221, 0, 0, 0, 120, 0, 0, 0, 230, 0, 0, 0, 212, 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 177, 0, 0, 0, 106, 0, 0, 0, 99, 0, 0, 0, 226, 0, 0, -0, 146, 0, 0, 0, 89, 0, 0, 0, 209, 0, 0, 0, 26, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 41, 0, 0, 0, 201, 0, 0, 0, 193, 0, 0, 0, 246, 0, 0, 0, 111, 0, 0, 0, 122, 0, 0, 0, 197, 0, 0, 0, 60, 0, 0, 0, 95, 0, 0, 0, 101, 0, 0, 0, 39, 0, 0, 0, 79, 0, 0, 0, 208, 0, 0, 0, 114, 0, 0, 0, 177, 0, 0, 0, 17, 0, 0, 0, 20, 0, 0, 0, 39, 0, 0, 0, 21, 0, 0, 0, 148, 0, 0, 0, 72, 0, 0, 0, 129, 0, 0, 0, 126, 0, 0, 0, 116, 0, 0, 0, 216, 0, 0, 0, 50, 0, 0, 0, 213, 0, 0, 0, 209, 0, 0, 0, 17, 0, 0, 0, 40, 0, 0, 0, -96, 0, 0, 0, 99, 0, 0, 0, 54, 0, 0, 0, 50, 0, 0, 0, 55, 0, 0, 0, 181, 0, 0, 0, 19, 0, 0, 0, 28, 0, 0, 0, 160, 0, 0, 0, 55, 0, 0, 0, 227, 0, 0, 0, 116, 0, 0, 0, 241, 0, 0, 0, 37, 0, 0, 0, 78, 0, 0, 0, 17, 0, 0, 0, 150, 0, 0, 0, 103, 0, 0, 0, 230, 0, 0, 0, 28, 0, 0, 0, 194, 0, 0, 0, 178, 0, 0, 0, 83, 0, 0, 0, 226, 0, 0, 0, 218, 0, 0, 0, 133, 0, 0, 0, 238, 0, 0, 0, 178, 0, 0, 0, 159, 0, 0, 0, 89, 0, 0, 0, 243, 0, 0, 0, 186, 0, 0, 0, 189, 0, 0, 0, 250, 0, 0, 0, 207, 0, 0, 0, 110, 0, 0, 0, 249, 0, 0, -0, 218, 0, 0, 0, 164, 0, 0, 0, 179, 0, 0, 0, 2, 0, 0, 0, 143, 0, 0, 0, 100, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 148, 0, 0, 0, 242, 0, 0, 0, 100, 0, 0, 0, 84, 0, 0, 0, 71, 0, 0, 0, 55, 0, 0, 0, 7, 0, 0, 0, 64, 0, 0, 0, 138, 0, 0, 0, 32, 0, -0, 0, 186, 0, 0, 0, 74, 0, 0, 0, 85, 0, 0, 0, 215, 0, 0, 0, 63, 0, 0, 0, 71, 0, 0, 0, 186, 0, 0, 0, 37, 0, 0, 0, 35, 0, 0, 0, 20, 0, 0, 0, 176, 0, 0, 0, 44, 0, 0, 0, 232, 0, 0, 0, 85, 0, 0, 0, 168, 0, 0, 0, 166, 0, 0, 0, 239, 0, 0, 0, 81, 0, 0, 0, 189, 0, 0, 0, 111, 0, 0, 0, 106, 0, 0, 0, 113, 0, 0, 0, 214, 0, 0, 0, 22, 0, 0, 0, 118, 0, 0, 0, 178, 0, 0, 0, 6, 0, 0, 0, 234, 0, 0, 0, 121, 0, 0, 0, 245, 0, 0, 0, 196, 0, 0, 0, 195, 0, 0, 0, 82, 0, 0, 0, 126, 0, 0, 0, 97, 0, 0, 0, 209, 0, 0, 0, 225, 0, -0, 0, 173, 0, 0, 0, 112, 0, 0, 0, 120, 0, 0, 0, 29, 0, 0, 0, 22, 0, 0, 0, 17, 0, 0, 0, 248, 0, 0, 0, 124, 0, 0, 0, 43, 0, 0, 0, 252, 0, 0, 0, 85, 0, 0, 0, 159, 0, 0, 0, 82, 0, 0, 0, 248, 0, 0, 0, 245, 0, 0, 0, 22, 0, 0, 0, 52, 0, 0, 0, 150, 0, 0, 0, 154, 0, 0, 0, 246, 0, 0, 0, 197, 0, 0, 0, 224, 0, 0, 0, 20, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 14, 0, 0, 0, 76, 0, 0, 0, 173, 0, 0, 0, 158, 0, 0, 0, 154, 0, 0, 0, 112, 0, 0, 0, 35, 0, 0, 0, 150, 0, 0, 0, 178, 0, 0, 0, 241, 0, 0, 0, 46, 0, 0, 0].concat([157, -0, 0, 0, 195, 0, 0, 0, 50, 0, 0, 0, 155, 0, 0, 0, 84, 0, 0, 0, 165, 0, 0, 0, 115, 0, 0, 0, 222, 0, 0, 0, 136, 0, 0, 0, 177, 0, 0, 0, 62, 0, 0, 0, 36, 0, 0, 0, 246, 0, 0, 0, 226, 0, 0, 0, 76, 0, 0, 0, 31, 0, 0, 0, 91, 0, 0, 0, 178, 0, 0, 0, 175, 0, 0, 0, 130, 0, 0, 0, 165, 0, 0, 0, 207, 0, 0, 0, 129, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 239, 0, 0, 0, 219, 0, 0, 0, 162, 0, 0, 0, 204, 0, 0, 0, 36, 0, 0, 0, 178, 0, 0, 0, 126, 0, 0, 0, 11, 0, 0, 0, 122, 0, 0, 0, 235, 0, 0, 0, 1, 0, 0, 0, 216, 0, 0, 0, 82, -0, 0, 0, 244, 0, 0, 0, 81, 0, 0, 0, 137, 0, 0, 0, 41, 0, 0, 0, 121, 0, 0, 0, 55, 0, 0, 0, 116, 0, 0, 0, 222, 0, 0, 0, 18, 0, 0, 0, 243, 0, 0, 0, 104, 0, 0, 0, 183, 0, 0, 0, 102, 0, 0, 0, 195, 0, 0, 0, 238, 0, 0, 0, 104, 0, 0, 0, 220, 0, 0, 0, 129, 0, 0, 0, 181, 0, 0, 0, 85, 0, 0, 0, 153, 0, 0, 0, 171, 0, 0, 0, 217, 0, 0, 0, 40, 0, 0, 0, 99, 0, 0, 0, 109, 0, 0, 0, 139, 0, 0, 0, 64, 0, 0, 0, 105, 0, 0, 0, 117, 0, 0, 0, 108, 0, 0, 0, 205, 0, 0, 0, 92, 0, 0, 0, 42, 0, 0, 0, 126, 0, 0, 0, 50, 0, 0, 0, -123, 0, 0, 0, 41, 0, 0, 0, 2, 0, 0, 0, 204, 0, 0, 0, 34, 0, 0, 0, 116, 0, 0, 0, 77, 0, 0, 0, 25, 0, 0, 0, 7, 0, 0, 0, 192, 0, 0, 0, 218, 0, 0, 0, 181, 0, 0, 0, 118, 0, 0, 0, 81, 0, 0, 0, 42, 0, 0, 0, 170, 0, 0, 0, 166, 0, 0, 0, 10, 0, 0, 0, 95, 0, 0, 0, 38, 0, 0, 0, 212, 0, 0, 0, 188, 0, 0, 0, 175, 0, 0, 0, 72, 0, 0, 0, 136, 0, 0, 0, 127, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 242, 0, 0, 0, 225, 0, 0, 0, 207, 0, 0, 0, 233, 0, 0, 0, 221, 0, 0, 0, 21, 0, 0, 0, 237, 0, 0, 0, 181, 0, 0, 0, 154, 0, 0, 0, -140, 0, 0, 0, 154, 0, 0, 0, 221, 0, 0, 0, 39, 0, 0, 0, 244, 0, 0, 0, 127, 0, 0, 0, 71, 0, 0, 0, 217, 0, 0, 0, 82, 0, 0, 0, 167, 0, 0, 0, 205, 0, 0, 0, 101, 0, 0, 0, 165, 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 237, 0, 0, 0, 166, 0, 0, 0, 99, 0, 0, 0, 91, 0, 0, 0, 128, 0, 0, 0, 74, 0, 0, 0, 173, 0, 0, 0, 77, 0, 0, 0, 237, 0, 0, 0, 191, 0, 0, 0, 238, 0, 0, 0, 73, 0, 0, 0, 179, 0, 0, 0, 6, 0, 0, 0, 248, 0, 0, 0, 100, 0, 0, 0, 139, 0, 0, 0, 96, 0, 0, 0, 144, 0, 0, 0, 233, 0, 0, 0, 222, 0, 0, 0, 68, 0, 0, -0, 119, 0, 0, 0, 185, 0, 0, 0, 7, 0, 0, 0, 54, 0, 0, 0, 50, 0, 0, 0, 194, 0, 0, 0, 80, 0, 0, 0, 245, 0, 0, 0, 101, 0, 0, 0, 223, 0, 0, 0, 72, 0, 0, 0, 76, 0, 0, 0, 55, 0, 0, 0, 170, 0, 0, 0, 104, 0, 0, 0, 171, 0, 0, 0, 154, 0, 0, 0, 31, 0, 0, 0, 62, 0, 0, 0, 255, 0, 0, 0, 137, 0, 0, 0, 146, 0, 0, 0, 160, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 79, 0, 0, 0, 156, 0, 0, 0, 25, 0, 0, 0, 192, 0, 0, 0, 74, 0, 0, 0, 49, 0, 0, 0, 236, 0, 0, 0, 249, 0, 0, 0, 170, 0, 0, 0, 235, 0, 0, 0, 178, 0, 0, 0, 22, 0, 0, 0, 156, 0, 0, 0, 163, 0, 0, 0, 102, 0, 0, 0, 95, 0, 0, 0, 209, 0, 0, 0, 212, 0, 0, 0, 237, 0, 0, 0, 184, 0, 0, 0, 146, 0, 0, 0, 28, 0, 0, 0, 171, 0, 0, 0, 218, 0, 0, 0, 234, 0, 0, 0, 217, 0, 0, 0, 87, 0, 0, 0, 223, 0, 0, 0, 76, 0, 0, -0, 42, 0, 0, 0, 72, 0, 0, 0, 75, 0, 0, 0, 176, 0, 0, 0, 78, 0, 0, 0, 110, 0, 0, 0, 17, 0, 0, 0, 59, 0, 0, 0, 81, 0, 0, 0, 189, 0, 0, 0, 106, 0, 0, 0, 253, 0, 0, 0, 228, 0, 0, 0, 37, 0, 0, 0, 165, 0, 0, 0, 95, 0, 0, 0, 17, 0, 0, 0, 63, 0, 0, 0, 152, 0, 0, 0, 146, 0, 0, 0, 81, 0, 0, 0, 20, 0, 0, 0, 198, 0, 0, 0, 95, 0, 0, 0, 60, 0, 0, 0, 11, 0, 0, 0, 168, 0, 0, 0, 247, 0, 0, 0, 194, 0, 0, 0, 129, 0, 0, 0, 67, 0, 0, 0, 222, 0, 0, 0, 145, 0, 0, 0, 115, 0, 0, 0, 60, 0, 0, 0, 143, 0, 0, 0, 159, 0, 0, 0, -51, 0, 0, 0, 42, 0, 0, 0, 31, 0, 0, 0, 67, 0, 0, 0, 51, 0, 0, 0, 143, 0, 0, 0, 104, 0, 0, 0, 255, 0, 0, 0, 31, 0, 0, 0, 61, 0, 0, 0, 115, 0, 0, 0, 107, 0, 0, 0, 191, 0, 0, 0, 104, 0, 0, 0, 204, 0, 0, 0, 125, 0, 0, 0, 19, 0, 0, 0, 108, 0, 0, 0, 36, 0, 0, 0, 75, 0, 0, 0, 204, 0, 0, 0, 77, 0, 0, 0, 36, 0, 0, 0, 13, 0, 0, 0, 254, 0, 0, 0, 222, 0, 0, 0, 134, 0, 0, 0, 173, 0, 0, 0, 59, 0, 0, 0, 121, 0, 0, 0, 81, 0, 0, 0, 129, 0, 0, 0, 1, 0, 0, 0, 220, 0, 0, 0, 115, 0, 0, 0, 83, 0, 0, 0, 224, 0, 0, 0, 110, -0, 0, 0, 155, 0, 0, 0, 234, 0, 0, 0, 104, 0, 0, 0, 63, 0, 0, 0, 92, 0, 0, 0, 20, 0, 0, 0, 132, 0, 0, 0, 83, 0, 0, 0, 141, 0, 0, 0, 75, 0, 0, 0, 192, 0, 0, 0, 159, 0, 0, 0, 159, 0, 0, 0, 137, 0, 0, 0, 43, 0, 0, 0, 140, 0, 0, 0, 186, 0, 0, 0, 134, 0, 0, 0, 250, 0, 0, 0, 242, 0, 0, 0, 205, 0, 0, 0, 227, 0, 0, 0, 45, 0, 0, 0, 6, 0, 0, 0, 249, 0, 0, 0, 41, 0, 0, 0, 90, 0, 0, 0, 219, 0, 0, 0, 61, 0, 0, 0, 132, 0, 0, 0, 82, 0, 0, 0, 171, 0, 0, 0, 204, 0, 0, 0, 107, 0, 0, 0, 96, 0, 0, 0, 157, 0, 0, 0, 183, -0, 0, 0, 74, 0, 0, 0, 14, 0, 0, 0, 54, 0, 0, 0, 99, 0, 0, 0, 145, 0, 0, 0, 173, 0, 0, 0, 160, 0, 0, 0, 149, 0, 0, 0, 176, 0, 0, 0, 151, 0, 0, 0, 137, 0, 0, 0, 78, 0, 0, 0, 207, 0, 0, 0, 125, 0, 0, 0, 60, 0, 0, 0, 229, 0, 0, 0, 124, 0, 0, 0, 40, 0, 0, 0, 46, 0, 0, 0, 105, 0, 0, 0, 152, 0, 0, 0, 253, 0, 0, 0, 198, 0, 0, 0, 189, 0, 0, 0, 204, 0, 0, 0, 202, 0, 0, 0, 223, 0, 0, 0, 154, 0, 0, 0, 68, 0, 0, 0, 126, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 137, 0, 0, 0, 109, 0, 0, 0, 191, 0, 0, 0, 39, 0, 0, 0, -194, 0, 0, 0, 248, 0, 0, 0, 205, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 181, 0, 0, 0, 88, 0, 0, 0, 78, 0, 0, 0, 183, 0, 0, 0, 137, 0, 0, 0, 9, 0, 0, 0, 233, 0, 0, 0, 45, 0, 0, 0, 84, 0, 0, 0, 190, 0, 0, 0, 117, 0, 0, 0, 203, 0, 0, 0, 5, 0, 0, 0, 176, 0, 0, 0, 84, 0, 0, 0, 183, 0, 0, 0, 231, 0, 0, 0, 38, 0, 0, 0, 134, 0, 0, 0, 74, 0, 0, 0, 252, 0, 0, 0, 25, 0, 0, 0, 207, 0, 0, 0, 39, 0, 0, 0, 70, 0, 0, 0, 212, 0, 0, 0, 34, 0, 0, 0, 150, 0, 0, 0, 90, 0, 0, 0, 17, 0, 0, 0, 232, 0, 0, 0, 213, -0, 0, 0, 27, 0, 0, 0, 237, 0, 0, 0, 113, 0, 0, 0, 197, 0, 0, 0, 93, 0, 0, 0, 200, 0, 0, 0, 175, 0, 0, 0, 69, 0, 0, 0, 64, 0, 0, 0, 123, 0, 0, 0, 119, 0, 0, 0, 87, 0, 0, 0, 73, 0, 0, 0, 158, 0, 0, 0, 128, 0, 0, 0, 57, 0, 0, 0, 35, 0, 0, 0, 238, 0, 0, 0, 129, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 207, 0, 0, 0, 219, 0, 0, 0, 122, 0, 0, 0, 47, 0, 0, 0, 20, 0, 0, 0, 184, 0, 0, 0, 87, 0, 0, 0, 143, 0, 0, 0, 161, 0, 0, 0, 57, 0, 0, 0, 30, 0, 0, 0, 119, 0, 0, 0, 252, 0, 0, 0, 11, 0, 0, 0, 166, 0, 0, 0, 191, -0, 0, 0, 138, 0, 0, 0, 12, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 58, 0, 0, 0, 212, 0, 0, 0, 216, 0, 0, 0, 39, 0, 0, 0, 207, 0, 0, 0, 232, 0, 0, 0, 161, 0, 0, 0, 114, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 221, 0, 0, 0, 13, 0, 0, 0, 150, 0, -0, 0, 218, 0, 0, 0, 121, 0, 0, 0, 237, 0, 0, 0, 86, 0, 0, 0, 66, 0, 0, 0, 21, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 28, 0, 0, 0, 107, 0, 0, 0, 38, 0, 0, 0, 48, 0, 0, 0, 246, 0, 0, 0, 106, 0, 0, 0, 149, 0, 0, 0, 103, 0, 0, 0, 243, 0, 0, 0, 10, 0, 0, 0, 197, 0, 0, 0, 8, 0, 0, 0, 164, 0, 0, 0, 43, 0, 0, 0, 47, 0, 0, 0, 189, 0, 0, 0, 49, 0, 0, 0, 129, 0, 0, 0, 42, 0, 0, 0, 166, 0, 0, 0, 182, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 218, 0, 0, 0, 61, 0, 0, 0, 178, 0, 0, 0, 176, 0, 0, 0, 150, 0, -0, 0, 206, 0, 0, 0, 138, 0, 0, 0, 210, 0, 0, 0, 141, 0, 0, 0, 112, 0, 0, 0, 179, 0, 0, 0, 211, 0, 0, 0, 52, 0, 0, 0, 1, 0, 0, 0, 144, 0, 0, 0, 141, 0, 0, 0, 16, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 13, 0, 0, 0, 231, 0, 0, 0, 186, 0, 0, 0, 79, 0, 0, 0, 7, 0, 0, 0, 223, 0, 0, 0, 141, 0, 0, 0, 234, 0, 0, 0, 125, 0, 0, 0, 160, 0, 0, 0, 197, 0, 0, 0, 214, 0, 0, 0, 177, 0, 0, 0, 176, 0, 0, 0, 229, 0, 0, 0, 87, 0, 0, 0, 27, 0, 0, 0, 91, 0, 0, 0, 245, 0, 0, 0, 69, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 100, 0, -0, 0, 90, 0, 0, 0, 235, 0, 0, 0, 92, 0, 0, 0, 252, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 43, 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 194, 0, 0, 0, 175, 0, 0, 0, 150, 0, 0, 0, 54, 0, 0, 0, 254, 0, 0, 0, 74, 0, 0, 0, 226, 0, 0, 0, 84, 0, 0, 0, 32, 0, 0, 0, 106, 0, 0, 0, 235, 0, 0, 0, 178, 0, 0, 0, 159, 0, 0, 0, 98, 0, 0, 0, 215, 0, 0, 0, 206, 0, 0, 0, 162, 0, 0, 0, 63, 0, 0, 0, 32, 0, 0, 0, 17, 0, 0, 0, 52, 0, 0, 0, 55, 0, 0, 0, 224, 0, 0, 0, 66, 0, 0, 0, 237, 0, 0, 0, 111, 0, 0, 0, 249, 0, 0, -0, 26, 0, 0, 0, 200, 0, 0, 0, 125, 0, 0, 0, 216, 0, 0, 0, 185, 0, 0, 0, 17, 0, 0, 0, 232, 0, 0, 0, 54, 0, 0, 0, 63, 0, 0, 0, 66, 0, 0, 0, 193, 0, 0, 0, 202, 0, 0, 0, 220, 0, 0, 0, 211, 0, 0, 0, 241, 0, 0, 0, 200, 0, 0, 0, 35, 0, 0, 0, 61, 0, 0, 0, 79, 0, 0, 0, 81, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 141, 0, 0, 0, 216, 0, 0, 0, 228, 0, 0, 0, 160, 0, 0, 0, 170, 0, 0, 0, 243, 0, 0, 0, 4, 0, 0, 0, 214, 0, 0, 0, 17, 0, 0, 0, 147, 0, 0, 0, 200, 0, 0, 0, 53, 0, 0, 0, 69, 0, 0, 0, 97, 0, 0, 0, 54, 0, 0, -0, 214, 0, 0, 0, 8, 0, 0, 0, 144, 0, 0, 0, 191, 0, 0, 0, 167, 0, 0, 0, 122, 0, 0, 0, 151, 0, 0, 0, 108, 0, 0, 0, 15, 0, 0, 0, 132, 0, 0, 0, 213, 0, 0, 0, 51, 0, 0, 0, 45, 0, 0, 0, 55, 0, 0, 0, 201, 0, 0, 0, 106, 0, 0, 0, 128, 0, 0, 0, 144, 0, 0, 0, 61, 0, 0, 0, 10, 0, 0, 0, 162, 0, 0, 0, 170, 0, 0, 0, 225, 0, 0, 0, 184, 0, 0, 0, 132, 0, 0, 0, 186, 0, 0, 0, 97, 0, 0, 0, 54, 0, 0, 0, 221, 0, 0, 0, 105, 0, 0, 0, 107, 0, 0, 0, 219, 0, 0, 0, 91, 0, 0, 0, 156, 0, 0, 0, 198, 0, 0, 0, 146, 0, 0, 0, 188, -0, 0, 0, 35, 0, 0, 0, 175, 0, 0, 0, 197, 0, 0, 0, 184, 0, 0, 0, 117, 0, 0, 0, 248, 0, 0, 0, 66, 0, 0, 0, 250, 0, 0, 0, 214, 0, 0, 0, 182, 0, 0, 0, 132, 0, 0, 0, 148, 0, 0, 0, 99, 0, 0, 0, 152, 0, 0, 0, 147, 0, 0, 0, 72, 0, 0, 0, 120, 0, 0, 0, 56, 0, 0, 0, 205, 0, 0, 0, 187, 0, 0, 0, 24, 0, 0, 0, 52, 0, 0, 0, 195, 0, 0, 0, 219, 0, 0, 0, 103, 0, 0, 0, 150, 0, 0, 0, 243, 0, 0, 0, 58, 0, 0, 0, 9, 0, 0, 0, 86, 0, 0, 0, 176, 0, 0, 0, 111, 0, 0, 0, 124, 0, 0, 0, 81, 0, 0, 0, 30, 0, 0, 0, 27, 0, 0, 0, 57, -0, 0, 0, 72, 0, 0, 0, 234, 0, 0, 0, 201, 0, 0, 0, 12, 0, 0, 0, 37, 0, 0, 0, 162, 0, 0, 0, 122, 0, 0, 0, 202, 0, 0, 0, 231, 0, 0, 0, 146, 0, 0, 0, 252, 0, 0, 0, 89, 0, 0, 0, 48, 0, 0, 0, 163, 0, 0, 0, 137, 0, 0, 0, 133, 0, 0, 0, 223, 0, 0, 0, 111, 0, 0, 0, 67, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 0, 132, 0, 0, 0, 68, 0, 0, 0, 25, 0, 0, 0, 189, 0, 0, 0, 233, 0, 0, 0, 84, 0, 0, 0, 196, 0, 0, 0, 192, 0, 0, 0, 110, 0, 0, 0, 42, 0, 0, 0, 168, 0, 0, 0, 168, 0, 0, 0, 155, 0, 0, 0, 67, 0, 0, 0, 213, 0, 0, 0, 113, 0, 0, 0, 34, 0, 0, 0, 95, 0, 0, 0, 220, 0, 0, 0, 1, 0, 0, 0, 250, 0, 0, 0, 223, 0, 0, 0, 179, 0, 0, 0, 184, 0, 0, 0, 71, 0, 0, 0, 75, 0, 0, 0, 10, 0, 0, 0, 165, 0, 0, 0, 68, 0, 0, 0, 234, 0, 0, 0, 41, 0, 0, 0, 5, 0, 0, 0, 144, 0, -0, 0, 80, 0, 0, 0, 175, 0, 0, 0, 99, 0, 0, 0, 95, 0, 0, 0, 157, 0, 0, 0, 158, 0, 0, 0, 225, 0, 0, 0, 157, 0, 0, 0, 56, 0, 0, 0, 151, 0, 0, 0, 31, 0, 0, 0, 108, 0, 0, 0, 172, 0, 0, 0, 48, 0, 0, 0, 70, 0, 0, 0, 178, 0, 0, 0, 106, 0, 0, 0, 25, 0, 0, 0, 209, 0, 0, 0, 75, 0, 0, 0, 219, 0, 0, 0, 187, 0, 0, 0, 140, 0, 0, 0, 218, 0, 0, 0, 46, 0, 0, 0, 171, 0, 0, 0, 200, 0, 0, 0, 90, 0, 0, 0, 119, 0, 0, 0, 108, 0, 0, 0, 43, 0, 0, 0, 190, 0, 0, 0, 175, 0, 0, 0, 161, 0, 0, 0, 109, 0, 0, 0, 47, 0, 0, 0, 11, -0, 0, 0, 177, 0, 0, 0, 143, 0, 0, 0, 227, 0, 0, 0, 224, 0, 0, 0, 56, 0, 0, 0, 205, 0, 0, 0, 11, 0, 0, 0, 65, 0, 0, 0, 27, 0, 0, 0, 74, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 243, 0, 0, 0, 111, 0, 0, 0, 220, 0, 0, 0, 184, 0, 0, 0, 233, 0, 0, 0, 222, 0, 0, 0, 178, 0, 0, 0, 163, 0, 0, 0, 64, 0, 0, 0, 1, 0, 0, 0, 166, 0, 0, 0, 69, 0, 0, 0, 30, 0, 0, 0, 118, 0, 0, 0, 10, 0, 0, 0, 218, 0, 0, 0, 141, 0, 0, 0, 44, 0, 0, 0, 7, 0, 0, 0, 63, 0, 0, 0, 137, 0, 0, 0, 125, 0, 0, 0, 4, 0, 0, 0, 173, 0, 0, 0, 67, 0, 0, -0, 80, 0, 0, 0, 110, 0, 0, 0, 210, 0, 0, 0, 71, 0, 0, 0, 203, 0, 0, 0, 138, 0, 0, 0, 230, 0, 0, 0, 133, 0, 0, 0, 26, 0, 0, 0, 36, 0, 0, 0, 243, 0, 0, 0, 210, 0, 0, 0, 96, 0, 0, 0, 253, 0, 0, 0, 223, 0, 0, 0, 115, 0, 0, 0, 164, 0, 0, 0, 13, 0, 0, 0, 115, 0, 0, 0, 14, 0, 0, 0, 253, 0, 0, 0, 103, 0, 0, 0, 107, 0, 0, 0, 113, 0, 0, 0, 155, 0, 0, 0, 129, 0, 0, 0, 83, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 244, 0, 0, 0, 184, 0, 0, 0, 213, 0, 0, 0, 195, 0, 0, 0, 48, 0, 0, 0, 155, 0, 0, 0, 59, 0, 0, 0, 124, 0, -0, 0, 163, 0, 0, 0, 240, 0, 0, 0, 208, 0, 0, 0, 132, 0, 0, 0, 33, 0, 0, 0, 214, 0, 0, 0, 191, 0, 0, 0, 183, 0, 0, 0, 76, 0, 0, 0, 135, 0, 0, 0, 19, 0, 0, 0, 69, 0, 0, 0, 45, 0, 0, 0, 167, 0, 0, 0, 85, 0, 0, 0, 93, 0, 0, 0, 4, 0, 0, 0, 179, 0, 0, 0, 64, 0, 0, 0, 40, 0, 0, 0, 149, 0, 0, 0, 45, 0, 0, 0, 48, 0, 0, 0, 131, 0, 0, 0, 236, 0, 0, 0, 94, 0, 0, 0, 228, 0, 0, 0, 255, 0, 0, 0, 117, 0, 0, 0, 254, 0, 0, 0, 121, 0, 0, 0, 38, 0, 0, 0, 157, 0, 0, 0, 29, 0, 0, 0, 54, 0, 0, 0, 205, 0, 0, 0, 10, 0, 0, -0, 21, 0, 0, 0, 210, 0, 0, 0, 36, 0, 0, 0, 20, 0, 0, 0, 119, 0, 0, 0, 113, 0, 0, 0, 215, 0, 0, 0, 138, 0, 0, 0, 27, 0, 0, 0, 4, 0, 0, 0, 93, 0, 0, 0, 147, 0, 0, 0, 201, 0, 0, 0, 190, 0, 0, 0, 170, 0, 0, 0, 144, 0, 0, 0, 205, 0, 0, 0, 155, 0, 0, 0, 251, 0, 0, 0, 115, 0, 0, 0, 126, 0, 0, 0, 176, 0, 0, 0, 100, 0, 0, 0, 152, 0, 0, 0, 87, 0, 0, 0, 68, 0, 0, 0, 66, 0, 0, 0, 65, 0, 0, 0, 177, 0, 0, 0, 175, 0, 0, 0, 234, 0, 0, 0, 193, 0, 0, 0, 195, 0, 0, 0, 34, 0, 0, 0, 255, 0, 0, 0, 96, 0, 0, 0, 70, 0, -0, 0, 203, 0, 0, 0, 97, 0, 0, 0, 129, 0, 0, 0, 112, 0, 0, 0, 97, 0, 0, 0, 13, 0, 0, 0, 130, 0, 0, 0, 185, 0, 0, 0, 254, 0, 0, 0, 33, 0, 0, 0, 205, 0, 0, 0, 196, 0, 0, 0, 245, 0, 0, 0, 152, 0, 0, 0, 12, 0, 0, 0, 78, 0, 0, 0, 114, 0, 0, 0, 238, 0, 0, 0, 135, 0, 0, 0, 73, 0, 0, 0, 248, 0, 0, 0, 161, 0, 0, 0, 149, 0, 0, 0, 223, 0, 0, 0, 143, 0, 0, 0, 45, 0, 0, 0, 189, 0, 0, 0, 33, 0, 0, 0, 6, 0, 0, 0, 124, 0, 0, 0, 21, 0, 0, 0, 232, 0, 0, 0, 18, 0, 0, 0, 109, 0, 0, 0, 147, 0, 0, 0, 214, 0, 0, 0, 56, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 247, 0, 0, 0, 81, 0, 0, 0, 217, 0, 0, 0, 239, 0, 0, 0, 125, 0, 0, 0, 66, 0, 0, 0, 1, 0, 0, 0, 19, 0, 0, 0, 233, 0, 0, 0, 184, 0, 0, 0, 127, 0, 0, 0, 166, 0, 0, 0, 73, 0, 0, 0, 23, 0, 0, 0, 100, 0, 0, 0, 33, 0, 0, -0, 128, 0, 0, 0, 131, 0, 0, 0, 44, 0, 0, 0, 99, 0, 0, 0, 76, 0, 0, 0, 96, 0, 0, 0, 9, 0, 0, 0, 89, 0, 0, 0, 145, 0, 0, 0, 146, 0, 0, 0, 119, 0, 0, 0, 57, 0, 0, 0, 81, 0, 0, 0, 244, 0, 0, 0, 72, 0, 0, 0, 96, 0, 0, 0, 213, 0, 0, 0, 34, 0, 0, 0, 131, 0, 0, 0, 8, 0, 0, 0, 47, 0, 0, 0, 255, 0, 0, 0, 153, 0, 0, 0, 62, 0, 0, 0, 105, 0, 0, 0, 109, 0, 0, 0, 136, 0, 0, 0, 218, 0, 0, 0, 231, 0, 0, 0, 91, 0, 0, 0, 82, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 42, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 222, 0, 0, 0, 104, -0, 0, 0, 144, 0, 0, 0, 182, 0, 0, 0, 34, 0, 0, 0, 90, 0, 0, 0, 189, 0, 0, 0, 211, 0, 0, 0, 133, 0, 0, 0, 83, 0, 0, 0, 49, 0, 0, 0, 216, 0, 0, 0, 206, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 60, 0, 0, 0, 75, 0, 0, 0, 162, 0, 0, 0, 29, 0, 0, 0, 44, 0, 0, 0, 47, 0, 0, 0, 54, 0, 0, 0, 190, 0, 0, 0, 122, 0, 0, 0, 252, 0, 0, 0, 205, 0, 0, 0, 188, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 48, 0, 0, 0, 189, 0, 0, 0, 255, 0, 0, 0, 5, 0, 0, 0, 199, 0, 0, 0, 228, 0, 0, 0, 142, 0, 0, 0, 23, 0, 0, 0, 98, 0, 0, 0, 248, -0, 0, 0, 77, 0, 0, 0, 160, 0, 0, 0, 86, 0, 0, 0, 121, 0, 0, 0, 130, 0, 0, 0, 231, 0, 0, 0, 246, 0, 0, 0, 186, 0, 0, 0, 83, 0, 0, 0, 132, 0, 0, 0, 10, 0, 0, 0, 163, 0, 0, 0, 52, 0, 0, 0, 255, 0, 0, 0, 60, 0, 0, 0, 163, 0, 0, 0, 106, 0, 0, 0, 161, 0, 0, 0, 55, 0, 0, 0, 234, 0, 0, 0, 221, 0, 0, 0, 182, 0, 0, 0, 149, 0, 0, 0, 179, 0, 0, 0, 120, 0, 0, 0, 25, 0, 0, 0, 118, 0, 0, 0, 30, 0, 0, 0, 85, 0, 0, 0, 47, 0, 0, 0, 119, 0, 0, 0, 46, 0, 0, 0, 127, 0, 0, 0, 193, 0, 0, 0, 234, 0, 0, 0, 94, 0, 0, 0, 131, -0, 0, 0, 225, 0, 0, 0, 110, 0, 0, 0, 169, 0, 0, 0, 7, 0, 0, 0, 51, 0, 0, 0, 62, 0, 0, 0, 131, 0, 0, 0, 255, 0, 0, 0, 203, 0, 0, 0, 28, 0, 0, 0, 159, 0, 0, 0, 177, 0, 0, 0, 163, 0, 0, 0, 180, 0, 0, 0, 201, 0, 0, 0, 225, 0, 0, 0, 7, 0, 0, 0, 151, 0, 0, 0, 255, 0, 0, 0, 248, 0, 0, 0, 35, 0, 0, 0, 143, 0, 0, 0, 206, 0, 0, 0, 64, 0, 0, 0, 253, 0, 0, 0, 46, 0, 0, 0, 94, 0, 0, 0, 219, 0, 0, 0, 22, 0, 0, 0, 67, 0, 0, 0, 45, 0, 0, 0, 186, 0, 0, 0, 56, 0, 0, 0, 2, 0, 0, 0, 247, 0, 0, 0, 129, 0, 0, 0, 67, 0, -0, 0, 131, 0, 0, 0, 163, 0, 0, 0, 32, 0, 0, 0, 79, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 138, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 49, 0, 0, 0, 198, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 223, 0, 0, 0, 215, 0, 0, 0, 250, 0, 0, 0, 47, 0, 0, 0, 136, 0, 0, 0, 63, 0, 0, 0, 252, 0, 0, 0, 12, 0, 0, 0, 118, 0, 0, 0, 196, 0, 0, 0, 166, 0, 0, 0, 69, 0, 0, 0, 114, 0, 0, 0, 187, 0, 0, 0, 12, 0, 0, 0, 188, 0, 0, 0, 106, 0, 0, 0, 164, 0, 0, 0, 151, 0, 0, 0, 23, 0, 0, 0, 147, 0, 0, 0, 45, 0, 0, 0, 111, 0, 0, 0, 222, 0, -0, 0, 114, 0, 0, 0, 16, 0, 0, 0, 28, 0, 0, 0, 8, 0, 0, 0, 44, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 50, 0, 0, 0, 104, 0, 0, 0, 39, 0, 0, 0, 212, 0, 0, 0, 171, 0, 0, 0, 221, 0, 0, 0, 197, 0, 0, 0, 88, 0, 0, 0, 97, 0, 0, 0, 19, 0, 0, 0, 109, 0, 0, 0, 17, 0, 0, 0, 30, 0, 0, 0, 77, 0, 0, 0, 26, 0, 0, 0, 185, 0, 0, 0, 201, 0, 0, 0, 16, 0, 0, 0, 251, 0, 0, 0, 30, 0, 0, 0, 78, 0, 0, 0, 244, 0, 0, 0, 132, 0, 0, 0, 75, 0, 0, 0, 138, 0, 0, 0, 94, 0, 0, 0, 123, 0, 0, 0, 75, 0, 0, 0, 232, 0, 0, 0, 67, 0, 0, 0, -140, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 84, 0, 0, 0, 19, 0, 0, 0, 197, 0, 0, 0, 92, 0, 0, 0, 182, 0, 0, 0, 53, 0, 0, 0, 78, 0, 0, 0, 157, 0, 0, 0, 228, 0, 0, 0, 91, 0, 0, 0, 65, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 125, 0, -0, 0, 18, 0, 0, 0, 72, 0, 0, 0, 130, 0, 0, 0, 20, 0, 0, 0, 66, 0, 0, 0, 205, 0, 0, 0, 50, 0, 0, 0, 212, 0, 0, 0, 75, 0, 0, 0, 193, 0, 0, 0, 114, 0, 0, 0, 97, 0, 0, 0, 42, 0, 0, 0, 140, 0, 0, 0, 236, 0, 0, 0, 226, 0, 0, 0, 248, 0, 0, 0, 36, 0, 0, 0, 69, 0, 0, 0, 148, 0, 0, 0, 227, 0, 0, 0, 190, 0, 0, 0, 221, 0, 0, 0, 103, 0, 0, 0, 168, 0, 0, 0, 119, 0, 0, 0, 90, 0, 0, 0, 174, 0, 0, 0, 91, 0, 0, 0, 75, 0, 0, 0, 203, 0, 0, 0, 119, 0, 0, 0, 154, 0, 0, 0, 32, 0, 0, 0, 222, 0, 0, 0, 184, 0, 0, 0, 35, 0, -0, 0, 217, 0, 0, 0, 160, 0, 0, 0, 15, 0, 0, 0, 140, 0, 0, 0, 123, 0, 0, 0, 165, 0, 0, 0, 203, 0, 0, 0, 174, 0, 0, 0, 182, 0, 0, 0, 236, 0, 0, 0, 66, 0, 0, 0, 103, 0, 0, 0, 14, 0, 0, 0, 88, 0, 0, 0, 164, 0, 0, 0, 117, 0, 0, 0, 152, 0, 0, 0, 33, 0, 0, 0, 113, 0, 0, 0, 132, 0, 0, 0, 179, 0, 0, 0, 224, 0, 0, 0, 118, 0, 0, 0, 148, 0, 0, 0, 115, 0, 0, 0, 223, 0, 0, 0, 252, 0, 0, 0, 105, 0, 0, 0, 40, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 0, 91, 0, 0, 0, 248, 0, 0, 0, 59, 0, 0, 0, 36, 0, 0, 0, 55, 0, 0, 0, 243, -0, 0, 0, 29, 0, 0, 0, 213, 0, 0, 0, 34, 0, 0, 0, 107, 0, 0, 0, 208, 0, 0, 0, 152, 0, 0, 0, 168, 0, 0, 0, 108, 0, 0, 0, 207, 0, 0, 0, 255, 0, 0, 0, 6, 0, 0, 0, 225, 0, 0, 0, 19, 0, 0, 0, 223, 0, 0, 0, 185, 0, 0, 0, 193, 0, 0, 0, 12, 0, 0, 0, 169, 0, 0, 0, 191, 0, 0, 0, 51, 0, 0, 0, 217, 0, 0, 0, 129, 0, 0, 0, 218, 0, 0, 0, 178, 0, 0, 0, 79, 0, 0, 0, 130, 0, 0, 0, 157, 0, 0, 0, 67, 0, 0, 0, 129, 0, 0, 0, 9, 0, 0, 0, 241, 0, 0, 0, 210, 0, 0, 0, 1, 0, 0, 0, 239, 0, 0, 0, 172, 0, 0, 0, 244, 0, 0, 0, 45, -0, 0, 0, 125, 0, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 241, 0, 0, 0, 255, 0, 0, 0, 165, 0, 0, 0, 159, 0, 0, 0, 229, 0, 0, 0, 202, 0, 0, 0, 39, 0, 0, 0, 99, 0, 0, 0, 219, 0, 0, 0, 32, 0, 0, 0, 177, 0, 0, 0, 83, 0, 0, 0, 103, 0, 0, 0, 2, 0, 0, 0, 232, 0, 0, 0, 173, 0, 0, 0, 169, 0, 0, 0, 52, 0, 0, 0, 212, 0, 0, 0, 240, 0, 0, 0, 21, 0, 0, 0, 129, 0, 0, 0, 170, 0, 0, 0, 199, 0, 0, 0, 77, 0, 0, 0, 135, 0, 0, 0, 148, 0, 0, 0, 234, 0, 0, 0, 117, 0, 0, 0, 231, 0, 0, 0, 76, 0, 0, 0, 148, 0, 0, 0, 4, 0, 0, 0, 14, -0, 0, 0, 105, 0, 0, 0, 135, 0, 0, 0, 231, 0, 0, 0, 81, 0, 0, 0, 145, 0, 0, 0, 16, 0, 0, 0, 3, 0, 0, 0, 199, 0, 0, 0, 190, 0, 0, 0, 86, 0, 0, 0, 50, 0, 0, 0, 251, 0, 0, 0, 134, 0, 0, 0, 236, 0, 0, 0, 51, 0, 0, 0, 107, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 43, 0, 0, 0, 200, 0, 0, 0, 250, 0, 0, 0, 108, 0, 0, 0, 112, 0, 0, 0, 71, 0, 0, 0, 126, 0, 0, 0, 206, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 113, 0, 0, 0, 243, 0, 0, 0, 180, 0, 0, 0, 86, 0, 0, 0, 166, 0, 0, 0, 220, 0, 0, 0, 204, 0, 0, 0, 120, 0, 0, 0, 7, -0, 0, 0, 117, 0, 0, 0, 208, 0, 0, 0, 221, 0, 0, 0, 178, 0, 0, 0, 106, 0, 0, 0, 198, 0, 0, 0, 239, 0, 0, 0, 185, 0, 0, 0, 192, 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 8, 0, 0, 0, 30, 0, 0, 0, 113, 0, 0, 0, 112, 0, 0, 0, 179, 0, 0, 0, 53, 0, 0, 0, 156, 0, 0, 0, 122, 0, 0, 0, 1, 0, 0, 0, 146, 0, 0, 0, 68, 0, 0, 0, 154, 0, 0, 0, 246, 0, 0, 0, 176, 0, 0, 0, 88, 0, 0, 0, 149, 0, 0, 0, 193, 0, 0, 0, 155, 0, 0, 0, 2, 0, 0, 0, 237, 0, 0, 0, 45, 0, 0, 0, 124, 0, 0, 0, 52, 0, 0, 0, 41, 0, 0, 0, 73, 0, 0, 0, 68, -0, 0, 0, 69, 0, 0, 0, 98, 0, 0, 0, 29, 0, 0, 0, 46, 0, 0, 0, 255, 0, 0, 0, 42, 0, 0, 0, 28, 0, 0, 0, 33, 0, 0, 0, 164, 0, 0, 0, 37, 0, 0, 0, 123, 0, 0, 0, 13, 0, 0, 0, 140, 0, 0, 0, 21, 0, 0, 0, 57, 0, 0, 0, 252, 0, 0, 0, 143, 0, 0, 0, 124, 0, 0, 0, 165, 0, 0, 0, 125, 0, 0, 0, 30, 0, 0, 0, 37, 0, 0, 0, 163, 0, 0, 0, 69, 0, 0, 0, 214, 0, 0, 0, 171, 0, 0, 0, 189, 0, 0, 0, 203, 0, 0, 0, 197, 0, 0, 0, 94, 0, 0, 0, 120, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 211, 0, 0, 0, 66, 0, 0, 0, 237, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 21, 0, 0, 0, 44, 0, 0, 0, 156, 0, 0, 0, 119, 0, 0, 0, 129, 0, 0, 0, 210, 0, 0, 0, 115, 0, 0, 0, 209, 0, 0, 0, 6, 0, 0, 0, 213, 0, 0, 0, 196, 0, 0, 0, 127, 0, 0, 0, 148, 0, 0, 0, 187, 0, 0, 0, 146, 0, 0, -0, 45, 0, 0, 0, 44, 0, 0, 0, 75, 0, 0, 0, 69, 0, 0, 0, 75, 0, 0, 0, 233, 0, 0, 0, 42, 0, 0, 0, 137, 0, 0, 0, 107, 0, 0, 0, 43, 0, 0, 0, 210, 0, 0, 0, 12, 0, 0, 0, 136, 0, 0, 0, 197, 0, 0, 0, 72, 0, 0, 0, 77, 0, 0, 0, 234, 0, 0, 0, 13, 0, 0, 0, 74, 0, 0, 0, 201, 0, 0, 0, 82, 0, 0, 0, 106, 0, 0, 0, 97, 0, 0, 0, 121, 0, 0, 0, 233, 0, 0, 0, 118, 0, 0, 0, 243, 0, 0, 0, 133, 0, 0, 0, 82, 0, 0, 0, 92, 0, 0, 0, 27, 0, 0, 0, 44, 0, 0, 0, 225, 0, 0, 0, 214, 0, 0, 0, 196, 0, 0, 0, 15, 0, 0, 0, 24, 0, 0, 0, -14, 0, 0, 0, 78, 0, 0, 0, 246, 0, 0, 0, 28, 0, 0, 0, 127, 0, 0, 0, 180, 0, 0, 0, 4, 0, 0, 0, 46, 0, 0, 0, 66, 0, 0, 0, 203, 0, 0, 0, 31, 0, 0, 0, 43, 0, 0, 0, 17, 0, 0, 0, 81, 0, 0, 0, 123, 0, 0, 0, 8, 0, 0, 0, 172, 0, 0, 0, 170, 0, 0, 0, 62, 0, 0, 0, 158, 0, 0, 0, 82, 0, 0, 0, 96, 0, 0, 0, 183, 0, 0, 0, 194, 0, 0, 0, 97, 0, 0, 0, 87, 0, 0, 0, 140, 0, 0, 0, 132, 0, 0, 0, 213, 0, 0, 0, 24, 0, 0, 0, 166, 0, 0, 0, 25, 0, 0, 0, 252, 0, 0, 0, 183, 0, 0, 0, 117, 0, 0, 0, 145, 0, 0, 0, 27, 0, 0, 0, 232, -0, 0, 0, 104, 0, 0, 0, 202, 0, 0, 0, 68, 0, 0, 0, 200, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 204, 0, 0, 0, 83, 0, 0, 0, 10, 0, 0, 0, 50, 0, 0, 0, 53, 0, 0, 0, 204, 0, 0, 0, 82, 0, 0, 0, 203, 0, 0, 0, 14, 0, 0, 0, 247, 0, 0, 0, 197, 0, 0, 0, 231, 0, 0, 0, 236, 0, 0, 0, 61, 0, 0, 0, 133, 0, 0, 0, 204, 0, 0, 0, 88, 0, 0, 0, 226, 0, 0, 0, 23, 0, 0, 0, 71, 0, 0, 0, 255, 0, 0, 0, 159, 0, 0, 0, 165, 0, 0, 0, 48, 0, 0, 0, 23, 0, 0, 0, 227, 0, 0, 0, 174, 0, 0, 0, 200, 0, 0, 0, 193, 0, 0, 0, 113, 0, 0, 0, 117, -0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 65, 0, 0, 0, 92, 0, 0, 0, 14, 0, 0, 0, 57, 0, 0, 0, 218, 0, 0, 0, 115, 0, 0, 0, 160, 0, 0, 0, 199, 0, 0, 0, 151, 0, 0, 0, 54, 0, 0, 0, 108, 0, 0, 0, 91, 0, 0, 0, 242, 0, 0, 0, 238, 0, 0, 0, 100, 0, 0, 0, 10, 0, 0, 0, 61, 0, 0, 0, 137, 0, 0, 0, 30, 0, 0, 0, 29, 0, 0, 0, 73, 0, 0, 0, 140, 0, 0, 0, 55, 0, 0, 0, 76, 0, 0, 0, 230, 0, 0, 0, 176, 0, 0, 0, 193, 0, 0, 0, 165, 0, 0, 0, 42, 0, 0, 0, 130, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0, 173, 0, 0, 0, 121, 0, 0, -0, 156, 0, 0, 0, 86, 0, 0, 0, 246, 0, 0, 0, 249, 0, 0, 0, 193, 0, 0, 0, 215, 0, 0, 0, 124, 0, 0, 0, 57, 0, 0, 0, 127, 0, 0, 0, 147, 0, 0, 0, 202, 0, 0, 0, 17, 0, 0, 0, 85, 0, 0, 0, 191, 0, 0, 0, 7, 0, 0, 0, 27, 0, 0, 0, 130, 0, 0, 0, 41, 0, 0, 0, 105, 0, 0, 0, 149, 0, 0, 0, 92, 0, 0, 0, 135, 0, 0, 0, 238, 0, 0, 0, 166, 0, 0, 0, 86, 0, 0, 0, 158, 0, 0, 0, 194, 0, 0, 0, 154, 0, 0, 0, 86, 0, 0, 0, 36, 0, 0, 0, 66, 0, 0, 0, 133, 0, 0, 0, 77, 0, 0, 0, 152, 0, 0, 0, 49, 0, 0, 0, 30, 0, 0, 0, 96, 0, 0, -0, 77, 0, 0, 0, 135, 0, 0, 0, 133, 0, 0, 0, 4, 0, 0, 0, 174, 0, 0, 0, 70, 0, 0, 0, 18, 0, 0, 0, 249, 0, 0, 0, 142, 0, 0, 0, 127, 0, 0, 0, 228, 0, 0, 0, 127, 0, 0, 0, 246, 0, 0, 0, 28, 0, 0, 0, 55, 0, 0, 0, 1, 0, 0, 0, 115, 0, 0, 0, 76, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 196, 0, 0, 0, 233, 0, 0, 0, 108, 0, 0, 0, 133, 0, 0, 0, 72, 0, 0, 0, 74, 0, 0, 0, 90, 0, 0, 0, 172, 0, 0, 0, 217, 0, 0, 0, 31, 0, 0, 0, 67, 0, 0, 0, 248, 0, 0, 0, 98, 0, 0, 0, 91, 0, 0, 0, 238, 0, 0, 0, 152, 0, 0, 0, 42, 0, 0, 0, -51, 0, 0, 0, 142, 0, 0, 0, 121, 0, 0, 0, 206, 0, 0, 0, 97, 0, 0, 0, 6, 0, 0, 0, 53, 0, 0, 0, 216, 0, 0, 0, 215, 0, 0, 0, 202, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 0, 0, 0, 211, 0, 0, 0, 174, 0, 0, 0, 166, 0, 0, 0, 202, 0, 0, 0, 143, 0, 0, 0, 205, -0, 0, 0, 204, 0, 0, 0, 120, 0, 0, 0, 142, 0, 0, 0, 25, 0, 0, 0, 77, 0, 0, 0, 167, 0, 0, 0, 210, 0, 0, 0, 39, 0, 0, 0, 233, 0, 0, 0, 164, 0, 0, 0, 60, 0, 0, 0, 22, 0, 0, 0, 91, 0, 0, 0, 132, 0, 0, 0, 128, 0, 0, 0, 249, 0, 0, 0, 208, 0, 0, 0, 204, 0, 0, 0, 106, 0, 0, 0, 30, 0, 0, 0, 202, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, 0, 189, 0, 0, 0, 99, 0, 0, 0, 123, 0, 0, 0, 110, 0, 0, 0, 42, 0, 0, 0, 210, 0, 0, 0, 135, 0, 0, 0, 72, 0, 0, 0, 255, 0, 0, 0, 161, 0, 0, 0, 202, 0, 0, 0, 233, 0, 0, 0, 21, 0, 0, 0, -133, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 44, 0, 0, 0, 57, 0, 0, 0, 18, 0, 0, 0, 145, 0, 0, 0, 169, 0, 0, 0, 32, 0, 0, 0, 170, 0, 0, 0, 79, 0, 0, 0, 41, 0, 0, 0, 244, 0, 0, 0, 21, 0, 0, 0, 122, 0, 0, 0, 210, 0, 0, 0, 245, 0, 0, 0, 50, 0, 0, 0, 204, 0, 0, 0, 96, 0, 0, 0, 4, 0, 0, 0, 229, 0, 0, 0, 16, 0, 0, 0, 71, 0, 0, 0, 59, 0, 0, 0, 250, 0, 0, 0, 144, 0, 0, 0, 252, 0, 0, 0, 48, 0, 0, 0, 181, 0, 0, 0, 234, 0, 0, 0, 111, 0, 0, 0, 86, 0, 0, 0, 143, 0, 0, 0, 251, 0, 0, 0, 14, 0, 0, 0, 167, 0, 0, 0, -59, 0, 0, 0, 200, 0, 0, 0, 178, 0, 0, 0, 255, 0, 0, 0, 2, 0, 0, 0, 122, 0, 0, 0, 51, 0, 0, 0, 148, 0, 0, 0, 147, 0, 0, 0, 42, 0, 0, 0, 3, 0, 0, 0, 224, 0, 0, 0, 150, 0, 0, 0, 58, 0, 0, 0, 108, 0, 0, 0, 15, 0, 0, 0, 90, 0, 0, 0, 99, 0, 0, 0, 103, 0, 0, 0, 225, 0, 0, 0, 155, 0, 0, 0, 71, 0, 0, 0, 120, 0, 0, 0, 159, 0, 0, 0, 56, 0, 0, 0, 121, 0, 0, 0, 172, 0, 0, 0, 151, 0, 0, 0, 102, 0, 0, 0, 29, 0, 0, 0, 94, 0, 0, 0, 81, 0, 0, 0, 238, 0, 0, 0, 36, 0, 0, 0, 66, 0, 0, 0, 232, 0, 0, 0, 88, 0, 0, 0, 75, -0, 0, 0, 138, 0, 0, 0, 3, 0, 0, 0, 117, 0, 0, 0, 134, 0, 0, 0, 55, 0, 0, 0, 134, 0, 0, 0, 226, 0, 0, 0, 151, 0, 0, 0, 78, 0, 0, 0, 61, 0, 0, 0, 63, 0, 0, 0, 117, 0, 0, 0, 142, 0, 0, 0, 180, 0, 0, 0, 255, 0, 0, 0, 216, 0, 0, 0, 221, 0, 0, 0, 214, 0, 0, 0, 55, 0, 0, 0, 87, 0, 0, 0, 157, 0, 0, 0, 109, 0, 0, 0, 59, 0, 0, 0, 189, 0, 0, 0, 213, 0, 0, 0, 96, 0, 0, 0, 136, 0, 0, 0, 101, 0, 0, 0, 154, 0, 0, 0, 185, 0, 0, 0, 74, 0, 0, 0, 104, 0, 0, 0, 132, 0, 0, 0, 162, 0, 0, 0, 103, 0, 0, 0, 221, 0, 0, 0, -23, 0, 0, 0, 37, 0, 0, 0, 151, 0, 0, 0, 4, 0, 0, 0, 139, 0, 0, 0, 94, 0, 0, 0, 187, 0, 0, 0, 64, 0, 0, 0, 94, 0, 0, 0, 188, 0, 0, 0, 22, 0, 0, 0, 146, 0, 0, 0, 5, 0, 0, 0, 196, 0, 0, 0, 192, 0, 0, 0, 78, 0, 0, 0, 114, 0, 0, 0, 144, 0, 0, 0, 14, 0, 0, 0, 171, 0, 0, 0, 207, 0, 0, 0, 138, 0, 0, 0, 237, 0, 0, 0, 239, 0, 0, 0, 185, 0, 0, 0, 45, 0, 0, 0, 59, 0, 0, 0, 248, 0, 0, 0, 67, 0, 0, 0, 91, 0, 0, 0, 186, 0, 0, 0, 45, 0, 0, 0, 235, 0, 0, 0, 47, 0, 0, 0, 82, 0, 0, 0, 210, 0, 0, 0, 209, 0, 0, 0, 90, -0, 0, 0, 64, 0, 0, 0, 180, 0, 0, 0, 171, 0, 0, 0, 230, 0, 0, 0, 173, 0, 0, 0, 159, 0, 0, 0, 70, 0, 0, 0, 105, 0, 0, 0, 74, 0, 0, 0, 179, 0, 0, 0, 142, 0, 0, 0, 170, 0, 0, 0, 234, 0, 0, 0, 156, 0, 0, 0, 138, 0, 0, 0, 32, 0, 0, 0, 22, 0, 0, 0, 93, 0, 0, 0, 140, 0, 0, 0, 19, 0, 0, 0, 189, 0, 0, 0, 246, 0, 0, 0, 29, 0, 0, 0, 197, 0, 0, 0, 36, 0, 0, 0, 189, 0, 0, 0, 144, 0, 0, 0, 42, 0, 0, 0, 28, 0, 0, 0, 199, 0, 0, 0, 19, 0, 0, 0, 59, 0, 0, 0, 84, 0, 0, 0, 220, 0, 0, 0, 22, 0, 0, 0, 13, 0, 0, 0, 24, -0, 0, 0, 190, 0, 0, 0, 53, 0, 0, 0, 100, 0, 0, 0, 97, 0, 0, 0, 82, 0, 0, 0, 2, 0, 0, 0, 128, 0, 0, 0, 175, 0, 0, 0, 5, 0, 0, 0, 247, 0, 0, 0, 166, 0, 0, 0, 66, 0, 0, 0, 211, 0, 0, 0, 143, 0, 0, 0, 46, 0, 0, 0, 121, 0, 0, 0, 38, 0, 0, 0, 168, 0, 0, 0, 187, 0, 0, 0, 178, 0, 0, 0, 23, 0, 0, 0, 72, 0, 0, 0, 178, 0, 0, 0, 122, 0, 0, 0, 10, 0, 0, 0, 137, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 168, 0, 0, 0, 136, 0, 0, 0, 227, 0, 0, 0, 145, 0, 0, 0, 192, 0, 0, 0, 110, 0, 0, 0, 187, 0, 0, 0, 138, 0, 0, 0, 39, 0, 0, 0, 130, 0, 0, 0, 81, 0, 0, 0, 131, 0, 0, 0, 178, 0, 0, 0, 40, 0, 0, 0, 169, 0, 0, 0, 131, 0, 0, 0, 235, 0, 0, 0, 166, 0, 0, 0, 169, 0, 0, 0, 77, 0, 0, 0, 23, 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, -0, 69, 0, 0, 0, 203, 0, 0, 0, 72, 0, 0, 0, 75, 0, 0, 0, 24, 0, 0, 0, 51, 0, 0, 0, 124, 0, 0, 0, 231, 0, 0, 0, 38, 0, 0, 0, 186, 0, 0, 0, 77, 0, 0, 0, 50, 0, 0, 0, 254, 0, 0, 0, 83, 0, 0, 0, 244, 0, 0, 0, 250, 0, 0, 0, 131, 0, 0, 0, 227, 0, 0, 0, 165, 0, 0, 0, 121, 0, 0, 0, 102, 0, 0, 0, 115, 0, 0, 0, 239, 0, 0, 0, 128, 0, 0, 0, 35, 0, 0, 0, 104, 0, 0, 0, 194, 0, 0, 0, 96, 0, 0, 0, 221, 0, 0, 0, 169, 0, 0, 0, 51, 0, 0, 0, 220, 0, 0, 0, 3, 0, 0, 0, 122, 0, 0, 0, 224, 0, 0, 0, 224, 0, 0, 0, 62, 0, 0, -0, 52, 0, 0, 0, 92, 0, 0, 0, 19, 0, 0, 0, 251, 0, 0, 0, 192, 0, 0, 0, 227, 0, 0, 0, 120, 0, 0, 0, 43, 0, 0, 0, 84, 0, 0, 0, 88, 0, 0, 0, 34, 0, 0, 0, 155, 0, 0, 0, 118, 0, 0, 0, 129, 0, 0, 0, 127, 0, 0, 0, 147, 0, 0, 0, 156, 0, 0, 0, 37, 0, 0, 0, 60, 0, 0, 0, 210, 0, 0, 0]).concat([233, 0, 0, 0, 150, 0, 0, 0, 33, 0, 0, 0, 38, 0, 0, 0, 8, 0, 0, 0, 245, 0, 0, 0, 237, 0, 0, 0, 149, 0, 0, 0, 17, 0, 0, 0, 174, 0, 0, 0, 4, 0, 0, 0, 90, 0, 0, 0, 185, 0, 0, 0, 232, 0, 0, 0, 197, 0, 0, 0, 18, 0, 0, 0, 151, -0, 0, 0, 31, 0, 0, 0, 131, 0, 0, 0, 254, 0, 0, 0, 62, 0, 0, 0, 148, 0, 0, 0, 153, 0, 0, 0, 212, 0, 0, 0, 45, 0, 0, 0, 249, 0, 0, 0, 82, 0, 0, 0, 89, 0, 0, 0, 92, 0, 0, 0, 130, 0, 0, 0, 166, 0, 0, 0, 240, 0, 0, 0, 117, 0, 0, 0, 126, 0, 0, 0, 232, 0, 0, 0, 236, 0, 0, 0, 204, 0, 0, 0, 172, 0, 0, 0, 24, 0, 0, 0, 33, 0, 0, 0, 9, 0, 0, 0, 103, 0, 0, 0, 102, 0, 0, 0, 103, 0, 0, 0, 179, 0, 0, 0, 64, 0, 0, 0, 41, 0, 0, 0, 209, 0, 0, 0, 203, 0, 0, 0, 27, 0, 0, 0, 8, 0, 0, 0, 158, 0, 0, 0, 156, 0, 0, 0, 183, -0, 0, 0, 83, 0, 0, 0, 185, 0, 0, 0, 59, 0, 0, 0, 113, 0, 0, 0, 8, 0, 0, 0, 149, 0, 0, 0, 18, 0, 0, 0, 26, 0, 0, 0, 88, 0, 0, 0, 175, 0, 0, 0, 126, 0, 0, 0, 130, 0, 0, 0, 82, 0, 0, 0, 67, 0, 0, 0, 79, 0, 0, 0, 17, 0, 0, 0, 57, 0, 0, 0, 244, 0, 0, 0, 147, 0, 0, 0, 26, 0, 0, 0, 38, 0, 0, 0, 5, 0, 0, 0, 110, 0, 0, 0, 68, 0, 0, 0, 163, 0, 0, 0, 249, 0, 0, 0, 100, 0, 0, 0, 175, 0, 0, 0, 231, 0, 0, 0, 109, 0, 0, 0, 125, 0, 0, 0, 223, 0, 0, 0, 30, 0, 0, 0, 172, 0, 0, 0, 4, 0, 0, 0, 234, 0, 0, 0, 59, 0, 0, -0, 95, 0, 0, 0, 155, 0, 0, 0, 232, 0, 0, 0, 36, 0, 0, 0, 157, 0, 0, 0, 14, 0, 0, 0, 229, 0, 0, 0, 46, 0, 0, 0, 62, 0, 0, 0, 223, 0, 0, 0, 169, 0, 0, 0, 247, 0, 0, 0, 212, 0, 0, 0, 80, 0, 0, 0, 113, 0, 0, 0, 240, 0, 0, 0, 120, 0, 0, 0, 62, 0, 0, 0, 168, 0, 0, 0, 56, 0, 0, 0, 194, 0, 0, 0, 87, 0, 0, 0, 86, 0, 0, 0, 66, 0, 0, 0, 154, 0, 0, 0, 177, 0, 0, 0, 226, 0, 0, 0, 248, 0, 0, 0, 69, 0, 0, 0, 170, 0, 0, 0, 17, 0, 0, 0, 72, 0, 0, 0, 95, 0, 0, 0, 23, 0, 0, 0, 196, 0, 0, 0, 84, 0, 0, 0, 39, 0, 0, 0, -220, 0, 0, 0, 93, 0, 0, 0, 170, 0, 0, 0, 221, 0, 0, 0, 65, 0, 0, 0, 188, 0, 0, 0, 223, 0, 0, 0, 129, 0, 0, 0, 185, 0, 0, 0, 83, 0, 0, 0, 238, 0, 0, 0, 82, 0, 0, 0, 195, 0, 0, 0, 241, 0, 0, 0, 167, 0, 0, 0, 109, 0, 0, 0, 179, 0, 0, 0, 95, 0, 0, 0, 146, 0, 0, 0, 111, 0, 0, 0, 204, 0, 0, 0, 145, 0, 0, 0, 184, 0, 0, 0, 149, 0, 0, 0, 5, 0, 0, 0, 223, 0, 0, 0, 60, 0, 0, 0, 100, 0, 0, 0, 87, 0, 0, 0, 57, 0, 0, 0, 97, 0, 0, 0, 81, 0, 0, 0, 173, 0, 0, 0, 140, 0, 0, 0, 56, 0, 0, 0, 123, 0, 0, 0, 200, 0, 0, -0, 222, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 190, 0, 0, 0, 161, 0, 0, 0, 176, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 36, 0, 0, 0, 29, 0, 0, 0, 138, 0, 0, 0, 103, 0, 0, 0, 32, 0, 0, 0, 238, 0, 0, 0, 66, 0, 0, 0, 235, 0, 0, 0, 56, 0, 0, 0, 237, -0, 0, 0, 11, 0, 0, 0, 139, 0, 0, 0, 205, 0, 0, 0, 70, 0, 0, 0, 157, 0, 0, 0, 94, 0, 0, 0, 107, 0, 0, 0, 30, 0, 0, 0, 36, 0, 0, 0, 157, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 26, 0, 0, 0, 204, 0, 0, 0, 5, 0, 0, 0, 78, 0, 0, 0, 146, 0, 0, 0, 56, 0, 0, 0, 225, 0, 0, 0, 31, 0, 0, 0, 80, 0, 0, 0, 78, 0, 0, 0, 238, 0, 0, 0, 28, 0, 0, 0, 145, 0, 0, 0, 230, 0, 0, 0, 17, 0, 0, 0, 189, 0, 0, 0, 142, 0, 0, 0, 85, 0, 0, 0, 26, 0, 0, 0, 24, 0, 0, 0, 117, 0, 0, 0, 102, 0, 0, 0, 175, 0, 0, 0, 77, 0, 0, 0, 123, 0, 0, -0, 15, 0, 0, 0, 174, 0, 0, 0, 109, 0, 0, 0, 133, 0, 0, 0, 202, 0, 0, 0, 130, 0, 0, 0, 88, 0, 0, 0, 33, 0, 0, 0, 156, 0, 0, 0, 24, 0, 0, 0, 224, 0, 0, 0, 237, 0, 0, 0, 236, 0, 0, 0, 34, 0, 0, 0, 128, 0, 0, 0, 47, 0, 0, 0, 104, 0, 0, 0, 59, 0, 0, 0, 10, 0, 0, 0, 57, 0, 0, 0, 29, 0, 0, 0, 106, 0, 0, 0, 21, 0, 0, 0, 87, 0, 0, 0, 252, 0, 0, 0, 240, 0, 0, 0, 99, 0, 0, 0, 84, 0, 0, 0, 219, 0, 0, 0, 57, 0, 0, 0, 219, 0, 0, 0, 232, 0, 0, 0, 92, 0, 0, 0, 100, 0, 0, 0, 255, 0, 0, 0, 160, 0, 0, 0, 9, 0, 0, 0, -79, 0, 0, 0, 59, 0, 0, 0, 183, 0, 0, 0, 50, 0, 0, 0, 96, 0, 0, 0, 153, 0, 0, 0, 148, 0, 0, 0, 253, 0, 0, 0, 148, 0, 0, 0, 130, 0, 0, 0, 45, 0, 0, 0, 36, 0, 0, 0, 246, 0, 0, 0, 90, 0, 0, 0, 68, 0, 0, 0, 241, 0, 0, 0, 85, 0, 0, 0, 44, 0, 0, 0, 219, 0, 0, 0, 234, 0, 0, 0, 124, 0, 0, 0, 132, 0, 0, 0, 124, 0, 0, 0, 1, 0, 0, 0, 172, 0, 0, 0, 227, 0, 0, 0, 253, 0, 0, 0, 201, 0, 0, 0, 39, 0, 0, 0, 193, 0, 0, 0, 90, 0, 0, 0, 185, 0, 0, 0, 222, 0, 0, 0, 79, 0, 0, 0, 90, 0, 0, 0, 144, 0, 0, 0, 221, 0, 0, 0, -198, 0, 0, 0, 103, 0, 0, 0, 170, 0, 0, 0, 111, 0, 0, 0, 138, 0, 0, 0, 58, 0, 0, 0, 120, 0, 0, 0, 82, 0, 0, 0, 135, 0, 0, 0, 201, 0, 0, 0, 151, 0, 0, 0, 99, 0, 0, 0, 177, 0, 0, 0, 221, 0, 0, 0, 84, 0, 0, 0, 95, 0, 0, 0, 193, 0, 0, 0, 248, 0, 0, 0, 241, 0, 0, 0, 6, 0, 0, 0, 166, 0, 0, 0, 168, 0, 0, 0, 163, 0, 0, 0, 136, 0, 0, 0, 130, 0, 0, 0, 212, 0, 0, 0, 203, 0, 0, 0, 166, 0, 0, 0, 25, 0, 0, 0, 221, 0, 0, 0, 209, 0, 0, 0, 17, 0, 0, 0, 135, 0, 0, 0, 8, 0, 0, 0, 23, 0, 0, 0, 76, 0, 0, 0, 55, 0, 0, -0, 42, 0, 0, 0, 161, 0, 0, 0, 12, 0, 0, 0, 243, 0, 0, 0, 8, 0, 0, 0, 67, 0, 0, 0, 217, 0, 0, 0, 36, 0, 0, 0, 30, 0, 0, 0, 131, 0, 0, 0, 167, 0, 0, 0, 223, 0, 0, 0, 145, 0, 0, 0, 202, 0, 0, 0, 189, 0, 0, 0, 105, 0, 0, 0, 71, 0, 0, 0, 141, 0, 0, 0, 27, 0, 0, 0, 226, 0, 0, 0, 185, 0, 0, 0, 78, 0, 0, 0, 181, 0, 0, 0, 225, 0, 0, 0, 118, 0, 0, 0, 179, 0, 0, 0, 28, 0, 0, 0, 147, 0, 0, 0, 3, 0, 0, 0, 206, 0, 0, 0, 95, 0, 0, 0, 179, 0, 0, 0, 90, 0, 0, 0, 29, 0, 0, 0, 218, 0, 0, 0, 228, 0, 0, 0, 97, 0, 0, -0, 3, 0, 0, 0, 80, 0, 0, 0, 169, 0, 0, 0, 139, 0, 0, 0, 104, 0, 0, 0, 24, 0, 0, 0, 239, 0, 0, 0, 178, 0, 0, 0, 28, 0, 0, 0, 132, 0, 0, 0, 59, 0, 0, 0, 162, 0, 0, 0, 68, 0, 0, 0, 149, 0, 0, 0, 163, 0, 0, 0, 4, 0, 0, 0, 59, 0, 0, 0, 214, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 118, 0, 0, 0, 66, 0, 0, 0, 103, 0, 0, 0, 2, 0, 0, 0, 125, 0, 0, 0, 133, 0, 0, 0, 86, 0, 0, 0, 206, 0, 0, 0, 114, 0, 0, 0, 14, 0, 0, 0, 41, 0, 0, 0, 132, 0, 0, 0, 178, 0, 0, 0, 125, 0, 0, 0, 210, 0, 0, 0, 69, 0, 0, 0, -190, 0, 0, 0, 87, 0, 0, 0, 6, 0, 0, 0, 237, 0, 0, 0, 127, 0, 0, 0, 207, 0, 0, 0, 237, 0, 0, 0, 205, 0, 0, 0, 239, 0, 0, 0, 25, 0, 0, 0, 214, 0, 0, 0, 188, 0, 0, 0, 21, 0, 0, 0, 121, 0, 0, 0, 100, 0, 0, 0, 210, 0, 0, 0, 24, 0, 0, 0, 227, 0, 0, 0, 32, 0, 0, 0, 103, 0, 0, 0, 58, 0, 0, 0, 84, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 253, 0, 0, 0, 4, 0, 0, 0, 197, 0, 0, 0, 251, 0, 0, 0, 153, 0, 0, 0, 231, 0, 0, 0, 232, 0, 0, 0, 251, 0, 0, 0, 140, 0, 0, 0, 225, 0, 0, 0, 66, 0, 0, 0, 3, 0, 0, 0, 239, 0, 0, 0, 157, 0, 0, 0, 217, 0, 0, 0, 158, 0, 0, 0, 77, 0, 0, 0, 247, 0, 0, 0, 128, 0, 0, 0, 207, 0, 0, 0, 46, 0, 0, 0, 204, 0, 0, 0, 155, 0, 0, 0, 69, 0, 0, 0, 201, 0, 0, 0, 123, 0, 0, 0, 122, 0, 0, 0, 188, 0, 0, 0, 55, 0, 0, 0, 168, 0, 0, 0, -82, 0, 0, 0, 150, 0, 0, 0, 17, 0, 0, 0, 65, 0, 0, 0, 138, 0, 0, 0, 71, 0, 0, 0, 145, 0, 0, 0, 254, 0, 0, 0, 182, 0, 0, 0, 218, 0, 0, 0, 122, 0, 0, 0, 84, 0, 0, 0, 99, 0, 0, 0, 209, 0, 0, 0, 20, 0, 0, 0, 53, 0, 0, 0, 5, 0, 0, 0, 134, 0, 0, 0, 140, 0, 0, 0, 169, 0, 0, 0, 54, 0, 0, 0, 63, 0, 0, 0, 242, 0, 0, 0, 133, 0, 0, 0, 84, 0, 0, 0, 78, 0, 0, 0, 146, 0, 0, 0, 216, 0, 0, 0, 133, 0, 0, 0, 1, 0, 0, 0, 70, 0, 0, 0, 214, 0, 0, 0, 80, 0, 0, 0, 83, 0, 0, 0, 205, 0, 0, 0, 243, 0, 0, 0, 134, 0, 0, 0, 64, -0, 0, 0, 230, 0, 0, 0, 57, 0, 0, 0, 66, 0, 0, 0, 149, 0, 0, 0, 214, 0, 0, 0, 203, 0, 0, 0, 69, 0, 0, 0, 26, 0, 0, 0, 32, 0, 0, 0, 200, 0, 0, 0, 69, 0, 0, 0, 75, 0, 0, 0, 50, 0, 0, 0, 105, 0, 0, 0, 4, 0, 0, 0, 177, 0, 0, 0, 175, 0, 0, 0, 32, 0, 0, 0, 70, 0, 0, 0, 199, 0, 0, 0, 107, 0, 0, 0, 35, 0, 0, 0, 91, 0, 0, 0, 105, 0, 0, 0, 238, 0, 0, 0, 48, 0, 0, 0, 63, 0, 0, 0, 112, 0, 0, 0, 131, 0, 0, 0, 71, 0, 0, 0, 192, 0, 0, 0, 219, 0, 0, 0, 85, 0, 0, 0, 8, 0, 0, 0, 168, 0, 0, 0, 123, 0, 0, 0, 24, 0, 0, -0, 109, 0, 0, 0, 245, 0, 0, 0, 4, 0, 0, 0, 90, 0, 0, 0, 32, 0, 0, 0, 12, 0, 0, 0, 74, 0, 0, 0, 140, 0, 0, 0, 96, 0, 0, 0, 174, 0, 0, 0, 174, 0, 0, 0, 15, 0, 0, 0, 100, 0, 0, 0, 85, 0, 0, 0, 85, 0, 0, 0, 46, 0, 0, 0, 213, 0, 0, 0, 29, 0, 0, 0, 83, 0, 0, 0, 49, 0, 0, 0, 66, 0, 0, 0, 65, 0, 0, 0, 202, 0, 0, 0, 252, 0, 0, 0, 136, 0, 0, 0, 107, 0, 0, 0, 150, 0, 0, 0, 120, 0, 0, 0, 10, 0, 0, 0, 139, 0, 0, 0, 131, 0, 0, 0, 220, 0, 0, 0, 188, 0, 0, 0, 175, 0, 0, 0, 64, 0, 0, 0, 182, 0, 0, 0, 141, 0, 0, 0, -127, 0, 0, 0, 239, 0, 0, 0, 180, 0, 0, 0, 209, 0, 0, 0, 63, 0, 0, 0, 204, 0, 0, 0, 162, 0, 0, 0, 116, 0, 0, 0, 201, 0, 0, 0, 194, 0, 0, 0, 146, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 171, 0, 0, 0, 219, 0, 0, 0, 191, 0, 0, 0, 79, 0, 0, 0, 147, 0, 0, 0, 28, 0, 0, 0, 6, 0, 0, 0, 45, 0, 0, 0, 102, 0, 0, 0, 101, 0, 0, 0, 2, 0, 0, 0, 164, 0, 0, 0, 151, 0, 0, 0, 24, 0, 0, 0, 253, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 171, 0, 0, 0, 3, 0, 0, 0, 236, 0, 0, 0, 206, 0, 0, 0, 193, 0, 0, 0, 191, 0, 0, 0, 55, 0, 0, 0, -248, 0, 0, 0, 19, 0, 0, 0, 83, 0, 0, 0, 165, 0, 0, 0, 229, 0, 0, 0, 12, 0, 0, 0, 58, 0, 0, 0, 168, 0, 0, 0, 85, 0, 0, 0, 185, 0, 0, 0, 255, 0, 0, 0, 104, 0, 0, 0, 228, 0, 0, 0, 230, 0, 0, 0, 109, 0, 0, 0, 48, 0, 0, 0, 125, 0, 0, 0, 48, 0, 0, 0, 53, 0, 0, 0, 194, 0, 0, 0, 120, 0, 0, 0, 135, 0, 0, 0, 249, 0, 0, 0, 252, 0, 0, 0, 107, 0, 0, 0, 90, 0, 0, 0, 195, 0, 0, 0, 183, 0, 0, 0, 101, 0, 0, 0, 216, 0, 0, 0, 46, 0, 0, 0, 199, 0, 0, 0, 165, 0, 0, 0, 12, 0, 0, 0, 198, 0, 0, 0, 220, 0, 0, 0, 18, 0, 0, -0, 170, 0, 0, 0, 214, 0, 0, 0, 79, 0, 0, 0, 197, 0, 0, 0, 56, 0, 0, 0, 188, 0, 0, 0, 14, 0, 0, 0, 226, 0, 0, 0, 60, 0, 0, 0, 118, 0, 0, 0, 134, 0, 0, 0, 56, 0, 0, 0, 242, 0, 0, 0, 123, 0, 0, 0, 44, 0, 0, 0, 22, 0, 0, 0, 120, 0, 0, 0, 141, 0, 0, 0, 245, 0, 0, 0, 164, 0, 0, 0, 21, 0, 0, 0, 218, 0, 0, 0, 219, 0, 0, 0, 38, 0, 0, 0, 133, 0, 0, 0, 160, 0, 0, 0, 86, 0, 0, 0, 221, 0, 0, 0, 29, 0, 0, 0, 227, 0, 0, 0, 179, 0, 0, 0, 253, 0, 0, 0, 64, 0, 0, 0, 239, 0, 0, 0, 242, 0, 0, 0, 217, 0, 0, 0, 161, 0, -0, 0, 179, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 73, 0, 0, 0, 14, 0, 0, 0, 230, 0, 0, 0, 88, 0, 0, 0, 16, 0, 0, 0, 122, 0, 0, 0, 82, 0, 0, 0, 218, 0, 0, 0, 181, 0, 0, 0, 125, 0, 0, 0, 55, 0, 0, 0, 106, 0, 0, 0, 62, 0, 0, 0, 161, 0, 0, 0, 120, -0, 0, 0, 206, 0, 0, 0, 199, 0, 0, 0, 28, 0, 0, 0, 36, 0, 0, 0, 35, 0, 0, 0, 219, 0, 0, 0, 125, 0, 0, 0, 251, 0, 0, 0, 140, 0, 0, 0, 141, 0, 0, 0, 220, 0, 0, 0, 48, 0, 0, 0, 103, 0, 0, 0, 105, 0, 0, 0, 117, 0, 0, 0, 59, 0, 0, 0, 169, 0, 0, 0, 234, 0, 0, 0, 109, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 96, 0, 0, 0, 244, 0, 0, 0, 96, 0, 0, 0, 135, 0, 0, 0, 25, 0, 0, 0, 68, 0, 0, 0, 140, 0, 0, 0, 74, 0, 0, 0, 139, 0, 0, 0, 62, 0, 0, 0, 251, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 166, 0, -0, 0, 158, 0, 0, 0, 159, 0, 0, 0, 239, 0, 0, 0, 207, 0, 0, 0, 217, 0, 0, 0, 210, 0, 0, 0, 76, 0, 0, 0, 116, 0, 0, 0, 49, 0, 0, 0, 208, 0, 0, 0, 52, 0, 0, 0, 164, 0, 0, 0, 235, 0, 0, 0, 4, 0, 0, 0, 164, 0, 0, 0, 140, 0, 0, 0, 143, 0, 0, 0, 113, 0, 0, 0, 39, 0, 0, 0, 149, 0, 0, 0, 133, 0, 0, 0, 93, 0, 0, 0, 85, 0, 0, 0, 75, 0, 0, 0, 177, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 200, 0, 0, 0, 174, 0, 0, 0, 106, 0, 0, 0, 125, 0, 0, 0, 162, 0, 0, 0, 33, 0, 0, 0, 202, 0, 0, 0, 206, 0, 0, 0, 56, 0, 0, 0, 171, -0, 0, 0, 15, 0, 0, 0, 208, 0, 0, 0, 213, 0, 0, 0, 43, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 103, 0, 0, 0, 12, 0, 0, 0, 241, 0, 0, 0, 58, 0, 0, 0, 154, 0, 0, 0, 234, 0, 0, 0, 9, 0, 0, 0, 57, 0, 0, 0, 239, 0, 0, 0, 209, 0, 0, 0, 48, 0, 0, 0, 188, 0, 0, 0, 51, 0, 0, 0, 186, 0, 0, 0, 177, 0, 0, 0, 106, 0, 0, 0, 197, 0, 0, 0, 39, 0, 0, 0, 8, 0, 0, 0, 127, 0, 0, 0, 84, 0, 0, 0, 128, 0, 0, 0, 61, 0, 0, 0, 171, 0, 0, 0, 246, 0, 0, 0, 21, 0, 0, 0, 122, 0, 0, 0, 194, 0, 0, 0, 64, 0, 0, 0, 115, 0, -0, 0, 114, 0, 0, 0, 132, 0, 0, 0, 86, 0, 0, 0, 130, 0, 0, 0, 182, 0, 0, 0, 18, 0, 0, 0, 112, 0, 0, 0, 127, 0, 0, 0, 247, 0, 0, 0, 240, 0, 0, 0, 189, 0, 0, 0, 91, 0, 0, 0, 169, 0, 0, 0, 213, 0, 0, 0, 197, 0, 0, 0, 95, 0, 0, 0, 89, 0, 0, 0, 191, 0, 0, 0, 127, 0, 0, 0, 179, 0, 0, 0, 85, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 201, 0, 0, 0, 68, 0, 0, 0, 85, 0, 0, 0, 135, 0, 0, 0, 143, 0, 0, 0, 150, 0, 0, 0, 152, 0, 0, 0, 100, 0, 0, 0, 109, 0, 0, 0, 21, 0, 0, 0, 176, 0, 0, 0, 139, 0, 0, 0, 170, 0, 0, 0, 30, -0, 0, 0, 236, 0, 0, 0, 199, 0, 0, 0, 165, 0, 0, 0, 143, 0, 0, 0, 31, 0, 0, 0, 146, 0, 0, 0, 4, 0, 0, 0, 198, 0, 0, 0, 5, 0, 0, 0, 246, 0, 0, 0, 223, 0, 0, 0, 161, 0, 0, 0, 204, 0, 0, 0, 31, 0, 0, 0, 129, 0, 0, 0, 245, 0, 0, 0, 14, 0, 0, 0, 156, 0, 0, 0, 87, 0, 0, 0, 220, 0, 0, 0, 227, 0, 0, 0, 187, 0, 0, 0, 6, 0, 0, 0, 135, 0, 0, 0, 30, 0, 0, 0, 254, 0, 0, 0, 35, 0, 0, 0, 108, 0, 0, 0, 216, 0, 0, 0, 43, 0, 0, 0, 91, 0, 0, 0, 22, 0, 0, 0, 234, 0, 0, 0, 32, 0, 0, 0, 241, 0, 0, 0, 211, 0, 0, 0, 104, -0, 0, 0, 143, 0, 0, 0, 174, 0, 0, 0, 91, 0, 0, 0, 208, 0, 0, 0, 169, 0, 0, 0, 26, 0, 0, 0, 25, 0, 0, 0, 168, 0, 0, 0, 54, 0, 0, 0, 251, 0, 0, 0, 43, 0, 0, 0, 87, 0, 0, 0, 136, 0, 0, 0, 125, 0, 0, 0, 144, 0, 0, 0, 213, 0, 0, 0, 166, 0, 0, 0, 243, 0, 0, 0, 220, 0, 0, 0, 56, 0, 0, 0, 137, 0, 0, 0, 78, 0, 0, 0, 31, 0, 0, 0, 204, 0, 0, 0, 25, 0, 0, 0, 218, 0, 0, 0, 155, 0, 0, 0, 59, 0, 0, 0, 67, 0, 0, 0, 72, 0, 0, 0, 33, 0, 0, 0, 46, 0, 0, 0, 35, 0, 0, 0, 77, 0, 0, 0, 61, 0, 0, 0, 174, 0, 0, 0, 248, 0, -0, 0, 140, 0, 0, 0, 252, 0, 0, 0, 221, 0, 0, 0, 166, 0, 0, 0, 116, 0, 0, 0, 55, 0, 0, 0, 101, 0, 0, 0, 202, 0, 0, 0, 238, 0, 0, 0, 26, 0, 0, 0, 25, 0, 0, 0, 142, 0, 0, 0, 159, 0, 0, 0, 100, 0, 0, 0, 111, 0, 0, 0, 12, 0, 0, 0, 139, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 185, 0, 0, 0, 194, 0, 0, 0, 240, 0, 0, 0, 114, 0, 0, 0, 184, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 204, 0, 0, 0, 141, 0, 0, 0, 60, 0, 0, 0, 111, 0, 0, 0, 37, 0, 0, 0, 237, 0, 0, 0, 244, 0, 0, 0, 70, 0, 0, 0, 46, 0, 0, 0, 12, 0, 0, 0, 96, 0, 0, 0, 15, 0, 0, 0, 226, 0, 0, 0, 132, 0, 0, 0, 52, 0, 0, 0, 85, 0, 0, 0, 137, 0, 0, 0, 89, 0, 0, 0, 52, 0, 0, 0, 27, 0, 0, 0, 245, 0, 0, 0, 141, 0, 0, 0, 254, 0, 0, 0, 8, 0, 0, 0, 248, 0, 0, 0, 171, 0, 0, 0, 147, 0, 0, 0, 188, 0, 0, -0, 68, 0, 0, 0, 186, 0, 0, 0, 27, 0, 0, 0, 117, 0, 0, 0, 75, 0, 0, 0, 73, 0, 0, 0, 111, 0, 0, 0, 208, 0, 0, 0, 84, 0, 0, 0, 46, 0, 0, 0, 99, 0, 0, 0, 186, 0, 0, 0, 181, 0, 0, 0, 234, 0, 0, 0, 237, 0, 0, 0, 50, 0, 0, 0, 20, 0, 0, 0, 201, 0, 0, 0, 148, 0, 0, 0, 216, 0, 0, 0, 197, 0, 0, 0, 206, 0, 0, 0, 244, 0, 0, 0, 16, 0, 0, 0, 104, 0, 0, 0, 224, 0, 0, 0, 56, 0, 0, 0, 39, 0, 0, 0, 116, 0, 0, 0, 28, 0, 0, 0, 20, 0, 0, 0, 155, 0, 0, 0, 212, 0, 0, 0, 100, 0, 0, 0, 97, 0, 0, 0, 113, 0, 0, 0, 90, 0, 0, -0, 182, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 79, 0, 0, 0, 247, 0, 0, 0, 142, 0, 0, 0, 186, 0, 0, 0, 165, 0, 0, 0, 72, 0, 0, 0, 154, 0, 0, 0, 199, 0, 0, 0, 250, 0, 0, 0, 154, 0, 0, 0, 240, 0, 0, 0, 180, 0, 0, 0, 98, 0, 0, 0, 173, 0, 0, 0, 242, 0, 0, 0, 94, 0, 0, 0, 204, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 26, 0, 0, 0, 245, 0, 0, 0, 118, 0, 0, 0, 253, 0, 0, 0, 228, 0, 0, 0, 175, 0, 0, 0, 185, 0, 0, 0, 3, 0, 0, 0, 89, 0, 0, 0, 206, 0, 0, 0, 99, 0, 0, 0, 210, 0, 0, 0, 59, 0, 0, 0, 31, 0, 0, 0, 205, 0, 0, -0, 33, 0, 0, 0, 12, 0, 0, 0, 173, 0, 0, 0, 68, 0, 0, 0, 165, 0, 0, 0, 151, 0, 0, 0, 172, 0, 0, 0, 128, 0, 0, 0, 17, 0, 0, 0, 2, 0, 0, 0, 155, 0, 0, 0, 12, 0, 0, 0, 229, 0, 0, 0, 139, 0, 0, 0, 205, 0, 0, 0, 251, 0, 0, 0, 121, 0, 0, 0, 119, 0, 0, 0, 21, 0, 0, 0, 190, 0, 0, 0, 154, 0, 0, 0, 13, 0, 0, 0, 186, 0, 0, 0, 56, 0, 0, 0, 114, 0, 0, 0, 32, 0, 0, 0, 138, 0, 0, 0, 245, 0, 0, 0, 190, 0, 0, 0, 89, 0, 0, 0, 147, 0, 0, 0, 121, 0, 0, 0, 183, 0, 0, 0, 246, 0, 0, 0, 106, 0, 0, 0, 12, 0, 0, 0, 56, 0, -0, 0, 39, 0, 0, 0, 26, 0, 0, 0, 96, 0, 0, 0, 244, 0, 0, 0, 134, 0, 0, 0, 59, 0, 0, 0, 171, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 206, 0, 0, 0, 33, 0, 0, 0, 125, 0, 0, 0, 108, 0, 0, 0, 186, 0, 0, 0, 20, 0, 0, 0, 197, 0, 0, 0, 234, 0, 0, 0, 18, 0, 0, 0, 158, 0, 0, 0, 46, 0, 0, 0, 130, 0, 0, 0, 99, 0, 0, 0, 206, 0, 0, 0, 155, 0, 0, 0, 74, 0, 0, 0, 231, 0, 0, 0, 29, 0, 0, 0, 236, 0, 0, 0, 241, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 28, 0, 0, 0, 244, 0, 0, 0, 208, 0, 0, 0, 105, 0, 0, 0, 21, 0, 0, -0, 66, 0, 0, 0, 157, 0, 0, 0, 163, 0, 0, 0, 63, 0, 0, 0, 14, 0, 0, 0, 191, 0, 0, 0, 233, 0, 0, 0, 92, 0, 0, 0, 228, 0, 0, 0, 13, 0, 0, 0, 244, 0, 0, 0, 189, 0, 0, 0, 238, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 237, 0, 0, 0, 203, 0, 0, 0, 18, 0, 0, 0, 134, 0, 0, 0, 173, 0, 0, 0, 212, 0, 0, 0, 47, 0, 0, 0, 144, 0, 0, 0, 55, 0, 0, 0, 50, 0, 0, 0, 195, 0, 0, 0, 11, 0, 0, 0, 115, 0, 0, 0, 236, 0, 0, 0, 151, 0, 0, 0, 133, 0, 0, 0, 164, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 118, 0, 0, 0, 53, 0, 0, 0, 254, 0, 0, -0, 117, 0, 0, 0, 221, 0, 0, 0, 113, 0, 0, 0, 17, 0, 0, 0, 164, 0, 0, 0, 136, 0, 0, 0, 159, 0, 0, 0, 62, 0, 0, 0, 83, 0, 0, 0, 105, 0, 0, 0, 59, 0, 0, 0, 27, 0, 0, 0, 224, 0, 0, 0, 247, 0, 0, 0, 186, 0, 0, 0, 155, 0, 0, 0, 173, 0, 0, 0, 78, 0, 0, 0, 129, 0, 0, 0, 95, 0, 0, 0, 181, 0, 0, 0, 92, 0, 0, 0, 174, 0, 0, 0, 190, 0, 0, 0, 103, 0, 0, 0, 134, 0, 0, 0, 55, 0, 0, 0, 52, 0, 0, 0, 142, 0, 0, 0, 7, 0, 0, 0, 50, 0, 0, 0, 69, 0, 0, 0, 74, 0, 0, 0, 103, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 112, 0, 0, 0, 88, 0, 0, 0, 32, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, 0, 178, 0, 0, 0, 200, 0, 0, 0, 155, 0, 0, 0, 88, 0, 0, 0, 197, 0, 0, 0, 177, 0, 0, 0, 235, 0, 0, 0, 45, 0, 0, 0, 74, 0, 0, 0, 222, 0, 0, 0, 130, 0, 0, 0, 140, 0, 0, 0, -242, 0, 0, 0, 210, 0, 0, 0, 20, 0, 0, 0, 184, 0, 0, 0, 112, 0, 0, 0, 97, 0, 0, 0, 78, 0, 0, 0, 115, 0, 0, 0, 214, 0, 0, 0, 11, 0, 0, 0, 107, 0, 0, 0, 13, 0, 0, 0, 48, 0, 0, 0, 129, 0, 0, 0, 252, 0, 0, 0, 85, 0, 0, 0, 92, 0, 0, 0, 191, 0, 0, 0, 167, 0, 0, 0, 196, 0, 0, 0, 189, 0, 0, 0, 226, 0, 0, 0, 240, 0, 0, 0, 75, 0, 0, 0, 143, 0, 0, 0, 233, 0, 0, 0, 125, 0, 0, 0, 153, 0, 0, 0, 250, 0, 0, 0, 211, 0, 0, 0, 171, 0, 0, 0, 188, 0, 0, 0, 199, 0, 0, 0, 131, 0, 0, 0, 43, 0, 0, 0, 4, 0, 0, 0, 127, 0, 0, -0, 12, 0, 0, 0, 25, 0, 0, 0, 67, 0, 0, 0, 3, 0, 0, 0, 61, 0, 0, 0, 7, 0, 0, 0, 202, 0, 0, 0, 64, 0, 0, 0, 249, 0, 0, 0, 200, 0, 0, 0, 190, 0, 0, 0, 140, 0, 0, 0, 22, 0, 0, 0, 129, 0, 0, 0, 57, 0, 0, 0, 150, 0, 0, 0, 246, 0, 0, 0, 23, 0, 0, 0, 88, 0, 0, 0, 200, 0, 0, 0, 48, 0, 0, 0, 88, 0, 0, 0, 251, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 69, 0, 0, 0, 210, 0, 0, 0, 82, 0, 0, 0, 118, 0, 0, 0, 224, 0, 0, 0, 106, 0, 0, 0, 38, 0, 0, 0, 40, 0, 0, 0, 92, 0, 0, 0, 136, 0, 0, 0, 89, 0, 0, 0, 106, 0, 0, 0, 90, -0, 0, 0, 84, 0, 0, 0, 66, 0, 0, 0, 7, 0, 0, 0, 181, 0, 0, 0, 46, 0, 0, 0, 44, 0, 0, 0, 103, 0, 0, 0, 21, 0, 0, 0, 155, 0, 0, 0, 251, 0, 0, 0, 131, 0, 0, 0, 105, 0, 0, 0, 30, 0, 0, 0, 15, 0, 0, 0, 218, 0, 0, 0, 214, 0, 0, 0, 41, 0, 0, 0, 177, 0, 0, 0, 96, 0, 0, 0, 224, 0, 0, 0, 178, 0, 0, 0, 186, 0, 0, 0, 105, 0, 0, 0, 162, 0, 0, 0, 158, 0, 0, 0, 189, 0, 0, 0, 189, 0, 0, 0, 224, 0, 0, 0, 28, 0, 0, 0, 189, 0, 0, 0, 205, 0, 0, 0, 6, 0, 0, 0, 100, 0, 0, 0, 112, 0, 0, 0, 65, 0, 0, 0, 250, 0, 0, 0, 140, -0, 0, 0, 225, 0, 0, 0, 137, 0, 0, 0, 143, 0, 0, 0, 39, 0, 0, 0, 200, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 111, 0, 0, 0, 95, 0, 0, 0, 85, 0, 0, 0, 248, 0, 0, 0, 222, 0, 0, 0, 149, 0, 0, 0, 109, 0, 0, 0, 47, 0, 0, 0, 117, 0, 0, 0, 22, 0, 0, 0, 43, 0, 0, 0, 78, 0, 0, 0, 68, 0, 0, 0, 253, 0, 0, 0, 134, 0, 0, 0, 110, 0, 0, 0, 233, 0, 0, 0, 112, 0, 0, 0, 57, 0, 0, 0, 118, 0, 0, 0, 151, 0, 0, 0, 126, 0, 0, 0, 23, 0, 0, 0, 98, 0, 0, 0, 107, 0, 0, 0, 20, 0, 0, 0, 161, 0, 0, 0, 124, 0, 0, 0, 208, 0, 0, 0, 121, -0, 0, 0, 110, 0, 0, 0, 216, 0, 0, 0, 138, 0, 0, 0, 165, 0, 0, 0, 109, 0, 0, 0, 140, 0, 0, 0, 147, 0, 0, 0, 210, 0, 0, 0, 63, 0, 0, 0, 236, 0, 0, 0, 68, 0, 0, 0, 141, 0, 0, 0, 110, 0, 0, 0, 145, 0, 0, 0, 1, 0, 0, 0, 140, 0, 0, 0, 143, 0, 0, 0, 238, 0, 0, 0, 1, 0, 0, 0, 143, 0, 0, 0, 192, 0, 0, 0, 180, 0, 0, 0, 133, 0, 0, 0, 14, 0, 0, 0, 2, 0, 0, 0, 58, 0, 0, 0, 112, 0, 0, 0, 65, 0, 0, 0, 228, 0, 0, 0, 17, 0, 0, 0, 87, 0, 0, 0, 35, 0, 0, 0, 172, 0, 0, 0, 230, 0, 0, 0, 252, 0, 0, 0, 84, 0, 0, 0, 126, -0, 0, 0, 205, 0, 0, 0, 215, 0, 0, 0, 34, 0, 0, 0, 203, 0, 0, 0, 118, 0, 0, 0, 159, 0, 0, 0, 32, 0, 0, 0, 206, 0, 0, 0, 160, 0, 0, 0, 115, 0, 0, 0, 118, 0, 0, 0, 81, 0, 0, 0, 59, 0, 0, 0, 164, 0, 0, 0, 248, 0, 0, 0, 227, 0, 0, 0, 98, 0, 0, 0, 18, 0, 0, 0, 108, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 38, 0, 0, 0, 13, 0, 0, 0, 111, 0, 0, 0, 72, 0, 0, 0, 127, 0, 0, 0, 58, 0, 0, 0, 1, 0, 0, 0, 237, 0, 0, 0, 197, 0, 0, 0, 150, 0, 0, 0, 176, 0, 0, 0, 31, 0, 0, 0, 79, 0, 0, 0, 168, 0, 0, 0, 2, 0, -0, 0, 98, 0, 0, 0, 39, 0, 0, 0, 138, 0, 0, 0, 80, 0, 0, 0, 141, 0, 0, 0, 154, 0, 0, 0, 139, 0, 0, 0, 82, 0, 0, 0, 15, 0, 0, 0, 30, 0, 0, 0, 207, 0, 0, 0, 65, 0, 0, 0, 56, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 108, 0, 0, 0, 212, 0, 0, 0, -47, 0, 0, 0, 15, 0, 0, 0, 105, 0, 0, 0, 15, 0, 0, 0, 135, 0, 0, 0, 63, 0, 0, 0, 97, 0, 0, 0, 101, 0, 0, 0, 30, 0, 0, 0, 53, 0, 0, 0, 52, 0, 0, 0, 133, 0, 0, 0, 186, 0, 0, 0, 2, 0, 0, 0, 48, 0, 0, 0, 172, 0, 0, 0, 37, 0, 0, 0, 61, 0, 0, 0, 226, 0, 0, 0, 98, 0, 0, 0, 241, 0, 0, 0, 204, 0, 0, 0, 233, 0, 0, 0, 27, 0, 0, 0, 194, 0, 0, 0, 239, 0, 0, 0, 106, 0, 0, 0, 66, 0, 0, 0, 87, 0, 0, 0, 52, 0, 0, 0, 31, 0, 0, 0, 46, 0, 0, 0, 172, 0, 0, 0, 209, 0, 0, 0, 199, 0, 0, 0, 4, 0, 0, 0, 82, 0, 0, 0, 50, 0, -0, 0, 102, 0, 0, 0, 178, 0, 0, 0, 51, 0, 0, 0, 115, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 84, 0, 0, 0, 247, 0, 0, 0, 113, 0, 0, 0, 237, 0, 0, 0, 6, 0, 0, 0, 176, 0, 0, 0, 255, 0, 0, 0, 166, 0, 0, 0, 89, 0, 0, 0, 111, 0, 0, 0, 138, 0, 0, 0, 78, 0, 0, 0, 251, 0, 0, 0, 2, 0, 0, 0, 176, 0, 0, 0, 69, 0, 0, 0, 107, 0, 0, 0, 245, 0, 0, 0, 72, 0, 0, 0, 11, 0, 0, 0, 3, 0, 0, 0, 197, 0, 0, 0, 34, 0, 0, 0, 125, 0, 0, 0, 128, 0, 0, 0, 8, 0, 0, 0, 83, 0, 0, 0, 254, 0, 0, 0, 50, 0, 0, 0, 177, 0, 0, 0, 161, 0, 0, -0, 138, 0, 0, 0, 116, 0, 0, 0, 111, 0, 0, 0, 189, 0, 0, 0, 63, 0, 0, 0, 133, 0, 0, 0, 244, 0, 0, 0, 207, 0, 0, 0, 245, 0, 0, 0, 96, 0, 0, 0, 175, 0, 0, 0, 65, 0, 0, 0, 126, 0, 0, 0, 62, 0, 0, 0, 70, 0, 0, 0, 163, 0, 0, 0, 90, 0, 0, 0, 32, 0, 0, 0, 170, 0, 0, 0, 53, 0, 0, 0, 135, 0, 0, 0, 68, 0, 0, 0, 99, 0, 0, 0, 102, 0, 0, 0, 151, 0, 0, 0, 248, 0, 0, 0, 110, 0, 0, 0, 85, 0, 0, 0, 12, 0, 0, 0, 4, 0, 0, 0, 62, 0, 0, 0, 53, 0, 0, 0, 80, 0, 0, 0, 191, 0, 0, 0, 147, 0, 0, 0, 105, 0, 0, 0, 210, 0, 0, -0, 139, 0, 0, 0, 5, 0, 0, 0, 85, 0, 0, 0, 153, 0, 0, 0, 190, 0, 0, 0, 226, 0, 0, 0, 83, 0, 0, 0, 97, 0, 0, 0, 236, 0, 0, 0, 232, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 50, 0, 0, 0, 179, 0, 0, 0, 16, 0, 0, 0, 69, 0, 0, 0, 2, 0, 0, 0, 105, 0, 0, 0, 89, 0, 0, 0, 46, 0, 0, 0, 151, 0, 0, 0, 217, 0, 0, 0, 100, 0, 0, 0, 248, 0, 0, 0, 219, 0, 0, 0, 37, 0, 0, 0, 128, 0, 0, 0, 220, 0, 0, 0, 196, 0, 0, 0, 213, 0, 0, 0, 98, 0, 0, 0, 60, 0, 0, 0, 237, 0, 0, 0, 101, 0, 0, 0, 145, 0, 0, 0, 173, 0, 0, 0, 209, 0, 0, 0, -87, 0, 0, 0, 129, 0, 0, 0, 148, 0, 0, 0, 170, 0, 0, 0, 161, 0, 0, 0, 41, 0, 0, 0, 252, 0, 0, 0, 104, 0, 0, 0, 221, 0, 0, 0, 181, 0, 0, 0, 125, 0, 0, 0, 171, 0, 0, 0, 90, 0, 0, 0, 33, 0, 0, 0, 65, 0, 0, 0, 83, 0, 0, 0, 187, 0, 0, 0, 23, 0, 0, 0, 121, 0, 0, 0, 13, 0, 0, 0, 209, 0, 0, 0, 168, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 32, 0, 0, 0, 136, 0, 0, 0, 9, 0, 0, 0, 233, 0, 0, 0, 132, 0, 0, 0, 232, 0, 0, 0, 37, 0, 0, 0, 17, 0, 0, 0, 103, 0, 0, 0, 122, 0, 0, 0, 139, 0, 0, 0, 26, 0, 0, 0, 228, 0, 0, 0, -93, 0, 0, 0, 225, 0, 0, 0, 93, 0, 0, 0, 55, 0, 0, 0, 234, 0, 0, 0, 254, 0, 0, 0, 101, 0, 0, 0, 59, 0, 0, 0, 37, 0, 0, 0, 232, 0, 0, 0, 225, 0, 0, 0, 194, 0, 0, 0, 197, 0, 0, 0, 2, 0, 0, 0, 164, 0, 0, 0, 190, 0, 0, 0, 152, 0, 0, 0, 10, 0, 0, 0, 43, 0, 0, 0, 97, 0, 0, 0, 193, 0, 0, 0, 155, 0, 0, 0, 226, 0, 0, 0, 213, 0, 0, 0, 146, 0, 0, 0, 230, 0, 0, 0, 158, 0, 0, 0, 125, 0, 0, 0, 31, 0, 0, 0, 202, 0, 0, 0, 67, 0, 0, 0, 136, 0, 0, 0, 139, 0, 0, 0, 44, 0, 0, 0, 89, 0, 0, 0, 224, 0, 0, 0, 181, 0, 0, -0, 0, 0, 0, 0, 29, 0, 0, 0, 42, 0, 0, 0, 111, 0, 0, 0, 175, 0, 0, 0, 121, 0, 0, 0, 134, 0, 0, 0, 47, 0, 0, 0, 166, 0, 0, 0, 90, 0, 0, 0, 147, 0, 0, 0, 209, 0, 0, 0, 254, 0, 0, 0, 174, 0, 0, 0, 58, 0, 0, 0, 238, 0, 0, 0, 219, 0, 0, 0, 124, 0, 0, 0, 97, 0, 0, 0, 190, 0, 0, 0, 124, 0, 0, 0, 1, 0, 0, 0, 249, 0, 0, 0, 254, 0, 0, 0, 82, 0, 0, 0, 220, 0, 0, 0, 216, 0, 0, 0, 82, 0, 0, 0, 163, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 175, 0, 0, 0, 19, 0, 0, 0, 55, 0, 0, 0, 189, 0, 0, 0, 55, 0, 0, 0, 113, 0, 0, 0, 172, 0, 0, 0, 4, 0, 0, 0, 70, 0, 0, 0, 99, 0, 0, 0, 172, 0, 0, 0, 164, 0, 0, 0, 119, 0, 0, 0, 237, 0, 0, 0, 37, 0, 0, 0, 56, 0, 0, 0, 224, 0, 0, 0, 21, 0, 0, 0, 168, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 206, 0, 0, 0, 81, 0, -0, 0, 1, 0, 0, 0, 169, 0, 0, 0, 188, 0, 0, 0, 15, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0, 4, 0, 0, 0, 137, 0, 0, 0, 249, 0, 0, 0, 128, 0, 0, 0, 7, 0, 0, 0, 207, 0, 0, 0, 63, 0, 0, 0, 179, 0, 0, 0, 233, 0, 0, 0, 231, 0, 0, 0, 69, 0, 0, 0, 68, 0, 0, 0, 61, 0, 0, 0, 42, 0, 0, 0, 124, 0, 0, 0, 233, 0, 0, 0, 228, 0, 0, 0, 22, 0, 0, 0, 92, 0, 0, 0, 94, 0, 0, 0, 101, 0, 0, 0, 28, 0, 0, 0, 199, 0, 0, 0, 125, 0, 0, 0, 198, 0, 0, 0, 122, 0, 0, 0, 251, 0, 0, 0, 67, 0, 0, 0, 238, 0, 0, 0, 37, 0, 0, 0, 118, 0, 0, 0, -70, 0, 0, 0, 114, 0, 0, 0, 2, 0, 0, 0, 162, 0, 0, 0, 237, 0, 0, 0, 244, 0, 0, 0, 143, 0, 0, 0, 107, 0, 0, 0, 11, 0, 0, 0, 62, 0, 0, 0, 235, 0, 0, 0, 53, 0, 0, 0, 26, 0, 0, 0, 213, 0, 0, 0, 126, 0, 0, 0, 219, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 138, 0, 0, 0, 160, 0, 0, 0, 180, 0, 0, 0, 207, 0, 0, 0, 96, 0, 0, 0, 75, 0, 0, 0, 212, 0, 0, 0, 213, 0, 0, 0, 249, 0, 0, 0, 45, 0, 0, 0, 191, 0, 0, 0, 136, 0, 0, 0, 189, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0, 19, 0, 0, 0, 83, 0, 0, 0, 228, 0, 0, 0, -130, 0, 0, 0, 87, 0, 0, 0, 250, 0, 0, 0, 30, 0, 0, 0, 143, 0, 0, 0, 6, 0, 0, 0, 43, 0, 0, 0, 144, 0, 0, 0, 186, 0, 0, 0, 8, 0, 0, 0, 182, 0, 0, 0, 16, 0, 0, 0, 84, 0, 0, 0, 79, 0, 0, 0, 124, 0, 0, 0, 27, 0, 0, 0, 38, 0, 0, 0, 237, 0, 0, 0, 218, 0, 0, 0, 107, 0, 0, 0, 221, 0, 0, 0, 37, 0, 0, 0, 208, 0, 0, 0, 78, 0, 0, 0, 234, 0, 0, 0, 66, 0, 0, 0, 187, 0, 0, 0, 37, 0, 0, 0, 3, 0, 0, 0, 81, 0, 0, 0, 22, 0, 0, 0, 80, 0, 0, 0, 124, 0, 0, 0, 213, 0, 0, 0, 93, 0, 0, 0, 246, 0, 0, 0, 153, 0, 0, 0, 232, -0, 0, 0, 119, 0, 0, 0, 114, 0, 0, 0, 78, 0, 0, 0, 250, 0, 0, 0, 98, 0, 0, 0, 203, 0, 0, 0, 118, 0, 0, 0, 117, 0, 0, 0, 12, 0, 0, 0, 226, 0, 0, 0, 113, 0, 0, 0, 152, 0, 0, 0, 146, 0, 0, 0, 213, 0, 0, 0, 250, 0, 0, 0, 69, 0, 0, 0, 223, 0, 0, 0, 92, 0, 0, 0, 111, 0, 0, 0, 30, 0, 0, 0, 158, 0, 0, 0, 40, 0, 0, 0, 105, 0, 0, 0, 13, 0, 0, 0, 172, 0, 0, 0, 102, 0, 0, 0, 109, 0, 0, 0, 195, 0, 0, 0, 139, 0, 0, 0, 186, 0, 0, 0, 22, 0, 0, 0, 181, 0, 0, 0, 226, 0, 0, 0, 160, 0, 0, 0, 13, 0, 0, 0, 12, 0, 0, 0, -189, 0, 0, 0, 164, 0, 0, 0, 142, 0, 0, 0, 24, 0, 0, 0, 108, 0, 0, 0, 242, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 220, 0, 0, 0, 74, 0, 0, 0, 134, 0, 0, 0, 37, 0, 0, 0, 149, 0, 0, 0, 20, 0, 0, 0, 203, 0, 0, 0, 216, 0, 0, 0, 26, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 151, 0, 0, 0, 165, 0, 0, 0, 219, 0, 0, 0, 139, 0, 0, 0, 45, 0, 0, 0, 170, 0, 0, 0, 66, 0, 0, 0, 17, 0, 0, 0, 9, 0, 0, 0, 242, 0, 0, 0, 147, 0, 0, 0, 187, 0, 0, 0, 217, 0, 0, 0, 6, 0, 0, 0, 132, 0, 0, 0, 78, 0, 0, 0, 17, 0, 0, 0, 168, 0, 0, 0, -160, 0, 0, 0, 37, 0, 0, 0, 43, 0, 0, 0, 166, 0, 0, 0, 95, 0, 0, 0, 174, 0, 0, 0, 196, 0, 0, 0, 180, 0, 0, 0, 76, 0, 0, 0, 200, 0, 0, 0, 171, 0, 0, 0, 199, 0, 0, 0, 59, 0, 0, 0, 2, 0, 0, 0, 238, 0, 0, 0, 201, 0, 0, 0, 41, 0, 0, 0, 15, 0, 0, 0, 223, 0, 0, 0, 17, 0, 0, 0, 133, 0, 0, 0, 237, 0, 0, 0, 206, 0, 0, 0, 13, 0, 0, 0, 98, 0, 0, 0, 44, 0, 0, 0, 143, 0, 0, 0, 75, 0, 0, 0, 249, 0, 0, 0, 4, 0, 0, 0, 233, 0, 0, 0, 6, 0, 0, 0, 114, 0, 0, 0, 29, 0, 0, 0, 55, 0, 0, 0, 32, 0, 0, 0, 80, 0, 0, 0, 201, -0, 0, 0, 20, 0, 0, 0, 235, 0, 0, 0, 236, 0, 0, 0, 57, 0, 0, 0, 167, 0, 0, 0, 151, 0, 0, 0, 43, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 209, 0, 0, 0, 57, 0, 0, 0, 189, 0, 0, 0, 251, 0, 0, 0, 51, 0, 0, 0, 190, 0, 0, 0, 196, 0, 0, 0, 240, 0, -0, 0, 92, 0, 0, 0, 239, 0, 0, 0, 240, 0, 0, 0, 86, 0, 0, 0, 104, 0, 0, 0, 252, 0, 0, 0, 151, 0, 0, 0, 71, 0, 0, 0, 200, 0, 0, 0, 114, 0, 0, 0, 182, 0, 0, 0, 83, 0, 0, 0, 164, 0, 0, 0, 10, 0, 0, 0, 152, 0, 0, 0, 165, 0, 0, 0, 180, 0, 0, 0, 55, 0, 0, 0, 113, 0, 0, 0, 207, 0, 0, 0, 102, 0, 0, 0, 80, 0, 0, 0, 109, 0, 0, 0, 23, 0, 0, 0, 164, 0, 0, 0, 25, 0, 0, 0, 82, 0, 0, 0, 17, 0, 0, 0, 71, 0, 0, 0, 179, 0, 0, 0, 92, 0, 0, 0, 91, 0, 0, 0, 169, 0, 0, 0, 46, 0, 0, 0, 34, 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, -0, 82, 0, 0, 0, 249, 0, 0, 0, 87, 0, 0, 0, 24, 0, 0, 0, 184, 0, 0, 0, 190, 0, 0, 0, 90, 0, 0, 0, 227, 0, 0, 0, 171, 0, 0, 0, 131, 0, 0, 0, 200, 0, 0, 0, 135, 0, 0, 0, 10, 0, 0, 0, 42, 0, 0, 0, 216, 0, 0, 0, 140, 0, 0, 0, 187, 0, 0, 0, 84, 0, 0, 0, 169, 0, 0, 0, 98, 0, 0, 0, 147, 0, 0, 0, 133, 0, 0, 0, 190, 0, 0, 0, 232, 0, 0, 0, 115, 0, 0, 0, 74, 0, 0, 0, 14, 0, 0, 0, 176, 0, 0, 0, 181, 0, 0, 0, 45, 0, 0, 0, 148, 0, 0, 0, 80, 0, 0, 0, 170, 0, 0, 0, 211, 0, 0, 0, 178, 0, 0, 0, 234, 0, 0, 0, 157, 0, -0, 0, 98, 0, 0, 0]).concat([118, 0, 0, 0, 59, 0, 0, 0, 7, 0, 0, 0, 52, 0, 0, 0, 78, 0, 0, 0, 45, 0, 0, 0, 112, 0, 0, 0, 200, 0, 0, 0, 154, 0, 0, 0, 21, 0, 0, 0, 102, 0, 0, 0, 107, 0, 0, 0, 197, 0, 0, 0, 150, 0, 0, 0, 202, 0, 0, 0, 200, 0, 0, 0, 34, 0, 0, 0, 26, 0, 0, 0, 238, 0, 0, 0, 95, 0, 0, 0, 231, 0, 0, 0, 49, 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 131, 0, 0, 0, 8, 0, 0, 0, 99, 0, 0, 0, 206, 0, 0, 0, 185, 0, 0, 0, 50, 0, 0, 0, 68, 0, 0, 0, 88, 0, 0, 0, 93, 0, 0, 0, 58, 0, 0, 0, 155, 0, 0, 0, 228, -0, 0, 0, 4, 0, 0, 0, 213, 0, 0, 0, 239, 0, 0, 0, 56, 0, 0, 0, 239, 0, 0, 0, 75, 0, 0, 0, 221, 0, 0, 0, 25, 0, 0, 0, 77, 0, 0, 0, 194, 0, 0, 0, 23, 0, 0, 0, 117, 0, 0, 0, 161, 0, 0, 0, 104, 0, 0, 0, 205, 0, 0, 0, 195, 0, 0, 0, 198, 0, 0, 0, 3, 0, 0, 0, 68, 0, 0, 0, 227, 0, 0, 0, 120, 0, 0, 0, 9, 0, 0, 0, 145, 0, 0, 0, 71, 0, 0, 0, 63, 0, 0, 0, 15, 0, 0, 0, 228, 0, 0, 0, 146, 0, 0, 0, 88, 0, 0, 0, 250, 0, 0, 0, 125, 0, 0, 0, 31, 0, 0, 0, 32, 0, 0, 0, 148, 0, 0, 0, 88, 0, 0, 0, 94, 0, 0, 0, 188, 0, -0, 0, 25, 0, 0, 0, 2, 0, 0, 0, 111, 0, 0, 0, 32, 0, 0, 0, 214, 0, 0, 0, 216, 0, 0, 0, 145, 0, 0, 0, 84, 0, 0, 0, 167, 0, 0, 0, 243, 0, 0, 0, 32, 0, 0, 0, 75, 0, 0, 0, 52, 0, 0, 0, 6, 0, 0, 0, 250, 0, 0, 0, 48, 0, 0, 0, 200, 0, 0, 0, 111, 0, 0, 0, 20, 0, 0, 0, 16, 0, 0, 0, 101, 0, 0, 0, 116, 0, 0, 0, 19, 0, 0, 0, 78, 0, 0, 0, 240, 0, 0, 0, 105, 0, 0, 0, 38, 0, 0, 0, 206, 0, 0, 0, 207, 0, 0, 0, 144, 0, 0, 0, 244, 0, 0, 0, 208, 0, 0, 0, 197, 0, 0, 0, 200, 0, 0, 0, 100, 0, 0, 0, 38, 0, 0, 0, 162, 0, -0, 0, 80, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, 114, 0, 0, 0, 241, 0, 0, 0, 240, 0, 0, 0, 78, 0, 0, 0, 45, 0, 0, 0, 147, 0, 0, 0, 213, 0, 0, 0, 8, 0, 0, 0, 231, 0, 0, 0, 174, 0, 0, 0, 56, 0, 0, 0, 247, 0, 0, 0, 24, 0, 0, 0, 165, 0, 0, 0, 50, 0, 0, 0, 52, 0, 0, 0, 194, 0, 0, 0, 240, 0, 0, 0, 166, 0, 0, 0, 236, 0, 0, 0, 185, 0, 0, 0, 97, 0, 0, 0, 123, 0, 0, 0, 100, 0, 0, 0, 153, 0, 0, 0, 172, 0, 0, 0, 113, 0, 0, 0, 37, 0, 0, 0, 207, 0, 0, 0, 116, 0, 0, 0, 85, 0, 0, 0, 27, 0, 0, 0, 170, 0, 0, 0, 169, 0, -0, 0, 56, 0, 0, 0, 65, 0, 0, 0, 64, 0, 0, 0, 213, 0, 0, 0, 149, 0, 0, 0, 149, 0, 0, 0, 171, 0, 0, 0, 28, 0, 0, 0, 94, 0, 0, 0, 188, 0, 0, 0, 65, 0, 0, 0, 126, 0, 0, 0, 20, 0, 0, 0, 48, 0, 0, 0, 190, 0, 0, 0, 19, 0, 0, 0, 137, 0, 0, 0, 244, 0, 0, 0, 229, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 192, 0, 0, 0, 194, 0, 0, 0, 150, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 119, 0, 0, 0, 69, 0, 0, 0, 236, 0, 0, 0, 103, 0, 0, 0, 118, 0, 0, 0, 50, 0, 0, 0, 76, 0, 0, 0, 185, 0, 0, 0, 223, 0, 0, 0, 37, 0, 0, 0, 50, 0, 0, 0, 107, 0, 0, 0, 203, 0, 0, 0, 231, 0, 0, 0, 20, 0, 0, 0, 97, 0, 0, 0, 67, 0, 0, 0, 238, 0, 0, 0, 186, 0, 0, 0, 155, 0, 0, 0, 113, 0, 0, 0, 239, 0, 0, 0, 210, 0, 0, 0, 72, 0, 0, 0, 101, 0, 0, 0, 187, 0, 0, 0, 27, 0, 0, 0, 138, 0, 0, -0, 19, 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 132, 0, 0, 0, 173, 0, 0, 0, 12, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 90, 0, 0, 0, 186, 0, 0, 0, 208, 0, 0, 0, 152, 0, 0, 0, 89, 0, 0, 0, 191, 0, 0, 0, 55, 0, 0, 0, 176, 0, 0, 0, 79, 0, 0, 0, 151, 0, 0, 0, 96, 0, 0, 0, 32, 0, 0, 0, 179, 0, 0, 0, 155, 0, 0, 0, 151, 0, 0, 0, 246, 0, 0, 0, 8, 0, 0, 0, 108, 0, 0, 0, 164, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 183, 0, 0, 0, 250, 0, 0, 0, 149, 0, 0, 0, 178, 0, 0, 0, 81, 0, 0, 0, 121, 0, 0, 0, 40, 0, 0, 0, 92, 0, 0, -0, 63, 0, 0, 0, 219, 0, 0, 0, 107, 0, 0, 0, 24, 0, 0, 0, 59, 0, 0, 0, 92, 0, 0, 0, 209, 0, 0, 0, 4, 0, 0, 0, 40, 0, 0, 0, 222, 0, 0, 0, 133, 0, 0, 0, 82, 0, 0, 0, 49, 0, 0, 0, 181, 0, 0, 0, 187, 0, 0, 0, 246, 0, 0, 0, 169, 0, 0, 0, 237, 0, 0, 0, 190, 0, 0, 0, 40, 0, 0, 0, 79, 0, 0, 0, 179, 0, 0, 0, 126, 0, 0, 0, 5, 0, 0, 0, 106, 0, 0, 0, 219, 0, 0, 0, 149, 0, 0, 0, 13, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 213, 0, 0, 0, 197, 0, 0, 0, 195, 0, 0, 0, 154, 0, 0, 0, 10, 0, 0, 0, 208, 0, 0, 0, 49, 0, 0, 0, -62, 0, 0, 0, 7, 0, 0, 0, 54, 0, 0, 0, 142, 0, 0, 0, 192, 0, 0, 0, 138, 0, 0, 0, 98, 0, 0, 0, 177, 0, 0, 0, 202, 0, 0, 0, 214, 0, 0, 0, 14, 0, 0, 0, 30, 0, 0, 0, 157, 0, 0, 0, 239, 0, 0, 0, 171, 0, 0, 0, 152, 0, 0, 0, 77, 0, 0, 0, 187, 0, 0, 0, 108, 0, 0, 0, 5, 0, 0, 0, 224, 0, 0, 0, 228, 0, 0, 0, 93, 0, 0, 0, 189, 0, 0, 0, 87, 0, 0, 0, 204, 0, 0, 0, 33, 0, 0, 0, 39, 0, 0, 0, 206, 0, 0, 0, 253, 0, 0, 0, 169, 0, 0, 0, 148, 0, 0, 0, 142, 0, 0, 0, 225, 0, 0, 0, 171, 0, 0, 0, 73, 0, 0, 0, 224, 0, 0, 0, -70, 0, 0, 0, 38, 0, 0, 0, 161, 0, 0, 0, 168, 0, 0, 0, 140, 0, 0, 0, 161, 0, 0, 0, 153, 0, 0, 0, 29, 0, 0, 0, 180, 0, 0, 0, 39, 0, 0, 0, 109, 0, 0, 0, 45, 0, 0, 0, 200, 0, 0, 0, 57, 0, 0, 0, 48, 0, 0, 0, 94, 0, 0, 0, 55, 0, 0, 0, 82, 0, 0, 0, 196, 0, 0, 0, 110, 0, 0, 0, 169, 0, 0, 0, 133, 0, 0, 0, 244, 0, 0, 0, 231, 0, 0, 0, 176, 0, 0, 0, 21, 0, 0, 0, 51, 0, 0, 0, 132, 0, 0, 0, 27, 0, 0, 0, 20, 0, 0, 0, 26, 0, 0, 0, 2, 0, 0, 0, 217, 0, 0, 0, 59, 0, 0, 0, 173, 0, 0, 0, 15, 0, 0, 0, 67, 0, 0, 0, 108, -0, 0, 0, 234, 0, 0, 0, 62, 0, 0, 0, 15, 0, 0, 0, 126, 0, 0, 0, 218, 0, 0, 0, 221, 0, 0, 0, 107, 0, 0, 0, 76, 0, 0, 0, 127, 0, 0, 0, 110, 0, 0, 0, 212, 0, 0, 0, 107, 0, 0, 0, 191, 0, 0, 0, 15, 0, 0, 0, 71, 0, 0, 0, 159, 0, 0, 0, 124, 0, 0, 0, 86, 0, 0, 0, 124, 0, 0, 0, 67, 0, 0, 0, 145, 0, 0, 0, 28, 0, 0, 0, 187, 0, 0, 0, 78, 0, 0, 0, 114, 0, 0, 0, 62, 0, 0, 0, 100, 0, 0, 0, 171, 0, 0, 0, 160, 0, 0, 0, 160, 0, 0, 0, 223, 0, 0, 0, 180, 0, 0, 0, 216, 0, 0, 0, 135, 0, 0, 0, 58, 0, 0, 0, 189, 0, 0, 0, -168, 0, 0, 0, 72, 0, 0, 0, 201, 0, 0, 0, 184, 0, 0, 0, 239, 0, 0, 0, 46, 0, 0, 0, 173, 0, 0, 0, 111, 0, 0, 0, 132, 0, 0, 0, 79, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 240, 0, 0, 0, 27, 0, 0, 0, 126, 0, 0, 0, 42, 0, 0, 0, 108, 0, 0, 0, 248, 0, 0, 0, 169, 0, 0, 0, 106, 0, 0, 0, 225, 0, 0, 0, 240, 0, 0, 0, 153, 0, 0, 0, 161, 0, 0, 0, 103, 0, 0, 0, 154, 0, 0, 0, 212, 0, 0, 0, 19, 0, 0, 0, 202, 0, 0, 0, 202, 0, 0, 0, 186, 0, 0, 0, 39, 0, 0, 0, 146, 0, 0, 0, 170, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 80, 0, -0, 0, 222, 0, 0, 0, 204, 0, 0, 0, 64, 0, 0, 0, 38, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 62, 0, 0, 0, 242, 0, 0, 0, 178, 0, 0, 0, 144, 0, 0, 0, 206, 0, 0, 0, 219, 0, 0, 0, 100, 0, 0, 0, 62, 0, 0, 0, 3, 0, 0, 0, 221, 0, 0, 0, 55, 0, 0, 0, -54, 0, 0, 0, 84, 0, 0, 0, 112, 0, 0, 0, 118, 0, 0, 0, 36, 0, 0, 0, 181, 0, 0, 0, 105, 0, 0, 0, 3, 0, 0, 0, 252, 0, 0, 0, 160, 0, 0, 0, 43, 0, 0, 0, 116, 0, 0, 0, 178, 0, 0, 0, 5, 0, 0, 0, 14, 0, 0, 0, 204, 0, 0, 0, 216, 0, 0, 0, 31, 0, 0, 0, 106, 0, 0, 0, 31, 0, 0, 0, 25, 0, 0, 0, 94, 0, 0, 0, 96, 0, 0, 0, 105, 0, 0, 0, 88, 0, 0, 0, 134, 0, 0, 0, 160, 0, 0, 0, 49, 0, 0, 0, 189, 0, 0, 0, 50, 0, 0, 0, 233, 0, 0, 0, 44, 0, 0, 0, 92, 0, 0, 0, 210, 0, 0, 0, 133, 0, 0, 0, 186, 0, 0, 0, 64, 0, 0, 0, 100, -0, 0, 0, 168, 0, 0, 0, 116, 0, 0, 0, 248, 0, 0, 0, 14, 0, 0, 0, 28, 0, 0, 0, 179, 0, 0, 0, 169, 0, 0, 0, 105, 0, 0, 0, 232, 0, 0, 0, 30, 0, 0, 0, 64, 0, 0, 0, 100, 0, 0, 0, 153, 0, 0, 0, 119, 0, 0, 0, 108, 0, 0, 0, 50, 0, 0, 0, 79, 0, 0, 0, 253, 0, 0, 0, 187, 0, 0, 0, 92, 0, 0, 0, 187, 0, 0, 0, 141, 0, 0, 0, 100, 0, 0, 0, 102, 0, 0, 0, 74, 0, 0, 0, 113, 0, 0, 0, 31, 0, 0, 0, 121, 0, 0, 0, 163, 0, 0, 0, 173, 0, 0, 0, 141, 0, 0, 0, 249, 0, 0, 0, 212, 0, 0, 0, 236, 0, 0, 0, 207, 0, 0, 0, 103, 0, 0, -0, 112, 0, 0, 0, 250, 0, 0, 0, 5, 0, 0, 0, 74, 0, 0, 0, 15, 0, 0, 0, 110, 0, 0, 0, 175, 0, 0, 0, 135, 0, 0, 0, 10, 0, 0, 0, 111, 0, 0, 0, 198, 0, 0, 0, 54, 0, 0, 0, 110, 0, 0, 0, 108, 0, 0, 0, 140, 0, 0, 0, 36, 0, 0, 0, 9, 0, 0, 0, 96, 0, 0, 0, 190, 0, 0, 0, 38, 0, 0, 0, 210, 0, 0, 0, 76, 0, 0, 0, 94, 0, 0, 0, 23, 0, 0, 0, 202, 0, 0, 0, 95, 0, 0, 0, 29, 0, 0, 0, 204, 0, 0, 0, 135, 0, 0, 0, 232, 0, 0, 0, 66, 0, 0, 0, 106, 0, 0, 0, 203, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 146, 0, 0, 0, 5, 0, 0, 0, -53, 0, 0, 0, 129, 0, 0, 0, 19, 0, 0, 0, 96, 0, 0, 0, 107, 0, 0, 0, 244, 0, 0, 0, 21, 0, 0, 0, 205, 0, 0, 0, 15, 0, 0, 0, 10, 0, 0, 0, 175, 0, 0, 0, 78, 0, 0, 0, 107, 0, 0, 0, 81, 0, 0, 0, 253, 0, 0, 0, 20, 0, 0, 0, 196, 0, 0, 0, 46, 0, 0, 0, 19, 0, 0, 0, 134, 0, 0, 0, 116, 0, 0, 0, 68, 0, 0, 0, 203, 0, 0, 0, 102, 0, 0, 0, 107, 0, 0, 0, 182, 0, 0, 0, 157, 0, 0, 0, 116, 0, 0, 0, 86, 0, 0, 0, 50, 0, 0, 0, 172, 0, 0, 0, 141, 0, 0, 0, 142, 0, 0, 0, 140, 0, 0, 0, 140, 0, 0, 0, 140, 0, 0, 0, 57, 0, 0, 0, -202, 0, 0, 0, 89, 0, 0, 0, 116, 0, 0, 0, 26, 0, 0, 0, 17, 0, 0, 0, 239, 0, 0, 0, 109, 0, 0, 0, 247, 0, 0, 0, 57, 0, 0, 0, 92, 0, 0, 0, 59, 0, 0, 0, 31, 0, 0, 0, 250, 0, 0, 0, 227, 0, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 35, 0, 0, 0, 158, 0, 0, 0, 246, 0, 0, 0, 209, 0, 0, 0, 33, 0, 0, 0, 162, 0, 0, 0, 191, 0, 0, 0, 173, 0, 0, 0, 101, 0, 0, 0, 66, 0, 0, 0, 107, 0, 0, 0, 89, 0, 0, 0, 138, 0, 0, 0, 232, 0, 0, 0, 197, 0, 0, 0, 127, 0, 0, 0, 100, 0, 0, 0, 5, 0, 0, 0, 122, 0, 0, 0, 132, 0, 0, 0, 74, 0, 0, 0, -19, 0, 0, 0, 195, 0, 0, 0, 246, 0, 0, 0, 176, 0, 0, 0, 110, 0, 0, 0, 154, 0, 0, 0, 107, 0, 0, 0, 83, 0, 0, 0, 107, 0, 0, 0, 50, 0, 0, 0, 218, 0, 0, 0, 217, 0, 0, 0, 116, 0, 0, 0, 117, 0, 0, 0, 196, 0, 0, 0, 186, 0, 0, 0, 100, 0, 0, 0, 61, 0, 0, 0, 59, 0, 0, 0, 8, 0, 0, 0, 221, 0, 0, 0, 16, 0, 0, 0, 70, 0, 0, 0, 239, 0, 0, 0, 199, 0, 0, 0, 144, 0, 0, 0, 31, 0, 0, 0, 123, 0, 0, 0, 47, 0, 0, 0, 58, 0, 0, 0, 206, 0, 0, 0, 200, 0, 0, 0, 161, 0, 0, 0, 121, 0, 0, 0, 60, 0, 0, 0, 48, 0, 0, 0, 18, 0, 0, 0, -68, 0, 0, 0, 40, 0, 0, 0, 246, 0, 0, 0, 188, 0, 0, 0, 255, 0, 0, 0, 253, 0, 0, 0, 244, 0, 0, 0, 192, 0, 0, 0, 151, 0, 0, 0, 176, 0, 0, 0, 204, 0, 0, 0, 195, 0, 0, 0, 19, 0, 0, 0, 122, 0, 0, 0, 185, 0, 0, 0, 154, 0, 0, 0, 22, 0, 0, 0, 228, 0, 0, 0, 203, 0, 0, 0, 76, 0, 0, 0, 52, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 78, 0, 0, 0, 211, 0, 0, 0, 45, 0, 0, 0, 9, 0, 0, 0, 51, 0, 0, 0, 14, 0, 0, 0, 210, 0, 0, 0, 13, 0, 0, 0, 190, 0, 0, 0, 62, 0, 0, 0, 231, 0, 0, 0, 228, 0, 0, 0, 170, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 232, 0, 0, 0, 173, 0, 0, 0, 170, 0, 0, 0, 122, 0, 0, 0, 141, 0, 0, 0, 52, 0, 0, 0, 40, 0, 0, 0, 169, 0, 0, 0, 129, 0, 0, 0, 148, 0, 0, 0, 197, 0, 0, 0, 231, 0, 0, 0, 66, 0, 0, 0, 172, 0, 0, 0, 71, 0, 0, 0, 36, -0, 0, 0, 137, 0, 0, 0, 122, 0, 0, 0, 143, 0, 0, 0, 181, 0, 0, 0, 155, 0, 0, 0, 240, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 100, 0, 0, 0, 208, 0, 0, 0, 30, 0, 0, 0, 245, 0, 0, 0, 164, 0, 0, 0, 178, 0, 0, 0, 243, 0, 0, 0, 116, 0, 0, 0, 233, 0, 0, 0, 26, 0, 0, 0, 22, 0, 0, 0, 253, 0, 0, 0, 203, 0, 0, 0, 21, 0, 0, 0, 234, 0, 0, 0, 235, 0, 0, 0, 16, 0, 0, 0, 108, 0, 0, 0, 53, 0, 0, 0, 209, 0, 0, 0, 193, 0, 0, 0, 166, 0, 0, 0, 40, 0, 0, 0, 204, 0, 0, 0, 213, 0, 0, 0, 57, 0, 0, 0, 252, 0, 0, 0, 165, 0, 0, 0, -164, 0, 0, 0, 173, 0, 0, 0, 50, 0, 0, 0, 21, 0, 0, 0, 206, 0, 0, 0, 25, 0, 0, 0, 232, 0, 0, 0, 52, 0, 0, 0, 43, 0, 0, 0, 28, 0, 0, 0, 96, 0, 0, 0, 145, 0, 0, 0, 252, 0, 0, 0, 5, 0, 0, 0, 169, 0, 0, 0, 179, 0, 0, 0, 220, 0, 0, 0, 128, 0, 0, 0, 41, 0, 0, 0, 196, 0, 0, 0, 32, 0, 0, 0, 121, 0, 0, 0, 6, 0, 0, 0, 57, 0, 0, 0, 192, 0, 0, 0, 226, 0, 0, 0, 34, 0, 0, 0, 187, 0, 0, 0, 168, 0, 0, 0, 225, 0, 0, 0, 137, 0, 0, 0, 112, 0, 0, 0, 87, 0, 0, 0, 24, 0, 0, 0, 84, 0, 0, 0, 60, 0, 0, 0, 246, 0, 0, 0, 13, -0, 0, 0, 130, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 135, 0, 0, 0, 150, 0, 0, 0, 6, 0, 0, 0, 57, 0, 0, 0, 227, 0, 0, 0, 248, 0, 0, 0, 179, 0, 0, 0, 149, 0, 0, 0, 229, 0, 0, 0, 215, 0, 0, 0, 38, 0, 0, 0, 191, 0, 0, 0, 9, 0, 0, 0, 90, 0, 0, 0, 148, 0, 0, 0, 249, 0, 0, 0, 28, 0, 0, 0, 99, 0, 0, 0, 43, 0, 0, 0, 140, 0, 0, 0, 45, 0, 0, 0, 154, 0, 0, 0, 139, 0, 0, 0, 132, 0, 0, 0, 242, 0, 0, 0, 86, 0, 0, 0, 251, 0, 0, 0, 173, 0, 0, 0, 46, 0, 0, 0, 127, 0, 0, 0, 183, 0, 0, 0, 252, 0, 0, 0, 48, 0, 0, 0, 225, -0, 0, 0, 53, 0, 0, 0, 137, 0, 0, 0, 186, 0, 0, 0, 77, 0, 0, 0, 168, 0, 0, 0, 109, 0, 0, 0, 206, 0, 0, 0, 140, 0, 0, 0, 139, 0, 0, 0, 48, 0, 0, 0, 224, 0, 0, 0, 218, 0, 0, 0, 41, 0, 0, 0, 24, 0, 0, 0, 17, 0, 0, 0, 23, 0, 0, 0, 25, 0, 0, 0, 166, 0, 0, 0, 90, 0, 0, 0, 101, 0, 0, 0, 147, 0, 0, 0, 195, 0, 0, 0, 181, 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0, 243, 0, 0, 0, 246, 0, 0, 0, 15, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 195, 0, 0, 0, 124, 0, 0, 0, 235, 0, 0, 0, 206, 0, 0, 0, 134, 0, 0, 0, 236, -0, 0, 0, 103, 0, 0, 0, 118, 0, 0, 0, 110, 0, 0, 0, 53, 0, 0, 0, 69, 0, 0, 0, 123, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, 146, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 0, 61, 0, 0, 0, 213, 0, 0, 0, 154, 0, 0, 0, 100, 0, 0, 0, 115, 0, 0, 0, 54, 0, 0, 0, 177, 0, 0, 0, 214, 0, 0, 0, 134, 0, 0, 0, 152, 0, 0, 0, 66, 0, 0, 0, 63, 0, 0, 0, 138, 0, 0, 0, 241, 0, 0, 0, 199, 0, 0, 0, 245, 0, 0, 0, 66, 0, 0, 0, 168, 0, 0, 0, 156, 0, 0, 0, 82, 0, 0, 0, 168, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 36, 0, 0, 0, 63, 0, 0, 0, -74, 0, 0, 0, 161, 0, 0, 0, 164, 0, 0, 0, 91, 0, 0, 0, 232, 0, 0, 0, 98, 0, 0, 0, 26, 0, 0, 0, 197, 0, 0, 0, 189, 0, 0, 0, 200, 0, 0, 0, 20, 0, 0, 0, 213, 0, 0, 0, 13, 0, 0, 0, 235, 0, 0, 0, 225, 0, 0, 0, 165, 0, 0, 0, 230, 0, 0, 0, 131, 0, 0, 0, 17, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 85, 0, 0, 0, 131, 0, 0, 0, 81, 0, 0, 0, 126, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 185, 0, 0, 0, 203, 0, 0, 0, 216, 0, 0, 0, 197, 0, 0, 0, 229, 0, 0, 0, 161, 0, 0, 0, 217, 0, 0, 0, 23, 0, 0, 0, -109, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 249, 0, 0, 0, 228, 0, 0, 0, 233, 0, 0, 0, 225, 0, 0, 0, 82, 0, 0, 0, 63, 0, 0, 0, 81, 0, 0, 0, 25, 0, 0, 0, 13, 0, 0, 0, 221, 0, 0, 0, 217, 0, 0, 0, 157, 0, 0, 0, 147, 0, 0, 0, 49, 0, 0, 0, 135, -0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0, 213, 0, 0, 0, 131, 0, 0, 0, 235, 0, 0, 0, 146, 0, 0, 0, 9, 0, 0, 0, 118, 0, 0, 0, 110, 0, 0, 0, 227, 0, 0, 0, 248, 0, 0, 0, 192, 0, 0, 0, 162, 0, 0, 0, 102, 0, 0, 0, 181, 0, 0, 0, 54, 0, 0, 0, 58, 0, 0, 0, 187, 0, 0, 0, 57, 0, 0, 0, 237, 0, 0, 0, 50, 0, 0, 0, 2, 0, 0, 0, 231, 0, 0, 0, 67, 0, 0, 0, 122, 0, 0, 0, 56, 0, 0, 0, 20, 0, 0, 0, 132, 0, 0, 0, 227, 0, 0, 0, 68, 0, 0, 0, 210, 0, 0, 0, 94, 0, 0, 0, 148, 0, 0, 0, 221, 0, 0, 0, 120, 0, 0, 0, 137, 0, 0, 0, 85, -0, 0, 0, 76, 0, 0, 0, 115, 0, 0, 0, 158, 0, 0, 0, 225, 0, 0, 0, 228, 0, 0, 0, 62, 0, 0, 0, 67, 0, 0, 0, 208, 0, 0, 0, 74, 0, 0, 0, 222, 0, 0, 0, 27, 0, 0, 0, 178, 0, 0, 0, 231, 0, 0, 0, 143, 0, 0, 0, 227, 0, 0, 0, 163, 0, 0, 0, 197, 0, 0, 0, 203, 0, 0, 0, 114, 0, 0, 0, 238, 0, 0, 0, 121, 0, 0, 0, 65, 0, 0, 0, 248, 0, 0, 0, 223, 0, 0, 0, 238, 0, 0, 0, 101, 0, 0, 0, 197, 0, 0, 0, 69, 0, 0, 0, 119, 0, 0, 0, 39, 0, 0, 0, 60, 0, 0, 0, 189, 0, 0, 0, 88, 0, 0, 0, 211, 0, 0, 0, 117, 0, 0, 0, 226, 0, 0, 0, -4, 0, 0, 0, 75, 0, 0, 0, 187, 0, 0, 0, 101, 0, 0, 0, 243, 0, 0, 0, 200, 0, 0, 0, 15, 0, 0, 0, 36, 0, 0, 0, 123, 0, 0, 0, 147, 0, 0, 0, 52, 0, 0, 0, 181, 0, 0, 0, 226, 0, 0, 0, 116, 0, 0, 0, 72, 0, 0, 0, 205, 0, 0, 0, 160, 0, 0, 0, 11, 0, 0, 0, 146, 0, 0, 0, 151, 0, 0, 0, 102, 0, 0, 0, 57, 0, 0, 0, 244, 0, 0, 0, 176, 0, 0, 0, 226, 0, 0, 0, 93, 0, 0, 0, 57, 0, 0, 0, 106, 0, 0, 0, 91, 0, 0, 0, 69, 0, 0, 0, 23, 0, 0, 0, 120, 0, 0, 0, 30, 0, 0, 0, 219, 0, 0, 0, 145, 0, 0, 0, 129, 0, 0, 0, 28, 0, 0, 0, -249, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 223, 0, 0, 0, 209, 0, 0, 0, 90, 0, 0, 0, 213, 0, 0, 0, 233, 0, 0, 0, 78, 0, 0, 0, 88, 0, 0, 0, 149, 0, 0, 0, 147, 0, 0, 0, 95, 0, 0, 0, 81, 0, 0, 0, 9, 0, 0, 0, 195, 0, 0, 0, 42, 0, 0, 0, 201, 0, 0, 0, 212, 0, 0, 0, 85, 0, 0, 0, 72, 0, 0, 0, 121, 0, 0, 0, 164, 0, 0, 0, 163, 0, 0, 0, 178, 0, 0, 0, 195, 0, 0, 0, 98, 0, 0, 0, 170, 0, 0, 0, 140, 0, 0, 0, 232, 0, 0, 0, 173, 0, 0, 0, 71, 0, 0, 0, 57, 0, 0, 0, 27, 0, 0, 0, 70, 0, 0, 0, 218, 0, 0, 0, 158, 0, 0, 0, -81, 0, 0, 0, 58, 0, 0, 0, 230, 0, 0, 0, 209, 0, 0, 0, 166, 0, 0, 0, 187, 0, 0, 0, 77, 0, 0, 0, 123, 0, 0, 0, 8, 0, 0, 0, 190, 0, 0, 0, 140, 0, 0, 0, 213, 0, 0, 0, 243, 0, 0, 0, 63, 0, 0, 0, 253, 0, 0, 0, 247, 0, 0, 0, 68, 0, 0, 0, 128, 0, 0, 0, 45, 0, 0, 0, 83, 0, 0, 0, 75, 0, 0, 0, 208, 0, 0, 0, 135, 0, 0, 0, 104, 0, 0, 0, 193, 0, 0, 0, 181, 0, 0, 0, 216, 0, 0, 0, 247, 0, 0, 0, 7, 0, 0, 0, 244, 0, 0, 0, 16, 0, 0, 0, 70, 0, 0, 0, 190, 0, 0, 0, 183, 0, 0, 0, 210, 0, 0, 0, 209, 0, 0, 0, 206, 0, 0, -0, 94, 0, 0, 0, 118, 0, 0, 0, 162, 0, 0, 0, 215, 0, 0, 0, 3, 0, 0, 0, 220, 0, 0, 0, 228, 0, 0, 0, 129, 0, 0, 0, 90, 0, 0, 0, 246, 0, 0, 0, 60, 0, 0, 0, 222, 0, 0, 0, 174, 0, 0, 0, 122, 0, 0, 0, 157, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 165, 0, 0, 0, 246, 0, 0, 0, 169, 0, 0, 0, 115, 0, 0, 0, 226, 0, 0, 0, 141, 0, 0, 0, 96, 0, 0, 0, 250, 0, 0, 0, 68, 0, 0, 0, 113, 0, 0, 0, 246, 0, 0, 0, 65, 0, 0, 0, 216, 0, 0, 0, 198, 0, 0, 0, 88, 0, 0, 0, 19, 0, 0, 0, 55, 0, 0, 0, 235, 0, 0, 0, 132, 0, 0, 0, 15, 0, -0, 0, 150, 0, 0, 0, 199, 0, 0, 0, 220, 0, 0, 0, 200, 0, 0, 0, 169, 0, 0, 0, 122, 0, 0, 0, 131, 0, 0, 0, 178, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 177, 0, 0, 0, 26, 0, 0, 0, 216, 0, 0, 0, 152, 0, 0, 0, 63, 0, 0, 0, 17, 0, 0, 0, 208, 0, 0, 0, 49, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 213, 0, 0, 0, 52, 0, 0, 0, 22, 0, 0, 0, 1, 0, 0, 0, 163, 0, 0, 0, 147, 0, 0, 0, 234, 0, 0, 0, 82, 0, 0, 0, 148, 0, 0, 0, 236, 0, 0, 0, 147, 0, 0, 0, 183, 0, 0, 0, 129, 0, 0, 0, 17, 0, 0, 0, 45, 0, 0, 0, 88, 0, 0, 0, 249, 0, 0, 0, 181, 0, 0, 0, 10, 0, 0, 0, 170, 0, 0, 0, 79, 0, 0, 0, 246, 0, 0, 0, 46, 0, 0, 0, 63, 0, 0, 0, 54, 0, 0, 0, 191, 0, 0, 0, 51, 0, 0, 0, 90, 0, 0, 0, 231, 0, 0, 0, 209, 0, 0, 0, 8, 0, 0, 0, 26, 0, 0, 0, 207, 0, 0, 0, 66, 0, 0, 0, -174, 0, 0, 0, 204, 0, 0, 0, 181, 0, 0, 0, 119, 0, 0, 0, 57, 0, 0, 0, 196, 0, 0, 0, 91, 0, 0, 0, 91, 0, 0, 0, 208, 0, 0, 0, 38, 0, 0, 0, 89, 0, 0, 0, 39, 0, 0, 0, 208, 0, 0, 0, 85, 0, 0, 0, 113, 0, 0, 0, 18, 0, 0, 0, 157, 0, 0, 0, 136, 0, 0, 0, 61, 0, 0, 0, 156, 0, 0, 0, 234, 0, 0, 0, 65, 0, 0, 0, 106, 0, 0, 0, 240, 0, 0, 0, 80, 0, 0, 0, 147, 0, 0, 0, 147, 0, 0, 0, 221, 0, 0, 0, 71, 0, 0, 0, 111, 0, 0, 0, 201, 0, 0, 0, 81, 0, 0, 0, 109, 0, 0, 0, 28, 0, 0, 0, 170, 0, 0, 0, 245, 0, 0, 0, 165, 0, 0, -0, 144, 0, 0, 0, 63, 0, 0, 0, 20, 0, 0, 0, 226, 0, 0, 0, 110, 0, 0, 0, 142, 0, 0, 0, 100, 0, 0, 0, 253, 0, 0, 0, 172, 0, 0, 0, 224, 0, 0, 0, 78, 0, 0, 0, 34, 0, 0, 0, 229, 0, 0, 0, 193, 0, 0, 0, 188, 0, 0, 0, 41, 0, 0, 0, 10, 0, 0, 0, 106, 0, 0, 0, 158, 0, 0, 0, 161, 0, 0, 0, 96, 0, 0, 0, 203, 0, 0, 0, 47, 0, 0, 0, 11, 0, 0, 0, 220, 0, 0, 0, 57, 0, 0, 0, 50, 0, 0, 0, 243, 0, 0, 0, 161, 0, 0, 0, 68, 0, 0, 0, 233, 0, 0, 0, 197, 0, 0, 0, 195, 0, 0, 0, 120, 0, 0, 0, 251, 0, 0, 0, 149, 0, 0, 0, 71, 0, -0, 0, 52, 0, 0, 0, 53, 0, 0, 0, 52, 0, 0, 0, 232, 0, 0, 0, 37, 0, 0, 0, 222, 0, 0, 0, 147, 0, 0, 0, 198, 0, 0, 0, 180, 0, 0, 0, 118, 0, 0, 0, 109, 0, 0, 0, 134, 0, 0, 0, 19, 0, 0, 0, 198, 0, 0, 0, 233, 0, 0, 0, 104, 0, 0, 0, 181, 0, 0, 0, 1, 0, 0, 0, 99, 0, 0, 0, 31, 0, 0, 0, 154, 0, 0, 0, 82, 0, 0, 0, 100, 0, 0, 0, 151, 0, 0, 0, 217, 0, 0, 0, 28, 0, 0, 0, 8, 0, 0, 0, 81, 0, 0, 0, 111, 0, 0, 0, 38, 0, 0, 0, 157, 0, 0, 0, 170, 0, 0, 0, 147, 0, 0, 0, 51, 0, 0, 0, 67, 0, 0, 0, 250, 0, 0, 0, 119, 0, -0, 0, 233, 0, 0, 0, 98, 0, 0, 0, 155, 0, 0, 0, 93, 0, 0, 0, 24, 0, 0, 0, 117, 0, 0, 0, 235, 0, 0, 0, 120, 0, 0, 0, 247, 0, 0, 0, 135, 0, 0, 0, 143, 0, 0, 0, 65, 0, 0, 0, 180, 0, 0, 0, 77, 0, 0, 0, 19, 0, 0, 0, 168, 0, 0, 0, 130, 0, 0, 0, 62, 0, 0, 0, 233, 0, 0, 0, 19, 0, 0, 0, 173, 0, 0, 0, 235, 0, 0, 0, 1, 0, 0, 0, 202, 0, 0, 0, 207, 0, 0, 0, 218, 0, 0, 0, 205, 0, 0, 0, 247, 0, 0, 0, 108, 0, 0, 0, 199, 0, 0, 0, 122, 0, 0, 0, 220, 0, 0, 0, 30, 0, 0, 0, 110, 0, 0, 0, 200, 0, 0, 0, 78, 0, 0, 0, 85, -0, 0, 0, 98, 0, 0, 0, 128, 0, 0, 0, 234, 0, 0, 0, 120, 0, 0, 0, 12, 0, 0, 0, 134, 0, 0, 0, 185, 0, 0, 0, 64, 0, 0, 0, 81, 0, 0, 0, 39, 0, 0, 0, 174, 0, 0, 0, 211, 0, 0, 0, 13, 0, 0, 0, 76, 0, 0, 0, 143, 0, 0, 0, 52, 0, 0, 0, 234, 0, 0, 0, 125, 0, 0, 0, 60, 0, 0, 0, 229, 0, 0, 0, 138, 0, 0, 0, 207, 0, 0, 0, 91, 0, 0, 0, 146, 0, 0, 0, 216, 0, 0, 0, 48, 0, 0, 0, 22, 0, 0, 0, 180, 0, 0, 0, 163, 0, 0, 0, 117, 0, 0, 0, 255, 0, 0, 0, 235, 0, 0, 0, 39, 0, 0, 0, 200, 0, 0, 0, 92, 0, 0, 0, 108, 0, 0, 0, 194, -0, 0, 0, 238, 0, 0, 0, 108, 0, 0, 0, 33, 0, 0, 0, 11, 0, 0, 0, 195, 0, 0, 0, 186, 0, 0, 0, 18, 0, 0, 0, 83, 0, 0, 0, 42, 0, 0, 0, 170, 0, 0, 0, 119, 0, 0, 0, 173, 0, 0, 0, 25, 0, 0, 0, 120, 0, 0, 0, 85, 0, 0, 0, 138, 0, 0, 0, 46, 0, 0, 0, 96, 0, 0, 0, 135, 0, 0, 0, 194, 0, 0, 0, 110, 0, 0, 0, 145, 0, 0, 0, 56, 0, 0, 0, 145, 0, 0, 0, 63, 0, 0, 0, 122, 0, 0, 0, 197, 0, 0, 0, 36, 0, 0, 0, 143, 0, 0, 0, 81, 0, 0, 0, 197, 0, 0, 0, 222, 0, 0, 0, 176, 0, 0, 0, 83, 0, 0, 0, 48, 0, 0, 0, 86, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 254, 0, 0, 0, 84, 0, 0, 0, 18, 0, 0, 0, 24, 0, 0, 0, 202, 0, 0, 0, 125, 0, 0, 0, 165, 0, 0, 0, 104, 0, 0, 0, 67, 0, 0, 0, 163, 0, 0, 0, 109, 0, 0, 0, 20, 0, 0, 0, 42, 0, 0, 0, 106, 0, 0, 0, 165, 0, 0, 0, 142, 0, 0, 0, 50, 0, 0, -0, 231, 0, 0, 0, 99, 0, 0, 0, 79, 0, 0, 0, 227, 0, 0, 0, 198, 0, 0, 0, 68, 0, 0, 0, 62, 0, 0, 0, 171, 0, 0, 0, 99, 0, 0, 0, 202, 0, 0, 0, 23, 0, 0, 0, 134, 0, 0, 0, 116, 0, 0, 0, 63, 0, 0, 0, 30, 0, 0, 0, 100, 0, 0, 0, 193, 0, 0, 0, 125, 0, 0, 0, 82, 0, 0, 0, 220, 0, 0, 0, 19, 0, 0, 0, 90, 0, 0, 0, 161, 0, 0, 0, 156, 0, 0, 0, 78, 0, 0, 0, 238, 0, 0, 0, 153, 0, 0, 0, 40, 0, 0, 0, 187, 0, 0, 0, 76, 0, 0, 0, 238, 0, 0, 0, 172, 0, 0, 0, 169, 0, 0, 0, 27, 0, 0, 0, 137, 0, 0, 0, 162, 0, 0, 0, 56, 0, 0, -0, 57, 0, 0, 0, 123, 0, 0, 0, 196, 0, 0, 0, 15, 0, 0, 0, 66, 0, 0, 0, 230, 0, 0, 0, 137, 0, 0, 0, 237, 0, 0, 0, 15, 0, 0, 0, 243, 0, 0, 0, 60, 0, 0, 0, 140, 0, 0, 0, 128, 0, 0, 0, 131, 0, 0, 0, 16, 0, 0, 0, 138, 0, 0, 0, 55, 0, 0, 0, 80, 0, 0, 0, 156, 0, 0, 0, 180, 0, 0, 0, 223, 0, 0, 0, 63, 0, 0, 0, 140, 0, 0, 0, 247, 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 0, 214, 0, 0, 0, 255, 0, 0, 0, 160, 0, 0, 0, 130, 0, 0, 0, 108, 0, 0, 0, 117, 0, 0, 0, 59, 0, 0, 0, 228, 0, 0, 0, 181, 0, 0, 0, 187, 0, 0, 0, 228, 0, -0, 0, 230, 0, 0, 0, 80, 0, 0, 0, 240, 0, 0, 0, 8, 0, 0, 0, 98, 0, 0, 0, 238, 0, 0, 0, 117, 0, 0, 0, 72, 0, 0, 0, 146, 0, 0, 0, 51, 0, 0, 0, 242, 0, 0, 0, 244, 0, 0, 0, 173, 0, 0, 0, 21, 0, 0, 0, 122, 0, 0, 0, 161, 0, 0, 0, 1, 0, 0, 0, 70, 0, 0, 0, 169, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, 136, 0, 0, 0, 182, 0, 0, 0, 54, 0, 0, 0, 71, 0, 0, 0, 53, 0, 0, 0, 185, 0, 0, 0, 180, 0, 0, 0, 66, 0, 0, 0, 133, 0, 0, 0, 118, 0, 0, 0, 240, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 56, 0, 0, 0, 81, 0, 0, 0, -21, 0, 0, 0, 157, 0, 0, 0, 195, 0, 0, 0, 149, 0, 0, 0, 209, 0, 0, 0, 57, 0, 0, 0, 187, 0, 0, 0, 100, 0, 0, 0, 157, 0, 0, 0, 21, 0, 0, 0, 129, 0, 0, 0, 193, 0, 0, 0, 104, 0, 0, 0, 208, 0, 0, 0, 182, 0, 0, 0, 164, 0, 0, 0, 44, 0, 0, 0, 125, 0, 0, 0, 94, 0, 0, 0, 2, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 59, 0, 0, 0, 164, 0, 0, 0, 204, 0, 0, 0, 202, 0, 0, 0, 29, 0, 0, 0, 129, 0, 0, 0, 36, 0, 0, 0, 16, 0, 0, 0, 231, 0, 0, 0, 41, 0, 0, 0, 249, 0, 0, 0, 55, 0, 0, 0, 217, 0, 0, 0, 70, 0, 0, 0, -90, 0, 0, 0, 205, 0, 0, 0, 112, 0, 0, 0, 254, 0, 0, 0, 77, 0, 0, 0, 91, 0, 0, 0, 191, 0, 0, 0, 165, 0, 0, 0, 207, 0, 0, 0, 145, 0, 0, 0, 244, 0, 0, 0, 239, 0, 0, 0, 238, 0, 0, 0, 138, 0, 0, 0, 41, 0, 0, 0, 208, 0, 0, 0, 231, 0, 0, 0, 196, 0, 0, 0, 37, 0, 0, 0, 146, 0, 0, 0, 138, 0, 0, 0, 255, 0, 0, 0, 54, 0, 0, 0, 252, 0, 0, 0, 228, 0, 0, 0, 73, 0, 0, 0, 189, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 4, 0, 0, 0, 125, 0, 0, 0, 53, 0, 0, 0, 252, 0, 0, 0, 235, 0, 0, 0, 208, 0, 0, 0, 11, 0, 0, 0, 5, 0, 0, 0, -50, 0, 0, 0, 82, 0, 0, 0, 122, 0, 0, 0, 137, 0, 0, 0, 36, 0, 0, 0, 117, 0, 0, 0, 80, 0, 0, 0, 225, 0, 0, 0, 99, 0, 0, 0, 2, 0, 0, 0, 130, 0, 0, 0, 142, 0, 0, 0, 231, 0, 0, 0, 133, 0, 0, 0, 12, 0, 0, 0, 242, 0, 0, 0, 86, 0, 0, 0, 68, 0, 0, 0, 55, 0, 0, 0, 131, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 161, 0, 0, 0, 206, 0, 0, 0, 203, 0, 0, 0, 96, 0, 0, 0, 218, 0, 0, 0, 18, 0, 0, 0, 2, 0, 0, 0, 30, 0, 0, 0, 41, 0, 0, 0, 57, 0, 0, 0, 42, 0, 0, 0, 3, 0, 0, 0, 183, 0, 0, 0, 235, 0, 0, 0, 119, 0, 0, 0, 64, 0, -0, 0, 234, 0, 0, 0, 201, 0, 0, 0, 43, 0, 0, 0, 44, 0, 0, 0, 213, 0, 0, 0, 125, 0, 0, 0, 126, 0, 0, 0, 44, 0, 0, 0, 199, 0, 0, 0, 90, 0, 0, 0, 253, 0, 0, 0, 255, 0, 0, 0, 196, 0, 0, 0, 209, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 136, 0, 0, -0, 152, 0, 0, 0, 91, 0, 0, 0, 78, 0, 0, 0, 252, 0, 0, 0, 65, 0, 0, 0, 36, 0, 0, 0, 5, 0, 0, 0, 230, 0, 0, 0, 80, 0, 0, 0, 43, 0, 0, 0, 174, 0, 0, 0, 150, 0, 0, 0, 81, 0, 0, 0, 217, 0, 0, 0, 107, 0, 0, 0, 114, 0, 0, 0, 178, 0, 0, 0, 51, 0, 0, 0, 66, 0, 0, 0, 152, 0, 0, 0, 104, 0, 0, 0, 187, 0, 0, 0, 16, 0, 0, 0, 90, 0, 0, 0, 122, 0, 0, 0, 140, 0, 0, 0, 157, 0, 0, 0, 7, 0, 0, 0, 180, 0, 0, 0, 5, 0, 0, 0, 47, 0, 0, 0, 97, 0, 0, 0, 159, 0, 0, 0, 215, 0, 0, 0, 168, 0, 0, 0, 63, 0, 0, 0, 131, 0, 0, 0, -140, 0, 0, 0, 16, 0, 0, 0, 105, 0, 0, 0, 144, 0, 0, 0, 230, 0, 0, 0, 207, 0, 0, 0, 210, 0, 0, 0, 99, 0, 0, 0, 163, 0, 0, 0, 228, 0, 0, 0, 84, 0, 0, 0, 126, 0, 0, 0, 229, 0, 0, 0, 105, 0, 0, 0, 19, 0, 0, 0, 28, 0, 0, 0, 144, 0, 0, 0, 87, 0, 0, 0, 170, 0, 0, 0, 233, 0, 0, 0, 83, 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0, 41, 0, 0, 0, 35, 0, 0, 0, 229, 0, 0, 0, 28, 0, 0, 0, 248, 0, 0, 0, 10, 0, 0, 0, 253, 0, 0, 0, 45, 0, 0, 0, 126, 0, 0, 0, 245, 0, 0, 0, 245, 0, 0, 0, 112, 0, 0, 0, 125, 0, 0, 0, 65, 0, 0, 0, -107, 0, 0, 0, 17, 0, 0, 0, 254, 0, 0, 0, 190, 0, 0, 0, 153, 0, 0, 0, 209, 0, 0, 0, 85, 0, 0, 0, 41, 0, 0, 0, 49, 0, 0, 0, 191, 0, 0, 0, 192, 0, 0, 0, 151, 0, 0, 0, 108, 0, 0, 0, 213, 0, 0, 0, 53, 0, 0, 0, 204, 0, 0, 0, 94, 0, 0, 0, 139, 0, 0, 0, 217, 0, 0, 0, 105, 0, 0, 0, 142, 0, 0, 0, 78, 0, 0, 0, 159, 0, 0, 0, 37, 0, 0, 0, 248, 0, 0, 0, 129, 0, 0, 0, 84, 0, 0, 0, 45, 0, 0, 0, 14, 0, 0, 0, 213, 0, 0, 0, 84, 0, 0, 0, 129, 0, 0, 0, 155, 0, 0, 0, 166, 0, 0, 0, 146, 0, 0, 0, 206, 0, 0, 0, 75, 0, 0, -0, 233, 0, 0, 0, 143, 0, 0, 0, 36, 0, 0, 0, 59, 0, 0, 0, 202, 0, 0, 0, 224, 0, 0, 0, 68, 0, 0, 0, 171, 0, 0, 0, 54, 0, 0, 0, 254, 0, 0, 0, 251, 0, 0, 0, 135, 0, 0, 0, 212, 0, 0, 0, 38, 0, 0, 0, 62, 0, 0, 0, 15, 0, 0, 0, 147, 0, 0, 0, 156, 0, 0, 0, 17, 0, 0, 0, 231, 0, 0, 0, 219, 0, 0, 0, 241, 0, 0, 0, 240, 0, 0, 0, 133, 0, 0, 0, 67, 0, 0, 0, 40, 0, 0, 0, 21, 0, 0, 0, 55, 0, 0, 0, 221, 0, 0, 0, 222, 0, 0, 0, 39, 0, 0, 0, 223, 0, 0, 0, 173, 0, 0, 0, 62, 0, 0, 0, 73, 0, 0, 0, 79, 0, 0, 0, 224, 0, 0, -0, 91, 0, 0, 0, 246, 0, 0, 0, 128, 0, 0, 0, 89, 0, 0, 0, 21, 0, 0, 0, 60, 0, 0, 0, 133, 0, 0, 0, 183, 0, 0, 0, 62, 0, 0, 0, 18, 0, 0, 0, 245, 0, 0, 0, 255, 0, 0, 0, 204, 0, 0, 0, 240, 0, 0, 0, 180, 0, 0, 0, 18, 0, 0, 0, 3, 0, 0, 0, 95, 0, 0, 0, 201, 0, 0, 0, 132, 0, 0, 0, 203, 0, 0, 0, 29, 0, 0, 0, 23, 0, 0, 0, 224, 0, 0, 0, 188, 0, 0, 0, 204, 0, 0, 0, 3, 0, 0, 0, 98, 0, 0, 0, 169, 0, 0, 0, 139, 0, 0, 0, 148, 0, 0, 0, 166, 0, 0, 0, 170, 0, 0, 0, 24, 0, 0, 0, 203, 0, 0, 0, 39, 0, 0, 0, 141, 0, 0, -0, 73, 0, 0, 0, 166, 0, 0, 0, 23, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 217, 0, 0, 0, 182, 0, 0, 0, 212, 0, 0, 0, 157, 0, 0, 0, 212, 0, 0, 0, 106, 0, 0, 0, 175, 0, 0, 0, 112, 0, 0, 0, 7, 0, 0, 0, 44, 0, 0, 0, 16, 0, 0, 0, 158, 0, 0, 0, 189, 0, 0, 0, 17, 0, 0, 0, 173, 0, 0, 0, 228, 0, 0, 0, 38, 0, 0, 0, 51, 0, 0, 0, 112, 0, 0, 0, 146, 0, 0, 0, 120, 0, 0, 0, 28, 0, 0, 0, 116, 0, 0, 0, 159, 0, 0, 0, 117, 0, 0, 0, 96, 0, 0, 0, 86, 0, 0, 0, 244, 0, 0, 0, 57, 0, 0, 0, 168, 0, 0, 0, 168, 0, 0, 0, 98, 0, 0, -0, 59, 0, 0, 0, 191, 0, 0, 0, 85, 0, 0, 0, 53, 0, 0, 0, 97, 0, 0, 0, 139, 0, 0, 0, 68, 0, 0, 0, 151, 0, 0, 0, 232, 0, 0, 0, 58, 0, 0, 0, 85, 0, 0, 0, 193, 0, 0, 0, 200, 0, 0, 0, 59, 0, 0, 0, 253, 0, 0, 0, 149, 0, 0, 0, 41, 0, 0, 0, 17, 0, 0, 0, 96, 0, 0, 0, 150, 0, 0, 0, 30, 0, 0, 0, 203, 0, 0, 0, 17, 0, 0, 0, 157, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 138, 0, 0, 0, 27, 0, 0, 0, 198, 0, 0, 0, 214, 0, 0, 0, 69, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 14, 0, 0, 0, 80, 0, 0, 0, 178, 0, 0, 0, 204, 0, 0, 0, 13, 0, 0, 0, 107, 0, 0, 0, 166, 0, 0, 0, 113, 0, 0, 0, 91, 0, 0, 0, 66, 0, 0, 0, 237, 0, 0, 0, 189, 0, 0, 0, 175, 0, 0, 0, 172, 0, 0, 0, 240, 0, 0, 0, 252, 0, 0, 0, 18, 0, 0, 0, 162, 0, 0, 0, 63, 0, 0, 0, 78, 0, 0, 0, 218, 0, 0, 0, 232, -0, 0, 0, 17, 0, 0, 0, 243, 0, 0, 0, 35, 0, 0, 0, 225, 0, 0, 0, 4, 0, 0, 0, 98, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0, 78, 0, 0, 0, 200, 0, 0, 0, 177, 0, 0, 0, 27, 0, 0, 0, 111, 0, 0, 0, 115, 0, 0, 0, 97, 0, 0, 0, 61, 0, 0, 0, 39, 0, 0, 0, 13, 0, 0, 0, 125, 0, 0, 0, 122, 0, 0, 0, 37, 0, 0, 0, 95, 0, 0, 0, 115, 0, 0, 0, 14, 0, 0, 0, 47, 0, 0, 0, 147, 0, 0, 0, 246, 0, 0, 0, 36, 0, 0, 0, 216, 0, 0, 0, 79, 0, 0, 0, 144, 0, 0, 0, 172, 0, 0, 0, 162, 0, 0, 0, 98, 0, 0, 0, 10, 0, 0, 0, 240, 0, 0, 0, 97, 0, 0, -0, 217, 0, 0, 0, 8, 0, 0, 0, 89, 0, 0, 0, 106, 0, 0, 0, 111, 0, 0, 0, 45, 0, 0, 0, 85, 0, 0, 0, 248, 0, 0, 0, 47, 0, 0, 0, 142, 0, 0, 0, 240, 0, 0, 0, 24, 0, 0, 0, 59, 0, 0, 0, 234, 0, 0, 0, 221, 0, 0, 0, 38, 0, 0, 0, 114, 0, 0, 0, 209, 0, 0, 0, 245, 0, 0, 0, 254, 0, 0, 0, 229, 0, 0, 0, 184, 0, 0, 0, 230, 0, 0, 0, 211, 0, 0, 0]).concat([16, 0, 0, 0, 72, 0, 0, 0, 70, 0, 0, 0, 73, 0, 0, 0, 58, 0, 0, 0, 159, 0, 0, 0, 94, 0, 0, 0, 69, 0, 0, 0, 107, 0, 0, 0, 144, 0, 0, 0, 232, 0, 0, 0, 127, 0, 0, 0, 211, -0, 0, 0, 118, 0, 0, 0, 105, 0, 0, 0, 51, 0, 0, 0, 123, 0, 0, 0, 185, 0, 0, 0, 64, 0, 0, 0, 112, 0, 0, 0, 238, 0, 0, 0, 166, 0, 0, 0, 41, 0, 0, 0, 107, 0, 0, 0, 221, 0, 0, 0, 208, 0, 0, 0, 93, 0, 0, 0, 141, 0, 0, 0, 193, 0, 0, 0, 62, 0, 0, 0, 74, 0, 0, 0, 234, 0, 0, 0, 55, 0, 0, 0, 177, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 53, 0, 0, 0, 241, 0, 0, 0, 40, 0, 0, 0, 157, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 122, 0, 0, 0, 219, 0, 0, 0, 18, 0, 0, 0, 210, 0, 0, 0, 138, 0, 0, 0, 130, 0, -0, 0, 3, 0, 0, 0, 27, 0, 0, 0, 30, 0, 0, 0, 175, 0, 0, 0, 249, 0, 0, 0, 75, 0, 0, 0, 156, 0, 0, 0, 190, 0, 0, 0, 174, 0, 0, 0, 124, 0, 0, 0, 228, 0, 0, 0, 148, 0, 0, 0, 42, 0, 0, 0, 35, 0, 0, 0, 179, 0, 0, 0, 98, 0, 0, 0, 134, 0, 0, 0, 231, 0, 0, 0, 253, 0, 0, 0, 35, 0, 0, 0, 170, 0, 0, 0, 153, 0, 0, 0, 189, 0, 0, 0, 43, 0, 0, 0, 17, 0, 0, 0, 108, 0, 0, 0, 141, 0, 0, 0, 166, 0, 0, 0, 213, 0, 0, 0, 172, 0, 0, 0, 157, 0, 0, 0, 204, 0, 0, 0, 104, 0, 0, 0, 117, 0, 0, 0, 127, 0, 0, 0, 195, 0, 0, 0, 77, -0, 0, 0, 75, 0, 0, 0, 221, 0, 0, 0, 108, 0, 0, 0, 187, 0, 0, 0, 17, 0, 0, 0, 90, 0, 0, 0, 96, 0, 0, 0, 229, 0, 0, 0, 189, 0, 0, 0, 125, 0, 0, 0, 39, 0, 0, 0, 139, 0, 0, 0, 218, 0, 0, 0, 180, 0, 0, 0, 149, 0, 0, 0, 246, 0, 0, 0, 3, 0, 0, 0, 39, 0, 0, 0, 164, 0, 0, 0, 146, 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 214, 0, 0, 0, 181, 0, 0, 0, 23, 0, 0, 0, 132, 0, 0, 0, 191, 0, 0, 0, 18, 0, 0, 0, 204, 0, 0, 0, 35, 0, 0, 0, 20, 0, 0, 0, 74, 0, 0, 0, 223, 0, 0, 0, 20, 0, 0, 0, 49, 0, 0, 0, 188, 0, 0, 0, 161, -0, 0, 0, 172, 0, 0, 0, 110, 0, 0, 0, 171, 0, 0, 0, 250, 0, 0, 0, 87, 0, 0, 0, 17, 0, 0, 0, 83, 0, 0, 0, 179, 0, 0, 0, 39, 0, 0, 0, 230, 0, 0, 0, 249, 0, 0, 0, 71, 0, 0, 0, 51, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 30, 0, 0, 0, 121, 0, 0, 0, 252, 0, 0, 0, 166, 0, 0, 0, 180, 0, 0, 0, 11, 0, 0, 0, 53, 0, 0, 0, 32, 0, 0, 0, 201, 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 132, 0, 0, 0, 196, 0, 0, 0, 169, 0, 0, 0, 32, 0, 0, 0, 236, 0, 0, 0, 137, 0, 0, 0, 148, 0, 0, 0, 186, 0, 0, 0, 102, 0, 0, 0, 86, 0, 0, 0, 72, -0, 0, 0, 185, 0, 0, 0, 135, 0, 0, 0, 127, 0, 0, 0, 202, 0, 0, 0, 30, 0, 0, 0, 6, 0, 0, 0, 237, 0, 0, 0, 165, 0, 0, 0, 85, 0, 0, 0, 89, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 225, 0, 0, 0, 245, 0, 0, 0, 241, 0, 0, 0, 213, 0, 0, 0, 171, 0, 0, -0, 168, 0, 0, 0, 43, 0, 0, 0, 174, 0, 0, 0, 137, 0, 0, 0, 243, 0, 0, 0, 207, 0, 0, 0, 86, 0, 0, 0, 159, 0, 0, 0, 242, 0, 0, 0, 75, 0, 0, 0, 49, 0, 0, 0, 188, 0, 0, 0, 24, 0, 0, 0, 169, 0, 0, 0, 6, 0, 0, 0, 91, 0, 0, 0, 190, 0, 0, 0, 180, 0, 0, 0, 97, 0, 0, 0, 248, 0, 0, 0, 178, 0, 0, 0, 6, 0, 0, 0, 156, 0, 0, 0, 129, 0, 0, 0, 171, 0, 0, 0, 76, 0, 0, 0, 31, 0, 0, 0, 104, 0, 0, 0, 118, 0, 0, 0, 1, 0, 0, 0, 22, 0, 0, 0, 56, 0, 0, 0, 43, 0, 0, 0, 15, 0, 0, 0, 119, 0, 0, 0, 151, 0, 0, 0, 146, 0, 0, 0, -103, 0, 0, 0, 78, 0, 0, 0, 134, 0, 0, 0, 106, 0, 0, 0, 139, 0, 0, 0, 229, 0, 0, 0, 232, 0, 0, 0, 12, 0, 0, 0, 247, 0, 0, 0, 54, 0, 0, 0, 57, 0, 0, 0, 181, 0, 0, 0, 51, 0, 0, 0, 230, 0, 0, 0, 207, 0, 0, 0, 94, 0, 0, 0, 189, 0, 0, 0, 24, 0, 0, 0, 251, 0, 0, 0, 16, 0, 0, 0, 31, 0, 0, 0, 131, 0, 0, 0, 240, 0, 0, 0, 13, 0, 0, 0, 99, 0, 0, 0, 239, 0, 0, 0, 83, 0, 0, 0, 107, 0, 0, 0, 181, 0, 0, 0, 107, 0, 0, 0, 249, 0, 0, 0, 131, 0, 0, 0, 207, 0, 0, 0, 222, 0, 0, 0, 4, 0, 0, 0, 34, 0, 0, 0, 155, 0, 0, 0, -44, 0, 0, 0, 10, 0, 0, 0, 224, 0, 0, 0, 165, 0, 0, 0, 216, 0, 0, 0, 199, 0, 0, 0, 156, 0, 0, 0, 165, 0, 0, 0, 163, 0, 0, 0, 246, 0, 0, 0, 111, 0, 0, 0, 207, 0, 0, 0, 144, 0, 0, 0, 107, 0, 0, 0, 104, 0, 0, 0, 124, 0, 0, 0, 51, 0, 0, 0, 21, 0, 0, 0, 215, 0, 0, 0, 127, 0, 0, 0, 26, 0, 0, 0, 213, 0, 0, 0, 33, 0, 0, 0, 88, 0, 0, 0, 196, 0, 0, 0, 24, 0, 0, 0, 165, 0, 0, 0, 240, 0, 0, 0, 204, 0, 0, 0, 115, 0, 0, 0, 168, 0, 0, 0, 253, 0, 0, 0, 250, 0, 0, 0, 24, 0, 0, 0, 209, 0, 0, 0, 3, 0, 0, 0, 145, 0, -0, 0, 141, 0, 0, 0, 82, 0, 0, 0, 210, 0, 0, 0, 163, 0, 0, 0, 164, 0, 0, 0, 211, 0, 0, 0, 177, 0, 0, 0, 234, 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 72, 0, 0, 0, 131, 0, 0, 0, 144, 0, 0, 0, 229, 0, 0, 0, 253, 0, 0, 0, 63, 0, 0, 0, 132, 0, 0, 0, 170, 0, 0, 0, 249, 0, 0, 0, 139, 0, 0, 0, 130, 0, 0, 0, 89, 0, 0, 0, 36, 0, 0, 0, 52, 0, 0, 0, 104, 0, 0, 0, 79, 0, 0, 0, 28, 0, 0, 0, 35, 0, 0, 0, 217, 0, 0, 0, 204, 0, 0, 0, 113, 0, 0, 0, 225, 0, 0, 0, 127, 0, 0, 0, 140, 0, 0, 0, 175, -0, 0, 0, 241, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 160, 0, 0, 0, 119, 0, 0, 0, 245, 0, 0, 0, 26, 0, 0, 0, 97, 0, 0, 0, 247, 0, 0, 0, 55, 0, 0, 0, 157, 0, 0, 0, 0, 0, 0, 0, 244, 0, 0, 0, 242, 0, 0, 0, 105, 0, 0, 0, 111, 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 0, 133, 0, 0, 0, 25, 0, 0, 0, 69, 0, 0, 0, 77, 0, 0, 0, 127, 0, 0, 0, 2, 0, 0, 0, 124, 0, 0, 0, 106, 0, 0, 0, 5, 0, 0, 0, 71, 0, 0, 0, 108, 0, 0, 0, 31, 0, 0, 0, 129, 0, 0, 0, 32, 0, 0, 0, 212, 0, 0, 0, 232, 0, 0, 0, 80, 0, 0, 0, 39, 0, 0, -0, 114, 0, 0, 0, 44, 0, 0, 0, 58, 0, 0, 0, 229, 0, 0, 0, 173, 0, 0, 0, 244, 0, 0, 0, 221, 0, 0, 0, 45, 0, 0, 0, 247, 0, 0, 0, 92, 0, 0, 0, 68, 0, 0, 0, 181, 0, 0, 0, 91, 0, 0, 0, 33, 0, 0, 0, 163, 0, 0, 0, 137, 0, 0, 0, 95, 0, 0, 0, 150, 0, 0, 0, 69, 0, 0, 0, 202, 0, 0, 0, 77, 0, 0, 0, 164, 0, 0, 0, 33, 0, 0, 0, 153, 0, 0, 0, 112, 0, 0, 0, 218, 0, 0, 0, 196, 0, 0, 0, 196, 0, 0, 0, 160, 0, 0, 0, 229, 0, 0, 0, 244, 0, 0, 0, 236, 0, 0, 0, 10, 0, 0, 0, 7, 0, 0, 0, 104, 0, 0, 0, 33, 0, 0, 0, 101, 0, 0, -0, 233, 0, 0, 0, 8, 0, 0, 0, 160, 0, 0, 0, 11, 0, 0, 0, 106, 0, 0, 0, 74, 0, 0, 0, 186, 0, 0, 0, 181, 0, 0, 0, 128, 0, 0, 0, 175, 0, 0, 0, 208, 0, 0, 0, 27, 0, 0, 0, 197, 0, 0, 0, 245, 0, 0, 0, 75, 0, 0, 0, 115, 0, 0, 0, 80, 0, 0, 0, 96, 0, 0, 0, 45, 0, 0, 0, 113, 0, 0, 0, 105, 0, 0, 0, 97, 0, 0, 0, 14, 0, 0, 0, 192, 0, 0, 0, 32, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 117, 0, 0, 0, 87, 0, 0, 0, 59, 0, 0, 0, 235, 0, 0, 0, 92, 0, 0, 0, 20, 0, 0, 0, 86, 0, 0, 0, 80, 0, 0, 0, 201, 0, 0, 0, 79, 0, 0, 0, 184, 0, 0, 0, 184, 0, 0, 0, 30, 0, 0, 0, 163, 0, 0, 0, 244, 0, 0, 0, 171, 0, 0, 0, 245, 0, 0, 0, 169, 0, 0, 0, 32, 0, 0, 0, 21, 0, 0, 0, 148, 0, 0, 0, 130, 0, 0, 0, 218, 0, 0, 0, 150, 0, 0, 0, 28, 0, 0, 0, 155, -0, 0, 0, 89, 0, 0, 0, 140, 0, 0, 0, 255, 0, 0, 0, 244, 0, 0, 0, 81, 0, 0, 0, 193, 0, 0, 0, 58, 0, 0, 0, 134, 0, 0, 0, 215, 0, 0, 0, 176, 0, 0, 0, 6, 0, 0, 0, 132, 0, 0, 0, 127, 0, 0, 0, 27, 0, 0, 0, 189, 0, 0, 0, 212, 0, 0, 0, 7, 0, 0, 0, 120, 0, 0, 0, 128, 0, 0, 0, 46, 0, 0, 0, 177, 0, 0, 0, 180, 0, 0, 0, 238, 0, 0, 0, 82, 0, 0, 0, 56, 0, 0, 0, 238, 0, 0, 0, 154, 0, 0, 0, 249, 0, 0, 0, 246, 0, 0, 0, 243, 0, 0, 0, 65, 0, 0, 0, 110, 0, 0, 0, 212, 0, 0, 0, 136, 0, 0, 0, 149, 0, 0, 0, 172, 0, 0, 0, -53, 0, 0, 0, 65, 0, 0, 0, 151, 0, 0, 0, 191, 0, 0, 0, 113, 0, 0, 0, 106, 0, 0, 0, 155, 0, 0, 0, 114, 0, 0, 0, 236, 0, 0, 0, 243, 0, 0, 0, 248, 0, 0, 0, 107, 0, 0, 0, 230, 0, 0, 0, 14, 0, 0, 0, 108, 0, 0, 0, 105, 0, 0, 0, 165, 0, 0, 0, 47, 0, 0, 0, 104, 0, 0, 0, 82, 0, 0, 0, 216, 0, 0, 0, 97, 0, 0, 0, 129, 0, 0, 0, 192, 0, 0, 0, 99, 0, 0, 0, 63, 0, 0, 0, 166, 0, 0, 0, 60, 0, 0, 0, 19, 0, 0, 0, 144, 0, 0, 0, 230, 0, 0, 0, 141, 0, 0, 0, 86, 0, 0, 0, 232, 0, 0, 0, 57, 0, 0, 0, 48, 0, 0, 0, 119, 0, 0, -0, 35, 0, 0, 0, 177, 0, 0, 0, 253, 0, 0, 0, 27, 0, 0, 0, 61, 0, 0, 0, 62, 0, 0, 0, 116, 0, 0, 0, 77, 0, 0, 0, 127, 0, 0, 0, 174, 0, 0, 0, 91, 0, 0, 0, 58, 0, 0, 0, 180, 0, 0, 0, 101, 0, 0, 0, 14, 0, 0, 0, 58, 0, 0, 0, 67, 0, 0, 0, 220, 0, 0, 0, 220, 0, 0, 0, 65, 0, 0, 0, 71, 0, 0, 0, 230, 0, 0, 0, 232, 0, 0, 0, 146, 0, 0, 0, 9, 0, 0, 0, 34, 0, 0, 0, 72, 0, 0, 0, 76, 0, 0, 0, 133, 0, 0, 0, 87, 0, 0, 0, 159, 0, 0, 0, 181, 0, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 178, 0, 0, 0, 159, 0, 0, 0, 71, 0, 0, 0, 63, -0, 0, 0, 240, 0, 0, 0, 250, 0, 0, 0, 230, 0, 0, 0, 169, 0, 0, 0, 177, 0, 0, 0, 155, 0, 0, 0, 111, 0, 0, 0, 150, 0, 0, 0, 125, 0, 0, 0, 249, 0, 0, 0, 164, 0, 0, 0, 101, 0, 0, 0, 9, 0, 0, 0, 117, 0, 0, 0, 50, 0, 0, 0, 166, 0, 0, 0, 108, 0, 0, 0, 127, 0, 0, 0, 71, 0, 0, 0, 75, 0, 0, 0, 47, 0, 0, 0, 79, 0, 0, 0, 52, 0, 0, 0, 233, 0, 0, 0, 89, 0, 0, 0, 147, 0, 0, 0, 157, 0, 0, 0, 38, 0, 0, 0, 128, 0, 0, 0, 84, 0, 0, 0, 242, 0, 0, 0, 204, 0, 0, 0, 60, 0, 0, 0, 194, 0, 0, 0, 37, 0, 0, 0, 133, 0, 0, 0, 227, -0, 0, 0, 106, 0, 0, 0, 193, 0, 0, 0, 98, 0, 0, 0, 4, 0, 0, 0, 167, 0, 0, 0, 8, 0, 0, 0, 50, 0, 0, 0, 109, 0, 0, 0, 161, 0, 0, 0, 57, 0, 0, 0, 132, 0, 0, 0, 138, 0, 0, 0, 59, 0, 0, 0, 135, 0, 0, 0, 95, 0, 0, 0, 17, 0, 0, 0, 19, 0, 0, 0, 218, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 102, 0, 0, 0, 196, 0, 0, 0, 12, 0, 0, 0, 115, 0, 0, 0, 110, 0, 0, 0, 188, 0, 0, 0, 36, 0, 0, 0, 181, 0, 0, 0, 249, 0, 0, 0, 112, 0, 0, 0, 129, 0, 0, 0, 82, 0, 0, 0, 233, 0, 0, 0, 244, 0, 0, 0, 124, 0, 0, 0, 35, 0, 0, 0, 221, 0, -0, 0, 159, 0, 0, 0, 184, 0, 0, 0, 70, 0, 0, 0, 239, 0, 0, 0, 29, 0, 0, 0, 34, 0, 0, 0, 85, 0, 0, 0, 125, 0, 0, 0, 113, 0, 0, 0, 196, 0, 0, 0, 66, 0, 0, 0, 51, 0, 0, 0, 197, 0, 0, 0, 55, 0, 0, 0, 105, 0, 0, 0, 91, 0, 0, 0, 168, 0, 0, 0, 198, 0, 0, 0, 157, 0, 0, 0, 164, 0, 0, 0, 252, 0, 0, 0, 97, 0, 0, 0, 110, 0, 0, 0, 104, 0, 0, 0, 70, 0, 0, 0, 234, 0, 0, 0, 215, 0, 0, 0, 28, 0, 0, 0, 103, 0, 0, 0, 210, 0, 0, 0, 125, 0, 0, 0, 250, 0, 0, 0, 241, 0, 0, 0, 204, 0, 0, 0, 84, 0, 0, 0, 141, 0, 0, 0, 54, -0, 0, 0, 53, 0, 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 108, 0, 0, 0, 103, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 0, 0, 0, 77, 0, 0, 0, 66, 0, 0, 0, 41, 0, 0, 0, 93, 0, 0, 0, 164, 0, 0, 0, 107, 0, 0, 0, 111, 0, 0, 0, 168, 0, 0, 0, 138, 0, 0, -0, 77, 0, 0, 0, 145, 0, 0, 0, 123, 0, 0, 0, 210, 0, 0, 0, 223, 0, 0, 0, 54, 0, 0, 0, 239, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 197, 0, 0, 0, 204, 0, 0, 0, 141, 0, 0, 0, 235, 0, 0, 0, 88, 0, 0, 0, 61, 0, 0, 0, 179, 0, 0, 0, 80, 0, 0, 0, 252, 0, 0, 0, 139, 0, 0, 0, 151, 0, 0, 0, 150, 0, 0, 0, 51, 0, 0, 0, 147, 0, 0, 0, 51, 0, 0, 0, 7, 0, 0, 0, 200, 0, 0, 0, 74, 0, 0, 0, 202, 0, 0, 0, 208, 0, 0, 0, 177, 0, 0, 0, 171, 0, 0, 0, 189, 0, 0, 0, 221, 0, 0, 0, 167, 0, 0, 0, 124, 0, 0, 0, 172, 0, 0, 0, 62, 0, -0, 0, 69, 0, 0, 0, 203, 0, 0, 0, 204, 0, 0, 0, 7, 0, 0, 0, 145, 0, 0, 0, 191, 0, 0, 0, 53, 0, 0, 0, 157, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 18, 0, 0, 0, 60, 0, 0, 0, 17, 0, 0, 0, 89, 0, 0, 0, 19, 0, 0, 0, 207, 0, 0, 0, 92, 0, 0, 0, 69, 0, 0, 0, 184, 0, 0, 0, 65, 0, 0, 0, 215, 0, 0, 0, 171, 0, 0, 0, 7, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, 206, 0, 0, 0, 223, 0, 0, 0, 178, 0, 0, 0, 67, 0, 0, 0, 92, 0, 0, 0, 1, 0, 0, 0, 220, 0, 0, 0, 244, 0, 0, 0, 1, 0, 0, 0, 81, 0, 0, 0, 149, 0, 0, 0, 16, -0, 0, 0, 90, 0, 0, 0, 246, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 160, 0, 0, 0, 25, 0, 0, 0, 58, 0, 0, 0, 9, 0, 0, 0, 42, 0, 0, 0, 170, 0, 0, 0, 63, 0, 0, 0, 220, 0, 0, 0, 142, 0, 0, 0, 235, 0, 0, 0, 198, 0, 0, 0, 191, 0, 0, 0, 221, 0, 0, 0, 17, 0, 0, 0, 123, 0, 0, 0, 231, 0, 0, 0, 71, 0, 0, 0, 230, 0, 0, 0, 206, 0, 0, 0, 231, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 232, 0, 0, 0, 138, 0, 0, 0, 220, 0, 0, 0, 75, 0, 0, 0, 87, 0, 0, 0, 21, 0, 0, 0, 59, 0, 0, 0, 102, 0, 0, 0, 202, 0, 0, 0, 137, 0, 0, 0, 163, -0, 0, 0, 253, 0, 0, 0, 172, 0, 0, 0, 13, 0, 0, 0, 225, 0, 0, 0, 29, 0, 0, 0, 122, 0, 0, 0, 137, 0, 0, 0, 239, 0, 0, 0, 191, 0, 0, 0, 3, 0, 0, 0, 117, 0, 0, 0, 208, 0, 0, 0, 41, 0, 0, 0, 80, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 214, 0, 0, 0, 190, 0, 0, 0, 173, 0, 0, 0, 95, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 170, 0, 0, 0, 152, 0, 0, 0, 237, 0, 0, 0, 63, 0, 0, 0, 143, 0, 0, 0, 146, 0, 0, 0, 203, 0, 0, 0, 129, 0, 0, 0, 86, 0, 0, 0, 1, 0, 0, 0, 99, 0, 0, 0, 100, 0, 0, 0, 163, 0, 0, 0, 56, -0, 0, 0, 57, 0, 0, 0, 139, 0, 0, 0, 164, 0, 0, 0, 214, 0, 0, 0, 80, 0, 0, 0, 180, 0, 0, 0, 170, 0, 0, 0, 93, 0, 0, 0, 100, 0, 0, 0, 100, 0, 0, 0, 118, 0, 0, 0, 46, 0, 0, 0, 161, 0, 0, 0, 166, 0, 0, 0, 179, 0, 0, 0, 184, 0, 0, 0, 124, 0, 0, 0, 122, 0, 0, 0, 86, 0, 0, 0, 245, 0, 0, 0, 92, 0, 0, 0, 78, 0, 0, 0, 132, 0, 0, 0, 92, 0, 0, 0, 251, 0, 0, 0, 221, 0, 0, 0, 202, 0, 0, 0, 72, 0, 0, 0, 139, 0, 0, 0, 72, 0, 0, 0, 185, 0, 0, 0, 186, 0, 0, 0, 52, 0, 0, 0, 197, 0, 0, 0, 227, 0, 0, 0, 232, 0, 0, 0, -174, 0, 0, 0, 23, 0, 0, 0, 39, 0, 0, 0, 227, 0, 0, 0, 100, 0, 0, 0, 96, 0, 0, 0, 113, 0, 0, 0, 71, 0, 0, 0, 41, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 146, 0, 0, 0, 93, 0, 0, 0, 16, 0, 0, 0, 147, 0, 0, 0, 200, 0, 0, 0, 14, 0, 0, 0, 161, 0, 0, 0, 237, 0, 0, 0, 186, 0, 0, 0, 169, 0, 0, 0, 150, 0, 0, 0, 28, 0, 0, 0, 197, 0, 0, 0, 118, 0, 0, 0, 48, 0, 0, 0, 205, 0, 0, 0, 249, 0, 0, 0, 48, 0, 0, 0, 149, 0, 0, 0, 176, 0, 0, 0, 189, 0, 0, 0, 140, 0, 0, 0, 188, 0, 0, 0, 167, 0, 0, 0, 79, 0, 0, 0, 126, 0, 0, 0, -253, 0, 0, 0, 78, 0, 0, 0, 58, 0, 0, 0, 191, 0, 0, 0, 95, 0, 0, 0, 4, 0, 0, 0, 121, 0, 0, 0, 128, 0, 0, 0, 43, 0, 0, 0, 90, 0, 0, 0, 159, 0, 0, 0, 79, 0, 0, 0, 104, 0, 0, 0, 33, 0, 0, 0, 25, 0, 0, 0, 113, 0, 0, 0, 198, 0, 0, 0, 32, 0, 0, 0, 1, 0, 0, 0, 66, 0, 0, 0, 170, 0, 0, 0, 223, 0, 0, 0, 174, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 110, 0, 0, 0, 126, 0, 0, 0, 75, 0, 0, 0, 113, 0, 0, 0, 147, 0, 0, 0, 192, 0, 0, 0, 114, 0, 0, 0, 237, 0, 0, 0, 235, 0, 0, 0, 113, 0, 0, 0, 36, 0, 0, 0, 151, 0, 0, 0, 38, 0, 0, 0, 156, 0, 0, 0, 254, 0, 0, 0, 203, 0, 0, 0, 62, 0, 0, 0, 89, 0, 0, 0, 25, 0, 0, 0, 168, 0, 0, 0, 15, 0, 0, 0, 117, 0, 0, 0, 125, 0, 0, 0, 190, 0, 0, 0, 24, 0, 0, 0, 230, 0, 0, 0, 150, 0, 0, 0, 30, 0, 0, 0, 149, 0, 0, 0, 112, -0, 0, 0, 96, 0, 0, 0, 137, 0, 0, 0, 102, 0, 0, 0, 62, 0, 0, 0, 29, 0, 0, 0, 76, 0, 0, 0, 95, 0, 0, 0, 254, 0, 0, 0, 192, 0, 0, 0, 4, 0, 0, 0, 67, 0, 0, 0, 214, 0, 0, 0, 68, 0, 0, 0, 25, 0, 0, 0, 181, 0, 0, 0, 173, 0, 0, 0, 199, 0, 0, 0, 34, 0, 0, 0, 220, 0, 0, 0, 113, 0, 0, 0, 40, 0, 0, 0, 100, 0, 0, 0, 222, 0, 0, 0, 65, 0, 0, 0, 56, 0, 0, 0, 39, 0, 0, 0, 143, 0, 0, 0, 44, 0, 0, 0, 107, 0, 0, 0, 8, 0, 0, 0, 184, 0, 0, 0, 184, 0, 0, 0, 123, 0, 0, 0, 61, 0, 0, 0, 112, 0, 0, 0, 39, 0, 0, 0, 157, 0, -0, 0, 217, 0, 0, 0, 175, 0, 0, 0, 177, 0, 0, 0, 39, 0, 0, 0, 175, 0, 0, 0, 227, 0, 0, 0, 93, 0, 0, 0, 30, 0, 0, 0, 58, 0, 0, 0, 48, 0, 0, 0, 84, 0, 0, 0, 97, 0, 0, 0, 96, 0, 0, 0, 232, 0, 0, 0, 195, 0, 0, 0, 38, 0, 0, 0, 58, 0, 0, 0, 188, 0, 0, 0, 126, 0, 0, 0, 245, 0, 0, 0, 129, 0, 0, 0, 221, 0, 0, 0, 100, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 235, 0, 0, 0, 192, 0, 0, 0, 30, 0, 0, 0, 218, 0, 0, 0, 44, 0, 0, 0, 164, 0, 0, 0, 209, 0, 0, 0, 161, 0, 0, 0, 195, 0, 0, 0, 92, 0, 0, 0, 110, 0, 0, 0, 50, 0, 0, -0, 7, 0, 0, 0, 31, 0, 0, 0, 184, 0, 0, 0, 14, 0, 0, 0, 25, 0, 0, 0, 158, 0, 0, 0, 153, 0, 0, 0, 41, 0, 0, 0, 51, 0, 0, 0, 154, 0, 0, 0, 174, 0, 0, 0, 122, 0, 0, 0, 237, 0, 0, 0, 104, 0, 0, 0, 66, 0, 0, 0, 105, 0, 0, 0, 124, 0, 0, 0, 7, 0, 0, 0, 179, 0, 0, 0, 56, 0, 0, 0, 44, 0, 0, 0, 246, 0, 0, 0, 61, 0, 0, 0, 100, 0, 0, 0, 170, 0, 0, 0, 181, 0, 0, 0, 136, 0, 0, 0, 121, 0, 0, 0, 101, 0, 0, 0, 56, 0, 0, 0, 140, 0, 0, 0, 148, 0, 0, 0, 214, 0, 0, 0, 98, 0, 0, 0, 55, 0, 0, 0, 125, 0, 0, 0, 100, 0, 0, -0, 205, 0, 0, 0, 58, 0, 0, 0, 235, 0, 0, 0, 255, 0, 0, 0, 232, 0, 0, 0, 129, 0, 0, 0, 9, 0, 0, 0, 199, 0, 0, 0, 106, 0, 0, 0, 80, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 40, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 0, 154, 0, 0, 0, 147, 0, 0, 0, 10, 0, 0, 0, 66, 0, 0, 0, 163, 0, 0, 0, 241, 0, 0, 0, 197, 0, 0, 0, 180, 0, 0, 0, 15, 0, 0, 0, 216, 0, 0, 0, 200, 0, 0, 0, 141, 0, 0, 0, 21, 0, 0, 0, 49, 0, 0, 0, 189, 0, 0, 0, 248, 0, 0, 0, 7, 0, 0, 0, 139, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, 138, 0, 0, 0, 251, 0, 0, 0, -24, 0, 0, 0, 7, 0, 0, 0, 254, 0, 0, 0, 142, 0, 0, 0, 82, 0, 0, 0, 134, 0, 0, 0, 239, 0, 0, 0, 190, 0, 0, 0, 236, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 153, 0, 0, 0, 8, 0, 0, 0, 15, 0, 0, 0, 169, 0, 0, 0, 213, 0, 0, 0, 1, 0, 0, 0, 170, 0, 0, 0, 72, 0, 0, 0, 79, 0, 0, 0, 40, 0, 0, 0, 102, 0, 0, 0, 50, 0, 0, 0, 26, 0, 0, 0, 186, 0, 0, 0, 124, 0, 0, 0, 234, 0, 0, 0, 17, 0, 0, 0, 128, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 155, 0, 0, 0, 86, 0, 0, 0, 136, 0, 0, 0, 37, 0, 0, 0, 6, 0, 0, 0, 105, 0, 0, 0, 18, 0, -0, 0, 44, 0, 0, 0, 234, 0, 0, 0, 86, 0, 0, 0, 105, 0, 0, 0, 65, 0, 0, 0, 36, 0, 0, 0, 25, 0, 0, 0, 222, 0, 0, 0, 33, 0, 0, 0, 240, 0, 0, 0, 218, 0, 0, 0, 138, 0, 0, 0, 251, 0, 0, 0, 177, 0, 0, 0, 184, 0, 0, 0, 205, 0, 0, 0, 200, 0, 0, 0, 106, 0, 0, 0, 130, 0, 0, 0, 25, 0, 0, 0, 115, 0, 0, 0, 219, 0, 0, 0, 199, 0, 0, 0, 207, 0, 0, 0, 136, 0, 0, 0, 235, 0, 0, 0, 150, 0, 0, 0, 238, 0, 0, 0, 111, 0, 0, 0, 251, 0, 0, 0, 6, 0, 0, 0, 210, 0, 0, 0, 205, 0, 0, 0, 125, 0, 0, 0, 123, 0, 0, 0, 18, 0, 0, 0, 40, -0, 0, 0, 142, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, 68, 0, 0, 0, 151, 0, 0, 0, 206, 0, 0, 0, 40, 0, 0, 0, 255, 0, 0, 0, 58, 0, 0, 0, 64, 0, 0, 0, 196, 0, 0, 0, 245, 0, 0, 0, 246, 0, 0, 0, 155, 0, 0, 0, 244, 0, 0, 0, 107, 0, 0, 0, 7, 0, -0, 0, 132, 0, 0, 0, 251, 0, 0, 0, 152, 0, 0, 0, 216, 0, 0, 0, 236, 0, 0, 0, 140, 0, 0, 0, 3, 0, 0, 0, 87, 0, 0, 0, 236, 0, 0, 0, 73, 0, 0, 0, 237, 0, 0, 0, 99, 0, 0, 0, 182, 0, 0, 0, 170, 0, 0, 0, 255, 0, 0, 0, 152, 0, 0, 0, 40, 0, 0, 0, 61, 0, 0, 0, 22, 0, 0, 0, 53, 0, 0, 0, 243, 0, 0, 0, 70, 0, 0, 0, 188, 0, 0, 0, 179, 0, 0, 0, 244, 0, 0, 0, 198, 0, 0, 0, 182, 0, 0, 0, 79, 0, 0, 0, 250, 0, 0, 0, 244, 0, 0, 0, 160, 0, 0, 0, 19, 0, 0, 0, 230, 0, 0, 0, 87, 0, 0, 0, 69, 0, 0, 0, 147, 0, 0, 0, 185, -0, 0, 0, 188, 0, 0, 0, 214, 0, 0, 0, 89, 0, 0, 0, 231, 0, 0, 0, 119, 0, 0, 0, 148, 0, 0, 0, 108, 0, 0, 0, 171, 0, 0, 0, 150, 0, 0, 0, 59, 0, 0, 0, 79, 0, 0, 0, 9, 0, 0, 0, 90, 0, 0, 0, 247, 0, 0, 0, 107, 0, 0, 0, 1, 0, 0, 0, 18, 0, 0, 0, 79, 0, 0, 0, 81, 0, 0, 0, 193, 0, 0, 0, 112, 0, 0, 0, 132, 0, 0, 0, 148, 0, 0, 0, 71, 0, 0, 0, 178, 0, 0, 0, 1, 0, 0, 0, 108, 0, 0, 0, 113, 0, 0, 0, 215, 0, 0, 0, 204, 0, 0, 0, 23, 0, 0, 0, 102, 0, 0, 0, 15, 0, 0, 0, 89, 0, 0, 0, 93, 0, 0, 0, 93, 0, 0, 0, 16, 0, -0, 0, 1, 0, 0, 0, 87, 0, 0, 0, 17, 0, 0, 0, 245, 0, 0, 0, 221, 0, 0, 0, 226, 0, 0, 0, 52, 0, 0, 0, 38, 0, 0, 0, 217, 0, 0, 0, 31, 0, 0, 0, 92, 0, 0, 0, 88, 0, 0, 0, 172, 0, 0, 0, 139, 0, 0, 0, 3, 0, 0, 0, 210, 0, 0, 0, 195, 0, 0, 0, 133, 0, 0, 0, 15, 0, 0, 0, 58, 0, 0, 0, 195, 0, 0, 0, 127, 0, 0, 0, 109, 0, 0, 0, 142, 0, 0, 0, 134, 0, 0, 0, 205, 0, 0, 0, 82, 0, 0, 0, 116, 0, 0, 0, 143, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 23, 0, 0, 0, 183, 0, 0, 0, 142, 0, 0, 0, 183, 0, 0, 0, 136, 0, 0, 0, 234, 0, -0, 0, 218, 0, 0, 0, 27, 0, 0, 0, 182, 0, 0, 0, 234, 0, 0, 0, 14, 0, 0, 0, 64, 0, 0, 0, 147, 0, 0, 0, 32, 0, 0, 0, 121, 0, 0, 0, 53, 0, 0, 0, 106, 0, 0, 0, 97, 0, 0, 0, 132, 0, 0, 0, 90, 0, 0, 0, 7, 0, 0, 0, 109, 0, 0, 0, 249, 0, 0, 0, 119, 0, 0, 0, 111, 0, 0, 0, 237, 0, 0, 0, 105, 0, 0, 0, 28, 0, 0, 0, 13, 0, 0, 0, 37, 0, 0, 0, 118, 0, 0, 0, 204, 0, 0, 0, 240, 0, 0, 0, 219, 0, 0, 0, 187, 0, 0, 0, 197, 0, 0, 0, 173, 0, 0, 0, 226, 0, 0, 0, 38, 0, 0, 0, 87, 0, 0, 0, 207, 0, 0, 0, 232, 0, 0, 0, 14, 0, -0, 0, 107, 0, 0, 0, 150, 0, 0, 0, 125, 0, 0, 0, 237, 0, 0, 0, 39, 0, 0, 0, 209, 0, 0, 0, 60, 0, 0, 0, 169, 0, 0, 0, 217, 0, 0, 0, 80, 0, 0, 0, 169, 0, 0, 0, 152, 0, 0, 0, 132, 0, 0, 0, 94, 0, 0, 0, 134, 0, 0, 0, 239, 0, 0, 0, 214, 0, 0, 0, 240, 0, 0, 0, 248, 0, 0, 0, 14, 0, 0, 0, 137, 0, 0, 0, 5, 0, 0, 0, 47, 0, 0, 0, 217, 0, 0, 0, 95, 0, 0, 0, 21, 0, 0, 0, 95, 0, 0, 0, 115, 0, 0, 0, 121, 0, 0, 0, 200, 0, 0, 0, 92, 0, 0, 0, 22, 0, 0, 0, 254, 0, 0, 0, 237, 0, 0, 0, 159, 0, 0, 0, 38, 0, 0, 0, 86, 0, -0, 0, 246, 0, 0, 0, 75, 0, 0, 0, 159, 0, 0, 0, 167, 0, 0, 0, 10, 0, 0, 0, 133, 0, 0, 0, 254, 0, 0, 0, 165, 0, 0, 0, 140, 0, 0, 0, 135, 0, 0, 0, 221, 0, 0, 0, 152, 0, 0, 0, 206, 0, 0, 0, 78, 0, 0, 0, 195, 0, 0, 0, 88, 0, 0, 0, 85, 0, 0, 0, 178, 0, 0, 0, 123, 0, 0, 0, 61, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, 181, 0, 0, 0, 76, 0, 0, 0, 101, 0, 0, 0, 56, 0, 0, 0, 160, 0, 0, 0, 21, 0, 0, 0, 250, 0, 0, 0, 167, 0, 0, 0, 180, 0, 0, 0, 143, 0, 0, 0, 235, 0, 0, 0, 196, 0, 0, 0, 134, 0, 0, 0, 155, 0, 0, 0, -48, 0, 0, 0, 165, 0, 0, 0, 94, 0, 0, 0, 77, 0, 0, 0, 234, 0, 0, 0, 138, 0, 0, 0, 154, 0, 0, 0, 159, 0, 0, 0, 26, 0, 0, 0, 216, 0, 0, 0, 91, 0, 0, 0, 83, 0, 0, 0, 20, 0, 0, 0, 25, 0, 0, 0, 37, 0, 0, 0, 99, 0, 0, 0, 180, 0, 0, 0, 111, 0, 0, 0, 31, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 143, 0, 0, 0, 188, 0, 0, 0, 30, 0, 0, 0, 125, 0, 0, 0, 139, 0, 0, 0, 90, 0, 0, 0, 11, 0, 0, 0, 141, 0, 0, 0, 175, 0, 0, 0, 118, 0, 0, 0, 46, 0, 0, 0, 113, 0, 0, 0, 227, 0, 0, 0, 59, 0, 0, 0, 111, 0, 0, 0, 83, 0, 0, 0, 47, 0, 0, 0, 62, 0, 0, 0, 144, 0, 0, 0, 149, 0, 0, 0, 212, 0, 0, 0, 53, 0, 0, 0, 20, 0, 0, 0, 79, 0, 0, 0, 140, 0, 0, 0, 60, 0, 0, 0, 206, 0, 0, 0, 87, 0, 0, 0, 28, 0, 0, 0, 118, 0, 0, 0, 73, 0, 0, 0, 168, 0, 0, 0, 80, 0, 0, 0, 225, 0, -0, 0, 97, 0, 0, 0, 107, 0, 0, 0, 87, 0, 0, 0, 53, 0, 0, 0, 235, 0, 0, 0, 68, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 110, 0, 0, 0, 249, 0, 0, 0, 37, 0, 0, 0, 128, 0, 0, 0, 116, 0, 0, 0, 242, 0, 0, 0, 143, 0, 0, 0, 111, 0, 0, 0, 122, 0, 0, 0, 62, 0, 0, 0, 127, 0, 0, 0, 45, 0, 0, 0, 243, 0, 0, 0, 78, 0, 0, 0, 9, 0, 0, 0, 101, 0, 0, 0, 16, 0, 0, 0, 94, 0, 0, 0, 3, 0, 0, 0, 37, 0, 0, 0, 50, 0, 0, 0, 169, 0, 0, 0, 96, 0, 0, 0, 220, 0, 0, 0, 15, 0, 0, 0, 100, 0, 0, 0, 229, 0, 0, 0, 29, 0, 0, 0, 226, 0, 0, 0, -141, 0, 0, 0, 79, 0, 0, 0, 121, 0, 0, 0, 47, 0, 0, 0, 14, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 119, 0, 0, 0, 67, 0, 0, 0, 37, 0, 0, 0, 61, 0, 0, 0, 106, 0, 0, 0, 199, 0, 0, 0, 183, 0, 0, 0, 191, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 101, 0, 0, 0, 244, 0, 0, 0, 57, 0, 0, 0, 75, 0, 0, 0, 101, 0, 0, 0, 150, 0, 0, 0, 25, 0, 0, 0, 18, 0, 0, 0, 107, 0, 0, 0, 106, 0, 0, 0, 183, 0, 0, 0, 227, 0, 0, 0, 220, 0, 0, 0, 69, 0, 0, 0, 155, 0, 0, 0, 219, 0, 0, 0, 180, 0, 0, 0, 168, 0, 0, 0, 174, -0, 0, 0, 220, 0, 0, 0, 168, 0, 0, 0, 20, 0, 0, 0, 68, 0, 0, 0, 101, 0, 0, 0, 98, 0, 0, 0, 206, 0, 0, 0, 52, 0, 0, 0, 154, 0, 0, 0, 132, 0, 0, 0, 24, 0, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 241, 0, 0, 0, 226, 0, 0, 0, 123, 0, 0, 0, 206, 0, 0, 0, 80, 0, 0, 0, 65, 0, 0, 0, 33, 0, 0, 0, 48, 0, 0, 0, 83, 0, 0, 0, 27, 0, 0, 0, 71, 0, 0, 0, 1, 0, 0, 0, 183, 0, 0, 0, 24, 0, 0, 0, 216, 0, 0, 0, 130, 0, 0, 0, 87, 0, 0, 0, 189, 0, 0, 0, 163, 0, 0, 0, 96, 0, 0, 0, 240, 0, 0, 0, 50, 0, 0, 0, 246, 0, 0, 0, 91, 0, 0, -0, 240, 0, 0, 0, 48, 0, 0, 0, 136, 0, 0, 0, 145, 0, 0, 0, 89, 0, 0, 0, 253, 0, 0, 0, 144, 0, 0, 0, 162, 0, 0, 0, 185, 0, 0, 0, 85, 0, 0, 0, 147, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 151, 0, 0, 0, 103, 0, 0, 0, 158, 0, 0, 0, 235, 0, 0, 0, 106, 0, 0, 0, 249, 0, 0, 0, 110, 0, 0, 0, 214, 0, 0, 0, 115, 0, 0, 0, 232, 0, 0, 0, 107, 0, 0, 0, 41, 0, 0, 0, 236, 0, 0, 0, 99, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 153, 0, 0, 0, 28, 0, 0, 0, 29, 0, 0, 0, 48, 0, 0, 0, 200, 0, 0, 0, 144, 0, 0, 0, 82, 0, -0, 0, 144, 0, 0, 0, 182, 0, 0, 0, 106, 0, 0, 0, 128, 0, 0, 0, 78, 0, 0, 0, 255, 0, 0, 0, 75, 0, 0, 0, 81, 0, 0, 0, 15, 0, 0, 0, 125, 0, 0, 0, 99, 0, 0, 0, 140, 0, 0, 0, 110, 0, 0, 0, 92, 0, 0, 0, 222, 0, 0, 0, 48, 0, 0, 0, 223, 0, 0, 0, 101, 0, 0, 0, 250, 0, 0, 0, 46, 0, 0, 0, 176, 0, 0, 0, 163, 0, 0, 0, 37, 0, 0, 0, 5, 0, 0, 0, 84, 0, 0, 0, 189, 0, 0, 0, 37, 0, 0, 0, 186, 0, 0, 0, 6, 0, 0, 0, 174, 0, 0, 0, 223, 0, 0, 0, 139, 0, 0, 0, 217, 0, 0, 0, 27, 0, 0, 0, 234, 0, 0, 0, 56, 0, 0, 0, 179, 0, -0, 0, 5, 0, 0, 0, 22, 0, 0, 0, 9, 0, 0, 0, 199, 0, 0, 0, 140, 0, 0, 0, 191, 0, 0, 0, 100, 0, 0, 0, 40, 0, 0, 0, 173, 0, 0, 0, 248, 0, 0, 0, 165, 0, 0, 0, 90, 0, 0, 0, 111, 0, 0, 0, 201, 0, 0, 0, 186, 0, 0, 0, 213, 0, 0, 0, 127, 0, 0, 0, 213, 0, 0, 0, 214, 0, 0, 0, 189, 0, 0, 0, 102, 0, 0, 0, 47, 0, 0, 0, 61, 0, 0, 0, 170, 0, 0, 0, 84, 0, 0, 0, 246, 0, 0, 0, 186, 0, 0, 0, 50, 0, 0, 0, 34, 0, 0, 0, 154, 0, 0, 0, 30, 0, 0, 0, 82, 0, 0, 0, 5, 0, 0, 0, 244, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 0, 0, 0, 31, 0, 0, 0, 187, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 228, 0, 0, 0, 135, 0, 0, 0, 252, 0, 0, 0, 177, 0, 0, 0, 44, 0, 0, 0, 183, 0, 0, 0, 136, 0, 0, 0, 244, 0, 0, 0, 198, 0, 0, 0, 185, 0, 0, 0, 245, 0, 0, 0, 36, 0, 0, 0, 70, 0, 0, 0, 242, 0, 0, -0, 165, 0, 0, 0, 159, 0, 0, 0, 143, 0, 0, 0, 138, 0, 0, 0, 147, 0, 0, 0, 112, 0, 0, 0, 105, 0, 0, 0, 212, 0, 0, 0, 86, 0, 0, 0, 236, 0, 0, 0, 253, 0, 0, 0, 6, 0, 0, 0, 70, 0, 0, 0, 78, 0, 0, 0, 102, 0, 0, 0, 207, 0, 0, 0, 78, 0, 0, 0, 52, 0, 0, 0, 206, 0, 0, 0, 12, 0, 0, 0, 217, 0, 0, 0, 166, 0, 0, 0, 80, 0, 0, 0, 214, 0, 0, 0, 94, 0, 0, 0, 149, 0, 0, 0, 175, 0, 0, 0, 233, 0, 0, 0, 88, 0, 0, 0, 250, 0, 0, 0, 238, 0, 0, 0, 155, 0, 0, 0, 184, 0, 0, 0, 165, 0, 0, 0, 15, 0, 0, 0, 53, 0, 0, 0, 224, 0, -0, 0, 67, 0, 0, 0, 130, 0, 0, 0, 109, 0, 0, 0, 101, 0, 0, 0, 230, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 123, 0, 0, 0, 117, 0, 0, 0, 58, 0, 0, 0, 252, 0, 0, 0, 100, 0, 0, 0, 211, 0, 0, 0, 41, 0, 0, 0, 126, 0, 0, 0, 221, 0, 0, 0, 73, 0, 0, 0, 154, 0, 0, 0, 89, 0, 0, 0, 83, 0, 0, 0, 191, 0, 0, 0, 180, 0, 0, 0, 167, 0, 0, 0, 82, 0, 0, 0, 179, 0, 0, 0, 5, 0, 0, 0, 171, 0, 0, 0, 195, 0, 0, 0, 175, 0, 0, 0, 22, 0, 0, 0, 26, 0, 0, 0, 133, 0, 0, 0, 66, 0, 0, 0, 50, 0, 0, 0, 162, 0, 0, 0, 134, 0, -0, 0, 250, 0, 0, 0, 57, 0, 0, 0, 67, 0, 0, 0, 14, 0, 0, 0, 75, 0, 0, 0, 163, 0, 0, 0, 99, 0, 0, 0, 138, 0, 0, 0, 254, 0, 0, 0, 165, 0, 0, 0, 88, 0, 0, 0, 241, 0, 0, 0, 19, 0, 0, 0, 189, 0, 0, 0, 157, 0, 0, 0, 170, 0, 0, 0, 127, 0, 0, 0, 118, 0, 0, 0, 64, 0, 0, 0, 112, 0, 0, 0, 129, 0, 0, 0, 16, 0, 0, 0, 117, 0, 0, 0, 153, 0, 0, 0, 187, 0, 0, 0, 190, 0, 0, 0, 11, 0, 0, 0, 22, 0, 0, 0, 233, 0, 0, 0, 186, 0, 0, 0, 98, 0, 0, 0, 52, 0, 0, 0, 204, 0, 0, 0, 7, 0, 0, 0, 109, 0, 0, 0, 195, 0, 0, 0, 241, 0, -0, 0, 198, 0, 0, 0, 147, 0, 0, 0, 101, 0, 0, 0, 238, 0, 0, 0, 11, 0, 0, 0, 188, 0, 0, 0, 234, 0, 0, 0, 20, 0, 0, 0, 240, 0, 0, 0, 193, 0, 0, 0, 248, 0, 0, 0, 132, 0, 0, 0, 137, 0, 0, 0, 194, 0, 0, 0, 201, 0, 0, 0, 215, 0, 0, 0, 234, 0, 0, 0, 52, 0, 0, 0, 202, 0, 0, 0, 167, 0, 0, 0, 196, 0, 0, 0, 153, 0, 0, 0, 213, 0, 0, 0, 80, 0, 0, 0, 105, 0, 0, 0, 203, 0, 0, 0, 214, 0, 0, 0, 33, 0, 0, 0, 99, 0, 0, 0, 124, 0, 0, 0, 153, 0, 0, 0, 235, 0, 0, 0, 124, 0, 0, 0, 49, 0, 0, 0, 115, 0, 0, 0, 100, 0, 0, 0, -103, 0, 0, 0, 127, 0, 0, 0, 12, 0, 0, 0, 102, 0, 0, 0, 170, 0, 0, 0, 140, 0, 0, 0, 105, 0, 0, 0, 145, 0, 0, 0, 226, 0, 0, 0, 38, 0, 0, 0, 211, 0, 0, 0, 35, 0, 0, 0, 226, 0, 0, 0, 118, 0, 0, 0, 93, 0, 0, 0, 50, 0, 0, 0, 82, 0, 0, 0, 223, 0, 0, 0, 93, 0, 0, 0, 197, 0, 0, 0, 143, 0, 0, 0, 183, 0, 0, 0, 124, 0, 0, 0, 132, 0, 0, 0, 179, 0, 0, 0, 112, 0, 0, 0, 235, 0, 0, 0, 1, 0, 0, 0, 199, 0, 0, 0, 54, 0, 0, 0, 151, 0, 0, 0, 78, 0, 0, 0, 182, 0, 0, 0, 171, 0, 0, 0, 95, 0, 0, 0, 13, 0, 0, 0, 44, 0, 0, -0, 186, 0, 0, 0, 103, 0, 0, 0, 100, 0, 0, 0, 85, 0, 0, 0, 222, 0, 0, 0, 188, 0, 0, 0, 255, 0, 0, 0, 166, 0, 0, 0, 236, 0, 0, 0, 4, 0, 0, 0, 211, 0, 0, 0, 141, 0, 0, 0, 57, 0, 0, 0, 86, 0, 0, 0, 94, 0, 0, 0, 238, 0, 0, 0, 248, 0, 0, 0, 228, 0, 0, 0, 46, 0, 0, 0, 51, 0, 0, 0, 98, 0, 0, 0, 101, 0, 0, 0, 239, 0, 0, 0, 184, 0, 0, 0, 159, 0, 0, 0, 200, 0, 0, 0, 75, 0, 0, 0, 167, 0, 0, 0, 253, 0, 0, 0, 33, 0, 0, 0, 73, 0, 0, 0, 155, 0, 0, 0, 146, 0, 0, 0, 53, 0, 0, 0, 130, 0, 0, 0, 214, 0, 0, 0, 10, 0, -0, 0, 155, 0, 0, 0, 242, 0, 0, 0, 121, 0, 0, 0, 241, 0, 0, 0, 71, 0, 0, 0, 47, 0, 0, 0, 106, 0, 0, 0, 126, 0, 0, 0, 159, 0, 0, 0, 207, 0, 0, 0, 24, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 251, 0, 0, 0, 27, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, -139, 0, 0, 0, 200, 0, 0, 0, 64, 0, 0, 0, 81, 0, 0, 0, 209, 0, 0, 0, 172, 0, 0, 0, 26, 0, 0, 0, 11, 0, 0, 0, 228, 0, 0, 0, 169, 0, 0, 0, 162, 0, 0, 0, 66, 0, 0, 0, 33, 0, 0, 0, 25, 0, 0, 0, 47, 0, 0, 0, 123, 0, 0, 0, 151, 0, 0, 0, 191, 0, 0, 0, 247, 0, 0, 0, 87, 0, 0, 0, 109, 0, 0, 0, 63, 0, 0, 0, 61, 0, 0, 0, 79, 0, 0, 0, 15, 0, 0, 0, 226, 0, 0, 0, 178, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 158, 0, 0, 0, 123, 0, 0, 0, 140, 0, 0, 0, 133, 0, 0, 0, 43, 0, 0, 0, 196, 0, 0, 0, 252, 0, 0, 0, 241, 0, 0, 0, -171, 0, 0, 0, 232, 0, 0, 0, 121, 0, 0, 0, 34, 0, 0, 0, 196, 0, 0, 0, 132, 0, 0, 0, 23, 0, 0, 0, 58, 0, 0, 0, 250, 0, 0, 0, 134, 0, 0, 0, 166, 0, 0, 0, 125, 0, 0, 0, 249, 0, 0, 0, 243, 0, 0, 0, 111, 0, 0, 0, 3, 0, 0, 0, 87, 0, 0, 0, 32, 0, 0, 0, 77, 0, 0, 0, 121, 0, 0, 0, 249, 0, 0, 0, 110, 0, 0, 0, 113, 0, 0, 0, 84, 0, 0, 0, 56, 0, 0, 0, 9, 0, 0, 0, 64, 0, 0, 0, 41, 0, 0, 0, 116, 0, 0, 0, 168, 0, 0, 0, 47, 0, 0, 0, 94, 0, 0, 0, 249, 0, 0, 0, 121, 0, 0, 0, 164, 0, 0, 0, 243, 0, 0, 0, 62, 0, 0, 0, -185, 0, 0, 0, 253, 0, 0, 0, 51, 0, 0, 0, 49, 0, 0, 0, 172, 0, 0, 0, 154, 0, 0, 0, 105, 0, 0, 0, 136, 0, 0, 0, 30, 0, 0, 0]).concat([119, 0, 0, 0, 33, 0, 0, 0, 45, 0, 0, 0, 243, 0, 0, 0, 145, 0, 0, 0, 82, 0, 0, 0, 38, 0, 0, 0, 21, 0, 0, 0, 178, 0, 0, 0, 166, 0, 0, 0, 207, 0, 0, 0, 126, 0, 0, 0, 198, 0, 0, 0, 32, 0, 0, 0, 71, 0, 0, 0, 108, 0, 0, 0, 164, 0, 0, 0, 125, 0, 0, 0, 203, 0, 0, 0, 99, 0, 0, 0, 234, 0, 0, 0, 91, 0, 0, 0, 3, 0, 0, 0, 223, 0, 0, 0, 62, 0, 0, 0, 136, 0, 0, 0, 129, 0, 0, 0, 109, -0, 0, 0, 206, 0, 0, 0, 7, 0, 0, 0, 66, 0, 0, 0, 24, 0, 0, 0, 96, 0, 0, 0, 126, 0, 0, 0, 123, 0, 0, 0, 85, 0, 0, 0, 254, 0, 0, 0, 106, 0, 0, 0, 243, 0, 0, 0, 218, 0, 0, 0, 92, 0, 0, 0, 139, 0, 0, 0, 149, 0, 0, 0, 16, 0, 0, 0, 98, 0, 0, 0, 228, 0, 0, 0, 13, 0, 0, 0, 3, 0, 0, 0, 180, 0, 0, 0, 215, 0, 0, 0, 205, 0, 0, 0, 250, 0, 0, 0, 189, 0, 0, 0, 70, 0, 0, 0, 223, 0, 0, 0, 147, 0, 0, 0, 113, 0, 0, 0, 16, 0, 0, 0, 44, 0, 0, 0, 168, 0, 0, 0, 59, 0, 0, 0, 182, 0, 0, 0, 9, 0, 0, 0, 5, 0, 0, 0, 112, 0, -0, 0, 132, 0, 0, 0, 67, 0, 0, 0, 41, 0, 0, 0, 168, 0, 0, 0, 89, 0, 0, 0, 245, 0, 0, 0, 142, 0, 0, 0, 16, 0, 0, 0, 228, 0, 0, 0, 215, 0, 0, 0, 32, 0, 0, 0, 87, 0, 0, 0, 130, 0, 0, 0, 28, 0, 0, 0, 171, 0, 0, 0, 191, 0, 0, 0, 98, 0, 0, 0, 112, 0, 0, 0, 232, 0, 0, 0, 196, 0, 0, 0, 207, 0, 0, 0, 240, 0, 0, 0, 40, 0, 0, 0, 110, 0, 0, 0, 22, 0, 0, 0, 60, 0, 0, 0, 8, 0, 0, 0, 120, 0, 0, 0, 137, 0, 0, 0, 133, 0, 0, 0, 70, 0, 0, 0, 15, 0, 0, 0, 246, 0, 0, 0, 127, 0, 0, 0, 207, 0, 0, 0, 203, 0, 0, 0, 126, 0, -0, 0, 184, 0, 0, 0, 37, 0, 0, 0, 233, 0, 0, 0, 90, 0, 0, 0, 250, 0, 0, 0, 3, 0, 0, 0, 251, 0, 0, 0, 149, 0, 0, 0, 146, 0, 0, 0, 99, 0, 0, 0, 80, 0, 0, 0, 252, 0, 0, 0, 98, 0, 0, 0, 240, 0, 0, 0, 164, 0, 0, 0, 94, 0, 0, 0, 140, 0, 0, 0, 24, 0, 0, 0, 194, 0, 0, 0, 23, 0, 0, 0, 36, 0, 0, 0, 183, 0, 0, 0, 120, 0, 0, 0, 194, 0, 0, 0, 169, 0, 0, 0, 231, 0, 0, 0, 106, 0, 0, 0, 50, 0, 0, 0, 214, 0, 0, 0, 41, 0, 0, 0, 133, 0, 0, 0, 175, 0, 0, 0, 203, 0, 0, 0, 141, 0, 0, 0, 145, 0, 0, 0, 19, 0, 0, 0, 218, -0, 0, 0, 107, 0, 0, 0, 54, 0, 0, 0, 10, 0, 0, 0, 194, 0, 0, 0, 182, 0, 0, 0, 75, 0, 0, 0, 165, 0, 0, 0, 93, 0, 0, 0, 7, 0, 0, 0, 23, 0, 0, 0, 65, 0, 0, 0, 49, 0, 0, 0, 95, 0, 0, 0, 98, 0, 0, 0, 70, 0, 0, 0, 248, 0, 0, 0, 146, 0, 0, 0, 249, 0, 0, 0, 102, 0, 0, 0, 72, 0, 0, 0, 115, 0, 0, 0, 166, 0, 0, 0, 151, 0, 0, 0, 13, 0, 0, 0, 125, 0, 0, 0, 136, 0, 0, 0, 238, 0, 0, 0, 98, 0, 0, 0, 177, 0, 0, 0, 3, 0, 0, 0, 168, 0, 0, 0, 63, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 177, 0, 0, 0, 112, 0, 0, 0, 138, 0, 0, 0, 169, 0, 0, 0, 232, 0, 0, 0, 99, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 37, 0, 0, 0, 22, 0, 0, 0, 202, 0, 0, 0, 75, 0, 0, 0, 15, 0, 0, 0, 164, 0, 0, 0, 102, 0, 0, 0, 173, 0, 0, 0, 25, 0, 0, 0, 159, 0, 0, 0, 136, 0, 0, 0, -103, 0, 0, 0, 12, 0, 0, 0, 139, 0, 0, 0, 194, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 43, 0, 0, 0, 109, 0, 0, 0, 149, 0, 0, 0, 175, 0, 0, 0, 25, 0, 0, 0, 139, 0, 0, 0, 157, 0, 0, 0, 182, 0, 0, 0, 204, 0, 0, 0, 96, 0, 0, 0, 180, 0, 0, 0, 114, 0, 0, 0, 79, 0, 0, 0, 23, 0, 0, 0, 105, 0, 0, 0, 90, 0, 0, 0, 74, 0, 0, 0, 104, 0, 0, 0, 52, 0, 0, 0, 171, 0, 0, 0, 161, 0, 0, 0, 69, 0, 0, 0, 50, 0, 0, 0, 60, 0, 0, 0, 131, 0, 0, 0, 135, 0, 0, 0, 114, 0, 0, 0, 48, 0, 0, 0, 84, 0, 0, 0, 119, 0, 0, 0, 104, 0, 0, 0, -174, 0, 0, 0, 251, 0, 0, 0, 181, 0, 0, 0, 139, 0, 0, 0, 34, 0, 0, 0, 94, 0, 0, 0, 241, 0, 0, 0, 185, 0, 0, 0, 135, 0, 0, 0, 53, 0, 0, 0, 197, 0, 0, 0, 187, 0, 0, 0, 185, 0, 0, 0, 207, 0, 0, 0, 245, 0, 0, 0, 214, 0, 0, 0, 205, 0, 0, 0, 213, 0, 0, 0, 12, 0, 0, 0, 124, 0, 0, 0, 14, 0, 0, 0, 230, 0, 0, 0, 144, 0, 0, 0, 52, 0, 0, 0, 251, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 30, 0, 0, 0, 109, 0, 0, 0, 172, 0, 0, 0, 154, 0, 0, 0, 70, 0, 0, 0, 196, 0, 0, 0, 151, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 191, 0, 0, -0, 69, 0, 0, 0, 102, 0, 0, 0, 158, 0, 0, 0, 198, 0, 0, 0, 36, 0, 0, 0, 192, 0, 0, 0, 237, 0, 0, 0, 165, 0, 0, 0, 93, 0, 0, 0, 136, 0, 0, 0, 212, 0, 0, 0, 240, 0, 0, 0, 115, 0, 0, 0, 151, 0, 0, 0, 123, 0, 0, 0, 234, 0, 0, 0, 127, 0, 0, 0, 66, 0, 0, 0, 255, 0, 0, 0, 33, 0, 0, 0, 160, 0, 0, 0, 155, 0, 0, 0, 47, 0, 0, 0, 154, 0, 0, 0, 253, 0, 0, 0, 83, 0, 0, 0, 87, 0, 0, 0, 7, 0, 0, 0, 132, 0, 0, 0, 72, 0, 0, 0, 136, 0, 0, 0, 157, 0, 0, 0, 82, 0, 0, 0, 198, 0, 0, 0, 150, 0, 0, 0, 72, 0, 0, 0, 52, 0, -0, 0, 42, 0, 0, 0, 6, 0, 0, 0, 175, 0, 0, 0, 148, 0, 0, 0, 61, 0, 0, 0, 244, 0, 0, 0, 26, 0, 0, 0, 207, 0, 0, 0, 242, 0, 0, 0, 192, 0, 0, 0, 33, 0, 0, 0, 194, 0, 0, 0, 66, 0, 0, 0, 94, 0, 0, 0, 200, 0, 0, 0, 47, 0, 0, 0, 53, 0, 0, 0, 162, 0, 0, 0, 62, 0, 0, 0, 41, 0, 0, 0, 250, 0, 0, 0, 12, 0, 0, 0, 132, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 114, 0, 0, 0, 124, 0, 0, 0, 6, 0, 0, 0, 50, 0, 0, 0, 101, 0, 0, 0, 3, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 166, 0, 0, 0, 110, 0, 0, 0, 179, 0, 0, 0, 91, 0, 0, -0, 142, 0, 0, 0, 202, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 34, 0, 0, 0, 86, 0, 0, 0, 139, 0, 0, 0, 93, 0, 0, 0, 20, 0, 0, 0, 75, 0, 0, 0, 77, 0, 0, 0, 249, 0, 0, 0, 190, 0, 0, 0, 181, 0, 0, 0, 245, 0, 0, 0, 230, 0, 0, 0, 92, 0, 0, 0, 123, 0, 0, 0, 139, 0, 0, 0, 244, 0, 0, 0, 19, 0, 0, 0, 17, 0, 0, 0, 52, 0, 0, 0, 7, 0, 0, 0, 198, 0, 0, 0, 34, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 156, 0, 0, 0, 96, 0, 0, 0, 162, 0, 0, 0, 25, 0, 0, 0, 217, 0, 0, 0, 39, 0, 0, 0, 174, 0, 0, 0, 55, 0, 0, 0, 78, 0, 0, 0, -166, 0, 0, 0, 201, 0, 0, 0, 128, 0, 0, 0, 166, 0, 0, 0, 145, 0, 0, 0, 143, 0, 0, 0, 18, 0, 0, 0, 73, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 71, 0, 0, 0, 209, 0, 0, 0, 215, 0, 0, 0, 40, 0, 0, 0, 34, 0, 0, 0, 99, 0, 0, 0, 57, 0, 0, 0, 232, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 242, 0, 0, 0, 158, 0, 0, 0, 30, 0, 0, 0, 153, 0, 0, 0, 57, 0, 0, 0, 149, 0, 0, 0, 4, 0, 0, 0, 189, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, 0, 123, 0, 0, 0, 178, 0, 0, 0, 38, 0, 0, 0, 172, 0, 0, 0, 230, 0, 0, 0, 170, -0, 0, 0, 226, 0, 0, 0, 70, 0, 0, 0, 213, 0, 0, 0, 228, 0, 0, 0, 232, 0, 0, 0, 134, 0, 0, 0, 189, 0, 0, 0, 171, 0, 0, 0, 124, 0, 0, 0, 85, 0, 0, 0, 89, 0, 0, 0, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 100, 0, 0, 0, 110, 0, 0, 0, 155, 0, 0, 0, 53, 0, -0, 0, 113, 0, 0, 0, 120, 0, 0, 0, 206, 0, 0, 0, 51, 0, 0, 0, 3, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 54, 0, 0, 0, 241, 0, 0, 0, 115, 0, 0, 0, 155, 0, 0, 0, 185, 0, 0, 0, 21, 0, 0, 0, 139, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 207, 0, 0, 0, 77, 0, 0, 0, 237, 0, 0, 0, 79, 0, 0, 0, 77, 0, 0, 0, 87, 0, 0, 0, 20, 0, 0, 0, 19, 0, 0, 0, 130, 0, 0, 0, 164, 0, 0, 0, 77, 0, 0, 0, 101, 0, 0, 0, 110, 0, 0, 0, 10, 0, 0, 0, 164, 0, 0, 0, 89, 0, 0, 0, 7, 0, 0, 0, 23, 0, 0, 0, 242, 0, 0, 0, 107, 0, 0, 0, 74, 0, 0, 0, -31, 0, 0, 0, 110, 0, 0, 0, 246, 0, 0, 0, 181, 0, 0, 0, 188, 0, 0, 0, 98, 0, 0, 0, 228, 0, 0, 0, 182, 0, 0, 0, 218, 0, 0, 0, 162, 0, 0, 0, 147, 0, 0, 0, 188, 0, 0, 0, 41, 0, 0, 0, 5, 0, 0, 0, 210, 0, 0, 0, 210, 0, 0, 0, 115, 0, 0, 0, 70, 0, 0, 0, 3, 0, 0, 0, 22, 0, 0, 0, 64, 0, 0, 0, 49, 0, 0, 0, 76, 0, 0, 0, 115, 0, 0, 0, 109, 0, 0, 0, 21, 0, 0, 0, 189, 0, 0, 0, 161, 0, 0, 0, 77, 0, 0, 0, 92, 0, 0, 0, 19, 0, 0, 0, 11, 0, 0, 0, 36, 0, 0, 0, 6, 0, 0, 0, 152, 0, 0, 0, 120, 0, 0, 0, 28, 0, 0, 0, 91, -0, 0, 0, 235, 0, 0, 0, 31, 0, 0, 0, 24, 0, 0, 0, 84, 0, 0, 0, 67, 0, 0, 0, 217, 0, 0, 0, 85, 0, 0, 0, 102, 0, 0, 0, 218, 0, 0, 0, 41, 0, 0, 0, 33, 0, 0, 0, 232, 0, 0, 0, 184, 0, 0, 0, 60, 0, 0, 0, 66, 0, 0, 0, 34, 0, 0, 0, 180, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, 111, 0, 0, 0, 21, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 237, 0, 0, 0, 209, 0, 0, 0, 241, 0, 0, 0, 167, 0, 0, 0, 199, 0, 0, 0, 115, 0, 0, 0, 69, 0, 0, 0, 243, 0, 0, 0, 158, 0, 0, 0, 206, 0, 0, 0, 118, 0, 0, 0, 183, 0, -0, 0, 246, 0, 0, 0, 57, 0, 0, 0, 182, 0, 0, 0, 142, 0, 0, 0, 121, 0, 0, 0, 190, 0, 0, 0, 233, 0, 0, 0, 155, 0, 0, 0, 207, 0, 0, 0, 125, 0, 0, 0, 98, 0, 0, 0, 146, 0, 0, 0, 91, 0, 0, 0, 252, 0, 0, 0, 114, 0, 0, 0, 253, 0, 0, 0, 186, 0, 0, 0, 241, 0, 0, 0, 253, 0, 0, 0, 166, 0, 0, 0, 124, 0, 0, 0, 149, 0, 0, 0, 227, 0, 0, 0, 97, 0, 0, 0, 63, 0, 0, 0, 233, 0, 0, 0, 3, 0, 0, 0, 212, 0, 0, 0, 43, 0, 0, 0, 212, 0, 0, 0, 32, 0, 0, 0, 217, 0, 0, 0, 219, 0, 0, 0, 77, 0, 0, 0, 50, 0, 0, 0, 62, 0, 0, 0, 245, -0, 0, 0, 17, 0, 0, 0, 100, 0, 0, 0, 227, 0, 0, 0, 180, 0, 0, 0, 190, 0, 0, 0, 50, 0, 0, 0, 134, 0, 0, 0, 23, 0, 0, 0, 144, 0, 0, 0, 231, 0, 0, 0, 201, 0, 0, 0, 31, 0, 0, 0, 16, 0, 0, 0, 165, 0, 0, 0, 106, 0, 0, 0, 45, 0, 0, 0, 57, 0, 0, 0, 208, 0, 0, 0, 59, 0, 0, 0, 196, 0, 0, 0, 166, 0, 0, 0, 233, 0, 0, 0, 89, 0, 0, 0, 19, 0, 0, 0, 218, 0, 0, 0, 26, 0, 0, 0, 230, 0, 0, 0, 160, 0, 0, 0, 185, 0, 0, 0, 60, 0, 0, 0, 80, 0, 0, 0, 184, 0, 0, 0, 64, 0, 0, 0, 124, 0, 0, 0, 21, 0, 0, 0, 54, 0, 0, 0, 90, -0, 0, 0, 66, 0, 0, 0, 180, 0, 0, 0, 11, 0, 0, 0, 50, 0, 0, 0, 171, 0, 0, 0, 220, 0, 0, 0, 4, 0, 0, 0, 81, 0, 0, 0, 85, 0, 0, 0, 33, 0, 0, 0, 30, 0, 0, 0, 11, 0, 0, 0, 117, 0, 0, 0, 153, 0, 0, 0, 137, 0, 0, 0, 115, 0, 0, 0, 53, 0, 0, 0, 58, 0, 0, 0, 145, 0, 0, 0, 43, 0, 0, 0, 254, 0, 0, 0, 231, 0, 0, 0, 73, 0, 0, 0, 234, 0, 0, 0, 118, 0, 0, 0, 193, 0, 0, 0, 249, 0, 0, 0, 70, 0, 0, 0, 185, 0, 0, 0, 83, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 252, 0, 0, 0, 90, 0, 0, 0, 30, 0, 0, 0, 29, 0, 0, 0, -116, 0, 0, 0, 88, 0, 0, 0, 149, 0, 0, 0, 166, 0, 0, 0, 143, 0, 0, 0, 123, 0, 0, 0, 151, 0, 0, 0, 62, 0, 0, 0, 23, 0, 0, 0, 59, 0, 0, 0, 121, 0, 0, 0, 45, 0, 0, 0, 166, 0, 0, 0, 87, 0, 0, 0, 239, 0, 0, 0, 69, 0, 0, 0, 2, 0, 0, 0, 11, 0, 0, 0, 77, 0, 0, 0, 110, 0, 0, 0, 158, 0, 0, 0, 147, 0, 0, 0, 141, 0, 0, 0, 47, 0, 0, 0, 217, 0, 0, 0, 157, 0, 0, 0, 219, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 215, 0, 0, 0, 86, 0, 0, 0, 151, 0, 0, 0, 88, 0, 0, 0, 145, 0, 0, 0, 222, 0, 0, 0, 9, 0, 0, 0, 79, 0, 0, 0, 159, 0, 0, 0, 190, 0, 0, 0, 99, 0, 0, 0, 176, 0, 0, 0, 131, 0, 0, 0, 134, 0, 0, 0, 67, 0, 0, 0, 93, 0, 0, 0, 188, 0, 0, 0, 224, 0, 0, 0, 243, 0, 0, 0, 192, 0, 0, 0, 117, 0, 0, 0, 191, 0, 0, 0, 139, 0, 0, 0, 142, 0, 0, 0, 170, 0, 0, 0, 247, -0, 0, 0, 139, 0, 0, 0, 100, 0, 0, 0, 110, 0, 0, 0, 176, 0, 0, 0, 99, 0, 0, 0, 22, 0, 0, 0, 174, 0, 0, 0, 139, 0, 0, 0, 224, 0, 0, 0, 155, 0, 0, 0, 36, 0, 0, 0, 104, 0, 0, 0, 92, 0, 0, 0, 68, 0, 0, 0, 194, 0, 0, 0, 208, 0, 0, 0, 8, 0, 0, 0, 183, 0, 0, 0, 123, 0, 0, 0, 98, 0, 0, 0, 253, 0, 0, 0, 127, 0, 0, 0, 216, 0, 0, 0, 212, 0, 0, 0, 183, 0, 0, 0, 80, 0, 0, 0, 253, 0, 0, 0, 44, 0, 0, 0, 27, 0, 0, 0, 191, 0, 0, 0, 65, 0, 0, 0, 149, 0, 0, 0, 217, 0, 0, 0, 142, 0, 0, 0, 216, 0, 0, 0, 23, 0, 0, 0, 27, -0, 0, 0, 134, 0, 0, 0, 85, 0, 0, 0, 55, 0, 0, 0, 142, 0, 0, 0, 195, 0, 0, 0, 56, 0, 0, 0, 72, 0, 0, 0, 20, 0, 0, 0, 181, 0, 0, 0, 151, 0, 0, 0, 210, 0, 0, 0, 167, 0, 0, 0, 84, 0, 0, 0, 69, 0, 0, 0, 241, 0, 0, 0, 53, 0, 0, 0, 68, 0, 0, 0, 56, 0, 0, 0, 158, 0, 0, 0, 241, 0, 0, 0, 27, 0, 0, 0, 182, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 150, 0, 0, 0, 238, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 44, 0, 0, 0, 11, 0, 0, 0, 234, 0, 0, 0, 218, 0, 0, 0, 153, 0, 0, 0, 158, 0, 0, 0, 25, 0, 0, -0, 131, 0, 0, 0, 102, 0, 0, 0, 109, 0, 0, 0, 233, 0, 0, 0, 118, 0, 0, 0, 135, 0, 0, 0, 80, 0, 0, 0, 209, 0, 0, 0, 253, 0, 0, 0, 60, 0, 0, 0, 96, 0, 0, 0, 135, 0, 0, 0, 198, 0, 0, 0, 65, 0, 0, 0, 217, 0, 0, 0, 142, 0, 0, 0, 219, 0, 0, 0, 94, 0, 0, 0, 222, 0, 0, 0, 170, 0, 0, 0, 154, 0, 0, 0, 211, 0, 0, 0, 40, 0, 0, 0, 218, 0, 0, 0, 149, 0, 0, 0, 234, 0, 0, 0, 71, 0, 0, 0, 208, 0, 0, 0, 128, 0, 0, 0, 186, 0, 0, 0, 25, 0, 0, 0, 174, 0, 0, 0, 29, 0, 0, 0, 169, 0, 0, 0, 121, 0, 0, 0, 246, 0, 0, 0, 63, -0, 0, 0, 172, 0, 0, 0, 93, 0, 0, 0, 111, 0, 0, 0, 150, 0, 0, 0, 31, 0, 0, 0, 42, 0, 0, 0, 206, 0, 0, 0, 41, 0, 0, 0, 178, 0, 0, 0, 255, 0, 0, 0, 55, 0, 0, 0, 241, 0, 0, 0, 148, 0, 0, 0, 143, 0, 0, 0, 12, 0, 0, 0, 181, 0, 0, 0, 40, 0, 0, 0, 186, 0, 0, 0, 154, 0, 0, 0, 33, 0, 0, 0, 246, 0, 0, 0, 102, 0, 0, 0, 2, 0, 0, 0, 251, 0, 0, 0, 84, 0, 0, 0, 184, 0, 0, 0, 5, 0, 0, 0, 243, 0, 0, 0, 129, 0, 0, 0, 82, 0, 0, 0, 105, 0, 0, 0, 52, 0, 0, 0, 70, 0, 0, 0, 157, 0, 0, 0, 134, 0, 0, 0, 118, 0, 0, 0, 143, -0, 0, 0, 215, 0, 0, 0, 248, 0, 0, 0, 106, 0, 0, 0, 102, 0, 0, 0, 255, 0, 0, 0, 230, 0, 0, 0, 167, 0, 0, 0, 144, 0, 0, 0, 247, 0, 0, 0, 94, 0, 0, 0, 205, 0, 0, 0, 106, 0, 0, 0, 155, 0, 0, 0, 85, 0, 0, 0, 252, 0, 0, 0, 157, 0, 0, 0, 72, 0, 0, 0, 189, 0, 0, 0, 170, 0, 0, 0, 19, 0, 0, 0, 230, 0, 0, 0, 205, 0, 0, 0, 69, 0, 0, 0, 74, 0, 0, 0, 164, 0, 0, 0, 89, 0, 0, 0, 10, 0, 0, 0, 100, 0, 0, 0, 177, 0, 0, 0, 152, 0, 0, 0, 214, 0, 0, 0, 52, 0, 0, 0, 19, 0, 0, 0, 4, 0, 0, 0, 230, 0, 0, 0, 151, 0, 0, 0, -148, 0, 0, 0, 6, 0, 0, 0, 203, 0, 0, 0, 212, 0, 0, 0, 78, 0, 0, 0, 187, 0, 0, 0, 150, 0, 0, 0, 205, 0, 0, 0, 209, 0, 0, 0, 87, 0, 0, 0, 209, 0, 0, 0, 227, 0, 0, 0, 6, 0, 0, 0, 122, 0, 0, 0, 108, 0, 0, 0, 69, 0, 0, 0, 39, 0, 0, 0, 196, 0, 0, 0, 147, 0, 0, 0, 127, 0, 0, 0, 125, 0, 0, 0, 124, 0, 0, 0, 98, 0, 0, 0, 80, 0, 0, 0, 56, 0, 0, 0, 58, 0, 0, 0, 107, 0, 0, 0, 181, 0, 0, 0, 136, 0, 0, 0, 198, 0, 0, 0, 217, 0, 0, 0, 241, 0, 0, 0, 120, 0, 0, 0, 25, 0, 0, 0, 185, 0, 0, 0, 57, 0, 0, 0, 147, 0, 0, -0, 61, 0, 0, 0, 201, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 60, 0, 0, 0, 206, 0, 0, 0, 245, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 234, 0, 0, 0, 35, 0, 0, 0, 125, 0, 0, 0, 86, 0, 0, 0, 44, 0, 0, 0, 226, 0, 0, 0, 89, 0, 0, 0, 14, 0, 0, 0, 133, -0, 0, 0, 96, 0, 0, 0, 4, 0, 0, 0, 136, 0, 0, 0, 90, 0, 0, 0, 116, 0, 0, 0, 30, 0, 0, 0, 75, 0, 0, 0, 239, 0, 0, 0, 19, 0, 0, 0, 218, 0, 0, 0, 76, 0, 0, 0, 255, 0, 0, 0, 131, 0, 0, 0, 69, 0, 0, 0, 133, 0, 0, 0, 63, 0, 0, 0, 8, 0, 0, 0, 149, 0, 0, 0, 44, 0, 0, 0, 32, 0, 0, 0, 19, 0, 0, 0, 31, 0, 0, 0, 72, 0, 0, 0, 95, 0, 0, 0, 39, 0, 0, 0, 144, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0, 0, 66, 0, 0, 0, 173, 0, 0, 0, 120, 0, 0, 0, 71, 0, 0, 0, 92, 0, 0, 0, 181, 0, 0, 0, 126, 0, 0, 0, 8, 0, 0, 0, 133, 0, 0, 0, 0, -0, 0, 0, 250, 0, 0, 0, 127, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 231, 0, 0, 0, 9, 0, 0, 0, 17, 0, 0, 0, 242, 0, 0, 0, 126, 0, 0, 0, 27, 0, 0, 0, 56, 0, 0, 0, 108, 0, 0, 0, 53, 0, 0, 0, 109, 0, 0, 0, 51, 0, 0, 0, 102, 0, 0, 0, 147, 0, 0, 0, 3, 0, 0, 0, 54, 0, 0, 0, 129, 0, 0, 0, 172, 0, 0, 0, 228, 0, 0, 0, 32, 0, 0, 0, 9, 0, 0, 0, 53, 0, 0, 0, 76, 0, 0, 0, 69, 0, 0, 0, 178, 0, 0, 0, 30, 0, 0, 0, 76, 0, 0, 0, 20, 0, 0, 0, 33, 0, 0, 0, 230, 0, 0, 0, 233, 0, 0, 0, 138, 0, 0, 0, 123, 0, 0, 0, 141, 0, -0, 0, 254, 0, 0, 0, 30, 0, 0, 0, 198, 0, 0, 0, 62, 0, 0, 0, 193, 0, 0, 0, 53, 0, 0, 0, 250, 0, 0, 0, 231, 0, 0, 0, 112, 0, 0, 0, 78, 0, 0, 0, 29, 0, 0, 0, 97, 0, 0, 0, 46, 0, 0, 0, 194, 0, 0, 0, 221, 0, 0, 0, 149, 0, 0, 0, 87, 0, 0, 0, 209, 0, 0, 0, 171, 0, 0, 0, 128, 0, 0, 0, 232, 0, 0, 0, 99, 0, 0, 0, 23, 0, 0, 0, 181, 0, 0, 0, 72, 0, 0, 0, 228, 0, 0, 0, 138, 0, 0, 0, 17, 0, 0, 0, 158, 0, 0, 0, 114, 0, 0, 0, 190, 0, 0, 0, 133, 0, 0, 0, 141, 0, 0, 0, 81, 0, 0, 0, 10, 0, 0, 0, 242, 0, 0, 0, 159, -0, 0, 0, 224, 0, 0, 0, 28, 0, 0, 0, 169, 0, 0, 0, 7, 0, 0, 0, 40, 0, 0, 0, 123, 0, 0, 0, 187, 0, 0, 0, 113, 0, 0, 0, 20, 0, 0, 0, 94, 0, 0, 0, 38, 0, 0, 0, 140, 0, 0, 0, 61, 0, 0, 0, 200, 0, 0, 0, 233, 0, 0, 0, 124, 0, 0, 0, 211, 0, 0, 0, 214, 0, 0, 0, 209, 0, 0, 0, 47, 0, 0, 0, 7, 0, 0, 0, 109, 0, 0, 0, 230, 0, 0, 0, 223, 0, 0, 0, 251, 0, 0, 0, 121, 0, 0, 0, 214, 0, 0, 0, 153, 0, 0, 0, 89, 0, 0, 0, 150, 0, 0, 0, 72, 0, 0, 0, 64, 0, 0, 0, 15, 0, 0, 0, 58, 0, 0, 0, 123, 0, 0, 0, 178, 0, 0, 0, 160, -0, 0, 0, 114, 0, 0, 0, 78, 0, 0, 0, 59, 0, 0, 0, 105, 0, 0, 0, 200, 0, 0, 0, 67, 0, 0, 0, 117, 0, 0, 0, 81, 0, 0, 0, 108, 0, 0, 0, 121, 0, 0, 0, 86, 0, 0, 0, 228, 0, 0, 0, 203, 0, 0, 0, 247, 0, 0, 0, 166, 0, 0, 0, 81, 0, 0, 0, 194, 0, 0, 0, 44, 0, 0, 0, 66, 0, 0, 0, 11, 0, 0, 0, 212, 0, 0, 0, 130, 0, 0, 0, 32, 0, 0, 0, 28, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 102, 0, 0, 0, 215, 0, 0, 0, 191, 0, 0, 0, 4, 0, 0, 0, 86, 0, 0, 0, 252, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, 232, 0, 0, 0, 183, 0, 0, 0, 96, 0, 0, -0, 174, 0, 0, 0, 71, 0, 0, 0, 128, 0, 0, 0, 252, 0, 0, 0, 229, 0, 0, 0, 35, 0, 0, 0, 231, 0, 0, 0, 194, 0, 0, 0, 201, 0, 0, 0, 133, 0, 0, 0, 230, 0, 0, 0, 152, 0, 0, 0, 160, 0, 0, 0, 41, 0, 0, 0, 78, 0, 0, 0, 225, 0, 0, 0, 132, 0, 0, 0, 57, 0, 0, 0, 45, 0, 0, 0, 149, 0, 0, 0, 44, 0, 0, 0, 243, 0, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 255, 0, 0, 0, 175, 0, 0, 0, 39, 0, 0, 0, 76, 0, 0, 0, 107, 0, 0, 0, 166, 0, 0, 0, 245, 0, 0, 0, 75, 0, 0, 0, 17, 0, 0, 0, 189, 0, 0, 0, 186, 0, 0, 0, 91, 0, 0, 0, 158, 0, -0, 0, 196, 0, 0, 0, 164, 0, 0, 0, 81, 0, 0, 0, 30, 0, 0, 0, 190, 0, 0, 0, 208, 0, 0, 0, 144, 0, 0, 0, 58, 0, 0, 0, 156, 0, 0, 0, 194, 0, 0, 0, 38, 0, 0, 0, 182, 0, 0, 0, 30, 0, 0, 0, 241, 0, 0, 0, 149, 0, 0, 0, 125, 0, 0, 0, 200, 0, 0, 0, 109, 0, 0, 0, 82, 0, 0, 0, 230, 0, 0, 0, 153, 0, 0, 0, 44, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 0, 0, 0, 224, 0, 0, 0, 36, 0, 0, 0, 50, 0, 0, 0, 180, 0, 0, 0, 209, 0, 0, 0, 239, 0, 0, 0, 252, 0, 0, 0, 105, 0, 0, 0, 162, 0, 0, 0, 191, 0, 0, 0, 143, 0, 0, 0, 114, 0, 0, 0, 44, 0, 0, 0, 149, 0, 0, 0, 246, 0, 0, 0, 228, 0, 0, 0, 110, 0, 0, 0, 125, 0, 0, 0, 144, 0, 0, 0, 247, 0, 0, 0, 87, 0, 0, 0, 129, 0, 0, 0, 160, 0, 0, 0, 247, 0, 0, 0, 218, 0, 0, 0, 239, 0, 0, 0, 51, 0, 0, 0, 7, 0, 0, 0, 227, 0, 0, 0, 107, -0, 0, 0, 120, 0, 0, 0, 54, 0, 0, 0, 39, 0, 0, 0, 62, 0, 0, 0, 198, 0, 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 171, 0, 0, 0, 78, 0, 0, 0, 190, 0, 0, 0, 105, 0, 0, 0, 157, 0, 0, 0, 179, 0, 0, 0, 190, 0, 0, 0, 8, 0, 0, 0, 124, 0, 0, 0, 42, 0, 0, 0, 71, 0, 0, 0, 8, 0, 0, 0, 253, 0, 0, 0, 212, 0, 0, 0, 205, 0, 0, 0, 14, 0, 0, 0, 39, 0, 0, 0, 52, 0, 0, 0, 91, 0, 0, 0, 152, 0, 0, 0, 52, 0, 0, 0, 47, 0, 0, 0, 119, 0, 0, 0, 95, 0, 0, 0, 58, 0, 0, 0, 101, 0, 0, 0, 19, 0, 0, 0, 170, 0, 0, 0, 46, 0, 0, 0, 76, 0, 0, 0, -240, 0, 0, 0, 34, 0, 0, 0, 184, 0, 0, 0, 108, 0, 0, 0, 179, 0, 0, 0, 25, 0, 0, 0, 77, 0, 0, 0, 235, 0, 0, 0, 107, 0, 0, 0, 208, 0, 0, 0, 164, 0, 0, 0, 198, 0, 0, 0, 156, 0, 0, 0, 221, 0, 0, 0, 200, 0, 0, 0, 91, 0, 0, 0, 129, 0, 0, 0, 87, 0, 0, 0, 137, 0, 0, 0, 223, 0, 0, 0, 51, 0, 0, 0, 169, 0, 0, 0, 104, 0, 0, 0, 73, 0, 0, 0, 128, 0, 0, 0, 228, 0, 0, 0, 254, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 144, 0, 0, 0, 48, 0, 0, 0, 233, 0, 0, 0, 211, 0, 0, 0, 96, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, -194, 0, 0, 0, 114, 0, 0, 0, 137, 0, 0, 0, 122, 0, 0, 0, 54, 0, 0, 0, 165, 0, 0, 0, 189, 0, 0, 0, 57, 0, 0, 0, 131, 0, 0, 0, 133, 0, 0, 0, 80, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 108, 0, 0, 0, 65, 0, 0, 0, 29, 0, 0, 0, 181, 0, 0, 0, 44, 0, 0, 0, 7, 0, 0, 0, 64, 0, 0, 0, 119, 0, 0, 0, 11, 0, 0, 0, 80, 0, 0, 0, 100, 0, 0, 0, 52, 0, 0, 0, 236, 0, 0, 0, 192, 0, 0, 0, 158, 0, 0, 0, 68, 0, 0, 0, 65, 0, 0, 0, 175, 0, 0, 0, 160, 0, 0, 0, 54, 0, 0, 0, 5, 0, 0, 0, 109, 0, 0, 0, 234, 0, 0, 0, 48, 0, 0, 0, 37, -0, 0, 0, 70, 0, 0, 0, 53, 0, 0, 0, 36, 0, 0, 0, 157, 0, 0, 0, 134, 0, 0, 0, 189, 0, 0, 0, 149, 0, 0, 0, 241, 0, 0, 0, 106, 0, 0, 0, 70, 0, 0, 0, 215, 0, 0, 0, 148, 0, 0, 0, 84, 0, 0, 0, 249, 0, 0, 0, 59, 0, 0, 0, 189, 0, 0, 0, 93, 0, 0, 0, 119, 0, 0, 0, 91, 0, 0, 0, 226, 0, 0, 0, 55, 0, 0, 0, 199, 0, 0, 0, 225, 0, 0, 0, 124, 0, 0, 0, 19, 0, 0, 0, 140, 0, 0, 0, 159, 0, 0, 0, 123, 0, 0, 0, 123, 0, 0, 0, 42, 0, 0, 0, 206, 0, 0, 0, 66, 0, 0, 0, 163, 0, 0, 0, 185, 0, 0, 0, 42, 0, 0, 0, 153, 0, 0, 0, 168, -0, 0, 0, 192, 0, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 134, 0, 0, 0, 176, 0, 0, 0, 251, 0, 0, 0, 233, 0, 0, 0, 118, 0, 0, 0, 119, 0, 0, 0, 247, 0, 0, 0, 245, 0, 0, 0, 86, 0, 0, 0, 223, 0, 0, 0, 179, 0, 0, 0, 70, 0, 0, 0, 17, 0, 0, 0, 110, 0, 0, 0, 19, 0, 0, 0, 183, 0, 0, 0, 40, 0, 0, 0, 78, 0, 0, 0, 86, 0, 0, 0, 221, 0, 0, 0, 241, 0, 0, 0, 172, 0, 0, 0, 173, 0, 0, 0, 88, 0, 0, 0, 195, 0, 0, 0, 248, 0, 0, 0, 136, 0, 0, 0, 148, 0, 0, 0, 94, 0, 0, 0, 6, 0, 0, 0, 152, 0, 0, 0, 161, 0, 0, 0, 228, 0, 0, 0, -106, 0, 0, 0, 251, 0, 0, 0, 10, 0, 0, 0, 73, 0, 0, 0, 93, 0, 0, 0, 138, 0, 0, 0, 254, 0, 0, 0, 119, 0, 0, 0, 70, 0, 0, 0, 2, 0, 0, 0, 245, 0, 0, 0, 165, 0, 0, 0, 175, 0, 0, 0, 197, 0, 0, 0, 117, 0, 0, 0, 109, 0, 0, 0, 186, 0, 0, 0, 69, 0, 0, 0, 53, 0, 0, 0, 10, 0, 0, 0, 254, 0, 0, 0, 201, 0, 0, 0, 172, 0, 0, 0, 34, 0, 0, 0, 145, 0, 0, 0, 141, 0, 0, 0, 33, 0, 0, 0, 149, 0, 0, 0, 51, 0, 0, 0, 3, 0, 0, 0, 192, 0, 0, 0, 138, 0, 0, 0, 22, 0, 0, 0, 243, 0, 0, 0, 57, 0, 0, 0, 224, 0, 0, 0, 1, 0, 0, 0, 15, -0, 0, 0, 83, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 117, 0, 0, 0, 55, 0, 0, 0, 31, 0, 0, 0, 52, 0, 0, 0, 78, 0, 0, 0, 169, 0, 0, 0, 29, 0, 0, 0, 104, 0, 0, 0, 103, 0, 0, 0, 248, 0, 0, 0, 73, 0, 0, 0, 152, 0, 0, 0, 150, 0, 0, 0, 252, 0, 0, 0, -76, 0, 0, 0, 101, 0, 0, 0, 151, 0, 0, 0, 247, 0, 0, 0, 2, 0, 0, 0, 74, 0, 0, 0, 82, 0, 0, 0, 108, 0, 0, 0, 1, 0, 0, 0, 189, 0, 0, 0, 72, 0, 0, 0, 187, 0, 0, 0, 27, 0, 0, 0, 237, 0, 0, 0, 164, 0, 0, 0, 226, 0, 0, 0, 83, 0, 0, 0, 89, 0, 0, 0, 213, 0, 0, 0, 155, 0, 0, 0, 90, 0, 0, 0, 162, 0, 0, 0, 144, 0, 0, 0, 211, 0, 0, 0, 184, 0, 0, 0, 55, 0, 0, 0, 76, 0, 0, 0, 85, 0, 0, 0, 130, 0, 0, 0, 40, 0, 0, 0, 8, 0, 0, 0, 15, 0, 0, 0, 127, 0, 0, 0, 170, 0, 0, 0, 129, 0, 0, 0, 101, 0, 0, 0, 224, 0, 0, 0, 12, -0, 0, 0, 82, 0, 0, 0, 201, 0, 0, 0, 163, 0, 0, 0, 50, 0, 0, 0, 39, 0, 0, 0, 100, 0, 0, 0, 218, 0, 0, 0, 253, 0, 0, 0, 52, 0, 0, 0, 35, 0, 0, 0, 90, 0, 0, 0, 181, 0, 0, 0, 176, 0, 0, 0, 12, 0, 0, 0, 77, 0, 0, 0, 179, 0, 0, 0, 123, 0, 0, 0, 35, 0, 0, 0, 200, 0, 0, 0, 31, 0, 0, 0, 138, 0, 0, 0, 57, 0, 0, 0, 102, 0, 0, 0, 230, 0, 0, 0, 186, 0, 0, 0, 76, 0, 0, 0, 16, 0, 0, 0, 55, 0, 0, 0, 202, 0, 0, 0, 156, 0, 0, 0, 124, 0, 0, 0, 5, 0, 0, 0, 158, 0, 0, 0, 255, 0, 0, 0, 192, 0, 0, 0, 248, 0, 0, 0, 142, -0, 0, 0, 177, 0, 0, 0, 143, 0, 0, 0, 111, 0, 0, 0, 103, 0, 0, 0, 24, 0, 0, 0, 38, 0, 0, 0, 75, 0, 0, 0, 65, 0, 0, 0, 19, 0, 0, 0, 84, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 0, 164, 0, 0, 0, 78, 0, 0, 0, 169, 0, 0, 0, 139, 0, 0, 0, 30, 0, 0, 0, 75, 0, 0, 0, 252, 0, 0, 0, 21, 0, 0, 0, 36, 0, 0, 0, 187, 0, 0, 0, 126, 0, 0, 0, 203, 0, 0, 0, 182, 0, 0, 0, 30, 0, 0, 0, 27, 0, 0, 0, 245, 0, 0, 0, 242, 0, 0, 0, 200, 0, 0, 0, 86, 0, 0, 0, 236, 0, 0, 0, 50, 0, 0, 0, 162, 0, 0, 0, 96, 0, 0, 0, 91, 0, 0, 0, 160, 0, -0, 0, 42, 0, 0, 0, 164, 0, 0, 0, 41, 0, 0, 0, 71, 0, 0, 0, 134, 0, 0, 0, 46, 0, 0, 0, 146, 0, 0, 0, 79, 0, 0, 0, 17, 0, 0, 0, 79, 0, 0, 0, 243, 0, 0, 0, 178, 0, 0, 0, 92, 0, 0, 0, 213, 0, 0, 0, 62, 0, 0, 0, 166, 0, 0, 0, 185, 0, 0, 0, 200, 0, 0, 0, 226, 0, 0, 0, 51, 0, 0, 0, 17, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 143, 0, 0, 0, 176, 0, 0, 0, 155, 0, 0, 0, 199, 0, 0, 0, 165, 0, 0, 0, 255, 0, 0, 0, 131, 0, 0, 0, 15, 0, 0, 0, 30, 0, 0, 0, 40, 0, 0, 0, 29, 0, 0, 0, 41, 0, 0, 0, 122, 0, 0, 0, 161, 0, 0, -0, 236, 0, 0, 0, 142, 0, 0, 0, 181, 0, 0, 0, 173, 0, 0, 0, 234, 0, 0, 0, 2, 0, 0, 0, 104, 0, 0, 0, 96, 0, 0, 0, 116, 0, 0, 0, 41, 0, 0, 0, 28, 0, 0, 0, 165, 0, 0, 0, 207, 0, 0, 0, 200, 0, 0, 0, 59, 0, 0, 0, 125, 0, 0, 0, 139, 0, 0, 0, 43, 0, 0, 0, 124, 0, 0, 0, 173, 0, 0, 0, 164, 0, 0, 0, 64, 0, 0, 0, 23, 0, 0, 0, 81, 0, 0, 0, 89, 0, 0, 0, 124, 0, 0, 0, 46, 0, 0, 0, 93, 0, 0, 0, 10, 0, 0, 0, 108, 0, 0, 0, 79, 0, 0, 0, 188, 0, 0, 0, 62, 0, 0, 0, 50, 0, 0, 0, 231, 0, 0, 0, 74, 0, 0, 0, 26, 0, 0, 0, -19, 0, 0, 0, 193, 0, 0, 0, 73, 0, 0, 0, 56, 0, 0, 0, 191, 0, 0, 0, 247, 0, 0, 0, 194, 0, 0, 0, 211, 0, 0, 0, 143, 0, 0, 0, 107, 0, 0, 0, 173, 0, 0, 0, 82, 0, 0, 0, 247, 0, 0, 0, 207, 0, 0, 0, 188, 0, 0, 0, 39, 0, 0, 0, 203, 0, 0, 0, 64, 0, 0, 0, 103, 0, 0, 0, 118, 0, 0, 0, 205, 0, 0, 0, 109, 0, 0, 0, 86, 0, 0, 0, 229, 0, 0, 0, 176, 0, 0, 0, 39, 0, 0, 0, 173, 0, 0, 0, 190, 0, 0, 0, 155, 0, 0, 0, 242, 0, 0, 0, 181, 0, 0, 0, 99, 0, 0, 0, 222, 0, 0, 0, 58, 0, 0, 0, 35, 0, 0, 0, 149, 0, 0, 0, 183, 0, -0, 0, 10, 0, 0, 0, 126, 0, 0, 0, 243, 0, 0, 0, 158, 0, 0, 0, 69, 0, 0, 0, 111, 0, 0, 0, 25, 0, 0, 0, 57, 0, 0, 0, 117, 0, 0, 0, 143, 0, 0, 0, 57, 0, 0, 0, 61, 0, 0, 0, 15, 0, 0, 0, 192, 0, 0, 0, 159, 0, 0, 0, 241, 0, 0, 0, 233, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 136, 0, 0, 0, 170, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 134, 0, 0, 0, 148, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 62, 0, 0, 0, 26, 0, 0, 0, 181, 0, 0, 0, 204, 0, 0, 0, 187, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 213, 0, 0, 0, 156, 0, 0, 0, 109, 0, 0, 0, 186, 0, 0, 0, 88, 0, 0, 0, 114, 0, 0, 0, 141, 0, 0, 0, 251, 0, 0, 0, 34, 0, 0, 0, 123, 0, 0, 0, 159, 0, 0, 0, 124, 0, 0, 0, 148, 0, 0, 0, 48, 0, 0, 0, 179, 0, 0, 0, 81, 0, 0, 0, 33, 0, 0, 0, 246, 0, 0, 0, 116, 0, 0, 0, 61, 0, 0, 0, 242, 0, -0, 0, 175, 0, 0, 0, 208, 0, 0, 0, 30, 0, 0, 0, 3, 0, 0, 0, 124, 0, 0, 0, 35, 0, 0, 0, 107, 0, 0, 0, 201, 0, 0, 0, 252, 0, 0, 0, 37, 0, 0, 0, 112, 0, 0, 0, 144, 0, 0, 0, 220, 0, 0, 0, 154, 0, 0, 0, 164, 0, 0, 0, 251, 0, 0, 0, 73, 0, 0, 0, 252, 0, 0, 0, 61, 0, 0, 0, 10, 0, 0, 0, 53, 0, 0, 0, 56, 0, 0, 0, 111, 0, 0, 0, 228, 0, 0, 0, 126, 0, 0, 0, 80, 0, 0, 0, 1, 0, 0, 0, 42, 0, 0, 0, 214, 0, 0, 0, 227, 0, 0, 0, 150, 0, 0, 0, 97, 0, 0, 0, 58, 0, 0, 0, 253, 0, 0, 0, 239, 0, 0, 0, 155, 0, 0, 0, 31, 0, -0, 0, 144, 0, 0, 0, 164, 0, 0, 0, 36, 0, 0, 0, 20, 0, 0, 0, 91, 0, 0, 0, 200, 0, 0, 0, 222, 0, 0, 0, 80, 0, 0, 0, 177, 0, 0, 0, 29, 0, 0, 0, 175, 0, 0, 0, 232, 0, 0, 0, 85, 0, 0, 0, 138, 0, 0, 0, 135, 0, 0, 0, 13, 0, 0, 0, 254, 0, 0, 0, 170, 0, 0, 0, 59, 0, 0, 0, 130, 0, 0, 0, 44, 0, 0, 0, 141, 0, 0, 0, 123, 0, 0, 0, 133, 0, 0, 0, 12, 0, 0, 0, 175, 0, 0, 0, 248, 0, 0, 0, 131, 0, 0, 0, 68, 0, 0, 0, 73, 0, 0, 0, 217, 0, 0, 0, 69, 0, 0, 0, 207, 0, 0, 0, 247, 0, 0, 0, 72, 0, 0, 0, 217, 0, 0, 0, 83, 0, -0, 0, 180, 0, 0, 0, 241, 0, 0, 0, 101, 0, 0, 0, 160, 0, 0, 0, 225, 0, 0, 0, 195, 0, 0, 0, 179, 0, 0, 0, 21, 0, 0, 0, 237, 0, 0, 0, 137, 0, 0, 0, 155, 0, 0, 0, 79, 0, 0, 0, 98, 0, 0, 0, 179, 0, 0, 0, 87, 0, 0, 0, 165, 0, 0, 0, 69, 0, 0, 0, 28, 0, 0, 0, 143, 0, 0, 0, 18, 0, 0, 0, 234, 0, 0, 0, 175, 0, 0, 0, 209, 0, 0, 0, 31, 0, 0, 0, 121, 0, 0, 0, 16, 0, 0, 0, 11, 0, 0, 0, 246, 0, 0, 0, 163, 0, 0, 0, 123, 0, 0, 0, 234, 0, 0, 0, 172, 0, 0, 0, 139, 0, 0, 0, 87, 0, 0, 0, 50, 0, 0, 0, 98, 0, 0, 0, 231, -0, 0, 0, 6, 0, 0, 0, 18, 0, 0, 0, 81, 0, 0, 0, 160, 0, 0, 0, 59, 0, 0, 0, 67, 0, 0, 0, 94, 0, 0, 0, 164, 0, 0, 0, 32, 0, 0, 0, 120, 0, 0, 0, 49, 0, 0, 0, 206, 0, 0, 0, 13, 0, 0, 0, 132, 0, 0, 0, 124, 0, 0, 0, 194, 0, 0, 0, 166, 0, 0, 0, 145, 0, 0, 0, 35, 0, 0, 0, 206, 0, 0, 0, 189, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 206, 0, 0, 0, 213, 0, 0, 0, 117, 0, 0, 0, 48, 0, 0, 0, 34, 0, 0, 0, 230, 0, 0, 0, 249, 0, 0, 0, 67, 0, 0, 0, 98, 0, 0, 0, 13, 0, 0, 0, 247, 0, 0, 0, 117, 0, 0, 0, 157, 0, 0, 0, 127, -0, 0, 0, 140, 0, 0, 0, 255, 0, 0, 0, 125, 0, 0, 0, 228, 0, 0, 0, 114, 0, 0, 0, 172, 0, 0, 0, 159, 0, 0, 0, 28, 0, 0, 0, 136, 0, 0, 0, 193, 0, 0, 0, 153, 0, 0, 0, 208, 0, 0, 0, 60, 0, 0, 0, 28, 0, 0, 0, 93, 0, 0, 0, 180, 0, 0, 0, 239, 0, 0, 0, 19, 0, 0, 0, 15, 0, 0, 0, 144, 0, 0, 0, 185, 0, 0, 0, 54, 0, 0, 0, 47, 0, 0, 0, 149, 0, 0, 0, 149, 0, 0, 0, 198, 0, 0, 0, 220, 0, 0, 0, 222, 0, 0, 0, 10, 0, 0, 0, 81, 0, 0, 0, 226, 0, 0, 0, 141, 0, 0, 0, 243, 0, 0, 0, 188, 0, 0, 0, 81, 0, 0, 0, 236, 0, 0, 0, -223, 0, 0, 0, 177, 0, 0, 0, 162, 0, 0, 0, 95, 0, 0, 0, 46, 0, 0, 0, 104, 0, 0, 0, 161, 0, 0, 0, 35, 0, 0, 0, 125, 0, 0, 0, 155, 0, 0, 0, 64, 0, 0, 0, 105, 0, 0, 0, 133, 0, 0, 0, 123, 0, 0, 0, 66, 0, 0, 0, 191, 0, 0, 0, 144, 0, 0, 0, 75, 0, 0, 0, 214, 0, 0, 0, 64, 0, 0, 0, 47, 0, 0, 0, 215, 0, 0, 0, 82, 0, 0, 0, 82, 0, 0, 0, 178, 0, 0, 0, 33, 0, 0, 0, 222, 0, 0, 0, 100, 0, 0, 0, 189, 0, 0, 0, 136, 0, 0, 0, 195, 0, 0, 0, 109, 0, 0, 0, 165, 0, 0, 0, 250, 0, 0, 0, 129, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 0, 0, 0, 253, 0, 0, 0, 71, 0, 0, 0, 123, 0, 0, 0, 138, 0, 0, 0, 102, 0, 0, 0, 158, 0, 0, 0, 121, 0, 0, 0, 46, 0, 0, 0, 100, 0, 0, 0, 130, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 33, 0, 0, 0, 236, 0, 0, 0, 246, 0, 0, 0, 216, 0, 0, 0, 134, 0, -0, 0, 9, 0, 0, 0, 49, 0, 0, 0, 124, 0, 0, 0, 221, 0, 0, 0, 3, 0, 0, 0, 106, 0, 0, 0, 88, 0, 0, 0, 160, 0, 0, 0, 119, 0, 0, 0, 183, 0, 0, 0, 155, 0, 0, 0, 140, 0, 0, 0, 135, 0, 0, 0, 31, 0, 0, 0, 85, 0, 0, 0, 71, 0, 0, 0, 228, 0, 0, 0, 168, 0, 0, 0, 61, 0, 0, 0, 85, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 171, 0, 0, 0, 29, 0, 0, 0, 174, 0, 0, 0, 224, 0, 0, 0, 244, 0, 0, 0, 234, 0, 0, 0, 219, 0, 0, 0, 197, 0, 0, 0, 185, 0, 0, 0, 88, 0, 0, 0, 191, 0, 0, 0, 196, 0, 0, 0, 42, 0, 0, 0, 137, 0, 0, 0, 49, 0, -0, 0, 26, 0, 0, 0, 244, 0, 0, 0, 45, 0, 0, 0, 225, 0, 0, 0, 202, 0, 0, 0, 55, 0, 0, 0, 153, 0, 0, 0, 71, 0, 0, 0, 89, 0, 0, 0, 199, 0, 0, 0, 202, 0, 0, 0, 99, 0, 0, 0, 193, 0, 0, 0, 73, 0, 0, 0, 169, 0, 0, 0, 53, 0, 0, 0, 69, 0, 0, 0, 85, 0, 0, 0, 126, 0, 0, 0, 218, 0, 0, 0, 100, 0, 0, 0, 50, 0, 0, 0, 7, 0, 0, 0, 80, 0, 0, 0, 247, 0, 0, 0, 50, 0, 0, 0, 172, 0, 0, 0, 222, 0, 0, 0, 117, 0, 0, 0]).concat([88, 0, 0, 0, 155, 0, 0, 0, 17, 0, 0, 0, 178, 0, 0, 0, 58, 0, 0, 0, 31, 0, 0, 0, 245, 0, 0, 0, 247, -0, 0, 0, 121, 0, 0, 0, 4, 0, 0, 0, 230, 0, 0, 0, 8, 0, 0, 0, 70, 0, 0, 0, 250, 0, 0, 0, 34, 0, 0, 0, 75, 0, 0, 0, 250, 0, 0, 0, 225, 0, 0, 0, 254, 0, 0, 0, 150, 0, 0, 0, 252, 0, 0, 0, 103, 0, 0, 0, 186, 0, 0, 0, 103, 0, 0, 0, 151, 0, 0, 0, 196, 0, 0, 0, 231, 0, 0, 0, 27, 0, 0, 0, 134, 0, 0, 0, 144, 0, 0, 0, 95, 0, 0, 0, 238, 0, 0, 0, 244, 0, 0, 0, 91, 0, 0, 0, 17, 0, 0, 0, 178, 0, 0, 0, 205, 0, 0, 0, 173, 0, 0, 0, 238, 0, 0, 0, 194, 0, 0, 0, 72, 0, 0, 0, 108, 0, 0, 0, 43, 0, 0, 0, 27, 0, 0, 0, 227, -0, 0, 0, 57, 0, 0, 0, 98, 0, 0, 0, 180, 0, 0, 0, 79, 0, 0, 0, 49, 0, 0, 0, 4, 0, 0, 0, 201, 0, 0, 0, 218, 0, 0, 0, 213, 0, 0, 0, 115, 0, 0, 0, 81, 0, 0, 0, 87, 0, 0, 0, 197, 0, 0, 0, 184, 0, 0, 0, 243, 0, 0, 0, 163, 0, 0, 0, 67, 0, 0, 0, 112, 0, 0, 0, 228, 0, 0, 0, 97, 0, 0, 0, 129, 0, 0, 0, 132, 0, 0, 0, 226, 0, 0, 0, 187, 0, 0, 0, 191, 0, 0, 0, 79, 0, 0, 0, 158, 0, 0, 0, 164, 0, 0, 0, 94, 0, 0, 0, 116, 0, 0, 0, 6, 0, 0, 0, 41, 0, 0, 0, 172, 0, 0, 0, 255, 0, 0, 0, 39, 0, 0, 0, 224, 0, 0, 0, 89, -0, 0, 0, 190, 0, 0, 0, 57, 0, 0, 0, 156, 0, 0, 0, 13, 0, 0, 0, 131, 0, 0, 0, 215, 0, 0, 0, 16, 0, 0, 0, 11, 0, 0, 0, 21, 0, 0, 0, 183, 0, 0, 0, 225, 0, 0, 0, 194, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 115, 0, 0, 0, 128, 0, 0, 0, 58, 0, 0, 0, 125, 0, 0, 0, 93, 0, 0, 0, 171, 0, 0, 0, 88, 0, 0, 0, 107, 0, 0, 0, 193, 0, 0, 0, 240, 0, 0, 0, 244, 0, 0, 0, 34, 0, 0, 0, 254, 0, 0, 0, 127, 0, 0, 0, 251, 0, 0, 0, 53, 0, 0, 0, 125, 0, 0, 0, 198, 0, 0, 0, 1, 0, 0, 0, 35, 0, 0, 0, 40, 0, 0, 0, 196, 0, 0, 0, 2, 0, -0, 0, 172, 0, 0, 0, 31, 0, 0, 0, 66, 0, 0, 0, 180, 0, 0, 0, 157, 0, 0, 0, 252, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 165, 0, 0, 0, 238, 0, 0, 0, 202, 0, 0, 0, 218, 0, 0, 0, 151, 0, 0, 0, 9, 0, 0, 0, 65, 0, 0, 0, 119, 0, 0, 0, 135, 0, 0, 0, 93, 0, 0, 0, 123, 0, 0, 0, 135, 0, 0, 0, 120, 0, 0, 0, 245, 0, 0, 0, 251, 0, 0, 0, 144, 0, 0, 0, 45, 0, 0, 0, 129, 0, 0, 0, 25, 0, 0, 0, 158, 0, 0, 0, 47, 0, 0, 0, 109, 0, 0, 0, 133, 0, 0, 0, 136, 0, 0, 0, 140, 0, 0, 0, 64, 0, 0, 0, 92, 0, 0, 0, 119, 0, 0, 0, 65, -0, 0, 0, 77, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 118, 0, 0, 0, 96, 0, 0, 0, 232, 0, 0, 0, 76, 0, 0, 0, 72, 0, 0, 0, 228, 0, 0, 0, 51, 0, 0, 0, 131, 0, 0, 0, 50, 0, 0, 0, 108, 0, 0, 0, 180, 0, 0, 0, 65, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 16, -0, 0, 0, 194, 0, 0, 0, 9, 0, 0, 0, 79, 0, 0, 0, 110, 0, 0, 0, 244, 0, 0, 0, 210, 0, 0, 0, 223, 0, 0, 0, 126, 0, 0, 0, 202, 0, 0, 0, 123, 0, 0, 0, 28, 0, 0, 0, 29, 0, 0, 0, 186, 0, 0, 0, 163, 0, 0, 0, 182, 0, 0, 0, 218, 0, 0, 0, 103, 0, 0, 0, 51, 0, 0, 0, 212, 0, 0, 0, 135, 0, 0, 0, 54, 0, 0, 0, 75, 0, 0, 0, 17, 0, 0, 0, 32, 0, 0, 0, 5, 0, 0, 0, 166, 0, 0, 0, 41, 0, 0, 0, 193, 0, 0, 0, 135, 0, 0, 0, 23, 0, 0, 0, 246, 0, 0, 0, 150, 0, 0, 0, 202, 0, 0, 0, 47, 0, 0, 0, 218, 0, 0, 0, 56, 0, 0, 0, 167, -0, 0, 0, 27, 0, 0, 0, 252, 0, 0, 0, 202, 0, 0, 0, 125, 0, 0, 0, 254, 0, 0, 0, 8, 0, 0, 0, 137, 0, 0, 0, 226, 0, 0, 0, 71, 0, 0, 0, 43, 0, 0, 0, 106, 0, 0, 0, 93, 0, 0, 0, 75, 0, 0, 0, 250, 0, 0, 0, 161, 0, 0, 0, 180, 0, 0, 0, 222, 0, 0, 0, 182, 0, 0, 0, 194, 0, 0, 0, 49, 0, 0, 0, 81, 0, 0, 0, 245, 0, 0, 0, 224, 0, 0, 0, 164, 0, 0, 0, 11, 0, 0, 0, 92, 0, 0, 0, 229, 0, 0, 0, 198, 0, 0, 0, 4, 0, 0, 0, 142, 0, 0, 0, 43, 0, 0, 0, 87, 0, 0, 0, 190, 0, 0, 0, 56, 0, 0, 0, 133, 0, 0, 0, 35, 0, 0, 0, 203, -0, 0, 0, 183, 0, 0, 0, 190, 0, 0, 0, 79, 0, 0, 0, 169, 0, 0, 0, 211, 0, 0, 0, 110, 0, 0, 0, 18, 0, 0, 0, 170, 0, 0, 0, 213, 0, 0, 0, 178, 0, 0, 0, 46, 0, 0, 0, 147, 0, 0, 0, 41, 0, 0, 0, 154, 0, 0, 0, 74, 0, 0, 0, 136, 0, 0, 0, 24, 0, 0, 0, 67, 0, 0, 0, 245, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 252, 0, 0, 0, 219, 0, 0, 0, 162, 0, 0, 0, 89, 0, 0, 0, 33, 0, 0, 0, 141, 0, 0, 0, 189, 0, 0, 0, 126, 0, 0, 0, 51, 0, 0, 0, 174, 0, 0, 0, 47, 0, 0, 0, 135, 0, 0, 0, 26, 0, 0, 0, 208, 0, 0, 0, 151, 0, 0, 0, 199, -0, 0, 0, 13, 0, 0, 0, 77, 0, 0, 0, 99, 0, 0, 0, 1, 0, 0, 0, 239, 0, 0, 0, 5, 0, 0, 0, 132, 0, 0, 0, 236, 0, 0, 0, 64, 0, 0, 0, 221, 0, 0, 0, 168, 0, 0, 0, 10, 0, 0, 0, 79, 0, 0, 0, 112, 0, 0, 0, 11, 0, 0, 0, 65, 0, 0, 0, 105, 0, 0, 0, 1, 0, 0, 0, 103, 0, 0, 0, 92, 0, 0, 0, 211, 0, 0, 0, 138, 0, 0, 0, 197, 0, 0, 0, 207, 0, 0, 0, 63, 0, 0, 0, 209, 0, 0, 0, 87, 0, 0, 0, 209, 0, 0, 0, 103, 0, 0, 0, 62, 0, 0, 0, 1, 0, 0, 0, 57, 0, 0, 0, 181, 0, 0, 0, 203, 0, 0, 0, 129, 0, 0, 0, 86, 0, 0, 0, 150, 0, 0, -0, 38, 0, 0, 0, 182, 0, 0, 0, 194, 0, 0, 0, 231, 0, 0, 0, 92, 0, 0, 0, 251, 0, 0, 0, 99, 0, 0, 0, 151, 0, 0, 0, 88, 0, 0, 0, 6, 0, 0, 0, 12, 0, 0, 0, 14, 0, 0, 0, 243, 0, 0, 0, 186, 0, 0, 0, 240, 0, 0, 0, 229, 0, 0, 0, 186, 0, 0, 0, 178, 0, 0, 0, 87, 0, 0, 0, 119, 0, 0, 0, 198, 0, 0, 0, 32, 0, 0, 0, 155, 0, 0, 0, 137, 0, 0, 0, 36, 0, 0, 0, 190, 0, 0, 0, 242, 0, 0, 0, 156, 0, 0, 0, 138, 0, 0, 0, 186, 0, 0, 0, 105, 0, 0, 0, 193, 0, 0, 0, 241, 0, 0, 0, 176, 0, 0, 0, 79, 0, 0, 0, 42, 0, 0, 0, 5, 0, 0, -0, 154, 0, 0, 0, 238, 0, 0, 0, 16, 0, 0, 0, 126, 0, 0, 0, 54, 0, 0, 0, 63, 0, 0, 0, 38, 0, 0, 0, 233, 0, 0, 0, 64, 0, 0, 0, 233, 0, 0, 0, 3, 0, 0, 0, 173, 0, 0, 0, 6, 0, 0, 0, 105, 0, 0, 0, 145, 0, 0, 0, 224, 0, 0, 0, 209, 0, 0, 0, 137, 0, 0, 0, 96, 0, 0, 0, 132, 0, 0, 0, 121, 0, 0, 0, 222, 0, 0, 0, 39, 0, 0, 0, 109, 0, 0, 0, 230, 0, 0, 0, 118, 0, 0, 0, 189, 0, 0, 0, 234, 0, 0, 0, 230, 0, 0, 0, 174, 0, 0, 0, 72, 0, 0, 0, 195, 0, 0, 0, 103, 0, 0, 0, 192, 0, 0, 0, 87, 0, 0, 0, 205, 0, 0, 0, 47, 0, -0, 0, 127, 0, 0, 0, 193, 0, 0, 0, 220, 0, 0, 0, 185, 0, 0, 0, 199, 0, 0, 0, 188, 0, 0, 0, 134, 0, 0, 0, 61, 0, 0, 0, 85, 0, 0, 0, 75, 0, 0, 0, 40, 0, 0, 0, 122, 0, 0, 0, 251, 0, 0, 0, 77, 0, 0, 0, 199, 0, 0, 0, 248, 0, 0, 0, 188, 0, 0, 0, 103, 0, 0, 0, 42, 0, 0, 0, 96, 0, 0, 0, 77, 0, 0, 0, 143, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 26, 0, 0, 0, 23, 0, 0, 0, 191, 0, 0, 0, 250, 0, 0, 0, 172, 0, 0, 0, 167, 0, 0, 0, 61, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 63, 0, 0, 0, 237, 0, 0, 0, 94, 0, 0, 0, 24, 0, 0, 0, 120, 0, 0, 0, 63, 0, 0, 0, 35, 0, 0, 0, 44, 0, 0, 0, 13, 0, 0, 0, 140, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 251, 0, 0, 0, 233, 0, 0, 0, 142, 0, 0, 0, 214, 0, 0, 0, 209, 0, 0, 0, 54, 0, 0, 0, 88, 0, 0, 0, 87, 0, 0, 0, 158, -0, 0, 0, 174, 0, 0, 0, 75, 0, 0, 0, 92, 0, 0, 0, 11, 0, 0, 0, 7, 0, 0, 0, 188, 0, 0, 0, 107, 0, 0, 0, 85, 0, 0, 0, 43, 0, 0, 0, 111, 0, 0, 0, 77, 0, 0, 0, 23, 0, 0, 0, 215, 0, 0, 0, 225, 0, 0, 0, 132, 0, 0, 0, 217, 0, 0, 0, 120, 0, 0, 0, 177, 0, 0, 0, 144, 0, 0, 0, 253, 0, 0, 0, 46, 0, 0, 0, 179, 0, 0, 0, 181, 0, 0, 0, 25, 0, 0, 0, 63, 0, 0, 0, 27, 0, 0, 0, 250, 0, 0, 0, 192, 0, 0, 0, 104, 0, 0, 0, 179, 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 137, 0, 0, 0, 189, 0, 0, 0, 126, 0, 0, 0, 128, -0, 0, 0, 50, 0, 0, 0, 19, 0, 0, 0, 160, 0, 0, 0, 123, 0, 0, 0, 26, 0, 0, 0, 111, 0, 0, 0, 64, 0, 0, 0, 175, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 176, 0, 0, 0, 67, 0, 0, 0, 143, 0, 0, 0, 13, 0, 0, 0, 208, 0, 0, 0, 30, 0, 0, 0, 196, 0, 0, 0, 11, 0, 0, 0, 25, 0, 0, 0, 93, 0, 0, 0, 142, 0, 0, 0, 254, 0, 0, 0, 193, 0, 0, 0, 243, 0, 0, 0, 197, 0, 0, 0, 92, 0, 0, 0, 145, 0, 0, 0, 248, 0, 0, 0, 4, 0, 0, 0, 78, 0, 0, 0, 190, 0, 0, 0, 144, 0, 0, 0, 180, 0, 0, 0, 71, 0, 0, 0, 92, 0, 0, 0, 63, 0, 0, 0, 176, 0, -0, 0, 59, 0, 0, 0, 44, 0, 0, 0, 243, 0, 0, 0, 254, 0, 0, 0, 50, 0, 0, 0, 113, 0, 0, 0, 7, 0, 0, 0, 63, 0, 0, 0, 170, 0, 0, 0, 186, 0, 0, 0, 69, 0, 0, 0, 96, 0, 0, 0, 168, 0, 0, 0, 141, 0, 0, 0, 234, 0, 0, 0, 84, 0, 0, 0, 203, 0, 0, 0, 57, 0, 0, 0, 16, 0, 0, 0, 180, 0, 0, 0, 242, 0, 0, 0, 139, 0, 0, 0, 210, 0, 0, 0, 20, 0, 0, 0, 130, 0, 0, 0, 66, 0, 0, 0, 7, 0, 0, 0, 142, 0, 0, 0, 233, 0, 0, 0, 124, 0, 0, 0, 83, 0, 0, 0, 176, 0, 0, 0, 174, 0, 0, 0, 193, 0, 0, 0, 141, 0, 0, 0, 201, 0, 0, 0, 143, 0, -0, 0, 185, 0, 0, 0, 122, 0, 0, 0, 119, 0, 0, 0, 239, 0, 0, 0, 186, 0, 0, 0, 121, 0, 0, 0, 160, 0, 0, 0, 60, 0, 0, 0, 168, 0, 0, 0, 245, 0, 0, 0, 106, 0, 0, 0, 226, 0, 0, 0, 63, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 227, 0, 0, 0, 75, 0, 0, 0, 69, 0, 0, 0, 36, 0, 0, 0, 123, 0, 0, 0, 67, 0, 0, 0, 120, 0, 0, 0, 85, 0, 0, 0, 29, 0, 0, 0, 43, 0, 0, 0, 30, 0, 0, 0, 1, 0, 0, 0, 184, 0, 0, 0, 214, 0, 0, 0, 22, 0, 0, 0, 103, 0, 0, 0, 160, 0, 0, 0, 21, 0, 0, 0, 185, 0, 0, 0, 225, 0, 0, 0, 88, 0, 0, 0, 164, 0, 0, -0, 167, 0, 0, 0, 49, 0, 0, 0, 55, 0, 0, 0, 119, 0, 0, 0, 47, 0, 0, 0, 139, 0, 0, 0, 18, 0, 0, 0, 159, 0, 0, 0, 244, 0, 0, 0, 63, 0, 0, 0, 199, 0, 0, 0, 54, 0, 0, 0, 102, 0, 0, 0, 210, 0, 0, 0, 168, 0, 0, 0, 86, 0, 0, 0, 247, 0, 0, 0, 127, 0, 0, 0, 116, 0, 0, 0, 198, 0, 0, 0, 65, 0, 0, 0, 93, 0, 0, 0, 248, 0, 0, 0, 180, 0, 0, 0, 168, 0, 0, 0, 48, 0, 0, 0, 221, 0, 0, 0, 204, 0, 0, 0, 56, 0, 0, 0, 165, 0, 0, 0, 211, 0, 0, 0, 202, 0, 0, 0, 216, 0, 0, 0, 209, 0, 0, 0, 248, 0, 0, 0, 178, 0, 0, 0, 49, 0, -0, 0, 145, 0, 0, 0, 212, 0, 0, 0, 114, 0, 0, 0, 5, 0, 0, 0, 87, 0, 0, 0, 74, 0, 0, 0, 59, 0, 0, 0, 130, 0, 0, 0, 74, 0, 0, 0, 198, 0, 0, 0, 104, 0, 0, 0, 32, 0, 0, 0, 226, 0, 0, 0, 24, 0, 0, 0, 65, 0, 0, 0, 97, 0, 0, 0, 25, 0, 0, 0, 212, 0, 0, 0, 141, 0, 0, 0, 71, 0, 0, 0, 41, 0, 0, 0, 18, 0, 0, 0, 101, 0, 0, 0, 176, 0, 0, 0, 17, 0, 0, 0, 120, 0, 0, 0, 71, 0, 0, 0, 181, 0, 0, 0, 203, 0, 0, 0, 163, 0, 0, 0, 165, 0, 0, 0, 250, 0, 0, 0, 5, 0, 0, 0, 133, 0, 0, 0, 84, 0, 0, 0, 169, 0, 0, 0, 51, 0, 0, -0, 151, 0, 0, 0, 141, 0, 0, 0, 43, 0, 0, 0, 194, 0, 0, 0, 254, 0, 0, 0, 153, 0, 0, 0, 53, 0, 0, 0, 40, 0, 0, 0, 229, 0, 0, 0, 235, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 239, 0, 0, 0, 216, 0, 0, 0, 244, 0, 0, 0, -252, 0, 0, 0, 179, 0, 0, 0, 160, 0, 0, 0, 96, 0, 0, 0, 80, 0, 0, 0, 6, 0, 0, 0, 43, 0, 0, 0, 41, 0, 0, 0, 82, 0, 0, 0, 112, 0, 0, 0, 21, 0, 0, 0, 11, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 248, 0, 0, 0, 95, 0, 0, 0, 121, 0, 0, 0, 24, 0, 0, 0, 204, 0, 0, 0, 255, 0, 0, 0, 137, 0, 0, 0, 153, 0, 0, 0, 132, 0, 0, 0, 161, 0, 0, 0, 174, 0, 0, 0, 19, 0, 0, 0, 68, 0, 0, 0, 31, 0, 0, 0, 184, 0, 0, 0, 194, 0, 0, 0, 1, 0, 0, 0, 193, 0, 0, 0, 48, 0, 0, 0, 25, 0, 0, 0, 85, 0, 0, 0, 5, 0, 0, 0, 96, 0, 0, 0, 16, 0, -0, 0, 164, 0, 0, 0, 108, 0, 0, 0, 45, 0, 0, 0, 103, 0, 0, 0, 112, 0, 0, 0, 229, 0, 0, 0, 37, 0, 0, 0, 27, 0, 0, 0, 242, 0, 0, 0, 191, 0, 0, 0, 221, 0, 0, 0, 251, 0, 0, 0, 112, 0, 0, 0, 43, 0, 0, 0, 161, 0, 0, 0, 140, 0, 0, 0, 156, 0, 0, 0, 148, 0, 0, 0, 132, 0, 0, 0, 8, 0, 0, 0, 231, 0, 0, 0, 196, 0, 0, 0, 67, 0, 0, 0, 77, 0, 0, 0, 201, 0, 0, 0, 43, 0, 0, 0, 105, 0, 0, 0, 93, 0, 0, 0, 29, 0, 0, 0, 60, 0, 0, 0, 175, 0, 0, 0, 187, 0, 0, 0, 67, 0, 0, 0, 56, 0, 0, 0, 78, 0, 0, 0, 152, 0, 0, 0, 61, 0, -0, 0, 237, 0, 0, 0, 13, 0, 0, 0, 33, 0, 0, 0, 3, 0, 0, 0, 253, 0, 0, 0, 240, 0, 0, 0, 153, 0, 0, 0, 71, 0, 0, 0, 4, 0, 0, 0, 176, 0, 0, 0, 152, 0, 0, 0, 105, 0, 0, 0, 85, 0, 0, 0, 114, 0, 0, 0, 15, 0, 0, 0, 94, 0, 0, 0, 223, 0, 0, 0, 21, 0, 0, 0, 83, 0, 0, 0, 59, 0, 0, 0, 134, 0, 0, 0, 128, 0, 0, 0, 176, 0, 0, 0, 241, 0, 0, 0, 112, 0, 0, 0, 104, 0, 0, 0, 143, 0, 0, 0, 102, 0, 0, 0, 124, 0, 0, 0, 14, 0, 0, 0, 73, 0, 0, 0, 26, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, 254, 0, 0, 0, 78, 0, 0, 0, 239, 0, -0, 0, 202, 0, 0, 0, 71, 0, 0, 0, 212, 0, 0, 0, 3, 0, 0, 0, 193, 0, 0, 0, 55, 0, 0, 0, 80, 0, 0, 0, 156, 0, 0, 0, 193, 0, 0, 0, 22, 0, 0, 0, 205, 0, 0, 0, 36, 0, 0, 0, 198, 0, 0, 0, 62, 0, 0, 0, 12, 0, 0, 0, 130, 0, 0, 0, 155, 0, 0, 0, 145, 0, 0, 0, 43, 0, 0, 0, 97, 0, 0, 0, 74, 0, 0, 0, 178, 0, 0, 0, 15, 0, 0, 0, 136, 0, 0, 0, 85, 0, 0, 0, 95, 0, 0, 0, 90, 0, 0, 0, 87, 0, 0, 0, 255, 0, 0, 0, 229, 0, 0, 0, 116, 0, 0, 0, 11, 0, 0, 0, 19, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, -207, 0, 0, 0, 210, 0, 0, 0, 21, 0, 0, 0, 3, 0, 0, 0, 44, 0, 0, 0, 220, 0, 0, 0, 255, 0, 0, 0, 21, 0, 0, 0, 97, 0, 0, 0, 47, 0, 0, 0, 74, 0, 0, 0, 47, 0, 0, 0, 98, 0, 0, 0, 242, 0, 0, 0, 4, 0, 0, 0, 47, 0, 0, 0, 181, 0, 0, 0, 12, 0, 0, 0, 183, 0, 0, 0, 30, 0, 0, 0, 63, 0, 0, 0, 116, 0, 0, 0, 26, 0, 0, 0, 15, 0, 0, 0, 215, 0, 0, 0, 234, 0, 0, 0, 205, 0, 0, 0, 217, 0, 0, 0, 125, 0, 0, 0, 246, 0, 0, 0, 18, 0, 0, 0, 14, 0, 0, 0, 47, 0, 0, 0, 219, 0, 0, 0, 90, 0, 0, 0, 59, 0, 0, 0, 22, 0, 0, 0, 27, 0, -0, 0, 55, 0, 0, 0, 71, 0, 0, 0, 227, 0, 0, 0, 245, 0, 0, 0, 158, 0, 0, 0, 234, 0, 0, 0, 44, 0, 0, 0, 42, 0, 0, 0, 231, 0, 0, 0, 130, 0, 0, 0, 54, 0, 0, 0, 244, 0, 0, 0, 31, 0, 0, 0, 129, 0, 0, 0, 71, 0, 0, 0, 146, 0, 0, 0, 75, 0, 0, 0, 105, 0, 0, 0, 14, 0, 0, 0, 17, 0, 0, 0, 140, 0, 0, 0, 93, 0, 0, 0, 83, 0, 0, 0, 91, 0, 0, 0, 129, 0, 0, 0, 39, 0, 0, 0, 8, 0, 0, 0, 188, 0, 0, 0, 160, 0, 0, 0, 174, 0, 0, 0, 37, 0, 0, 0, 105, 0, 0, 0, 50, 0, 0, 0, 161, 0, 0, 0, 5, 0, 0, 0, 17, 0, 0, 0, 66, 0, 0, 0, -0, 0, 0, 0, 210, 0, 0, 0, 89, 0, 0, 0, 172, 0, 0, 0, 77, 0, 0, 0, 98, 0, 0, 0, 139, 0, 0, 0, 19, 0, 0, 0, 226, 0, 0, 0, 80, 0, 0, 0, 93, 0, 0, 0, 160, 0, 0, 0, 157, 0, 0, 0, 155, 0, 0, 0, 253, 0, 0, 0, 187, 0, 0, 0, 18, 0, 0, 0, 65, 0, 0, 0, 117, 0, 0, 0, 65, 0, 0, 0, 158, 0, 0, 0, 204, 0, 0, 0, 220, 0, 0, 0, 199, 0, 0, 0, 220, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 227, 0, 0, 0, 56, 0, 0, 0, 6, 0, 0, 0, 70, 0, 0, 0, 112, 0, 0, 0, 130, 0, 0, 0, 94, 0, 0, 0, 40, 0, 0, 0, 73, 0, 0, 0, 121, 0, 0, 0, 255, 0, 0, 0, 37, 0, 0, 0, 210, 0, 0, 0, 78, 0, 0, 0, 41, 0, 0, 0, 141, 0, 0, 0, 6, 0, 0, 0, 176, 0, 0, 0, 35, 0, 0, 0, 174, 0, 0, 0, 155, 0, 0, 0, 102, 0, 0, 0, 228, 0, 0, 0, 125, 0, 0, 0, 192, 0, 0, 0, 112, 0, 0, 0, 145, 0, 0, 0, 163, -0, 0, 0, 252, 0, 0, 0, 236, 0, 0, 0, 78, 0, 0, 0, 98, 0, 0, 0, 18, 0, 0, 0, 55, 0, 0, 0, 106, 0, 0, 0, 48, 0, 0, 0, 246, 0, 0, 0, 30, 0, 0, 0, 251, 0, 0, 0, 20, 0, 0, 0, 92, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 183, 0, 0, 0, 129, 0, 0, 0, 106, 0, 0, 0, 231, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 172, 0, 0, 0, 170, 0, 0, 0, 56, 0, 0, 0, 70, 0, 0, 0, 226, 0, 0, 0, 115, 0, 0, 0, 234, 0, 0, 0, 75, 0, 0, 0, 7, 0, 0, 0, 129, 0, 0, 0, 67, 0, 0, 0, 124, 0, 0, 0, 158, 0, 0, 0, 94, 0, 0, 0, 252, 0, 0, 0, 249, 0, 0, -0, 33, 0, 0, 0, 79, 0, 0, 0, 46, 0, 0, 0, 118, 0, 0, 0, 155, 0, 0, 0, 31, 0, 0, 0, 40, 0, 0, 0, 96, 0, 0, 0, 119, 0, 0, 0, 67, 0, 0, 0, 50, 0, 0, 0, 157, 0, 0, 0, 190, 0, 0, 0, 23, 0, 0, 0, 48, 0, 0, 0, 42, 0, 0, 0, 198, 0, 0, 0, 24, 0, 0, 0, 146, 0, 0, 0, 102, 0, 0, 0, 98, 0, 0, 0, 48, 0, 0, 0, 152, 0, 0, 0, 64, 0, 0, 0, 17, 0, 0, 0, 166, 0, 0, 0, 127, 0, 0, 0, 24, 0, 0, 0, 132, 0, 0, 0, 40, 0, 0, 0, 63, 0, 0, 0, 171, 0, 0, 0, 211, 0, 0, 0, 244, 0, 0, 0, 138, 0, 0, 0, 118, 0, 0, 0, 161, 0, 0, 0, -60, 0, 0, 0, 202, 0, 0, 0, 45, 0, 0, 0, 73, 0, 0, 0, 195, 0, 0, 0, 234, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 133, 0, 0, 0, 23, 0, 0, 0, 42, 0, 0, 0, 195, 0, 0, 0, 108, 0, 0, 0, 8, 0, 0, 0, 253, 0, 0, 0, 87, 0, 0, 0, 159, 0, 0, 0, 61, 0, 0, 0, 95, 0, 0, 0, 223, 0, 0, 0, 103, 0, 0, 0, 104, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 81, 0, 0, 0, 96, 0, 0, 0, 27, 0, 0, 0, 6, 0, 0, 0, 79, 0, 0, 0, 138, 0, 0, 0, 33, 0, 0, 0, 186, 0, 0, 0, 56, 0, 0, 0, 168, 0, 0, 0, 186, 0, 0, 0, 214, 0, 0, 0, 64, 0, 0, -0, 246, 0, 0, 0, 233, 0, 0, 0, 155, 0, 0, 0, 118, 0, 0, 0, 77, 0, 0, 0, 86, 0, 0, 0, 33, 0, 0, 0, 91, 0, 0, 0, 10, 0, 0, 0, 155, 0, 0, 0, 46, 0, 0, 0, 79, 0, 0, 0, 61, 0, 0, 0, 129, 0, 0, 0, 50, 0, 0, 0, 8, 0, 0, 0, 159, 0, 0, 0, 151, 0, 0, 0, 91, 0, 0, 0, 229, 0, 0, 0, 68, 0, 0, 0, 236, 0, 0, 0, 6, 0, 0, 0, 157, 0, 0, 0, 144, 0, 0, 0, 121, 0, 0, 0, 159, 0, 0, 0, 211, 0, 0, 0, 224, 0, 0, 0, 121, 0, 0, 0, 175, 0, 0, 0, 143, 0, 0, 0, 16, 0, 0, 0, 253, 0, 0, 0, 221, 0, 0, 0, 4, 0, 0, 0, 174, 0, 0, 0, -39, 0, 0, 0, 151, 0, 0, 0, 70, 0, 0, 0, 51, 0, 0, 0, 121, 0, 0, 0, 234, 0, 0, 0, 184, 0, 0, 0, 78, 0, 0, 0, 202, 0, 0, 0, 90, 0, 0, 0, 89, 0, 0, 0, 87, 0, 0, 0, 225, 0, 0, 0, 14, 0, 0, 0, 26, 0, 0, 0, 218, 0, 0, 0, 243, 0, 0, 0, 165, 0, 0, 0, 65, 0, 0, 0, 67, 0, 0, 0, 40, 0, 0, 0, 252, 0, 0, 0, 126, 0, 0, 0, 231, 0, 0, 0, 113, 0, 0, 0, 234, 0, 0, 0, 198, 0, 0, 0, 59, 0, 0, 0, 89, 0, 0, 0, 204, 0, 0, 0, 46, 0, 0, 0, 211, 0, 0, 0, 64, 0, 0, 0, 236, 0, 0, 0, 179, 0, 0, 0, 19, 0, 0, 0, 111, 0, 0, 0, -68, 0, 0, 0, 205, 0, 0, 0, 19, 0, 0, 0, 178, 0, 0, 0, 55, 0, 0, 0, 242, 0, 0, 0, 110, 0, 0, 0, 217, 0, 0, 0, 28, 0, 0, 0, 227, 0, 0, 0, 219, 0, 0, 0, 96, 0, 0, 0, 205, 0, 0, 0, 92, 0, 0, 0, 74, 0, 0, 0, 24, 0, 0, 0, 15, 0, 0, 0, 239, 0, 0, 0, 115, 0, 0, 0, 54, 0, 0, 0, 113, 0, 0, 0, 140, 0, 0, 0, 246, 0, 0, 0, 17, 0, 0, 0, 180, 0, 0, 0, 216, 0, 0, 0, 206, 0, 0, 0, 23, 0, 0, 0, 94, 0, 0, 0, 79, 0, 0, 0, 38, 0, 0, 0, 119, 0, 0, 0, 151, 0, 0, 0, 95, 0, 0, 0, 203, 0, 0, 0, 239, 0, 0, 0, 145, 0, 0, 0, -235, 0, 0, 0, 106, 0, 0, 0, 98, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 74, 0, 0, 0, 162, 0, 0, 0, 151, 0, 0, 0, 8, 0, 0, 0, 129, 0, 0, 0, 45, 0, 0, 0, 131, 0, 0, 0, 196, 0, 0, 0, 204, 0, 0, 0, 240, 0, 0, 0, 131, 0, 0, 0, 126, 0, 0, 0, 236, -0, 0, 0, 13, 0, 0, 0, 149, 0, 0, 0, 76, 0, 0, 0, 91, 0, 0, 0, 251, 0, 0, 0, 250, 0, 0, 0, 152, 0, 0, 0, 128, 0, 0, 0, 74, 0, 0, 0, 102, 0, 0, 0, 86, 0, 0, 0, 12, 0, 0, 0, 81, 0, 0, 0, 179, 0, 0, 0, 242, 0, 0, 0, 4, 0, 0, 0, 93, 0, 0, 0, 39, 0, 0, 0, 59, 0, 0, 0, 185, 0, 0, 0, 184, 0, 0, 0, 6, 0, 0, 0, 90, 0, 0, 0, 46, 0, 0, 0, 254, 0, 0, 0, 195, 0, 0, 0, 130, 0, 0, 0, 55, 0, 0, 0, 156, 0, 0, 0, 163, 0, 0, 0, 17, 0, 0, 0, 31, 0, 0, 0, 156, 0, 0, 0, 166, 0, 0, 0, 218, 0, 0, 0, 99, 0, 0, 0, 72, 0, 0, -0, 155, 0, 0, 0, 173, 0, 0, 0, 222, 0, 0, 0, 45, 0, 0, 0, 166, 0, 0, 0, 188, 0, 0, 0, 110, 0, 0, 0, 50, 0, 0, 0, 218, 0, 0, 0, 39, 0, 0, 0, 101, 0, 0, 0, 221, 0, 0, 0, 87, 0, 0, 0, 132, 0, 0, 0, 79, 0, 0, 0, 55, 0, 0, 0, 49, 0, 0, 0, 125, 0, 0, 0, 46, 0, 0, 0, 188, 0, 0, 0, 173, 0, 0, 0, 135, 0, 0, 0, 7, 0, 0, 0, 42, 0, 0, 0, 107, 0, 0, 0, 55, 0, 0, 0, 252, 0, 0, 0, 95, 0, 0, 0, 235, 0, 0, 0, 78, 0, 0, 0, 117, 0, 0, 0, 53, 0, 0, 0, 166, 0, 0, 0, 222, 0, 0, 0, 171, 0, 0, 0, 10, 0, 0, 0, 25, 0, 0, -0, 58, 0, 0, 0, 183, 0, 0, 0, 177, 0, 0, 0, 239, 0, 0, 0, 146, 0, 0, 0, 106, 0, 0, 0, 59, 0, 0, 0, 60, 0, 0, 0, 59, 0, 0, 0, 178, 0, 0, 0, 148, 0, 0, 0, 109, 0, 0, 0, 57, 0, 0, 0, 96, 0, 0, 0, 172, 0, 0, 0, 238, 0, 0, 0, 231, 0, 0, 0, 129, 0, 0, 0, 26, 0, 0, 0, 59, 0, 0, 0, 118, 0, 0, 0, 135, 0, 0, 0, 92, 0, 0, 0, 5, 0, 0, 0, 148, 0, 0, 0, 42, 0, 0, 0, 69, 0, 0, 0, 185, 0, 0, 0, 128, 0, 0, 0, 233, 0, 0, 0, 34, 0, 0, 0, 177, 0, 0, 0, 7, 0, 0, 0, 203, 0, 0, 0, 64, 0, 0, 0, 158, 0, 0, 0, 112, 0, 0, -0, 73, 0, 0, 0, 109, 0, 0, 0, 18, 0, 0, 0, 253, 0, 0, 0, 24, 0, 0, 0, 120, 0, 0, 0, 132, 0, 0, 0, 168, 0, 0, 0, 76, 0, 0, 0, 125, 0, 0, 0, 110, 0, 0, 0, 89, 0, 0, 0, 166, 0, 0, 0, 229, 0, 0, 0, 116, 0, 0, 0, 241, 0, 0, 0, 25, 0, 0, 0, 166, 0, 0, 0, 132, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 193, 0, 0, 0, 41, 0, 0, 0, 19, 0, 0, 0, 242, 0, 0, 0, 20, 0, 0, 0, 107, 0, 0, 0, 93, 0, 0, 0, 83, 0, 0, 0, 81, 0, 0, 0, 247, 0, 0, 0, 239, 0, 0, 0, 191, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 164, 0, 0, 0, 75, 0, 0, 0, -98, 0, 0, 0, 76, 0, 0, 0, 230, 0, 0, 0, 253, 0, 0, 0, 114, 0, 0, 0, 7, 0, 0, 0, 242, 0, 0, 0, 129, 0, 0, 0, 252, 0, 0, 0, 242, 0, 0, 0, 189, 0, 0, 0, 18, 0, 0, 0, 124, 0, 0, 0, 104, 0, 0, 0, 118, 0, 0, 0, 42, 0, 0, 0, 186, 0, 0, 0, 245, 0, 0, 0, 101, 0, 0, 0, 177, 0, 0, 0, 31, 0, 0, 0, 23, 0, 0, 0, 10, 0, 0, 0, 56, 0, 0, 0, 176, 0, 0, 0, 191, 0, 0, 0, 192, 0, 0, 0, 248, 0, 0, 0, 244, 0, 0, 0, 42, 0, 0, 0, 85, 0, 0, 0, 96, 0, 0, 0, 85, 0, 0, 0, 91, 0, 0, 0, 228, 0, 0, 0, 29, 0, 0, 0, 113, 0, 0, 0, -76, 0, 0, 0, 157, 0, 0, 0, 91, 0, 0, 0, 159, 0, 0, 0, 112, 0, 0, 0, 166, 0, 0, 0, 133, 0, 0, 0, 154, 0, 0, 0, 44, 0, 0, 0, 160, 0, 0, 0, 226, 0, 0, 0, 50, 0, 0, 0, 72, 0, 0, 0, 206, 0, 0, 0, 158, 0, 0, 0, 42, 0, 0, 0, 165, 0, 0, 0, 7, 0, 0, 0, 59, 0, 0, 0, 199, 0, 0, 0, 108, 0, 0, 0, 134, 0, 0, 0, 119, 0, 0, 0, 222, 0, 0, 0, 60, 0, 0, 0, 247, 0, 0, 0, 24, 0, 0, 0, 122, 0, 0, 0, 150, 0, 0, 0, 126, 0, 0, 0, 67, 0, 0, 0, 87, 0, 0, 0, 169, 0, 0, 0, 85, 0, 0, 0, 252, 0, 0, 0, 78, 0, 0, 0, 182, 0, 0, 0, -114, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 0, 228, 0, 0, 0, 215, 0, 0, 0, 82, 0, 0, 0, 211, 0, 0, 0, 211, 0, 0, 0, 182, 0, 0, 0, 133, 0, 0, 0, 246, 0, 0, 0, 113, 0, 0, 0, 199, 0, 0, 0, 68, 0, 0, 0, 63, 0, 0, 0, 127, 0, 0, 0, 215, 0, 0, 0, 179, 0, 0, 0, 242, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 202, 0, 0, 0, 167, 0, 0, 0, 85, 0, 0, 0, 123, 0, 0, 0, 121, 0, 0, 0, 243, 0, 0, 0, 202, 0, 0, 0, 90, 0, 0, 0, 101, 0, 0, 0, 246, 0, 0, 0, 237, 0, 0, 0, 80, 0, 0, 0, 20, 0, 0, 0, 123, 0, 0, 0, 228, 0, 0, 0, 196, 0, 0, 0, 42, 0, 0, 0, 101, 0, 0, 0, 158, 0, 0, 0, 226, 0, 0, 0, 249, 0, 0, 0, 202, 0, 0, 0, 167, 0, 0, 0, 34, 0, 0, 0, 38, 0, 0, 0, 83, 0, 0, 0, 203, 0, 0, 0, 33, 0, 0, 0, 91, 0, 0, 0, 167, 0, 0, 0, 49, 0, 0, 0, 144, 0, 0, 0, 215, 0, 0, 0, -197, 0, 0, 0, 38, 0, 0, 0, 8, 0, 0, 0, 189, 0, 0, 0, 176, 0, 0, 0, 83, 0, 0, 0, 99, 0, 0, 0, 88, 0, 0, 0, 195, 0, 0, 0, 49, 0, 0, 0, 94, 0, 0, 0, 117, 0, 0, 0, 70, 0, 0, 0, 21, 0, 0, 0, 145, 0, 0, 0, 166, 0, 0, 0, 248, 0, 0, 0, 47, 0, 0, 0, 26, 0, 0, 0, 8, 0, 0, 0, 101, 0, 0, 0, 136, 0, 0, 0, 47, 0, 0, 0, 152, 0, 0, 0, 4, 0, 0, 0, 241, 0, 0, 0, 124, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 129, 0, 0, 0, 33, 0, 0, 0, 97, 0, 0, 0, 9, 0, 0, 0, 246, 0, 0, 0, 78, 0, 0, 0, 241, 0, 0, 0, 146, 0, -0, 0, 238, 0, 0, 0, 99, 0, 0, 0, 97, 0, 0, 0, 115, 0, 0, 0, 135, 0, 0, 0, 199, 0, 0, 0, 84, 0, 0, 0, 14, 0, 0, 0, 66, 0, 0, 0, 75, 0, 0, 0, 201, 0, 0, 0, 71, 0, 0, 0, 209, 0, 0, 0, 184, 0, 0, 0, 126, 0, 0, 0, 145, 0, 0, 0, 117, 0, 0, 0, 55, 0, 0, 0, 153, 0, 0, 0, 40, 0, 0, 0, 184, 0, 0, 0, 221, 0, 0, 0, 127, 0, 0, 0, 80, 0, 0, 0, 137, 0, 0, 0, 143, 0, 0, 0, 192, 0, 0, 0, 190, 0, 0, 0, 93, 0, 0, 0, 214, 0, 0, 0, 159, 0, 0, 0, 160, 0, 0, 0, 240, 0, 0, 0, 157, 0, 0, 0, 129, 0, 0, 0, 206, 0, 0, 0, 58, -0, 0, 0, 123, 0, 0, 0, 152, 0, 0, 0, 88, 0, 0, 0, 187, 0, 0, 0, 215, 0, 0, 0, 120, 0, 0, 0, 200, 0, 0, 0, 63, 0, 0, 0, 19, 0, 0, 0, 241, 0, 0, 0, 116, 0, 0, 0, 25, 0, 0, 0, 223, 0, 0, 0, 248, 0, 0, 0, 152, 0, 0, 0, 137, 0, 0, 0, 93, 0, 0, 0, 250, 0, 0, 0, 95, 0, 0, 0, 158, 0, 0, 0, 53, 0, 0, 0, 133, 0, 0, 0, 148, 0, 0, 0, 71, 0, 0, 0, 31, 0, 0, 0, 144, 0, 0, 0, 21, 0, 0, 0, 38, 0, 0, 0, 208, 0, 0, 0, 132, 0, 0, 0, 237, 0, 0, 0, 138, 0, 0, 0, 128, 0, 0, 0, 247, 0, 0, 0, 99, 0, 0, 0, 66, 0, 0, 0, 134, -0, 0, 0, 39, 0, 0, 0, 215, 0, 0, 0, 244, 0, 0, 0, 117, 0, 0, 0, 88, 0, 0, 0, 220, 0, 0, 0, 156, 0, 0, 0, 192, 0, 0, 0, 34, 0, 0, 0, 126, 0, 0, 0, 32, 0, 0, 0, 53, 0, 0, 0, 253, 0, 0, 0, 31, 0, 0, 0, 104, 0, 0, 0, 14, 0, 0, 0, 111, 0, 0, 0, 151, 0, 0, 0, 186, 0, 0, 0, 112, 0, 0, 0, 187, 0, 0, 0, 163, 0, 0, 0, 14, 0, 0, 0, 229, 0, 0, 0, 11, 0, 0, 0, 18, 0, 0, 0, 244, 0, 0, 0, 162, 0, 0, 0, 220, 0, 0, 0, 71, 0, 0, 0, 248, 0, 0, 0, 230, 0, 0, 0, 208, 0, 0, 0, 35, 0, 0, 0, 108, 0, 0, 0, 51, 0, 0, 0, 168, -0, 0, 0, 153, 0, 0, 0, 70, 0, 0, 0, 110, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 186, 0, 0, 0, 118, 0, 0, 0, 72, 0, 0, 0, 15, 0, 0, 0, 163, 0, 0, 0, 42, 0, 0, 0, 97, 0, 0, 0, 55, 0, 0, 0, 226, 0, 0, 0, 89, 0, 0, 0, 18, 0, 0, 0, 14, 0, 0, 0, 39, 0, 0, 0, 186, 0, 0, 0, 100, 0, 0, 0, 67, 0, 0, 0, 174, 0, 0, 0, 192, 0, 0, 0, 66, 0, 0, 0, 105, 0, 0, 0, 121, 0, 0, 0, 164, 0, 0, 0, 30, 0, 0, 0, 41, 0, 0, 0, 139, 0, 0, 0, 21, 0, 0, 0, 235, 0, 0, 0, 248, 0, 0, 0, 175, 0, 0, 0, 212, 0, 0, 0, 162, 0, 0, 0, 104, -0, 0, 0, 51, 0, 0, 0, 181, 0, 0, 0, 122, 0, 0, 0, 36, 0, 0, 0, 44, 0, 0, 0, 25, 0, 0, 0, 51, 0, 0, 0, 221, 0, 0, 0, 27, 0, 0, 0, 171, 0, 0, 0, 236, 0, 0, 0, 1, 0, 0, 0, 176, 0, 0, 0, 35, 0, 0, 0, 248, 0, 0, 0, 66, 0, 0, 0, 43, 0, 0, 0, 6, 0, 0, 0, 136, 0, 0, 0, 234, 0, 0, 0, 61, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 120, 0, 0, 0, 69, 0, 0, 0, 77, 0, 0, 0, 56, 0, 0, 0, 237, 0, 0, 0, 46, 0, 0, 0, 46, 0, 0, 0, 68, 0, 0, 0, 73, 0, 0, 0, 237, 0, 0, 0, 203, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 104, 0, 0, 0, 232, 0, 0, 0, 65, 0, 0, 0, 143, 0, 0, 0, 145, 0, 0, 0, 248, 0, 0, 0, 17, 0, 0, 0, 19, 0, 0, 0, 144, 0, 0, 0, 46, 0, 0, 0, 167, 0, 0, 0, 171, 0, 0, 0, 48, 0, 0, 0, 239, 0, 0, 0, 173, 0, 0, 0, 160, 0, 0, 0, 97, 0, 0, 0, 0, -0, 0, 0, 136, 0, 0, 0, 239, 0, 0, 0, 219, 0, 0, 0, 206, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 187, 0, 0, 0, 98, 0, 0, 0, 200, 0, 0, 0, 86, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0, 115, 0, 0, 0, 63, 0, 0, 0, 96, 0, 0, 0, 193, 0, 0, 0, 130, 0, 0, 0, 45, 0, 0, 0, 163, 0, 0, 0, 40, 0, 0, 0, 88, 0, 0, 0, 36, 0, 0, 0, 158, 0, 0, 0, 159, 0, 0, 0, 227, 0, 0, 0, 112, 0, 0, 0, 204, 0, 0, 0, 9, 0, 0, 0, 78, 0, 0, 0, 26, 0, 0, 0, 63, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 60, 0, 0, 0, 164, 0, 0, -0, 65, 0, 0, 0, 224, 0, 0, 0, 101, 0, 0, 0, 163, 0, 0, 0, 10, 0, 0, 0, 65, 0, 0, 0, 109, 0, 0, 0, 17, 0, 0, 0, 49, 0, 0, 0, 64, 0, 0, 0, 1, 0, 0, 0, 82, 0, 0, 0, 86, 0, 0, 0, 148, 0, 0, 0, 91, 0, 0, 0, 40, 0, 0, 0, 138, 0, 0, 0, 170, 0, 0, 0, 82, 0, 0, 0, 238, 0, 0, 0, 216, 0, 0, 0, 10, 0, 0, 0, 5, 0, 0, 0, 141, 0, 0, 0, 205, 0, 0, 0, 181, 0, 0, 0, 170, 0, 0, 0, 46, 0, 0, 0, 56, 0, 0, 0, 170, 0, 0, 0, 183, 0, 0, 0, 135, 0, 0, 0, 247, 0, 0, 0, 43, 0, 0, 0, 251, 0, 0, 0, 4, 0, 0, 0, 203, 0, 0, 0, 132, -0, 0, 0, 61, 0, 0, 0, 84, 0, 0, 0, 32, 0, 0, 0, 239, 0, 0, 0, 89, 0, 0, 0, 222, 0, 0, 0, 164, 0, 0, 0, 43, 0, 0, 0, 147, 0, 0, 0, 110, 0, 0, 0, 46, 0, 0, 0, 236, 0, 0, 0, 66, 0, 0, 0, 154, 0, 0, 0, 212, 0, 0, 0, 45, 0, 0, 0, 244, 0, 0, 0, 70, 0, 0, 0, 88, 0, 0, 0, 39, 0, 0, 0, 43, 0, 0, 0, 24, 0, 0, 0, 143, 0, 0, 0, 131, 0, 0, 0, 61, 0, 0, 0, 105, 0, 0, 0, 158, 0, 0, 0, 212, 0, 0, 0, 62, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 253, 0, 0, 0, 88, 0, 0, 0, 3, 0, 0, 0, 51, 0, 0, 0, 137, 0, 0, 0, 201, 0, -0, 0, 99, 0, 0, 0, 98, 0, 0, 0, 28, 0, 0, 0, 23, 0, 0, 0, 180, 0, 0, 0, 96, 0, 0, 0, 196, 0, 0, 0, 38, 0, 0, 0, 104, 0, 0, 0, 9, 0, 0, 0, 195, 0, 0, 0, 46, 0, 0, 0, 55, 0, 0, 0, 15, 0, 0, 0, 123, 0, 0, 0, 180, 0, 0, 0, 156, 0, 0, 0, 182, 0, 0, 0, 249, 0, 0, 0, 251, 0, 0, 0, 212, 0, 0, 0, 81, 0, 0, 0, 120, 0, 0, 0, 200, 0, 0, 0, 99, 0, 0, 0, 234, 0, 0, 0, 119, 0, 0, 0, 71, 0, 0, 0, 7, 0, 0, 0, 50, 0, 0, 0, 180, 0, 0, 0, 24, 0, 0, 0, 71, 0, 0, 0, 121, 0, 0, 0, 203, 0, 0, 0, 212, 0, 0, 0, 90, 0, 0, -0, 7, 0, 0, 0, 20, 0, 0, 0, 15, 0, 0, 0, 160, 0, 0, 0, 213, 0, 0, 0, 172, 0, 0, 0, 208, 0, 0, 0, 65, 0, 0, 0, 64, 0, 0, 0, 171, 0, 0, 0, 97, 0, 0, 0, 35, 0, 0, 0, 229, 0, 0, 0, 42, 0, 0, 0, 42, 0, 0, 0, 111, 0, 0, 0, 247, 0, 0, 0, 168, 0, 0, 0, 212, 0, 0, 0, 118, 0, 0, 0, 239, 0, 0, 0, 231, 0, 0, 0, 69, 0, 0, 0, 108, 0, 0, 0, 161, 0, 0, 0, 94, 0, 0, 0, 96, 0, 0, 0, 79, 0, 0, 0, 251, 0, 0, 0, 225, 0, 0, 0, 112, 0, 0, 0, 106, 0, 0, 0, 31, 0, 0, 0, 85, 0, 0, 0, 79, 0, 0, 0, 9, 0, 0, 0, 180, 0, 0, 0, -149, 0, 0, 0, 51, 0, 0, 0, 54, 0, 0, 0, 198, 0, 0, 0, 129, 0, 0, 0, 1, 0, 0, 0, 24, 0, 0, 0, 6, 0, 0, 0, 37, 0, 0, 0, 39, 0, 0, 0, 164, 0, 0, 0, 180, 0, 0, 0, 36, 0, 0, 0, 164, 0, 0, 0, 134, 0, 0, 0, 3, 0, 0, 0, 76, 0, 0, 0, 172, 0, 0, 0, 2, 0, 0, 0, 119, 0, 0, 0, 56, 0, 0, 0, 222, 0, 0, 0, 215, 0, 0, 0, 96, 0, 0, 0, 72, 0, 0, 0, 7, 0, 0, 0, 240, 0, 0, 0, 116, 0, 0, 0, 168, 0, 0, 0, 255, 0, 0, 0, 84, 0, 0, 0, 229, 0, 0, 0, 48, 0, 0, 0, 67, 0, 0, 0, 255, 0, 0, 0, 119, 0, 0, 0, 251, 0, 0, 0, 33, 0, -0, 0, 7, 0, 0, 0, 255, 0, 0, 0, 178, 0, 0, 0, 7, 0, 0, 0, 107, 0, 0, 0, 228, 0, 0, 0, 229, 0, 0, 0, 48, 0, 0, 0, 252, 0, 0, 0, 25, 0, 0, 0, 108, 0, 0, 0, 163, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 197, 0, 0, 0, 44, 0, 0, 0, 172, 0, 0, 0, -211, 0, 0, 0, 131, 0, 0, 0, 130, 0, 0, 0, 124, 0, 0, 0, 41, 0, 0, 0, 247, 0, 0, 0, 5, 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 31, 0, 0, 0, 134, 0, 0, 0, 85, 0, 0, 0, 244, 0, 0, 0, 214, 0, 0, 0, 47, 0, 0, 0, 12, 0, 0, 0, 153, 0, 0, 0, 208, 0, 0, 0, 101, 0, 0, 0, 155, 0, 0, 0, 107, 0, 0, 0, 70, 0, 0, 0, 13, 0, 0, 0, 67, 0, 0, 0, 248, 0, 0, 0, 22, 0, 0, 0, 40, 0, 0, 0, 30, 0, 0, 0, 127, 0, 0, 0, 180, 0, 0, 0, 116, 0, 0, 0, 126, 0, 0, 0, 177, 0, 0, 0, 137, 0, 0, 0, 79, 0, 0, 0, 24, 0, 0, 0, -90, 0, 0, 0, 171, 0, 0, 0, 100, 0, 0, 0, 6, 0, 0, 0, 223, 0, 0, 0, 69, 0, 0, 0, 135, 0, 0, 0, 224, 0, 0, 0, 106, 0, 0, 0, 198, 0, 0, 0, 240, 0, 0, 0, 14, 0, 0, 0, 201, 0, 0, 0, 36, 0, 0, 0, 53, 0, 0, 0, 56, 0, 0, 0, 234, 0, 0, 0, 48, 0, 0, 0, 84, 0, 0, 0, 180, 0, 0, 0, 196, 0, 0, 0, 82, 0, 0, 0, 84, 0, 0, 0, 233, 0, 0, 0, 159, 0, 0, 0, 220, 0, 0, 0, 63, 0, 0, 0, 193, 0, 0, 0, 137, 0, 0, 0, 68, 0, 0, 0, 116, 0, 0, 0, 39, 0, 0, 0, 228, 0, 0, 0, 193, 0, 0, 0, 144, 0, 0, 0, 255, 0, 0, 0, 74, 0, 0, 0, -167, 0, 0, 0, 60, 0, 0, 0, 238, 0, 0, 0, 205, 0, 0, 0, 244, 0, 0, 0, 29, 0, 0, 0]).concat([37, 0, 0, 0, 148, 0, 0, 0, 127, 0, 0, 0, 99, 0, 0, 0, 22, 0, 0, 0, 72, 0, 0, 0, 188, 0, 0, 0, 100, 0, 0, 0, 254, 0, 0, 0, 149, 0, 0, 0, 196, 0, 0, 0, 12, 0, 0, 0, 139, 0, 0, 0, 25, 0, 0, 0, 117, 0, 0, 0, 110, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 94, 0, 0, 0, 106, 0, 0, 0, 111, 0, 0, 0, 26, 0, 0, 0, 140, 0, 0, 0, 227, 0, 0, 0, 211, 0, 0, 0, 40, 0, 0, 0, 242, 0, 0, 0, 224, 0, 0, 0, 185, 0, 0, 0, 122, 0, 0, 0, 67, -0, 0, 0, 105, 0, 0, 0, 230, 0, 0, 0, 211, 0, 0, 0, 192, 0, 0, 0, 254, 0, 0, 0, 126, 0, 0, 0, 151, 0, 0, 0, 171, 0, 0, 0, 108, 0, 0, 0, 123, 0, 0, 0, 142, 0, 0, 0, 19, 0, 0, 0, 66, 0, 0, 0, 212, 0, 0, 0, 202, 0, 0, 0, 112, 0, 0, 0, 61, 0, 0, 0, 171, 0, 0, 0, 251, 0, 0, 0, 95, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 204, 0, 0, 0, 119, 0, 0, 0, 34, 0, 0, 0, 248, 0, 0, 0, 120, 0, 0, 0, 85, 0, 0, 0, 174, 0, 0, 0, 98, 0, 0, 0, 53, 0, 0, 0, 251, 0, 0, 0, 154, 0, 0, 0, 198, 0, 0, 0, 3, 0, 0, 0, 228, -0, 0, 0, 12, 0, 0, 0, 238, 0, 0, 0, 171, 0, 0, 0, 199, 0, 0, 0, 192, 0, 0, 0, 137, 0, 0, 0, 135, 0, 0, 0, 84, 0, 0, 0, 50, 0, 0, 0, 173, 0, 0, 0, 174, 0, 0, 0, 133, 0, 0, 0, 88, 0, 0, 0, 67, 0, 0, 0, 184, 0, 0, 0, 177, 0, 0, 0, 230, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 120, 0, 0, 0, 136, 0, 0, 0, 86, 0, 0, 0, 219, 0, 0, 0, 156, 0, 0, 0, 252, 0, 0, 0, 121, 0, 0, 0, 246, 0, 0, 0, 249, 0, 0, 0, 65, 0, 0, 0, 95, 0, 0, 0, 183, 0, 0, 0, 188, 0, 0, 0, 17, 0, 0, 0, 249, 0, 0, 0, 32, 0, 0, 0, 54, -0, 0, 0, 28, 0, 0, 0, 83, 0, 0, 0, 43, 0, 0, 0, 90, 0, 0, 0, 32, 0, 0, 0, 91, 0, 0, 0, 161, 0, 0, 0, 165, 0, 0, 0, 68, 0, 0, 0, 145, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 100, 0, 0, 0, 184, 0, 0, 0, 85, 0, 0, 0, 246, 0, 0, 0, 222, 0, 0, 0, 44, 0, 0, 0, 219, 0, 0, 0, 71, 0, 0, 0, 184, 0, 0, 0, 198, 0, 0, 0, 10, 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 147, 0, 0, 0, 216, 0, 0, 0, 245, 0, 0, 0, 245, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 10, 0, 0, 0, 214, 0, 0, 0, 27, 0, 0, -0, 154, 0, 0, 0, 108, 0, 0, 0, 229, 0, 0, 0, 70, 0, 0, 0, 234, 0, 0, 0, 112, 0, 0, 0, 150, 0, 0, 0, 141, 0, 0, 0, 78, 0, 0, 0, 42, 0, 0, 0, 82, 0, 0, 0, 33, 0, 0, 0, 38, 0, 0, 0, 75, 0, 0, 0, 177, 0, 0, 0, 187, 0, 0, 0, 15, 0, 0, 0, 124, 0, 0, 0, 169, 0, 0, 0, 155, 0, 0, 0, 4, 0, 0, 0, 187, 0, 0, 0, 81, 0, 0, 0, 8, 0, 0, 0, 241, 0, 0, 0, 154, 0, 0, 0, 164, 0, 0, 0, 118, 0, 0, 0, 124, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 148, 0, 0, 0, 247, 0, 0, 0, 64, 0, 0, 0, 208, 0, 0, 0, 215, 0, 0, 0, 235, 0, 0, 0, 169, 0, 0, 0, 130, 0, 0, 0, 54, 0, 0, 0, 213, 0, 0, 0, 21, 0, 0, 0, 185, 0, 0, 0, 51, 0, 0, 0, 122, 0, 0, 0, 191, 0, 0, 0, 138, 0, 0, 0, 242, 0, 0, 0, 99, 0, 0, 0, 170, 0, 0, 0, 55, 0, 0, 0, 245, 0, 0, 0, 89, 0, 0, 0, 172, 0, 0, 0, -189, 0, 0, 0, 187, 0, 0, 0, 50, 0, 0, 0, 54, 0, 0, 0, 190, 0, 0, 0, 115, 0, 0, 0, 153, 0, 0, 0, 56, 0, 0, 0, 44, 0, 0, 0, 179, 0, 0, 0, 218, 0, 0, 0, 122, 0, 0, 0, 216, 0, 0, 0, 61, 0, 0, 0, 153, 0, 0, 0, 202, 0, 0, 0, 210, 0, 0, 0, 244, 0, 0, 0, 218, 0, 0, 0, 153, 0, 0, 0, 142, 0, 0, 0, 79, 0, 0, 0, 152, 0, 0, 0, 183, 0, 0, 0, 244, 0, 0, 0, 174, 0, 0, 0, 62, 0, 0, 0, 159, 0, 0, 0, 142, 0, 0, 0, 53, 0, 0, 0, 96, 0, 0, 0, 164, 0, 0, 0, 51, 0, 0, 0, 117, 0, 0, 0, 164, 0, 0, 0, 4, 0, 0, 0, 147, 0, 0, -0, 177, 0, 0, 0, 107, 0, 0, 0, 77, 0, 0, 0, 151, 0, 0, 0, 157, 0, 0, 0, 168, 0, 0, 0, 205, 0, 0, 0, 151, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 185, 0, 0, 0, 231, 0, 0, 0, 165, 0, 0, 0, 239, 0, 0, 0, 253, 0, 0, 0, 168, 0, 0, 0, 66, 0, 0, 0, 107, 0, 0, 0, 195, 0, 0, 0, 98, 0, 0, 0, 100, 0, 0, 0, 125, 0, 0, 0, 165, 0, 0, 0, 27, 0, 0, 0, 201, 0, 0, 0, 158, 0, 0, 0, 210, 0, 0, 0, 69, 0, 0, 0, 185, 0, 0, 0, 238, 0, 0, 0, 3, 0, 0, 0, 176, 0, 0, 0, 191, 0, 0, 0, 192, 0, 0, 0, 104, 0, 0, 0, 237, 0, 0, 0, 183, -0, 0, 0, 132, 0, 0, 0, 44, 0, 0, 0, 246, 0, 0, 0, 211, 0, 0, 0, 161, 0, 0, 0, 107, 0, 0, 0, 36, 0, 0, 0, 109, 0, 0, 0, 135, 0, 0, 0, 86, 0, 0, 0, 151, 0, 0, 0, 89, 0, 0, 0, 121, 0, 0, 0, 98, 0, 0, 0, 159, 0, 0, 0, 172, 0, 0, 0, 237, 0, 0, 0, 243, 0, 0, 0, 201, 0, 0, 0, 137, 0, 0, 0, 33, 0, 0, 0, 46, 0, 0, 0, 4, 0, 0, 0, 179, 0, 0, 0, 204, 0, 0, 0, 47, 0, 0, 0, 190, 0, 0, 0, 214, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0, 57, 0, 0, 0, 97, 0, 0, 0, 5, 0, 0, 0, 237, 0, 0, 0, 37, 0, 0, 0, 137, 0, 0, 0, 139, -0, 0, 0, 93, 0, 0, 0, 27, 0, 0, 0, 203, 0, 0, 0, 12, 0, 0, 0, 85, 0, 0, 0, 244, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 70, 0, 0, 0, 232, 0, 0, 0, 30, 0, 0, 0, 198, 0, 0, 0, 131, 0, 0, 0, 200, 0, 0, 0, 90, 0, 0, 0, 118, 0, 0, 0, 219, 0, 0, 0, 204, 0, 0, 0, 25, 0, 0, 0, 122, 0, 0, 0, 204, 0, 0, 0, 103, 0, 0, 0, 70, 0, 0, 0, 11, 0, 0, 0, 83, 0, 0, 0, 207, 0, 0, 0, 194, 0, 0, 0, 161, 0, 0, 0, 173, 0, 0, 0, 106, 0, 0, 0, 243, 0, 0, 0, 205, 0, 0, 0, 143, 0, 0, 0, 201, 0, 0, 0, 222, 0, 0, 0, 28, -0, 0, 0, 248, 0, 0, 0, 108, 0, 0, 0, 143, 0, 0, 0, 248, 0, 0, 0, 118, 0, 0, 0, 66, 0, 0, 0, 231, 0, 0, 0, 254, 0, 0, 0, 178, 0, 0, 0, 114, 0, 0, 0, 33, 0, 0, 0, 10, 0, 0, 0, 102, 0, 0, 0, 116, 0, 0, 0, 143, 0, 0, 0, 183, 0, 0, 0, 235, 0, 0, 0, 228, 0, 0, 0, 111, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 140, 0, 0, 0, 107, 0, 0, 0, 190, 0, 0, 0, 252, 0, 0, 0, 77, 0, 0, 0, 112, 0, 0, 0, 98, 0, 0, 0, 110, 0, 0, 0, 82, 0, 0, 0, 119, 0, 0, 0, 153, 0, 0, 0, 136, 0, 0, 0, 126, 0, 0, 0, 123, 0, 0, 0, 87, 0, 0, 0, -122, 0, 0, 0, 13, 0, 0, 0, 254, 0, 0, 0, 220, 0, 0, 0, 114, 0, 0, 0, 146, 0, 0, 0, 241, 0, 0, 0, 104, 0, 0, 0, 29, 0, 0, 0, 151, 0, 0, 0, 215, 0, 0, 0, 124, 0, 0, 0, 141, 0, 0, 0, 83, 0, 0, 0, 16, 0, 0, 0, 55, 0, 0, 0, 83, 0, 0, 0, 136, 0, 0, 0, 119, 0, 0, 0, 2, 0, 0, 0, 202, 0, 0, 0, 39, 0, 0, 0, 168, 0, 0, 0, 229, 0, 0, 0, 69, 0, 0, 0, 226, 0, 0, 0, 168, 0, 0, 0, 72, 0, 0, 0, 42, 0, 0, 0, 171, 0, 0, 0, 24, 0, 0, 0, 202, 0, 0, 0, 234, 0, 0, 0, 45, 0, 0, 0, 42, 0, 0, 0, 84, 0, 0, 0, 23, 0, 0, 0, -55, 0, 0, 0, 50, 0, 0, 0, 9, 0, 0, 0, 220, 0, 0, 0, 224, 0, 0, 0, 74, 0, 0, 0, 183, 0, 0, 0, 125, 0, 0, 0, 130, 0, 0, 0, 16, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 100, 0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 10, 0, 0, 0, 87, 0, 0, 0, 212, 0, -0, 0, 218, 0, 0, 0, 92, 0, 0, 0, 150, 0, 0, 0, 155, 0, 0, 0, 1, 0, 0, 0, 76, 0, 0, 0, 103, 0, 0, 0, 191, 0, 0, 0, 139, 0, 0, 0, 48, 0, 0, 0, 254, 0, 0, 0, 8, 0, 0, 0, 219, 0, 0, 0, 13, 0, 0, 0, 213, 0, 0, 0, 168, 0, 0, 0, 215, 0, 0, 0, 9, 0, 0, 0, 17, 0, 0, 0, 133, 0, 0, 0, 162, 0, 0, 0, 211, 0, 0, 0, 69, 0, 0, 0, 251, 0, 0, 0, 126, 0, 0, 0, 218, 0, 0, 0, 140, 0, 0, 0, 194, 0, 0, 0, 208, 0, 0, 0, 172, 0, 0, 0, 24, 0, 0, 0, 232, 0, 0, 0, 82, 0, 0, 0, 54, 0, 0, 0, 212, 0, 0, 0, 33, 0, 0, 0, 163, 0, -0, 0, 221, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0, 121, 0, 0, 0, 183, 0, 0, 0, 248, 0, 0, 0, 113, 0, 0, 0, 157, 0, 0, 0, 198, 0, 0, 0, 145, 0, 0, 0, 112, 0, 0, 0, 134, 0, 0, 0, 86, 0, 0, 0, 191, 0, 0, 0, 161, 0, 0, 0, 17, 0, 0, 0, 139, 0, 0, 0, 25, 0, 0, 0, 225, 0, 0, 0, 15, 0, 0, 0, 24, 0, 0, 0, 50, 0, 0, 0, 152, 0, 0, 0, 44, 0, 0, 0, 143, 0, 0, 0, 145, 0, 0, 0, 174, 0, 0, 0, 18, 0, 0, 0, 240, 0, 0, 0, 140, 0, 0, 0, 234, 0, 0, 0, 243, 0, 0, 0, 60, 0, 0, 0, 185, 0, 0, 0, 93, 0, 0, 0, 228, 0, 0, 0, 105, -0, 0, 0, 237, 0, 0, 0, 178, 0, 0, 0, 71, 0, 0, 0, 24, 0, 0, 0, 189, 0, 0, 0, 206, 0, 0, 0, 22, 0, 0, 0, 82, 0, 0, 0, 92, 0, 0, 0, 35, 0, 0, 0, 226, 0, 0, 0, 165, 0, 0, 0, 37, 0, 0, 0, 82, 0, 0, 0, 93, 0, 0, 0, 185, 0, 0, 0, 177, 0, 0, 0, 231, 0, 0, 0, 93, 0, 0, 0, 78, 0, 0, 0, 188, 0, 0, 0, 238, 0, 0, 0, 187, 0, 0, 0, 64, 0, 0, 0, 129, 0, 0, 0, 119, 0, 0, 0, 130, 0, 0, 0, 25, 0, 0, 0, 171, 0, 0, 0, 181, 0, 0, 0, 198, 0, 0, 0, 238, 0, 0, 0, 171, 0, 0, 0, 91, 0, 0, 0, 107, 0, 0, 0, 99, 0, 0, 0, 146, -0, 0, 0, 138, 0, 0, 0, 52, 0, 0, 0, 141, 0, 0, 0, 205, 0, 0, 0, 238, 0, 0, 0, 79, 0, 0, 0, 73, 0, 0, 0, 229, 0, 0, 0, 201, 0, 0, 0, 126, 0, 0, 0, 33, 0, 0, 0, 172, 0, 0, 0, 139, 0, 0, 0, 34, 0, 0, 0, 205, 0, 0, 0, 195, 0, 0, 0, 154, 0, 0, 0, 233, 0, 0, 0, 94, 0, 0, 0, 120, 0, 0, 0, 189, 0, 0, 0, 222, 0, 0, 0, 186, 0, 0, 0, 173, 0, 0, 0, 171, 0, 0, 0, 191, 0, 0, 0, 117, 0, 0, 0, 65, 0, 0, 0, 9, 0, 0, 0, 197, 0, 0, 0, 88, 0, 0, 0, 164, 0, 0, 0, 125, 0, 0, 0, 146, 0, 0, 0, 176, 0, 0, 0, 127, 0, 0, 0, -242, 0, 0, 0, 161, 0, 0, 0, 209, 0, 0, 0, 192, 0, 0, 0, 179, 0, 0, 0, 109, 0, 0, 0, 98, 0, 0, 0, 79, 0, 0, 0, 208, 0, 0, 0, 117, 0, 0, 0, 119, 0, 0, 0, 186, 0, 0, 0, 118, 0, 0, 0, 119, 0, 0, 0, 215, 0, 0, 0, 184, 0, 0, 0, 216, 0, 0, 0, 146, 0, 0, 0, 111, 0, 0, 0, 152, 0, 0, 0, 52, 0, 0, 0, 61, 0, 0, 0, 214, 0, 0, 0, 78, 0, 0, 0, 28, 0, 0, 0, 15, 0, 0, 0, 240, 0, 0, 0, 143, 0, 0, 0, 46, 0, 0, 0, 241, 0, 0, 0, 179, 0, 0, 0, 189, 0, 0, 0, 177, 0, 0, 0, 185, 0, 0, 0, 236, 0, 0, 0, 153, 0, 0, 0, 180, -0, 0, 0, 7, 0, 0, 0, 96, 0, 0, 0, 87, 0, 0, 0, 46, 0, 0, 0, 154, 0, 0, 0, 114, 0, 0, 0, 29, 0, 0, 0, 107, 0, 0, 0, 110, 0, 0, 0, 88, 0, 0, 0, 51, 0, 0, 0, 36, 0, 0, 0, 140, 0, 0, 0, 72, 0, 0, 0, 57, 0, 0, 0, 70, 0, 0, 0, 142, 0, 0, 0, 137, 0, 0, 0, 106, 0, 0, 0, 136, 0, 0, 0, 81, 0, 0, 0, 35, 0, 0, 0, 98, 0, 0, 0, 181, 0, 0, 0, 50, 0, 0, 0, 9, 0, 0, 0, 54, 0, 0, 0, 227, 0, 0, 0, 87, 0, 0, 0, 245, 0, 0, 0, 152, 0, 0, 0, 222, 0, 0, 0, 111, 0, 0, 0, 139, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, -74, 0, 0, 0, 249, 0, 0, 0, 91, 0, 0, 0, 135, 0, 0, 0, 105, 0, 0, 0, 82, 0, 0, 0, 229, 0, 0, 0, 91, 0, 0, 0, 209, 0, 0, 0, 177, 0, 0, 0, 229, 0, 0, 0, 37, 0, 0, 0, 37, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 194, 0, 0, 0, 19, 0, 0, 0, 68, 0, 0, 0, 232, 0, 0, 0, 185, 0, 0, 0, 10, 0, 0, 0, 112, 0, 0, 0, 173, 0, 0, 0, 189, 0, 0, 0, 15, 0, 0, 0, 81, 0, 0, 0, 148, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, 220, 0, 0, 0, 171, 0, 0, 0, 169, 0, 0, 0, 37, 0, 0, 0, 45, 0, 0, 0, 172, 0, 0, 0, 95, 0, 0, 0, 3, 0, 0, 0, 51, 0, 0, 0, 8, 0, 0, 0, 231, 0, 0, 0, 126, 0, 0, 0, 254, 0, 0, 0, 149, 0, 0, 0, 54, 0, 0, 0, 60, 0, 0, 0, 91, 0, 0, 0, 58, 0, 0, 0, 211, 0, 0, 0, 5, 0, 0, 0, 130, 0, 0, 0, 28, 0, 0, 0, 149, 0, 0, 0, 45, 0, 0, 0, 216, 0, 0, 0, 119, 0, -0, 0, 126, 0, 0, 0, 2, 0, 0, 0, 217, 0, 0, 0, 91, 0, 0, 0, 112, 0, 0, 0, 194, 0, 0, 0, 254, 0, 0, 0, 27, 0, 0, 0, 12, 0, 0, 0, 103, 0, 0, 0, 205, 0, 0, 0, 214, 0, 0, 0, 224, 0, 0, 0, 81, 0, 0, 0, 142, 0, 0, 0, 44, 0, 0, 0, 224, 0, 0, 0, 121, 0, 0, 0, 136, 0, 0, 0, 240, 0, 0, 0, 207, 0, 0, 0, 65, 0, 0, 0, 74, 0, 0, 0, 173, 0, 0, 0, 35, 0, 0, 0, 212, 0, 0, 0, 70, 0, 0, 0, 202, 0, 0, 0, 148, 0, 0, 0, 161, 0, 0, 0, 195, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 6, 0, 0, 0, 250, 0, 0, 0, 23, 0, 0, 0, 20, 0, -0, 0, 123, 0, 0, 0, 170, 0, 0, 0, 112, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0, 251, 0, 0, 0, 245, 0, 0, 0, 191, 0, 0, 0, 128, 0, 0, 0, 197, 0, 0, 0, 207, 0, 0, 0, 8, 0, 0, 0, 122, 0, 0, 0, 221, 0, 0, 0, 161, 0, 0, 0, 244, 0, 0, 0, 157, 0, 0, 0, 84, 0, 0, 0, 80, 0, 0, 0, 83, 0, 0, 0, 35, 0, 0, 0, 119, 0, 0, 0, 35, 0, 0, 0, 245, 0, 0, 0, 52, 0, 0, 0, 165, 0, 0, 0, 34, 0, 0, 0, 209, 0, 0, 0, 13, 0, 0, 0, 150, 0, 0, 0, 46, 0, 0, 0, 71, 0, 0, 0, 204, 0, 0, 0, 183, 0, 0, 0, 50, 0, 0, 0, 137, 0, 0, 0, 87, 0, -0, 0, 208, 0, 0, 0, 152, 0, 0, 0, 117, 0, 0, 0, 228, 0, 0, 0, 55, 0, 0, 0, 153, 0, 0, 0, 169, 0, 0, 0, 232, 0, 0, 0, 186, 0, 0, 0, 237, 0, 0, 0, 186, 0, 0, 0, 235, 0, 0, 0, 199, 0, 0, 0, 79, 0, 0, 0, 21, 0, 0, 0, 118, 0, 0, 0, 7, 0, 0, 0, 12, 0, 0, 0, 76, 0, 0, 0, 239, 0, 0, 0, 159, 0, 0, 0, 82, 0, 0, 0, 252, 0, 0, 0, 4, 0, 0, 0, 93, 0, 0, 0, 88, 0, 0, 0, 16, 0, 0, 0, 206, 0, 0, 0, 130, 0, 0, 0, 240, 0, 0, 0, 143, 0, 0, 0, 121, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 209, 0, 0, 0, 218, 0, 0, 0, 20, 0, -0, 0, 9, 0, 0, 0, 72, 0, 0, 0, 238, 0, 0, 0, 138, 0, 0, 0, 64, 0, 0, 0, 152, 0, 0, 0, 118, 0, 0, 0, 96, 0, 0, 0, 84, 0, 0, 0, 90, 0, 0, 0, 222, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 245, 0, 0, 0, 230, 0, 0, 0, 47, 0, 0, 0, 225, 0, 0, 0, 3, 0, 0, 0, 191, 0, 0, 0, 104, 0, 0, 0, 130, 0, 0, 0, 127, 0, 0, 0, 100, 0, 0, 0, 233, 0, 0, 0, 40, 0, 0, 0, 199, 0, 0, 0, 164, 0, 0, 0, 207, 0, 0, 0, 42, 0, 0, 0, 249, 0, 0, 0, 144, 0, 0, 0, 100, 0, 0, 0, 114, 0, 0, 0, 44, 0, 0, 0, 139, 0, 0, 0, 235, 0, 0, 0, 236, 0, -0, 0, 160, 0, 0, 0, 242, 0, 0, 0, 125, 0, 0, 0, 53, 0, 0, 0, 181, 0, 0, 0, 144, 0, 0, 0, 77, 0, 0, 0, 127, 0, 0, 0, 91, 0, 0, 0, 74, 0, 0, 0, 73, 0, 0, 0, 228, 0, 0, 0, 184, 0, 0, 0, 59, 0, 0, 0, 200, 0, 0, 0, 161, 0, 0, 0, 47, 0, 0, 0, 139, 0, 0, 0, 197, 0, 0, 0, 204, 0, 0, 0, 61, 0, 0, 0, 105, 0, 0, 0, 166, 0, 0, 0, 161, 0, 0, 0, 24, 0, 0, 0, 68, 0, 0, 0, 188, 0, 0, 0, 77, 0, 0, 0, 119, 0, 0, 0, 55, 0, 0, 0, 199, 0, 0, 0, 134, 0, 0, 0, 236, 0, 0, 0, 12, 0, 0, 0, 201, 0, 0, 0, 214, 0, 0, 0, 68, -0, 0, 0, 169, 0, 0, 0, 35, 0, 0, 0, 39, 0, 0, 0, 185, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 167, 0, 0, 0, 10, 0, 0, 0, 213, 0, 0, 0, 199, 0, 0, 0, 52, 0, 0, 0, 55, 0, 0, 0, 249, 0, 0, 0, 126, 0, 0, 0, 62, 0, 0, 0, 102, 0, 0, 0, 238, 0, 0, 0, 249, 0, 0, 0, 153, 0, 0, 0, 40, 0, 0, 0, 255, 0, 0, 0, 173, 0, 0, 0, 17, 0, 0, 0, 216, 0, 0, 0, 226, 0, 0, 0, 102, 0, 0, 0, 197, 0, 0, 0, 205, 0, 0, 0, 15, 0, 0, 0, 13, 0, 0, 0, 11, 0, 0, 0, 106, 0, 0, 0, 252, 0, 0, 0, 124, 0, 0, 0, 36, 0, 0, 0, 168, 0, 0, 0, 79, -0, 0, 0, 168, 0, 0, 0, 94, 0, 0, 0, 128, 0, 0, 0, 69, 0, 0, 0, 139, 0, 0, 0, 108, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 0, 0, 0, 30, 0, 0, 0, 236, 0, 0, 0, 247, 0, 0, 0, 141, 0, 0, 0, 119, 0, 0, 0, 242, 0, 0, 0, 234, 0, 0, 0, 219, 0, 0, 0, 96, 0, -0, 0, 3, 0, 0, 0, 33, 0, 0, 0, 192, 0, 0, 0, 255, 0, 0, 0, 94, 0, 0, 0, 103, 0, 0, 0, 195, 0, 0, 0, 113, 0, 0, 0, 11, 0, 0, 0, 33, 0, 0, 0, 180, 0, 0, 0, 65, 0, 0, 0, 160, 0, 0, 0, 104, 0, 0, 0, 56, 0, 0, 0, 198, 0, 0, 0, 1, 0, 0, 0, 163, 0, 0, 0, 211, 0, 0, 0, 81, 0, 0, 0, 60, 0, 0, 0, 60, 0, 0, 0, 146, 0, 0, 0, 248, 0, 0, 0, 214, 0, 0, 0, 75, 0, 0, 0, 239, 0, 0, 0, 66, 0, 0, 0, 19, 0, 0, 0, 178, 0, 0, 0, 74, 0, 0, 0, 196, 0, 0, 0, 46, 0, 0, 0, 114, 0, 0, 0, 63, 0, 0, 0, 201, 0, 0, 0, 17, 0, 0, -0, 189, 0, 0, 0, 116, 0, 0, 0, 2, 0, 0, 0, 14, 0, 0, 0, 245, 0, 0, 0, 19, 0, 0, 0, 157, 0, 0, 0, 131, 0, 0, 0, 26, 0, 0, 0, 27, 0, 0, 0, 213, 0, 0, 0, 84, 0, 0, 0, 222, 0, 0, 0, 196, 0, 0, 0, 30, 0, 0, 0, 22, 0, 0, 0, 108, 0, 0, 0, 39, 0, 0, 0, 82, 0, 0, 0, 228, 0, 0, 0, 99, 0, 0, 0, 170, 0, 0, 0, 148, 0, 0, 0, 230, 0, 0, 0, 195, 0, 0, 0, 40, 0, 0, 0, 156, 0, 0, 0, 198, 0, 0, 0, 86, 0, 0, 0, 172, 0, 0, 0, 250, 0, 0, 0, 182, 0, 0, 0, 189, 0, 0, 0, 226, 0, 0, 0, 204, 0, 0, 0, 118, 0, 0, 0, 198, 0, -0, 0, 39, 0, 0, 0, 39, 0, 0, 0, 162, 0, 0, 0, 142, 0, 0, 0, 120, 0, 0, 0, 43, 0, 0, 0, 132, 0, 0, 0, 114, 0, 0, 0, 16, 0, 0, 0, 189, 0, 0, 0, 78, 0, 0, 0, 42, 0, 0, 0, 234, 0, 0, 0, 167, 0, 0, 0, 35, 0, 0, 0, 239, 0, 0, 0, 4, 0, 0, 0, 97, 0, 0, 0, 128, 0, 0, 0, 80, 0, 0, 0, 201, 0, 0, 0, 110, 0, 0, 0, 165, 0, 0, 0, 150, 0, 0, 0, 209, 0, 0, 0, 209, 0, 0, 0, 200, 0, 0, 0, 195, 0, 0, 0, 24, 0, 0, 0, 215, 0, 0, 0, 45, 0, 0, 0, 253, 0, 0, 0, 38, 0, 0, 0, 189, 0, 0, 0, 203, 0, 0, 0, 123, 0, 0, 0, 146, -0, 0, 0, 81, 0, 0, 0, 14, 0, 0, 0, 74, 0, 0, 0, 101, 0, 0, 0, 87, 0, 0, 0, 184, 0, 0, 0, 73, 0, 0, 0, 171, 0, 0, 0, 85, 0, 0, 0, 54, 0, 0, 0, 195, 0, 0, 0, 236, 0, 0, 0, 99, 0, 0, 0, 85, 0, 0, 0, 17, 0, 0, 0, 85, 0, 0, 0, 246, 0, 0, 0, 165, 0, 0, 0, 199, 0, 0, 0, 1, 0, 0, 0, 95, 0, 0, 0, 254, 0, 0, 0, 121, 0, 0, 0, 216, 0, 0, 0, 10, 0, 0, 0, 247, 0, 0, 0, 3, 0, 0, 0, 216, 0, 0, 0, 152, 0, 0, 0, 153, 0, 0, 0, 245, 0, 0, 0, 208, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 107, 0, 0, 0, 102, 0, 0, 0, 40, 0, 0, -0, 245, 0, 0, 0, 37, 0, 0, 0, 122, 0, 0, 0, 141, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 112, 0, 0, 0, 93, 0, 0, 0, 81, 0, 0, 0, 39, 0, 0, 0, 238, 0, 0, 0, 48, 0, 0, 0, 101, 0, 0, 0, 86, 0, 0, 0, 149, 0, 0, 0, 70, 0, 0, 0, 222, 0, 0, 0, 189, 0, 0, 0, 3, 0, 0, 0, 117, 0, 0, 0, 180, 0, 0, 0, 87, 0, 0, 0, 89, 0, 0, 0, 137, 0, 0, 0, 235, 0, 0, 0, 2, 0, 0, 0, 158, 0, 0, 0, 204, 0, 0, 0, 137, 0, 0, 0, 25, 0, 0, 0, 167, 0, 0, 0, 203, 0, 0, 0, 23, 0, 0, 0, 103, 0, 0, 0, 106, 0, 0, 0, 235, 0, 0, 0, 252, 0, 0, -0, 154, 0, 0, 0, 154, 0, 0, 0, 16, 0, 0, 0, 206, 0, 0, 0, 219, 0, 0, 0, 58, 0, 0, 0, 28, 0, 0, 0, 60, 0, 0, 0, 106, 0, 0, 0, 157, 0, 0, 0, 234, 0, 0, 0, 70, 0, 0, 0, 188, 0, 0, 0, 69, 0, 0, 0, 73, 0, 0, 0, 172, 0, 0, 0, 227, 0, 0, 0, 65, 0, 0, 0, 18, 0, 0, 0, 124, 0, 0, 0, 240, 0, 0, 0, 247, 0, 0, 0, 79, 0, 0, 0, 249, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 44, 0, 0, 0, 137, 0, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 84, 0, 0, 0, 26, 0, 0, 0, 70, 0, 0, 0, 202, 0, 0, 0, 230, 0, 0, 0, 198, 0, 0, 0, -203, 0, 0, 0, 226, 0, 0, 0, 195, 0, 0, 0, 193, 0, 0, 0, 139, 0, 0, 0, 117, 0, 0, 0, 129, 0, 0, 0, 190, 0, 0, 0, 238, 0, 0, 0, 248, 0, 0, 0, 163, 0, 0, 0, 17, 0, 0, 0, 28, 0, 0, 0, 37, 0, 0, 0, 163, 0, 0, 0, 167, 0, 0, 0, 53, 0, 0, 0, 81, 0, 0, 0, 85, 0, 0, 0, 226, 0, 0, 0, 37, 0, 0, 0, 170, 0, 0, 0, 226, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 72, 0, 0, 0, 16, 0, 0, 0, 159, 0, 0, 0, 138, 0, 0, 0, 9, 0, 0, 0, 118, 0, 0, 0, 250, 0, 0, 0, 240, 0, 0, 0, 122, 0, 0, 0, 176, 0, 0, 0, 112, 0, 0, 0, 247, 0, 0, 0, 131, 0, 0, 0, 128, 0, 0, 0, 82, 0, 0, 0, 132, 0, 0, 0, 43, 0, 0, 0, 38, 0, 0, 0, 162, 0, 0, 0, 196, 0, 0, 0, 93, 0, 0, 0, 79, 0, 0, 0, 186, 0, 0, 0, 177, 0, 0, 0, 200, 0, 0, 0, 64, 0, 0, 0, 13, 0, 0, 0, 120, 0, 0, 0, 151, 0, 0, 0, -196, 0, 0, 0, 96, 0, 0, 0, 212, 0, 0, 0, 177, 0, 0, 0, 108, 0, 0, 0, 8, 0, 0, 0, 199, 0, 0, 0, 64, 0, 0, 0, 56, 0, 0, 0, 115, 0, 0, 0, 95, 0, 0, 0, 11, 0, 0, 0, 243, 0, 0, 0, 118, 0, 0, 0, 93, 0, 0, 0, 178, 0, 0, 0, 165, 0, 0, 0, 47, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 7, 0, 0, 0, 237, 0, 0, 0, 8, 0, 0, 0, 162, 0, 0, 0, 108, 0, 0, 0, 79, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 181, 0, 0, 0, 14, 0, 0, 0, 238, 0, 0, 0, 68, 0, 0, 0, 250, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 166, 0, 0, -0, 4, 0, 0, 0, 25, 0, 0, 0, 86, 0, 0, 0, 101, 0, 0, 0, 49, 0, 0, 0, 127, 0, 0, 0, 139, 0, 0, 0, 235, 0, 0, 0, 13, 0, 0, 0, 225, 0, 0, 0, 71, 0, 0, 0, 137, 0, 0, 0, 151, 0, 0, 0, 22, 0, 0, 0, 83, 0, 0, 0, 250, 0, 0, 0, 129, 0, 0, 0, 167, 0, 0, 0, 170, 0, 0, 0, 178, 0, 0, 0, 191, 0, 0, 0, 103, 0, 0, 0, 235, 0, 0, 0, 114, 0, 0, 0, 96, 0, 0, 0, 129, 0, 0, 0, 13, 0, 0, 0, 72, 0, 0, 0, 126, 0, 0, 0, 19, 0, 0, 0, 51, 0, 0, 0, 205, 0, 0, 0, 168, 0, 0, 0, 132, 0, 0, 0, 86, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, -0, 175, 0, 0, 0, 107, 0, 0, 0, 67, 0, 0, 0, 172, 0, 0, 0, 23, 0, 0, 0, 175, 0, 0, 0, 22, 0, 0, 0, 192, 0, 0, 0, 82, 0, 0, 0, 153, 0, 0, 0, 73, 0, 0, 0, 91, 0, 0, 0, 135, 0, 0, 0, 115, 0, 0, 0, 126, 0, 0, 0, 181, 0, 0, 0, 67, 0, 0, 0, 218, 0, 0, 0, 107, 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, 0, 45, 0, 0, 0, 85, 0, 0, 0, 233, 0, 0, 0, 88, 0, 0, 0, 31, 0, 0, 0, 255, 0, 0, 0, 132, 0, 0, 0, 63, 0, 0, 0, 147, 0, 0, 0, 28, 0, 0, 0, 203, 0, 0, 0, 225, 0, 0, 0, 48, 0, 0, 0, 105, 0, 0, 0, 165, 0, 0, 0, 117, 0, 0, -0, 25, 0, 0, 0, 126, 0, 0, 0, 20, 0, 0, 0, 95, 0, 0, 0, 248, 0, 0, 0, 252, 0, 0, 0, 9, 0, 0, 0, 221, 0, 0, 0, 168, 0, 0, 0, 120, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 89, 0, 0, 0, 139, 0, 0, 0, 209, 0, 0, 0, 48, 0, 0, 0, 1, 0, 0, 0, 19, 0, 0, 0, 255, 0, 0, 0, 118, 0, 0, 0, 3, 0, 0, 0, 197, 0, 0, 0, 75, 0, 0, 0, 137, 0, 0, 0, 153, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 112, 0, 0, 0, 156, 0, 0, 0, 213, 0, 0, 0, 217, 0, 0, 0, 17, 0, 0, 0, 137, 0, 0, 0, 90, 0, 0, 0, 70, 0, 0, 0, 254, 0, 0, 0, -239, 0, 0, 0, 220, 0, 0, 0, 217, 0, 0, 0, 85, 0, 0, 0, 43, 0, 0, 0, 69, 0, 0, 0, 167, 0, 0, 0, 176, 0, 0, 0, 45, 0, 0, 0, 251, 0, 0, 0, 36, 0, 0, 0, 194, 0, 0, 0, 41, 0, 0, 0, 56, 0, 0, 0, 6, 0, 0, 0, 248, 0, 0, 0, 11, 0, 0, 0, 172, 0, 0, 0, 130, 0, 0, 0, 196, 0, 0, 0, 151, 0, 0, 0, 43, 0, 0, 0, 144, 0, 0, 0, 224, 0, 0, 0, 247, 0, 0, 0, 168, 0, 0, 0, 171, 0, 0, 0, 108, 0, 0, 0, 8, 0, 0, 0, 128, 0, 0, 0, 102, 0, 0, 0, 144, 0, 0, 0, 70, 0, 0, 0, 247, 0, 0, 0, 38, 0, 0, 0, 45, 0, 0, 0, 248, 0, 0, 0, -241, 0, 0, 0, 196, 0, 0, 0, 107, 0, 0, 0, 74, 0, 0, 0, 130, 0, 0, 0, 152, 0, 0, 0, 142, 0, 0, 0, 55, 0, 0, 0, 142, 0, 0, 0, 180, 0, 0, 0, 238, 0, 0, 0, 184, 0, 0, 0, 212, 0, 0, 0, 63, 0, 0, 0, 178, 0, 0, 0, 27, 0, 0, 0, 224, 0, 0, 0, 10, 0, 0, 0, 61, 0, 0, 0, 117, 0, 0, 0, 52, 0, 0, 0, 40, 0, 0, 0, 162, 0, 0, 0, 142, 0, 0, 0, 196, 0, 0, 0, 146, 0, 0, 0, 123, 0, 0, 0, 254, 0, 0, 0, 96, 0, 0, 0, 110, 0, 0, 0, 109, 0, 0, 0, 184, 0, 0, 0, 49, 0, 0, 0, 29, 0, 0, 0, 98, 0, 0, 0, 13, 0, 0, 0, 120, 0, 0, -0, 20, 0, 0, 0, 66, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, 168, 0, 0, 0, 216, 0, 0, 0, 4, 0, 0, 0, 155, 0, 0, 0, 115, 0, 0, 0, 201, 0, 0, 0, 201, 0, 0, 0, 220, 0, 0, 0, 13, 0, 0, 0, 115, 0, 0, 0, 191, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 115, -0, 0, 0, 255, 0, 0, 0, 24, 0, 0, 0, 31, 0, 0, 0, 156, 0, 0, 0, 81, 0, 0, 0, 170, 0, 0, 0, 198, 0, 0, 0, 241, 0, 0, 0, 131, 0, 0, 0, 37, 0, 0, 0, 253, 0, 0, 0, 171, 0, 0, 0, 163, 0, 0, 0, 17, 0, 0, 0, 211, 0, 0, 0, 1, 0, 0, 0, 36, 0, 0, 0, 77, 0, 0, 0, 227, 0, 0, 0, 126, 0, 0, 0, 56, 0, 0, 0, 98, 0, 0, 0, 94, 0, 0, 0, 100, 0, 0, 0, 187, 0, 0, 0, 43, 0, 0, 0, 83, 0, 0, 0, 181, 0, 0, 0, 3, 0, 0, 0, 104, 0, 0, 0, 196, 0, 0, 0, 242, 0, 0, 0, 43, 0, 0, 0, 90, 0, 0, 0, 3, 0, 0, 0, 50, 0, 0, 0, 153, 0, 0, -0, 74, 0, 0, 0, 65, 0, 0, 0, 154, 0, 0, 0, 225, 0, 0, 0, 26, 0, 0, 0, 174, 0, 0, 0, 140, 0, 0, 0, 72, 0, 0, 0, 243, 0, 0, 0, 36, 0, 0, 0, 50, 0, 0, 0, 101, 0, 0, 0, 232, 0, 0, 0, 221, 0, 0, 0, 173, 0, 0, 0, 58, 0, 0, 0, 140, 0, 0, 0, 234, 0, 0, 0, 244, 0, 0, 0, 179, 0, 0, 0, 178, 0, 0, 0, 229, 0, 0, 0, 115, 0, 0, 0, 242, 0, 0, 0, 237, 0, 0, 0, 139, 0, 0, 0, 191, 0, 0, 0, 237, 0, 0, 0, 177, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 251, 0, 0, 0, 43, 0, 0, 0, 241, 0, 0, 0, 1, 0, 0, 0, 72, 0, 0, 0, 232, 0, -0, 0, 38, 0, 0, 0, 3, 0, 0, 0, 142, 0, 0, 0, 39, 0, 0, 0, 77, 0, 0, 0, 150, 0, 0, 0, 114, 0, 0, 0, 200, 0, 0, 0, 9, 0, 0, 0, 59, 0, 0, 0, 96, 0, 0, 0, 201, 0, 0, 0, 38, 0, 0, 0, 77, 0, 0, 0, 124, 0, 0, 0, 242, 0, 0, 0, 156, 0, 0, 0, 212, 0, 0, 0, 161, 0, 0, 0, 59, 0, 0, 0, 38, 0, 0, 0, 194, 0, 0, 0, 4, 0, 0, 0, 51, 0, 0, 0, 68, 0, 0, 0, 118, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0, 0, 187, 0, 0, 0, 17, 0, 0, 0, 66, 0, 0, 0, 12, 0, 0, 0, 34, 0, 0, 0, 183, 0, 0, 0, 198, 0, 0, 0, 225, 0, 0, 0, 172, 0, 0, 0, 180, -0, 0, 0, 14, 0, 0, 0, 111, 0, 0, 0, 133, 0, 0, 0, 231, 0, 0, 0, 239, 0, 0, 0, 222, 0, 0, 0, 103, 0, 0, 0, 48, 0, 0, 0, 252, 0, 0, 0, 191, 0, 0, 0, 90, 0, 0, 0, 224, 0, 0, 0, 123, 0, 0, 0, 122, 0, 0, 0, 42, 0, 0, 0, 84, 0, 0, 0, 107, 0, 0, 0, 93, 0, 0, 0, 98, 0, 0, 0, 133, 0, 0, 0, 161, 0, 0, 0, 248, 0, 0, 0, 22, 0, 0, 0, 136, 0, 0, 0, 236, 0, 0, 0, 97, 0, 0, 0, 185, 0, 0, 0, 150, 0, 0, 0, 181, 0, 0, 0, 239, 0, 0, 0, 45, 0, 0, 0, 67, 0, 0, 0, 77, 0, 0, 0, 124, 0, 0, 0, 49, 0, 0, 0, 51, 0, 0, 0, 204, -0, 0, 0, 228, 0, 0, 0, 207, 0, 0, 0, 108, 0, 0, 0, 255, 0, 0, 0, 128, 0, 0, 0, 71, 0, 0, 0, 119, 0, 0, 0, 209, 0, 0, 0, 216, 0, 0, 0, 233, 0, 0, 0, 105, 0, 0, 0, 151, 0, 0, 0, 152, 0, 0, 0, 127, 0, 0, 0, 32, 0, 0, 0, 87, 0, 0, 0, 29, 0, 0, 0, 29, 0, 0, 0, 79, 0, 0, 0, 8, 0, 0, 0, 39, 0, 0, 0, 200, 0, 0, 0, 53, 0, 0, 0, 87, 0, 0, 0, 64, 0, 0, 0, 198, 0, 0, 0, 33, 0, 0, 0, 12, 0, 0, 0, 210, 0, 0, 0, 142, 0, 0, 0, 155, 0, 0, 0, 250, 0, 0, 0, 66, 0, 0, 0, 142, 0, 0, 0, 223, 0, 0, 0, 143, 0, 0, 0, 199, -0, 0, 0, 134, 0, 0, 0, 249, 0, 0, 0, 164, 0, 0, 0, 202, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, 33, 0, 0, 0, 191, 0, 0, 0, 236, 0, 0, 0, 87, 0, 0, 0, 98, 0, 0, 0, 48, 0, 0, 0, 88, 0, 0, 0, 140, 0, 0, 0, 13, 0, 0, 0, 53, 0, 0, 0, 219, 0, 0, 0, 93, 0, 0, 0, 139, 0, 0, 0, 106, 0, 0, 0, 160, 0, 0, 0, 90, 0, 0, 0, 193, 0, 0, 0, 88, 0, 0, 0, 124, 0, 0, 0, 13, 0, 0, 0, 32, 0, 0, 0, 221, 0, 0, 0, 17, 0, 0, 0, 38, 0, 0, 0, 95, 0, 0, 0, 137, 0, 0, 0, 59, 0, 0, 0, 151, 0, 0, 0, 88, 0, 0, 0, 248, 0, -0, 0, 139, 0, 0, 0, 227, 0, 0, 0, 223, 0, 0, 0, 50, 0, 0, 0, 226, 0, 0, 0, 252, 0, 0, 0, 216, 0, 0, 0, 103, 0, 0, 0, 242, 0, 0, 0, 165, 0, 0, 0, 55, 0, 0, 0, 30, 0, 0, 0, 109, 0, 0, 0, 236, 0, 0, 0, 124, 0, 0, 0, 39, 0, 0, 0, 32, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 233, 0, 0, 0, 192, 0, 0, 0, 250, 0, 0, 0, 149, 0, 0, 0, 69, 0, 0, 0, 35, 0, 0, 0, 150, 0, 0, 0, 241, 0, 0, 0, 44, 0, 0, 0, 121, 0, 0, 0, 37, 0, 0, 0, 20, 0, 0, 0, 206, 0, 0, 0, 64, 0, 0, 0, 20, 0, 0, 0, 68, 0, 0, 0, 44, 0, 0, 0, 54, 0, 0, 0, 80, 0, 0, 0, 217, 0, 0, 0, 99, 0, 0, 0, 86, 0, 0, 0, 183, 0, 0, 0, 86, 0, 0, 0, 59, 0, 0, 0, 158, 0, 0, 0, 167, 0, 0, 0, 239, 0, 0, 0, 137, 0, 0, 0, 187, 0, 0, 0, 14, 0, 0, 0, 206, 0, 0, 0, 127, 0, 0, 0, 220, 0, 0, 0, 10, 0, 0, -0, 204, 0, 0, 0, 130, 0, 0, 0, 28, 0, 0, 0, 10, 0, 0, 0, 120, 0, 0, 0, 113, 0, 0, 0, 232, 0, 0, 0, 116, 0, 0, 0, 141, 0, 0, 0, 1, 0, 0, 0, 48, 0, 0, 0, 15, 0, 0, 0, 167, 0, 0, 0, 17, 0, 0, 0, 76, 0, 0, 0, 223, 0, 0, 0, 56, 0, 0, 0, 215, 0, 0, 0, 167, 0, 0, 0, 13, 0, 0, 0, 248, 0, 0, 0, 72, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 123, 0, 0, 0, 95, 0, 0, 0, 14, 0, 0, 0, 37, 0, 0, 0, 131, 0, 0, 0, 230, 0, 0, 0, 148, 0, 0, 0, 123, 0, 0, 0, 129, 0, 0, 0, 178, 0, 0, 0, 145, 0, 0, 0, 174, 0, 0, -0, 14, 0, 0, 0, 5, 0, 0, 0, 201, 0, 0, 0, 163, 0, 0, 0, 104, 0, 0, 0, 45, 0, 0, 0, 217, 0, 0, 0, 136, 0, 0, 0, 37, 0, 0, 0, 25, 0, 0, 0, 42, 0, 0, 0, 97, 0, 0, 0, 97, 0, 0, 0, 33, 0, 0, 0, 151, 0, 0, 0, 21, 0, 0, 0, 161, 0, 0, 0, 53, 0, 0, 0, 165, 0, 0, 0, 70, 0, 0, 0, 200, 0, 0, 0, 162, 0, 0, 0, 14, 0, 0, 0, 27, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 0, 139, 0, 0, 0, 90, 0, 0, 0, 27, 0, 0, 0, 151, 0, 0, 0, 75, 0, 0, 0, 242, 0, 0, 0, 22, 0, 0, 0, 49, 0, 0, 0, 61, 0, 0, 0, 31, 0, 0, 0, 51, 0, 0, 0, 160, 0, -0, 0, 80, 0, 0, 0, 58, 0, 0, 0, 24, 0, 0, 0, 190, 0, 0, 0, 19, 0, 0, 0, 161, 0, 0, 0, 118, 0, 0, 0, 193, 0, 0, 0, 186, 0, 0, 0, 27, 0, 0, 0, 241, 0, 0, 0, 5, 0, 0, 0, 123, 0, 0, 0, 51, 0, 0, 0, 168, 0, 0, 0, 130, 0, 0, 0, 59, 0, 0, 0, 186, 0, 0, 0, 54, 0, 0, 0, 123, 0, 0, 0, 109, 0, 0, 0, 169, 0, 0, 0, 234, 0, 0, 0, 20, 0, 0, 0, 18, 0, 0, 0, 197, 0, 0, 0, 250, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 155, 0, 0, 0, 153, 0, 0, 0, 204, 0, 0, 0, 86, 0, 0, 0, 2, 0, 0, 0, 233, 0, 0, 0, 160, 0, -0, 0, 38, 0, 0, 0, 64, 0, 0, 0, 102, 0, 0, 0, 140, 0, 0, 0, 196, 0, 0, 0, 248, 0, 0, 0, 133, 0, 0, 0, 51, 0, 0, 0, 104, 0, 0, 0, 231, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0, 80, 0, 0, 0, 91, 0, 0, 0, 255, 0, 0, 0, 169, 0, 0, 0, 178, 0, 0, 0, 241, 0, 0, 0, 241, 0, 0, 0, 120, 0, 0, 0, 207, 0, 0, 0, 20, 0, 0, 0, 164, 0, 0, 0, 169, 0, 0, 0, 252, 0, 0, 0, 9, 0, 0, 0, 70, 0, 0, 0, 148, 0, 0, 0, 84, 0, 0, 0, 101, 0, 0, 0, 13, 0, 0, 0, 156, 0, 0, 0, 95, 0, 0, 0, 114, 0, 0, 0, 33, 0, 0, 0, 226, 0, 0, 0, 151, 0, -0, 0, 165, 0, 0, 0, 45, 0, 0, 0, 129, 0, 0, 0, 206, 0, 0, 0, 74, 0, 0, 0, 95, 0, 0, 0, 121, 0, 0, 0, 61, 0, 0, 0, 95, 0, 0, 0, 92, 0, 0, 0, 210, 0, 0, 0, 188, 0, 0, 0, 125, 0, 0, 0, 119, 0, 0, 0, 14, 0, 0, 0, 42, 0, 0, 0, 109, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0, 132, 0, 0, 0, 6, 0, 0, 0, 196, 0, 0, 0, 221, 0, 0, 0, 198, 0, 0, 0, 166, 0, 0, 0, 198, 0, 0, 0, 215, 0, 0, 0, 73, 0, 0, 0, 173, 0, 0, 0, 109, 0, 0, 0, 135, 0, 0, 0, 145, 0, 0, 0, 14, 0, 0, 0, 58, 0, 0, 0, 103, 0, 0, 0, 29, 0, 0, 0, 44, 0, -0, 0, 29, 0, 0, 0, 86, 0, 0, 0, 254, 0, 0, 0, 122, 0, 0, 0, 116, 0, 0, 0, 207, 0, 0, 0, 212, 0, 0, 0, 210, 0, 0, 0, 229, 0, 0, 0, 25, 0, 0, 0, 222, 0, 0, 0, 208, 0, 0, 0, 219, 0, 0, 0, 112, 0, 0, 0, 35, 0, 0, 0, 105, 0, 0, 0, 230, 0, 0, 0, 109, 0, 0, 0, 236, 0, 0, 0, 236, 0, 0, 0, 204, 0, 0, 0, 9, 0, 0, 0, 51, 0, 0, 0, 106, 0, 0, 0, 119, 0, 0, 0, 220, 0, 0, 0, 107, 0, 0, 0, 34, 0, 0, 0, 118, 0, 0, 0, 93, 0, 0, 0, 146, 0, 0, 0, 9, 0, 0, 0, 172, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 0, 23, 0, 0, 0, 235, 0, 0, 0, 211, 0, 0, 0, 219, 0, 0, 0, 18, 0, 0, 0, 94, 0, 0, 0, 1, 0, 0, 0, 240, 0, 0, 0, 145, 0, 0, 0, 171, 0, 0, 0, 44, 0, 0, 0, 65, 0, 0, 0, 206, 0, 0, 0, 172, 0, 0, 0, 237, 0, 0, 0, 27, 0, 0, 0, 75, 0, 0, 0, 45, 0, 0, 0, -188, 0, 0, 0, 219, 0, 0, 0, 23, 0, 0, 0, 102, 0, 0, 0, 137, 0, 0, 0, 70, 0, 0, 0, 173, 0, 0, 0, 75, 0, 0, 0, 30, 0, 0, 0, 111, 0, 0, 0, 11, 0, 0, 0, 20, 0, 0, 0, 17, 0, 0, 0, 206, 0, 0, 0, 191, 0, 0, 0, 182, 0, 0, 0, 119, 0, 0, 0, 45, 0, 0, 0, 72, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 79, 0, 0, 0, 163, 0, 0, 0, 93, 0, 0, 0, 74, 0, 0, 0, 176, 0, 0, 0, 112, 0, 0, 0, 18, 0, 0, 0, 62, 0, 0, 0, 84, 0, 0, 0, 215, 0, 0, 0, 216, 0, 0, 0, 14, 0, 0, 0, 43, 0, 0, 0, 39, 0, 0, 0, 220, 0, 0, 0, 83, 0, 0, 0, 255, -0, 0, 0, 202, 0, 0, 0, 140, 0, 0, 0, 89, 0, 0, 0, 179, 0, 0, 0, 78, 0, 0, 0, 68, 0, 0, 0, 7, 0, 0, 0, 118, 0, 0, 0, 97, 0, 0, 0, 15, 0, 0, 0, 102, 0, 0, 0, 178, 0, 0, 0, 33, 0, 0, 0, 57, 0, 0, 0, 126, 0, 0, 0, 192, 0, 0, 0, 236, 0, 0, 0, 69, 0, 0, 0, 40, 0, 0, 0, 130, 0, 0, 0, 161, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 68, 0, 0, 0, 53, 0, 0, 0, 19, 0, 0, 0]).concat([94, 0, 0, 0, 97, 0, 0, 0, 94, 0, 0, 0, 84, 0, 0, 0, 203, 0, 0, 0, 124, 0, 0, 0, 239, 0, 0, 0, 246, 0, 0, 0, 65, 0, 0, 0, 207, 0, 0, 0, -159, 0, 0, 0, 10, 0, 0, 0, 221, 0, 0, 0, 249, 0, 0, 0, 218, 0, 0, 0, 132, 0, 0, 0, 195, 0, 0, 0, 230, 0, 0, 0, 138, 0, 0, 0, 159, 0, 0, 0, 36, 0, 0, 0, 210, 0, 0, 0, 150, 0, 0, 0, 93, 0, 0, 0, 57, 0, 0, 0, 111, 0, 0, 0, 88, 0, 0, 0, 140, 0, 0, 0, 193, 0, 0, 0, 86, 0, 0, 0, 147, 0, 0, 0, 171, 0, 0, 0, 181, 0, 0, 0, 121, 0, 0, 0, 59, 0, 0, 0, 210, 0, 0, 0, 168, 0, 0, 0, 115, 0, 0, 0, 22, 0, 0, 0, 237, 0, 0, 0, 250, 0, 0, 0, 180, 0, 0, 0, 47, 0, 0, 0, 115, 0, 0, 0, 139, 0, 0, 0, 177, 0, 0, 0, 149, 0, -0, 0, 229, 0, 0, 0, 146, 0, 0, 0, 80, 0, 0, 0, 53, 0, 0, 0, 17, 0, 0, 0, 118, 0, 0, 0, 172, 0, 0, 0, 244, 0, 0, 0, 77, 0, 0, 0, 36, 0, 0, 0, 195, 0, 0, 0, 50, 0, 0, 0, 230, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 44, 0, 0, 0, 135, 0, 0, 0, 196, 0, 0, 0, 241, 0, 0, 0, 86, 0, 0, 0, 196, 0, 0, 0, 117, 0, 0, 0, 36, 0, 0, 0, 122, 0, 0, 0, 86, 0, 0, 0, 133, 0, 0, 0, 90, 0, 0, 0, 58, 0, 0, 0, 19, 0, 0, 0, 13, 0, 0, 0, 22, 0, 0, 0, 172, 0, 0, 0, 60, 0, 0, 0, 74, 0, 0, 0, 88, 0, 0, 0, 134, 0, 0, 0, 58, 0, 0, -0, 70, 0, 0, 0, 127, 0, 0, 0, 108, 0, 0, 0, 163, 0, 0, 0, 82, 0, 0, 0, 110, 0, 0, 0, 55, 0, 0, 0, 228, 0, 0, 0, 150, 0, 0, 0, 156, 0, 0, 0, 233, 0, 0, 0, 92, 0, 0, 0, 102, 0, 0, 0, 65, 0, 0, 0, 103, 0, 0, 0, 228, 0, 0, 0, 251, 0, 0, 0, 121, 0, 0, 0, 12, 0, 0, 0, 5, 0, 0, 0, 246, 0, 0, 0, 100, 0, 0, 0, 213, 0, 0, 0, 124, 0, 0, 0, 40, 0, 0, 0, 193, 0, 0, 0, 225, 0, 0, 0, 84, 0, 0, 0, 115, 0, 0, 0, 242, 0, 0, 0, 191, 0, 0, 0, 118, 0, 0, 0, 116, 0, 0, 0, 25, 0, 0, 0, 25, 0, 0, 0, 27, 0, 0, 0, 228, 0, -0, 0, 185, 0, 0, 0, 168, 0, 0, 0, 70, 0, 0, 0, 101, 0, 0, 0, 115, 0, 0, 0, 243, 0, 0, 0, 119, 0, 0, 0, 155, 0, 0, 0, 41, 0, 0, 0, 116, 0, 0, 0, 91, 0, 0, 0, 198, 0, 0, 0, 137, 0, 0, 0, 108, 0, 0, 0, 44, 0, 0, 0, 124, 0, 0, 0, 248, 0, 0, 0, 179, 0, 0, 0, 15, 0, 0, 0, 247, 0, 0, 0, 213, 0, 0, 0, 233, 0, 0, 0, 116, 0, 0, 0, 93, 0, 0, 0, 184, 0, 0, 0, 37, 0, 0, 0, 22, 0, 0, 0, 181, 0, 0, 0, 48, 0, 0, 0, 188, 0, 0, 0, 132, 0, 0, 0, 197, 0, 0, 0, 240, 0, 0, 0, 173, 0, 0, 0, 202, 0, 0, 0, 18, 0, 0, 0, 40, -0, 0, 0, 188, 0, 0, 0, 157, 0, 0, 0, 212, 0, 0, 0, 250, 0, 0, 0, 130, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0, 0, 191, 0, 0, 0, 162, 0, 0, 0, 21, 0, 0, 0, 44, 0, 0, 0, 212, 0, 0, 0, 52, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 177, 0, 0, 0, 70, 0, -0, 0, 186, 0, 0, 0, 14, 0, 0, 0, 49, 0, 0, 0, 165, 0, 0, 0, 103, 0, 0, 0, 108, 0, 0, 0, 127, 0, 0, 0, 214, 0, 0, 0, 217, 0, 0, 0, 39, 0, 0, 0, 133, 0, 0, 0, 15, 0, 0, 0, 121, 0, 0, 0, 20, 0, 0, 0, 200, 0, 0, 0, 108, 0, 0, 0, 47, 0, 0, 0, 95, 0, 0, 0, 91, 0, 0, 0, 156, 0, 0, 0, 53, 0, 0, 0, 61, 0, 0, 0, 56, 0, 0, 0, 134, 0, 0, 0, 119, 0, 0, 0, 101, 0, 0, 0, 85, 0, 0, 0, 106, 0, 0, 0, 123, 0, 0, 0, 211, 0, 0, 0, 176, 0, 0, 0, 58, 0, 0, 0, 102, 0, 0, 0, 96, 0, 0, 0, 27, 0, 0, 0, 67, 0, 0, 0, 241, 0, -0, 0, 38, 0, 0, 0, 88, 0, 0, 0, 153, 0, 0, 0, 9, 0, 0, 0, 143, 0, 0, 0, 45, 0, 0, 0, 163, 0, 0, 0, 20, 0, 0, 0, 113, 0, 0, 0, 133, 0, 0, 0, 219, 0, 0, 0, 237, 0, 0, 0, 246, 0, 0, 0, 38, 0, 0, 0, 213, 0, 0, 0, 97, 0, 0, 0, 154, 0, 0, 0, 115, 0, 0, 0, 172, 0, 0, 0, 14, 0, 0, 0, 234, 0, 0, 0, 172, 0, 0, 0, 183, 0, 0, 0, 12, 0, 0, 0, 94, 0, 0, 0, 244, 0, 0, 0, 229, 0, 0, 0, 23, 0, 0, 0, 14, 0, 0, 0, 16, 0, 0, 0, 159, 0, 0, 0, 231, 0, 0, 0, 67, 0, 0, 0, 95, 0, 0, 0, 103, 0, 0, 0, 92, 0, 0, 0, 172, 0, -0, 0, 75, 0, 0, 0, 229, 0, 0, 0, 20, 0, 0, 0, 65, 0, 0, 0, 210, 0, 0, 0, 191, 0, 0, 0, 72, 0, 0, 0, 245, 0, 0, 0, 20, 0, 0, 0, 176, 0, 0, 0, 113, 0, 0, 0, 198, 0, 0, 0, 97, 0, 0, 0, 193, 0, 0, 0, 178, 0, 0, 0, 112, 0, 0, 0, 88, 0, 0, 0, 210, 0, 0, 0, 90, 0, 0, 0, 45, 0, 0, 0, 186, 0, 0, 0, 22, 0, 0, 0, 7, 0, 0, 0, 146, 0, 0, 0, 148, 0, 0, 0, 220, 0, 0, 0, 189, 0, 0, 0, 80, 0, 0, 0, 43, 0, 0, 0, 201, 0, 0, 0, 127, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 97, 0, 0, 0, 237, 0, 0, 0, 248, 0, 0, -0, 67, 0, 0, 0, 237, 0, 0, 0, 245, 0, 0, 0, 249, 0, 0, 0, 64, 0, 0, 0, 96, 0, 0, 0, 178, 0, 0, 0, 176, 0, 0, 0, 130, 0, 0, 0, 203, 0, 0, 0, 237, 0, 0, 0, 117, 0, 0, 0, 199, 0, 0, 0, 101, 0, 0, 0, 128, 0, 0, 0, 186, 0, 0, 0, 13, 0, 0, 0, 9, 0, 0, 0, 64, 0, 0, 0, 167, 0, 0, 0, 57, 0, 0, 0, 166, 0, 0, 0, 103, 0, 0, 0, 52, 0, 0, 0, 126, 0, 0, 0, 102, 0, 0, 0, 190, 0, 0, 0, 86, 0, 0, 0, 251, 0, 0, 0, 83, 0, 0, 0, 120, 0, 0, 0, 196, 0, 0, 0, 70, 0, 0, 0, 232, 0, 0, 0, 237, 0, 0, 0, 104, 0, 0, 0, 108, 0, -0, 0, 127, 0, 0, 0, 206, 0, 0, 0, 232, 0, 0, 0, 159, 0, 0, 0, 206, 0, 0, 0, 162, 0, 0, 0, 100, 0, 0, 0, 88, 0, 0, 0, 83, 0, 0, 0, 232, 0, 0, 0, 193, 0, 0, 0, 169, 0, 0, 0, 194, 0, 0, 0, 123, 0, 0, 0, 89, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 226, 0, 0, 0, 67, 0, 0, 0, 115, 0, 0, 0, 43, 0, 0, 0, 172, 0, 0, 0, 45, 0, 0, 0, 193, 0, 0, 0, 137, 0, 0, 0, 59, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 213, 0, 0, 0, 192, 0, 0, 0, 151, 0, 0, 0, 138, 0, 0, 0, 253, 0, 0, 0, 111, 0, 0, 0, 54, 0, 0, 0, 51, 0, 0, 0, 183, -0, 0, 0, 185, 0, 0, 0, 195, 0, 0, 0, 136, 0, 0, 0, 9, 0, 0, 0, 208, 0, 0, 0, 182, 0, 0, 0, 86, 0, 0, 0, 48, 0, 0, 0, 92, 0, 0, 0, 174, 0, 0, 0, 179, 0, 0, 0, 117, 0, 0, 0, 68, 0, 0, 0, 164, 0, 0, 0, 131, 0, 0, 0, 81, 0, 0, 0, 110, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 0, 239, 0, 0, 0, 69, 0, 0, 0, 118, 0, 0, 0, 230, 0, 0, 0, 245, 0, 0, 0, 162, 0, 0, 0, 13, 0, 0, 0, 212, 0, 0, 0, 22, 0, 0, 0, 59, 0, 0, 0, 88, 0, 0, 0, 47, 0, 0, 0, 242, 0, 0, 0, 47, 0, 0, 0, 54, 0, 0, 0, 24, 0, 0, 0, 63, 0, 0, 0, 253, 0, -0, 0, 47, 0, 0, 0, 224, 0, 0, 0, 155, 0, 0, 0, 30, 0, 0, 0, 140, 0, 0, 0, 197, 0, 0, 0, 24, 0, 0, 0, 169, 0, 0, 0, 202, 0, 0, 0, 212, 0, 0, 0, 43, 0, 0, 0, 53, 0, 0, 0, 182, 0, 0, 0, 149, 0, 0, 0, 10, 0, 0, 0, 159, 0, 0, 0, 126, 0, 0, 0, 251, 0, 0, 0, 196, 0, 0, 0, 239, 0, 0, 0, 136, 0, 0, 0, 123, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 0, 236, 0, 0, 0, 47, 0, 0, 0, 13, 0, 0, 0, 15, 0, 0, 0, 122, 0, 0, 0, 252, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 210, 0, 0, 0, 218, 0, 0, 0, 199, 0, 0, 0, 68, 0, 0, 0, 214, 0, 0, 0, 122, 0, 0, 0, 219, 0, 0, 0, 38, 0, 0, 0, 125, 0, 0, 0, 29, 0, 0, 0, 184, 0, 0, 0, 225, 0, 0, 0, 222, 0, 0, 0, 157, 0, 0, 0, 122, 0, 0, 0, 125, 0, 0, 0, 23, 0, 0, 0, 126, 0, 0, 0, 28, 0, 0, 0, 55, 0, 0, 0, 4, 0, 0, 0, 141, 0, 0, -0, 45, 0, 0, 0, 124, 0, 0, 0, 94, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 30, 0, 0, 0, 175, 0, 0, 0, 199, 0, 0, 0, 27, 0, 0, 0, 51, 0, 0, 0, 72, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 246, 0, 0, 0, 242, 0, 0, 0, 202, 0, 0, 0, 15, 0, 0, 0, 39, 0, 0, 0, 27, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 126, 0, 0, 0, 2, 0, 0, 0, 29, 0, 0, 0, 73, 0, 0, 0, 192, 0, 0, 0, 93, 0, 0, 0, 121, 0, 0, 0, 135, 0, 0, 0, 239, 0, 0, 0, 94, 0, 0, 0, 122, 0, 0, 0, 47, 0, 0, 0, 31, 0, 0, 0, 102, 0, 0, 0, 85, 0, 0, 0, 216, 0, -0, 0, 9, 0, 0, 0, 217, 0, 0, 0, 97, 0, 0, 0, 84, 0, 0, 0, 131, 0, 0, 0, 2, 0, 0, 0, 24, 0, 0, 0, 130, 0, 0, 0, 147, 0, 0, 0, 153, 0, 0, 0, 7, 0, 0, 0, 208, 0, 0, 0, 167, 0, 0, 0, 218, 0, 0, 0, 216, 0, 0, 0, 117, 0, 0, 0, 137, 0, 0, 0, 250, 0, 0, 0, 242, 0, 0, 0, 217, 0, 0, 0, 163, 0, 0, 0, 184, 0, 0, 0, 107, 0, 0, 0, 90, 0, 0, 0, 53, 0, 0, 0, 40, 0, 0, 0, 210, 0, 0, 0, 107, 0, 0, 0, 89, 0, 0, 0, 194, 0, 0, 0, 248, 0, 0, 0, 69, 0, 0, 0, 226, 0, 0, 0, 188, 0, 0, 0, 6, 0, 0, 0, 101, 0, 0, 0, 192, 0, -0, 0, 163, 0, 0, 0, 136, 0, 0, 0, 81, 0, 0, 0, 149, 0, 0, 0, 252, 0, 0, 0, 150, 0, 0, 0, 148, 0, 0, 0, 120, 0, 0, 0, 232, 0, 0, 0, 13, 0, 0, 0, 139, 0, 0, 0, 65, 0, 0, 0, 201, 0, 0, 0, 194, 0, 0, 0, 88, 0, 0, 0, 72, 0, 0, 0, 117, 0, 0, 0, 16, 0, 0, 0, 47, 0, 0, 0, 205, 0, 0, 0, 42, 0, 0, 0, 201, 0, 0, 0, 160, 0, 0, 0, 109, 0, 0, 0, 15, 0, 0, 0, 221, 0, 0, 0, 156, 0, 0, 0, 152, 0, 0, 0, 38, 0, 0, 0, 61, 0, 0, 0, 47, 0, 0, 0, 102, 0, 0, 0, 41, 0, 0, 0, 27, 0, 0, 0, 4, 0, 0, 0, 137, 0, 0, 0, 189, 0, -0, 0, 126, 0, 0, 0, 238, 0, 0, 0, 110, 0, 0, 0, 221, 0, 0, 0, 183, 0, 0, 0, 14, 0, 0, 0, 239, 0, 0, 0, 176, 0, 0, 0, 12, 0, 0, 0, 180, 0, 0, 0, 252, 0, 0, 0, 127, 0, 0, 0, 194, 0, 0, 0, 201, 0, 0, 0, 58, 0, 0, 0, 60, 0, 0, 0, 100, 0, 0, 0, 239, 0, 0, 0, 69, 0, 0, 0, 68, 0, 0, 0, 175, 0, 0, 0, 138, 0, 0, 0, 144, 0, 0, 0, 101, 0, 0, 0, 118, 0, 0, 0, 161, 0, 0, 0, 76, 0, 0, 0, 112, 0, 0, 0, 75, 0, 0, 0, 14, 0, 0, 0, 160, 0, 0, 0, 131, 0, 0, 0, 112, 0, 0, 0, 19, 0, 0, 0, 164, 0, 0, 0, 175, 0, 0, 0, 184, -0, 0, 0, 56, 0, 0, 0, 25, 0, 0, 0, 34, 0, 0, 0, 101, 0, 0, 0, 9, 0, 0, 0, 180, 0, 0, 0, 2, 0, 0, 0, 79, 0, 0, 0, 6, 0, 0, 0, 248, 0, 0, 0, 23, 0, 0, 0, 206, 0, 0, 0, 70, 0, 0, 0, 69, 0, 0, 0, 218, 0, 0, 0, 80, 0, 0, 0, 124, 0, 0, 0, 138, 0, 0, 0, 209, 0, 0, 0, 78, 0, 0, 0, 247, 0, 0, 0, 212, 0, 0, 0, 22, 0, 0, 0, 108, 0, 0, 0, 78, 0, 0, 0, 149, 0, 0, 0, 157, 0, 0, 0, 93, 0, 0, 0, 15, 0, 0, 0, 145, 0, 0, 0, 43, 0, 0, 0, 82, 0, 0, 0, 254, 0, 0, 0, 92, 0, 0, 0, 52, 0, 0, 0, 229, 0, 0, 0, 48, 0, 0, 0, -230, 0, 0, 0, 164, 0, 0, 0, 59, 0, 0, 0, 243, 0, 0, 0, 243, 0, 0, 0, 52, 0, 0, 0, 8, 0, 0, 0, 169, 0, 0, 0, 74, 0, 0, 0, 160, 0, 0, 0, 181, 0, 0, 0, 110, 0, 0, 0, 179, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 38, 0, 0, 0, 217, 0, 0, 0, 94, 0, 0, 0, 163, 0, 0, 0, 15, 0, 0, 0, 235, 0, 0, 0, 162, 0, 0, 0, 243, 0, 0, 0, 32, 0, 0, 0, 59, 0, 0, 0, 55, 0, 0, 0, 212, 0, 0, 0, 228, 0, 0, 0, 158, 0, 0, 0, 206, 0, 0, 0, 6, 0, 0, 0, 61, 0, 0, 0, 83, 0, 0, 0, 237, 0, 0, 0, 174, 0, 0, 0, 43, 0, 0, 0, 235, 0, 0, 0, 182, -0, 0, 0, 36, 0, 0, 0, 10, 0, 0, 0, 17, 0, 0, 0, 163, 0, 0, 0, 15, 0, 0, 0, 214, 0, 0, 0, 127, 0, 0, 0, 164, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 159, 0, 0, 0, 44, 0, 0, 0, 252, 0, 0, 0, 214, 0, 0, 0, 178, 0, 0, 0, 30, 0, 0, 0, 46, 0, 0, -0, 82, 0, 0, 0, 122, 0, 0, 0, 6, 0, 0, 0, 135, 0, 0, 0, 45, 0, 0, 0, 134, 0, 0, 0, 114, 0, 0, 0, 43, 0, 0, 0, 109, 0, 0, 0, 144, 0, 0, 0, 119, 0, 0, 0, 70, 0, 0, 0, 67, 0, 0, 0, 181, 0, 0, 0, 122, 0, 0, 0, 248, 0, 0, 0, 96, 0, 0, 0, 125, 0, 0, 0, 145, 0, 0, 0, 96, 0, 0, 0, 91, 0, 0, 0, 157, 0, 0, 0, 158, 0, 0, 0, 7, 0, 0, 0, 151, 0, 0, 0, 135, 0, 0, 0, 199, 0, 0, 0, 4, 0, 0, 0, 28, 0, 0, 0, 56, 0, 0, 0, 1, 0, 0, 0, 57, 0, 0, 0, 88, 0, 0, 0, 199, 0, 0, 0, 133, 0, 0, 0, 163, 0, 0, 0, 252, 0, 0, 0, -100, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 37, 0, 0, 0, 162, 0, 0, 0, 191, 0, 0, 0, 80, 0, 0, 0, 148, 0, 0, 0, 202, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 69, 0, 0, 0, 10, 0, 0, 0, 36, 0, 0, 0, 210, 0, 0, 0, 81, 0, 0, 0, 41, 0, 0, 0, 81, 0, 0, 0, 22, 0, 0, 0, 77, 0, 0, 0, 74, 0, 0, 0, 215, 0, 0, 0, 152, 0, 0, 0, 113, 0, 0, 0, 87, 0, 0, 0, 172, 0, 0, 0, 125, 0, 0, 0, 139, 0, 0, 0, 55, 0, 0, 0, 189, 0, 0, 0, 99, 0, 0, 0, 255, 0, 0, 0, 135, 0, 0, 0, 177, 0, 0, 0, 73, 0, 0, 0, 149, 0, 0, 0, 32, 0, 0, 0, 124, -0, 0, 0, 207, 0, 0, 0, 124, 0, 0, 0, 89, 0, 0, 0, 196, 0, 0, 0, 145, 0, 0, 0, 156, 0, 0, 0, 239, 0, 0, 0, 208, 0, 0, 0, 219, 0, 0, 0, 96, 0, 0, 0, 9, 0, 0, 0, 157, 0, 0, 0, 70, 0, 0, 0, 203, 0, 0, 0, 120, 0, 0, 0, 148, 0, 0, 0, 144, 0, 0, 0, 228, 0, 0, 0, 69, 0, 0, 0, 179, 0, 0, 0, 246, 0, 0, 0, 217, 0, 0, 0, 246, 0, 0, 0, 87, 0, 0, 0, 116, 0, 0, 0, 213, 0, 0, 0, 248, 0, 0, 0, 131, 0, 0, 0, 79, 0, 0, 0, 57, 0, 0, 0, 201, 0, 0, 0, 189, 0, 0, 0, 136, 0, 0, 0, 194, 0, 0, 0, 87, 0, 0, 0, 33, 0, 0, 0, -31, 0, 0, 0, 36, 0, 0, 0, 50, 0, 0, 0, 104, 0, 0, 0, 248, 0, 0, 0, 199, 0, 0, 0, 33, 0, 0, 0, 95, 0, 0, 0, 11, 0, 0, 0, 42, 0, 0, 0, 54, 0, 0, 0, 104, 0, 0, 0, 252, 0, 0, 0, 95, 0, 0, 0, 182, 0, 0, 0, 79, 0, 0, 0, 165, 0, 0, 0, 227, 0, 0, 0, 157, 0, 0, 0, 36, 0, 0, 0, 47, 0, 0, 0, 192, 0, 0, 0, 147, 0, 0, 0, 97, 0, 0, 0, 207, 0, 0, 0, 248, 0, 0, 0, 10, 0, 0, 0, 237, 0, 0, 0, 225, 0, 0, 0, 219, 0, 0, 0, 39, 0, 0, 0, 236, 0, 0, 0, 14, 0, 0, 0, 20, 0, 0, 0, 50, 0, 0, 0, 95, 0, 0, 0, 142, 0, 0, 0, 161, -0, 0, 0, 98, 0, 0, 0, 65, 0, 0, 0, 22, 0, 0, 0, 149, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, 206, 0, 0, 0, 149, 0, 0, 0, 91, 0, 0, 0, 14, 0, 0, 0, 87, 0, 0, 0, 199, 0, 0, 0, 185, 0, 0, 0, 98, 0, 0, 0, 181, 0, 0, 0, 40, 0, 0, 0, 202, 0, 0, 0, 17, 0, 0, 0, 236, 0, 0, 0, 180, 0, 0, 0, 70, 0, 0, 0, 6, 0, 0, 0, 115, 0, 0, 0, 38, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 102, 0, 0, 0, 125, 0, 0, 0, 238, 0, 0, 0, 95, 0, 0, 0, 178, 0, 0, 0, 86, 0, 0, 0, 253, 0, 0, 0, 42, 0, 0, 0, 8, 0, 0, 0, 146, 0, 0, 0, 103, 0, 0, -0, 119, 0, 0, 0, 86, 0, 0, 0, 161, 0, 0, 0, 255, 0, 0, 0, 196, 0, 0, 0, 197, 0, 0, 0, 149, 0, 0, 0, 240, 0, 0, 0, 227, 0, 0, 0, 58, 0, 0, 0, 10, 0, 0, 0, 202, 0, 0, 0, 148, 0, 0, 0, 77, 0, 0, 0, 158, 0, 0, 0, 126, 0, 0, 0, 61, 0, 0, 0, 185, 0, 0, 0, 110, 0, 0, 0, 182, 0, 0, 0, 176, 0, 0, 0, 206, 0, 0, 0, 164, 0, 0, 0, 48, 0, 0, 0, 137, 0, 0, 0, 153, 0, 0, 0, 233, 0, 0, 0, 173, 0, 0, 0, 17, 0, 0, 0, 89, 0, 0, 0, 246, 0, 0, 0, 72, 0, 0, 0, 149, 0, 0, 0, 161, 0, 0, 0, 111, 0, 0, 0, 95, 0, 0, 0, 183, -0, 0, 0, 165, 0, 0, 0, 187, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 210, 0, 0, 0, 138, 0, 0, 0, 214, 0, 0, 0, 37, 0, 0, 0, 38, 0, 0, 0, 27, 0, 0, 0, 178, 0, 0, 0, 13, 0, 0, 0, 55, 0, 0, 0, 106, 0, 0, 0, 5, 0, 0, 0, 244, 0, 0, 0, 157, 0, 0, 0, 62, 0, 0, 0, 23, 0, 0, 0, 42, 0, 0, 0, 67, 0, 0, 0, 210, 0, 0, 0, 58, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 153, 0, 0, 0, 147, 0, 0, 0, 209, 0, 0, 0, 154, 0, 0, 0, 114, 0, 0, 0, 243, 0, 0, 0, 169, 0, 0, 0, 22, 0, 0, 0, 189, 0, 0, 0, 180, 0, 0, 0, 76, 0, 0, 0, 221, 0, 0, 0, 249, 0, 0, 0, 212, 0, 0, 0, 178, 0, 0, 0, 100, 0, 0, 0, 154, 0, 0, 0, 211, 0, 0, 0, 5, 0, 0, 0, 228, 0, 0, 0, 163, 0, 0, 0, 115, 0, 0, 0, 28, 0, 0, 0, 203, 0, 0, 0, 126, 0, 0, 0, 87, 0, 0, 0, 103, 0, 0, 0, 255, 0, 0, -0, 4, 0, 0, 0, 179, 0, 0, 0, 16, 0, 0, 0, 185, 0, 0, 0, 75, 0, 0, 0, 164, 0, 0, 0, 173, 0, 0, 0, 208, 0, 0, 0, 109, 0, 0, 0, 97, 0, 0, 0, 35, 0, 0, 0, 180, 0, 0, 0, 175, 0, 0, 0, 52, 0, 0, 0, 169, 0, 0, 0, 170, 0, 0, 0, 101, 0, 0, 0, 236, 0, 0, 0, 217, 0, 0, 0, 105, 0, 0, 0, 227, 0, 0, 0, 133, 0, 0, 0, 205, 0, 0, 0, 204, 0, 0, 0, 231, 0, 0, 0, 176, 0, 0, 0, 155, 0, 0, 0, 65, 0, 0, 0, 193, 0, 0, 0, 28, 0, 0, 0, 249, 0, 0, 0, 160, 0, 0, 0, 250, 0, 0, 0, 183, 0, 0, 0, 19, 0, 0, 0, 4, 0, 0, 0, 253, 0, -0, 0, 136, 0, 0, 0, 60, 0, 0, 0, 12, 0, 0, 0, 208, 0, 0, 0, 9, 0, 0, 0, 82, 0, 0, 0, 81, 0, 0, 0, 79, 0, 0, 0, 6, 0, 0, 0, 25, 0, 0, 0, 204, 0, 0, 0, 195, 0, 0, 0, 187, 0, 0, 0, 222, 0, 0, 0, 128, 0, 0, 0, 197, 0, 0, 0, 51, 0, 0, 0, 188, 0, 0, 0, 249, 0, 0, 0, 243, 0, 0, 0, 23, 0, 0, 0, 54, 0, 0, 0, 221, 0, 0, 0, 198, 0, 0, 0, 222, 0, 0, 0, 232, 0, 0, 0, 155, 0, 0, 0, 93, 0, 0, 0, 121, 0, 0, 0, 27, 0, 0, 0, 101, 0, 0, 0, 10, 0, 0, 0, 190, 0, 0, 0, 81, 0, 0, 0, 87, 0, 0, 0, 173, 0, 0, 0, 80, 0, 0, -0, 121, 0, 0, 0, 8, 0, 0, 0, 113, 0, 0, 0, 155, 0, 0, 0, 7, 0, 0, 0, 149, 0, 0, 0, 143, 0, 0, 0, 251, 0, 0, 0, 174, 0, 0, 0, 75, 0, 0, 0, 56, 0, 0, 0, 186, 0, 0, 0, 207, 0, 0, 0, 83, 0, 0, 0, 42, 0, 0, 0, 134, 0, 0, 0, 30, 0, 0, 0, 192, 0, 0, 0, 80, 0, 0, 0, 92, 0, 0, 0, 103, 0, 0, 0, 27, 0, 0, 0, 246, 0, 0, 0, 135, 0, 0, 0, 108, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 178, 0, 0, 0, 102, 0, 0, 0, 85, 0, 0, 0, 237, 0, 0, 0, 74, 0, 0, 0, 237, 0, 0, 0, 141, 0, 0, 0, 225, 0, 0, 0, 102, 0, 0, 0, 24, 0, 0, 0, -178, 0, 0, 0, 20, 0, 0, 0, 116, 0, 0, 0, 141, 0, 0, 0, 253, 0, 0, 0, 26, 0, 0, 0, 54, 0, 0, 0, 15, 0, 0, 0, 38, 0, 0, 0, 92, 0, 0, 0, 139, 0, 0, 0, 137, 0, 0, 0, 243, 0, 0, 0, 171, 0, 0, 0, 242, 0, 0, 0, 243, 0, 0, 0, 36, 0, 0, 0, 103, 0, 0, 0, 253, 0, 0, 0, 112, 0, 0, 0, 253, 0, 0, 0, 78, 0, 0, 0, 42, 0, 0, 0, 193, 0, 0, 0, 58, 0, 0, 0, 202, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 236, 0, 0, 0, 116, 0, 0, 0, 103, 0, 0, 0, 239, 0, 0, 0, 97, 0, 0, 0, 224, 0, 0, 0, 40, 0, 0, 0, 208, 0, 0, -0, 150, 0, 0, 0, 244, 0, 0, 0, 72, 0, 0, 0, 222, 0, 0, 0, 129, 0, 0, 0, 227, 0, 0, 0, 239, 0, 0, 0, 220, 0, 0, 0, 170, 0, 0, 0, 125, 0, 0, 0, 243, 0, 0, 0, 182, 0, 0, 0, 85, 0, 0, 0, 166, 0, 0, 0, 101, 0, 0, 0, 235, 0, 0, 0, 203, 0, 0, 0, 197, 0, 0, 0, 112, 0, 0, 0, 145, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 147, 0, 0, 0, 13, 0, 0, 0, 200, 0, 0, 0, 208, 0, 0, 0, 239, 0, 0, 0, 98, 0, 0, 0, 232, 0, 0, 0, 111, 0, 0, 0, 130, 0, 0, 0, 227, 0, 0, 0, 105, 0, 0, 0, 61, 0, 0, 0, 145, 0, 0, 0, 127, 0, 0, 0, 49, -0, 0, 0, 225, 0, 0, 0, 38, 0, 0, 0, 53, 0, 0, 0, 60, 0, 0, 0, 74, 0, 0, 0, 47, 0, 0, 0, 171, 0, 0, 0, 196, 0, 0, 0, 154, 0, 0, 0, 94, 0, 0, 0, 171, 0, 0, 0, 27, 0, 0, 0, 181, 0, 0, 0, 229, 0, 0, 0, 43, 0, 0, 0, 195, 0, 0, 0, 14, 0, 0, 0, 41, 0, 0, 0, 176, 0, 0, 0, 208, 0, 0, 0, 115, 0, 0, 0, 230, 0, 0, 0, 79, 0, 0, 0, 100, 0, 0, 0, 242, 0, 0, 0, 188, 0, 0, 0, 228, 0, 0, 0, 228, 0, 0, 0, 225, 0, 0, 0, 154, 0, 0, 0, 82, 0, 0, 0, 51, 0, 0, 0, 47, 0, 0, 0, 189, 0, 0, 0, 204, 0, 0, 0, 3, 0, 0, 0, 238, -0, 0, 0, 138, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 219, 0, 0, 0, 13, 0, 0, 0, 34, 0, 0, 0, 61, 0, 0, 0, 181, 0, 0, 0, 20, 0, 0, 0, 117, 0, 0, 0, 49, 0, 0, 0, 240, 0, 0, 0, 129, 0, 0, 0, 226, 0, 0, -0, 185, 0, 0, 0, 55, 0, 0, 0, 162, 0, 0, 0, 169, 0, 0, 0, 132, 0, 0, 0, 17, 0, 0, 0, 154, 0, 0, 0, 7, 0, 0, 0, 181, 0, 0, 0, 83, 0, 0, 0, 137, 0, 0, 0, 120, 0, 0, 0, 169, 0, 0, 0, 48, 0, 0, 0, 39, 0, 0, 0, 161, 0, 0, 0, 241, 0, 0, 0, 78, 0, 0, 0, 92, 0, 0, 0, 46, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 251, 0, 0, 0, 77, 0, 0, 0, 220, 0, 0, 0, 203, 0, 0, 0, 23, 0, 0, 0, 53, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 183, 0, 0, 0, 140, 0, 0, 0, 254, 0, 0, 0, 74, 0, 0, 0, 228, 0, 0, 0, 78, 0, 0, 0, -153, 0, 0, 0, 78, 0, 0, 0, 168, 0, 0, 0, 116, 0, 0, 0, 84, 0, 0, 0, 93, 0, 0, 0, 92, 0, 0, 0, 150, 0, 0, 0, 163, 0, 0, 0, 18, 0, 0, 0, 85, 0, 0, 0, 54, 0, 0, 0, 49, 0, 0, 0, 23, 0, 0, 0, 92, 0, 0, 0, 206, 0, 0, 0, 36, 0, 0, 0, 239, 0, 0, 0, 123, 0, 0, 0, 134, 0, 0, 0, 242, 0, 0, 0, 15, 0, 0, 0, 119, 0, 0, 0, 232, 0, 0, 0, 92, 0, 0, 0, 125, 0, 0, 0, 135, 0, 0, 0, 56, 0, 0, 0, 45, 0, 0, 0, 239, 0, 0, 0, 175, 0, 0, 0, 242, 0, 0, 0, 140, 0, 0, 0, 114, 0, 0, 0, 46, 0, 0, 0, 235, 0, 0, 0, 182, 0, 0, 0, -85, 0, 0, 0, 75, 0, 0, 0, 110, 0, 0, 0, 241, 0, 0, 0, 78, 0, 0, 0, 138, 0, 0, 0, 14, 0, 0, 0, 154, 0, 0, 0, 108, 0, 0, 0, 76, 0, 0, 0, 37, 0, 0, 0, 234, 0, 0, 0, 134, 0, 0, 0, 194, 0, 0, 0, 209, 0, 0, 0, 79, 0, 0, 0, 183, 0, 0, 0, 62, 0, 0, 0, 168, 0, 0, 0, 92, 0, 0, 0, 141, 0, 0, 0, 102, 0, 0, 0, 129, 0, 0, 0, 37, 0, 0, 0, 237, 0, 0, 0, 197, 0, 0, 0, 76, 0, 0, 0, 5, 0, 0, 0, 185, 0, 0, 0, 216, 0, 0, 0, 214, 0, 0, 0, 112, 0, 0, 0, 190, 0, 0, 0, 115, 0, 0, 0, 130, 0, 0, 0, 232, 0, 0, 0, 161, 0, 0, -0, 229, 0, 0, 0, 30, 0, 0, 0, 113, 0, 0, 0, 213, 0, 0, 0, 38, 0, 0, 0, 78, 0, 0, 0, 109, 0, 0, 0, 195, 0, 0, 0, 167, 0, 0, 0, 79, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0, 38, 0, 0, 0, 162, 0, 0, 0, 126, 0, 0, 0, 22, 0, 0, 0, 247, 0, 0, 0, 247, 0, 0, 0, 99, 0, 0, 0, 220, 0, 0, 0, 134, 0, 0, 0, 1, 0, 0, 0, 42, 0, 0, 0, 113, 0, 0, 0, 56, 0, 0, 0, 92, 0, 0, 0, 51, 0, 0, 0, 195, 0, 0, 0, 206, 0, 0, 0, 48, 0, 0, 0, 255, 0, 0, 0, 249, 0, 0, 0, 44, 0, 0, 0, 145, 0, 0, 0, 113, 0, 0, 0, 138, 0, 0, 0, 114, 0, 0, -0, 140, 0, 0, 0, 68, 0, 0, 0, 9, 0, 0, 0, 40, 0, 0, 0, 213, 0, 0, 0, 35, 0, 0, 0, 201, 0, 0, 0, 143, 0, 0, 0, 243, 0, 0, 0, 132, 0, 0, 0, 69, 0, 0, 0, 198, 0, 0, 0, 154, 0, 0, 0, 94, 0, 0, 0, 255, 0, 0, 0, 210, 0, 0, 0, 199, 0, 0, 0, 87, 0, 0, 0, 147, 0, 0, 0, 163, 0, 0, 0, 193, 0, 0, 0, 105, 0, 0, 0, 221, 0, 0, 0, 98, 0, 0, 0, 15, 0, 0, 0, 218, 0, 0, 0, 92, 0, 0, 0, 48, 0, 0, 0, 89, 0, 0, 0, 93, 0, 0, 0, 233, 0, 0, 0, 76, 0, 0, 0, 146, 0, 0, 0, 126, 0, 0, 0, 80, 0, 0, 0, 39, 0, 0, 0, 114, 0, 0, -0, 215, 0, 0, 0, 12, 0, 0, 0, 214, 0, 0, 0, 105, 0, 0, 0, 150, 0, 0, 0, 129, 0, 0, 0, 53, 0, 0, 0, 132, 0, 0, 0, 148, 0, 0, 0, 53, 0, 0, 0, 139, 0, 0, 0, 108, 0, 0, 0, 170, 0, 0, 0, 98, 0, 0, 0, 134, 0, 0, 0, 110, 0, 0, 0, 28, 0, 0, 0, 21, 0, 0, 0, 243, 0, 0, 0, 108, 0, 0, 0, 179, 0, 0, 0, 255, 0, 0, 0, 101, 0, 0, 0, 27, 0, 0, 0, 162, 0, 0, 0, 155, 0, 0, 0, 89, 0, 0, 0, 226, 0, 0, 0, 169, 0, 0, 0, 101, 0, 0, 0, 136, 0, 0, 0, 196, 0, 0, 0, 80, 0, 0, 0, 250, 0, 0, 0, 187, 0, 0, 0, 59, 0, 0, 0, 110, -0, 0, 0, 95, 0, 0, 0, 68, 0, 0, 0, 1, 0, 0, 0, 202, 0, 0, 0, 151, 0, 0, 0, 212, 0, 0, 0, 221, 0, 0, 0, 246, 0, 0, 0, 205, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 229, 0, 0, 0, 151, 0, 0, 0, 103, 0, 0, 0, 43, 0, 0, 0, 140, 0, 0, 0, 102, 0, 0, 0, 15, 0, 0, 0, 53, 0, 0, 0, 155, 0, 0, 0, 245, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 89, 0, 0, 0, 39, 0, 0, 0, 216, 0, 0, 0, 219, 0, 0, 0, 90, 0, 0, 0, 17, 0, 0, 0, 94, 0, 0, 0, 130, 0, 0, 0, 243, 0, 0, 0, 56, 0, 0, 0, 255, 0, 0, 0, 28, 0, 0, 0, 237, 0, 0, 0, 254, 0, 0, 0, 63, 0, 0, 0, 100, 0, 0, 0, 84, 0, 0, 0, 63, 0, 0, 0, 127, 0, 0, 0, 209, 0, 0, 0, 129, 0, 0, 0, 237, 0, 0, 0, 239, 0, 0, 0, 101, 0, 0, 0, 197, 0, 0, 0, 203, 0, 0, 0, 253, 0, 0, 0, 225, 0, 0, 0, 128, 0, 0, 0, 205, 0, 0, 0, 17, 0, -0, 0, 224, 0, 0, 0, 219, 0, 0, 0, 34, 0, 0, 0, 40, 0, 0, 0, 230, 0, 0, 0, 255, 0, 0, 0, 97, 0, 0, 0, 157, 0, 0, 0, 65, 0, 0, 0, 20, 0, 0, 0, 45, 0, 0, 0, 59, 0, 0, 0, 38, 0, 0, 0, 34, 0, 0, 0, 223, 0, 0, 0, 241, 0, 0, 0, 52, 0, 0, 0, 129, 0, 0, 0, 233, 0, 0, 0, 69, 0, 0, 0, 238, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 139, 0, 0, 0, 166, 0, 0, 0, 63, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 67, 0, 0, 0, 25, 0, 0, 0, 241, 0, 0, 0, 67, 0, 0, 0, 238, 0, 0, 0, 243, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 80, 0, 0, -0, 222, 0, 0, 0, 192, 0, 0, 0, 182, 0, 0, 0, 1, 0, 0, 0, 227, 0, 0, 0, 140, 0, 0, 0, 60, 0, 0, 0, 77, 0, 0, 0, 49, 0, 0, 0, 210, 0, 0, 0, 176, 0, 0, 0, 88, 0, 0, 0, 205, 0, 0, 0, 237, 0, 0, 0, 16, 0, 0, 0, 74, 0, 0, 0, 122, 0, 0, 0, 239, 0, 0, 0, 128, 0, 0, 0, 169, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, 0, 243, 0, 0, 0, 216, 0, 0, 0, 51, 0, 0, 0, 140, 0, 0, 0, 6, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 79, 0, 0, 0, 255, 0, 0, 0, 48, 0, 0, 0, 216, 0, 0, 0, 18, 0, 0, 0, 59, 0, 0, 0, 57, 0, 0, 0, 28, 0, 0, 0, -6, 0, 0, 0, 249, 0, 0, 0, 76, 0, 0, 0, 52, 0, 0, 0, 53, 0, 0, 0, 113, 0, 0, 0, 181, 0, 0, 0, 22, 0, 0, 0, 148, 0, 0, 0, 103, 0, 0, 0, 223, 0, 0, 0, 238, 0, 0, 0, 17, 0, 0, 0, 222, 0, 0, 0, 164, 0, 0, 0, 29, 0, 0, 0, 136, 0, 0, 0, 147, 0, 0, 0, 53, 0, 0, 0, 169, 0, 0, 0, 50, 0, 0, 0, 16, 0, 0, 0, 233, 0, 0, 0, 195, 0, 0, 0, 188, 0, 0, 0, 123, 0, 0, 0, 92, 0, 0, 0, 252, 0, 0, 0, 178, 0, 0, 0, 249, 0, 0, 0, 201, 0, 0, 0, 47, 0, 0, 0, 229, 0, 0, 0, 186, 0, 0, 0, 58, 0, 0, 0, 11, 0, 0, 0, 171, 0, 0, 0, -100, 0, 0, 0, 56, 0, 0, 0, 111, 0, 0, 0, 91, 0, 0, 0, 75, 0, 0, 0, 147, 0, 0, 0, 218, 0, 0, 0, 100, 0, 0, 0, 236, 0, 0, 0, 77, 0, 0, 0, 61, 0, 0, 0, 160, 0, 0, 0, 245, 0, 0, 0, 187, 0, 0, 0, 186, 0, 0, 0, 71, 0, 0, 0, 72, 0, 0, 0, 96, 0, 0, 0, 188, 0, 0, 0, 69, 0, 0, 0, 31, 0, 0, 0, 35, 0, 0, 0, 162, 0, 0, 0, 59, 0, 0, 0, 112, 0, 0, 0, 118, 0, 0, 0, 230, 0, 0, 0, 151, 0, 0, 0, 153, 0, 0, 0, 79, 0, 0, 0, 119, 0, 0, 0, 84, 0, 0, 0, 103, 0, 0, 0, 48, 0, 0, 0, 154, 0, 0, 0, 231, 0, 0, 0, 102, 0, 0, 0, -214, 0, 0, 0, 205, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 36, 0, 0, 0, 44, 0, 0, 0, 66, 0, 0, 0, 74, 0, 0, 0, 17, 0, 0, 0, 254, 0, 0, 0, 111, 0, 0, 0, 126, 0, 0, 0, 135, 0, 0, 0, 192, 0, 0, 0, 177, 0, 0, 0, 240, 0, 0, 0, 163, 0, 0, 0, 111, 0, 0, 0, 12, 0, 0, 0, 147, 0, 0, 0, 169, 0, 0, 0, 10, 0, 0, 0, 114, 0, 0, 0, 239, 0, 0, 0, 92, 0, 0, 0, 190, 0, 0, 0, 101, 0, 0, 0, 53, 0, 0, 0, 167, 0, 0, 0, 106, 0, 0, 0, 78, 0, 0, 0, 44, 0, 0, 0, 191, 0, 0, 0, 33, 0, 0, 0, 35, 0, 0, 0, 232, 0, 0, 0, 47, 0, 0, 0, -151, 0, 0, 0, 199, 0, 0, 0, 62, 0, 0, 0, 200, 0, 0, 0, 23, 0, 0, 0, 172, 0, 0, 0, 30, 0, 0, 0, 123, 0, 0, 0, 239, 0, 0, 0, 33, 0, 0, 0, 229, 0, 0, 0, 64, 0, 0, 0, 204, 0, 0, 0, 30, 0, 0, 0, 220, 0, 0, 0, 214, 0, 0, 0, 189, 0, 0, 0, 151, 0, 0, 0, 122, 0, 0, 0, 124, 0, 0, 0, 117, 0, 0, 0, 134, 0, 0, 0, 122, 0, 0, 0, 37, 0, 0, 0, 90, 0, 0, 0, 110, 0, 0, 0, 124, 0, 0, 0, 229, 0, 0, 0, 81, 0, 0, 0, 60, 0, 0, 0, 27, 0, 0, 0, 91, 0, 0, 0, 130, 0, 0, 0, 154, 0, 0, 0, 7, 0, 0, 0, 96, 0, 0, 0, 161, 0, 0, 0, -25, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 136, 0, 0, 0, 166, 0, 0, 0, 171, 0, 0, 0, 143, 0, 0, 0, 227, 0, 0, 0, 58, 0, 0, 0, 73, 0, 0, 0, 248, 0, 0, 0, 254, 0, 0, 0, 52, 0, 0, 0, 231, 0, 0, 0, 106, 0, 0, 0, 178, 0, 0, 0, 254, 0, 0, 0, 64, -0, 0, 0, 38, 0, 0, 0, 116, 0, 0, 0, 87, 0, 0, 0, 76, 0, 0, 0, 246, 0, 0, 0, 212, 0, 0, 0, 153, 0, 0, 0, 206, 0, 0, 0, 93, 0, 0, 0, 123, 0, 0, 0, 47, 0, 0, 0, 103, 0, 0, 0, 214, 0, 0, 0, 90, 0, 0, 0, 228, 0, 0, 0, 78, 0, 0, 0, 92, 0, 0, 0, 130, 0, 0, 0, 179, 0, 0, 0, 189, 0, 0, 0, 85, 0, 0, 0, 37, 0, 0, 0, 246, 0, 0, 0, 106, 0, 0, 0, 147, 0, 0, 0, 164, 0, 0, 0, 2, 0, 0, 0, 198, 0, 0, 0, 125, 0, 0, 0, 92, 0, 0, 0, 177, 0, 0, 0, 43, 0, 0, 0, 91, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 86, 0, 0, 0, 248, -0, 0, 0, 1, 0, 0, 0, 65, 0, 0, 0, 144, 0, 0, 0, 198, 0, 0, 0, 182, 0, 0, 0, 172, 0, 0, 0, 79, 0, 0, 0, 254, 0, 0, 0, 167, 0, 0, 0, 65, 0, 0, 0, 112, 0, 0, 0, 219, 0, 0, 0, 250, 0, 0, 0, 155, 0, 0, 0, 44, 0, 0, 0, 212, 0, 0, 0, 35, 0, 0, 0, 103, 0, 0, 0, 44, 0, 0, 0, 138, 0, 0, 0, 99, 0, 0, 0, 108, 0, 0, 0, 7, 0, 0, 0, 38, 0, 0, 0, 72, 0, 0, 0, 79, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 210, 0, 0, 0, 83, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 237, 0, 0, 0, 101, 0, 0, 0, 113, 0, 0, 0, 71, 0, 0, 0, 169, 0, -0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 18, 0, 0, 0, 188, 0, 0, 0, 40, 0, 0, 0, 51, 0, 0, 0, 57, 0, 0, 0, 192, 0, 0, 0, 250, 0, 0, 0, 250, 0, 0, 0, 205, 0, 0, 0, 51, 0, 0, 0, 67, 0, 0, 0, 199, 0, 0, 0, 151, 0, 0, 0, 118, 0, 0, 0, 155, 0, 0, 0, 147, 0, 0, 0, 145, 0, 0, 0, 114, 0, 0, 0, 235, 0, 0, 0, 197, 0, 0, 0, 24, 0, 0, 0, 103, 0, 0, 0, 76, 0, 0, 0, 17, 0, 0, 0, 240, 0, 0, 0, 244, 0, 0, 0, 229, 0, 0, 0, 115, 0, 0, 0, 178, 0, 0, 0, 92, 0, 0, 0, 27, 0, 0, 0, 194, 0, 0, 0, 38, 0, 0, 0, 63, 0, 0, 0, 191, 0, -0, 0, 43, 0, 0, 0, 134, 0, 0, 0, 230, 0, 0, 0, 140, 0, 0, 0, 29, 0, 0, 0, 223, 0, 0, 0, 202, 0, 0, 0, 252, 0, 0, 0, 213, 0, 0, 0, 248, 0, 0, 0, 58, 0, 0, 0, 195, 0, 0, 0, 68, 0, 0, 0, 114, 0, 0, 0, 230, 0, 0, 0, 120, 0, 0, 0, 157, 0, 0, 0, 43, 0, 0, 0, 151, 0, 0, 0, 248, 0, 0, 0, 40, 0, 0, 0, 69, 0, 0, 0, 180, 0, 0, 0, 32, 0, 0, 0, 201, 0, 0, 0, 42, 0, 0, 0, 140, 0, 0, 0, 103, 0, 0, 0, 170, 0, 0, 0, 17, 0, 0, 0, 197, 0, 0, 0, 91, 0, 0, 0, 47, 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 134, 0, 0, 0, 82, 0, -0, 0, 215, 0, 0, 0, 157, 0, 0, 0, 195, 0, 0, 0, 68, 0, 0, 0, 81, 0, 0, 0, 118, 0, 0, 0, 50, 0, 0, 0, 101, 0, 0, 0, 180, 0, 0, 0, 55, 0, 0, 0, 129, 0, 0, 0, 153, 0, 0, 0, 70, 0, 0, 0, 55, 0, 0, 0, 98, 0, 0, 0, 237, 0, 0, 0, 207, 0, 0, 0, 100, 0, 0, 0, 157, 0, 0, 0, 114, 0, 0, 0, 64, 0, 0, 0, 122, 0, 0, 0, 76, 0, 0, 0, 11, 0, 0, 0, 118, 0, 0, 0, 42, 0, 0, 0, 251, 0, 0, 0, 86, 0, 0, 0, 51, 0, 0, 0, 167, 0, 0, 0, 144, 0, 0, 0, 124, 0, 0, 0, 195, 0, 0, 0, 111, 0, 0, 0, 23, 0, 0, 0, 165, 0, 0, 0, 160, -0, 0, 0, 103, 0, 0, 0, 114, 0, 0, 0, 23, 0, 0, 0, 234, 0, 0, 0, 126, 0, 0, 0, 99, 0, 0, 0, 20, 0, 0, 0, 131, 0, 0, 0, 222, 0, 0, 0, 193, 0, 0, 0, 113, 0, 0, 0, 45, 0, 0, 0, 65, 0, 0, 0, 50, 0, 0, 0, 122, 0, 0, 0, 243, 0, 0, 0, 209, 0, 0, 0, 43, 0, 0, 0, 216, 0, 0, 0, 42, 0, 0, 0, 166, 0, 0, 0, 70, 0, 0, 0, 54, 0, 0, 0, 172, 0, 0, 0, 204, 0, 0, 0, 107, 0, 0, 0, 124, 0, 0, 0, 249, 0, 0, 0, 184, 0, 0, 0, 139, 0, 0, 0, 8, 0, 0, 0, 92, 0, 0, 0, 208, 0, 0, 0, 125, 0, 0, 0, 143, 0, 0, 0, 115, 0, 0, 0, 234, -0, 0, 0, 32, 0, 0, 0, 218, 0, 0, 0, 134, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, 0, 173, 0, 0, 0, 115, 0, 0, 0, 77, 0, 0, 0, 233, 0, 0, 0, 232, 0, 0, 0, 169, 0, 0, 0, 218, 0, 0, 0, 31, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 221, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 156, 0, 0, 0, 178, 0, 0, 0, 97, 0, 0, 0, 10, 0, 0, 0, 152, 0, 0, 0, 42, 0, 0, 0, 165, 0, 0, 0, 215, 0, 0, 0, 238, 0, 0, 0, 169, 0, 0, 0, 172, 0, 0, 0, 101, 0, 0, 0, 203, 0, 0, 0, 10, 0, 0, 0, 30, 0, 0, 0, 226, 0, 0, 0, 190, 0, 0, 0, 220, 0, 0, 0, 133, 0, 0, 0, 89, 0, 0, 0, 15, 0, 0, 0, 156, 0, 0, 0, 166, 0, 0, 0, 87, 0, 0, 0, 52, 0, 0, 0, 165, 0, 0, 0, 135, 0, 0, 0, 235, 0, 0, 0, 123, 0, 0, 0, 30, 0, 0, 0, 12, 0, 0, 0, 60, 0, 0, 0, 47, 0, 0, 0, 189, 0, 0, 0, 132, 0, 0, 0, 99, 0, 0, -0, 13, 0, 0, 0, 181, 0, 0, 0, 160, 0, 0, 0, 240, 0, 0, 0, 75, 0, 0, 0, 158, 0, 0, 0, 147, 0, 0, 0, 198, 0, 0, 0, 52, 0, 0, 0, 154, 0, 0, 0, 52, 0, 0, 0, 255, 0, 0, 0, 115, 0, 0, 0, 25, 0, 0, 0, 47, 0, 0, 0, 110, 0, 0, 0, 84, 0, 0, 0, 69, 0, 0, 0, 44, 0, 0, 0, 146, 0, 0, 0, 49, 0, 0, 0, 118, 0, 0, 0, 52, 0, 0, 0, 241, 0, 0, 0, 178, 0, 0, 0, 38, 0, 0, 0, 232, 0, 0, 0, 116, 0, 0, 0, 10, 0, 0, 0, 103, 0, 0, 0, 144, 0, 0, 0, 109, 0, 0, 0, 12, 0, 0, 0, 76, 0, 0, 0, 204, 0, 0, 0, 192, 0, 0, 0, 230, 0, 0, -0, 189, 0, 0, 0, 167, 0, 0, 0, 94, 0, 0, 0, 85, 0, 0, 0, 140, 0, 0, 0, 205, 0, 0, 0, 88, 0, 0, 0, 155, 0, 0, 0, 17, 0, 0, 0, 162, 0, 0, 0, 187, 0, 0, 0]).concat([75, 0, 0, 0, 177, 0, 0, 0, 67, 0, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 85, 0, 0, 0, 237, 0, 0, 0, 35, 0, 0, 0, 254, 0, 0, 0, 205, 0, 0, 0, 177, 0, 0, 0, 83, 0, 0, 0, 5, 0, 0, 0, 251, 0, 0, 0, 117, 0, 0, 0, 245, 0, 0, 0, 1, 0, 0, 0, 175, 0, 0, 0, 56, 0, 0, 0, 114, 0, 0, 0, 88, 0, 0, 0, 252, 0, 0, 0, 4, 0, 0, 0, 41, 0, 0, 0, 52, 0, 0, 0, 122, 0, -0, 0, 103, 0, 0, 0, 162, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 110, 0, 0, 0, 208, 0, 0, 0, 43, 0, 0, 0, 115, 0, 0, 0, 213, 0, 0, 0, 184, 0, 0, 0, 228, 0, 0, 0, 48, 0, 0, 0, 150, 0, 0, 0, 173, 0, 0, 0, 69, 0, 0, 0, 223, 0, 0, 0, 166, 0, 0, 0, 92, 0, 0, 0, 13, 0, 0, 0, 136, 0, 0, 0, 26, 0, 0, 0, 144, 0, 0, 0, 126, 0, 0, 0, 220, 0, 0, 0, 216, 0, 0, 0, 254, 0, 0, 0, 193, 0, 0, 0, 47, 0, 0, 0, 93, 0, 0, 0, 103, 0, 0, 0, 238, 0, 0, 0, 103, 0, 0, 0, 47, 0, 0, 0, 237, 0, 0, 0, 111, 0, 0, 0, 85, 0, 0, 0, 67, -0, 0, 0, 95, 0, 0, 0, 135, 0, 0, 0, 20, 0, 0, 0, 53, 0, 0, 0, 66, 0, 0, 0, 211, 0, 0, 0, 117, 0, 0, 0, 174, 0, 0, 0, 213, 0, 0, 0, 211, 0, 0, 0, 133, 0, 0, 0, 26, 0, 0, 0, 118, 0, 0, 0, 135, 0, 0, 0, 200, 0, 0, 0, 160, 0, 0, 0, 110, 0, 0, 0, 225, 0, 0, 0, 176, 0, 0, 0, 173, 0, 0, 0, 106, 0, 0, 0, 74, 0, 0, 0, 52, 0, 0, 0, 113, 0, 0, 0, 237, 0, 0, 0, 124, 0, 0, 0, 214, 0, 0, 0, 68, 0, 0, 0, 3, 0, 0, 0, 101, 0, 0, 0, 74, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 4, 0, 0, 0, 245, 0, 0, 0, 36, 0, 0, 0, 63, -0, 0, 0, 176, 0, 0, 0, 22, 0, 0, 0, 94, 0, 0, 0, 140, 0, 0, 0, 178, 0, 0, 0, 210, 0, 0, 0, 197, 0, 0, 0, 32, 0, 0, 0, 152, 0, 0, 0, 131, 0, 0, 0, 194, 0, 0, 0, 55, 0, 0, 0, 160, 0, 0, 0, 65, 0, 0, 0, 168, 0, 0, 0, 72, 0, 0, 0, 92, 0, 0, 0, 95, 0, 0, 0, 191, 0, 0, 0, 200, 0, 0, 0, 250, 0, 0, 0, 36, 0, 0, 0, 224, 0, 0, 0, 89, 0, 0, 0, 44, 0, 0, 0, 189, 0, 0, 0, 246, 0, 0, 0, 129, 0, 0, 0, 126, 0, 0, 0, 136, 0, 0, 0, 230, 0, 0, 0, 202, 0, 0, 0, 4, 0, 0, 0, 216, 0, 0, 0, 93, 0, 0, 0, 96, 0, 0, 0, 187, -0, 0, 0, 116, 0, 0, 0, 167, 0, 0, 0, 11, 0, 0, 0, 33, 0, 0, 0, 19, 0, 0, 0, 145, 0, 0, 0, 191, 0, 0, 0, 119, 0, 0, 0, 122, 0, 0, 0, 51, 0, 0, 0, 188, 0, 0, 0, 233, 0, 0, 0, 7, 0, 0, 0, 57, 0, 0, 0, 10, 0, 0, 0, 221, 0, 0, 0, 125, 0, 0, 0, 6, 0, 0, 0, 16, 0, 0, 0, 154, 0, 0, 0, 238, 0, 0, 0, 71, 0, 0, 0, 115, 0, 0, 0, 27, 0, 0, 0, 21, 0, 0, 0, 90, 0, 0, 0, 251, 0, 0, 0, 205, 0, 0, 0, 77, 0, 0, 0, 208, 0, 0, 0, 210, 0, 0, 0, 58, 0, 0, 0, 1, 0, 0, 0, 186, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 213, 0, 0, 0, 57, 0, 0, 0, 74, 0, 0, 0, 11, 0, 0, 0, 32, 0, 0, 0, 106, 0, 0, 0, 67, 0, 0, 0, 160, 0, 0, 0, 7, 0, 0, 0, 130, 0, 0, 0, 94, 0, 0, 0, 73, 0, 0, 0, 124, 0, 0, 0, 201, 0, 0, 0, 71, 0, 0, 0, 241, 0, 0, 0, 124, 0, 0, 0, 55, 0, 0, 0, 185, -0, 0, 0, 35, 0, 0, 0, 239, 0, 0, 0, 107, 0, 0, 0, 70, 0, 0, 0, 69, 0, 0, 0, 140, 0, 0, 0, 69, 0, 0, 0, 118, 0, 0, 0, 223, 0, 0, 0, 20, 0, 0, 0, 107, 0, 0, 0, 110, 0, 0, 0, 66, 0, 0, 0, 201, 0, 0, 0, 202, 0, 0, 0, 41, 0, 0, 0, 76, 0, 0, 0, 118, 0, 0, 0, 55, 0, 0, 0, 218, 0, 0, 0, 138, 0, 0, 0, 45, 0, 0, 0, 124, 0, 0, 0, 58, 0, 0, 0, 88, 0, 0, 0, 242, 0, 0, 0, 3, 0, 0, 0, 180, 0, 0, 0, 181, 0, 0, 0, 185, 0, 0, 0, 26, 0, 0, 0, 19, 0, 0, 0, 45, 0, 0, 0, 222, 0, 0, 0, 95, 0, 0, 0, 107, 0, 0, 0, 157, 0, -0, 0, 186, 0, 0, 0, 82, 0, 0, 0, 201, 0, 0, 0, 93, 0, 0, 0, 179, 0, 0, 0, 243, 0, 0, 0, 48, 0, 0, 0, 76, 0, 0, 0, 111, 0, 0, 0, 254, 0, 0, 0, 107, 0, 0, 0, 12, 0, 0, 0, 98, 0, 0, 0, 215, 0, 0, 0, 72, 0, 0, 0, 113, 0, 0, 0, 239, 0, 0, 0, 177, 0, 0, 0, 133, 0, 0, 0, 121, 0, 0, 0, 192, 0, 0, 0, 237, 0, 0, 0, 36, 0, 0, 0, 177, 0, 0, 0, 8, 0, 0, 0, 147, 0, 0, 0, 118, 0, 0, 0, 142, 0, 0, 0, 247, 0, 0, 0, 56, 0, 0, 0, 142, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 128, 0, 0, 0, 64, 0, 0, 0, 175, 0, 0, 0, 144, -0, 0, 0, 100, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 136, 0, 0, 0, 218, 0, 0, 0, 193, 0, 0, 0, 152, 0, 0, 0, 68, 0, 0, 0, 60, 0, 0, 0, 83, 0, 0, 0, 78, 0, 0, 0, 219, 0, 0, 0, 75, 0, 0, 0, 185, 0, 0, 0, 18, 0, 0, 0, 95, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 239, 0, 0, 0, 117, 0, 0, 0, 231, 0, 0, 0, 177, 0, 0, 0, 58, 0, 0, 0, 229, 0, 0, 0, 7, 0, 0, 0, 250, 0, 0, 0, 202, 0, 0, 0, 101, 0, 0, 0, 123, 0, 0, 0, 114, 0, 0, 0, 16, 0, 0, 0, 100, 0, 0, 0, 127, 0, 0, 0, 61, 0, 0, 0, 129, 0, 0, 0, 240, 0, -0, 0, 235, 0, 0, 0, 22, 0, 0, 0, 253, 0, 0, 0, 88, 0, 0, 0, 51, 0, 0, 0, 141, 0, 0, 0, 124, 0, 0, 0, 26, 0, 0, 0, 251, 0, 0, 0, 32, 0, 0, 0, 44, 0, 0, 0, 138, 0, 0, 0, 238, 0, 0, 0, 144, 0, 0, 0, 187, 0, 0, 0, 51, 0, 0, 0, 109, 0, 0, 0, 69, 0, 0, 0, 233, 0, 0, 0, 142, 0, 0, 0, 153, 0, 0, 0, 133, 0, 0, 0, 225, 0, 0, 0, 8, 0, 0, 0, 31, 0, 0, 0, 197, 0, 0, 0, 241, 0, 0, 0, 181, 0, 0, 0, 70, 0, 0, 0, 228, 0, 0, 0, 231, 0, 0, 0, 67, 0, 0, 0, 75, 0, 0, 0, 160, 0, 0, 0, 63, 0, 0, 0, 43, 0, 0, 0, 6, 0, 0, -0, 186, 0, 0, 0, 23, 0, 0, 0, 174, 0, 0, 0, 61, 0, 0, 0, 230, 0, 0, 0, 206, 0, 0, 0, 189, 0, 0, 0, 184, 0, 0, 0, 237, 0, 0, 0, 116, 0, 0, 0, 17, 0, 0, 0, 53, 0, 0, 0, 236, 0, 0, 0, 150, 0, 0, 0, 254, 0, 0, 0, 49, 0, 0, 0, 227, 0, 0, 0, 14, 0, 0, 0, 122, 0, 0, 0, 78, 0, 0, 0, 201, 0, 0, 0, 29, 0, 0, 0, 203, 0, 0, 0, 32, 0, 0, 0, 224, 0, 0, 0, 103, 0, 0, 0, 233, 0, 0, 0, 123, 0, 0, 0, 219, 0, 0, 0, 150, 0, 0, 0, 92, 0, 0, 0, 176, 0, 0, 0, 50, 0, 0, 0, 208, 0, 0, 0, 89, 0, 0, 0, 49, 0, 0, 0, 144, 0, -0, 0, 220, 0, 0, 0, 146, 0, 0, 0, 151, 0, 0, 0, 172, 0, 0, 0, 9, 0, 0, 0, 56, 0, 0, 0, 49, 0, 0, 0, 15, 0, 0, 0, 126, 0, 0, 0, 214, 0, 0, 0, 93, 0, 0, 0, 208, 0, 0, 0, 6, 0, 0, 0, 182, 0, 0, 0, 31, 0, 0, 0, 234, 0, 0, 0, 240, 0, 0, 0, 91, 0, 0, 0, 7, 0, 0, 0, 129, 0, 0, 0, 159, 0, 0, 0, 199, 0, 0, 0, 222, 0, 0, 0, 107, 0, 0, 0, 65, 0, 0, 0, 34, 0, 0, 0, 53, 0, 0, 0, 20, 0, 0, 0, 103, 0, 0, 0, 119, 0, 0, 0, 62, 0, 0, 0, 144, 0, 0, 0, 129, 0, 0, 0, 176, 0, 0, 0, 217, 0, 0, 0, 133, 0, 0, 0, 76, 0, 0, -0, 202, 0, 0, 0, 155, 0, 0, 0, 63, 0, 0, 0, 4, 0, 0, 0, 89, 0, 0, 0, 214, 0, 0, 0, 170, 0, 0, 0, 23, 0, 0, 0, 195, 0, 0, 0, 136, 0, 0, 0, 52, 0, 0, 0, 55, 0, 0, 0, 186, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 182, 0, 0, 0, 105, 0, 0, 0, 200, -0, 0, 0, 129, 0, 0, 0, 149, 0, 0, 0, 148, 0, 0, 0, 51, 0, 0, 0, 146, 0, 0, 0, 52, 0, 0, 0, 233, 0, 0, 0, 60, 0, 0, 0, 132, 0, 0, 0, 13, 0, 0, 0, 61, 0, 0, 0, 90, 0, 0, 0, 55, 0, 0, 0, 156, 0, 0, 0, 34, 0, 0, 0, 160, 0, 0, 0, 170, 0, 0, 0, 101, 0, 0, 0, 206, 0, 0, 0, 180, 0, 0, 0, 194, 0, 0, 0, 45, 0, 0, 0, 102, 0, 0, 0, 103, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 116, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 176, 0, 0, 0, 213, 0, 0, 0, 230, 0, 0, 0, 199, 0, 0, 0, 239, 0, 0, 0, 177, 0, 0, 0, 167, 0, 0, 0, 19, -0, 0, 0, 218, 0, 0, 0, 96, 0, 0, 0, 180, 0, 0, 0, 128, 0, 0, 0, 193, 0, 0, 0, 66, 0, 0, 0, 125, 0, 0, 0, 16, 0, 0, 0, 112, 0, 0, 0, 151, 0, 0, 0, 4, 0, 0, 0, 77, 0, 0, 0, 218, 0, 0, 0, 35, 0, 0, 0, 137, 0, 0, 0, 194, 0, 0, 0, 14, 0, 0, 0, 104, 0, 0, 0, 203, 0, 0, 0, 222, 0, 0, 0, 224, 0, 0, 0, 155, 0, 0, 0, 41, 0, 0, 0, 51, 0, 0, 0, 254, 0, 0, 0, 66, 0, 0, 0, 42, 0, 0, 0, 54, 0, 0, 0, 43, 0, 0, 0, 46, 0, 0, 0, 54, 0, 0, 0, 100, 0, 0, 0, 92, 0, 0, 0, 139, 0, 0, 0, 204, 0, 0, 0, 129, 0, 0, 0, 106, -0, 0, 0, 21, 0, 0, 0, 8, 0, 0, 0, 161, 0, 0, 0, 39, 0, 0, 0, 232, 0, 0, 0, 87, 0, 0, 0, 229, 0, 0, 0, 120, 0, 0, 0, 142, 0, 0, 0, 242, 0, 0, 0, 88, 0, 0, 0, 25, 0, 0, 0, 18, 0, 0, 0, 66, 0, 0, 0, 174, 0, 0, 0, 196, 0, 0, 0, 99, 0, 0, 0, 62, 0, 0, 0, 120, 0, 0, 0, 150, 0, 0, 0, 156, 0, 0, 0, 167, 0, 0, 0, 202, 0, 0, 0, 128, 0, 0, 0, 174, 0, 0, 0, 2, 0, 0, 0, 133, 0, 0, 0, 177, 0, 0, 0, 124, 0, 0, 0, 4, 0, 0, 0, 92, 0, 0, 0, 193, 0, 0, 0, 91, 0, 0, 0, 38, 0, 0, 0, 193, 0, 0, 0, 186, 0, 0, 0, 237, 0, -0, 0, 165, 0, 0, 0, 89, 0, 0, 0, 112, 0, 0, 0, 133, 0, 0, 0, 140, 0, 0, 0, 140, 0, 0, 0, 232, 0, 0, 0, 135, 0, 0, 0, 172, 0, 0, 0, 106, 0, 0, 0, 40, 0, 0, 0, 153, 0, 0, 0, 53, 0, 0, 0, 159, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 40, 0, 0, 0, 190, 0, 0, 0, 135, 0, 0, 0, 218, 0, 0, 0, 128, 0, 0, 0, 40, 0, 0, 0, 56, 0, 0, 0, 222, 0, 0, 0, 159, 0, 0, 0, 205, 0, 0, 0, 228, 0, 0, 0, 227, 0, 0, 0, 98, 0, 0, 0, 251, 0, 0, 0, 46, 0, 0, 0, 70, 0, 0, 0, 141, 0, 0, 0, 1, 0, 0, 0, 179, 0, 0, 0, 6, 0, 0, 0, 81, 0, 0, -0, 212, 0, 0, 0, 25, 0, 0, 0, 59, 0, 0, 0, 17, 0, 0, 0, 250, 0, 0, 0, 226, 0, 0, 0, 173, 0, 0, 0, 30, 0, 0, 0, 160, 0, 0, 0, 32, 0, 0, 0, 153, 0, 0, 0, 105, 0, 0, 0, 10, 0, 0, 0, 174, 0, 0, 0, 163, 0, 0, 0, 112, 0, 0, 0, 78, 0, 0, 0, 100, 0, 0, 0, 128, 0, 0, 0, 183, 0, 0, 0, 133, 0, 0, 0, 156, 0, 0, 0, 135, 0, 0, 0, 84, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 85, 0, 0, 0, 128, 0, 0, 0, 109, 0, 0, 0, 141, 0, 0, 0, 124, 0, 0, 0, 169, 0, 0, 0, 100, 0, 0, 0, 202, 0, 0, 0, 108, 0, 0, 0, 46, 0, 0, 0, 33, 0, -0, 0, 216, 0, 0, 0, 200, 0, 0, 0, 108, 0, 0, 0, 145, 0, 0, 0, 74, 0, 0, 0, 7, 0, 0, 0, 173, 0, 0, 0, 8, 0, 0, 0, 117, 0, 0, 0, 193, 0, 0, 0, 79, 0, 0, 0, 164, 0, 0, 0, 178, 0, 0, 0, 195, 0, 0, 0, 111, 0, 0, 0, 70, 0, 0, 0, 62, 0, 0, 0, 177, 0, 0, 0, 206, 0, 0, 0, 82, 0, 0, 0, 171, 0, 0, 0, 103, 0, 0, 0, 9, 0, 0, 0, 84, 0, 0, 0, 72, 0, 0, 0, 107, 0, 0, 0, 108, 0, 0, 0, 215, 0, 0, 0, 29, 0, 0, 0, 113, 0, 0, 0, 118, 0, 0, 0, 203, 0, 0, 0, 255, 0, 0, 0, 221, 0, 0, 0, 49, 0, 0, 0, 54, 0, 0, 0, 136, 0, -0, 0, 250, 0, 0, 0, 253, 0, 0, 0, 240, 0, 0, 0, 54, 0, 0, 0, 111, 0, 0, 0, 7, 0, 0, 0, 116, 0, 0, 0, 136, 0, 0, 0, 80, 0, 0, 0, 208, 0, 0, 0, 149, 0, 0, 0, 56, 0, 0, 0, 74, 0, 0, 0, 72, 0, 0, 0, 46, 0, 0, 0, 7, 0, 0, 0, 100, 0, 0, 0, 151, 0, 0, 0, 17, 0, 0, 0, 118, 0, 0, 0, 1, 0, 0, 0, 26, 0, 0, 0, 39, 0, 0, 0, 77, 0, 0, 0, 142, 0, 0, 0, 37, 0, 0, 0, 154, 0, 0, 0, 155, 0, 0, 0, 28, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 0, 0, 0, 87, 0, 0, 0, 189, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 172, 0, 0, 0, 94, 0, 0, 0, 118, 0, 0, 0, 163, 0, 0, 0, 113, 0, 0, 0, 173, 0, 0, 0, 43, 0, 0, 0, 16, 0, 0, 0, 69, 0, 0, 0, 2, 0, 0, 0, 236, 0, 0, 0, 89, 0, 0, 0, 213, 0, 0, 0, 93, 0, 0, 0, 169, 0, 0, 0, 68, 0, 0, 0, 204, 0, 0, 0, 37, 0, 0, 0, 76, 0, 0, 0, 179, 0, -0, 0, 60, 0, 0, 0, 91, 0, 0, 0, 105, 0, 0, 0, 7, 0, 0, 0, 85, 0, 0, 0, 38, 0, 0, 0, 107, 0, 0, 0, 48, 0, 0, 0, 107, 0, 0, 0, 212, 0, 0, 0, 167, 0, 0, 0, 81, 0, 0, 0, 41, 0, 0, 0, 227, 0, 0, 0, 249, 0, 0, 0, 122, 0, 0, 0, 117, 0, 0, 0, 42, 0, 0, 0, 130, 0, 0, 0, 47, 0, 0, 0, 214, 0, 0, 0, 29, 0, 0, 0, 153, 0, 0, 0, 43, 0, 0, 0, 128, 0, 0, 0, 213, 0, 0, 0, 103, 0, 0, 0, 30, 0, 0, 0, 21, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 253, 0, 0, 0, 235, 0, 0, 0, 172, 0, 0, 0, 151, 0, 0, 0, 53, 0, 0, 0, 9, 0, 0, -0, 127, 0, 0, 0, 63, 0, 0, 0, 53, 0, 0, 0, 13, 0, 0, 0, 52, 0, 0, 0, 10, 0, 0, 0, 184, 0, 0, 0, 103, 0, 0, 0, 86, 0, 0, 0, 41, 0, 0, 0, 32, 0, 0, 0, 243, 0, 0, 0, 25, 0, 0, 0, 95, 0, 0, 0, 226, 0, 0, 0, 131, 0, 0, 0, 66, 0, 0, 0, 115, 0, 0, 0, 83, 0, 0, 0, 168, 0, 0, 0, 197, 0, 0, 0, 2, 0, 0, 0, 25, 0, 0, 0, 51, 0, 0, 0, 180, 0, 0, 0, 100, 0, 0, 0, 189, 0, 0, 0, 195, 0, 0, 0, 135, 0, 0, 0, 140, 0, 0, 0, 215, 0, 0, 0, 118, 0, 0, 0, 237, 0, 0, 0, 37, 0, 0, 0, 71, 0, 0, 0, 57, 0, 0, 0, 55, 0, 0, 0, -118, 0, 0, 0, 13, 0, 0, 0, 29, 0, 0, 0, 12, 0, 0, 0, 245, 0, 0, 0, 90, 0, 0, 0, 109, 0, 0, 0, 67, 0, 0, 0, 136, 0, 0, 0, 153, 0, 0, 0, 21, 0, 0, 0, 180, 0, 0, 0, 82, 0, 0, 0, 15, 0, 0, 0, 42, 0, 0, 0, 179, 0, 0, 0, 176, 0, 0, 0, 63, 0, 0, 0, 166, 0, 0, 0, 179, 0, 0, 0, 38, 0, 0, 0, 179, 0, 0, 0, 199, 0, 0, 0, 69, 0, 0, 0, 245, 0, 0, 0, 146, 0, 0, 0, 95, 0, 0, 0, 155, 0, 0, 0, 23, 0, 0, 0, 157, 0, 0, 0, 35, 0, 0, 0, 189, 0, 0, 0, 21, 0, 0, 0, 254, 0, 0, 0, 82, 0, 0, 0, 82, 0, 0, 0, 21, 0, 0, 0, 38, -0, 0, 0, 121, 0, 0, 0, 134, 0, 0, 0, 186, 0, 0, 0, 6, 0, 0, 0, 86, 0, 0, 0, 102, 0, 0, 0, 187, 0, 0, 0, 140, 0, 0, 0, 46, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 213, 0, 0, 0, 74, 0, 0, 0, 24, 0, 0, 0, 82, 0, 0, 0, 218, 0, 0, 0, 132, 0, 0, 0, 68, 0, 0, 0, 240, 0, 0, 0, 62, 0, 0, 0, 233, 0, 0, 0, 140, 0, 0, 0, 53, 0, 0, 0, 173, 0, 0, 0, 160, 0, 0, 0, 65, 0, 0, 0, 236, 0, 0, 0, 200, 0, 0, 0, 77, 0, 0, 0, 185, 0, 0, 0, 210, 0, 0, 0, 110, 0, 0, 0, 150, 0, 0, 0, 78, 0, 0, 0, 91, 0, 0, 0, 197, 0, 0, 0, 194, -0, 0, 0, 160, 0, 0, 0, 27, 0, 0, 0, 207, 0, 0, 0, 12, 0, 0, 0, 191, 0, 0, 0, 23, 0, 0, 0, 102, 0, 0, 0, 87, 0, 0, 0, 193, 0, 0, 0, 23, 0, 0, 0, 144, 0, 0, 0, 69, 0, 0, 0, 113, 0, 0, 0, 194, 0, 0, 0, 225, 0, 0, 0, 36, 0, 0, 0, 235, 0, 0, 0, 39, 0, 0, 0, 44, 0, 0, 0, 185, 0, 0, 0, 66, 0, 0, 0, 164, 0, 0, 0, 175, 0, 0, 0, 59, 0, 0, 0, 66, 0, 0, 0, 14, 0, 0, 0, 194, 0, 0, 0, 15, 0, 0, 0, 242, 0, 0, 0, 234, 0, 0, 0, 131, 0, 0, 0, 175, 0, 0, 0, 154, 0, 0, 0, 19, 0, 0, 0, 23, 0, 0, 0, 176, 0, 0, 0, 189, -0, 0, 0, 137, 0, 0, 0, 23, 0, 0, 0, 227, 0, 0, 0, 114, 0, 0, 0, 203, 0, 0, 0, 14, 0, 0, 0, 118, 0, 0, 0, 126, 0, 0, 0, 65, 0, 0, 0, 99, 0, 0, 0, 4, 0, 0, 0, 136, 0, 0, 0, 113, 0, 0, 0, 117, 0, 0, 0, 120, 0, 0, 0, 56, 0, 0, 0, 134, 0, 0, 0, 87, 0, 0, 0, 221, 0, 0, 0, 159, 0, 0, 0, 238, 0, 0, 0, 84, 0, 0, 0, 112, 0, 0, 0, 101, 0, 0, 0, 191, 0, 0, 0, 241, 0, 0, 0, 44, 0, 0, 0, 224, 0, 0, 0, 57, 0, 0, 0, 13, 0, 0, 0, 227, 0, 0, 0, 137, 0, 0, 0, 253, 0, 0, 0, 142, 0, 0, 0, 147, 0, 0, 0, 79, 0, 0, 0, 67, -0, 0, 0, 220, 0, 0, 0, 213, 0, 0, 0, 91, 0, 0, 0, 222, 0, 0, 0, 249, 0, 0, 0, 152, 0, 0, 0, 229, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 59, 0, 0, 0, 101, 0, 0, 0, 17, 0, 0, 0, 223, 0, 0, 0, 178, 0, 0, 0, 242, 0, 0, 0, 99, 0, 0, 0, 148, -0, 0, 0, 18, 0, 0, 0, 111, 0, 0, 0, 92, 0, 0, 0, 158, 0, 0, 0, 119, 0, 0, 0, 193, 0, 0, 0, 182, 0, 0, 0, 216, 0, 0, 0, 171, 0, 0, 0, 88, 0, 0, 0, 122, 0, 0, 0, 29, 0, 0, 0, 149, 0, 0, 0, 115, 0, 0, 0, 221, 0, 0, 0, 231, 0, 0, 0, 227, 0, 0, 0, 111, 0, 0, 0, 242, 0, 0, 0, 3, 0, 0, 0, 29, 0, 0, 0, 219, 0, 0, 0, 118, 0, 0, 0, 174, 0, 0, 0, 6, 0, 0, 0, 78, 0, 0, 0, 44, 0, 0, 0, 82, 0, 0, 0, 27, 0, 0, 0, 188, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 165, 0, 0, 0, 190, 0, 0, 0, 39, 0, 0, 0, 189, 0, 0, 0, 235, -0, 0, 0, 225, 0, 0, 0, 20, 0, 0, 0, 23, 0, 0, 0, 104, 0, 0, 0, 38, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 209, 0, 0, 0, 24, 0, 0, 0, 11, 0, 0, 0, 223, 0, 0, 0, 241, 0, 0, 0, 6, 0, 0, 0, 92, 0, 0, 0, 166, 0, 0, 0, 27, 0, 0, 0, 185, 0, 0, 0, 36, 0, 0, 0, 197, 0, 0, 0, 102, 0, 0, 0, 128, 0, 0, 0, 19, 0, 0, 0, 14, 0, 0, 0, 72, 0, 0, 0, 140, 0, 0, 0, 135, 0, 0, 0, 49, 0, 0, 0, 132, 0, 0, 0, 180, 0, 0, 0, 96, 0, 0, 0, 237, 0, 0, 0, 197, 0, 0, 0, 236, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 5, 0, 0, 0, 51, 0, 0, -0, 95, 0, 0, 0, 47, 0, 0, 0, 125, 0, 0, 0, 64, 0, 0, 0, 182, 0, 0, 0, 50, 0, 0, 0, 29, 0, 0, 0, 56, 0, 0, 0, 116, 0, 0, 0, 27, 0, 0, 0, 241, 0, 0, 0, 9, 0, 0, 0, 61, 0, 0, 0, 212, 0, 0, 0, 105, 0, 0, 0, 130, 0, 0, 0, 188, 0, 0, 0, 141, 0, 0, 0, 248, 0, 0, 0, 52, 0, 0, 0, 54, 0, 0, 0, 117, 0, 0, 0, 85, 0, 0, 0, 24, 0, 0, 0, 85, 0, 0, 0, 88, 0, 0, 0, 60, 0, 0, 0, 121, 0, 0, 0, 175, 0, 0, 0, 38, 0, 0, 0, 128, 0, 0, 0, 171, 0, 0, 0, 155, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 203, 0, 0, 0, -218, 0, 0, 0, 193, 0, 0, 0, 159, 0, 0, 0, 246, 0, 0, 0, 47, 0, 0, 0, 162, 0, 0, 0, 244, 0, 0, 0, 69, 0, 0, 0, 23, 0, 0, 0, 190, 0, 0, 0, 235, 0, 0, 0, 133, 0, 0, 0, 237, 0, 0, 0, 158, 0, 0, 0, 205, 0, 0, 0, 86, 0, 0, 0, 245, 0, 0, 0, 23, 0, 0, 0, 69, 0, 0, 0, 66, 0, 0, 0, 180, 0, 0, 0, 31, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 5, 0, 0, 0, 116, 0, 0, 0, 21, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 106, 0, 0, 0, 61, 0, 0, 0, 36, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 88, 0, 0, 0, 177, 0, 0, 0, 66, 0, -0, 0, 215, 0, 0, 0, 4, 0, 0, 0, 141, 0, 0, 0, 189, 0, 0, 0, 163, 0, 0, 0, 196, 0, 0, 0, 6, 0, 0, 0, 155, 0, 0, 0, 31, 0, 0, 0, 144, 0, 0, 0, 88, 0, 0, 0, 96, 0, 0, 0, 116, 0, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 60, 0, 0, 0, 210, 0, 0, 0, 218, 0, 0, 0, 130, 0, 0, 0, 187, 0, 0, 0, 16, 0, 0, 0, 144, 0, 0, 0, 105, 0, 0, 0, 146, 0, 0, 0, 169, 0, 0, 0, 180, 0, 0, 0, 48, 0, 0, 0, 129, 0, 0, 0, 227, 0, 0, 0, 124, 0, 0, 0, 168, 0, 0, 0, 137, 0, 0, 0, 69, 0, 0, 0, 63, 0, 0, 0, 220, 0, 0, 0, 5, 0, -0, 0, 203, 0, 0, 0, 65, 0, 0, 0, 60, 0, 0, 0, 200, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 44, 0, 0, 0, 56, 0, 0, 0, 153, 0, 0, 0, 227, 0, 0, 0, 104, 0, 0, 0, 85, 0, 0, 0, 249, 0, 0, 0, 211, 0, 0, 0, 50, 0, 0, 0, 199, 0, 0, 0, 191, 0, 0, 0, 250, 0, 0, 0, 212, 0, 0, 0, 27, 0, 0, 0, 93, 0, 0, 0, 222, 0, 0, 0, 220, 0, 0, 0, 16, 0, 0, 0, 66, 0, 0, 0, 192, 0, 0, 0, 66, 0, 0, 0, 217, 0, 0, 0, 117, 0, 0, 0, 45, 0, 0, 0, 171, 0, 0, 0, 53, 0, 0, 0, 78, 0, 0, 0, 135, 0, 0, 0, 196, 0, 0, 0, 101, 0, 0, 0, 151, 0, -0, 0, 103, 0, 0, 0, 36, 0, 0, 0, 164, 0, 0, 0, 71, 0, 0, 0, 173, 0, 0, 0, 63, 0, 0, 0, 142, 0, 0, 0, 243, 0, 0, 0, 203, 0, 0, 0, 49, 0, 0, 0, 23, 0, 0, 0, 119, 0, 0, 0, 197, 0, 0, 0, 226, 0, 0, 0, 215, 0, 0, 0, 143, 0, 0, 0, 60, 0, 0, 0, 193, 0, 0, 0, 205, 0, 0, 0, 86, 0, 0, 0, 72, 0, 0, 0, 193, 0, 0, 0, 108, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 174, 0, 0, 0, 95, 0, 0, 0, 136, 0, 0, 0, 123, 0, 0, 0, 165, 0, 0, 0, 144, 0, 0, 0, 223, 0, 0, 0, 16, 0, 0, 0, 178, 0, 0, 0, 139, 0, 0, 0, 94, 0, 0, 0, 36, 0, 0, 0, 23, 0, 0, 0, 195, 0, 0, 0, 163, 0, 0, 0, 212, 0, 0, 0, 15, 0, 0, 0, 146, 0, 0, 0, 97, 0, 0, 0, 26, 0, 0, 0, 25, 0, 0, 0, 90, 0, 0, 0, 173, 0, 0, 0, 118, 0, 0, 0, 189, 0, 0, 0, 216, 0, 0, 0, 28, 0, 0, 0, 221, 0, 0, 0, 224, 0, -0, 0, 18, 0, 0, 0, 109, 0, 0, 0, 142, 0, 0, 0, 189, 0, 0, 0, 112, 0, 0, 0, 143, 0, 0, 0, 2, 0, 0, 0, 163, 0, 0, 0, 36, 0, 0, 0, 77, 0, 0, 0, 90, 0, 0, 0, 103, 0, 0, 0, 196, 0, 0, 0, 218, 0, 0, 0, 247, 0, 0, 0, 32, 0, 0, 0, 15, 0, 0, 0, 129, 0, 0, 0, 91, 0, 0, 0, 122, 0, 0, 0, 5, 0, 0, 0, 36, 0, 0, 0, 103, 0, 0, 0, 131, 0, 0, 0, 11, 0, 0, 0, 42, 0, 0, 0, 128, 0, 0, 0, 231, 0, 0, 0, 253, 0, 0, 0, 116, 0, 0, 0, 75, 0, 0, 0, 158, 0, 0, 0, 92, 0, 0, 0, 13, 0, 0, 0, 148, 0, 0, 0, 213, 0, 0, 0, 95, 0, 0, -0, 31, 0, 0, 0, 162, 0, 0, 0, 251, 0, 0, 0, 235, 0, 0, 0, 225, 0, 0, 0, 7, 0, 0, 0, 52, 0, 0, 0, 248, 0, 0, 0, 32, 0, 0, 0, 173, 0, 0, 0, 129, 0, 0, 0, 48, 0, 0, 0, 6, 0, 0, 0, 45, 0, 0, 0, 161, 0, 0, 0, 129, 0, 0, 0, 149, 0, 0, 0, 54, 0, 0, 0, 207, 0, 0, 0, 17, 0, 0, 0, 11, 0, 0, 0, 175, 0, 0, 0, 193, 0, 0, 0, 43, 0, 0, 0, 154, 0, 0, 0, 108, 0, 0, 0, 85, 0, 0, 0, 193, 0, 0, 0, 22, 0, 0, 0, 54, 0, 0, 0, 79, 0, 0, 0, 241, 0, 0, 0, 94, 0, 0, 0, 116, 0, 0, 0, 53, 0, 0, 0, 19, 0, 0, 0, 40, 0, 0, 0, 215, -0, 0, 0, 17, 0, 0, 0, 207, 0, 0, 0, 184, 0, 0, 0, 222, 0, 0, 0, 147, 0, 0, 0, 179, 0, 0, 0, 5, 0, 0, 0, 184, 0, 0, 0, 181, 0, 0, 0, 115, 0, 0, 0, 233, 0, 0, 0, 235, 0, 0, 0, 173, 0, 0, 0, 25, 0, 0, 0, 30, 0, 0, 0, 137, 0, 0, 0, 15, 0, 0, 0, 139, 0, 0, 0, 21, 0, 0, 0, 213, 0, 0, 0, 140, 0, 0, 0, 227, 0, 0, 0, 35, 0, 0, 0, 51, 0, 0, 0, 121, 0, 0, 0, 231, 0, 0, 0, 24, 0, 0, 0, 230, 0, 0, 0, 15, 0, 0, 0, 87, 0, 0, 0, 147, 0, 0, 0, 21, 0, 0, 0, 160, 0, 0, 0, 167, 0, 0, 0, 170, 0, 0, 0, 196, 0, 0, 0, 191, -0, 0, 0, 79, 0, 0, 0, 48, 0, 0, 0, 116, 0, 0, 0, 149, 0, 0, 0, 94, 0, 0, 0, 105, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 69, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, 35, 0, 0, 0, 116, 0, 0, 0, 76, 0, 0, 0, 223, 0, 0, 0, 107, 0, 0, 0, 69, 0, 0, 0, 151, 0, 0, 0, 41, 0, 0, 0, 108, 0, 0, 0, 196, 0, 0, 0, 66, 0, 0, 0, 11, 0, 0, 0, 221, 0, 0, 0, 192, 0, 0, 0, 41, 0, 0, 0, 92, 0, 0, 0, 155, 0, 0, 0, 52, 0, 0, 0, 151, 0, 0, 0, 208, 0, 0, 0, 199, 0, 0, 0, 121, 0, 0, 0, 128, 0, 0, 0, 99, 0, 0, 0, 116, 0, -0, 0, 228, 0, 0, 0, 142, 0, 0, 0, 55, 0, 0, 0, 176, 0, 0, 0, 43, 0, 0, 0, 124, 0, 0, 0, 232, 0, 0, 0, 104, 0, 0, 0, 108, 0, 0, 0, 195, 0, 0, 0, 130, 0, 0, 0, 151, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0, 190, 0, 0, 0, 131, 0, 0, 0, 182, 0, 0, 0, 75, 0, 0, 0, 128, 0, 0, 0, 107, 0, 0, 0, 67, 0, 0, 0, 36, 0, 0, 0, 94, 0, 0, 0, 239, 0, 0, 0, 153, 0, 0, 0, 155, 0, 0, 0, 168, 0, 0, 0, 252, 0, 0, 0, 37, 0, 0, 0, 141, 0, 0, 0, 59, 0, 0, 0, 3, 0, 0, 0, 148, 0, 0, 0, 43, 0, 0, 0, 62, 0, 0, 0, 231, 0, 0, 0, 149, -0, 0, 0, 118, 0, 0, 0, 155, 0, 0, 0, 204, 0, 0, 0, 21, 0, 0, 0, 219, 0, 0, 0, 50, 0, 0, 0, 230, 0, 0, 0, 102, 0, 0, 0, 132, 0, 0, 0, 240, 0, 0, 0, 74, 0, 0, 0, 19, 0, 0, 0, 166, 0, 0, 0, 214, 0, 0, 0, 250, 0, 0, 0, 147, 0, 0, 0, 70, 0, 0, 0, 7, 0, 0, 0, 246, 0, 0, 0, 126, 0, 0, 0, 92, 0, 0, 0, 109, 0, 0, 0, 94, 0, 0, 0, 246, 0, 0, 0, 166, 0, 0, 0, 231, 0, 0, 0, 72, 0, 0, 0, 240, 0, 0, 0, 6, 0, 0, 0, 234, 0, 0, 0, 255, 0, 0, 0, 144, 0, 0, 0, 193, 0, 0, 0, 204, 0, 0, 0, 76, 0, 0, 0, 25, 0, 0, 0, 156, -0, 0, 0, 60, 0, 0, 0, 78, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 80, 0, 0, 0, 227, 0, 0, 0, 7, 0, 0, 0, 21, 0, 0, 0, 89, 0, 0, 0, 242, 0, 0, 0, 139, 0, 0, 0, 129, 0, 0, 0, 242, 0, 0, 0, 243, 0, 0, 0, 211, 0, 0, 0, 108, 0, 0, 0, 153, 0, 0, -0, 140, 0, 0, 0, 112, 0, 0, 0, 103, 0, 0, 0, 236, 0, 0, 0, 204, 0, 0, 0, 238, 0, 0, 0, 158, 0, 0, 0, 89, 0, 0, 0, 69, 0, 0, 0, 89, 0, 0, 0, 125, 0, 0, 0, 71, 0, 0, 0, 117, 0, 0, 0, 105, 0, 0, 0, 245, 0, 0, 0, 36, 0, 0, 0, 147, 0, 0, 0, 93, 0, 0, 0, 106, 0, 0, 0, 79, 0, 0, 0, 27, 0, 0, 0, 190, 0, 0, 0, 107, 0, 0, 0, 48, 0, 0, 0, 207, 0, 0, 0, 117, 0, 0, 0, 70, 0, 0, 0, 227, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 252, 0, 0, 0, 205, 0, 0, 0, 216, 0, 0, 0, 92, 0, 0, 0, 31, 0, 0, 0, 180, 0, 0, 0, 200, 0, -0, 0, 226, 0, 0, 0, 36, 0, 0, 0, 236, 0, 0, 0, 26, 0, 0, 0, 40, 0, 0, 0, 5, 0, 0, 0, 50, 0, 0, 0, 87, 0, 0, 0, 253, 0, 0, 0, 60, 0, 0, 0, 90, 0, 0, 0, 152, 0, 0, 0, 16, 0, 0, 0, 163, 0, 0, 0, 219, 0, 0, 0, 247, 0, 0, 0, 48, 0, 0, 0, 216, 0, 0, 0, 194, 0, 0, 0, 154, 0, 0, 0, 225, 0, 0, 0, 211, 0, 0, 0, 206, 0, 0, 0, 34, 0, 0, 0, 229, 0, 0, 0, 128, 0, 0, 0, 30, 0, 0, 0, 217, 0, 0, 0, 228, 0, 0, 0, 31, 0, 0, 0, 171, 0, 0, 0, 192, 0, 0, 0, 113, 0, 0, 0, 26, 0, 0, 0, 134, 0, 0, 0, 14, 0, 0, 0, 39, 0, -0, 0, 153, 0, 0, 0, 91, 0, 0, 0, 250, 0, 0, 0, 118, 0, 0, 0, 153, 0, 0, 0, 176, 0, 0, 0, 8, 0, 0, 0, 60, 0, 0, 0, 42, 0, 0, 0, 147, 0, 0, 0, 210, 0, 0, 0, 133, 0, 0, 0, 27, 0, 0, 0, 106, 0, 0, 0, 93, 0, 0, 0, 166, 0, 0, 0, 238, 0, 0, 0, 209, 0, 0, 0, 209, 0, 0, 0, 51, 0, 0, 0, 189, 0, 0, 0, 106, 0, 0, 0, 54, 0, 0, 0, 115, 0, 0, 0, 55, 0, 0, 0, 58, 0, 0, 0, 68, 0, 0, 0, 180, 0, 0, 0, 236, 0, 0, 0, 169, 0, 0, 0, 122, 0, 0, 0, 222, 0, 0, 0, 131, 0, 0, 0, 64, 0, 0, 0, 215, 0, 0, 0, 223, 0, 0, 0, 40, -0, 0, 0, 186, 0, 0, 0, 162, 0, 0, 0, 48, 0, 0, 0, 211, 0, 0, 0, 181, 0, 0, 0, 109, 0, 0, 0, 5, 0, 0, 0, 63, 0, 0, 0, 159, 0, 0, 0, 243, 0, 0, 0, 21, 0, 0, 0, 141, 0, 0, 0, 124, 0, 0, 0, 202, 0, 0, 0, 201, 0, 0, 0, 252, 0, 0, 0, 138, 0, 0, 0, 124, 0, 0, 0, 148, 0, 0, 0, 176, 0, 0, 0, 99, 0, 0, 0, 54, 0, 0, 0, 155, 0, 0, 0, 120, 0, 0, 0, 209, 0, 0, 0, 145, 0, 0, 0, 31, 0, 0, 0, 147, 0, 0, 0, 216, 0, 0, 0, 87, 0, 0, 0, 67, 0, 0, 0, 222, 0, 0, 0, 118, 0, 0, 0, 163, 0, 0, 0, 67, 0, 0, 0, 155, 0, 0, 0, -53, 0, 0, 0, 226, 0, 0, 0, 169, 0, 0, 0, 61, 0, 0, 0, 50, 0, 0, 0, 30, 0, 0, 0, 187, 0, 0, 0, 22, 0, 0, 0, 40, 0, 0, 0, 112, 0, 0, 0, 233, 0, 0, 0, 69, 0, 0, 0, 47, 0, 0, 0, 143, 0, 0, 0, 112, 0, 0, 0, 127, 0, 0, 0, 8, 0, 0, 0, 126, 0, 0, 0, 83, 0, 0, 0, 196, 0, 0, 0, 122, 0, 0, 0, 191, 0, 0, 0, 247, 0, 0, 0, 225, 0, 0, 0, 164, 0, 0, 0, 106, 0, 0, 0, 216, 0, 0, 0, 172, 0, 0, 0, 100, 0, 0, 0, 27, 0, 0, 0, 17, 0, 0, 0, 178, 0, 0, 0, 235, 0, 0, 0, 71, 0, 0, 0, 70, 0, 0, 0, 24, 0, 0, 0, 62, 0, 0, 0, -31, 0, 0, 0, 153, 0, 0, 0, 12, 0, 0, 0, 204, 0, 0, 0, 241, 0, 0, 0, 44, 0, 0, 0, 224, 0, 0, 0, 231, 0, 0, 0, 143, 0, 0, 0, 224, 0, 0, 0, 1, 0, 0, 0, 126, 0, 0, 0, 101, 0, 0, 0, 184, 0, 0, 0, 12, 0, 0, 0, 208, 0, 0, 0, 251, 0, 0, 0, 200, 0, 0, 0, 185, 0, 0, 0, 144, 0, 0, 0, 152, 0, 0, 0, 51, 0, 0, 0, 97, 0, 0, 0, 59, 0, 0, 0, 216, 0, 0, 0, 39, 0, 0, 0, 160, 0, 0, 0, 190, 0, 0, 0, 114, 0, 0, 0, 58, 0, 0, 0, 80, 0, 0, 0, 75, 0, 0, 0, 116, 0, 0, 0, 171, 0, 0, 0, 1, 0, 0, 0, 200, 0, 0, 0, 147, 0, 0, 0, -197, 0, 0, 0, 228, 0, 0, 0, 199, 0, 0, 0, 8, 0, 0, 0, 108, 0, 0, 0, 180, 0, 0, 0, 202, 0, 0, 0, 238, 0, 0, 0, 235, 0, 0, 0, 142, 0, 0, 0, 215, 0, 0, 0, 78, 0, 0, 0, 38, 0, 0, 0, 198, 0, 0, 0, 29, 0, 0, 0, 226, 0, 0, 0, 113, 0, 0, 0, 175, 0, 0, 0, 137, 0, 0, 0, 160, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 11, 0, 0, 0, 228, 0, 0, 0, 222, 0, 0, 0, 219, 0, 0, 0, 168, 0, 0, 0, 250, 0, 0, 0, 130, 0, 0, 0, 116, 0, 0, 0, 6, 0, 0, 0, 82, 0, 0, 0, 109, 0, 0, 0, 8, 0, 0, 0, 82, 0, 0, 0, 138, 0, 0, 0, 255, 0, 0, 0, 98, 0, 0, 0, 197, 0, 0, 0, 106, 0, 0, 0, 68, 0, 0, 0, 15, 0, 0, 0, 81, 0, 0, 0, 140, 0, 0, 0, 31, 0, 0, 0, 110, 0, 0, 0, 182, 0, 0, 0, 198, 0, 0, 0, 44, 0, 0, 0, 129, 0, 0, 0, 211, 0, 0, 0, 118, 0, 0, 0, 70, 0, 0, 0, 244, 0, 0, 0, -41, 0, 0, 0, 116, 0, 0, 0, 46, 0, 0, 0, 128, 0, 0, 0, 167, 0, 0, 0, 26, 0, 0, 0, 143, 0, 0, 0, 246, 0, 0, 0, 189, 0, 0, 0, 214, 0, 0, 0, 142, 0, 0, 0, 191, 0, 0, 0, 193, 0, 0, 0, 149, 0, 0, 0, 42, 0, 0, 0, 235, 0, 0, 0, 160, 0, 0, 0, 127, 0, 0, 0, 69, 0, 0, 0, 160, 0, 0, 0, 80, 0, 0, 0, 20, 0, 0, 0, 5, 0, 0, 0, 177, 0, 0, 0, 87, 0, 0, 0, 76, 0, 0, 0, 116, 0, 0, 0, 183, 0, 0, 0, 226, 0, 0, 0, 137, 0, 0, 0, 125, 0, 0, 0, 7, 0, 0, 0, 238, 0, 0, 0, 167, 0, 0, 0, 173, 0, 0, 0, 183, 0, 0, 0, 9, 0, 0, 0, -11, 0, 0, 0, 73, 0, 0, 0, 78, 0, 0, 0, 191, 0, 0, 0, 202, 0, 0, 0, 229, 0, 0, 0, 33, 0, 0, 0, 230, 0, 0, 0, 230, 0, 0, 0, 175, 0, 0, 0, 213, 0, 0, 0, 103, 0, 0, 0, 243, 0, 0, 0, 206, 0, 0, 0, 126, 0, 0, 0, 124, 0, 0, 0, 147, 0, 0, 0, 123, 0, 0, 0, 90, 0, 0, 0, 16, 0, 0, 0, 18, 0, 0, 0, 14, 0, 0, 0, 108, 0, 0, 0, 6, 0, 0, 0, 17, 0, 0, 0, 117, 0, 0, 0, 213, 0, 0, 0, 252, 0, 0, 0, 134, 0, 0, 0, 163, 0, 0, 0, 59, 0, 0, 0, 163, 0, 0, 0, 62, 0, 0, 0, 10, 0, 0, 0, 251, 0, 0, 0, 11, 0, 0, 0, 247, 0, 0, 0, -54, 0, 0, 0, 177, 0, 0, 0, 91, 0, 0, 0, 218, 0, 0, 0, 112, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 167, 0, 0, 0, 218, 0, 0, 0, 136, 0, 0, 0, 143, 0, 0, 0, 132, 0, 0, 0, 168, 0, 0, 0, 188, 0, 0, 0, 28, 0, 0, 0, 57, 0, 0, 0, 184, 0, 0, 0, 101, 0, 0, 0, 243, 0, 0, 0, 77, 0, 0, 0, 96, 0, 0, 0, 150, 0, 0, 0, 157, 0, 0, 0, 49, 0, 0, 0, 244, 0, 0, 0, 162, 0, 0, 0, 190, 0, 0, 0, 129, 0, 0, 0, 185, 0, 0, 0, 165, 0, 0, 0, 89, 0, 0, 0, 158, 0, 0, 0, 186, 0, 0, 0, 7, 0, 0, 0, 190, 0, 0, 0, 116, 0, 0, 0, 88, 0, 0, -0, 216, 0, 0, 0, 235, 0, 0, 0, 197, 0, 0, 0, 159, 0, 0, 0, 61, 0, 0, 0, 209, 0, 0, 0, 244, 0, 0, 0, 174, 0, 0, 0, 206, 0, 0, 0, 83, 0, 0, 0, 223, 0, 0, 0, 79, 0, 0, 0, 199, 0, 0, 0, 42, 0, 0, 0, 137, 0, 0, 0, 77, 0, 0, 0, 41, 0, 0, 0, 216, 0, 0, 0, 242, 0, 0, 0, 170, 0, 0, 0, 233, 0, 0, 0, 14, 0, 0, 0, 247, 0, 0, 0, 46, 0, 0, 0, 95, 0, 0, 0, 157, 0, 0, 0, 138, 0, 0, 0, 91, 0, 0, 0, 9, 0, 0, 0, 237, 0, 0, 0, 201, 0, 0, 0, 36, 0, 0, 0, 34, 0, 0, 0, 244, 0, 0, 0, 15, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, -0, 28, 0, 0, 0, 132, 0, 0, 0, 110, 0, 0, 0, 52, 0, 0, 0, 20, 0, 0, 0, 108, 0, 0, 0, 234, 0, 0, 0, 179, 0, 0, 0, 134, 0, 0, 0, 93, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 152, 0, 0, 0, 97, 0, 0, 0, 232, 0, 0, 0, 106, 0, 0, 0, 210, 0, 0, 0, 129, 0, 0, 0, 73, 0, 0, 0, 37, 0, 0, 0, 213, 0, 0, 0, 91, 0, 0, 0, 24, 0, 0, 0, 199, 0, 0, 0, 53, 0, 0, 0, 82, 0, 0, 0, 81, 0, 0, 0, 164, 0, 0, 0, 70, 0, 0, 0, 173, 0, 0, 0, 24, 0, 0, 0, 13, 0, 0, 0, 201, 0, 0, 0, 95, 0, 0, 0, 24, 0, 0, 0, 145, 0, 0, 0, 59, 0, 0, 0, 180, -0, 0, 0, 192, 0, 0, 0, 96, 0, 0, 0, 89, 0, 0, 0, 141, 0, 0, 0, 102, 0, 0, 0, 3, 0, 0, 0, 27, 0, 0, 0, 121, 0, 0, 0, 83, 0, 0, 0, 110, 0, 0, 0, 36, 0, 0, 0, 174, 0, 0, 0, 87, 0, 0, 0, 217, 0, 0, 0, 88, 0, 0, 0, 9, 0, 0, 0, 133, 0, 0, 0, 72, 0, 0, 0, 162, 0, 0, 0, 211, 0, 0, 0, 181, 0, 0, 0, 226, 0, 0, 0, 77, 0, 0, 0, 17, 0, 0, 0, 130, 0, 0, 0, 230, 0, 0, 0, 134, 0, 0, 0, 60, 0, 0, 0, 233, 0, 0, 0, 177, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 194, 0, 0, 0, 87, 0, 0, 0, 247, 0, 0, 0, 102, 0, 0, 0, 122, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 227, 0, 0, 0, 137, 0, 0, 0, 3, 0, 0, 0, 215, 0, 0, 0, 34, 0, 0, 0, 149, 0, 0, 0, 159, 0, 0, 0, 202, 0, 0, 0, 180, 0, 0, 0, 141, 0, 0, 0, 158, 0, 0, 0, 109, 0, 0, 0, 151, 0, 0, 0, 255, 0, 0, 0, 141, 0, 0, 0, 33, 0, 0, -0, 89, 0, 0, 0, 7, 0, 0, 0, 239, 0, 0, 0, 3, 0, 0, 0, 45, 0, 0, 0, 94, 0, 0, 0, 248, 0, 0, 0, 68, 0, 0, 0, 70, 0, 0, 0, 231, 0, 0, 0, 133, 0, 0, 0, 128, 0, 0, 0, 197, 0, 0, 0, 137, 0, 0, 0, 80, 0, 0, 0, 139, 0, 0, 0, 216, 0, 0, 0, 83, 0, 0, 0, 134, 0, 0, 0, 36, 0, 0, 0, 134, 0, 0, 0, 41, 0, 0, 0, 82, 0, 0, 0, 1, 0, 0, 0, 250, 0, 0, 0, 32, 0, 0, 0, 195, 0, 0, 0, 78, 0, 0, 0, 149, 0, 0, 0, 203, 0, 0, 0, 173, 0, 0, 0, 123, 0, 0, 0, 52, 0, 0, 0, 148, 0, 0, 0, 48, 0, 0, 0, 183, 0, 0, 0, 122, 0, 0, 0, -250, 0, 0, 0, 150, 0, 0, 0, 65, 0, 0, 0, 96, 0, 0, 0, 43, 0, 0, 0, 203, 0, 0, 0, 89, 0, 0, 0, 185, 0, 0, 0, 202, 0, 0, 0, 80, 0, 0, 0, 194, 0, 0, 0, 91, 0, 0, 0, 155, 0, 0, 0, 120, 0, 0, 0, 35, 0, 0, 0, 27, 0, 0, 0, 58, 0, 0, 0, 136, 0, 0, 0, 148, 0, 0, 0, 95, 0, 0, 0, 10, 0, 0, 0, 155, 0, 0, 0, 152, 0, 0, 0, 43, 0, 0, 0, 110, 0, 0, 0, 83, 0, 0, 0, 17, 0, 0, 0, 246, 0, 0, 0, 255, 0, 0, 0, 198, 0, 0, 0]).concat([125, 0, 0, 0, 66, 0, 0, 0, 204, 0, 0, 0, 2, 0, 0, 0, 128, 0, 0, 0, 64, 0, 0, 0, 13, 0, -0, 0, 30, 0, 0, 0, 251, 0, 0, 0, 175, 0, 0, 0, 97, 0, 0, 0, 7, 0, 0, 0, 176, 0, 0, 0, 230, 0, 0, 0, 47, 0, 0, 0, 129, 0, 0, 0, 112, 0, 0, 0, 161, 0, 0, 0, 46, 0, 0, 0, 57, 0, 0, 0, 4, 0, 0, 0, 124, 0, 0, 0, 196, 0, 0, 0, 44, 0, 0, 0, 135, 0, 0, 0, 69, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 105, 0, 0, 0, 151, 0, 0, 0, 172, 0, 0, 0, 109, 0, 0, 0, 44, 0, 0, 0, 16, 0, 0, 0, 66, 0, 0, 0, 124, 0, 0, 0, 59, 0, 0, 0, 21, 0, 0, 0, 112, 0, 0, 0, 96, 0, 0, 0, 14, 0, 0, 0, 17, 0, 0, 0, 109, 0, 0, 0, 58, 0, 0, 0, -155, 0, 0, 0, 24, 0, 0, 0, 128, 0, 0, 0, 94, 0, 0, 0, 219, 0, 0, 0, 5, 0, 0, 0, 189, 0, 0, 0, 198, 0, 0, 0, 183, 0, 0, 0, 60, 0, 0, 0, 194, 0, 0, 0, 64, 0, 0, 0, 77, 0, 0, 0, 93, 0, 0, 0, 206, 0, 0, 0, 151, 0, 0, 0, 138, 0, 0, 0, 52, 0, 0, 0, 21, 0, 0, 0, 171, 0, 0, 0, 40, 0, 0, 0, 93, 0, 0, 0, 16, 0, 0, 0, 240, 0, 0, 0, 55, 0, 0, 0, 12, 0, 0, 0, 204, 0, 0, 0, 22, 0, 0, 0, 250, 0, 0, 0, 31, 0, 0, 0, 51, 0, 0, 0, 13, 0, 0, 0, 25, 0, 0, 0, 249, 0, 0, 0, 53, 0, 0, 0, 170, 0, 0, 0, 89, 0, 0, 0, 26, 0, -0, 0, 12, 0, 0, 0, 92, 0, 0, 0, 6, 0, 0, 0, 252, 0, 0, 0, 106, 0, 0, 0, 11, 0, 0, 0, 151, 0, 0, 0, 83, 0, 0, 0, 54, 0, 0, 0, 252, 0, 0, 0, 42, 0, 0, 0, 165, 0, 0, 0, 90, 0, 0, 0, 155, 0, 0, 0, 48, 0, 0, 0, 239, 0, 0, 0, 35, 0, 0, 0, 175, 0, 0, 0, 57, 0, 0, 0, 93, 0, 0, 0, 154, 0, 0, 0, 107, 0, 0, 0, 117, 0, 0, 0, 87, 0, 0, 0, 72, 0, 0, 0, 11, 0, 0, 0, 38, 0, 0, 0, 220, 0, 0, 0, 118, 0, 0, 0, 59, 0, 0, 0, 252, 0, 0, 0, 249, 0, 0, 0, 156, 0, 0, 0, 63, 0, 0, 0, 137, 0, 0, 0, 11, 0, 0, 0, 98, 0, 0, 0, -83, 0, 0, 0, 175, 0, 0, 0, 131, 0, 0, 0, 1, 0, 0, 0, 46, 0, 0, 0, 188, 0, 0, 0, 106, 0, 0, 0, 198, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 0, 117, 0, 0, 0, 42, 0, 0, 0, 13, 0, 0, 0, 230, 0, 0, 0, 148, 0, 0, 0, 84, 0, 0, 0, 207, 0, 0, 0, 179, 0, 0, 0, 229, 0, 0, 0, 150, 0, 0, 0, 37, 0, 0, 0, 254, 0, 0, 0, 130, 0, 0, 0, 177, 0, 0, 0, 116, 0, 0, 0, 49, 0, 0, 0, 138, 0, 0, 0, 167, 0, 0, 0, 111, 0, 0, 0, 86, 0, 0, 0, 189, 0, 0, 0, 141, 0, 0, 0, 244, 0, 0, 0, 224, 0, 0, 0, 148, 0, 0, 0, 81, 0, 0, 0, 89, 0, 0, 0, -222, 0, 0, 0, 44, 0, 0, 0, 90, 0, 0, 0, 244, 0, 0, 0, 132, 0, 0, 0, 107, 0, 0, 0, 74, 0, 0, 0, 136, 0, 0, 0, 147, 0, 0, 0, 192, 0, 0, 0, 12, 0, 0, 0, 154, 0, 0, 0, 172, 0, 0, 0, 167, 0, 0, 0, 160, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 13, -0, 0, 0, 214, 0, 0, 0, 199, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 0, 16, 0, 0, 0, 173, 0, 0, 0, 199, 0, 0, 0, 8, 0, 0, 0, 92, 0, 0, 0, 135, 0, 0, 0, 135, 0, 0, 0, 147, 0, 0, 0, 152, 0, 0, 0, 24, 0, 0, 0, 184, 0, 0, 0, 211, 0, 0, 0, 156, 0, 0, 0, 172, 0, 0, 0, 90, 0, 0, 0, 61, 0, 0, 0, 197, 0, 0, 0, 117, 0, 0, 0, 248, 0, 0, 0, 73, 0, 0, 0, 50, 0, 0, 0, 20, 0, 0, 0, 204, 0, 0, 0, 81, 0, 0, 0, 150, 0, 0, 0, 36, 0, 0, 0, 101, 0, 0, 0, 156, 0, 0, 0, 93, 0, 0, 0, 240, 0, 0, 0, 55, 0, 0, 0, 4, 0, 0, 0, 240, 0, -0, 0, 52, 0, 0, 0, 105, 0, 0, 0, 42, 0, 0, 0, 240, 0, 0, 0, 165, 0, 0, 0, 100, 0, 0, 0, 202, 0, 0, 0, 222, 0, 0, 0, 43, 0, 0, 0, 91, 0, 0, 0, 21, 0, 0, 0, 16, 0, 0, 0, 210, 0, 0, 0, 171, 0, 0, 0, 6, 0, 0, 0, 221, 0, 0, 0, 196, 0, 0, 0, 176, 0, 0, 0, 182, 0, 0, 0, 91, 0, 0, 0, 193, 0, 0, 0, 23, 0, 0, 0, 223, 0, 0, 0, 143, 0, 0, 0, 2, 0, 0, 0, 189, 0, 0, 0, 89, 0, 0, 0, 61, 0, 0, 0, 191, 0, 0, 0, 92, 0, 0, 0, 49, 0, 0, 0, 68, 0, 0, 0, 44, 0, 0, 0, 50, 0, 0, 0, 148, 0, 0, 0, 4, 0, 0, 0, 96, 0, 0, 0, -132, 0, 0, 0, 15, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 143, 0, 0, 0, 201, 0, 0, 0, 29, 0, 0, 0, 204, 0, 0, 0, 92, 0, 0, 0, 162, 0, 0, 0, 73, 0, 0, 0, 14, 0, 0, 0, 80, 0, 0, 0, 145, 0, 0, 0, 8, 0, 0, 0, 154, 0, 0, 0, 67, 0, 0, 0, 85, 0, 0, 0, 5, 0, 0, 0, 93, 0, 0, 0, 147, 0, 0, 0, 85, 0, 0, 0, 223, 0, 0, 0, 155, 0, 0, 0, 18, 0, 0, 0, 25, 0, 0, 0, 236, 0, 0, 0, 147, 0, 0, 0, 133, 0, 0, 0, 66, 0, 0, 0, 158, 0, 0, 0, 102, 0, 0, 0, 15, 0, 0, 0, 157, 0, 0, 0, 175, 0, 0, 0, 153, 0, 0, 0, 175, -0, 0, 0, 38, 0, 0, 0, 137, 0, 0, 0, 188, 0, 0, 0, 97, 0, 0, 0, 253, 0, 0, 0, 255, 0, 0, 0, 206, 0, 0, 0, 75, 0, 0, 0, 244, 0, 0, 0, 51, 0, 0, 0, 149, 0, 0, 0, 201, 0, 0, 0, 53, 0, 0, 0, 88, 0, 0, 0, 18, 0, 0, 0, 85, 0, 0, 0, 249, 0, 0, 0, 218, 0, 0, 0, 203, 0, 0, 0, 68, 0, 0, 0, 167, 0, 0, 0, 220, 0, 0, 0, 87, 0, 0, 0, 226, 0, 0, 0, 249, 0, 0, 0, 154, 0, 0, 0, 230, 0, 0, 0, 7, 0, 0, 0, 35, 0, 0, 0, 96, 0, 0, 0, 84, 0, 0, 0, 167, 0, 0, 0, 57, 0, 0, 0, 165, 0, 0, 0, 155, 0, 0, 0, 132, 0, 0, 0, 86, -0, 0, 0, 110, 0, 0, 0, 170, 0, 0, 0, 139, 0, 0, 0, 143, 0, 0, 0, 176, 0, 0, 0, 44, 0, 0, 0, 135, 0, 0, 0, 175, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 76, 0, 0, 0, 178, 0, 0, 0, 18, 0, 0, 0, 248, 0, 0, 0, 50, 0, 0, 0, 168, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 73, 0, 0, 0, 50, 0, 0, 0, 186, 0, 0, 0, 31, 0, 0, 0, 93, 0, 0, 0, 68, 0, 0, 0, 142, 0, 0, 0, 68, 0, 0, 0, 122, 0, 0, 0, 220, 0, 0, 0, 17, 0, 0, 0, 251, 0, 0, 0, 57, 0, 0, 0, 8, 0, 0, 0, 87, 0, 0, 0, 135, 0, 0, 0, 165, 0, -0, 0, 18, 0, 0, 0, 66, 0, 0, 0, 147, 0, 0, 0, 14, 0, 0, 0, 23, 0, 0, 0, 180, 0, 0, 0, 174, 0, 0, 0, 114, 0, 0, 0, 89, 0, 0, 0, 208, 0, 0, 0, 170, 0, 0, 0, 168, 0, 0, 0, 22, 0, 0, 0, 139, 0, 0, 0, 99, 0, 0, 0, 17, 0, 0, 0, 179, 0, 0, 0, 67, 0, 0, 0, 4, 0, 0, 0, 218, 0, 0, 0, 12, 0, 0, 0, 168, 0, 0, 0, 183, 0, 0, 0, 104, 0, 0, 0, 221, 0, 0, 0, 78, 0, 0, 0, 84, 0, 0, 0, 231, 0, 0, 0, 175, 0, 0, 0, 93, 0, 0, 0, 93, 0, 0, 0, 5, 0, 0, 0, 118, 0, 0, 0, 54, 0, 0, 0, 236, 0, 0, 0, 13, 0, 0, 0, 109, 0, 0, -0, 124, 0, 0, 0, 130, 0, 0, 0, 50, 0, 0, 0, 56, 0, 0, 0, 85, 0, 0, 0, 87, 0, 0, 0, 116, 0, 0, 0, 91, 0, 0, 0, 125, 0, 0, 0, 195, 0, 0, 0, 196, 0, 0, 0, 251, 0, 0, 0, 6, 0, 0, 0, 41, 0, 0, 0, 240, 0, 0, 0, 19, 0, 0, 0, 85, 0, 0, 0, 84, 0, 0, 0, 198, 0, 0, 0, 167, 0, 0, 0, 220, 0, 0, 0, 76, 0, 0, 0, 159, 0, 0, 0, 152, 0, 0, 0, 73, 0, 0, 0, 32, 0, 0, 0, 168, 0, 0, 0, 195, 0, 0, 0, 141, 0, 0, 0, 250, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, 71, 0, 0, 0, 157, 0, 0, 0, 233, 0, 0, 0, 37, 0, 0, 0, 213, 0, 0, 0, 227, 0, 0, 0, 71, 0, 0, 0, 120, 0, 0, 0, 223, 0, 0, 0, 133, 0, 0, 0, 167, 0, 0, 0, 133, 0, 0, 0, 94, 0, 0, 0, 122, 0, 0, 0, 76, 0, 0, 0, 95, 0, 0, 0, 121, 0, 0, 0, 26, 0, 0, 0, 243, 0, 0, 0, 162, 0, 0, 0, 178, 0, 0, 0, 40, 0, 0, 0, 160, -0, 0, 0, 156, 0, 0, 0, 221, 0, 0, 0, 48, 0, 0, 0, 64, 0, 0, 0, 212, 0, 0, 0, 56, 0, 0, 0, 189, 0, 0, 0, 40, 0, 0, 0, 252, 0, 0, 0, 187, 0, 0, 0, 213, 0, 0, 0, 120, 0, 0, 0, 109, 0, 0, 0, 29, 0, 0, 0, 212, 0, 0, 0, 153, 0, 0, 0, 180, 0, 0, 0, 170, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 122, 0, 0, 0, 27, 0, 0, 0, 216, 0, 0, 0, 254, 0, 0, 0, 180, 0, 0, 0, 153, 0, 0, 0, 185, 0, 0, 0, 204, 0, 0, 0, 231, 0, 0, 0, 196, 0, 0, 0, 211, 0, 0, 0, 58, 0, 0, 0, 115, 0, 0, 0, 131, 0, 0, 0, 65, 0, 0, 0, 92, 0, 0, 0, -64, 0, 0, 0, 215, 0, 0, 0, 45, 0, 0, 0, 85, 0, 0, 0, 38, 0, 0, 0, 225, 0, 0, 0, 123, 0, 0, 0, 95, 0, 0, 0, 229, 0, 0, 0, 220, 0, 0, 0, 63, 0, 0, 0, 125, 0, 0, 0, 161, 0, 0, 0, 167, 0, 0, 0, 38, 0, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 192, 0, 0, 0, 143, 0, 0, 0, 125, 0, 0, 0, 241, 0, 0, 0, 181, 0, 0, 0, 17, 0, 0, 0, 71, 0, 0, 0, 123, 0, 0, 0, 25, 0, 0, 0, 212, 0, 0, 0, 117, 0, 0, 0, 111, 0, 0, 0, 30, 0, 0, 0, 165, 0, 0, 0, 39, 0, 0, 0, 254, 0, 0, 0, 200, 0, 0, 0, 14, 0, 0, 0, 211, 0, 0, 0, -17, 0, 0, 0, 61, 0, 0, 0, 171, 0, 0, 0, 239, 0, 0, 0, 44, 0, 0, 0, 237, 0, 0, 0, 177, 0, 0, 0, 61, 0, 0, 0, 124, 0, 0, 0, 50, 0, 0, 0, 129, 0, 0, 0, 107, 0, 0, 0, 254, 0, 0, 0, 248, 0, 0, 0, 28, 0, 0, 0, 60, 0, 0, 0, 123, 0, 0, 0, 192, 0, 0, 0, 97, 0, 0, 0, 223, 0, 0, 0, 184, 0, 0, 0, 117, 0, 0, 0, 118, 0, 0, 0, 127, 0, 0, 0, 170, 0, 0, 0, 216, 0, 0, 0, 147, 0, 0, 0, 175, 0, 0, 0, 61, 0, 0, 0, 232, 0, 0, 0, 61, 0, 0, 0, 253, 0, 0, 0, 91, 0, 0, 0, 78, 0, 0, 0, 141, 0, 0, 0, 182, 0, 0, 0, 126, 0, 0, -0, 130, 0, 0, 0, 155, 0, 0, 0, 239, 0, 0, 0, 206, 0, 0, 0, 4, 0, 0, 0, 105, 0, 0, 0, 81, 0, 0, 0, 82, 0, 0, 0, 255, 0, 0, 0, 239, 0, 0, 0, 160, 0, 0, 0, 82, 0, 0, 0, 181, 0, 0, 0, 121, 0, 0, 0, 23, 0, 0, 0, 94, 0, 0, 0, 47, 0, 0, 0, 222, 0, 0, 0, 214, 0, 0, 0, 60, 0, 0, 0, 45, 0, 0, 0, 160, 0, 0, 0, 67, 0, 0, 0, 180, 0, 0, 0, 11, 0, 0, 0, 25, 0, 0, 0, 192, 0, 0, 0, 97, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 23, 0, 0, 0, 244, 0, 0, 0, 158, 0, 0, 0, 24, 0, 0, 0, 81, 0, 0, 0, 45, 0, 0, 0, 234, 0, 0, 0, -47, 0, 0, 0, 242, 0, 0, 0, 242, 0, 0, 0, 224, 0, 0, 0, 163, 0, 0, 0, 20, 0, 0, 0, 183, 0, 0, 0, 139, 0, 0, 0, 58, 0, 0, 0, 48, 0, 0, 0, 245, 0, 0, 0, 129, 0, 0, 0, 193, 0, 0, 0, 93, 0, 0, 0, 113, 0, 0, 0, 57, 0, 0, 0, 98, 0, 0, 0, 85, 0, 0, 0, 31, 0, 0, 0, 96, 0, 0, 0, 90, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 138, 0, 0, 0, 118, 0, 0, 0, 108, 0, 0, 0, 219, 0, 0, 0, 77, 0, 0, 0, 10, 0, 0, 0, 91, 0, 0, 0, 114, 0, 0, 0, 157, 0, 0, 0, 89, 0, 0, 0, 110, 0, 0, 0, 99, 0, 0, 0, 99, 0, 0, 0, 24, 0, 0, 0, 124, -0, 0, 0, 227, 0, 0, 0, 250, 0, 0, 0, 226, 0, 0, 0, 219, 0, 0, 0, 161, 0, 0, 0, 141, 0, 0, 0, 244, 0, 0, 0, 165, 0, 0, 0, 215, 0, 0, 0, 22, 0, 0, 0, 178, 0, 0, 0, 208, 0, 0, 0, 179, 0, 0, 0, 63, 0, 0, 0, 57, 0, 0, 0, 206, 0, 0, 0, 96, 0, 0, 0, 9, 0, 0, 0, 108, 0, 0, 0, 245, 0, 0, 0, 118, 0, 0, 0, 23, 0, 0, 0, 36, 0, 0, 0, 128, 0, 0, 0, 58, 0, 0, 0, 150, 0, 0, 0, 199, 0, 0, 0, 148, 0, 0, 0, 46, 0, 0, 0, 247, 0, 0, 0, 107, 0, 0, 0, 239, 0, 0, 0, 181, 0, 0, 0, 5, 0, 0, 0, 150, 0, 0, 0, 239, 0, 0, 0, -211, 0, 0, 0, 123, 0, 0, 0, 81, 0, 0, 0, 218, 0, 0, 0, 5, 0, 0, 0, 68, 0, 0, 0, 103, 0, 0, 0, 188, 0, 0, 0, 7, 0, 0, 0, 33, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 115, 0, 0, 0, 111, 0, 0, 0, 33, 0, 0, 0, 185, 0, 0, 0, 222, 0, 0, 0, 34, 0, -0, 0, 125, 0, 0, 0, 235, 0, 0, 0, 151, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 163, 0, 0, 0, 234, 0, 0, 0, 225, 0, 0, 0, 198, 0, 0, 0, 55, 0, 0, 0, 235, 0, 0, 0, 143, 0, 0, 0, 67, 0, 0, 0, 88, 0, 0, 0, 222, 0, 0, 0, 65, 0, 0, 0, 100, 0, 0, 0, 14, 0, 0, 0, 62, 0, 0, 0, 7, 0, 0, 0, 153, 0, 0, 0, 61, 0, 0, 0, 241, 0, 0, 0, 223, 0, 0, 0, 30, 0, 0, 0, 248, 0, 0, 0, 173, 0, 0, 0, 67, 0, 0, 0, 194, 0, 0, 0, 23, 0, 0, 0, 6, 0, 0, 0, 226, 0, 0, 0, 228, 0, 0, 0, 169, 0, 0, 0, 134, 0, 0, 0, 205, 0, 0, 0, 24, 0, -0, 0, 215, 0, 0, 0, 120, 0, 0, 0, 200, 0, 0, 0, 116, 0, 0, 0, 102, 0, 0, 0, 210, 0, 0, 0, 9, 0, 0, 0, 24, 0, 0, 0, 165, 0, 0, 0, 241, 0, 0, 0, 202, 0, 0, 0, 166, 0, 0, 0, 98, 0, 0, 0, 146, 0, 0, 0, 193, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, 66, 0, 0, 0, 46, 0, 0, 0, 123, 0, 0, 0, 52, 0, 0, 0, 36, 0, 0, 0, 76, 0, 0, 0, 207, 0, 0, 0, 56, 0, 0, 0, 229, 0, 0, 0, 108, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 44, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 36, 0, 0, 0, 56, 0, 0, 0, 173, 0, 0, 0, 36, 0, 0, 0, -126, 0, 0, 0, 25, 0, 0, 0, 240, 0, 0, 0, 108, 0, 0, 0, 249, 0, 0, 0, 49, 0, 0, 0, 244, 0, 0, 0, 53, 0, 0, 0, 17, 0, 0, 0, 246, 0, 0, 0, 70, 0, 0, 0, 51, 0, 0, 0, 58, 0, 0, 0, 35, 0, 0, 0, 89, 0, 0, 0, 32, 0, 0, 0, 11, 0, 0, 0, 161, 0, 0, 0, 8, 0, 0, 0, 25, 0, 0, 0, 173, 0, 0, 0, 57, 0, 0, 0, 84, 0, 0, 0, 234, 0, 0, 0, 62, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0, 182, 0, 0, 0, 226, 0, 0, 0, 210, 0, 0, 0, 188, 0, 0, 0, 77, 0, 0, 0, 252, 0, 0, 0, 156, 0, 0, 0, 240, 0, 0, 0, 19, 0, 0, 0, 22, 0, 0, 0, 34, 0, -0, 0, 63, 0, 0, 0, 185, 0, 0, 0, 210, 0, 0, 0, 17, 0, 0, 0, 134, 0, 0, 0, 144, 0, 0, 0, 85, 0, 0, 0, 206, 0, 0, 0, 60, 0, 0, 0, 196, 0, 0, 0, 11, 0, 0, 0, 75, 0, 0, 0, 98, 0, 0, 0, 153, 0, 0, 0, 55, 0, 0, 0, 132, 0, 0, 0, 63, 0, 0, 0, 116, 0, 0, 0, 162, 0, 0, 0, 249, 0, 0, 0, 206, 0, 0, 0, 226, 0, 0, 0, 11, 0, 0, 0, 15, 0, 0, 0, 42, 0, 0, 0, 61, 0, 0, 0, 163, 0, 0, 0, 227, 0, 0, 0, 219, 0, 0, 0, 90, 0, 0, 0, 157, 0, 0, 0, 147, 0, 0, 0, 204, 0, 0, 0, 165, 0, 0, 0, 239, 0, 0, 0, 130, 0, 0, 0, 145, -0, 0, 0, 29, 0, 0, 0, 230, 0, 0, 0, 108, 0, 0, 0, 104, 0, 0, 0, 163, 0, 0, 0, 100, 0, 0, 0, 23, 0, 0, 0, 155, 0, 0, 0, 139, 0, 0, 0, 200, 0, 0, 0, 58, 0, 0, 0, 97, 0, 0, 0, 230, 0, 0, 0, 157, 0, 0, 0, 198, 0, 0, 0, 237, 0, 0, 0, 123, 0, 0, 0, 3, 0, 0, 0, 82, 0, 0, 0, 38, 0, 0, 0, 157, 0, 0, 0, 58, 0, 0, 0, 179, 0, 0, 0, 19, 0, 0, 0, 204, 0, 0, 0, 138, 0, 0, 0, 253, 0, 0, 0, 44, 0, 0, 0, 26, 0, 0, 0, 29, 0, 0, 0, 237, 0, 0, 0, 19, 0, 0, 0, 208, 0, 0, 0, 85, 0, 0, 0, 87, 0, 0, 0, 14, 0, 0, 0, 26, 0, -0, 0, 234, 0, 0, 0, 191, 0, 0, 0, 253, 0, 0, 0, 74, 0, 0, 0, 60, 0, 0, 0, 142, 0, 0, 0, 236, 0, 0, 0, 41, 0, 0, 0, 126, 0, 0, 0, 119, 0, 0, 0, 119, 0, 0, 0, 18, 0, 0, 0, 153, 0, 0, 0, 215, 0, 0, 0, 132, 0, 0, 0, 249, 0, 0, 0, 85, 0, 0, 0, 127, 0, 0, 0, 241, 0, 0, 0, 139, 0, 0, 0, 180, 0, 0, 0, 210, 0, 0, 0, 149, 0, 0, 0, 163, 0, 0, 0, 141, 0, 0, 0, 240, 0, 0, 0, 138, 0, 0, 0, 167, 0, 0, 0, 235, 0, 0, 0, 130, 0, 0, 0, 75, 0, 0, 0, 44, 0, 0, 0, 40, 0, 0, 0, 244, 0, 0, 0, 58, 0, 0, 0, 246, 0, 0, 0, -222, 0, 0, 0, 10, 0, 0, 0, 224, 0, 0, 0, 65, 0, 0, 0, 68, 0, 0, 0, 35, 0, 0, 0, 248, 0, 0, 0, 63, 0, 0, 0, 3, 0, 0, 0, 100, 0, 0, 0, 159, 0, 0, 0, 195, 0, 0, 0, 85, 0, 0, 0, 76, 0, 0, 0, 198, 0, 0, 0, 193, 0, 0, 0, 148, 0, 0, 0, 28, 0, 0, 0, 36, 0, 0, 0, 93, 0, 0, 0, 95, 0, 0, 0, 146, 0, 0, 0, 69, 0, 0, 0, 150, 0, 0, 0, 87, 0, 0, 0, 55, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 205, 0, 0, 0, 144, 0, 0, 0, 102, 0, 0, 0, 185, 0, 0, 0, 118, 0, 0, 0, 160, 0, 0, 0, 91, 0, 0, 0, 165, 0, 0, 0, 133, 0, 0, 0, 117, 0, 0, 0, 35, 0, 0, 0, 249, 0, 0, 0, 137, 0, 0, 0, 165, 0, 0, 0, 130, 0, 0, 0, 178, 0, 0, 0, 111, 0, 0, 0, 177, 0, 0, 0, 235, 0, 0, 0, 196, 0, 0, 0, 105, 0, 0, 0, 111, 0, 0, 0, 24, 0, 0, 0, 90, 0, 0, 0, 237, 0, 0, 0, 148, 0, 0, 0, 61, -0, 0, 0, 157, 0, 0, 0, 217, 0, 0, 0, 44, 0, 0, 0, 26, 0, 0, 0, 53, 0, 0, 0, 176, 0, 0, 0, 230, 0, 0, 0, 115, 0, 0, 0, 6, 0, 0, 0, 183, 0, 0, 0, 55, 0, 0, 0, 224, 0, 0, 0, 248, 0, 0, 0, 176, 0, 0, 0, 34, 0, 0, 0, 232, 0, 0, 0, 210, 0, 0, 0, 237, 0, 0, 0, 11, 0, 0, 0, 239, 0, 0, 0, 230, 0, 0, 0, 198, 0, 0, 0, 90, 0, 0, 0, 153, 0, 0, 0, 158, 0, 0, 0, 26, 0, 0, 0, 159, 0, 0, 0, 4, 0, 0, 0, 151, 0, 0, 0, 228, 0, 0, 0, 77, 0, 0, 0, 11, 0, 0, 0, 190, 0, 0, 0, 186, 0, 0, 0, 68, 0, 0, 0, 64, 0, 0, 0, 193, -0, 0, 0, 86, 0, 0, 0, 150, 0, 0, 0, 145, 0, 0, 0, 95, 0, 0, 0, 31, 0, 0, 0, 187, 0, 0, 0, 84, 0, 0, 0, 111, 0, 0, 0, 136, 0, 0, 0, 137, 0, 0, 0, 10, 0, 0, 0, 178, 0, 0, 0, 214, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 106, 0, 0, 0, 130, 0, 0, 0, 238, 0, 0, 0, 20, 0, 0, 0, 170, 0, 0, 0, 118, 0, 0, 0, 48, 0, 0, 0, 101, 0, 0, 0, 15, 0, 0, 0, 103, 0, 0, 0, 57, 0, 0, 0, 166, 0, 0, 0, 81, 0, 0, 0, 124, 0, 0, 0, 73, 0, 0, 0, 36, 0, 0, 0, 53, 0, 0, 0, 163, 0, 0, 0, 120, 0, 0, 0, 209, 0, 0, 0, 17, 0, 0, 0, 15, -0, 0, 0, 117, 0, 0, 0, 211, 0, 0, 0, 112, 0, 0, 0, 70, 0, 0, 0, 219, 0, 0, 0, 32, 0, 0, 0, 81, 0, 0, 0, 203, 0, 0, 0, 146, 0, 0, 0, 128, 0, 0, 0, 84, 0, 0, 0, 16, 0, 0, 0, 116, 0, 0, 0, 54, 0, 0, 0, 134, 0, 0, 0, 169, 0, 0, 0, 215, 0, 0, 0, 163, 0, 0, 0, 8, 0, 0, 0, 120, 0, 0, 0, 241, 0, 0, 0, 1, 0, 0, 0, 41, 0, 0, 0, 248, 0, 0, 0, 128, 0, 0, 0, 59, 0, 0, 0, 219, 0, 0, 0, 167, 0, 0, 0, 157, 0, 0, 0, 157, 0, 0, 0, 191, 0, 0, 0, 160, 0, 0, 0, 204, 0, 0, 0, 237, 0, 0, 0, 83, 0, 0, 0, 162, 0, 0, 0, 162, -0, 0, 0, 25, 0, 0, 0, 57, 0, 0, 0, 72, 0, 0, 0, 131, 0, 0, 0, 25, 0, 0, 0, 55, 0, 0, 0, 88, 0, 0, 0, 209, 0, 0, 0, 4, 0, 0, 0, 40, 0, 0, 0, 64, 0, 0, 0, 247, 0, 0, 0, 138, 0, 0, 0, 194, 0, 0, 0, 8, 0, 0, 0, 183, 0, 0, 0, 165, 0, 0, 0, 66, 0, 0, 0, 207, 0, 0, 0, 83, 0, 0, 0, 76, 0, 0, 0, 167, 0, 0, 0, 187, 0, 0, 0, 246, 0, 0, 0, 142, 0, 0, 0, 173, 0, 0, 0, 221, 0, 0, 0, 247, 0, 0, 0, 144, 0, 0, 0, 221, 0, 0, 0, 95, 0, 0, 0, 147, 0, 0, 0, 137, 0, 0, 0, 174, 0, 0, 0, 4, 0, 0, 0, 55, 0, 0, 0, 230, 0, -0, 0, 154, 0, 0, 0, 183, 0, 0, 0, 232, 0, 0, 0, 192, 0, 0, 0, 223, 0, 0, 0, 22, 0, 0, 0, 42, 0, 0, 0, 191, 0, 0, 0, 196, 0, 0, 0, 58, 0, 0, 0, 60, 0, 0, 0, 65, 0, 0, 0, 213, 0, 0, 0, 137, 0, 0, 0, 114, 0, 0, 0, 90, 0, 0, 0, 31, 0, 0, 0, 150, 0, 0, 0, 255, 0, 0, 0, 52, 0, 0, 0, 44, 0, 0, 0, 19, 0, 0, 0, 33, 0, 0, 0, 203, 0, 0, 0, 10, 0, 0, 0, 137, 0, 0, 0, 133, 0, 0, 0, 190, 0, 0, 0, 179, 0, 0, 0, 112, 0, 0, 0, 158, 0, 0, 0, 30, 0, 0, 0, 222, 0, 0, 0, 151, 0, 0, 0, 175, 0, 0, 0, 150, 0, 0, 0, 48, -0, 0, 0, 247, 0, 0, 0, 72, 0, 0, 0, 137, 0, 0, 0, 64, 0, 0, 0, 141, 0, 0, 0, 7, 0, 0, 0, 241, 0, 0, 0, 37, 0, 0, 0, 240, 0, 0, 0, 48, 0, 0, 0, 88, 0, 0, 0, 30, 0, 0, 0, 212, 0, 0, 0, 147, 0, 0, 0, 87, 0, 0, 0, 226, 0, 0, 0, 23, 0, 0, 0, 231, 0, 0, 0, 157, 0, 0, 0, 171, 0, 0, 0, 60, 0, 0, 0, 85, 0, 0, 0, 3, 0, 0, 0, 130, 0, 0, 0, 47, 0, 0, 0, 43, 0, 0, 0, 219, 0, 0, 0, 86, 0, 0, 0, 30, 0, 0, 0, 48, 0, 0, 0, 46, 0, 0, 0, 36, 0, 0, 0, 71, 0, 0, 0, 110, 0, 0, 0, 230, 0, 0, 0, 255, 0, 0, 0, 51, 0, 0, -0, 36, 0, 0, 0, 44, 0, 0, 0, 117, 0, 0, 0, 81, 0, 0, 0, 212, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 6, 0, 0, 0, 217, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 225, 0, 0, 0, 244, 0, 0, 0, 209, 0, 0, 0, 30, 0, 0, 0, 60, 0, 0, 0, 154, 0, 0, 0, 198, -0, 0, 0, 41, 0, 0, 0, 43, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 120, 0, 0, 0, 192, 0, 0, 0, 216, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 45, 0, 0, 0, 158, 0, 0, 0, 169, 0, 0, 0, 201, 0, 0, 0, 121, 0, 0, 0, 87, 0, 0, 0, 171, 0, 0, 0, 36, 0, 0, 0, 145, 0, 0, 0, 146, 0, 0, 0, 25, 0, 0, 0, 105, 0, 0, 0, 251, 0, 0, 0, 161, 0, 0, 0, 156, 0, 0, 0, 166, 0, 0, 0, 117, 0, 0, 0, 73, 0, 0, 0, 125, 0, 0, 0, 96, 0, 0, 0, 115, 0, 0, 0, 64, 0, 0, 0, 66, 0, 0, 0, 196, 0, 0, 0, 19, 0, 0, 0, 10, 0, 0, 0, 149, 0, 0, 0, 121, -0, 0, 0, 30, 0, 0, 0, 4, 0, 0, 0, 131, 0, 0, 0, 148, 0, 0, 0, 153, 0, 0, 0, 155, 0, 0, 0, 30, 0, 0, 0, 12, 0, 0, 0, 232, 0, 0, 0, 31, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 203, 0, 0, 0, 192, 0, 0, 0, 82, 0, 0, 0, 20, 0, 0, 0, 137, 0, 0, 0, 115, 0, 0, 0, 161, 0, 0, 0, 55, 0, 0, 0, 135, 0, 0, 0, 106, 0, 0, 0, 122, 0, 0, 0, 207, 0, 0, 0, 29, 0, 0, 0, 217, 0, 0, 0, 46, 0, 0, 0, 26, 0, 0, 0, 103, 0, 0, 0, 237, 0, 0, 0, 116, 0, 0, 0, 192, 0, 0, 0, 240, 0, 0, 0, 156, 0, 0, 0, 51, 0, 0, 0, 221, 0, 0, 0, 223, -0, 0, 0, 8, 0, 0, 0, 191, 0, 0, 0, 123, 0, 0, 0, 209, 0, 0, 0, 102, 0, 0, 0, 218, 0, 0, 0, 230, 0, 0, 0, 201, 0, 0, 0, 73, 0, 0, 0, 8, 0, 0, 0, 233, 0, 0, 0, 221, 0, 0, 0, 94, 0, 0, 0, 85, 0, 0, 0, 176, 0, 0, 0, 10, 0, 0, 0, 222, 0, 0, 0, 33, 0, 0, 0, 76, 0, 0, 0, 90, 0, 0, 0, 46, 0, 0, 0, 212, 0, 0, 0, 128, 0, 0, 0, 58, 0, 0, 0, 87, 0, 0, 0, 146, 0, 0, 0, 122, 0, 0, 0, 241, 0, 0, 0, 196, 0, 0, 0, 44, 0, 0, 0, 64, 0, 0, 0, 175, 0, 0, 0, 47, 0, 0, 0, 201, 0, 0, 0, 146, 0, 0, 0, 3, 0, 0, 0, 229, 0, -0, 0, 90, 0, 0, 0, 188, 0, 0, 0, 220, 0, 0, 0, 244, 0, 0, 0, 9, 0, 0, 0, 243, 0, 0, 0, 225, 0, 0, 0, 43, 0, 0, 0, 124, 0, 0, 0, 5, 0, 0, 0, 134, 0, 0, 0, 128, 0, 0, 0, 147, 0, 0, 0, 74, 0, 0, 0, 173, 0, 0, 0, 180, 0, 0, 0, 143, 0, 0, 0, 126, 0, 0, 0, 153, 0, 0, 0, 12, 0, 0, 0, 253, 0, 0, 0, 205, 0, 0, 0, 239, 0, 0, 0, 209, 0, 0, 0, 255, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 52, 0, 0, 0, 19, 0, 0, 0, 65, 0, 0, 0, 100, 0, 0, 0, 207, 0, 0, 0, 59, 0, 0, 0, 208, 0, 0, 0, 144, 0, 0, 0, 9, 0, 0, 0, 30, 0, -0, 0, 157, 0, 0, 0, 69, 0, 0, 0, 214, 0, 0, 0, 128, 0, 0, 0, 230, 0, 0, 0, 69, 0, 0, 0, 170, 0, 0, 0, 244, 0, 0, 0, 21, 0, 0, 0, 170, 0, 0, 0, 92, 0, 0, 0, 52, 0, 0, 0, 135, 0, 0, 0, 153, 0, 0, 0, 162, 0, 0, 0, 140, 0, 0, 0, 38, 0, 0, 0, 132, 0, 0, 0, 98, 0, 0, 0, 125, 0, 0, 0, 182, 0, 0, 0, 41, 0, 0, 0, 192, 0, 0, 0, 82, 0, 0, 0, 234, 0, 0, 0, 245, 0, 0, 0, 129, 0, 0, 0, 24, 0, 0, 0, 15, 0, 0, 0, 53, 0, 0, 0, 169, 0, 0, 0, 14, 0, 0, 0, 231, 0, 0, 0, 32, 0, 0, 0, 114, 0, 0, 0, 124, 0, 0, 0, 109, -0, 0, 0, 148, 0, 0, 0, 95, 0, 0, 0, 82, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 227, 0, 0, 0, 241, 0, 0, 0, 178, 0, 0, 0, 176, 0, 0, 0, 54, 0, 0, 0, 70, 0, 0, 0, 15, 0, 0, 0, 174, 0, 0, 0, 146, 0, 0, 0, 232, 0, 0, 0, 112, 0, 0, 0, 157, 0, 0, 0, 110, 0, 0, 0, 121, 0, 0, 0, 177, 0, 0, 0, 173, 0, 0, 0, 55, 0, 0, 0, 169, 0, 0, 0, 95, 0, 0, 0, 192, 0, 0, 0, 222, 0, 0, 0, 3, 0, 0, 0, 21, 0, 0, 0, 85, 0, 0, 0, 55, 0, 0, 0, 198, 0, 0, 0, 28, 0, 0, 0, 39, 0, 0, 0, 28, 0, 0, 0, 109, 0, 0, 0, 20, 0, 0, 0, 79, 0, -0, 0, 202, 0, 0, 0, 164, 0, 0, 0, 196, 0, 0, 0, 136, 0, 0, 0, 37, 0, 0, 0, 70, 0, 0, 0, 57, 0, 0, 0, 252, 0, 0, 0, 90, 0, 0, 0, 229, 0, 0, 0, 254, 0, 0, 0, 41, 0, 0, 0, 17, 0, 0, 0, 105, 0, 0, 0, 245, 0, 0, 0, 114, 0, 0, 0, 132, 0, 0, 0, 77, 0, 0, 0, 120, 0, 0, 0, 159, 0, 0, 0, 148, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 211, 0, 0, 0, 255, 0, 0, 0, 87, 0, 0, 0, 11, 0, 0, 0, 176, 0, 0, 0, 178, 0, 0, 0, 220, 0, 0, 0, 248, 0, 0, 0, 79, 0, 0, 0, 226, 0, 0, 0, 18, 0, 0, 0, 213, 0, 0, 0, 54, 0, 0, 0, 190, 0, 0, 0, 107, 0, 0, 0, 9, 0, 0, 0, 67, 0, 0, 0, 109, 0, 0, 0, 163, 0, 0, 0, 77, 0, 0, 0, 144, 0, 0, 0, 45, 0, 0, 0, 184, 0, 0, 0, 116, 0, 0, 0, 232, 0, 0, 0, 113, 0, 0, 0, 69, 0, 0, 0, 25, 0, 0, 0, 139, 0, 0, 0, 12, 0, 0, 0, 106, 0, -0, 0, 184, 0, 0, 0, 66, 0, 0, 0, 28, 0, 0, 0, 3, 0, 0, 0, 173, 0, 0, 0, 44, 0, 0, 0, 3, 0, 0, 0, 142, 0, 0, 0, 172, 0, 0, 0, 215, 0, 0, 0, 152, 0, 0, 0, 41, 0, 0, 0, 19, 0, 0, 0, 198, 0, 0, 0, 2, 0, 0, 0, 41, 0, 0, 0, 181, 0, 0, 0, 212, 0, 0, 0, 231, 0, 0, 0, 207, 0, 0, 0, 204, 0, 0, 0, 139, 0, 0, 0, 131, 0, 0, 0, 236, 0, 0, 0, 53, 0, 0, 0, 199, 0, 0, 0, 156, 0, 0, 0, 116, 0, 0, 0, 183, 0, 0, 0, 173, 0, 0, 0, 133, 0, 0, 0, 95, 0, 0, 0, 120, 0, 0, 0, 132, 0, 0, 0, 225, 0, 0, 0, 86, 0, 0, 0, 69, 0, -0, 0, 105, 0, 0, 0, 104, 0, 0, 0, 90, 0, 0, 0, 79, 0, 0, 0, 184, 0, 0, 0, 177, 0, 0, 0, 41, 0, 0, 0, 255, 0, 0, 0, 51, 0, 0, 0, 3, 0, 0, 0, 49, 0, 0, 0, 183, 0, 0, 0, 203, 0, 0, 0, 150, 0, 0, 0, 37, 0, 0, 0, 230, 0, 0, 0, 230, 0, 0, 0, 65, 0, 0, 0, 152, 0, 0, 0, 26, 0, 0, 0, 187, 0, 0, 0, 3, 0, 0, 0, 86, 0, 0, 0, 242, 0, 0, 0, 178, 0, 0, 0, 145, 0, 0, 0, 52, 0, 0, 0, 44, 0, 0, 0, 108, 0, 0, 0, 247, 0, 0, 0, 102, 0, 0, 0, 164, 0, 0, 0, 98, 0, 0, 0, 107, 0, 0, 0, 57, 0, 0, 0, 179, 0, 0, 0, 186, 0, -0, 0, 101, 0, 0, 0, 211, 0, 0, 0, 28, 0, 0, 0, 248, 0, 0, 0, 17, 0, 0, 0, 170, 0, 0, 0, 190, 0, 0, 0, 220, 0, 0, 0, 128, 0, 0, 0, 89, 0, 0, 0, 135, 0, 0, 0, 245, 0, 0, 0, 123, 0, 0, 0, 229, 0, 0, 0, 227, 0, 0, 0, 179, 0, 0, 0, 62, 0, 0, 0, 57, 0, 0, 0, 218, 0, 0, 0, 190, 0, 0, 0, 136, 0, 0, 0, 9, 0, 0, 0, 139, 0, 0, 0, 241, 0, 0, 0, 160, 0, 0, 0, 245, 0, 0, 0, 220, 0, 0, 0, 41, 0, 0, 0, 180, 0, 0, 0, 226, 0, 0, 0, 7, 0, 0, 0, 198, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 137, 0, 0, 0, 23, -0, 0, 0, 81, 0, 0, 0, 212, 0, 0, 0, 187, 0, 0, 0, 212, 0, 0, 0, 34, 0, 0, 0, 234, 0, 0, 0, 126, 0, 0, 0, 125, 0, 0, 0, 124, 0, 0, 0, 36, 0, 0, 0, 234, 0, 0, 0, 242, 0, 0, 0, 232, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 149, 0, 0, 0, 6, 0, 0, 0, 218, 0, 0, 0, 124, 0, 0, 0, 164, 0, 0, 0, 12, 0, 0, 0, 244, 0, 0, 0, 186, 0, 0, 0, 110, 0, 0, 0, 225, 0, 0, 0, 137, 0, 0, 0, 181, 0, 0, 0, 89, 0, 0, 0, 202, 0, 0, 0, 241, 0, 0, 0, 192, 0, 0, 0, 41, 0, 0, 0, 54, 0, 0, 0, 9, 0, 0, 0, 68, 0, 0, 0, 226, 0, 0, 0, 127, -0, 0, 0, 209, 0, 0, 0, 99, 0, 0, 0, 21, 0, 0, 0, 153, 0, 0, 0, 234, 0, 0, 0, 37, 0, 0, 0, 207, 0, 0, 0, 12, 0, 0, 0, 157, 0, 0, 0, 192, 0, 0, 0, 68, 0, 0, 0, 111, 0, 0, 0, 29, 0, 0, 0, 134, 0, 0, 0, 78, 0, 0, 0, 207, 0, 0, 0, 247, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 18, 0, 0, 0, 251, 0, 0, 0, 25, 0, 0, 0, 251, 0, 0, 0, 224, 0, 0, 0, 237, 0, 0, 0, 16, 0, 0, 0, 200, 0, 0, 0, 226, 0, 0, 0, 245, 0, 0, 0, 117, 0, 0, 0, 177, 0, 0, 0, 51, 0, 0, 0, 192, 0, 0, 0, 150, 0, 0, 0, 13, -0, 0, 0, 251, 0, 0, 0, 21, 0, 0, 0, 108, 0, 0, 0, 13, 0, 0, 0, 7, 0, 0, 0, 95, 0, 0, 0, 5, 0, 0, 0, 105, 0, 0, 0, 62, 0, 0, 0, 71, 0, 0, 0, 151, 0, 0, 0, 44, 0, 0, 0, 175, 0, 0, 0, 82, 0, 0, 0, 124, 0, 0, 0, 120, 0, 0, 0, 131, 0, 0, 0, 173, 0, 0, 0, 27, 0, 0, 0, 57, 0, 0, 0, 130, 0, 0, 0, 47, 0, 0, 0, 2, 0, 0, 0, 111, 0, 0, 0, 71, 0, 0, 0, 219, 0, 0, 0, 42, 0, 0, 0, 176, 0, 0, 0, 225, 0, 0, 0, 145, 0, 0, 0, 153, 0, 0, 0, 85, 0, 0, 0, 184, 0, 0, 0, 153, 0, 0, 0, 58, 0, 0, 0, 160, 0, 0, 0, 68, 0, 0, -0, 17, 0, 0, 0, 81, 0, 0, 0, 163, 120, 89, 19, 202, 77, 235, 117, 171, 216, 65, 65, 77, 10, 112, 0, 152, 232, 121, 119, 121, 64, 199, 140, 115, 254, 111, 43, 238, 108, 3, 82, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 15, 10, 5, 0, 14, 9, 4, 3, 13, 8, 7, 2, 12, 11, 6, 1, 1, 2, 3, 0, 6, 7, 4, 5, 11, 8, 9, 10, 12, 13, 14, 15, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 12, 8, 4, 0, 13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3, 15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0, 3, 3, 3, -3, 7, 7, 7, 7, 11, 11, 11, 11, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31, 26, 0, 0, 0, 213, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 96, 0, 0, 0, 45, 0, 0, 0, 86, 0, 0, 0, 201, 0, 0, 0, 178, 0, 0, 0, 167, 0, 0, 0, 37, 0, 0, 0, 149, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 92, 0, 0, 0, 220, 0, 0, 0, 214, 0, 0, 0, 253, 0, 0, 0, 49, 0, 0, 0, 226, -0, 0, 0, 164, 0, 0, 0, 192, 0, 0, 0, 254, 0, 0, 0, 83, 0, 0, 0, 110, 0, 0, 0, 205, 0, 0, 0, 211, 0, 0, 0, 54, 0, 0, 0, 105, 0, 0, 0, 33, 0, 0, 0, 88, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, -0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 0, 0, 0, 221, 0, 0, 0, -183, 0, 0, 0, 165, 0, 0, 0, 179, 0, 0, 0, 138, 0, 0, 0, 222, 0, 0, 0, 109, 0, 0, 0, 245, 0, 0, 0, 82, 0, 0, 0, 81, 0, 0, 0, 119, 0, 0, 0, 128, 0, 0, 0, 159, 0, 0, 0, 240, 0, 0, 0, 32, 0, 0, 0, 125, 0, 0, 0, 227, 0, 0, 0, 171, 0, 0, 0, 100, 0, 0, 0, 142, 0, 0, 0, 78, 0, 0, 0, 234, 0, 0, 0, 102, 0, 0, 0, 101, 0, 0, 0, 118, 0, 0, 0, 139, 0, 0, 0, 215, 0, 0, 0, 15, 0, 0, 0, 95, 0, 0, 0, 135, 0, 0, 0, 103, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 97, 109, 98, 105, 103, 117, 111, 117, 115, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 46, 42, 115, 0, 0, 0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 80, 79, 83, 73, 88, 76, 89, 95, 67, 79, 82, 82, 69, 67, 84, 0, 115, 116, 100, 58, 58, 98, 97, 100, 95, 97, 108, 108, 111, 99, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 105, 110, 32, 117, 115, 101, 32, 98, 121, 116, 101, 115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, -0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, 115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 109, 97, 120, 32, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, 115, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 120, 181, 1, 0, 6, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 181, 1, 0, 6, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 116, 57, 101, 120, 99, 101, 112, 116, 105, 111, 110, 0, 0, 0, 0, 83, 116, 57, 98, 97, 100, 95, 97, 108, 108, 111, 99, 0, 0, 0, 0, 83, 116, 50, 48, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 181, 1, 0, 0, 0, +F([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, +32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107, 111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 114, 101, 113, 117, 105, 114, 101, 115, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 36, 64, 0, 0, 0, 0, 0, 0, 89, 64, 0, 0, 0, 0, 0, 136, 195, 64, 0, 0, 0, 0, 132, 215, 151, 65, 0, 128, 224, 55, 121, 195, 65, 67, 23, 110, 5, 181, 181, 184, 147, 70, 245, 249, 63, 233, 3, 79, 56, 77, 50, 29, 48, 249, 72, 119, 130, 90, 60, 191, 115, 127, 221, 79, 21, 117, 16, 182, 1, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 111, 112, 116, 105, 111, 110, 32, 100, 111, 101, +115, 110, 39, 116, 32, 116, 97, 107, 101, 32, 97, 110, 32, 97, 114, 103, 117, 109, 101, 110, 116, 32, 45, 45, 32, 37, 46, 42, 115, 0, 27, 0, 0, 0, 19, 0, 0, 0, 44, 0, 0, 0, 10, 0, 0, 0, 163, 0, 0, 0, 229, 0, 0, 0, 156, 0, 0, 0, 237, 0, 0, 0, 167, 0, 0, 0, 41, 0, 0, 0, 99, 0, 0, 0, 8, 0, 0, 0, 93, 0, 0, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 0, 0, 235, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, +0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 19, 0, 0, 0, 44, 0, 0, 0, 10, 0, 0, 0, 163, 0, 0, 0, 229, 0, 0, 0, 156, 0, 0, 0, 237, 0, 0, 0, 167, 0, 0, 0, 41, 0, 0, 0, 99, 0, 0, 0, 8, 0, 0, 0, 93, 0, 0, 0, 33, 0, 0, 0, 6, 0, 0, 0, 33, 0, 0, 0, 235, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, +0, 0, 0, 255, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 211, 0, 0, 0, 245, 0, 0, 0, 92, 0, 0, 0, 26, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 88, 0, 0, 0, 214, 0, 0, 0, 156, 0, 0, 0, 247, 0, 0, 0, 162, 0, 0, 0, 222, 0, 0, 0, 249, 0, 0, 0, 222, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 237, 0, 0, 0, 211, 0, 0, 0, 245, 0, 0, 0, 92, 0, 0, 0, 26, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 88, 0, 0, 0, 214, 0, 0, 0, 156, 0, 0, 0, 247, 0, 0, 0, 162, 0, 0, 0, 222, 0, 0, 0, 249, 0, 0, 0, 222, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 106, 9, 230, 103, 243, 188, 201, +8, 187, 103, 174, 133, 132, 202, 167, 59, 60, 110, 243, 114, 254, 148, 248, 43, 165, 79, 245, 58, 95, 29, 54, 241, 81, 14, 82, 127, 173, 230, 130, 209, 155, 5, 104, 140, 43, 62, 108, 31, 31, 131, 217, 171, 251, 65, 189, 107, 91, 224, 205, 25, 19, 126, 33, 121, 106, 9, 230, 103, 187, 103, 174, 133, 60, 110, 243, 114, 165, 79, 245, 58, 81, 14, 82, 127, 155, 5, 104, 140, 31, 131, 217, 171, 91, 224, 205, 25, 106, 9, 230, 103, 243, 188, 201, 8, 187, 103, 174, 133, 132, 202, 167, 59, 60, 110, 243, 114, +254, 148, 248, 43, 165, 79, 245, 58, 95, 29, 54, 241, 81, 14, 82, 127, 173, 230, 130, 209, 155, 5, 104, 140, 43, 62, 108, 31, 31, 131, 217, 171, 251, 65, 189, 107, 91, 224, 205, 25, 19, 126, 33, 121, 106, 9, 230, 103, 187, 103, 174, 133, 60, 110, 243, 114, 165, 79, 245, 58, 81, 14, 82, 127, 155, 5, 104, 140, 31, 131, 217, 171, 91, 224, 205, 25, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +63, 117, 110, 107, 110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 115, 0, 0, 0, 0, 117, 110, 107, 110, 111, 119, 110, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 99, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 176, 0, 0, 0, 160, 0, 0, 0, 14, 0, 0, 0, 74, 0, 0, 0, 39, 0, 0, 0, 27, 0, 0, 0, 238, 0, 0, 0, 196, 0, 0, 0, 120, 0, 0, 0, 228, 0, 0, 0, 47, 0, 0, 0, 173, 0, 0, 0, 6, 0, 0, 0, 24, 0, 0, 0, 67, 0, 0, 0, 47, 0, 0, 0, 167, 0, 0, 0, 215, 0, 0, 0, 251, 0, 0, 0, +61, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 77, 0, 0, 0, 43, 0, 0, 0, 11, 0, 0, 0, 223, 0, 0, 0, 193, 0, 0, 0, 79, 0, 0, 0, 128, 0, 0, 0, 36, 0, 0, 0, 131, 0, 0, 0, 43, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 0, 0, 0, 120, 0, 0, 0, 89, 0, 0, 0, 19, 0, 0, 0, 202, 0, 0, 0, 77, 0, 0, 0, 235, 0, 0, 0, 117, 0, 0, 0, 171, 0, 0, 0, 216, 0, 0, 0, +65, 0, 0, 0, 65, 0, 0, 0, 77, 0, 0, 0, 10, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 232, 0, 0, 0, 121, 0, 0, 0, 119, 0, 0, 0, 121, 0, 0, 0, 64, 0, 0, 0, 199, 0, 0, 0, 140, 0, 0, 0, 115, 0, 0, 0, 254, 0, 0, 0, 111, 0, 0, 0, 43, 0, 0, 0, 238, 0, 0, 0, 108, 0, 0, 0, 3, 0, 0, 0, 82, 0, 0, 0, 89, 0, 0, 0, 241, 0, 0, 0, 178, 0, 0, 0, 38, 0, 0, 0, 148, 0, 0, 0, 155, 0, 0, 0, 214, 0, 0, 0, 235, 0, 0, 0, 86, 0, 0, 0, 177, 0, 0, 0, 131, 0, 0, 0, 130, 0, 0, 0, 154, 0, 0, 0, 20, 0, 0, 0, 224, 0, 0, 0, +0, 0, 0, 0, 48, 0, 0, 0, 209, 0, 0, 0, 243, 0, 0, 0, 238, 0, 0, 0, 242, 0, 0, 0, 128, 0, 0, 0, 142, 0, 0, 0, 25, 0, 0, 0, 231, 0, 0, 0, 252, 0, 0, 0, 223, 0, 0, 0, 86, 0, 0, 0, 220, 0, 0, 0, 217, 0, 0, 0, 6, 0, 0, 0, 36, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 26, 213, 37, 143, +96, 45, 86, 201, 178, 167, 37, 149, 96, 199, 44, 105, 92, 220, 214, 253, 49, 226, 164, 192, 254, 83, 110, 205, 211, 54, 105, 33, 163, 221, 183, 165, 179, 138, 222, 109, 245, 82, 81, 119, 128, 159, 240, 32, 125, 227, 171, 100, 142, 78, 234, 102, 101, 118, 139, 215, 15, 95, 135, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 213, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 96, 0, 0, 0, 45, 0, 0, 0, 86, 0, 0, 0, 201, 0, 0, 0, 178, 0, 0, 0, 167, 0, 0, 0, 37, 0, 0, 0, 149, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 92, 0, 0, 0, 220, 0, 0, 0, 214, 0, 0, 0, 253, 0, 0, 0, 49, 0, 0, 0, 226, 0, 0, 0, 164, 0, 0, 0, 192, 0, 0, 0, 254, 0, 0, 0, 83, 0, 0, 0, 110, 0, 0, 0, 205, 0, 0, 0, 211, 0, 0, 0, 54, 0, 0, 0, 105, 0, 0, 0, 33, 0, 0, 0, 88, 0, 0, 0, 102, +0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 14, 0, 0, 0, 206, 0, 0, 0, 67, 0, 0, 0, 40, 0, 0, 0, 78, 0, 0, 0, 161, 0, +0, 0, 197, 0, 0, 0, 131, 0, 0, 0, 95, 0, 0, 0, 164, 0, 0, 0, 215, 0, 0, 0, 21, 0, 0, 0, 69, 0, 0, 0, 142, 0, 0, 0, 13, 0, 0, 0, 8, 0, 0, 0, 172, 0, 0, 0, 231, 0, 0, 0, 51, 0, 0, 0, 24, 0, 0, 0, 125, 0, 0, 0, 59, 0, 0, 0, 4, 0, 0, 0, 61, 0, 0, 0, 108, 0, 0, 0, 4, 0, 0, 0, 90, 0, 0, 0, 159, 0, 0, 0, 76, 0, 0, 0, 56, 0, 0, 0, 171, 0, 0, 0, 54, 0, 0, 0, 201, 0, 0, 0, 163, 0, 0, 0, 248, 0, 0, 0, 106, 0, 0, 0, 174, 0, 0, 0, 70, 0, 0, 0, 95, 0, 0, 0, 14, 0, 0, 0, 86, 0, 0, 0, 81, 0, 0, 0, 56, 0, 0, 0, 100, +0, 0, 0, 81, 0, 0, 0, 15, 0, 0, 0, 57, 0, 0, 0, 151, 0, 0, 0, 86, 0, 0, 0, 31, 0, 0, 0, 162, 0, 0, 0, 201, 0, 0, 0, 232, 0, 0, 0, 94, 0, 0, 0, 162, 0, 0, 0, 29, 0, 0, 0, 194, 0, 0, 0, 41, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0, 243, 0, 0, 0, 205, 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 92, 0, 0, 0, 226, 0, 0, 0, 248, 0, 0, 0, 211, 0, 0, 0, 95, 0, 0, 0, 72, 0, 0, 0, 98, 0, 0, 0, 172, 0, 0, 0, 134, 0, 0, 0, 72, 0, 0, 0, 98, 0, 0, 0, 129, 0, 0, 0, 25, 0, 0, 0, 152, 0, 0, 0, 67, 0, 0, 0, 99, 0, 0, 0, 58, 0, 0, +0, 200, 0, 0, 0, 218, 0, 0, 0, 62, 0, 0, 0, 116, 0, 0, 0, 174, 0, 0, 0, 244, 0, 0, 0, 31, 0, 0, 0, 73, 0, 0, 0, 143, 0, 0, 0, 146, 0, 0, 0, 34, 0, 0, 0, 74, 0, 0, 0, 156, 0, 0, 0, 174, 0, 0, 0, 103, 0, 0, 0, 212, 0, 0, 0, 180, 0, 0, 0, 245, 0, 0, 0, 120, 0, 0, 0, 72, 0, 0, 0, 104, 0, 0, 0, 195, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 103, 0, 0, 0, 23, 0, 0, 0, 236, 0, 0, 0, 22, 0, 0, 0, 159, 0, 0, 0, 247, 0, 0, 0, 158, 0, 0, 0, 38, 0, 0, 0, 96, 0, 0, 0, 142, 0, 0, 0, 161, 0, 0, +0, 38, 0, 0, 0, 161, 0, 0, 0, 171, 0, 0, 0, 105, 0, 0, 0, 238, 0, 0, 0, 119, 0, 0, 0, 209, 0, 0, 0, 177, 0, 0, 0, 103, 0, 0, 0, 18, 0, 0, 0, 112, 0, 0, 0, 248, 0, 0, 0, 201, 0, 0, 0, 196, 0, 0, 0, 87, 0, 0, 0, 166, 0, 0, 0, 58, 0, 0, 0, 73, 0, 0, 0, 71, 0, 0, 0, 21, 0, 0, 0, 206, 0, 0, 0, 147, 0, 0, 0, 193, 0, 0, 0, 158, 0, 0, 0, 115, 0, 0, 0, 26, 0, 0, 0, 249, 0, 0, 0, 32, 0, 0, 0, 53, 0, 0, 0, 122, 0, 0, 0, 184, 0, 0, 0, 212, 0, 0, 0, 37, 0, 0, 0, 131, 0, 0, 0, 70, 0, 0, 0, 241, 0, 0, 0, 207, 0, +0, 0, 86, 0, 0, 0, 219, 0, 0, 0, 168, 0, 0, 0, 61, 0, 0, 0, 32, 0, 0, 0, 47, 0, 0, 0, 17, 0, 0, 0, 50, 0, 0, 0, 202, 0, 0, 0, 97, 0, 0, 0, 171, 0, 0, 0, 56, 0, 0, 0, 223, 0, 0, 0, 240, 0, 0, 0, 15, 0, 0, 0, 47, 0, 0, 0, 234, 0, 0, 0, 50, 0, 0, 0, 40, 0, 0, 0, 242, 0, 0, 0, 76, 0, 0, 0, 108, 0, 0, 0, 113, 0, 0, 0, 213, 0, 0, 0, 128, 0, 0, 0, 133, 0, 0, 0, 184, 0, 0, 0, 14, 0, 0, 0, 71, 0, 0, 0, 225, 0, 0, 0, 149, 0, 0, 0, 21, 0, 0, 0, 203, 0, 0, 0, 39, 0, 0, 0, 232, 0, 0, 0, 208, 0, 0, 0, 71, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 132, 0, 0, 0, 165, 0, 0, 0, 8, 0, 0, 0, 188, 0, 0, 0, 253, 0, 0, 0, 135, 0, 0, 0, 59, 0, 0, 0, 153, 0, 0, 0, 139, 0, 0, 0, 105, 0, 0, 0, 128, 0, 0, 0, 123, 0, 0, 0, 198, 0, 0, 0, 58, 0, 0, 0, 235, 0, 0, 0, 147, 0, 0, +0, 207, 0, 0, 0, 78, 0, 0, 0, 248, 0, 0, 0, 92, 0, 0, 0, 45, 0, 0, 0, 134, 0, 0, 0, 66, 0, 0, 0, 182, 0, 0, 0, 113, 0, 0, 0, 215, 0, 0, 0, 151, 0, 0, 0, 95, 0, 0, 0, 225, 0, 0, 0, 66, 0, 0, 0, 103, 0, 0, 0, 180, 0, 0, 0, 185, 0, 0, 0, 55, 0, 0, 0, 252, 0, 0, 0, 169, 0, 0, 0, 91, 0, 0, 0, 47, 0, 0, 0, 30, 0, 0, 0, 147, 0, 0, 0, 228, 0, 0, 0, 30, 0, 0, 0, 98, 0, 0, 0, 252, 0, 0, 0, 60, 0, 0, 0, 120, 0, 0, 0, 129, 0, 0, 0, 143, 0, 0, 0, 243, 0, 0, 0, 138, 0, 0, 0, 102, 0, 0, 0, 9, 0, 0, 0, 111, 0, 0, +0, 173, 0, 0, 0, 110, 0, 0, 0, 121, 0, 0, 0, 115, 0, 0, 0, 229, 0, 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 211, 0, 0, 0, 33, 0, 0, 0, 248, 0, 0, 0, 249, 0, 0, 0, 40, 0, 0, 0, 108, 0, 0, 0, 109, 0, 0, 0, 89, 0, 0, 0, 178, 0, 0, 0, 89, 0, 0, 0, 116, 0, 0, 0, 35, 0, 0, 0, 191, 0, 0, 0, 231, 0, 0, 0, 51, 0, 0, 0, 141, 0, 0, 0, 87, 0, 0, 0, 9, 0, 0, 0, 145, 0, 0, 0, 156, 0, 0, 0, 36, 0, 0, 0, 8, 0, 0, 0, 21, 0, 0, 0, 43, 0, 0, 0, 226, 0, 0, 0, 184, 0, 0, 0, 238, 0, 0, 0, 58, 0, 0, 0, 229, 0, 0, 0, +39, 0, 0, 0, 6, 0, 0, 0, 134, 0, 0, 0, 164, 0, 0, 0, 35, 0, 0, 0, 235, 0, 0, 0, 39, 0, 0, 0, 103, 0, 0, 0, 193, 0, 0, 0, 55, 0, 0, 0, 171, 0, 0, 0, 122, 0, 0, 0, 216, 0, 0, 0, 39, 0, 0, 0, 156, 0, 0, 0, 7, 0, 0, 0, 142, 0, 0, 0, 255, 0, 0, 0, 17, 0, 0, 0, 106, 0, 0, 0, 176, 0, 0, 0, 120, 0, 0, 0, 110, 0, 0, 0, 173, 0, 0, 0, 58, 0, 0, 0, 46, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 159, 0, 0, 0, 114, 0, 0, 0, 195, 0, 0, 0, 127, 0, 0, 0, 130, 0, 0, 0, 242, 0, 0, 0, 150, 0, 0, 0, 150, 0, 0, 0, 112, 0, 0, +0, 129, 0, 0, 0, 107, 0, 0, 0, 136, 0, 0, 0, 232, 0, 0, 0, 30, 0, 0, 0, 199, 0, 0, 0, 119, 0, 0, 0, 150, 0, 0, 0, 14, 0, 0, 0, 161, 0, 0, 0, 169, 0, 0, 0, 82, 0, 0, 0, 224, 0, 0, 0, 216, 0, 0, 0, 14, 0, 0, 0, 97, 0, 0, 0, 158, 0, 0, 0, 121, 0, 0, 0, 45, 0, 0, 0, 149, 0, 0, 0, 156, 0, 0, 0, 141, 0, 0, 0, 150, 0, 0, 0, 224, 0, 0, 0, 6, 0, 0, 0, 64, 0, 0, 0, 93, 0, 0, 0, 135, 0, 0, 0, 40, 0, 0, 0, 95, 0, 0, 0, 152, 0, 0, 0, 112, 0, 0, 0, 241, 0, 0, 0, 121, 0, 0, 0, 123, 0, 0, 0, 237, 0, 0, 0, 79, 0, +0, 0, 68, 0, 0, 0, 178, 0, 0, 0, 231, 0, 0, 0, 8, 0, 0, 0, 13, 0, 0, 0, 194, 0, 0, 0, 8, 0, 0, 0, 18, 0, 0, 0, 210, 0, 0, 0, 159, 0, 0, 0, 223, 0, 0, 0, 205, 0, 0, 0, 147, 0, 0, 0, 32, 0, 0, 0, 138, 0, 0, 0, 207, 0, 0, 0, 51, 0, 0, 0, 202, 0, 0, 0, 109, 0, 0, 0, 137, 0, 0, 0, 185, 0, 0, 0, 119, 0, 0, 0, 200, 0, 0, 0, 147, 0, 0, 0, 27, 0, 0, 0, 78, 0, 0, 0, 96, 0, 0, 0, 38, 0, 0, 0, 79, 0, 0, 0, 126, 0, 0, 0, 151, 0, 0, 0, 246, 0, 0, 0, 64, 0, 0, 0, 221, 0, 0, 0, 79, 0, 0, 0, 252, 0, 0, 0, 82, 0, +0, 0, 120, 0, 0, 0, 249, 0, 0, 0, 144, 0, 0, 0, 49, 0, 0, 0, 3, 0, 0, 0, 230, 0, 0, 0, 125, 0, 0, 0, 86, 0, 0, 0, 57, 0, 0, 0, 11, 0, 0, 0, 29, 0, 0, 0, 86, 0, 0, 0, 130, 0, 0, 0, 133, 0, 0, 0, 249, 0, 0, 0, 26, 0, 0, 0, 66, 0, 0, 0, 23, 0, 0, 0, 105, 0, 0, 0, 108, 0, 0, 0, 207, 0, 0, 0, 57, 0, 0, 0, 105, 0, 0, 0, 210, 0, 0, 0, 6, 0, 0, 0, 58, 0, 0, 0, 79, 0, 0, 0, 57, 0, 0, 0, 45, 0, 0, 0, 249, 0, 0, 0, 56, 0, 0, 0, 64, 0, 0, 0, 140, 0, 0, 0, 76, 0, 0, 0, 231, 0, 0, 0, 5, 0, 0, 0, 18, 0, 0, 0, 180, +0, 0, 0, 120, 0, 0, 0, 139, 0, 0, 0, 248, 0, 0, 0, 192, 0, 0, 0, 236, 0, 0, 0, 147, 0, 0, 0, 222, 0, 0, 0, 122, 0, 0, 0, 107, 0, 0, 0, 206, 0, 0, 0, 44, 0, 0, 0, 225, 0, 0, 0, 14, 0, 0, 0, 169, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, +0, 0, 164, 0, 0, 0, 60, 0, 0, 0, 176, 0, 0, 0, 15, 0, 0, 0, 122, 0, 0, 0, 81, 0, 0, 0, 241, 0, 0, 0, 120, 0, 0, 0, 214, 0, 0, 0, 217, 0, 0, 0, 106, 0, 0, 0, 253, 0, 0, 0, 70, 0, 0, 0, 232, 0, 0, 0, 184, 0, 0, 0, 168, 0, 0, 0, 121, 0, 0, 0, 29, 0, 0, 0, 135, 0, 0, 0, 249, 0, 0, 0, 144, 0, 0, 0, 242, 0, 0, 0, 156, 0, 0, 0, 19, 0, 0, 0, 41, 0, 0, 0, 248, 0, 0, 0, 11, 0, 0, 0, 32, 0, 0, 0, 100, 0, 0, 0, 250, 0, 0, 0, 5, 0, 0, 0, 38, 0, 0, 0, 9, 0, 0, 0, 218, 0, 0, 0, 23, 0, 0, 0, 175, 0, 0, 0, 149, 0, +0, 0, 214, 0, 0, 0, 251, 0, 0, 0, 106, 0, 0, 0, 25, 0, 0, 0, 13, 0, 0, 0, 110, 0, 0, 0, 94, 0, 0, 0, 18, 0, 0, 0, 241, 0, 0, 0, 153, 0, 0, 0, 76, 0, 0, 0, 170, 0, 0, 0, 168, 0, 0, 0, 111, 0, 0, 0, 121, 0, 0, 0, 134, 0, 0, 0, 244, 0, 0, 0, 114, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 249, 0, 0, 0, 234, 0, 0, 0, 158, 0, 0, 0, 25, 0, 0, 0, 61, 0, 0, 0, 135, 0, 0, 0, 221, 0, 0, 0, 207, 0, 0, 0, 240, 0, 0, 0, 91, 0, 0, 0, 73, 0, 0, 0, 162, 0, 0, 0, 93, 0, 0, 0, 64, 0, 0, 0, 122, 0, 0, 0, 35, 0, +0, 0, 38, 0, 0, 0, 164, 0, 0, 0, 122, 0, 0, 0, 131, 0, 0, 0, 138, 0, 0, 0, 183, 0, 0, 0, 139, 0, 0, 0, 210, 0, 0, 0, 26, 0, 0, 0, 191, 0, 0, 0, 234, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, 8, 0, 0, 0, 95, 0, 0, 0, 123, 0, 0, 0, 169, 0, 0, 0, 177, 0, 0, 0, 190, 0, 0, 0, 157, 0, 0, 0, 55, 0, 0, 0, 252, 0, 0, 0, 134, 0, 0, 0, 75, 0, 0, 0, 8, 0, 0, 0, 238, 0, 0, 0, 231, 0, 0, 0, 160, 0, 0, 0, 253, 0, 0, 0, 33, 0, 0, 0, 69, 0, 0, 0, 9, 0, 0, 0, 52, 0, 0, 0, 193, 0, 0, 0, 97, 0, 0, 0, 50, 0, 0, 0, 35, 0, 0, +0, 252, 0, 0, 0, 155, 0, 0, 0, 85, 0, 0, 0, 72, 0, 0, 0, 83, 0, 0, 0, 153, 0, 0, 0, 247, 0, 0, 0, 99, 0, 0, 0, 208, 0, 0, 0, 153, 0, 0, 0, 206, 0, 0, 0, 1, 0, 0, 0, 224, 0, 0, 0, 159, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 71, 0, 0, 0, 252, 0, 0, 0, 171, 0, 0, 0, 90, 0, 0, 0, 23, 0, 0, 0, 240, 0, 0, 0, 133, 0, 0, 0, 86, 0, 0, 0, 58, 0, 0, 0, 48, 0, 0, 0, 134, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 75, 0, 0, 0, 142, 0, 0, 0, 68, 0, 0, 0, 116, 0, 0, 0, 58, 0, 0, 0, 110, 0, 0, 0, 2, 0, 0, 0, 241, 0, 0, 0, +50, 0, 0, 0, 143, 0, 0, 0, 159, 0, 0, 0, 63, 0, 0, 0, 8, 0, 0, 0, 53, 0, 0, 0, 233, 0, 0, 0, 202, 0, 0, 0, 22, 0, 0, 0, 95, 0, 0, 0, 110, 0, 0, 0, 28, 0, 0, 0, 89, 0, 0, 0, 28, 0, 0, 0, 101, 0, 0, 0, 93, 0, 0, 0, 52, 0, 0, 0, 164, 0, 0, 0, 9, 0, 0, 0, 205, 0, 0, 0, 19, 0, 0, 0, 156, 0, 0, 0, 112, 0, 0, 0, 125, 0, 0, 0, 177, 0, 0, 0, 42, 0, 0, 0, 197, 0, 0, 0, 136, 0, 0, 0, 175, 0, 0, 0, 11, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 159, 0, 0, 0, 52, 0, 0, 0, 141, 0, 0, 0, 214, 0, 0, 0, 183, 0, 0, 0, 127, +0, 0, 0, 234, 0, 0, 0, 120, 0, 0, 0, 101, 0, 0, 0, 141, 0, 0, 0, 119, 0, 0, 0, 86, 0, 0, 0, 165, 0, 0, 0, 194, 0, 0, 0, 12, 0, 0, 0, 221, 0, 0, 0, 188, 0, 0, 0, 184, 0, 0, 0, 32, 0, 0, 0, 109, 0, 0, 0, 87, 0, 0, 0, 97, 0, 0, 0, 181, 0, 0, 0, 251, 0, 0, 0, 120, 0, 0, 0, 181, 0, 0, 0, 212, 0, 0, 0, 73, 0, 0, 0, 84, 0, 0, 0, 144, 0, 0, 0, 38, 0, 0, 0, 193, 0, 0, 0, 203, 0, 0, 0, 233, 0, 0, 0, 230, 0, 0, 0, 191, 0, 0, 0, 236, 0, 0, 0, 29, 0, 0, 0, 78, 0, 0, 0, 237, 0, 0, 0, 7, 0, 0, 0, 126, 0, 0, 0, +94, 0, 0, 0, 199, 0, 0, 0, 246, 0, 0, 0, 108, 0, 0, 0, 86, 0, 0, 0, 49, 0, 0, 0, 32, 0, 0, 0, 20, 0, 0, 0, 14, 0, 0, 0, 168, 0, 0, 0, 217, 0, 0, 0, 39, 0, 0, 0, 193, 0, 0, 0, 154, 0, 0, 0, 61, 0, 0, 0, 27, 0, 0, 0, 125, 0, 0, 0, 14, 0, 0, 0, 38, 0, 0, 0, 211, 0, 0, 0, 129, 0, 0, 0, 170, 0, 0, 0, 235, 0, 0, 0, 245, 0, 0, 0, 107, 0, 0, 0, 121, 0, 0, 0, 2, 0, 0, 0, 241, 0, 0, 0, 81, 0, 0, 0, 92, 0, 0, 0, 117, 0, 0, 0, 85, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 52, 0, 0, 0, 205, 0, 0, 0, 130, 0, 0, 0, 60, 0, 0, 0, 51, 0, 0, 0, 9, 0, 0, 0, 84, 0, 0, 0, 210, 0, 0, 0, 97, 0, 0, 0, 57, 0, 0, 0, 48, 0, 0, 0, 155, 0, 0, 0, 253, 0, 0, 0, 239, 0, 0, 0, 33, 0, 0, 0, 38, 0, 0, 0, 212, 0, 0, 0, 112, 0, 0, 0, 250, 0, 0, 0, 238, 0, 0, 0, 249, 0, 0, +0, 49, 0, 0, 0, 51, 0, 0, 0, 115, 0, 0, 0, 132, 0, 0, 0, 208, 0, 0, 0, 179, 0, 0, 0, 129, 0, 0, 0, 191, 0, 0, 0, 236, 0, 0, 0, 46, 0, 0, 0, 232, 0, 0, 0, 147, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 247, 0, 0, 0, 156, 0, 0, 0, 184, 0, 0, 0, 116, 0, 0, 0, 224, 0, 0, 0, 230, 0, 0, 0, 73, 0, 0, 0, 72, 0, 0, 0, 77, 0, 0, 0, 77, 0, 0, 0, 72, 0, 0, 0, 182, 0, 0, 0, 25, 0, 0, 0, 161, 0, 0, 0, 64, 0, 0, 0, 183, 0, 0, 0, 217, 0, 0, 0, 50, 0, 0, 0, 65, 0, 0, 0, 124, 0, 0, 0, 130, 0, 0, 0, 55, 0, 0, +0, 161, 0, 0, 0, 45, 0, 0, 0, 220, 0, 0, 0, 210, 0, 0, 0, 84, 0, 0, 0, 104, 0, 0, 0, 43, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 213, 0, 0, 0, 199, 0, 0, 0, 81, 0, 0, 0, 145, 0, 0, 0, 29, 0, 0, 0, 225, 0, 0, 0, 42, 0, 0, 0, 75, 0, 0, 0, 196, 0, 0, 0, 71, 0, 0, 0, 241, 0, 0, 0, 188, 0, 0, 0, 122, 0, 0, 0, 179, 0, 0, 0, 203, 0, 0, 0, 200, 0, 0, 0, 182, 0, 0, 0, 124, 0, 0, 0, 172, 0, 0, 0, 144, 0, 0, 0, 5, 0, 0, 0, 253, 0, 0, 0, 243, 0, 0, 0, 249, 0, 0, 0, 82, 0, 0, 0, 58, 0, 0, 0, 17, 0, 0, 0, 107, 0, 0, +0, 61, 0, 0, 0, 193, 0, 0, 0, 39, 0, 0, 0, 243, 0, 0, 0, 89, 0, 0, 0, 67, 0, 0, 0, 149, 0, 0, 0, 144, 0, 0, 0, 197, 0, 0, 0, 150, 0, 0, 0, 121, 0, 0, 0, 245, 0, 0, 0, 244, 0, 0, 0, 149, 0, 0, 0, 101, 0, 0, 0, 41, 0, 0, 0, 6, 0, 0, 0, 156, 0, 0, 0, 81, 0, 0, 0, 5, 0, 0, 0, 24, 0, 0, 0, 218, 0, 0, 0, 184, 0, 0, 0, 46, 0, 0, 0, 121, 0, 0, 0, 126, 0, 0, 0, 105, 0, 0, 0, 89, 0, 0, 0, 113, 0, 0, 0, 1, 0, 0, 0, 235, 0, 0, 0, 26, 0, 0, 0, 21, 0, 0, 0, 6, 0, 0, 0, 73, 0, 0, 0, 182, 0, 0, 0, 138, 0, 0, 0, +60, 0, 0, 0, 234, 0, 0, 0, 47, 0, 0, 0, 52, 0, 0, 0, 32, 0, 0, 0, 20, 0, 0, 0, 195, 0, 0, 0, 170, 0, 0, 0, 214, 0, 0, 0, 175, 0, 0, 0, 44, 0, 0, 0, 62, 0, 0, 0, 189, 0, 0, 0, 101, 0, 0, 0, 32, 0, 0, 0, 226, 0, 0, 0, 77, 0, 0, 0, 75, 0, 0, 0, 59, 0, 0, 0, 235, 0, 0, 0, 159, 0, 0, 0, 74, 0, 0, 0, 195, 0, 0, 0, 173, 0, 0, 0, 164, 0, 0, 0, 59, 0, 0, 0, 96, 0, 0, 0, 188, 0, 0, 0, 88, 0, 0, 0, 230, 0, 0, 0, 192, 0, 0, 0, 149, 0, 0, 0, 42, 0, 0, 0, 42, 0, 0, 0, 129, 0, 0, 0, 154, 0, 0, 0, 122, 0, 0, 0, +243, 0, 0, 0, 210, 0, 0, 0, 6, 0, 0, 0, 190, 0, 0, 0, 72, 0, 0, 0, 188, 0, 0, 0, 12, 0, 0, 0, 197, 0, 0, 0, 70, 0, 0, 0, 224, 0, 0, 0, 106, 0, 0, 0, 212, 0, 0, 0, 172, 0, 0, 0, 15, 0, 0, 0, 217, 0, 0, 0, 204, 0, 0, 0, 130, 0, 0, 0, 52, 0, 0, 0, 44, 0, 0, 0, 175, 0, 0, 0, 219, 0, 0, 0, 31, 0, 0, 0, 247, 0, 0, 0, 23, 0, 0, 0, 19, 0, 0, 0, 189, 0, 0, 0, 251, 0, 0, 0, 188, 0, 0, 0, 210, 0, 0, 0, 236, 0, 0, 0, 69, 0, 0, 0, 179, 0, 0, 0, 21, 0, 0, 0, 49, 0, 0, 0, 233, 0, 0, 0, 175, 0, 0, 0, 130, 0, 0, +0, 132, 0, 0, 0, 61, 0, 0, 0, 40, 0, 0, 0, 198, 0, 0, 0, 252, 0, 0, 0, 17, 0, 0, 0, 245, 0, 0, 0, 65, 0, 0, 0, 181, 0, 0, 0, 139, 0, 0, 0, 211, 0, 0, 0, 18, 0, 0, 0, 118, 0, 0, 0, 82, 0, 0, 0, 231, 0, 0, 0, 26, 0, 0, 0, 60, 0, 0, 0, 78, 0, 0, 0, 54, 0, 0, 0, 17, 0, 0, 0, 7, 0, 0, 0, 162, 0, 0, 0, 21, 0, 0, 0, 32, 0, 0, 0, 81, 0, 0, 0, 196, 0, 0, 0, 42, 0, 0, 0, 195, 0, 0, 0, 98, 0, 0, 0, 139, 0, 0, 0, 94, 0, 0, 0, 127, 0, 0, 0, 166, 0, 0, 0, 15, 0, 0, 0, 249, 0, 0, 0, 69, 0, 0, 0, 133, 0, 0, 0, 108, +0, 0, 0, 17, 0, 0, 0, 134, 0, 0, 0, 183, 0, 0, 0, 126, 0, 0, 0, 229, 0, 0, 0, 215, 0, 0, 0, 249, 0, 0, 0, 195, 0, 0, 0, 145, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 214, 0, 0, 0, 222, 0, 0, 0, 41, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, +0, 185, 0, 0, 0, 2, 0, 0, 0, 89, 0, 0, 0, 203, 0, 0, 0, 38, 0, 0, 0, 196, 0, 0, 0, 186, 0, 0, 0, 153, 0, 0, 0, 177, 0, 0, 0, 151, 0, 0, 0, 47, 0, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, 0, 38, 0, 0, 0, 79, 0, 0, 0, 82, 0, 0, 0, 235, 0, 0, 0, 71, 0, 0, 0, 27, 0, 0, 0, 137, 0, 0, 0, 139, 0, 0, 0, 36, 0, 0, 0, 192, 0, 0, 0, 19, 0, 0, 0, 125, 0, 0, 0, 213, 0, 0, 0, 32, 0, 0, 0, 91, 0, 0, 0, 128, 0, 0, 0, 166, 0, 0, 0, 128, 0, 0, 0, 32, 0, 0, 0, 149, 0, 0, 0, 195, 0, 0, 0, 233, 0, 0, 0, 159, 0, 0, +0, 142, 0, 0, 0, 135, 0, 0, 0, 158, 0, 0, 0, 30, 0, 0, 0, 158, 0, 0, 0, 122, 0, 0, 0, 199, 0, 0, 0, 204, 0, 0, 0, 117, 0, 0, 0, 108, 0, 0, 0, 165, 0, 0, 0, 241, 0, 0, 0, 145, 0, 0, 0, 26, 0, 0, 0, 168, 0, 0, 0, 1, 0, 0, 0, 44, 0, 0, 0, 171, 0, 0, 0, 118, 0, 0, 0, 169, 0, 0, 0, 89, 0, 0, 0, 222, 0, 0, 0, 201, 0, 0, 0, 177, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 170, 0, 0, 0, 53, 0, 0, 0, 20, 0, 0, 0, 106, 0, 0, 0, 212, 0, 0, 0, 181, 0, 0, 0, 52, 0, 0, 0, 130, 0, 0, 0, 113, 0, 0, 0, 210, 0, +0, 0, 74, 0, 0, 0, 93, 0, 0, 0, 154, 0, 0, 0, 31, 0, 0, 0, 83, 0, 0, 0, 38, 0, 0, 0, 60, 0, 0, 0, 229, 0, 0, 0, 142, 0, 0, 0, 141, 0, 0, 0, 51, 0, 0, 0, 127, 0, 0, 0, 255, 0, 0, 0, 169, 0, 0, 0, 213, 0, 0, 0, 23, 0, 0, 0, 137, 0, 0, 0, 175, 0, 0, 0, 246, 0, 0, 0, 164, 0, 0, 0, 100, 0, 0, 0, 213, 0, 0, 0, 16, 0, 0, 0, 224, 0, 0, 0, 29, 0, 0, 0, 173, 0, 0, 0, 239, 0, 0, 0, 68, 0, 0, 0, 189, 0, 0, 0, 218, 0, 0, 0, 131, 0, 0, 0, 172, 0, 0, 0, 122, 0, 0, 0, 168, 0, 0, 0, 240, 0, 0, 0, 28, 0, 0, 0, 7, +0, 0, 0, 249, 0, 0, 0, 195, 0, 0, 0, 67, 0, 0, 0, 108, 0, 0, 0, 63, 0, 0, 0, 183, 0, 0, 0, 211, 0, 0, 0, 135, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 115, 0, 0, 0, 100, 0, 0, 0, 29, 0, 0, 0, 73, 0, 0, 0, 19, 0, 0, 0, 47, 0, 0, 0, 113, 0, 0, 0, 236, 0, 0, 0, 105, 0, 0, 0, 135, 0, 0, 0, 208, 0, 0, 0, 66, 0, 0, 0, 238, 0, 0, 0, 19, 0, 0, 0, 236, 0, 0, 0, 227, 0, 0, 0, 237, 0, 0, 0, 86, 0, 0, 0, 123, 0, 0, 0, 191, 0, 0, 0, 189, 0, 0, 0, 140, 0, 0, 0, 47, 0, 0, 0, 125, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 40, +0, 0, 0, 236, 0, 0, 0, 142, 0, 0, 0, 118, 0, 0, 0, 47, 0, 0, 0, 111, 0, 0, 0, 8, 0, 0, 0, 34, 0, 0, 0, 245, 0, 0, 0, 95, 0, 0, 0, 77, 0, 0, 0, 21, 0, 0, 0, 239, 0, 0, 0, 252, 0, 0, 0, 78, 0, 0, 0, 87, 0, 0, 0, 3, 0, 0, 0, 54, 0, 0, 0, 137, 0, 0, 0, 240, 0, 0, 0, 235, 0, 0, 0, 91, 0, 0, 0, 145, 0, 0, 0, 214, 0, 0, 0, 226, 0, 0, 0, 202, 0, 0, 0, 1, 0, 0, 0, 165, 0, 0, 0, 238, 0, 0, 0, 82, 0, 0, 0, 236, 0, 0, 0, 160, 0, 0, 0, 60, 0, 0, 0, 143, 0, 0, 0, 51, 0, 0, 0, 144, 0, 0, 0, 90, 0, 0, 0, 148, 0, +0, 0, 114, 0, 0, 0, 138, 0, 0, 0, 75, 0, 0, 0, 231, 0, 0, 0, 56, 0, 0, 0, 188, 0, 0, 0, 218, 0, 0, 0, 194, 0, 0, 0, 176, 0, 0, 0, 133, 0, 0, 0, 225, 0, 0, 0, 74, 0, 0, 0, 254, 0, 0, 0, 45, 0, 0, 0, 68, 0, 0, 0, 132, 0, 0, 0, 203, 0, 0, 0, 32, 0, 0, 0, 107, 0, 0, 0, 45, 0, 0, 0, 191, 0, 0, 0, 17, 0, 0, 0, 156, 0, 0, 0, 215, 0, 0, 0, 190, 0, 0, 0, 211, 0, 0, 0, 62, 0, 0, 0, 95, 0, 0, 0, 191, 0, 0, 0, 104, 0, 0, 0, 188, 0, 0, 0, 168, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 137, 0, 0, 0, 40, 0, 0, 0, 34, 0, +0, 0, 106, 0, 0, 0, 120, 0, 0, 0, 170, 0, 0, 0, 41, 0, 0, 0, 3, 0, 0, 0, 200, 0, 0, 0, 116, 0, 0, 0, 149, 0, 0, 0, 3, 0, 0, 0, 62, 0, 0, 0, 220, 0, 0, 0, 189, 0, 0, 0, 7, 0, 0, 0, 19, 0, 0, 0, 168, 0, 0, 0, 162, 0, 0, 0, 32, 0, 0, 0, 45, 0, 0, 0, 179, 0, 0, 0, 24, 0, 0, 0, 112, 0, 0, 0, 66, 0, 0, 0, 253, 0, 0, 0, 122, 0, 0, 0, 196, 0, 0, 0, 215, 0, 0, 0, 73, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 50, 0, 0, 0, 43, 0, 0, 0, 92, 0, 0, 0, 147, 0, 0, 0, 84, 0, 0, 0, 50, 0, 0, 0, 232, 0, 0, 0, 87, 0, 0, 0, 84, 0, 0, 0, 26, 0, 0, 0, 139, 0, 0, 0, 51, 0, 0, 0, 96, 0, 0, 0, 101, 0, 0, 0, 211, 0, 0, 0, 103, 0, 0, 0, 164, 0, 0, 0, 193, 0, 0, 0, 38, 0, 0, 0, 196, 0, 0, 0, 164, 0, 0, 0, 52, 0, 0, 0, 31, 0, 0, 0, 155, 0, 0, 0, 167, +0, 0, 0, 169, 0, 0, 0, 244, 0, 0, 0, 217, 0, 0, 0, 79, 0, 0, 0, 91, 0, 0, 0, 70, 0, 0, 0, 141, 0, 0, 0, 176, 0, 0, 0, 51, 0, 0, 0, 84, 0, 0, 0, 38, 0, 0, 0, 91, 0, 0, 0, 104, 0, 0, 0, 223, 0, 0, 0, 187, 0, 0, 0, 197, 0, 0, 0, 236, 0, 0, 0, 194, 0, 0, 0, 249, 0, 0, 0, 60, 0, 0, 0, 90, 0, 0, 0, 55, 0, 0, 0, 193, 0, 0, 0, 142, 0, 0, 0, 39, 0, 0, 0, 71, 0, 0, 0, 170, 0, 0, 0, 73, 0, 0, 0, 90, 0, 0, 0, 248, 0, 0, 0, 251, 0, 0, 0, 104, 0, 0, 0, 4, 0, 0, 0, 35, 0, 0, 0, 209, 0, 0, 0, 235, 0, 0, 0, 64, 0, +0, 0, 101, 0, 0, 0, 165, 0, 0, 0, 17, 0, 0, 0, 132, 0, 0, 0, 138, 0, 0, 0, 103, 0, 0, 0, 157, 0, 0, 0, 158, 0, 0, 0, 209, 0, 0, 0, 68, 0, 0, 0, 104, 0, 0, 0, 122, 0, 0, 0, 52, 0, 0, 0, 225, 0, 0, 0, 159, 0, 0, 0, 163, 0, 0, 0, 84, 0, 0, 0, 205, 0, 0, 0, 7, 0, 0, 0, 202, 0, 0, 0, 121, 0, 0, 0, 31, 0, 0, 0, 84, 0, 0, 0, 47, 0, 0, 0, 19, 0, 0, 0, 112, 0, 0, 0, 78, 0, 0, 0, 238, 0, 0, 0, 162, 0, 0, 0, 250, 0, 0, 0, 231, 0, 0, 0, 93, 0, 0, 0, 54, 0, 0, 0, 236, 0, 0, 0, 84, 0, 0, 0, 248, 0, 0, 0, 206, +0, 0, 0, 228, 0, 0, 0, 133, 0, 0, 0, 223, 0, 0, 0, 246, 0, 0, 0, 111, 0, 0, 0, 29, 0, 0, 0, 144, 0, 0, 0, 8, 0, 0, 0, 188, 0, 0, 0, 232, 0, 0, 0, 192, 0, 0, 0, 146, 0, 0, 0, 45, 0, 0, 0, 67, 0, 0, 0, 107, 0, 0, 0, 146, 0, 0, 0, 169, 0, 0, 0, 142, 0, 0, 0, 171, 0, 0, 0, 10, 0, 0, 0, 46, 0, 0, 0, 28, 0, 0, 0, 30, 0, 0, 0, 100, 0, 0, 0, 35, 0, 0, 0, 159, 0, 0, 0, 44, 0, 0, 0, 167, 0, 0, 0, 214, 0, 0, 0, 46, 0, 0, 0, 213, 0, 0, 0, 204, 0, 0, 0, 212, 0, 0, 0, 203, 0, 0, 0, 90, 0, 0, 0, 59, 0, 0, 0, 167, +0, 0, 0, 249, 0, 0, 0, 70, 0, 0, 0, 3, 0, 0, 0, 29, 0, 0, 0, 173, 0, 0, 0, 43, 0, 0, 0, 52, 0, 0, 0, 49, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 8, 0, 0, 0, 130, 0, 0, 0, 20, 0, 0, 0, 196, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 240, 0, 0, 0, 227, 0, 0, 0, 85, 0, 0, 0, 67, 0, 0, 0, 49, 0, 0, 0, 96, 0, 0, 0, 214, 0, 0, 0, 221, 0, 0, 0, 120, 0, 0, 0, 230, 0, 0, 0, 212, 0, 0, 0, 34, 0, 0, 0, 66, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 177, 0, 0, 0, 106, 0, 0, 0, 99, 0, 0, 0, 226, 0, 0, +0, 146, 0, 0, 0, 89, 0, 0, 0, 209, 0, 0, 0, 26, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 41, 0, 0, 0, 201, 0, 0, 0, 193, 0, 0, 0, 246, 0, 0, 0, 111, 0, 0, 0, 122, 0, 0, 0, 197, 0, 0, 0, 60, 0, 0, 0, 95, 0, 0, 0, 101, 0, 0, 0, 39, 0, 0, 0, 79, 0, 0, 0, 208, 0, 0, 0, 114, 0, 0, 0, 177, 0, 0, 0, 17, 0, 0, 0, 20, 0, 0, 0, 39, 0, 0, 0, 21, 0, 0, 0, 148, 0, 0, 0, 72, 0, 0, 0, 129, 0, 0, 0, 126, 0, 0, 0, 116, 0, 0, 0, 216, 0, 0, 0, 50, 0, 0, 0, 213, 0, 0, 0, 209, 0, 0, 0, 17, 0, 0, 0, 40, 0, 0, 0, +96, 0, 0, 0, 99, 0, 0, 0, 54, 0, 0, 0, 50, 0, 0, 0, 55, 0, 0, 0, 181, 0, 0, 0, 19, 0, 0, 0, 28, 0, 0, 0, 160, 0, 0, 0, 55, 0, 0, 0, 227, 0, 0, 0, 116, 0, 0, 0, 241, 0, 0, 0, 37, 0, 0, 0, 78, 0, 0, 0, 17, 0, 0, 0, 150, 0, 0, 0, 103, 0, 0, 0, 230, 0, 0, 0, 28, 0, 0, 0, 194, 0, 0, 0, 178, 0, 0, 0, 83, 0, 0, 0, 226, 0, 0, 0, 218, 0, 0, 0, 133, 0, 0, 0, 238, 0, 0, 0, 178, 0, 0, 0, 159, 0, 0, 0, 89, 0, 0, 0, 243, 0, 0, 0, 186, 0, 0, 0, 189, 0, 0, 0, 250, 0, 0, 0, 207, 0, 0, 0, 110, 0, 0, 0, 249, 0, 0, +0, 218, 0, 0, 0, 164, 0, 0, 0, 179, 0, 0, 0, 2, 0, 0, 0, 143, 0, 0, 0, 100, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 148, 0, 0, 0, 242, 0, 0, 0, 100, 0, 0, 0, 84, 0, 0, 0, 71, 0, 0, 0, 55, 0, 0, 0, 7, 0, 0, 0, 64, 0, 0, 0, 138, 0, 0, 0, 32, 0, +0, 0, 186, 0, 0, 0, 74, 0, 0, 0, 85, 0, 0, 0, 215, 0, 0, 0, 63, 0, 0, 0, 71, 0, 0, 0, 186, 0, 0, 0, 37, 0, 0, 0, 35, 0, 0, 0, 20, 0, 0, 0, 176, 0, 0, 0, 44, 0, 0, 0, 232, 0, 0, 0, 85, 0, 0, 0, 168, 0, 0, 0, 166, 0, 0, 0, 239, 0, 0, 0, 81, 0, 0, 0, 189, 0, 0, 0, 111, 0, 0, 0, 106, 0, 0, 0, 113, 0, 0, 0, 214, 0, 0, 0, 22, 0, 0, 0, 118, 0, 0, 0, 178, 0, 0, 0, 6, 0, 0, 0, 234, 0, 0, 0, 121, 0, 0, 0, 245, 0, 0, 0, 196, 0, 0, 0, 195, 0, 0, 0, 82, 0, 0, 0, 126, 0, 0, 0, 97, 0, 0, 0, 209, 0, 0, 0, 225, 0, +0, 0, 173, 0, 0, 0, 112, 0, 0, 0, 120, 0, 0, 0, 29, 0, 0, 0, 22, 0, 0, 0, 17, 0, 0, 0, 248, 0, 0, 0, 124, 0, 0, 0, 43, 0, 0, 0, 252, 0, 0, 0, 85, 0, 0, 0, 159, 0, 0, 0, 82, 0, 0, 0, 248, 0, 0, 0, 245, 0, 0, 0, 22, 0, 0, 0, 52, 0, 0, 0, 150, 0, 0, 0, 154, 0, 0, 0, 246, 0, 0, 0, 197, 0, 0, 0, 224, 0, 0, 0, 20, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 14, 0, 0, 0, 76, 0, 0, 0, 173, 0, 0, 0, 158, 0, 0, 0, 154, 0, 0, 0, 112, 0, 0, 0, 35, 0, 0, 0, 150, 0, 0, 0, 178, 0, 0, 0, 241, 0, 0, 0, 46, 0, 0, 0].concat([157, +0, 0, 0, 195, 0, 0, 0, 50, 0, 0, 0, 155, 0, 0, 0, 84, 0, 0, 0, 165, 0, 0, 0, 115, 0, 0, 0, 222, 0, 0, 0, 136, 0, 0, 0, 177, 0, 0, 0, 62, 0, 0, 0, 36, 0, 0, 0, 246, 0, 0, 0, 226, 0, 0, 0, 76, 0, 0, 0, 31, 0, 0, 0, 91, 0, 0, 0, 178, 0, 0, 0, 175, 0, 0, 0, 130, 0, 0, 0, 165, 0, 0, 0, 207, 0, 0, 0, 129, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 239, 0, 0, 0, 219, 0, 0, 0, 162, 0, 0, 0, 204, 0, 0, 0, 36, 0, 0, 0, 178, 0, 0, 0, 126, 0, 0, 0, 11, 0, 0, 0, 122, 0, 0, 0, 235, 0, 0, 0, 1, 0, 0, 0, 216, 0, 0, 0, 82, +0, 0, 0, 244, 0, 0, 0, 81, 0, 0, 0, 137, 0, 0, 0, 41, 0, 0, 0, 121, 0, 0, 0, 55, 0, 0, 0, 116, 0, 0, 0, 222, 0, 0, 0, 18, 0, 0, 0, 243, 0, 0, 0, 104, 0, 0, 0, 183, 0, 0, 0, 102, 0, 0, 0, 195, 0, 0, 0, 238, 0, 0, 0, 104, 0, 0, 0, 220, 0, 0, 0, 129, 0, 0, 0, 181, 0, 0, 0, 85, 0, 0, 0, 153, 0, 0, 0, 171, 0, 0, 0, 217, 0, 0, 0, 40, 0, 0, 0, 99, 0, 0, 0, 109, 0, 0, 0, 139, 0, 0, 0, 64, 0, 0, 0, 105, 0, 0, 0, 117, 0, 0, 0, 108, 0, 0, 0, 205, 0, 0, 0, 92, 0, 0, 0, 42, 0, 0, 0, 126, 0, 0, 0, 50, 0, 0, 0, +123, 0, 0, 0, 41, 0, 0, 0, 2, 0, 0, 0, 204, 0, 0, 0, 34, 0, 0, 0, 116, 0, 0, 0, 77, 0, 0, 0, 25, 0, 0, 0, 7, 0, 0, 0, 192, 0, 0, 0, 218, 0, 0, 0, 181, 0, 0, 0, 118, 0, 0, 0, 81, 0, 0, 0, 42, 0, 0, 0, 170, 0, 0, 0, 166, 0, 0, 0, 10, 0, 0, 0, 95, 0, 0, 0, 38, 0, 0, 0, 212, 0, 0, 0, 188, 0, 0, 0, 175, 0, 0, 0, 72, 0, 0, 0, 136, 0, 0, 0, 127, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0, 242, 0, 0, 0, 225, 0, 0, 0, 207, 0, 0, 0, 233, 0, 0, 0, 221, 0, 0, 0, 21, 0, 0, 0, 237, 0, 0, 0, 181, 0, 0, 0, 154, 0, 0, 0, +140, 0, 0, 0, 154, 0, 0, 0, 221, 0, 0, 0, 39, 0, 0, 0, 244, 0, 0, 0, 127, 0, 0, 0, 71, 0, 0, 0, 217, 0, 0, 0, 82, 0, 0, 0, 167, 0, 0, 0, 205, 0, 0, 0, 101, 0, 0, 0, 165, 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 237, 0, 0, 0, 166, 0, 0, 0, 99, 0, 0, 0, 91, 0, 0, 0, 128, 0, 0, 0, 74, 0, 0, 0, 173, 0, 0, 0, 77, 0, 0, 0, 237, 0, 0, 0, 191, 0, 0, 0, 238, 0, 0, 0, 73, 0, 0, 0, 179, 0, 0, 0, 6, 0, 0, 0, 248, 0, 0, 0, 100, 0, 0, 0, 139, 0, 0, 0, 96, 0, 0, 0, 144, 0, 0, 0, 233, 0, 0, 0, 222, 0, 0, 0, 68, 0, 0, +0, 119, 0, 0, 0, 185, 0, 0, 0, 7, 0, 0, 0, 54, 0, 0, 0, 50, 0, 0, 0, 194, 0, 0, 0, 80, 0, 0, 0, 245, 0, 0, 0, 101, 0, 0, 0, 223, 0, 0, 0, 72, 0, 0, 0, 76, 0, 0, 0, 55, 0, 0, 0, 170, 0, 0, 0, 104, 0, 0, 0, 171, 0, 0, 0, 154, 0, 0, 0, 31, 0, 0, 0, 62, 0, 0, 0, 255, 0, 0, 0, 137, 0, 0, 0, 146, 0, 0, 0, 160, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 0, 0, 79, 0, 0, 0, 156, 0, 0, 0, 25, 0, 0, 0, 192, 0, 0, 0, 74, 0, 0, 0, 49, 0, 0, 0, 236, 0, 0, 0, 249, 0, 0, 0, 170, 0, 0, 0, 235, 0, 0, 0, 178, 0, 0, 0, 22, 0, 0, 0, 156, 0, 0, 0, 163, 0, 0, 0, 102, 0, 0, 0, 95, 0, 0, 0, 209, 0, 0, 0, 212, 0, 0, 0, 237, 0, 0, 0, 184, 0, 0, 0, 146, 0, 0, 0, 28, 0, 0, 0, 171, 0, 0, 0, 218, 0, 0, 0, 234, 0, 0, 0, 217, 0, 0, 0, 87, 0, 0, 0, 223, 0, 0, 0, 76, 0, 0, +0, 42, 0, 0, 0, 72, 0, 0, 0, 75, 0, 0, 0, 176, 0, 0, 0, 78, 0, 0, 0, 110, 0, 0, 0, 17, 0, 0, 0, 59, 0, 0, 0, 81, 0, 0, 0, 189, 0, 0, 0, 106, 0, 0, 0, 253, 0, 0, 0, 228, 0, 0, 0, 37, 0, 0, 0, 165, 0, 0, 0, 95, 0, 0, 0, 17, 0, 0, 0, 63, 0, 0, 0, 152, 0, 0, 0, 146, 0, 0, 0, 81, 0, 0, 0, 20, 0, 0, 0, 198, 0, 0, 0, 95, 0, 0, 0, 60, 0, 0, 0, 11, 0, 0, 0, 168, 0, 0, 0, 247, 0, 0, 0, 194, 0, 0, 0, 129, 0, 0, 0, 67, 0, 0, 0, 222, 0, 0, 0, 145, 0, 0, 0, 115, 0, 0, 0, 60, 0, 0, 0, 143, 0, 0, 0, 159, 0, 0, 0, +51, 0, 0, 0, 42, 0, 0, 0, 31, 0, 0, 0, 67, 0, 0, 0, 51, 0, 0, 0, 143, 0, 0, 0, 104, 0, 0, 0, 255, 0, 0, 0, 31, 0, 0, 0, 61, 0, 0, 0, 115, 0, 0, 0, 107, 0, 0, 0, 191, 0, 0, 0, 104, 0, 0, 0, 204, 0, 0, 0, 125, 0, 0, 0, 19, 0, 0, 0, 108, 0, 0, 0, 36, 0, 0, 0, 75, 0, 0, 0, 204, 0, 0, 0, 77, 0, 0, 0, 36, 0, 0, 0, 13, 0, 0, 0, 254, 0, 0, 0, 222, 0, 0, 0, 134, 0, 0, 0, 173, 0, 0, 0, 59, 0, 0, 0, 121, 0, 0, 0, 81, 0, 0, 0, 129, 0, 0, 0, 1, 0, 0, 0, 220, 0, 0, 0, 115, 0, 0, 0, 83, 0, 0, 0, 224, 0, 0, 0, 110, +0, 0, 0, 155, 0, 0, 0, 234, 0, 0, 0, 104, 0, 0, 0, 63, 0, 0, 0, 92, 0, 0, 0, 20, 0, 0, 0, 132, 0, 0, 0, 83, 0, 0, 0, 141, 0, 0, 0, 75, 0, 0, 0, 192, 0, 0, 0, 159, 0, 0, 0, 159, 0, 0, 0, 137, 0, 0, 0, 43, 0, 0, 0, 140, 0, 0, 0, 186, 0, 0, 0, 134, 0, 0, 0, 250, 0, 0, 0, 242, 0, 0, 0, 205, 0, 0, 0, 227, 0, 0, 0, 45, 0, 0, 0, 6, 0, 0, 0, 249, 0, 0, 0, 41, 0, 0, 0, 90, 0, 0, 0, 219, 0, 0, 0, 61, 0, 0, 0, 132, 0, 0, 0, 82, 0, 0, 0, 171, 0, 0, 0, 204, 0, 0, 0, 107, 0, 0, 0, 96, 0, 0, 0, 157, 0, 0, 0, 183, +0, 0, 0, 74, 0, 0, 0, 14, 0, 0, 0, 54, 0, 0, 0, 99, 0, 0, 0, 145, 0, 0, 0, 173, 0, 0, 0, 160, 0, 0, 0, 149, 0, 0, 0, 176, 0, 0, 0, 151, 0, 0, 0, 137, 0, 0, 0, 78, 0, 0, 0, 207, 0, 0, 0, 125, 0, 0, 0, 60, 0, 0, 0, 229, 0, 0, 0, 124, 0, 0, 0, 40, 0, 0, 0, 46, 0, 0, 0, 105, 0, 0, 0, 152, 0, 0, 0, 253, 0, 0, 0, 198, 0, 0, 0, 189, 0, 0, 0, 204, 0, 0, 0, 202, 0, 0, 0, 223, 0, 0, 0, 154, 0, 0, 0, 68, 0, 0, 0, 126, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 137, 0, 0, 0, 109, 0, 0, 0, 191, 0, 0, 0, 39, 0, 0, 0, +194, 0, 0, 0, 248, 0, 0, 0, 205, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 181, 0, 0, 0, 88, 0, 0, 0, 78, 0, 0, 0, 183, 0, 0, 0, 137, 0, 0, 0, 9, 0, 0, 0, 233, 0, 0, 0, 45, 0, 0, 0, 84, 0, 0, 0, 190, 0, 0, 0, 117, 0, 0, 0, 203, 0, 0, 0, 5, 0, 0, 0, 176, 0, 0, 0, 84, 0, 0, 0, 183, 0, 0, 0, 231, 0, 0, 0, 38, 0, 0, 0, 134, 0, 0, 0, 74, 0, 0, 0, 252, 0, 0, 0, 25, 0, 0, 0, 207, 0, 0, 0, 39, 0, 0, 0, 70, 0, 0, 0, 212, 0, 0, 0, 34, 0, 0, 0, 150, 0, 0, 0, 90, 0, 0, 0, 17, 0, 0, 0, 232, 0, 0, 0, 213, +0, 0, 0, 27, 0, 0, 0, 237, 0, 0, 0, 113, 0, 0, 0, 197, 0, 0, 0, 93, 0, 0, 0, 200, 0, 0, 0, 175, 0, 0, 0, 69, 0, 0, 0, 64, 0, 0, 0, 123, 0, 0, 0, 119, 0, 0, 0, 87, 0, 0, 0, 73, 0, 0, 0, 158, 0, 0, 0, 128, 0, 0, 0, 57, 0, 0, 0, 35, 0, 0, 0, 238, 0, 0, 0, 129, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 207, 0, 0, 0, 219, 0, 0, 0, 122, 0, 0, 0, 47, 0, 0, 0, 20, 0, 0, 0, 184, 0, 0, 0, 87, 0, 0, 0, 143, 0, 0, 0, 161, 0, 0, 0, 57, 0, 0, 0, 30, 0, 0, 0, 119, 0, 0, 0, 252, 0, 0, 0, 11, 0, 0, 0, 166, 0, 0, 0, 191, +0, 0, 0, 138, 0, 0, 0, 12, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 58, 0, 0, 0, 212, 0, 0, 0, 216, 0, 0, 0, 39, 0, 0, 0, 207, 0, 0, 0, 232, 0, 0, 0, 161, 0, 0, 0, 114, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 221, 0, 0, 0, 13, 0, 0, 0, 150, 0, +0, 0, 218, 0, 0, 0, 121, 0, 0, 0, 237, 0, 0, 0, 86, 0, 0, 0, 66, 0, 0, 0, 21, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 28, 0, 0, 0, 107, 0, 0, 0, 38, 0, 0, 0, 48, 0, 0, 0, 246, 0, 0, 0, 106, 0, 0, 0, 149, 0, 0, 0, 103, 0, 0, 0, 243, 0, 0, 0, 10, 0, 0, 0, 197, 0, 0, 0, 8, 0, 0, 0, 164, 0, 0, 0, 43, 0, 0, 0, 47, 0, 0, 0, 189, 0, 0, 0, 49, 0, 0, 0, 129, 0, 0, 0, 42, 0, 0, 0, 166, 0, 0, 0, 182, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 218, 0, 0, 0, 61, 0, 0, 0, 178, 0, 0, 0, 176, 0, 0, 0, 150, 0, +0, 0, 206, 0, 0, 0, 138, 0, 0, 0, 210, 0, 0, 0, 141, 0, 0, 0, 112, 0, 0, 0, 179, 0, 0, 0, 211, 0, 0, 0, 52, 0, 0, 0, 1, 0, 0, 0, 144, 0, 0, 0, 141, 0, 0, 0, 16, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 13, 0, 0, 0, 231, 0, 0, 0, 186, 0, 0, 0, 79, 0, 0, 0, 7, 0, 0, 0, 223, 0, 0, 0, 141, 0, 0, 0, 234, 0, 0, 0, 125, 0, 0, 0, 160, 0, 0, 0, 197, 0, 0, 0, 214, 0, 0, 0, 177, 0, 0, 0, 176, 0, 0, 0, 229, 0, 0, 0, 87, 0, 0, 0, 27, 0, 0, 0, 91, 0, 0, 0, 245, 0, 0, 0, 69, 0, 0, 0, 19, 0, 0, 0, 20, 0, 0, 0, 100, 0, +0, 0, 90, 0, 0, 0, 235, 0, 0, 0, 92, 0, 0, 0, 252, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 43, 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 194, 0, 0, 0, 175, 0, 0, 0, 150, 0, 0, 0, 54, 0, 0, 0, 254, 0, 0, 0, 74, 0, 0, 0, 226, 0, 0, 0, 84, 0, 0, 0, 32, 0, 0, 0, 106, 0, 0, 0, 235, 0, 0, 0, 178, 0, 0, 0, 159, 0, 0, 0, 98, 0, 0, 0, 215, 0, 0, 0, 206, 0, 0, 0, 162, 0, 0, 0, 63, 0, 0, 0, 32, 0, 0, 0, 17, 0, 0, 0, 52, 0, 0, 0, 55, 0, 0, 0, 224, 0, 0, 0, 66, 0, 0, 0, 237, 0, 0, 0, 111, 0, 0, 0, 249, 0, 0, +0, 26, 0, 0, 0, 200, 0, 0, 0, 125, 0, 0, 0, 216, 0, 0, 0, 185, 0, 0, 0, 17, 0, 0, 0, 232, 0, 0, 0, 54, 0, 0, 0, 63, 0, 0, 0, 66, 0, 0, 0, 193, 0, 0, 0, 202, 0, 0, 0, 220, 0, 0, 0, 211, 0, 0, 0, 241, 0, 0, 0, 200, 0, 0, 0, 35, 0, 0, 0, 61, 0, 0, 0, 79, 0, 0, 0, 81, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 141, 0, 0, 0, 216, 0, 0, 0, 228, 0, 0, 0, 160, 0, 0, 0, 170, 0, 0, 0, 243, 0, 0, 0, 4, 0, 0, 0, 214, 0, 0, 0, 17, 0, 0, 0, 147, 0, 0, 0, 200, 0, 0, 0, 53, 0, 0, 0, 69, 0, 0, 0, 97, 0, 0, 0, 54, 0, 0, +0, 214, 0, 0, 0, 8, 0, 0, 0, 144, 0, 0, 0, 191, 0, 0, 0, 167, 0, 0, 0, 122, 0, 0, 0, 151, 0, 0, 0, 108, 0, 0, 0, 15, 0, 0, 0, 132, 0, 0, 0, 213, 0, 0, 0, 51, 0, 0, 0, 45, 0, 0, 0, 55, 0, 0, 0, 201, 0, 0, 0, 106, 0, 0, 0, 128, 0, 0, 0, 144, 0, 0, 0, 61, 0, 0, 0, 10, 0, 0, 0, 162, 0, 0, 0, 170, 0, 0, 0, 225, 0, 0, 0, 184, 0, 0, 0, 132, 0, 0, 0, 186, 0, 0, 0, 97, 0, 0, 0, 54, 0, 0, 0, 221, 0, 0, 0, 105, 0, 0, 0, 107, 0, 0, 0, 219, 0, 0, 0, 91, 0, 0, 0, 156, 0, 0, 0, 198, 0, 0, 0, 146, 0, 0, 0, 188, +0, 0, 0, 35, 0, 0, 0, 175, 0, 0, 0, 197, 0, 0, 0, 184, 0, 0, 0, 117, 0, 0, 0, 248, 0, 0, 0, 66, 0, 0, 0, 250, 0, 0, 0, 214, 0, 0, 0, 182, 0, 0, 0, 132, 0, 0, 0, 148, 0, 0, 0, 99, 0, 0, 0, 152, 0, 0, 0, 147, 0, 0, 0, 72, 0, 0, 0, 120, 0, 0, 0, 56, 0, 0, 0, 205, 0, 0, 0, 187, 0, 0, 0, 24, 0, 0, 0, 52, 0, 0, 0, 195, 0, 0, 0, 219, 0, 0, 0, 103, 0, 0, 0, 150, 0, 0, 0, 243, 0, 0, 0, 58, 0, 0, 0, 9, 0, 0, 0, 86, 0, 0, 0, 176, 0, 0, 0, 111, 0, 0, 0, 124, 0, 0, 0, 81, 0, 0, 0, 30, 0, 0, 0, 27, 0, 0, 0, 57, +0, 0, 0, 72, 0, 0, 0, 234, 0, 0, 0, 201, 0, 0, 0, 12, 0, 0, 0, 37, 0, 0, 0, 162, 0, 0, 0, 122, 0, 0, 0, 202, 0, 0, 0, 231, 0, 0, 0, 146, 0, 0, 0, 252, 0, 0, 0, 89, 0, 0, 0, 48, 0, 0, 0, 163, 0, 0, 0, 137, 0, 0, 0, 133, 0, 0, 0, 223, 0, 0, 0, 111, 0, 0, 0, 67, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, 0, 0, 132, 0, 0, 0, 68, 0, 0, 0, 25, 0, 0, 0, 189, 0, 0, 0, 233, 0, 0, 0, 84, 0, 0, 0, 196, 0, 0, 0, 192, 0, 0, 0, 110, 0, 0, 0, 42, 0, 0, 0, 168, 0, 0, 0, 168, 0, 0, 0, 155, 0, 0, 0, 67, 0, 0, 0, 213, 0, 0, 0, 113, 0, 0, 0, 34, 0, 0, 0, 95, 0, 0, 0, 220, 0, 0, 0, 1, 0, 0, 0, 250, 0, 0, 0, 223, 0, 0, 0, 179, 0, 0, 0, 184, 0, 0, 0, 71, 0, 0, 0, 75, 0, 0, 0, 10, 0, 0, 0, 165, 0, 0, 0, 68, 0, 0, 0, 234, 0, 0, 0, 41, 0, 0, 0, 5, 0, 0, 0, 144, 0, +0, 0, 80, 0, 0, 0, 175, 0, 0, 0, 99, 0, 0, 0, 95, 0, 0, 0, 157, 0, 0, 0, 158, 0, 0, 0, 225, 0, 0, 0, 157, 0, 0, 0, 56, 0, 0, 0, 151, 0, 0, 0, 31, 0, 0, 0, 108, 0, 0, 0, 172, 0, 0, 0, 48, 0, 0, 0, 70, 0, 0, 0, 178, 0, 0, 0, 106, 0, 0, 0, 25, 0, 0, 0, 209, 0, 0, 0, 75, 0, 0, 0, 219, 0, 0, 0, 187, 0, 0, 0, 140, 0, 0, 0, 218, 0, 0, 0, 46, 0, 0, 0, 171, 0, 0, 0, 200, 0, 0, 0, 90, 0, 0, 0, 119, 0, 0, 0, 108, 0, 0, 0, 43, 0, 0, 0, 190, 0, 0, 0, 175, 0, 0, 0, 161, 0, 0, 0, 109, 0, 0, 0, 47, 0, 0, 0, 11, +0, 0, 0, 177, 0, 0, 0, 143, 0, 0, 0, 227, 0, 0, 0, 224, 0, 0, 0, 56, 0, 0, 0, 205, 0, 0, 0, 11, 0, 0, 0, 65, 0, 0, 0, 27, 0, 0, 0, 74, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 243, 0, 0, 0, 111, 0, 0, 0, 220, 0, 0, 0, 184, 0, 0, 0, 233, 0, 0, 0, 222, 0, 0, 0, 178, 0, 0, 0, 163, 0, 0, 0, 64, 0, 0, 0, 1, 0, 0, 0, 166, 0, 0, 0, 69, 0, 0, 0, 30, 0, 0, 0, 118, 0, 0, 0, 10, 0, 0, 0, 218, 0, 0, 0, 141, 0, 0, 0, 44, 0, 0, 0, 7, 0, 0, 0, 63, 0, 0, 0, 137, 0, 0, 0, 125, 0, 0, 0, 4, 0, 0, 0, 173, 0, 0, 0, 67, 0, 0, +0, 80, 0, 0, 0, 110, 0, 0, 0, 210, 0, 0, 0, 71, 0, 0, 0, 203, 0, 0, 0, 138, 0, 0, 0, 230, 0, 0, 0, 133, 0, 0, 0, 26, 0, 0, 0, 36, 0, 0, 0, 243, 0, 0, 0, 210, 0, 0, 0, 96, 0, 0, 0, 253, 0, 0, 0, 223, 0, 0, 0, 115, 0, 0, 0, 164, 0, 0, 0, 13, 0, 0, 0, 115, 0, 0, 0, 14, 0, 0, 0, 253, 0, 0, 0, 103, 0, 0, 0, 107, 0, 0, 0, 113, 0, 0, 0, 155, 0, 0, 0, 129, 0, 0, 0, 83, 0, 0, 0, 57, 0, 0, 0, 57, 0, 0, 0, 244, 0, 0, 0, 184, 0, 0, 0, 213, 0, 0, 0, 195, 0, 0, 0, 48, 0, 0, 0, 155, 0, 0, 0, 59, 0, 0, 0, 124, 0, +0, 0, 163, 0, 0, 0, 240, 0, 0, 0, 208, 0, 0, 0, 132, 0, 0, 0, 33, 0, 0, 0, 214, 0, 0, 0, 191, 0, 0, 0, 183, 0, 0, 0, 76, 0, 0, 0, 135, 0, 0, 0, 19, 0, 0, 0, 69, 0, 0, 0, 45, 0, 0, 0, 167, 0, 0, 0, 85, 0, 0, 0, 93, 0, 0, 0, 4, 0, 0, 0, 179, 0, 0, 0, 64, 0, 0, 0, 40, 0, 0, 0, 149, 0, 0, 0, 45, 0, 0, 0, 48, 0, 0, 0, 131, 0, 0, 0, 236, 0, 0, 0, 94, 0, 0, 0, 228, 0, 0, 0, 255, 0, 0, 0, 117, 0, 0, 0, 254, 0, 0, 0, 121, 0, 0, 0, 38, 0, 0, 0, 157, 0, 0, 0, 29, 0, 0, 0, 54, 0, 0, 0, 205, 0, 0, 0, 10, 0, 0, +0, 21, 0, 0, 0, 210, 0, 0, 0, 36, 0, 0, 0, 20, 0, 0, 0, 119, 0, 0, 0, 113, 0, 0, 0, 215, 0, 0, 0, 138, 0, 0, 0, 27, 0, 0, 0, 4, 0, 0, 0, 93, 0, 0, 0, 147, 0, 0, 0, 201, 0, 0, 0, 190, 0, 0, 0, 170, 0, 0, 0, 144, 0, 0, 0, 205, 0, 0, 0, 155, 0, 0, 0, 251, 0, 0, 0, 115, 0, 0, 0, 126, 0, 0, 0, 176, 0, 0, 0, 100, 0, 0, 0, 152, 0, 0, 0, 87, 0, 0, 0, 68, 0, 0, 0, 66, 0, 0, 0, 65, 0, 0, 0, 177, 0, 0, 0, 175, 0, 0, 0, 234, 0, 0, 0, 193, 0, 0, 0, 195, 0, 0, 0, 34, 0, 0, 0, 255, 0, 0, 0, 96, 0, 0, 0, 70, 0, +0, 0, 203, 0, 0, 0, 97, 0, 0, 0, 129, 0, 0, 0, 112, 0, 0, 0, 97, 0, 0, 0, 13, 0, 0, 0, 130, 0, 0, 0, 185, 0, 0, 0, 254, 0, 0, 0, 33, 0, 0, 0, 205, 0, 0, 0, 196, 0, 0, 0, 245, 0, 0, 0, 152, 0, 0, 0, 12, 0, 0, 0, 78, 0, 0, 0, 114, 0, 0, 0, 238, 0, 0, 0, 135, 0, 0, 0, 73, 0, 0, 0, 248, 0, 0, 0, 161, 0, 0, 0, 149, 0, 0, 0, 223, 0, 0, 0, 143, 0, 0, 0, 45, 0, 0, 0, 189, 0, 0, 0, 33, 0, 0, 0, 6, 0, 0, 0, 124, 0, 0, 0, 21, 0, 0, 0, 232, 0, 0, 0, 18, 0, 0, 0, 109, 0, 0, 0, 147, 0, 0, 0, 214, 0, 0, 0, 56, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 247, 0, 0, 0, 81, 0, 0, 0, 217, 0, 0, 0, 239, 0, 0, 0, 125, 0, 0, 0, 66, 0, 0, 0, 1, 0, 0, 0, 19, 0, 0, 0, 233, 0, 0, 0, 184, 0, 0, 0, 127, 0, 0, 0, 166, 0, 0, 0, 73, 0, 0, 0, 23, 0, 0, 0, 100, 0, 0, 0, 33, 0, 0, +0, 128, 0, 0, 0, 131, 0, 0, 0, 44, 0, 0, 0, 99, 0, 0, 0, 76, 0, 0, 0, 96, 0, 0, 0, 9, 0, 0, 0, 89, 0, 0, 0, 145, 0, 0, 0, 146, 0, 0, 0, 119, 0, 0, 0, 57, 0, 0, 0, 81, 0, 0, 0, 244, 0, 0, 0, 72, 0, 0, 0, 96, 0, 0, 0, 213, 0, 0, 0, 34, 0, 0, 0, 131, 0, 0, 0, 8, 0, 0, 0, 47, 0, 0, 0, 255, 0, 0, 0, 153, 0, 0, 0, 62, 0, 0, 0, 105, 0, 0, 0, 109, 0, 0, 0, 136, 0, 0, 0, 218, 0, 0, 0, 231, 0, 0, 0, 91, 0, 0, 0, 82, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 42, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 222, 0, 0, 0, 104, +0, 0, 0, 144, 0, 0, 0, 182, 0, 0, 0, 34, 0, 0, 0, 90, 0, 0, 0, 189, 0, 0, 0, 211, 0, 0, 0, 133, 0, 0, 0, 83, 0, 0, 0, 49, 0, 0, 0, 216, 0, 0, 0, 206, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 60, 0, 0, 0, 75, 0, 0, 0, 162, 0, 0, 0, 29, 0, 0, 0, 44, 0, 0, 0, 47, 0, 0, 0, 54, 0, 0, 0, 190, 0, 0, 0, 122, 0, 0, 0, 252, 0, 0, 0, 205, 0, 0, 0, 188, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 48, 0, 0, 0, 189, 0, 0, 0, 255, 0, 0, 0, 5, 0, 0, 0, 199, 0, 0, 0, 228, 0, 0, 0, 142, 0, 0, 0, 23, 0, 0, 0, 98, 0, 0, 0, 248, +0, 0, 0, 77, 0, 0, 0, 160, 0, 0, 0, 86, 0, 0, 0, 121, 0, 0, 0, 130, 0, 0, 0, 231, 0, 0, 0, 246, 0, 0, 0, 186, 0, 0, 0, 83, 0, 0, 0, 132, 0, 0, 0, 10, 0, 0, 0, 163, 0, 0, 0, 52, 0, 0, 0, 255, 0, 0, 0, 60, 0, 0, 0, 163, 0, 0, 0, 106, 0, 0, 0, 161, 0, 0, 0, 55, 0, 0, 0, 234, 0, 0, 0, 221, 0, 0, 0, 182, 0, 0, 0, 149, 0, 0, 0, 179, 0, 0, 0, 120, 0, 0, 0, 25, 0, 0, 0, 118, 0, 0, 0, 30, 0, 0, 0, 85, 0, 0, 0, 47, 0, 0, 0, 119, 0, 0, 0, 46, 0, 0, 0, 127, 0, 0, 0, 193, 0, 0, 0, 234, 0, 0, 0, 94, 0, 0, 0, 131, +0, 0, 0, 225, 0, 0, 0, 110, 0, 0, 0, 169, 0, 0, 0, 7, 0, 0, 0, 51, 0, 0, 0, 62, 0, 0, 0, 131, 0, 0, 0, 255, 0, 0, 0, 203, 0, 0, 0, 28, 0, 0, 0, 159, 0, 0, 0, 177, 0, 0, 0, 163, 0, 0, 0, 180, 0, 0, 0, 201, 0, 0, 0, 225, 0, 0, 0, 7, 0, 0, 0, 151, 0, 0, 0, 255, 0, 0, 0, 248, 0, 0, 0, 35, 0, 0, 0, 143, 0, 0, 0, 206, 0, 0, 0, 64, 0, 0, 0, 253, 0, 0, 0, 46, 0, 0, 0, 94, 0, 0, 0, 219, 0, 0, 0, 22, 0, 0, 0, 67, 0, 0, 0, 45, 0, 0, 0, 186, 0, 0, 0, 56, 0, 0, 0, 2, 0, 0, 0, 247, 0, 0, 0, 129, 0, 0, 0, 67, 0, +0, 0, 131, 0, 0, 0, 163, 0, 0, 0, 32, 0, 0, 0, 79, 0, 0, 0, 1, 0, 0, 0, 59, 0, 0, 0, 138, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 49, 0, 0, 0, 198, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 223, 0, 0, 0, 215, 0, 0, 0, 250, 0, 0, 0, 47, 0, 0, 0, 136, 0, 0, 0, 63, 0, 0, 0, 252, 0, 0, 0, 12, 0, 0, 0, 118, 0, 0, 0, 196, 0, 0, 0, 166, 0, 0, 0, 69, 0, 0, 0, 114, 0, 0, 0, 187, 0, 0, 0, 12, 0, 0, 0, 188, 0, 0, 0, 106, 0, 0, 0, 164, 0, 0, 0, 151, 0, 0, 0, 23, 0, 0, 0, 147, 0, 0, 0, 45, 0, 0, 0, 111, 0, 0, 0, 222, 0, +0, 0, 114, 0, 0, 0, 16, 0, 0, 0, 28, 0, 0, 0, 8, 0, 0, 0, 44, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 50, 0, 0, 0, 104, 0, 0, 0, 39, 0, 0, 0, 212, 0, 0, 0, 171, 0, 0, 0, 221, 0, 0, 0, 197, 0, 0, 0, 88, 0, 0, 0, 97, 0, 0, 0, 19, 0, 0, 0, 109, 0, 0, 0, 17, 0, 0, 0, 30, 0, 0, 0, 77, 0, 0, 0, 26, 0, 0, 0, 185, 0, 0, 0, 201, 0, 0, 0, 16, 0, 0, 0, 251, 0, 0, 0, 30, 0, 0, 0, 78, 0, 0, 0, 244, 0, 0, 0, 132, 0, 0, 0, 75, 0, 0, 0, 138, 0, 0, 0, 94, 0, 0, 0, 123, 0, 0, 0, 75, 0, 0, 0, 232, 0, 0, 0, 67, 0, 0, 0, +140, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, 0, 84, 0, 0, 0, 19, 0, 0, 0, 197, 0, 0, 0, 92, 0, 0, 0, 182, 0, 0, 0, 53, 0, 0, 0, 78, 0, 0, 0, 157, 0, 0, 0, 228, 0, 0, 0, 91, 0, 0, 0, 65, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 125, 0, +0, 0, 18, 0, 0, 0, 72, 0, 0, 0, 130, 0, 0, 0, 20, 0, 0, 0, 66, 0, 0, 0, 205, 0, 0, 0, 50, 0, 0, 0, 212, 0, 0, 0, 75, 0, 0, 0, 193, 0, 0, 0, 114, 0, 0, 0, 97, 0, 0, 0, 42, 0, 0, 0, 140, 0, 0, 0, 236, 0, 0, 0, 226, 0, 0, 0, 248, 0, 0, 0, 36, 0, 0, 0, 69, 0, 0, 0, 148, 0, 0, 0, 227, 0, 0, 0, 190, 0, 0, 0, 221, 0, 0, 0, 103, 0, 0, 0, 168, 0, 0, 0, 119, 0, 0, 0, 90, 0, 0, 0, 174, 0, 0, 0, 91, 0, 0, 0, 75, 0, 0, 0, 203, 0, 0, 0, 119, 0, 0, 0, 154, 0, 0, 0, 32, 0, 0, 0, 222, 0, 0, 0, 184, 0, 0, 0, 35, 0, +0, 0, 217, 0, 0, 0, 160, 0, 0, 0, 15, 0, 0, 0, 140, 0, 0, 0, 123, 0, 0, 0, 165, 0, 0, 0, 203, 0, 0, 0, 174, 0, 0, 0, 182, 0, 0, 0, 236, 0, 0, 0, 66, 0, 0, 0, 103, 0, 0, 0, 14, 0, 0, 0, 88, 0, 0, 0, 164, 0, 0, 0, 117, 0, 0, 0, 152, 0, 0, 0, 33, 0, 0, 0, 113, 0, 0, 0, 132, 0, 0, 0, 179, 0, 0, 0, 224, 0, 0, 0, 118, 0, 0, 0, 148, 0, 0, 0, 115, 0, 0, 0, 223, 0, 0, 0, 252, 0, 0, 0, 105, 0, 0, 0, 40, 0, 0, 0, 35, 0, 0, 0, 63, 0, 0, 0, 91, 0, 0, 0, 248, 0, 0, 0, 59, 0, 0, 0, 36, 0, 0, 0, 55, 0, 0, 0, 243, +0, 0, 0, 29, 0, 0, 0, 213, 0, 0, 0, 34, 0, 0, 0, 107, 0, 0, 0, 208, 0, 0, 0, 152, 0, 0, 0, 168, 0, 0, 0, 108, 0, 0, 0, 207, 0, 0, 0, 255, 0, 0, 0, 6, 0, 0, 0, 225, 0, 0, 0, 19, 0, 0, 0, 223, 0, 0, 0, 185, 0, 0, 0, 193, 0, 0, 0, 12, 0, 0, 0, 169, 0, 0, 0, 191, 0, 0, 0, 51, 0, 0, 0, 217, 0, 0, 0, 129, 0, 0, 0, 218, 0, 0, 0, 178, 0, 0, 0, 79, 0, 0, 0, 130, 0, 0, 0, 157, 0, 0, 0, 67, 0, 0, 0, 129, 0, 0, 0, 9, 0, 0, 0, 241, 0, 0, 0, 210, 0, 0, 0, 1, 0, 0, 0, 239, 0, 0, 0, 172, 0, 0, 0, 244, 0, 0, 0, 45, +0, 0, 0, 125, 0, 0, 0, 1, 0, 0, 0, 9, 0, 0, 0, 241, 0, 0, 0, 255, 0, 0, 0, 165, 0, 0, 0, 159, 0, 0, 0, 229, 0, 0, 0, 202, 0, 0, 0, 39, 0, 0, 0, 99, 0, 0, 0, 219, 0, 0, 0, 32, 0, 0, 0, 177, 0, 0, 0, 83, 0, 0, 0, 103, 0, 0, 0, 2, 0, 0, 0, 232, 0, 0, 0, 173, 0, 0, 0, 169, 0, 0, 0, 52, 0, 0, 0, 212, 0, 0, 0, 240, 0, 0, 0, 21, 0, 0, 0, 129, 0, 0, 0, 170, 0, 0, 0, 199, 0, 0, 0, 77, 0, 0, 0, 135, 0, 0, 0, 148, 0, 0, 0, 234, 0, 0, 0, 117, 0, 0, 0, 231, 0, 0, 0, 76, 0, 0, 0, 148, 0, 0, 0, 4, 0, 0, 0, 14, +0, 0, 0, 105, 0, 0, 0, 135, 0, 0, 0, 231, 0, 0, 0, 81, 0, 0, 0, 145, 0, 0, 0, 16, 0, 0, 0, 3, 0, 0, 0, 199, 0, 0, 0, 190, 0, 0, 0, 86, 0, 0, 0, 50, 0, 0, 0, 251, 0, 0, 0, 134, 0, 0, 0, 236, 0, 0, 0, 51, 0, 0, 0, 107, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 43, 0, 0, 0, 200, 0, 0, 0, 250, 0, 0, 0, 108, 0, 0, 0, 112, 0, 0, 0, 71, 0, 0, 0, 126, 0, 0, 0, 206, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 113, 0, 0, 0, 243, 0, 0, 0, 180, 0, 0, 0, 86, 0, 0, 0, 166, 0, 0, 0, 220, 0, 0, 0, 204, 0, 0, 0, 120, 0, 0, 0, 7, +0, 0, 0, 117, 0, 0, 0, 208, 0, 0, 0, 221, 0, 0, 0, 178, 0, 0, 0, 106, 0, 0, 0, 198, 0, 0, 0, 239, 0, 0, 0, 185, 0, 0, 0, 192, 0, 0, 0, 43, 0, 0, 0, 34, 0, 0, 0, 8, 0, 0, 0, 30, 0, 0, 0, 113, 0, 0, 0, 112, 0, 0, 0, 179, 0, 0, 0, 53, 0, 0, 0, 156, 0, 0, 0, 122, 0, 0, 0, 1, 0, 0, 0, 146, 0, 0, 0, 68, 0, 0, 0, 154, 0, 0, 0, 246, 0, 0, 0, 176, 0, 0, 0, 88, 0, 0, 0, 149, 0, 0, 0, 193, 0, 0, 0, 155, 0, 0, 0, 2, 0, 0, 0, 237, 0, 0, 0, 45, 0, 0, 0, 124, 0, 0, 0, 52, 0, 0, 0, 41, 0, 0, 0, 73, 0, 0, 0, 68, +0, 0, 0, 69, 0, 0, 0, 98, 0, 0, 0, 29, 0, 0, 0, 46, 0, 0, 0, 255, 0, 0, 0, 42, 0, 0, 0, 28, 0, 0, 0, 33, 0, 0, 0, 164, 0, 0, 0, 37, 0, 0, 0, 123, 0, 0, 0, 13, 0, 0, 0, 140, 0, 0, 0, 21, 0, 0, 0, 57, 0, 0, 0, 252, 0, 0, 0, 143, 0, 0, 0, 124, 0, 0, 0, 165, 0, 0, 0, 125, 0, 0, 0, 30, 0, 0, 0, 37, 0, 0, 0, 163, 0, 0, 0, 69, 0, 0, 0, 214, 0, 0, 0, 171, 0, 0, 0, 189, 0, 0, 0, 203, 0, 0, 0, 197, 0, 0, 0, 94, 0, 0, 0, 120, 0, 0, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 211, 0, 0, 0, 66, 0, 0, 0, 237, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 21, 0, 0, 0, 44, 0, 0, 0, 156, 0, 0, 0, 119, 0, 0, 0, 129, 0, 0, 0, 210, 0, 0, 0, 115, 0, 0, 0, 209, 0, 0, 0, 6, 0, 0, 0, 213, 0, 0, 0, 196, 0, 0, 0, 127, 0, 0, 0, 148, 0, 0, 0, 187, 0, 0, 0, 146, 0, 0, +0, 45, 0, 0, 0, 44, 0, 0, 0, 75, 0, 0, 0, 69, 0, 0, 0, 75, 0, 0, 0, 233, 0, 0, 0, 42, 0, 0, 0, 137, 0, 0, 0, 107, 0, 0, 0, 43, 0, 0, 0, 210, 0, 0, 0, 12, 0, 0, 0, 136, 0, 0, 0, 197, 0, 0, 0, 72, 0, 0, 0, 77, 0, 0, 0, 234, 0, 0, 0, 13, 0, 0, 0, 74, 0, 0, 0, 201, 0, 0, 0, 82, 0, 0, 0, 106, 0, 0, 0, 97, 0, 0, 0, 121, 0, 0, 0, 233, 0, 0, 0, 118, 0, 0, 0, 243, 0, 0, 0, 133, 0, 0, 0, 82, 0, 0, 0, 92, 0, 0, 0, 27, 0, 0, 0, 44, 0, 0, 0, 225, 0, 0, 0, 214, 0, 0, 0, 196, 0, 0, 0, 15, 0, 0, 0, 24, 0, 0, 0, +14, 0, 0, 0, 78, 0, 0, 0, 246, 0, 0, 0, 28, 0, 0, 0, 127, 0, 0, 0, 180, 0, 0, 0, 4, 0, 0, 0, 46, 0, 0, 0, 66, 0, 0, 0, 203, 0, 0, 0, 31, 0, 0, 0, 43, 0, 0, 0, 17, 0, 0, 0, 81, 0, 0, 0, 123, 0, 0, 0, 8, 0, 0, 0, 172, 0, 0, 0, 170, 0, 0, 0, 62, 0, 0, 0, 158, 0, 0, 0, 82, 0, 0, 0, 96, 0, 0, 0, 183, 0, 0, 0, 194, 0, 0, 0, 97, 0, 0, 0, 87, 0, 0, 0, 140, 0, 0, 0, 132, 0, 0, 0, 213, 0, 0, 0, 24, 0, 0, 0, 166, 0, 0, 0, 25, 0, 0, 0, 252, 0, 0, 0, 183, 0, 0, 0, 117, 0, 0, 0, 145, 0, 0, 0, 27, 0, 0, 0, 232, +0, 0, 0, 104, 0, 0, 0, 202, 0, 0, 0, 68, 0, 0, 0, 200, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 204, 0, 0, 0, 83, 0, 0, 0, 10, 0, 0, 0, 50, 0, 0, 0, 53, 0, 0, 0, 204, 0, 0, 0, 82, 0, 0, 0, 203, 0, 0, 0, 14, 0, 0, 0, 247, 0, 0, 0, 197, 0, 0, 0, 231, 0, 0, 0, 236, 0, 0, 0, 61, 0, 0, 0, 133, 0, 0, 0, 204, 0, 0, 0, 88, 0, 0, 0, 226, 0, 0, 0, 23, 0, 0, 0, 71, 0, 0, 0, 255, 0, 0, 0, 159, 0, 0, 0, 165, 0, 0, 0, 48, 0, 0, 0, 23, 0, 0, 0, 227, 0, 0, 0, 174, 0, 0, 0, 200, 0, 0, 0, 193, 0, 0, 0, 113, 0, 0, 0, 117, +0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 65, 0, 0, 0, 92, 0, 0, 0, 14, 0, 0, 0, 57, 0, 0, 0, 218, 0, 0, 0, 115, 0, 0, 0, 160, 0, 0, 0, 199, 0, 0, 0, 151, 0, 0, 0, 54, 0, 0, 0, 108, 0, 0, 0, 91, 0, 0, 0, 242, 0, 0, 0, 238, 0, 0, 0, 100, 0, 0, 0, 10, 0, 0, 0, 61, 0, 0, 0, 137, 0, 0, 0, 30, 0, 0, 0, 29, 0, 0, 0, 73, 0, 0, 0, 140, 0, 0, 0, 55, 0, 0, 0, 76, 0, 0, 0, 230, 0, 0, 0, 176, 0, 0, 0, 193, 0, 0, 0, 165, 0, 0, 0, 42, 0, 0, 0, 130, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0, 173, 0, 0, 0, 121, 0, 0, +0, 156, 0, 0, 0, 86, 0, 0, 0, 246, 0, 0, 0, 249, 0, 0, 0, 193, 0, 0, 0, 215, 0, 0, 0, 124, 0, 0, 0, 57, 0, 0, 0, 127, 0, 0, 0, 147, 0, 0, 0, 202, 0, 0, 0, 17, 0, 0, 0, 85, 0, 0, 0, 191, 0, 0, 0, 7, 0, 0, 0, 27, 0, 0, 0, 130, 0, 0, 0, 41, 0, 0, 0, 105, 0, 0, 0, 149, 0, 0, 0, 92, 0, 0, 0, 135, 0, 0, 0, 238, 0, 0, 0, 166, 0, 0, 0, 86, 0, 0, 0, 158, 0, 0, 0, 194, 0, 0, 0, 154, 0, 0, 0, 86, 0, 0, 0, 36, 0, 0, 0, 66, 0, 0, 0, 133, 0, 0, 0, 77, 0, 0, 0, 152, 0, 0, 0, 49, 0, 0, 0, 30, 0, 0, 0, 96, 0, 0, +0, 77, 0, 0, 0, 135, 0, 0, 0, 133, 0, 0, 0, 4, 0, 0, 0, 174, 0, 0, 0, 70, 0, 0, 0, 18, 0, 0, 0, 249, 0, 0, 0, 142, 0, 0, 0, 127, 0, 0, 0, 228, 0, 0, 0, 127, 0, 0, 0, 246, 0, 0, 0, 28, 0, 0, 0, 55, 0, 0, 0, 1, 0, 0, 0, 115, 0, 0, 0, 76, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 196, 0, 0, 0, 233, 0, 0, 0, 108, 0, 0, 0, 133, 0, 0, 0, 72, 0, 0, 0, 74, 0, 0, 0, 90, 0, 0, 0, 172, 0, 0, 0, 217, 0, 0, 0, 31, 0, 0, 0, 67, 0, 0, 0, 248, 0, 0, 0, 98, 0, 0, 0, 91, 0, 0, 0, 238, 0, 0, 0, 152, 0, 0, 0, 42, 0, 0, 0, +51, 0, 0, 0, 142, 0, 0, 0, 121, 0, 0, 0, 206, 0, 0, 0, 97, 0, 0, 0, 6, 0, 0, 0, 53, 0, 0, 0, 216, 0, 0, 0, 215, 0, 0, 0, 202, 0, 0, 0, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 0, 0, 0, 211, 0, 0, 0, 174, 0, 0, 0, 166, 0, 0, 0, 202, 0, 0, 0, 143, 0, 0, 0, 205, +0, 0, 0, 204, 0, 0, 0, 120, 0, 0, 0, 142, 0, 0, 0, 25, 0, 0, 0, 77, 0, 0, 0, 167, 0, 0, 0, 210, 0, 0, 0, 39, 0, 0, 0, 233, 0, 0, 0, 164, 0, 0, 0, 60, 0, 0, 0, 22, 0, 0, 0, 91, 0, 0, 0, 132, 0, 0, 0, 128, 0, 0, 0, 249, 0, 0, 0, 208, 0, 0, 0, 204, 0, 0, 0, 106, 0, 0, 0, 30, 0, 0, 0, 202, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, 0, 189, 0, 0, 0, 99, 0, 0, 0, 123, 0, 0, 0, 110, 0, 0, 0, 42, 0, 0, 0, 210, 0, 0, 0, 135, 0, 0, 0, 72, 0, 0, 0, 255, 0, 0, 0, 161, 0, 0, 0, 202, 0, 0, 0, 233, 0, 0, 0, 21, 0, 0, 0, +133, 0, 0, 0, 220, 0, 0, 0, 219, 0, 0, 0, 44, 0, 0, 0, 57, 0, 0, 0, 18, 0, 0, 0, 145, 0, 0, 0, 169, 0, 0, 0, 32, 0, 0, 0, 170, 0, 0, 0, 79, 0, 0, 0, 41, 0, 0, 0, 244, 0, 0, 0, 21, 0, 0, 0, 122, 0, 0, 0, 210, 0, 0, 0, 245, 0, 0, 0, 50, 0, 0, 0, 204, 0, 0, 0, 96, 0, 0, 0, 4, 0, 0, 0, 229, 0, 0, 0, 16, 0, 0, 0, 71, 0, 0, 0, 59, 0, 0, 0, 250, 0, 0, 0, 144, 0, 0, 0, 252, 0, 0, 0, 48, 0, 0, 0, 181, 0, 0, 0, 234, 0, 0, 0, 111, 0, 0, 0, 86, 0, 0, 0, 143, 0, 0, 0, 251, 0, 0, 0, 14, 0, 0, 0, 167, 0, 0, 0, +59, 0, 0, 0, 200, 0, 0, 0, 178, 0, 0, 0, 255, 0, 0, 0, 2, 0, 0, 0, 122, 0, 0, 0, 51, 0, 0, 0, 148, 0, 0, 0, 147, 0, 0, 0, 42, 0, 0, 0, 3, 0, 0, 0, 224, 0, 0, 0, 150, 0, 0, 0, 58, 0, 0, 0, 108, 0, 0, 0, 15, 0, 0, 0, 90, 0, 0, 0, 99, 0, 0, 0, 103, 0, 0, 0, 225, 0, 0, 0, 155, 0, 0, 0, 71, 0, 0, 0, 120, 0, 0, 0, 159, 0, 0, 0, 56, 0, 0, 0, 121, 0, 0, 0, 172, 0, 0, 0, 151, 0, 0, 0, 102, 0, 0, 0, 29, 0, 0, 0, 94, 0, 0, 0, 81, 0, 0, 0, 238, 0, 0, 0, 36, 0, 0, 0, 66, 0, 0, 0, 232, 0, 0, 0, 88, 0, 0, 0, 75, +0, 0, 0, 138, 0, 0, 0, 3, 0, 0, 0, 117, 0, 0, 0, 134, 0, 0, 0, 55, 0, 0, 0, 134, 0, 0, 0, 226, 0, 0, 0, 151, 0, 0, 0, 78, 0, 0, 0, 61, 0, 0, 0, 63, 0, 0, 0, 117, 0, 0, 0, 142, 0, 0, 0, 180, 0, 0, 0, 255, 0, 0, 0, 216, 0, 0, 0, 221, 0, 0, 0, 214, 0, 0, 0, 55, 0, 0, 0, 87, 0, 0, 0, 157, 0, 0, 0, 109, 0, 0, 0, 59, 0, 0, 0, 189, 0, 0, 0, 213, 0, 0, 0, 96, 0, 0, 0, 136, 0, 0, 0, 101, 0, 0, 0, 154, 0, 0, 0, 185, 0, 0, 0, 74, 0, 0, 0, 104, 0, 0, 0, 132, 0, 0, 0, 162, 0, 0, 0, 103, 0, 0, 0, 221, 0, 0, 0, +23, 0, 0, 0, 37, 0, 0, 0, 151, 0, 0, 0, 4, 0, 0, 0, 139, 0, 0, 0, 94, 0, 0, 0, 187, 0, 0, 0, 64, 0, 0, 0, 94, 0, 0, 0, 188, 0, 0, 0, 22, 0, 0, 0, 146, 0, 0, 0, 5, 0, 0, 0, 196, 0, 0, 0, 192, 0, 0, 0, 78, 0, 0, 0, 114, 0, 0, 0, 144, 0, 0, 0, 14, 0, 0, 0, 171, 0, 0, 0, 207, 0, 0, 0, 138, 0, 0, 0, 237, 0, 0, 0, 239, 0, 0, 0, 185, 0, 0, 0, 45, 0, 0, 0, 59, 0, 0, 0, 248, 0, 0, 0, 67, 0, 0, 0, 91, 0, 0, 0, 186, 0, 0, 0, 45, 0, 0, 0, 235, 0, 0, 0, 47, 0, 0, 0, 82, 0, 0, 0, 210, 0, 0, 0, 209, 0, 0, 0, 90, +0, 0, 0, 64, 0, 0, 0, 180, 0, 0, 0, 171, 0, 0, 0, 230, 0, 0, 0, 173, 0, 0, 0, 159, 0, 0, 0, 70, 0, 0, 0, 105, 0, 0, 0, 74, 0, 0, 0, 179, 0, 0, 0, 142, 0, 0, 0, 170, 0, 0, 0, 234, 0, 0, 0, 156, 0, 0, 0, 138, 0, 0, 0, 32, 0, 0, 0, 22, 0, 0, 0, 93, 0, 0, 0, 140, 0, 0, 0, 19, 0, 0, 0, 189, 0, 0, 0, 246, 0, 0, 0, 29, 0, 0, 0, 197, 0, 0, 0, 36, 0, 0, 0, 189, 0, 0, 0, 144, 0, 0, 0, 42, 0, 0, 0, 28, 0, 0, 0, 199, 0, 0, 0, 19, 0, 0, 0, 59, 0, 0, 0, 84, 0, 0, 0, 220, 0, 0, 0, 22, 0, 0, 0, 13, 0, 0, 0, 24, +0, 0, 0, 190, 0, 0, 0, 53, 0, 0, 0, 100, 0, 0, 0, 97, 0, 0, 0, 82, 0, 0, 0, 2, 0, 0, 0, 128, 0, 0, 0, 175, 0, 0, 0, 5, 0, 0, 0, 247, 0, 0, 0, 166, 0, 0, 0, 66, 0, 0, 0, 211, 0, 0, 0, 143, 0, 0, 0, 46, 0, 0, 0, 121, 0, 0, 0, 38, 0, 0, 0, 168, 0, 0, 0, 187, 0, 0, 0, 178, 0, 0, 0, 23, 0, 0, 0, 72, 0, 0, 0, 178, 0, 0, 0, 122, 0, 0, 0, 10, 0, 0, 0, 137, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 168, 0, 0, 0, 136, 0, 0, 0, 227, 0, 0, 0, 145, 0, 0, 0, 192, 0, 0, 0, 110, 0, 0, 0, 187, 0, 0, 0, 138, 0, 0, 0, 39, 0, 0, 0, 130, 0, 0, 0, 81, 0, 0, 0, 131, 0, 0, 0, 178, 0, 0, 0, 40, 0, 0, 0, 169, 0, 0, 0, 131, 0, 0, 0, 235, 0, 0, 0, 166, 0, 0, 0, 169, 0, 0, 0, 77, 0, 0, 0, 23, 0, 0, 0, 89, 0, 0, 0, 34, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 80, 0, 0, +0, 69, 0, 0, 0, 203, 0, 0, 0, 72, 0, 0, 0, 75, 0, 0, 0, 24, 0, 0, 0, 51, 0, 0, 0, 124, 0, 0, 0, 231, 0, 0, 0, 38, 0, 0, 0, 186, 0, 0, 0, 77, 0, 0, 0, 50, 0, 0, 0, 254, 0, 0, 0, 83, 0, 0, 0, 244, 0, 0, 0, 250, 0, 0, 0, 131, 0, 0, 0, 227, 0, 0, 0, 165, 0, 0, 0, 121, 0, 0, 0, 102, 0, 0, 0, 115, 0, 0, 0, 239, 0, 0, 0, 128, 0, 0, 0, 35, 0, 0, 0, 104, 0, 0, 0, 194, 0, 0, 0, 96, 0, 0, 0, 221, 0, 0, 0, 169, 0, 0, 0, 51, 0, 0, 0, 220, 0, 0, 0, 3, 0, 0, 0, 122, 0, 0, 0, 224, 0, 0, 0, 224, 0, 0, 0, 62, 0, 0, +0, 52, 0, 0, 0, 92, 0, 0, 0, 19, 0, 0, 0, 251, 0, 0, 0, 192, 0, 0, 0, 227, 0, 0, 0, 120, 0, 0, 0, 43, 0, 0, 0, 84, 0, 0, 0, 88, 0, 0, 0, 34, 0, 0, 0, 155, 0, 0, 0, 118, 0, 0, 0, 129, 0, 0, 0, 127, 0, 0, 0, 147, 0, 0, 0, 156, 0, 0, 0, 37, 0, 0, 0, 60, 0, 0, 0, 210, 0, 0, 0]).concat([233, 0, 0, 0, 150, 0, 0, 0, 33, 0, 0, 0, 38, 0, 0, 0, 8, 0, 0, 0, 245, 0, 0, 0, 237, 0, 0, 0, 149, 0, 0, 0, 17, 0, 0, 0, 174, 0, 0, 0, 4, 0, 0, 0, 90, 0, 0, 0, 185, 0, 0, 0, 232, 0, 0, 0, 197, 0, 0, 0, 18, 0, 0, 0, 151, +0, 0, 0, 31, 0, 0, 0, 131, 0, 0, 0, 254, 0, 0, 0, 62, 0, 0, 0, 148, 0, 0, 0, 153, 0, 0, 0, 212, 0, 0, 0, 45, 0, 0, 0, 249, 0, 0, 0, 82, 0, 0, 0, 89, 0, 0, 0, 92, 0, 0, 0, 130, 0, 0, 0, 166, 0, 0, 0, 240, 0, 0, 0, 117, 0, 0, 0, 126, 0, 0, 0, 232, 0, 0, 0, 236, 0, 0, 0, 204, 0, 0, 0, 172, 0, 0, 0, 24, 0, 0, 0, 33, 0, 0, 0, 9, 0, 0, 0, 103, 0, 0, 0, 102, 0, 0, 0, 103, 0, 0, 0, 179, 0, 0, 0, 64, 0, 0, 0, 41, 0, 0, 0, 209, 0, 0, 0, 203, 0, 0, 0, 27, 0, 0, 0, 8, 0, 0, 0, 158, 0, 0, 0, 156, 0, 0, 0, 183, +0, 0, 0, 83, 0, 0, 0, 185, 0, 0, 0, 59, 0, 0, 0, 113, 0, 0, 0, 8, 0, 0, 0, 149, 0, 0, 0, 18, 0, 0, 0, 26, 0, 0, 0, 88, 0, 0, 0, 175, 0, 0, 0, 126, 0, 0, 0, 130, 0, 0, 0, 82, 0, 0, 0, 67, 0, 0, 0, 79, 0, 0, 0, 17, 0, 0, 0, 57, 0, 0, 0, 244, 0, 0, 0, 147, 0, 0, 0, 26, 0, 0, 0, 38, 0, 0, 0, 5, 0, 0, 0, 110, 0, 0, 0, 68, 0, 0, 0, 163, 0, 0, 0, 249, 0, 0, 0, 100, 0, 0, 0, 175, 0, 0, 0, 231, 0, 0, 0, 109, 0, 0, 0, 125, 0, 0, 0, 223, 0, 0, 0, 30, 0, 0, 0, 172, 0, 0, 0, 4, 0, 0, 0, 234, 0, 0, 0, 59, 0, 0, +0, 95, 0, 0, 0, 155, 0, 0, 0, 232, 0, 0, 0, 36, 0, 0, 0, 157, 0, 0, 0, 14, 0, 0, 0, 229, 0, 0, 0, 46, 0, 0, 0, 62, 0, 0, 0, 223, 0, 0, 0, 169, 0, 0, 0, 247, 0, 0, 0, 212, 0, 0, 0, 80, 0, 0, 0, 113, 0, 0, 0, 240, 0, 0, 0, 120, 0, 0, 0, 62, 0, 0, 0, 168, 0, 0, 0, 56, 0, 0, 0, 194, 0, 0, 0, 87, 0, 0, 0, 86, 0, 0, 0, 66, 0, 0, 0, 154, 0, 0, 0, 177, 0, 0, 0, 226, 0, 0, 0, 248, 0, 0, 0, 69, 0, 0, 0, 170, 0, 0, 0, 17, 0, 0, 0, 72, 0, 0, 0, 95, 0, 0, 0, 23, 0, 0, 0, 196, 0, 0, 0, 84, 0, 0, 0, 39, 0, 0, 0, +220, 0, 0, 0, 93, 0, 0, 0, 170, 0, 0, 0, 221, 0, 0, 0, 65, 0, 0, 0, 188, 0, 0, 0, 223, 0, 0, 0, 129, 0, 0, 0, 185, 0, 0, 0, 83, 0, 0, 0, 238, 0, 0, 0, 82, 0, 0, 0, 195, 0, 0, 0, 241, 0, 0, 0, 167, 0, 0, 0, 109, 0, 0, 0, 179, 0, 0, 0, 95, 0, 0, 0, 146, 0, 0, 0, 111, 0, 0, 0, 204, 0, 0, 0, 145, 0, 0, 0, 184, 0, 0, 0, 149, 0, 0, 0, 5, 0, 0, 0, 223, 0, 0, 0, 60, 0, 0, 0, 100, 0, 0, 0, 87, 0, 0, 0, 57, 0, 0, 0, 97, 0, 0, 0, 81, 0, 0, 0, 173, 0, 0, 0, 140, 0, 0, 0, 56, 0, 0, 0, 123, 0, 0, 0, 200, 0, 0, +0, 222, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 190, 0, 0, 0, 161, 0, 0, 0, 176, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 36, 0, 0, 0, 29, 0, 0, 0, 138, 0, 0, 0, 103, 0, 0, 0, 32, 0, 0, 0, 238, 0, 0, 0, 66, 0, 0, 0, 235, 0, 0, 0, 56, 0, 0, 0, 237, +0, 0, 0, 11, 0, 0, 0, 139, 0, 0, 0, 205, 0, 0, 0, 70, 0, 0, 0, 157, 0, 0, 0, 94, 0, 0, 0, 107, 0, 0, 0, 30, 0, 0, 0, 36, 0, 0, 0, 157, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 26, 0, 0, 0, 204, 0, 0, 0, 5, 0, 0, 0, 78, 0, 0, 0, 146, 0, 0, 0, 56, 0, 0, 0, 225, 0, 0, 0, 31, 0, 0, 0, 80, 0, 0, 0, 78, 0, 0, 0, 238, 0, 0, 0, 28, 0, 0, 0, 145, 0, 0, 0, 230, 0, 0, 0, 17, 0, 0, 0, 189, 0, 0, 0, 142, 0, 0, 0, 85, 0, 0, 0, 26, 0, 0, 0, 24, 0, 0, 0, 117, 0, 0, 0, 102, 0, 0, 0, 175, 0, 0, 0, 77, 0, 0, 0, 123, 0, 0, +0, 15, 0, 0, 0, 174, 0, 0, 0, 109, 0, 0, 0, 133, 0, 0, 0, 202, 0, 0, 0, 130, 0, 0, 0, 88, 0, 0, 0, 33, 0, 0, 0, 156, 0, 0, 0, 24, 0, 0, 0, 224, 0, 0, 0, 237, 0, 0, 0, 236, 0, 0, 0, 34, 0, 0, 0, 128, 0, 0, 0, 47, 0, 0, 0, 104, 0, 0, 0, 59, 0, 0, 0, 10, 0, 0, 0, 57, 0, 0, 0, 29, 0, 0, 0, 106, 0, 0, 0, 21, 0, 0, 0, 87, 0, 0, 0, 252, 0, 0, 0, 240, 0, 0, 0, 99, 0, 0, 0, 84, 0, 0, 0, 219, 0, 0, 0, 57, 0, 0, 0, 219, 0, 0, 0, 232, 0, 0, 0, 92, 0, 0, 0, 100, 0, 0, 0, 255, 0, 0, 0, 160, 0, 0, 0, 9, 0, 0, 0, +79, 0, 0, 0, 59, 0, 0, 0, 183, 0, 0, 0, 50, 0, 0, 0, 96, 0, 0, 0, 153, 0, 0, 0, 148, 0, 0, 0, 253, 0, 0, 0, 148, 0, 0, 0, 130, 0, 0, 0, 45, 0, 0, 0, 36, 0, 0, 0, 246, 0, 0, 0, 90, 0, 0, 0, 68, 0, 0, 0, 241, 0, 0, 0, 85, 0, 0, 0, 44, 0, 0, 0, 219, 0, 0, 0, 234, 0, 0, 0, 124, 0, 0, 0, 132, 0, 0, 0, 124, 0, 0, 0, 1, 0, 0, 0, 172, 0, 0, 0, 227, 0, 0, 0, 253, 0, 0, 0, 201, 0, 0, 0, 39, 0, 0, 0, 193, 0, 0, 0, 90, 0, 0, 0, 185, 0, 0, 0, 222, 0, 0, 0, 79, 0, 0, 0, 90, 0, 0, 0, 144, 0, 0, 0, 221, 0, 0, 0, +198, 0, 0, 0, 103, 0, 0, 0, 170, 0, 0, 0, 111, 0, 0, 0, 138, 0, 0, 0, 58, 0, 0, 0, 120, 0, 0, 0, 82, 0, 0, 0, 135, 0, 0, 0, 201, 0, 0, 0, 151, 0, 0, 0, 99, 0, 0, 0, 177, 0, 0, 0, 221, 0, 0, 0, 84, 0, 0, 0, 95, 0, 0, 0, 193, 0, 0, 0, 248, 0, 0, 0, 241, 0, 0, 0, 6, 0, 0, 0, 166, 0, 0, 0, 168, 0, 0, 0, 163, 0, 0, 0, 136, 0, 0, 0, 130, 0, 0, 0, 212, 0, 0, 0, 203, 0, 0, 0, 166, 0, 0, 0, 25, 0, 0, 0, 221, 0, 0, 0, 209, 0, 0, 0, 17, 0, 0, 0, 135, 0, 0, 0, 8, 0, 0, 0, 23, 0, 0, 0, 76, 0, 0, 0, 55, 0, 0, +0, 42, 0, 0, 0, 161, 0, 0, 0, 12, 0, 0, 0, 243, 0, 0, 0, 8, 0, 0, 0, 67, 0, 0, 0, 217, 0, 0, 0, 36, 0, 0, 0, 30, 0, 0, 0, 131, 0, 0, 0, 167, 0, 0, 0, 223, 0, 0, 0, 145, 0, 0, 0, 202, 0, 0, 0, 189, 0, 0, 0, 105, 0, 0, 0, 71, 0, 0, 0, 141, 0, 0, 0, 27, 0, 0, 0, 226, 0, 0, 0, 185, 0, 0, 0, 78, 0, 0, 0, 181, 0, 0, 0, 225, 0, 0, 0, 118, 0, 0, 0, 179, 0, 0, 0, 28, 0, 0, 0, 147, 0, 0, 0, 3, 0, 0, 0, 206, 0, 0, 0, 95, 0, 0, 0, 179, 0, 0, 0, 90, 0, 0, 0, 29, 0, 0, 0, 218, 0, 0, 0, 228, 0, 0, 0, 97, 0, 0, +0, 3, 0, 0, 0, 80, 0, 0, 0, 169, 0, 0, 0, 139, 0, 0, 0, 104, 0, 0, 0, 24, 0, 0, 0, 239, 0, 0, 0, 178, 0, 0, 0, 28, 0, 0, 0, 132, 0, 0, 0, 59, 0, 0, 0, 162, 0, 0, 0, 68, 0, 0, 0, 149, 0, 0, 0, 163, 0, 0, 0, 4, 0, 0, 0, 59, 0, 0, 0, 214, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 175, 0, 0, 0, 118, 0, 0, 0, 66, 0, 0, 0, 103, 0, 0, 0, 2, 0, 0, 0, 125, 0, 0, 0, 133, 0, 0, 0, 86, 0, 0, 0, 206, 0, 0, 0, 114, 0, 0, 0, 14, 0, 0, 0, 41, 0, 0, 0, 132, 0, 0, 0, 178, 0, 0, 0, 125, 0, 0, 0, 210, 0, 0, 0, 69, 0, 0, 0, +190, 0, 0, 0, 87, 0, 0, 0, 6, 0, 0, 0, 237, 0, 0, 0, 127, 0, 0, 0, 207, 0, 0, 0, 237, 0, 0, 0, 205, 0, 0, 0, 239, 0, 0, 0, 25, 0, 0, 0, 214, 0, 0, 0, 188, 0, 0, 0, 21, 0, 0, 0, 121, 0, 0, 0, 100, 0, 0, 0, 210, 0, 0, 0, 24, 0, 0, 0, 227, 0, 0, 0, 32, 0, 0, 0, 103, 0, 0, 0, 58, 0, 0, 0, 84, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 253, 0, 0, 0, 4, 0, 0, 0, 197, 0, 0, 0, 251, 0, 0, 0, 153, 0, 0, 0, 231, 0, 0, 0, 232, 0, 0, 0, 251, 0, 0, 0, 140, 0, 0, 0, 225, 0, 0, 0, 66, 0, 0, 0, 3, 0, 0, 0, 239, 0, 0, 0, 157, 0, 0, 0, 217, 0, 0, 0, 158, 0, 0, 0, 77, 0, 0, 0, 247, 0, 0, 0, 128, 0, 0, 0, 207, 0, 0, 0, 46, 0, 0, 0, 204, 0, 0, 0, 155, 0, 0, 0, 69, 0, 0, 0, 201, 0, 0, 0, 123, 0, 0, 0, 122, 0, 0, 0, 188, 0, 0, 0, 55, 0, 0, 0, 168, 0, 0, 0, +82, 0, 0, 0, 150, 0, 0, 0, 17, 0, 0, 0, 65, 0, 0, 0, 138, 0, 0, 0, 71, 0, 0, 0, 145, 0, 0, 0, 254, 0, 0, 0, 182, 0, 0, 0, 218, 0, 0, 0, 122, 0, 0, 0, 84, 0, 0, 0, 99, 0, 0, 0, 209, 0, 0, 0, 20, 0, 0, 0, 53, 0, 0, 0, 5, 0, 0, 0, 134, 0, 0, 0, 140, 0, 0, 0, 169, 0, 0, 0, 54, 0, 0, 0, 63, 0, 0, 0, 242, 0, 0, 0, 133, 0, 0, 0, 84, 0, 0, 0, 78, 0, 0, 0, 146, 0, 0, 0, 216, 0, 0, 0, 133, 0, 0, 0, 1, 0, 0, 0, 70, 0, 0, 0, 214, 0, 0, 0, 80, 0, 0, 0, 83, 0, 0, 0, 205, 0, 0, 0, 243, 0, 0, 0, 134, 0, 0, 0, 64, +0, 0, 0, 230, 0, 0, 0, 57, 0, 0, 0, 66, 0, 0, 0, 149, 0, 0, 0, 214, 0, 0, 0, 203, 0, 0, 0, 69, 0, 0, 0, 26, 0, 0, 0, 32, 0, 0, 0, 200, 0, 0, 0, 69, 0, 0, 0, 75, 0, 0, 0, 50, 0, 0, 0, 105, 0, 0, 0, 4, 0, 0, 0, 177, 0, 0, 0, 175, 0, 0, 0, 32, 0, 0, 0, 70, 0, 0, 0, 199, 0, 0, 0, 107, 0, 0, 0, 35, 0, 0, 0, 91, 0, 0, 0, 105, 0, 0, 0, 238, 0, 0, 0, 48, 0, 0, 0, 63, 0, 0, 0, 112, 0, 0, 0, 131, 0, 0, 0, 71, 0, 0, 0, 192, 0, 0, 0, 219, 0, 0, 0, 85, 0, 0, 0, 8, 0, 0, 0, 168, 0, 0, 0, 123, 0, 0, 0, 24, 0, 0, +0, 109, 0, 0, 0, 245, 0, 0, 0, 4, 0, 0, 0, 90, 0, 0, 0, 32, 0, 0, 0, 12, 0, 0, 0, 74, 0, 0, 0, 140, 0, 0, 0, 96, 0, 0, 0, 174, 0, 0, 0, 174, 0, 0, 0, 15, 0, 0, 0, 100, 0, 0, 0, 85, 0, 0, 0, 85, 0, 0, 0, 46, 0, 0, 0, 213, 0, 0, 0, 29, 0, 0, 0, 83, 0, 0, 0, 49, 0, 0, 0, 66, 0, 0, 0, 65, 0, 0, 0, 202, 0, 0, 0, 252, 0, 0, 0, 136, 0, 0, 0, 107, 0, 0, 0, 150, 0, 0, 0, 120, 0, 0, 0, 10, 0, 0, 0, 139, 0, 0, 0, 131, 0, 0, 0, 220, 0, 0, 0, 188, 0, 0, 0, 175, 0, 0, 0, 64, 0, 0, 0, 182, 0, 0, 0, 141, 0, 0, 0, +127, 0, 0, 0, 239, 0, 0, 0, 180, 0, 0, 0, 209, 0, 0, 0, 63, 0, 0, 0, 204, 0, 0, 0, 162, 0, 0, 0, 116, 0, 0, 0, 201, 0, 0, 0, 194, 0, 0, 0, 146, 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, 0, 171, 0, 0, 0, 219, 0, 0, 0, 191, 0, 0, 0, 79, 0, 0, 0, 147, 0, 0, 0, 28, 0, 0, 0, 6, 0, 0, 0, 45, 0, 0, 0, 102, 0, 0, 0, 101, 0, 0, 0, 2, 0, 0, 0, 164, 0, 0, 0, 151, 0, 0, 0, 24, 0, 0, 0, 253, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 171, 0, 0, 0, 3, 0, 0, 0, 236, 0, 0, 0, 206, 0, 0, 0, 193, 0, 0, 0, 191, 0, 0, 0, 55, 0, 0, 0, +248, 0, 0, 0, 19, 0, 0, 0, 83, 0, 0, 0, 165, 0, 0, 0, 229, 0, 0, 0, 12, 0, 0, 0, 58, 0, 0, 0, 168, 0, 0, 0, 85, 0, 0, 0, 185, 0, 0, 0, 255, 0, 0, 0, 104, 0, 0, 0, 228, 0, 0, 0, 230, 0, 0, 0, 109, 0, 0, 0, 48, 0, 0, 0, 125, 0, 0, 0, 48, 0, 0, 0, 53, 0, 0, 0, 194, 0, 0, 0, 120, 0, 0, 0, 135, 0, 0, 0, 249, 0, 0, 0, 252, 0, 0, 0, 107, 0, 0, 0, 90, 0, 0, 0, 195, 0, 0, 0, 183, 0, 0, 0, 101, 0, 0, 0, 216, 0, 0, 0, 46, 0, 0, 0, 199, 0, 0, 0, 165, 0, 0, 0, 12, 0, 0, 0, 198, 0, 0, 0, 220, 0, 0, 0, 18, 0, 0, +0, 170, 0, 0, 0, 214, 0, 0, 0, 79, 0, 0, 0, 197, 0, 0, 0, 56, 0, 0, 0, 188, 0, 0, 0, 14, 0, 0, 0, 226, 0, 0, 0, 60, 0, 0, 0, 118, 0, 0, 0, 134, 0, 0, 0, 56, 0, 0, 0, 242, 0, 0, 0, 123, 0, 0, 0, 44, 0, 0, 0, 22, 0, 0, 0, 120, 0, 0, 0, 141, 0, 0, 0, 245, 0, 0, 0, 164, 0, 0, 0, 21, 0, 0, 0, 218, 0, 0, 0, 219, 0, 0, 0, 38, 0, 0, 0, 133, 0, 0, 0, 160, 0, 0, 0, 86, 0, 0, 0, 221, 0, 0, 0, 29, 0, 0, 0, 227, 0, 0, 0, 179, 0, 0, 0, 253, 0, 0, 0, 64, 0, 0, 0, 239, 0, 0, 0, 242, 0, 0, 0, 217, 0, 0, 0, 161, 0, +0, 0, 179, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 73, 0, 0, 0, 14, 0, 0, 0, 230, 0, 0, 0, 88, 0, 0, 0, 16, 0, 0, 0, 122, 0, 0, 0, 82, 0, 0, 0, 218, 0, 0, 0, 181, 0, 0, 0, 125, 0, 0, 0, 55, 0, 0, 0, 106, 0, 0, 0, 62, 0, 0, 0, 161, 0, 0, 0, 120, +0, 0, 0, 206, 0, 0, 0, 199, 0, 0, 0, 28, 0, 0, 0, 36, 0, 0, 0, 35, 0, 0, 0, 219, 0, 0, 0, 125, 0, 0, 0, 251, 0, 0, 0, 140, 0, 0, 0, 141, 0, 0, 0, 220, 0, 0, 0, 48, 0, 0, 0, 103, 0, 0, 0, 105, 0, 0, 0, 117, 0, 0, 0, 59, 0, 0, 0, 169, 0, 0, 0, 234, 0, 0, 0, 109, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 96, 0, 0, 0, 244, 0, 0, 0, 96, 0, 0, 0, 135, 0, 0, 0, 25, 0, 0, 0, 68, 0, 0, 0, 140, 0, 0, 0, 74, 0, 0, 0, 139, 0, 0, 0, 62, 0, 0, 0, 251, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 166, 0, +0, 0, 158, 0, 0, 0, 159, 0, 0, 0, 239, 0, 0, 0, 207, 0, 0, 0, 217, 0, 0, 0, 210, 0, 0, 0, 76, 0, 0, 0, 116, 0, 0, 0, 49, 0, 0, 0, 208, 0, 0, 0, 52, 0, 0, 0, 164, 0, 0, 0, 235, 0, 0, 0, 4, 0, 0, 0, 164, 0, 0, 0, 140, 0, 0, 0, 143, 0, 0, 0, 113, 0, 0, 0, 39, 0, 0, 0, 149, 0, 0, 0, 133, 0, 0, 0, 93, 0, 0, 0, 85, 0, 0, 0, 75, 0, 0, 0, 177, 0, 0, 0, 38, 0, 0, 0, 38, 0, 0, 0, 200, 0, 0, 0, 174, 0, 0, 0, 106, 0, 0, 0, 125, 0, 0, 0, 162, 0, 0, 0, 33, 0, 0, 0, 202, 0, 0, 0, 206, 0, 0, 0, 56, 0, 0, 0, 171, +0, 0, 0, 15, 0, 0, 0, 208, 0, 0, 0, 213, 0, 0, 0, 43, 0, 0, 0, 107, 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, 0, 103, 0, 0, 0, 12, 0, 0, 0, 241, 0, 0, 0, 58, 0, 0, 0, 154, 0, 0, 0, 234, 0, 0, 0, 9, 0, 0, 0, 57, 0, 0, 0, 239, 0, 0, 0, 209, 0, 0, 0, 48, 0, 0, 0, 188, 0, 0, 0, 51, 0, 0, 0, 186, 0, 0, 0, 177, 0, 0, 0, 106, 0, 0, 0, 197, 0, 0, 0, 39, 0, 0, 0, 8, 0, 0, 0, 127, 0, 0, 0, 84, 0, 0, 0, 128, 0, 0, 0, 61, 0, 0, 0, 171, 0, 0, 0, 246, 0, 0, 0, 21, 0, 0, 0, 122, 0, 0, 0, 194, 0, 0, 0, 64, 0, 0, 0, 115, 0, +0, 0, 114, 0, 0, 0, 132, 0, 0, 0, 86, 0, 0, 0, 130, 0, 0, 0, 182, 0, 0, 0, 18, 0, 0, 0, 112, 0, 0, 0, 127, 0, 0, 0, 247, 0, 0, 0, 240, 0, 0, 0, 189, 0, 0, 0, 91, 0, 0, 0, 169, 0, 0, 0, 213, 0, 0, 0, 197, 0, 0, 0, 95, 0, 0, 0, 89, 0, 0, 0, 191, 0, 0, 0, 127, 0, 0, 0, 179, 0, 0, 0, 85, 0, 0, 0, 34, 0, 0, 0, 2, 0, 0, 0, 201, 0, 0, 0, 68, 0, 0, 0, 85, 0, 0, 0, 135, 0, 0, 0, 143, 0, 0, 0, 150, 0, 0, 0, 152, 0, 0, 0, 100, 0, 0, 0, 109, 0, 0, 0, 21, 0, 0, 0, 176, 0, 0, 0, 139, 0, 0, 0, 170, 0, 0, 0, 30, +0, 0, 0, 236, 0, 0, 0, 199, 0, 0, 0, 165, 0, 0, 0, 143, 0, 0, 0, 31, 0, 0, 0, 146, 0, 0, 0, 4, 0, 0, 0, 198, 0, 0, 0, 5, 0, 0, 0, 246, 0, 0, 0, 223, 0, 0, 0, 161, 0, 0, 0, 204, 0, 0, 0, 31, 0, 0, 0, 129, 0, 0, 0, 245, 0, 0, 0, 14, 0, 0, 0, 156, 0, 0, 0, 87, 0, 0, 0, 220, 0, 0, 0, 227, 0, 0, 0, 187, 0, 0, 0, 6, 0, 0, 0, 135, 0, 0, 0, 30, 0, 0, 0, 254, 0, 0, 0, 35, 0, 0, 0, 108, 0, 0, 0, 216, 0, 0, 0, 43, 0, 0, 0, 91, 0, 0, 0, 22, 0, 0, 0, 234, 0, 0, 0, 32, 0, 0, 0, 241, 0, 0, 0, 211, 0, 0, 0, 104, +0, 0, 0, 143, 0, 0, 0, 174, 0, 0, 0, 91, 0, 0, 0, 208, 0, 0, 0, 169, 0, 0, 0, 26, 0, 0, 0, 25, 0, 0, 0, 168, 0, 0, 0, 54, 0, 0, 0, 251, 0, 0, 0, 43, 0, 0, 0, 87, 0, 0, 0, 136, 0, 0, 0, 125, 0, 0, 0, 144, 0, 0, 0, 213, 0, 0, 0, 166, 0, 0, 0, 243, 0, 0, 0, 220, 0, 0, 0, 56, 0, 0, 0, 137, 0, 0, 0, 78, 0, 0, 0, 31, 0, 0, 0, 204, 0, 0, 0, 25, 0, 0, 0, 218, 0, 0, 0, 155, 0, 0, 0, 59, 0, 0, 0, 67, 0, 0, 0, 72, 0, 0, 0, 33, 0, 0, 0, 46, 0, 0, 0, 35, 0, 0, 0, 77, 0, 0, 0, 61, 0, 0, 0, 174, 0, 0, 0, 248, 0, +0, 0, 140, 0, 0, 0, 252, 0, 0, 0, 221, 0, 0, 0, 166, 0, 0, 0, 116, 0, 0, 0, 55, 0, 0, 0, 101, 0, 0, 0, 202, 0, 0, 0, 238, 0, 0, 0, 26, 0, 0, 0, 25, 0, 0, 0, 142, 0, 0, 0, 159, 0, 0, 0, 100, 0, 0, 0, 111, 0, 0, 0, 12, 0, 0, 0, 139, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 185, 0, 0, 0, 194, 0, 0, 0, 240, 0, 0, 0, 114, 0, 0, 0, 184, 0, 0, 0, 21, 0, 0, 0, 22, 0, 0, 0, 204, 0, 0, 0, 141, 0, 0, 0, 60, 0, 0, 0, 111, 0, 0, 0, 37, 0, 0, 0, 237, 0, 0, 0, 244, 0, 0, 0, 70, 0, 0, 0, 46, 0, 0, 0, 12, 0, 0, 0, 96, 0, 0, 0, 15, 0, 0, 0, 226, 0, 0, 0, 132, 0, 0, 0, 52, 0, 0, 0, 85, 0, 0, 0, 137, 0, 0, 0, 89, 0, 0, 0, 52, 0, 0, 0, 27, 0, 0, 0, 245, 0, 0, 0, 141, 0, 0, 0, 254, 0, 0, 0, 8, 0, 0, 0, 248, 0, 0, 0, 171, 0, 0, 0, 147, 0, 0, 0, 188, 0, 0, +0, 68, 0, 0, 0, 186, 0, 0, 0, 27, 0, 0, 0, 117, 0, 0, 0, 75, 0, 0, 0, 73, 0, 0, 0, 111, 0, 0, 0, 208, 0, 0, 0, 84, 0, 0, 0, 46, 0, 0, 0, 99, 0, 0, 0, 186, 0, 0, 0, 181, 0, 0, 0, 234, 0, 0, 0, 237, 0, 0, 0, 50, 0, 0, 0, 20, 0, 0, 0, 201, 0, 0, 0, 148, 0, 0, 0, 216, 0, 0, 0, 197, 0, 0, 0, 206, 0, 0, 0, 244, 0, 0, 0, 16, 0, 0, 0, 104, 0, 0, 0, 224, 0, 0, 0, 56, 0, 0, 0, 39, 0, 0, 0, 116, 0, 0, 0, 28, 0, 0, 0, 20, 0, 0, 0, 155, 0, 0, 0, 212, 0, 0, 0, 100, 0, 0, 0, 97, 0, 0, 0, 113, 0, 0, 0, 90, 0, 0, +0, 182, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 79, 0, 0, 0, 247, 0, 0, 0, 142, 0, 0, 0, 186, 0, 0, 0, 165, 0, 0, 0, 72, 0, 0, 0, 154, 0, 0, 0, 199, 0, 0, 0, 250, 0, 0, 0, 154, 0, 0, 0, 240, 0, 0, 0, 180, 0, 0, 0, 98, 0, 0, 0, 173, 0, 0, 0, 242, 0, 0, 0, 94, 0, 0, 0, 204, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 26, 0, 0, 0, 245, 0, 0, 0, 118, 0, 0, 0, 253, 0, 0, 0, 228, 0, 0, 0, 175, 0, 0, 0, 185, 0, 0, 0, 3, 0, 0, 0, 89, 0, 0, 0, 206, 0, 0, 0, 99, 0, 0, 0, 210, 0, 0, 0, 59, 0, 0, 0, 31, 0, 0, 0, 205, 0, 0, +0, 33, 0, 0, 0, 12, 0, 0, 0, 173, 0, 0, 0, 68, 0, 0, 0, 165, 0, 0, 0, 151, 0, 0, 0, 172, 0, 0, 0, 128, 0, 0, 0, 17, 0, 0, 0, 2, 0, 0, 0, 155, 0, 0, 0, 12, 0, 0, 0, 229, 0, 0, 0, 139, 0, 0, 0, 205, 0, 0, 0, 251, 0, 0, 0, 121, 0, 0, 0, 119, 0, 0, 0, 21, 0, 0, 0, 190, 0, 0, 0, 154, 0, 0, 0, 13, 0, 0, 0, 186, 0, 0, 0, 56, 0, 0, 0, 114, 0, 0, 0, 32, 0, 0, 0, 138, 0, 0, 0, 245, 0, 0, 0, 190, 0, 0, 0, 89, 0, 0, 0, 147, 0, 0, 0, 121, 0, 0, 0, 183, 0, 0, 0, 246, 0, 0, 0, 106, 0, 0, 0, 12, 0, 0, 0, 56, 0, +0, 0, 39, 0, 0, 0, 26, 0, 0, 0, 96, 0, 0, 0, 244, 0, 0, 0, 134, 0, 0, 0, 59, 0, 0, 0, 171, 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 206, 0, 0, 0, 33, 0, 0, 0, 125, 0, 0, 0, 108, 0, 0, 0, 186, 0, 0, 0, 20, 0, 0, 0, 197, 0, 0, 0, 234, 0, 0, 0, 18, 0, 0, 0, 158, 0, 0, 0, 46, 0, 0, 0, 130, 0, 0, 0, 99, 0, 0, 0, 206, 0, 0, 0, 155, 0, 0, 0, 74, 0, 0, 0, 231, 0, 0, 0, 29, 0, 0, 0, 236, 0, 0, 0, 241, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 28, 0, 0, 0, 244, 0, 0, 0, 208, 0, 0, 0, 105, 0, 0, 0, 21, 0, 0, +0, 66, 0, 0, 0, 157, 0, 0, 0, 163, 0, 0, 0, 63, 0, 0, 0, 14, 0, 0, 0, 191, 0, 0, 0, 233, 0, 0, 0, 92, 0, 0, 0, 228, 0, 0, 0, 13, 0, 0, 0, 244, 0, 0, 0, 189, 0, 0, 0, 238, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 237, 0, 0, 0, 203, 0, 0, 0, 18, 0, 0, 0, 134, 0, 0, 0, 173, 0, 0, 0, 212, 0, 0, 0, 47, 0, 0, 0, 144, 0, 0, 0, 55, 0, 0, 0, 50, 0, 0, 0, 195, 0, 0, 0, 11, 0, 0, 0, 115, 0, 0, 0, 236, 0, 0, 0, 151, 0, 0, 0, 133, 0, 0, 0, 164, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0, 118, 0, 0, 0, 53, 0, 0, 0, 254, 0, 0, +0, 117, 0, 0, 0, 221, 0, 0, 0, 113, 0, 0, 0, 17, 0, 0, 0, 164, 0, 0, 0, 136, 0, 0, 0, 159, 0, 0, 0, 62, 0, 0, 0, 83, 0, 0, 0, 105, 0, 0, 0, 59, 0, 0, 0, 27, 0, 0, 0, 224, 0, 0, 0, 247, 0, 0, 0, 186, 0, 0, 0, 155, 0, 0, 0, 173, 0, 0, 0, 78, 0, 0, 0, 129, 0, 0, 0, 95, 0, 0, 0, 181, 0, 0, 0, 92, 0, 0, 0, 174, 0, 0, 0, 190, 0, 0, 0, 103, 0, 0, 0, 134, 0, 0, 0, 55, 0, 0, 0, 52, 0, 0, 0, 142, 0, 0, 0, 7, 0, 0, 0, 50, 0, 0, 0, 69, 0, 0, 0, 74, 0, 0, 0, 103, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 112, 0, 0, 0, 88, 0, 0, 0, 32, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, 0, 178, 0, 0, 0, 200, 0, 0, 0, 155, 0, 0, 0, 88, 0, 0, 0, 197, 0, 0, 0, 177, 0, 0, 0, 235, 0, 0, 0, 45, 0, 0, 0, 74, 0, 0, 0, 222, 0, 0, 0, 130, 0, 0, 0, 140, 0, 0, 0, +242, 0, 0, 0, 210, 0, 0, 0, 20, 0, 0, 0, 184, 0, 0, 0, 112, 0, 0, 0, 97, 0, 0, 0, 78, 0, 0, 0, 115, 0, 0, 0, 214, 0, 0, 0, 11, 0, 0, 0, 107, 0, 0, 0, 13, 0, 0, 0, 48, 0, 0, 0, 129, 0, 0, 0, 252, 0, 0, 0, 85, 0, 0, 0, 92, 0, 0, 0, 191, 0, 0, 0, 167, 0, 0, 0, 196, 0, 0, 0, 189, 0, 0, 0, 226, 0, 0, 0, 240, 0, 0, 0, 75, 0, 0, 0, 143, 0, 0, 0, 233, 0, 0, 0, 125, 0, 0, 0, 153, 0, 0, 0, 250, 0, 0, 0, 211, 0, 0, 0, 171, 0, 0, 0, 188, 0, 0, 0, 199, 0, 0, 0, 131, 0, 0, 0, 43, 0, 0, 0, 4, 0, 0, 0, 127, 0, 0, +0, 12, 0, 0, 0, 25, 0, 0, 0, 67, 0, 0, 0, 3, 0, 0, 0, 61, 0, 0, 0, 7, 0, 0, 0, 202, 0, 0, 0, 64, 0, 0, 0, 249, 0, 0, 0, 200, 0, 0, 0, 190, 0, 0, 0, 140, 0, 0, 0, 22, 0, 0, 0, 129, 0, 0, 0, 57, 0, 0, 0, 150, 0, 0, 0, 246, 0, 0, 0, 23, 0, 0, 0, 88, 0, 0, 0, 200, 0, 0, 0, 48, 0, 0, 0, 88, 0, 0, 0, 251, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 69, 0, 0, 0, 210, 0, 0, 0, 82, 0, 0, 0, 118, 0, 0, 0, 224, 0, 0, 0, 106, 0, 0, 0, 38, 0, 0, 0, 40, 0, 0, 0, 92, 0, 0, 0, 136, 0, 0, 0, 89, 0, 0, 0, 106, 0, 0, 0, 90, +0, 0, 0, 84, 0, 0, 0, 66, 0, 0, 0, 7, 0, 0, 0, 181, 0, 0, 0, 46, 0, 0, 0, 44, 0, 0, 0, 103, 0, 0, 0, 21, 0, 0, 0, 155, 0, 0, 0, 251, 0, 0, 0, 131, 0, 0, 0, 105, 0, 0, 0, 30, 0, 0, 0, 15, 0, 0, 0, 218, 0, 0, 0, 214, 0, 0, 0, 41, 0, 0, 0, 177, 0, 0, 0, 96, 0, 0, 0, 224, 0, 0, 0, 178, 0, 0, 0, 186, 0, 0, 0, 105, 0, 0, 0, 162, 0, 0, 0, 158, 0, 0, 0, 189, 0, 0, 0, 189, 0, 0, 0, 224, 0, 0, 0, 28, 0, 0, 0, 189, 0, 0, 0, 205, 0, 0, 0, 6, 0, 0, 0, 100, 0, 0, 0, 112, 0, 0, 0, 65, 0, 0, 0, 250, 0, 0, 0, 140, +0, 0, 0, 225, 0, 0, 0, 137, 0, 0, 0, 143, 0, 0, 0, 39, 0, 0, 0, 200, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 111, 0, 0, 0, 95, 0, 0, 0, 85, 0, 0, 0, 248, 0, 0, 0, 222, 0, 0, 0, 149, 0, 0, 0, 109, 0, 0, 0, 47, 0, 0, 0, 117, 0, 0, 0, 22, 0, 0, 0, 43, 0, 0, 0, 78, 0, 0, 0, 68, 0, 0, 0, 253, 0, 0, 0, 134, 0, 0, 0, 110, 0, 0, 0, 233, 0, 0, 0, 112, 0, 0, 0, 57, 0, 0, 0, 118, 0, 0, 0, 151, 0, 0, 0, 126, 0, 0, 0, 23, 0, 0, 0, 98, 0, 0, 0, 107, 0, 0, 0, 20, 0, 0, 0, 161, 0, 0, 0, 124, 0, 0, 0, 208, 0, 0, 0, 121, +0, 0, 0, 110, 0, 0, 0, 216, 0, 0, 0, 138, 0, 0, 0, 165, 0, 0, 0, 109, 0, 0, 0, 140, 0, 0, 0, 147, 0, 0, 0, 210, 0, 0, 0, 63, 0, 0, 0, 236, 0, 0, 0, 68, 0, 0, 0, 141, 0, 0, 0, 110, 0, 0, 0, 145, 0, 0, 0, 1, 0, 0, 0, 140, 0, 0, 0, 143, 0, 0, 0, 238, 0, 0, 0, 1, 0, 0, 0, 143, 0, 0, 0, 192, 0, 0, 0, 180, 0, 0, 0, 133, 0, 0, 0, 14, 0, 0, 0, 2, 0, 0, 0, 58, 0, 0, 0, 112, 0, 0, 0, 65, 0, 0, 0, 228, 0, 0, 0, 17, 0, 0, 0, 87, 0, 0, 0, 35, 0, 0, 0, 172, 0, 0, 0, 230, 0, 0, 0, 252, 0, 0, 0, 84, 0, 0, 0, 126, +0, 0, 0, 205, 0, 0, 0, 215, 0, 0, 0, 34, 0, 0, 0, 203, 0, 0, 0, 118, 0, 0, 0, 159, 0, 0, 0, 32, 0, 0, 0, 206, 0, 0, 0, 160, 0, 0, 0, 115, 0, 0, 0, 118, 0, 0, 0, 81, 0, 0, 0, 59, 0, 0, 0, 164, 0, 0, 0, 248, 0, 0, 0, 227, 0, 0, 0, 98, 0, 0, 0, 18, 0, 0, 0, 108, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 38, 0, 0, 0, 13, 0, 0, 0, 111, 0, 0, 0, 72, 0, 0, 0, 127, 0, 0, 0, 58, 0, 0, 0, 1, 0, 0, 0, 237, 0, 0, 0, 197, 0, 0, 0, 150, 0, 0, 0, 176, 0, 0, 0, 31, 0, 0, 0, 79, 0, 0, 0, 168, 0, 0, 0, 2, 0, +0, 0, 98, 0, 0, 0, 39, 0, 0, 0, 138, 0, 0, 0, 80, 0, 0, 0, 141, 0, 0, 0, 154, 0, 0, 0, 139, 0, 0, 0, 82, 0, 0, 0, 15, 0, 0, 0, 30, 0, 0, 0, 207, 0, 0, 0, 65, 0, 0, 0, 56, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 245, 0, 0, 0, 108, 0, 0, 0, 212, 0, 0, 0, +47, 0, 0, 0, 15, 0, 0, 0, 105, 0, 0, 0, 15, 0, 0, 0, 135, 0, 0, 0, 63, 0, 0, 0, 97, 0, 0, 0, 101, 0, 0, 0, 30, 0, 0, 0, 53, 0, 0, 0, 52, 0, 0, 0, 133, 0, 0, 0, 186, 0, 0, 0, 2, 0, 0, 0, 48, 0, 0, 0, 172, 0, 0, 0, 37, 0, 0, 0, 61, 0, 0, 0, 226, 0, 0, 0, 98, 0, 0, 0, 241, 0, 0, 0, 204, 0, 0, 0, 233, 0, 0, 0, 27, 0, 0, 0, 194, 0, 0, 0, 239, 0, 0, 0, 106, 0, 0, 0, 66, 0, 0, 0, 87, 0, 0, 0, 52, 0, 0, 0, 31, 0, 0, 0, 46, 0, 0, 0, 172, 0, 0, 0, 209, 0, 0, 0, 199, 0, 0, 0, 4, 0, 0, 0, 82, 0, 0, 0, 50, 0, +0, 0, 102, 0, 0, 0, 178, 0, 0, 0, 51, 0, 0, 0, 115, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 84, 0, 0, 0, 247, 0, 0, 0, 113, 0, 0, 0, 237, 0, 0, 0, 6, 0, 0, 0, 176, 0, 0, 0, 255, 0, 0, 0, 166, 0, 0, 0, 89, 0, 0, 0, 111, 0, 0, 0, 138, 0, 0, 0, 78, 0, 0, 0, 251, 0, 0, 0, 2, 0, 0, 0, 176, 0, 0, 0, 69, 0, 0, 0, 107, 0, 0, 0, 245, 0, 0, 0, 72, 0, 0, 0, 11, 0, 0, 0, 3, 0, 0, 0, 197, 0, 0, 0, 34, 0, 0, 0, 125, 0, 0, 0, 128, 0, 0, 0, 8, 0, 0, 0, 83, 0, 0, 0, 254, 0, 0, 0, 50, 0, 0, 0, 177, 0, 0, 0, 161, 0, 0, +0, 138, 0, 0, 0, 116, 0, 0, 0, 111, 0, 0, 0, 189, 0, 0, 0, 63, 0, 0, 0, 133, 0, 0, 0, 244, 0, 0, 0, 207, 0, 0, 0, 245, 0, 0, 0, 96, 0, 0, 0, 175, 0, 0, 0, 65, 0, 0, 0, 126, 0, 0, 0, 62, 0, 0, 0, 70, 0, 0, 0, 163, 0, 0, 0, 90, 0, 0, 0, 32, 0, 0, 0, 170, 0, 0, 0, 53, 0, 0, 0, 135, 0, 0, 0, 68, 0, 0, 0, 99, 0, 0, 0, 102, 0, 0, 0, 151, 0, 0, 0, 248, 0, 0, 0, 110, 0, 0, 0, 85, 0, 0, 0, 12, 0, 0, 0, 4, 0, 0, 0, 62, 0, 0, 0, 53, 0, 0, 0, 80, 0, 0, 0, 191, 0, 0, 0, 147, 0, 0, 0, 105, 0, 0, 0, 210, 0, 0, +0, 139, 0, 0, 0, 5, 0, 0, 0, 85, 0, 0, 0, 153, 0, 0, 0, 190, 0, 0, 0, 226, 0, 0, 0, 83, 0, 0, 0, 97, 0, 0, 0, 236, 0, 0, 0, 232, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 50, 0, 0, 0, 179, 0, 0, 0, 16, 0, 0, 0, 69, 0, 0, 0, 2, 0, 0, 0, 105, 0, 0, 0, 89, 0, 0, 0, 46, 0, 0, 0, 151, 0, 0, 0, 217, 0, 0, 0, 100, 0, 0, 0, 248, 0, 0, 0, 219, 0, 0, 0, 37, 0, 0, 0, 128, 0, 0, 0, 220, 0, 0, 0, 196, 0, 0, 0, 213, 0, 0, 0, 98, 0, 0, 0, 60, 0, 0, 0, 237, 0, 0, 0, 101, 0, 0, 0, 145, 0, 0, 0, 173, 0, 0, 0, 209, 0, 0, 0, +87, 0, 0, 0, 129, 0, 0, 0, 148, 0, 0, 0, 170, 0, 0, 0, 161, 0, 0, 0, 41, 0, 0, 0, 252, 0, 0, 0, 104, 0, 0, 0, 221, 0, 0, 0, 181, 0, 0, 0, 125, 0, 0, 0, 171, 0, 0, 0, 90, 0, 0, 0, 33, 0, 0, 0, 65, 0, 0, 0, 83, 0, 0, 0, 187, 0, 0, 0, 23, 0, 0, 0, 121, 0, 0, 0, 13, 0, 0, 0, 209, 0, 0, 0, 168, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 32, 0, 0, 0, 136, 0, 0, 0, 9, 0, 0, 0, 233, 0, 0, 0, 132, 0, 0, 0, 232, 0, 0, 0, 37, 0, 0, 0, 17, 0, 0, 0, 103, 0, 0, 0, 122, 0, 0, 0, 139, 0, 0, 0, 26, 0, 0, 0, 228, 0, 0, 0, +93, 0, 0, 0, 225, 0, 0, 0, 93, 0, 0, 0, 55, 0, 0, 0, 234, 0, 0, 0, 254, 0, 0, 0, 101, 0, 0, 0, 59, 0, 0, 0, 37, 0, 0, 0, 232, 0, 0, 0, 225, 0, 0, 0, 194, 0, 0, 0, 197, 0, 0, 0, 2, 0, 0, 0, 164, 0, 0, 0, 190, 0, 0, 0, 152, 0, 0, 0, 10, 0, 0, 0, 43, 0, 0, 0, 97, 0, 0, 0, 193, 0, 0, 0, 155, 0, 0, 0, 226, 0, 0, 0, 213, 0, 0, 0, 146, 0, 0, 0, 230, 0, 0, 0, 158, 0, 0, 0, 125, 0, 0, 0, 31, 0, 0, 0, 202, 0, 0, 0, 67, 0, 0, 0, 136, 0, 0, 0, 139, 0, 0, 0, 44, 0, 0, 0, 89, 0, 0, 0, 224, 0, 0, 0, 181, 0, 0, +0, 0, 0, 0, 0, 29, 0, 0, 0, 42, 0, 0, 0, 111, 0, 0, 0, 175, 0, 0, 0, 121, 0, 0, 0, 134, 0, 0, 0, 47, 0, 0, 0, 166, 0, 0, 0, 90, 0, 0, 0, 147, 0, 0, 0, 209, 0, 0, 0, 254, 0, 0, 0, 174, 0, 0, 0, 58, 0, 0, 0, 238, 0, 0, 0, 219, 0, 0, 0, 124, 0, 0, 0, 97, 0, 0, 0, 190, 0, 0, 0, 124, 0, 0, 0, 1, 0, 0, 0, 249, 0, 0, 0, 254, 0, 0, 0, 82, 0, 0, 0, 220, 0, 0, 0, 216, 0, 0, 0, 82, 0, 0, 0, 163, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 175, 0, 0, 0, 19, 0, 0, 0, 55, 0, 0, 0, 189, 0, 0, 0, 55, 0, 0, 0, 113, 0, 0, 0, 172, 0, 0, 0, 4, 0, 0, 0, 70, 0, 0, 0, 99, 0, 0, 0, 172, 0, 0, 0, 164, 0, 0, 0, 119, 0, 0, 0, 237, 0, 0, 0, 37, 0, 0, 0, 56, 0, 0, 0, 224, 0, 0, 0, 21, 0, 0, 0, 168, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 206, 0, 0, 0, 81, 0, +0, 0, 1, 0, 0, 0, 169, 0, 0, 0, 188, 0, 0, 0, 15, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0, 4, 0, 0, 0, 137, 0, 0, 0, 249, 0, 0, 0, 128, 0, 0, 0, 7, 0, 0, 0, 207, 0, 0, 0, 63, 0, 0, 0, 179, 0, 0, 0, 233, 0, 0, 0, 231, 0, 0, 0, 69, 0, 0, 0, 68, 0, 0, 0, 61, 0, 0, 0, 42, 0, 0, 0, 124, 0, 0, 0, 233, 0, 0, 0, 228, 0, 0, 0, 22, 0, 0, 0, 92, 0, 0, 0, 94, 0, 0, 0, 101, 0, 0, 0, 28, 0, 0, 0, 199, 0, 0, 0, 125, 0, 0, 0, 198, 0, 0, 0, 122, 0, 0, 0, 251, 0, 0, 0, 67, 0, 0, 0, 238, 0, 0, 0, 37, 0, 0, 0, 118, 0, 0, 0, +70, 0, 0, 0, 114, 0, 0, 0, 2, 0, 0, 0, 162, 0, 0, 0, 237, 0, 0, 0, 244, 0, 0, 0, 143, 0, 0, 0, 107, 0, 0, 0, 11, 0, 0, 0, 62, 0, 0, 0, 235, 0, 0, 0, 53, 0, 0, 0, 26, 0, 0, 0, 213, 0, 0, 0, 126, 0, 0, 0, 219, 0, 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 138, 0, 0, 0, 160, 0, 0, 0, 180, 0, 0, 0, 207, 0, 0, 0, 96, 0, 0, 0, 75, 0, 0, 0, 212, 0, 0, 0, 213, 0, 0, 0, 249, 0, 0, 0, 45, 0, 0, 0, 191, 0, 0, 0, 136, 0, 0, 0, 189, 0, 0, 0, 34, 0, 0, 0, 98, 0, 0, 0, 19, 0, 0, 0, 83, 0, 0, 0, 228, 0, 0, 0, +130, 0, 0, 0, 87, 0, 0, 0, 250, 0, 0, 0, 30, 0, 0, 0, 143, 0, 0, 0, 6, 0, 0, 0, 43, 0, 0, 0, 144, 0, 0, 0, 186, 0, 0, 0, 8, 0, 0, 0, 182, 0, 0, 0, 16, 0, 0, 0, 84, 0, 0, 0, 79, 0, 0, 0, 124, 0, 0, 0, 27, 0, 0, 0, 38, 0, 0, 0, 237, 0, 0, 0, 218, 0, 0, 0, 107, 0, 0, 0, 221, 0, 0, 0, 37, 0, 0, 0, 208, 0, 0, 0, 78, 0, 0, 0, 234, 0, 0, 0, 66, 0, 0, 0, 187, 0, 0, 0, 37, 0, 0, 0, 3, 0, 0, 0, 81, 0, 0, 0, 22, 0, 0, 0, 80, 0, 0, 0, 124, 0, 0, 0, 213, 0, 0, 0, 93, 0, 0, 0, 246, 0, 0, 0, 153, 0, 0, 0, 232, +0, 0, 0, 119, 0, 0, 0, 114, 0, 0, 0, 78, 0, 0, 0, 250, 0, 0, 0, 98, 0, 0, 0, 203, 0, 0, 0, 118, 0, 0, 0, 117, 0, 0, 0, 12, 0, 0, 0, 226, 0, 0, 0, 113, 0, 0, 0, 152, 0, 0, 0, 146, 0, 0, 0, 213, 0, 0, 0, 250, 0, 0, 0, 69, 0, 0, 0, 223, 0, 0, 0, 92, 0, 0, 0, 111, 0, 0, 0, 30, 0, 0, 0, 158, 0, 0, 0, 40, 0, 0, 0, 105, 0, 0, 0, 13, 0, 0, 0, 172, 0, 0, 0, 102, 0, 0, 0, 109, 0, 0, 0, 195, 0, 0, 0, 139, 0, 0, 0, 186, 0, 0, 0, 22, 0, 0, 0, 181, 0, 0, 0, 226, 0, 0, 0, 160, 0, 0, 0, 13, 0, 0, 0, 12, 0, 0, 0, +189, 0, 0, 0, 164, 0, 0, 0, 142, 0, 0, 0, 24, 0, 0, 0, 108, 0, 0, 0, 242, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 220, 0, 0, 0, 74, 0, 0, 0, 134, 0, 0, 0, 37, 0, 0, 0, 149, 0, 0, 0, 20, 0, 0, 0, 203, 0, 0, 0, 216, 0, 0, 0, 26, 0, 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 151, 0, 0, 0, 165, 0, 0, 0, 219, 0, 0, 0, 139, 0, 0, 0, 45, 0, 0, 0, 170, 0, 0, 0, 66, 0, 0, 0, 17, 0, 0, 0, 9, 0, 0, 0, 242, 0, 0, 0, 147, 0, 0, 0, 187, 0, 0, 0, 217, 0, 0, 0, 6, 0, 0, 0, 132, 0, 0, 0, 78, 0, 0, 0, 17, 0, 0, 0, 168, 0, 0, 0, +160, 0, 0, 0, 37, 0, 0, 0, 43, 0, 0, 0, 166, 0, 0, 0, 95, 0, 0, 0, 174, 0, 0, 0, 196, 0, 0, 0, 180, 0, 0, 0, 76, 0, 0, 0, 200, 0, 0, 0, 171, 0, 0, 0, 199, 0, 0, 0, 59, 0, 0, 0, 2, 0, 0, 0, 238, 0, 0, 0, 201, 0, 0, 0, 41, 0, 0, 0, 15, 0, 0, 0, 223, 0, 0, 0, 17, 0, 0, 0, 133, 0, 0, 0, 237, 0, 0, 0, 206, 0, 0, 0, 13, 0, 0, 0, 98, 0, 0, 0, 44, 0, 0, 0, 143, 0, 0, 0, 75, 0, 0, 0, 249, 0, 0, 0, 4, 0, 0, 0, 233, 0, 0, 0, 6, 0, 0, 0, 114, 0, 0, 0, 29, 0, 0, 0, 55, 0, 0, 0, 32, 0, 0, 0, 80, 0, 0, 0, 201, +0, 0, 0, 20, 0, 0, 0, 235, 0, 0, 0, 236, 0, 0, 0, 57, 0, 0, 0, 167, 0, 0, 0, 151, 0, 0, 0, 43, 0, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 0, 0, 0, 209, 0, 0, 0, 57, 0, 0, 0, 189, 0, 0, 0, 251, 0, 0, 0, 51, 0, 0, 0, 190, 0, 0, 0, 196, 0, 0, 0, 240, 0, +0, 0, 92, 0, 0, 0, 239, 0, 0, 0, 240, 0, 0, 0, 86, 0, 0, 0, 104, 0, 0, 0, 252, 0, 0, 0, 151, 0, 0, 0, 71, 0, 0, 0, 200, 0, 0, 0, 114, 0, 0, 0, 182, 0, 0, 0, 83, 0, 0, 0, 164, 0, 0, 0, 10, 0, 0, 0, 152, 0, 0, 0, 165, 0, 0, 0, 180, 0, 0, 0, 55, 0, 0, 0, 113, 0, 0, 0, 207, 0, 0, 0, 102, 0, 0, 0, 80, 0, 0, 0, 109, 0, 0, 0, 23, 0, 0, 0, 164, 0, 0, 0, 25, 0, 0, 0, 82, 0, 0, 0, 17, 0, 0, 0, 71, 0, 0, 0, 179, 0, 0, 0, 92, 0, 0, 0, 91, 0, 0, 0, 169, 0, 0, 0, 46, 0, 0, 0, 34, 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, +0, 82, 0, 0, 0, 249, 0, 0, 0, 87, 0, 0, 0, 24, 0, 0, 0, 184, 0, 0, 0, 190, 0, 0, 0, 90, 0, 0, 0, 227, 0, 0, 0, 171, 0, 0, 0, 131, 0, 0, 0, 200, 0, 0, 0, 135, 0, 0, 0, 10, 0, 0, 0, 42, 0, 0, 0, 216, 0, 0, 0, 140, 0, 0, 0, 187, 0, 0, 0, 84, 0, 0, 0, 169, 0, 0, 0, 98, 0, 0, 0, 147, 0, 0, 0, 133, 0, 0, 0, 190, 0, 0, 0, 232, 0, 0, 0, 115, 0, 0, 0, 74, 0, 0, 0, 14, 0, 0, 0, 176, 0, 0, 0, 181, 0, 0, 0, 45, 0, 0, 0, 148, 0, 0, 0, 80, 0, 0, 0, 170, 0, 0, 0, 211, 0, 0, 0, 178, 0, 0, 0, 234, 0, 0, 0, 157, 0, +0, 0, 98, 0, 0, 0]).concat([118, 0, 0, 0, 59, 0, 0, 0, 7, 0, 0, 0, 52, 0, 0, 0, 78, 0, 0, 0, 45, 0, 0, 0, 112, 0, 0, 0, 200, 0, 0, 0, 154, 0, 0, 0, 21, 0, 0, 0, 102, 0, 0, 0, 107, 0, 0, 0, 197, 0, 0, 0, 150, 0, 0, 0, 202, 0, 0, 0, 200, 0, 0, 0, 34, 0, 0, 0, 26, 0, 0, 0, 238, 0, 0, 0, 95, 0, 0, 0, 231, 0, 0, 0, 49, 0, 0, 0, 96, 0, 0, 0, 34, 0, 0, 0, 131, 0, 0, 0, 8, 0, 0, 0, 99, 0, 0, 0, 206, 0, 0, 0, 185, 0, 0, 0, 50, 0, 0, 0, 68, 0, 0, 0, 88, 0, 0, 0, 93, 0, 0, 0, 58, 0, 0, 0, 155, 0, 0, 0, 228, +0, 0, 0, 4, 0, 0, 0, 213, 0, 0, 0, 239, 0, 0, 0, 56, 0, 0, 0, 239, 0, 0, 0, 75, 0, 0, 0, 221, 0, 0, 0, 25, 0, 0, 0, 77, 0, 0, 0, 194, 0, 0, 0, 23, 0, 0, 0, 117, 0, 0, 0, 161, 0, 0, 0, 104, 0, 0, 0, 205, 0, 0, 0, 195, 0, 0, 0, 198, 0, 0, 0, 3, 0, 0, 0, 68, 0, 0, 0, 227, 0, 0, 0, 120, 0, 0, 0, 9, 0, 0, 0, 145, 0, 0, 0, 71, 0, 0, 0, 63, 0, 0, 0, 15, 0, 0, 0, 228, 0, 0, 0, 146, 0, 0, 0, 88, 0, 0, 0, 250, 0, 0, 0, 125, 0, 0, 0, 31, 0, 0, 0, 32, 0, 0, 0, 148, 0, 0, 0, 88, 0, 0, 0, 94, 0, 0, 0, 188, 0, +0, 0, 25, 0, 0, 0, 2, 0, 0, 0, 111, 0, 0, 0, 32, 0, 0, 0, 214, 0, 0, 0, 216, 0, 0, 0, 145, 0, 0, 0, 84, 0, 0, 0, 167, 0, 0, 0, 243, 0, 0, 0, 32, 0, 0, 0, 75, 0, 0, 0, 52, 0, 0, 0, 6, 0, 0, 0, 250, 0, 0, 0, 48, 0, 0, 0, 200, 0, 0, 0, 111, 0, 0, 0, 20, 0, 0, 0, 16, 0, 0, 0, 101, 0, 0, 0, 116, 0, 0, 0, 19, 0, 0, 0, 78, 0, 0, 0, 240, 0, 0, 0, 105, 0, 0, 0, 38, 0, 0, 0, 206, 0, 0, 0, 207, 0, 0, 0, 144, 0, 0, 0, 244, 0, 0, 0, 208, 0, 0, 0, 197, 0, 0, 0, 200, 0, 0, 0, 100, 0, 0, 0, 38, 0, 0, 0, 162, 0, +0, 0, 80, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, 114, 0, 0, 0, 241, 0, 0, 0, 240, 0, 0, 0, 78, 0, 0, 0, 45, 0, 0, 0, 147, 0, 0, 0, 213, 0, 0, 0, 8, 0, 0, 0, 231, 0, 0, 0, 174, 0, 0, 0, 56, 0, 0, 0, 247, 0, 0, 0, 24, 0, 0, 0, 165, 0, 0, 0, 50, 0, 0, 0, 52, 0, 0, 0, 194, 0, 0, 0, 240, 0, 0, 0, 166, 0, 0, 0, 236, 0, 0, 0, 185, 0, 0, 0, 97, 0, 0, 0, 123, 0, 0, 0, 100, 0, 0, 0, 153, 0, 0, 0, 172, 0, 0, 0, 113, 0, 0, 0, 37, 0, 0, 0, 207, 0, 0, 0, 116, 0, 0, 0, 85, 0, 0, 0, 27, 0, 0, 0, 170, 0, 0, 0, 169, 0, +0, 0, 56, 0, 0, 0, 65, 0, 0, 0, 64, 0, 0, 0, 213, 0, 0, 0, 149, 0, 0, 0, 149, 0, 0, 0, 171, 0, 0, 0, 28, 0, 0, 0, 94, 0, 0, 0, 188, 0, 0, 0, 65, 0, 0, 0, 126, 0, 0, 0, 20, 0, 0, 0, 48, 0, 0, 0, 190, 0, 0, 0, 19, 0, 0, 0, 137, 0, 0, 0, 244, 0, 0, 0, 229, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 192, 0, 0, 0, 194, 0, 0, 0, 150, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 119, 0, 0, 0, 69, 0, 0, 0, 236, 0, 0, 0, 103, 0, 0, 0, 118, 0, 0, 0, 50, 0, 0, 0, 76, 0, 0, 0, 185, 0, 0, 0, 223, 0, 0, 0, 37, 0, 0, 0, 50, 0, 0, 0, 107, 0, 0, 0, 203, 0, 0, 0, 231, 0, 0, 0, 20, 0, 0, 0, 97, 0, 0, 0, 67, 0, 0, 0, 238, 0, 0, 0, 186, 0, 0, 0, 155, 0, 0, 0, 113, 0, 0, 0, 239, 0, 0, 0, 210, 0, 0, 0, 72, 0, 0, 0, 101, 0, 0, 0, 187, 0, 0, 0, 27, 0, 0, 0, 138, 0, 0, +0, 19, 0, 0, 0, 27, 0, 0, 0, 34, 0, 0, 0, 132, 0, 0, 0, 173, 0, 0, 0, 12, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 90, 0, 0, 0, 186, 0, 0, 0, 208, 0, 0, 0, 152, 0, 0, 0, 89, 0, 0, 0, 191, 0, 0, 0, 55, 0, 0, 0, 176, 0, 0, 0, 79, 0, 0, 0, 151, 0, 0, 0, 96, 0, 0, 0, 32, 0, 0, 0, 179, 0, 0, 0, 155, 0, 0, 0, 151, 0, 0, 0, 246, 0, 0, 0, 8, 0, 0, 0, 108, 0, 0, 0, 164, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 183, 0, 0, 0, 250, 0, 0, 0, 149, 0, 0, 0, 178, 0, 0, 0, 81, 0, 0, 0, 121, 0, 0, 0, 40, 0, 0, 0, 92, 0, 0, +0, 63, 0, 0, 0, 219, 0, 0, 0, 107, 0, 0, 0, 24, 0, 0, 0, 59, 0, 0, 0, 92, 0, 0, 0, 209, 0, 0, 0, 4, 0, 0, 0, 40, 0, 0, 0, 222, 0, 0, 0, 133, 0, 0, 0, 82, 0, 0, 0, 49, 0, 0, 0, 181, 0, 0, 0, 187, 0, 0, 0, 246, 0, 0, 0, 169, 0, 0, 0, 237, 0, 0, 0, 190, 0, 0, 0, 40, 0, 0, 0, 79, 0, 0, 0, 179, 0, 0, 0, 126, 0, 0, 0, 5, 0, 0, 0, 106, 0, 0, 0, 219, 0, 0, 0, 149, 0, 0, 0, 13, 0, 0, 0, 27, 0, 0, 0, 28, 0, 0, 0, 213, 0, 0, 0, 197, 0, 0, 0, 195, 0, 0, 0, 154, 0, 0, 0, 10, 0, 0, 0, 208, 0, 0, 0, 49, 0, 0, 0, +62, 0, 0, 0, 7, 0, 0, 0, 54, 0, 0, 0, 142, 0, 0, 0, 192, 0, 0, 0, 138, 0, 0, 0, 98, 0, 0, 0, 177, 0, 0, 0, 202, 0, 0, 0, 214, 0, 0, 0, 14, 0, 0, 0, 30, 0, 0, 0, 157, 0, 0, 0, 239, 0, 0, 0, 171, 0, 0, 0, 152, 0, 0, 0, 77, 0, 0, 0, 187, 0, 0, 0, 108, 0, 0, 0, 5, 0, 0, 0, 224, 0, 0, 0, 228, 0, 0, 0, 93, 0, 0, 0, 189, 0, 0, 0, 87, 0, 0, 0, 204, 0, 0, 0, 33, 0, 0, 0, 39, 0, 0, 0, 206, 0, 0, 0, 253, 0, 0, 0, 169, 0, 0, 0, 148, 0, 0, 0, 142, 0, 0, 0, 225, 0, 0, 0, 171, 0, 0, 0, 73, 0, 0, 0, 224, 0, 0, 0, +70, 0, 0, 0, 38, 0, 0, 0, 161, 0, 0, 0, 168, 0, 0, 0, 140, 0, 0, 0, 161, 0, 0, 0, 153, 0, 0, 0, 29, 0, 0, 0, 180, 0, 0, 0, 39, 0, 0, 0, 109, 0, 0, 0, 45, 0, 0, 0, 200, 0, 0, 0, 57, 0, 0, 0, 48, 0, 0, 0, 94, 0, 0, 0, 55, 0, 0, 0, 82, 0, 0, 0, 196, 0, 0, 0, 110, 0, 0, 0, 169, 0, 0, 0, 133, 0, 0, 0, 244, 0, 0, 0, 231, 0, 0, 0, 176, 0, 0, 0, 21, 0, 0, 0, 51, 0, 0, 0, 132, 0, 0, 0, 27, 0, 0, 0, 20, 0, 0, 0, 26, 0, 0, 0, 2, 0, 0, 0, 217, 0, 0, 0, 59, 0, 0, 0, 173, 0, 0, 0, 15, 0, 0, 0, 67, 0, 0, 0, 108, +0, 0, 0, 234, 0, 0, 0, 62, 0, 0, 0, 15, 0, 0, 0, 126, 0, 0, 0, 218, 0, 0, 0, 221, 0, 0, 0, 107, 0, 0, 0, 76, 0, 0, 0, 127, 0, 0, 0, 110, 0, 0, 0, 212, 0, 0, 0, 107, 0, 0, 0, 191, 0, 0, 0, 15, 0, 0, 0, 71, 0, 0, 0, 159, 0, 0, 0, 124, 0, 0, 0, 86, 0, 0, 0, 124, 0, 0, 0, 67, 0, 0, 0, 145, 0, 0, 0, 28, 0, 0, 0, 187, 0, 0, 0, 78, 0, 0, 0, 114, 0, 0, 0, 62, 0, 0, 0, 100, 0, 0, 0, 171, 0, 0, 0, 160, 0, 0, 0, 160, 0, 0, 0, 223, 0, 0, 0, 180, 0, 0, 0, 216, 0, 0, 0, 135, 0, 0, 0, 58, 0, 0, 0, 189, 0, 0, 0, +168, 0, 0, 0, 72, 0, 0, 0, 201, 0, 0, 0, 184, 0, 0, 0, 239, 0, 0, 0, 46, 0, 0, 0, 173, 0, 0, 0, 111, 0, 0, 0, 132, 0, 0, 0, 79, 0, 0, 0, 45, 0, 0, 0, 45, 0, 0, 0, 240, 0, 0, 0, 27, 0, 0, 0, 126, 0, 0, 0, 42, 0, 0, 0, 108, 0, 0, 0, 248, 0, 0, 0, 169, 0, 0, 0, 106, 0, 0, 0, 225, 0, 0, 0, 240, 0, 0, 0, 153, 0, 0, 0, 161, 0, 0, 0, 103, 0, 0, 0, 154, 0, 0, 0, 212, 0, 0, 0, 19, 0, 0, 0, 202, 0, 0, 0, 202, 0, 0, 0, 186, 0, 0, 0, 39, 0, 0, 0, 146, 0, 0, 0, 170, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 80, 0, +0, 0, 222, 0, 0, 0, 204, 0, 0, 0, 64, 0, 0, 0, 38, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 62, 0, 0, 0, 242, 0, 0, 0, 178, 0, 0, 0, 144, 0, 0, 0, 206, 0, 0, 0, 219, 0, 0, 0, 100, 0, 0, 0, 62, 0, 0, 0, 3, 0, 0, 0, 221, 0, 0, 0, 55, 0, 0, 0, +54, 0, 0, 0, 84, 0, 0, 0, 112, 0, 0, 0, 118, 0, 0, 0, 36, 0, 0, 0, 181, 0, 0, 0, 105, 0, 0, 0, 3, 0, 0, 0, 252, 0, 0, 0, 160, 0, 0, 0, 43, 0, 0, 0, 116, 0, 0, 0, 178, 0, 0, 0, 5, 0, 0, 0, 14, 0, 0, 0, 204, 0, 0, 0, 216, 0, 0, 0, 31, 0, 0, 0, 106, 0, 0, 0, 31, 0, 0, 0, 25, 0, 0, 0, 94, 0, 0, 0, 96, 0, 0, 0, 105, 0, 0, 0, 88, 0, 0, 0, 134, 0, 0, 0, 160, 0, 0, 0, 49, 0, 0, 0, 189, 0, 0, 0, 50, 0, 0, 0, 233, 0, 0, 0, 44, 0, 0, 0, 92, 0, 0, 0, 210, 0, 0, 0, 133, 0, 0, 0, 186, 0, 0, 0, 64, 0, 0, 0, 100, +0, 0, 0, 168, 0, 0, 0, 116, 0, 0, 0, 248, 0, 0, 0, 14, 0, 0, 0, 28, 0, 0, 0, 179, 0, 0, 0, 169, 0, 0, 0, 105, 0, 0, 0, 232, 0, 0, 0, 30, 0, 0, 0, 64, 0, 0, 0, 100, 0, 0, 0, 153, 0, 0, 0, 119, 0, 0, 0, 108, 0, 0, 0, 50, 0, 0, 0, 79, 0, 0, 0, 253, 0, 0, 0, 187, 0, 0, 0, 92, 0, 0, 0, 187, 0, 0, 0, 141, 0, 0, 0, 100, 0, 0, 0, 102, 0, 0, 0, 74, 0, 0, 0, 113, 0, 0, 0, 31, 0, 0, 0, 121, 0, 0, 0, 163, 0, 0, 0, 173, 0, 0, 0, 141, 0, 0, 0, 249, 0, 0, 0, 212, 0, 0, 0, 236, 0, 0, 0, 207, 0, 0, 0, 103, 0, 0, +0, 112, 0, 0, 0, 250, 0, 0, 0, 5, 0, 0, 0, 74, 0, 0, 0, 15, 0, 0, 0, 110, 0, 0, 0, 175, 0, 0, 0, 135, 0, 0, 0, 10, 0, 0, 0, 111, 0, 0, 0, 198, 0, 0, 0, 54, 0, 0, 0, 110, 0, 0, 0, 108, 0, 0, 0, 140, 0, 0, 0, 36, 0, 0, 0, 9, 0, 0, 0, 96, 0, 0, 0, 190, 0, 0, 0, 38, 0, 0, 0, 210, 0, 0, 0, 76, 0, 0, 0, 94, 0, 0, 0, 23, 0, 0, 0, 202, 0, 0, 0, 95, 0, 0, 0, 29, 0, 0, 0, 204, 0, 0, 0, 135, 0, 0, 0, 232, 0, 0, 0, 66, 0, 0, 0, 106, 0, 0, 0, 203, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 146, 0, 0, 0, 5, 0, 0, 0, +53, 0, 0, 0, 129, 0, 0, 0, 19, 0, 0, 0, 96, 0, 0, 0, 107, 0, 0, 0, 244, 0, 0, 0, 21, 0, 0, 0, 205, 0, 0, 0, 15, 0, 0, 0, 10, 0, 0, 0, 175, 0, 0, 0, 78, 0, 0, 0, 107, 0, 0, 0, 81, 0, 0, 0, 253, 0, 0, 0, 20, 0, 0, 0, 196, 0, 0, 0, 46, 0, 0, 0, 19, 0, 0, 0, 134, 0, 0, 0, 116, 0, 0, 0, 68, 0, 0, 0, 203, 0, 0, 0, 102, 0, 0, 0, 107, 0, 0, 0, 182, 0, 0, 0, 157, 0, 0, 0, 116, 0, 0, 0, 86, 0, 0, 0, 50, 0, 0, 0, 172, 0, 0, 0, 141, 0, 0, 0, 142, 0, 0, 0, 140, 0, 0, 0, 140, 0, 0, 0, 140, 0, 0, 0, 57, 0, 0, 0, +202, 0, 0, 0, 89, 0, 0, 0, 116, 0, 0, 0, 26, 0, 0, 0, 17, 0, 0, 0, 239, 0, 0, 0, 109, 0, 0, 0, 247, 0, 0, 0, 57, 0, 0, 0, 92, 0, 0, 0, 59, 0, 0, 0, 31, 0, 0, 0, 250, 0, 0, 0, 227, 0, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 35, 0, 0, 0, 158, 0, 0, 0, 246, 0, 0, 0, 209, 0, 0, 0, 33, 0, 0, 0, 162, 0, 0, 0, 191, 0, 0, 0, 173, 0, 0, 0, 101, 0, 0, 0, 66, 0, 0, 0, 107, 0, 0, 0, 89, 0, 0, 0, 138, 0, 0, 0, 232, 0, 0, 0, 197, 0, 0, 0, 127, 0, 0, 0, 100, 0, 0, 0, 5, 0, 0, 0, 122, 0, 0, 0, 132, 0, 0, 0, 74, 0, 0, 0, +19, 0, 0, 0, 195, 0, 0, 0, 246, 0, 0, 0, 176, 0, 0, 0, 110, 0, 0, 0, 154, 0, 0, 0, 107, 0, 0, 0, 83, 0, 0, 0, 107, 0, 0, 0, 50, 0, 0, 0, 218, 0, 0, 0, 217, 0, 0, 0, 116, 0, 0, 0, 117, 0, 0, 0, 196, 0, 0, 0, 186, 0, 0, 0, 100, 0, 0, 0, 61, 0, 0, 0, 59, 0, 0, 0, 8, 0, 0, 0, 221, 0, 0, 0, 16, 0, 0, 0, 70, 0, 0, 0, 239, 0, 0, 0, 199, 0, 0, 0, 144, 0, 0, 0, 31, 0, 0, 0, 123, 0, 0, 0, 47, 0, 0, 0, 58, 0, 0, 0, 206, 0, 0, 0, 200, 0, 0, 0, 161, 0, 0, 0, 121, 0, 0, 0, 60, 0, 0, 0, 48, 0, 0, 0, 18, 0, 0, 0, +68, 0, 0, 0, 40, 0, 0, 0, 246, 0, 0, 0, 188, 0, 0, 0, 255, 0, 0, 0, 253, 0, 0, 0, 244, 0, 0, 0, 192, 0, 0, 0, 151, 0, 0, 0, 176, 0, 0, 0, 204, 0, 0, 0, 195, 0, 0, 0, 19, 0, 0, 0, 122, 0, 0, 0, 185, 0, 0, 0, 154, 0, 0, 0, 22, 0, 0, 0, 228, 0, 0, 0, 203, 0, 0, 0, 76, 0, 0, 0, 52, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 78, 0, 0, 0, 211, 0, 0, 0, 45, 0, 0, 0, 9, 0, 0, 0, 51, 0, 0, 0, 14, 0, 0, 0, 210, 0, 0, 0, 13, 0, 0, 0, 190, 0, 0, 0, 62, 0, 0, 0, 231, 0, 0, 0, 228, 0, 0, 0, 170, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, 0, 232, 0, 0, 0, 173, 0, 0, 0, 170, 0, 0, 0, 122, 0, 0, 0, 141, 0, 0, 0, 52, 0, 0, 0, 40, 0, 0, 0, 169, 0, 0, 0, 129, 0, 0, 0, 148, 0, 0, 0, 197, 0, 0, 0, 231, 0, 0, 0, 66, 0, 0, 0, 172, 0, 0, 0, 71, 0, 0, 0, 36, +0, 0, 0, 137, 0, 0, 0, 122, 0, 0, 0, 143, 0, 0, 0, 181, 0, 0, 0, 155, 0, 0, 0, 240, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 100, 0, 0, 0, 208, 0, 0, 0, 30, 0, 0, 0, 245, 0, 0, 0, 164, 0, 0, 0, 178, 0, 0, 0, 243, 0, 0, 0, 116, 0, 0, 0, 233, 0, 0, 0, 26, 0, 0, 0, 22, 0, 0, 0, 253, 0, 0, 0, 203, 0, 0, 0, 21, 0, 0, 0, 234, 0, 0, 0, 235, 0, 0, 0, 16, 0, 0, 0, 108, 0, 0, 0, 53, 0, 0, 0, 209, 0, 0, 0, 193, 0, 0, 0, 166, 0, 0, 0, 40, 0, 0, 0, 204, 0, 0, 0, 213, 0, 0, 0, 57, 0, 0, 0, 252, 0, 0, 0, 165, 0, 0, 0, +164, 0, 0, 0, 173, 0, 0, 0, 50, 0, 0, 0, 21, 0, 0, 0, 206, 0, 0, 0, 25, 0, 0, 0, 232, 0, 0, 0, 52, 0, 0, 0, 43, 0, 0, 0, 28, 0, 0, 0, 96, 0, 0, 0, 145, 0, 0, 0, 252, 0, 0, 0, 5, 0, 0, 0, 169, 0, 0, 0, 179, 0, 0, 0, 220, 0, 0, 0, 128, 0, 0, 0, 41, 0, 0, 0, 196, 0, 0, 0, 32, 0, 0, 0, 121, 0, 0, 0, 6, 0, 0, 0, 57, 0, 0, 0, 192, 0, 0, 0, 226, 0, 0, 0, 34, 0, 0, 0, 187, 0, 0, 0, 168, 0, 0, 0, 225, 0, 0, 0, 137, 0, 0, 0, 112, 0, 0, 0, 87, 0, 0, 0, 24, 0, 0, 0, 84, 0, 0, 0, 60, 0, 0, 0, 246, 0, 0, 0, 13, +0, 0, 0, 130, 0, 0, 0, 18, 0, 0, 0, 5, 0, 0, 0, 135, 0, 0, 0, 150, 0, 0, 0, 6, 0, 0, 0, 57, 0, 0, 0, 227, 0, 0, 0, 248, 0, 0, 0, 179, 0, 0, 0, 149, 0, 0, 0, 229, 0, 0, 0, 215, 0, 0, 0, 38, 0, 0, 0, 191, 0, 0, 0, 9, 0, 0, 0, 90, 0, 0, 0, 148, 0, 0, 0, 249, 0, 0, 0, 28, 0, 0, 0, 99, 0, 0, 0, 43, 0, 0, 0, 140, 0, 0, 0, 45, 0, 0, 0, 154, 0, 0, 0, 139, 0, 0, 0, 132, 0, 0, 0, 242, 0, 0, 0, 86, 0, 0, 0, 251, 0, 0, 0, 173, 0, 0, 0, 46, 0, 0, 0, 127, 0, 0, 0, 183, 0, 0, 0, 252, 0, 0, 0, 48, 0, 0, 0, 225, +0, 0, 0, 53, 0, 0, 0, 137, 0, 0, 0, 186, 0, 0, 0, 77, 0, 0, 0, 168, 0, 0, 0, 109, 0, 0, 0, 206, 0, 0, 0, 140, 0, 0, 0, 139, 0, 0, 0, 48, 0, 0, 0, 224, 0, 0, 0, 218, 0, 0, 0, 41, 0, 0, 0, 24, 0, 0, 0, 17, 0, 0, 0, 23, 0, 0, 0, 25, 0, 0, 0, 166, 0, 0, 0, 90, 0, 0, 0, 101, 0, 0, 0, 147, 0, 0, 0, 195, 0, 0, 0, 181, 0, 0, 0, 49, 0, 0, 0, 34, 0, 0, 0, 79, 0, 0, 0, 243, 0, 0, 0, 246, 0, 0, 0, 15, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 195, 0, 0, 0, 124, 0, 0, 0, 235, 0, 0, 0, 206, 0, 0, 0, 134, 0, 0, 0, 236, +0, 0, 0, 103, 0, 0, 0, 118, 0, 0, 0, 110, 0, 0, 0, 53, 0, 0, 0, 69, 0, 0, 0, 123, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, 146, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 0, 61, 0, 0, 0, 213, 0, 0, 0, 154, 0, 0, 0, 100, 0, 0, 0, 115, 0, 0, 0, 54, 0, 0, 0, 177, 0, 0, 0, 214, 0, 0, 0, 134, 0, 0, 0, 152, 0, 0, 0, 66, 0, 0, 0, 63, 0, 0, 0, 138, 0, 0, 0, 241, 0, 0, 0, 199, 0, 0, 0, 245, 0, 0, 0, 66, 0, 0, 0, 168, 0, 0, 0, 156, 0, 0, 0, 82, 0, 0, 0, 168, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 36, 0, 0, 0, 63, 0, 0, 0, +74, 0, 0, 0, 161, 0, 0, 0, 164, 0, 0, 0, 91, 0, 0, 0, 232, 0, 0, 0, 98, 0, 0, 0, 26, 0, 0, 0, 197, 0, 0, 0, 189, 0, 0, 0, 200, 0, 0, 0, 20, 0, 0, 0, 213, 0, 0, 0, 13, 0, 0, 0, 235, 0, 0, 0, 225, 0, 0, 0, 165, 0, 0, 0, 230, 0, 0, 0, 131, 0, 0, 0, 17, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 85, 0, 0, 0, 131, 0, 0, 0, 81, 0, 0, 0, 126, 0, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 185, 0, 0, 0, 203, 0, 0, 0, 216, 0, 0, 0, 197, 0, 0, 0, 229, 0, 0, 0, 161, 0, 0, 0, 217, 0, 0, 0, 23, 0, 0, 0, +109, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 249, 0, 0, 0, 228, 0, 0, 0, 233, 0, 0, 0, 225, 0, 0, 0, 82, 0, 0, 0, 63, 0, 0, 0, 81, 0, 0, 0, 25, 0, 0, 0, 13, 0, 0, 0, 221, 0, 0, 0, 217, 0, 0, 0, 157, 0, 0, 0, 147, 0, 0, 0, 49, 0, 0, 0, 135, +0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0, 213, 0, 0, 0, 131, 0, 0, 0, 235, 0, 0, 0, 146, 0, 0, 0, 9, 0, 0, 0, 118, 0, 0, 0, 110, 0, 0, 0, 227, 0, 0, 0, 248, 0, 0, 0, 192, 0, 0, 0, 162, 0, 0, 0, 102, 0, 0, 0, 181, 0, 0, 0, 54, 0, 0, 0, 58, 0, 0, 0, 187, 0, 0, 0, 57, 0, 0, 0, 237, 0, 0, 0, 50, 0, 0, 0, 2, 0, 0, 0, 231, 0, 0, 0, 67, 0, 0, 0, 122, 0, 0, 0, 56, 0, 0, 0, 20, 0, 0, 0, 132, 0, 0, 0, 227, 0, 0, 0, 68, 0, 0, 0, 210, 0, 0, 0, 94, 0, 0, 0, 148, 0, 0, 0, 221, 0, 0, 0, 120, 0, 0, 0, 137, 0, 0, 0, 85, +0, 0, 0, 76, 0, 0, 0, 115, 0, 0, 0, 158, 0, 0, 0, 225, 0, 0, 0, 228, 0, 0, 0, 62, 0, 0, 0, 67, 0, 0, 0, 208, 0, 0, 0, 74, 0, 0, 0, 222, 0, 0, 0, 27, 0, 0, 0, 178, 0, 0, 0, 231, 0, 0, 0, 143, 0, 0, 0, 227, 0, 0, 0, 163, 0, 0, 0, 197, 0, 0, 0, 203, 0, 0, 0, 114, 0, 0, 0, 238, 0, 0, 0, 121, 0, 0, 0, 65, 0, 0, 0, 248, 0, 0, 0, 223, 0, 0, 0, 238, 0, 0, 0, 101, 0, 0, 0, 197, 0, 0, 0, 69, 0, 0, 0, 119, 0, 0, 0, 39, 0, 0, 0, 60, 0, 0, 0, 189, 0, 0, 0, 88, 0, 0, 0, 211, 0, 0, 0, 117, 0, 0, 0, 226, 0, 0, 0, +4, 0, 0, 0, 75, 0, 0, 0, 187, 0, 0, 0, 101, 0, 0, 0, 243, 0, 0, 0, 200, 0, 0, 0, 15, 0, 0, 0, 36, 0, 0, 0, 123, 0, 0, 0, 147, 0, 0, 0, 52, 0, 0, 0, 181, 0, 0, 0, 226, 0, 0, 0, 116, 0, 0, 0, 72, 0, 0, 0, 205, 0, 0, 0, 160, 0, 0, 0, 11, 0, 0, 0, 146, 0, 0, 0, 151, 0, 0, 0, 102, 0, 0, 0, 57, 0, 0, 0, 244, 0, 0, 0, 176, 0, 0, 0, 226, 0, 0, 0, 93, 0, 0, 0, 57, 0, 0, 0, 106, 0, 0, 0, 91, 0, 0, 0, 69, 0, 0, 0, 23, 0, 0, 0, 120, 0, 0, 0, 30, 0, 0, 0, 219, 0, 0, 0, 145, 0, 0, 0, 129, 0, 0, 0, 28, 0, 0, 0, +249, 0, 0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 223, 0, 0, 0, 209, 0, 0, 0, 90, 0, 0, 0, 213, 0, 0, 0, 233, 0, 0, 0, 78, 0, 0, 0, 88, 0, 0, 0, 149, 0, 0, 0, 147, 0, 0, 0, 95, 0, 0, 0, 81, 0, 0, 0, 9, 0, 0, 0, 195, 0, 0, 0, 42, 0, 0, 0, 201, 0, 0, 0, 212, 0, 0, 0, 85, 0, 0, 0, 72, 0, 0, 0, 121, 0, 0, 0, 164, 0, 0, 0, 163, 0, 0, 0, 178, 0, 0, 0, 195, 0, 0, 0, 98, 0, 0, 0, 170, 0, 0, 0, 140, 0, 0, 0, 232, 0, 0, 0, 173, 0, 0, 0, 71, 0, 0, 0, 57, 0, 0, 0, 27, 0, 0, 0, 70, 0, 0, 0, 218, 0, 0, 0, 158, 0, 0, 0, +81, 0, 0, 0, 58, 0, 0, 0, 230, 0, 0, 0, 209, 0, 0, 0, 166, 0, 0, 0, 187, 0, 0, 0, 77, 0, 0, 0, 123, 0, 0, 0, 8, 0, 0, 0, 190, 0, 0, 0, 140, 0, 0, 0, 213, 0, 0, 0, 243, 0, 0, 0, 63, 0, 0, 0, 253, 0, 0, 0, 247, 0, 0, 0, 68, 0, 0, 0, 128, 0, 0, 0, 45, 0, 0, 0, 83, 0, 0, 0, 75, 0, 0, 0, 208, 0, 0, 0, 135, 0, 0, 0, 104, 0, 0, 0, 193, 0, 0, 0, 181, 0, 0, 0, 216, 0, 0, 0, 247, 0, 0, 0, 7, 0, 0, 0, 244, 0, 0, 0, 16, 0, 0, 0, 70, 0, 0, 0, 190, 0, 0, 0, 183, 0, 0, 0, 210, 0, 0, 0, 209, 0, 0, 0, 206, 0, 0, +0, 94, 0, 0, 0, 118, 0, 0, 0, 162, 0, 0, 0, 215, 0, 0, 0, 3, 0, 0, 0, 220, 0, 0, 0, 228, 0, 0, 0, 129, 0, 0, 0, 90, 0, 0, 0, 246, 0, 0, 0, 60, 0, 0, 0, 222, 0, 0, 0, 174, 0, 0, 0, 122, 0, 0, 0, 157, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 165, 0, 0, 0, 246, 0, 0, 0, 169, 0, 0, 0, 115, 0, 0, 0, 226, 0, 0, 0, 141, 0, 0, 0, 96, 0, 0, 0, 250, 0, 0, 0, 68, 0, 0, 0, 113, 0, 0, 0, 246, 0, 0, 0, 65, 0, 0, 0, 216, 0, 0, 0, 198, 0, 0, 0, 88, 0, 0, 0, 19, 0, 0, 0, 55, 0, 0, 0, 235, 0, 0, 0, 132, 0, 0, 0, 15, 0, +0, 0, 150, 0, 0, 0, 199, 0, 0, 0, 220, 0, 0, 0, 200, 0, 0, 0, 169, 0, 0, 0, 122, 0, 0, 0, 131, 0, 0, 0, 178, 0, 0, 0, 47, 0, 0, 0, 49, 0, 0, 0, 177, 0, 0, 0, 26, 0, 0, 0, 216, 0, 0, 0, 152, 0, 0, 0, 63, 0, 0, 0, 17, 0, 0, 0, 208, 0, 0, 0, 49, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 213, 0, 0, 0, 52, 0, 0, 0, 22, 0, 0, 0, 1, 0, 0, 0, 163, 0, 0, 0, 147, 0, 0, 0, 234, 0, 0, 0, 82, 0, 0, 0, 148, 0, 0, 0, 236, 0, 0, 0, 147, 0, 0, 0, 183, 0, 0, 0, 129, 0, 0, 0, 17, 0, 0, 0, 45, 0, 0, 0, 88, 0, 0, 0, 249, 0, 0, 0, 181, 0, 0, 0, 10, 0, 0, 0, 170, 0, 0, 0, 79, 0, 0, 0, 246, 0, 0, 0, 46, 0, 0, 0, 63, 0, 0, 0, 54, 0, 0, 0, 191, 0, 0, 0, 51, 0, 0, 0, 90, 0, 0, 0, 231, 0, 0, 0, 209, 0, 0, 0, 8, 0, 0, 0, 26, 0, 0, 0, 207, 0, 0, 0, 66, 0, 0, 0, +174, 0, 0, 0, 204, 0, 0, 0, 181, 0, 0, 0, 119, 0, 0, 0, 57, 0, 0, 0, 196, 0, 0, 0, 91, 0, 0, 0, 91, 0, 0, 0, 208, 0, 0, 0, 38, 0, 0, 0, 89, 0, 0, 0, 39, 0, 0, 0, 208, 0, 0, 0, 85, 0, 0, 0, 113, 0, 0, 0, 18, 0, 0, 0, 157, 0, 0, 0, 136, 0, 0, 0, 61, 0, 0, 0, 156, 0, 0, 0, 234, 0, 0, 0, 65, 0, 0, 0, 106, 0, 0, 0, 240, 0, 0, 0, 80, 0, 0, 0, 147, 0, 0, 0, 147, 0, 0, 0, 221, 0, 0, 0, 71, 0, 0, 0, 111, 0, 0, 0, 201, 0, 0, 0, 81, 0, 0, 0, 109, 0, 0, 0, 28, 0, 0, 0, 170, 0, 0, 0, 245, 0, 0, 0, 165, 0, 0, +0, 144, 0, 0, 0, 63, 0, 0, 0, 20, 0, 0, 0, 226, 0, 0, 0, 110, 0, 0, 0, 142, 0, 0, 0, 100, 0, 0, 0, 253, 0, 0, 0, 172, 0, 0, 0, 224, 0, 0, 0, 78, 0, 0, 0, 34, 0, 0, 0, 229, 0, 0, 0, 193, 0, 0, 0, 188, 0, 0, 0, 41, 0, 0, 0, 10, 0, 0, 0, 106, 0, 0, 0, 158, 0, 0, 0, 161, 0, 0, 0, 96, 0, 0, 0, 203, 0, 0, 0, 47, 0, 0, 0, 11, 0, 0, 0, 220, 0, 0, 0, 57, 0, 0, 0, 50, 0, 0, 0, 243, 0, 0, 0, 161, 0, 0, 0, 68, 0, 0, 0, 233, 0, 0, 0, 197, 0, 0, 0, 195, 0, 0, 0, 120, 0, 0, 0, 251, 0, 0, 0, 149, 0, 0, 0, 71, 0, +0, 0, 52, 0, 0, 0, 53, 0, 0, 0, 52, 0, 0, 0, 232, 0, 0, 0, 37, 0, 0, 0, 222, 0, 0, 0, 147, 0, 0, 0, 198, 0, 0, 0, 180, 0, 0, 0, 118, 0, 0, 0, 109, 0, 0, 0, 134, 0, 0, 0, 19, 0, 0, 0, 198, 0, 0, 0, 233, 0, 0, 0, 104, 0, 0, 0, 181, 0, 0, 0, 1, 0, 0, 0, 99, 0, 0, 0, 31, 0, 0, 0, 154, 0, 0, 0, 82, 0, 0, 0, 100, 0, 0, 0, 151, 0, 0, 0, 217, 0, 0, 0, 28, 0, 0, 0, 8, 0, 0, 0, 81, 0, 0, 0, 111, 0, 0, 0, 38, 0, 0, 0, 157, 0, 0, 0, 170, 0, 0, 0, 147, 0, 0, 0, 51, 0, 0, 0, 67, 0, 0, 0, 250, 0, 0, 0, 119, 0, +0, 0, 233, 0, 0, 0, 98, 0, 0, 0, 155, 0, 0, 0, 93, 0, 0, 0, 24, 0, 0, 0, 117, 0, 0, 0, 235, 0, 0, 0, 120, 0, 0, 0, 247, 0, 0, 0, 135, 0, 0, 0, 143, 0, 0, 0, 65, 0, 0, 0, 180, 0, 0, 0, 77, 0, 0, 0, 19, 0, 0, 0, 168, 0, 0, 0, 130, 0, 0, 0, 62, 0, 0, 0, 233, 0, 0, 0, 19, 0, 0, 0, 173, 0, 0, 0, 235, 0, 0, 0, 1, 0, 0, 0, 202, 0, 0, 0, 207, 0, 0, 0, 218, 0, 0, 0, 205, 0, 0, 0, 247, 0, 0, 0, 108, 0, 0, 0, 199, 0, 0, 0, 122, 0, 0, 0, 220, 0, 0, 0, 30, 0, 0, 0, 110, 0, 0, 0, 200, 0, 0, 0, 78, 0, 0, 0, 85, +0, 0, 0, 98, 0, 0, 0, 128, 0, 0, 0, 234, 0, 0, 0, 120, 0, 0, 0, 12, 0, 0, 0, 134, 0, 0, 0, 185, 0, 0, 0, 64, 0, 0, 0, 81, 0, 0, 0, 39, 0, 0, 0, 174, 0, 0, 0, 211, 0, 0, 0, 13, 0, 0, 0, 76, 0, 0, 0, 143, 0, 0, 0, 52, 0, 0, 0, 234, 0, 0, 0, 125, 0, 0, 0, 60, 0, 0, 0, 229, 0, 0, 0, 138, 0, 0, 0, 207, 0, 0, 0, 91, 0, 0, 0, 146, 0, 0, 0, 216, 0, 0, 0, 48, 0, 0, 0, 22, 0, 0, 0, 180, 0, 0, 0, 163, 0, 0, 0, 117, 0, 0, 0, 255, 0, 0, 0, 235, 0, 0, 0, 39, 0, 0, 0, 200, 0, 0, 0, 92, 0, 0, 0, 108, 0, 0, 0, 194, +0, 0, 0, 238, 0, 0, 0, 108, 0, 0, 0, 33, 0, 0, 0, 11, 0, 0, 0, 195, 0, 0, 0, 186, 0, 0, 0, 18, 0, 0, 0, 83, 0, 0, 0, 42, 0, 0, 0, 170, 0, 0, 0, 119, 0, 0, 0, 173, 0, 0, 0, 25, 0, 0, 0, 120, 0, 0, 0, 85, 0, 0, 0, 138, 0, 0, 0, 46, 0, 0, 0, 96, 0, 0, 0, 135, 0, 0, 0, 194, 0, 0, 0, 110, 0, 0, 0, 145, 0, 0, 0, 56, 0, 0, 0, 145, 0, 0, 0, 63, 0, 0, 0, 122, 0, 0, 0, 197, 0, 0, 0, 36, 0, 0, 0, 143, 0, 0, 0, 81, 0, 0, 0, 197, 0, 0, 0, 222, 0, 0, 0, 176, 0, 0, 0, 83, 0, 0, 0, 48, 0, 0, 0, 86, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 254, 0, 0, 0, 84, 0, 0, 0, 18, 0, 0, 0, 24, 0, 0, 0, 202, 0, 0, 0, 125, 0, 0, 0, 165, 0, 0, 0, 104, 0, 0, 0, 67, 0, 0, 0, 163, 0, 0, 0, 109, 0, 0, 0, 20, 0, 0, 0, 42, 0, 0, 0, 106, 0, 0, 0, 165, 0, 0, 0, 142, 0, 0, 0, 50, 0, 0, +0, 231, 0, 0, 0, 99, 0, 0, 0, 79, 0, 0, 0, 227, 0, 0, 0, 198, 0, 0, 0, 68, 0, 0, 0, 62, 0, 0, 0, 171, 0, 0, 0, 99, 0, 0, 0, 202, 0, 0, 0, 23, 0, 0, 0, 134, 0, 0, 0, 116, 0, 0, 0, 63, 0, 0, 0, 30, 0, 0, 0, 100, 0, 0, 0, 193, 0, 0, 0, 125, 0, 0, 0, 82, 0, 0, 0, 220, 0, 0, 0, 19, 0, 0, 0, 90, 0, 0, 0, 161, 0, 0, 0, 156, 0, 0, 0, 78, 0, 0, 0, 238, 0, 0, 0, 153, 0, 0, 0, 40, 0, 0, 0, 187, 0, 0, 0, 76, 0, 0, 0, 238, 0, 0, 0, 172, 0, 0, 0, 169, 0, 0, 0, 27, 0, 0, 0, 137, 0, 0, 0, 162, 0, 0, 0, 56, 0, 0, +0, 57, 0, 0, 0, 123, 0, 0, 0, 196, 0, 0, 0, 15, 0, 0, 0, 66, 0, 0, 0, 230, 0, 0, 0, 137, 0, 0, 0, 237, 0, 0, 0, 15, 0, 0, 0, 243, 0, 0, 0, 60, 0, 0, 0, 140, 0, 0, 0, 128, 0, 0, 0, 131, 0, 0, 0, 16, 0, 0, 0, 138, 0, 0, 0, 55, 0, 0, 0, 80, 0, 0, 0, 156, 0, 0, 0, 180, 0, 0, 0, 223, 0, 0, 0, 63, 0, 0, 0, 140, 0, 0, 0, 247, 0, 0, 0, 35, 0, 0, 0, 7, 0, 0, 0, 214, 0, 0, 0, 255, 0, 0, 0, 160, 0, 0, 0, 130, 0, 0, 0, 108, 0, 0, 0, 117, 0, 0, 0, 59, 0, 0, 0, 228, 0, 0, 0, 181, 0, 0, 0, 187, 0, 0, 0, 228, 0, +0, 0, 230, 0, 0, 0, 80, 0, 0, 0, 240, 0, 0, 0, 8, 0, 0, 0, 98, 0, 0, 0, 238, 0, 0, 0, 117, 0, 0, 0, 72, 0, 0, 0, 146, 0, 0, 0, 51, 0, 0, 0, 242, 0, 0, 0, 244, 0, 0, 0, 173, 0, 0, 0, 21, 0, 0, 0, 122, 0, 0, 0, 161, 0, 0, 0, 1, 0, 0, 0, 70, 0, 0, 0, 169, 0, 0, 0, 50, 0, 0, 0, 6, 0, 0, 0, 136, 0, 0, 0, 182, 0, 0, 0, 54, 0, 0, 0, 71, 0, 0, 0, 53, 0, 0, 0, 185, 0, 0, 0, 180, 0, 0, 0, 66, 0, 0, 0, 133, 0, 0, 0, 118, 0, 0, 0, 240, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 56, 0, 0, 0, 81, 0, 0, 0, +21, 0, 0, 0, 157, 0, 0, 0, 195, 0, 0, 0, 149, 0, 0, 0, 209, 0, 0, 0, 57, 0, 0, 0, 187, 0, 0, 0, 100, 0, 0, 0, 157, 0, 0, 0, 21, 0, 0, 0, 129, 0, 0, 0, 193, 0, 0, 0, 104, 0, 0, 0, 208, 0, 0, 0, 182, 0, 0, 0, 164, 0, 0, 0, 44, 0, 0, 0, 125, 0, 0, 0, 94, 0, 0, 0, 2, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 59, 0, 0, 0, 164, 0, 0, 0, 204, 0, 0, 0, 202, 0, 0, 0, 29, 0, 0, 0, 129, 0, 0, 0, 36, 0, 0, 0, 16, 0, 0, 0, 231, 0, 0, 0, 41, 0, 0, 0, 249, 0, 0, 0, 55, 0, 0, 0, 217, 0, 0, 0, 70, 0, 0, 0, +90, 0, 0, 0, 205, 0, 0, 0, 112, 0, 0, 0, 254, 0, 0, 0, 77, 0, 0, 0, 91, 0, 0, 0, 191, 0, 0, 0, 165, 0, 0, 0, 207, 0, 0, 0, 145, 0, 0, 0, 244, 0, 0, 0, 239, 0, 0, 0, 238, 0, 0, 0, 138, 0, 0, 0, 41, 0, 0, 0, 208, 0, 0, 0, 231, 0, 0, 0, 196, 0, 0, 0, 37, 0, 0, 0, 146, 0, 0, 0, 138, 0, 0, 0, 255, 0, 0, 0, 54, 0, 0, 0, 252, 0, 0, 0, 228, 0, 0, 0, 73, 0, 0, 0, 189, 0, 0, 0, 0, 0, 0, 0, 185, 0, 0, 0, 4, 0, 0, 0, 125, 0, 0, 0, 53, 0, 0, 0, 252, 0, 0, 0, 235, 0, 0, 0, 208, 0, 0, 0, 11, 0, 0, 0, 5, 0, 0, 0, +50, 0, 0, 0, 82, 0, 0, 0, 122, 0, 0, 0, 137, 0, 0, 0, 36, 0, 0, 0, 117, 0, 0, 0, 80, 0, 0, 0, 225, 0, 0, 0, 99, 0, 0, 0, 2, 0, 0, 0, 130, 0, 0, 0, 142, 0, 0, 0, 231, 0, 0, 0, 133, 0, 0, 0, 12, 0, 0, 0, 242, 0, 0, 0, 86, 0, 0, 0, 68, 0, 0, 0, 55, 0, 0, 0, 131, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 161, 0, 0, 0, 206, 0, 0, 0, 203, 0, 0, 0, 96, 0, 0, 0, 218, 0, 0, 0, 18, 0, 0, 0, 2, 0, 0, 0, 30, 0, 0, 0, 41, 0, 0, 0, 57, 0, 0, 0, 42, 0, 0, 0, 3, 0, 0, 0, 183, 0, 0, 0, 235, 0, 0, 0, 119, 0, 0, 0, 64, 0, +0, 0, 234, 0, 0, 0, 201, 0, 0, 0, 43, 0, 0, 0, 44, 0, 0, 0, 213, 0, 0, 0, 125, 0, 0, 0, 126, 0, 0, 0, 44, 0, 0, 0, 199, 0, 0, 0, 90, 0, 0, 0, 253, 0, 0, 0, 255, 0, 0, 0, 196, 0, 0, 0, 209, 0, 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 136, 0, 0, +0, 152, 0, 0, 0, 91, 0, 0, 0, 78, 0, 0, 0, 252, 0, 0, 0, 65, 0, 0, 0, 36, 0, 0, 0, 5, 0, 0, 0, 230, 0, 0, 0, 80, 0, 0, 0, 43, 0, 0, 0, 174, 0, 0, 0, 150, 0, 0, 0, 81, 0, 0, 0, 217, 0, 0, 0, 107, 0, 0, 0, 114, 0, 0, 0, 178, 0, 0, 0, 51, 0, 0, 0, 66, 0, 0, 0, 152, 0, 0, 0, 104, 0, 0, 0, 187, 0, 0, 0, 16, 0, 0, 0, 90, 0, 0, 0, 122, 0, 0, 0, 140, 0, 0, 0, 157, 0, 0, 0, 7, 0, 0, 0, 180, 0, 0, 0, 5, 0, 0, 0, 47, 0, 0, 0, 97, 0, 0, 0, 159, 0, 0, 0, 215, 0, 0, 0, 168, 0, 0, 0, 63, 0, 0, 0, 131, 0, 0, 0, +140, 0, 0, 0, 16, 0, 0, 0, 105, 0, 0, 0, 144, 0, 0, 0, 230, 0, 0, 0, 207, 0, 0, 0, 210, 0, 0, 0, 99, 0, 0, 0, 163, 0, 0, 0, 228, 0, 0, 0, 84, 0, 0, 0, 126, 0, 0, 0, 229, 0, 0, 0, 105, 0, 0, 0, 19, 0, 0, 0, 28, 0, 0, 0, 144, 0, 0, 0, 87, 0, 0, 0, 170, 0, 0, 0, 233, 0, 0, 0, 83, 0, 0, 0, 34, 0, 0, 0, 67, 0, 0, 0, 41, 0, 0, 0, 35, 0, 0, 0, 229, 0, 0, 0, 28, 0, 0, 0, 248, 0, 0, 0, 10, 0, 0, 0, 253, 0, 0, 0, 45, 0, 0, 0, 126, 0, 0, 0, 245, 0, 0, 0, 245, 0, 0, 0, 112, 0, 0, 0, 125, 0, 0, 0, 65, 0, 0, 0, +107, 0, 0, 0, 17, 0, 0, 0, 254, 0, 0, 0, 190, 0, 0, 0, 153, 0, 0, 0, 209, 0, 0, 0, 85, 0, 0, 0, 41, 0, 0, 0, 49, 0, 0, 0, 191, 0, 0, 0, 192, 0, 0, 0, 151, 0, 0, 0, 108, 0, 0, 0, 213, 0, 0, 0, 53, 0, 0, 0, 204, 0, 0, 0, 94, 0, 0, 0, 139, 0, 0, 0, 217, 0, 0, 0, 105, 0, 0, 0, 142, 0, 0, 0, 78, 0, 0, 0, 159, 0, 0, 0, 37, 0, 0, 0, 248, 0, 0, 0, 129, 0, 0, 0, 84, 0, 0, 0, 45, 0, 0, 0, 14, 0, 0, 0, 213, 0, 0, 0, 84, 0, 0, 0, 129, 0, 0, 0, 155, 0, 0, 0, 166, 0, 0, 0, 146, 0, 0, 0, 206, 0, 0, 0, 75, 0, 0, +0, 233, 0, 0, 0, 143, 0, 0, 0, 36, 0, 0, 0, 59, 0, 0, 0, 202, 0, 0, 0, 224, 0, 0, 0, 68, 0, 0, 0, 171, 0, 0, 0, 54, 0, 0, 0, 254, 0, 0, 0, 251, 0, 0, 0, 135, 0, 0, 0, 212, 0, 0, 0, 38, 0, 0, 0, 62, 0, 0, 0, 15, 0, 0, 0, 147, 0, 0, 0, 156, 0, 0, 0, 17, 0, 0, 0, 231, 0, 0, 0, 219, 0, 0, 0, 241, 0, 0, 0, 240, 0, 0, 0, 133, 0, 0, 0, 67, 0, 0, 0, 40, 0, 0, 0, 21, 0, 0, 0, 55, 0, 0, 0, 221, 0, 0, 0, 222, 0, 0, 0, 39, 0, 0, 0, 223, 0, 0, 0, 173, 0, 0, 0, 62, 0, 0, 0, 73, 0, 0, 0, 79, 0, 0, 0, 224, 0, 0, +0, 91, 0, 0, 0, 246, 0, 0, 0, 128, 0, 0, 0, 89, 0, 0, 0, 21, 0, 0, 0, 60, 0, 0, 0, 133, 0, 0, 0, 183, 0, 0, 0, 62, 0, 0, 0, 18, 0, 0, 0, 245, 0, 0, 0, 255, 0, 0, 0, 204, 0, 0, 0, 240, 0, 0, 0, 180, 0, 0, 0, 18, 0, 0, 0, 3, 0, 0, 0, 95, 0, 0, 0, 201, 0, 0, 0, 132, 0, 0, 0, 203, 0, 0, 0, 29, 0, 0, 0, 23, 0, 0, 0, 224, 0, 0, 0, 188, 0, 0, 0, 204, 0, 0, 0, 3, 0, 0, 0, 98, 0, 0, 0, 169, 0, 0, 0, 139, 0, 0, 0, 148, 0, 0, 0, 166, 0, 0, 0, 170, 0, 0, 0, 24, 0, 0, 0, 203, 0, 0, 0, 39, 0, 0, 0, 141, 0, 0, +0, 73, 0, 0, 0, 166, 0, 0, 0, 23, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 217, 0, 0, 0, 182, 0, 0, 0, 212, 0, 0, 0, 157, 0, 0, 0, 212, 0, 0, 0, 106, 0, 0, 0, 175, 0, 0, 0, 112, 0, 0, 0, 7, 0, 0, 0, 44, 0, 0, 0, 16, 0, 0, 0, 158, 0, 0, 0, 189, 0, 0, 0, 17, 0, 0, 0, 173, 0, 0, 0, 228, 0, 0, 0, 38, 0, 0, 0, 51, 0, 0, 0, 112, 0, 0, 0, 146, 0, 0, 0, 120, 0, 0, 0, 28, 0, 0, 0, 116, 0, 0, 0, 159, 0, 0, 0, 117, 0, 0, 0, 96, 0, 0, 0, 86, 0, 0, 0, 244, 0, 0, 0, 57, 0, 0, 0, 168, 0, 0, 0, 168, 0, 0, 0, 98, 0, 0, +0, 59, 0, 0, 0, 191, 0, 0, 0, 85, 0, 0, 0, 53, 0, 0, 0, 97, 0, 0, 0, 139, 0, 0, 0, 68, 0, 0, 0, 151, 0, 0, 0, 232, 0, 0, 0, 58, 0, 0, 0, 85, 0, 0, 0, 193, 0, 0, 0, 200, 0, 0, 0, 59, 0, 0, 0, 253, 0, 0, 0, 149, 0, 0, 0, 41, 0, 0, 0, 17, 0, 0, 0, 96, 0, 0, 0, 150, 0, 0, 0, 30, 0, 0, 0, 203, 0, 0, 0, 17, 0, 0, 0, 157, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 138, 0, 0, 0, 27, 0, 0, 0, 198, 0, 0, 0, 214, 0, 0, 0, 69, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 14, 0, 0, 0, 80, 0, 0, 0, 178, 0, 0, 0, 204, 0, 0, 0, 13, 0, 0, 0, 107, 0, 0, 0, 166, 0, 0, 0, 113, 0, 0, 0, 91, 0, 0, 0, 66, 0, 0, 0, 237, 0, 0, 0, 189, 0, 0, 0, 175, 0, 0, 0, 172, 0, 0, 0, 240, 0, 0, 0, 252, 0, 0, 0, 18, 0, 0, 0, 162, 0, 0, 0, 63, 0, 0, 0, 78, 0, 0, 0, 218, 0, 0, 0, 232, +0, 0, 0, 17, 0, 0, 0, 243, 0, 0, 0, 35, 0, 0, 0, 225, 0, 0, 0, 4, 0, 0, 0, 98, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0, 78, 0, 0, 0, 200, 0, 0, 0, 177, 0, 0, 0, 27, 0, 0, 0, 111, 0, 0, 0, 115, 0, 0, 0, 97, 0, 0, 0, 61, 0, 0, 0, 39, 0, 0, 0, 13, 0, 0, 0, 125, 0, 0, 0, 122, 0, 0, 0, 37, 0, 0, 0, 95, 0, 0, 0, 115, 0, 0, 0, 14, 0, 0, 0, 47, 0, 0, 0, 147, 0, 0, 0, 246, 0, 0, 0, 36, 0, 0, 0, 216, 0, 0, 0, 79, 0, 0, 0, 144, 0, 0, 0, 172, 0, 0, 0, 162, 0, 0, 0, 98, 0, 0, 0, 10, 0, 0, 0, 240, 0, 0, 0, 97, 0, 0, +0, 217, 0, 0, 0, 8, 0, 0, 0, 89, 0, 0, 0, 106, 0, 0, 0, 111, 0, 0, 0, 45, 0, 0, 0, 85, 0, 0, 0, 248, 0, 0, 0, 47, 0, 0, 0, 142, 0, 0, 0, 240, 0, 0, 0, 24, 0, 0, 0, 59, 0, 0, 0, 234, 0, 0, 0, 221, 0, 0, 0, 38, 0, 0, 0, 114, 0, 0, 0, 209, 0, 0, 0, 245, 0, 0, 0, 254, 0, 0, 0, 229, 0, 0, 0, 184, 0, 0, 0, 230, 0, 0, 0, 211, 0, 0, 0]).concat([16, 0, 0, 0, 72, 0, 0, 0, 70, 0, 0, 0, 73, 0, 0, 0, 58, 0, 0, 0, 159, 0, 0, 0, 94, 0, 0, 0, 69, 0, 0, 0, 107, 0, 0, 0, 144, 0, 0, 0, 232, 0, 0, 0, 127, 0, 0, 0, 211, +0, 0, 0, 118, 0, 0, 0, 105, 0, 0, 0, 51, 0, 0, 0, 123, 0, 0, 0, 185, 0, 0, 0, 64, 0, 0, 0, 112, 0, 0, 0, 238, 0, 0, 0, 166, 0, 0, 0, 41, 0, 0, 0, 107, 0, 0, 0, 221, 0, 0, 0, 208, 0, 0, 0, 93, 0, 0, 0, 141, 0, 0, 0, 193, 0, 0, 0, 62, 0, 0, 0, 74, 0, 0, 0, 234, 0, 0, 0, 55, 0, 0, 0, 177, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 53, 0, 0, 0, 241, 0, 0, 0, 40, 0, 0, 0, 157, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 122, 0, 0, 0, 219, 0, 0, 0, 18, 0, 0, 0, 210, 0, 0, 0, 138, 0, 0, 0, 130, 0, +0, 0, 3, 0, 0, 0, 27, 0, 0, 0, 30, 0, 0, 0, 175, 0, 0, 0, 249, 0, 0, 0, 75, 0, 0, 0, 156, 0, 0, 0, 190, 0, 0, 0, 174, 0, 0, 0, 124, 0, 0, 0, 228, 0, 0, 0, 148, 0, 0, 0, 42, 0, 0, 0, 35, 0, 0, 0, 179, 0, 0, 0, 98, 0, 0, 0, 134, 0, 0, 0, 231, 0, 0, 0, 253, 0, 0, 0, 35, 0, 0, 0, 170, 0, 0, 0, 153, 0, 0, 0, 189, 0, 0, 0, 43, 0, 0, 0, 17, 0, 0, 0, 108, 0, 0, 0, 141, 0, 0, 0, 166, 0, 0, 0, 213, 0, 0, 0, 172, 0, 0, 0, 157, 0, 0, 0, 204, 0, 0, 0, 104, 0, 0, 0, 117, 0, 0, 0, 127, 0, 0, 0, 195, 0, 0, 0, 77, +0, 0, 0, 75, 0, 0, 0, 221, 0, 0, 0, 108, 0, 0, 0, 187, 0, 0, 0, 17, 0, 0, 0, 90, 0, 0, 0, 96, 0, 0, 0, 229, 0, 0, 0, 189, 0, 0, 0, 125, 0, 0, 0, 39, 0, 0, 0, 139, 0, 0, 0, 218, 0, 0, 0, 180, 0, 0, 0, 149, 0, 0, 0, 246, 0, 0, 0, 3, 0, 0, 0, 39, 0, 0, 0, 164, 0, 0, 0, 146, 0, 0, 0, 63, 0, 0, 0, 34, 0, 0, 0, 214, 0, 0, 0, 181, 0, 0, 0, 23, 0, 0, 0, 132, 0, 0, 0, 191, 0, 0, 0, 18, 0, 0, 0, 204, 0, 0, 0, 35, 0, 0, 0, 20, 0, 0, 0, 74, 0, 0, 0, 223, 0, 0, 0, 20, 0, 0, 0, 49, 0, 0, 0, 188, 0, 0, 0, 161, +0, 0, 0, 172, 0, 0, 0, 110, 0, 0, 0, 171, 0, 0, 0, 250, 0, 0, 0, 87, 0, 0, 0, 17, 0, 0, 0, 83, 0, 0, 0, 179, 0, 0, 0, 39, 0, 0, 0, 230, 0, 0, 0, 249, 0, 0, 0, 71, 0, 0, 0, 51, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 30, 0, 0, 0, 121, 0, 0, 0, 252, 0, 0, 0, 166, 0, 0, 0, 180, 0, 0, 0, 11, 0, 0, 0, 53, 0, 0, 0, 32, 0, 0, 0, 201, 0, 0, 0, 77, 0, 0, 0, 34, 0, 0, 0, 132, 0, 0, 0, 196, 0, 0, 0, 169, 0, 0, 0, 32, 0, 0, 0, 236, 0, 0, 0, 137, 0, 0, 0, 148, 0, 0, 0, 186, 0, 0, 0, 102, 0, 0, 0, 86, 0, 0, 0, 72, +0, 0, 0, 185, 0, 0, 0, 135, 0, 0, 0, 127, 0, 0, 0, 202, 0, 0, 0, 30, 0, 0, 0, 6, 0, 0, 0, 237, 0, 0, 0, 165, 0, 0, 0, 85, 0, 0, 0, 89, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, 225, 0, 0, 0, 245, 0, 0, 0, 241, 0, 0, 0, 213, 0, 0, 0, 171, 0, 0, +0, 168, 0, 0, 0, 43, 0, 0, 0, 174, 0, 0, 0, 137, 0, 0, 0, 243, 0, 0, 0, 207, 0, 0, 0, 86, 0, 0, 0, 159, 0, 0, 0, 242, 0, 0, 0, 75, 0, 0, 0, 49, 0, 0, 0, 188, 0, 0, 0, 24, 0, 0, 0, 169, 0, 0, 0, 6, 0, 0, 0, 91, 0, 0, 0, 190, 0, 0, 0, 180, 0, 0, 0, 97, 0, 0, 0, 248, 0, 0, 0, 178, 0, 0, 0, 6, 0, 0, 0, 156, 0, 0, 0, 129, 0, 0, 0, 171, 0, 0, 0, 76, 0, 0, 0, 31, 0, 0, 0, 104, 0, 0, 0, 118, 0, 0, 0, 1, 0, 0, 0, 22, 0, 0, 0, 56, 0, 0, 0, 43, 0, 0, 0, 15, 0, 0, 0, 119, 0, 0, 0, 151, 0, 0, 0, 146, 0, 0, 0, +103, 0, 0, 0, 78, 0, 0, 0, 134, 0, 0, 0, 106, 0, 0, 0, 139, 0, 0, 0, 229, 0, 0, 0, 232, 0, 0, 0, 12, 0, 0, 0, 247, 0, 0, 0, 54, 0, 0, 0, 57, 0, 0, 0, 181, 0, 0, 0, 51, 0, 0, 0, 230, 0, 0, 0, 207, 0, 0, 0, 94, 0, 0, 0, 189, 0, 0, 0, 24, 0, 0, 0, 251, 0, 0, 0, 16, 0, 0, 0, 31, 0, 0, 0, 131, 0, 0, 0, 240, 0, 0, 0, 13, 0, 0, 0, 99, 0, 0, 0, 239, 0, 0, 0, 83, 0, 0, 0, 107, 0, 0, 0, 181, 0, 0, 0, 107, 0, 0, 0, 249, 0, 0, 0, 131, 0, 0, 0, 207, 0, 0, 0, 222, 0, 0, 0, 4, 0, 0, 0, 34, 0, 0, 0, 155, 0, 0, 0, +44, 0, 0, 0, 10, 0, 0, 0, 224, 0, 0, 0, 165, 0, 0, 0, 216, 0, 0, 0, 199, 0, 0, 0, 156, 0, 0, 0, 165, 0, 0, 0, 163, 0, 0, 0, 246, 0, 0, 0, 111, 0, 0, 0, 207, 0, 0, 0, 144, 0, 0, 0, 107, 0, 0, 0, 104, 0, 0, 0, 124, 0, 0, 0, 51, 0, 0, 0, 21, 0, 0, 0, 215, 0, 0, 0, 127, 0, 0, 0, 26, 0, 0, 0, 213, 0, 0, 0, 33, 0, 0, 0, 88, 0, 0, 0, 196, 0, 0, 0, 24, 0, 0, 0, 165, 0, 0, 0, 240, 0, 0, 0, 204, 0, 0, 0, 115, 0, 0, 0, 168, 0, 0, 0, 253, 0, 0, 0, 250, 0, 0, 0, 24, 0, 0, 0, 209, 0, 0, 0, 3, 0, 0, 0, 145, 0, +0, 0, 141, 0, 0, 0, 82, 0, 0, 0, 210, 0, 0, 0, 163, 0, 0, 0, 164, 0, 0, 0, 211, 0, 0, 0, 177, 0, 0, 0, 234, 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 204, 0, 0, 0, 72, 0, 0, 0, 131, 0, 0, 0, 144, 0, 0, 0, 229, 0, 0, 0, 253, 0, 0, 0, 63, 0, 0, 0, 132, 0, 0, 0, 170, 0, 0, 0, 249, 0, 0, 0, 139, 0, 0, 0, 130, 0, 0, 0, 89, 0, 0, 0, 36, 0, 0, 0, 52, 0, 0, 0, 104, 0, 0, 0, 79, 0, 0, 0, 28, 0, 0, 0, 35, 0, 0, 0, 217, 0, 0, 0, 204, 0, 0, 0, 113, 0, 0, 0, 225, 0, 0, 0, 127, 0, 0, 0, 140, 0, 0, 0, 175, +0, 0, 0, 241, 0, 0, 0, 238, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 160, 0, 0, 0, 119, 0, 0, 0, 245, 0, 0, 0, 26, 0, 0, 0, 97, 0, 0, 0, 247, 0, 0, 0, 55, 0, 0, 0, 157, 0, 0, 0, 0, 0, 0, 0, 244, 0, 0, 0, 242, 0, 0, 0, 105, 0, 0, 0, 111, 0, 0, 0, 75, 0, 0, 0, 1, 0, 0, 0, 133, 0, 0, 0, 25, 0, 0, 0, 69, 0, 0, 0, 77, 0, 0, 0, 127, 0, 0, 0, 2, 0, 0, 0, 124, 0, 0, 0, 106, 0, 0, 0, 5, 0, 0, 0, 71, 0, 0, 0, 108, 0, 0, 0, 31, 0, 0, 0, 129, 0, 0, 0, 32, 0, 0, 0, 212, 0, 0, 0, 232, 0, 0, 0, 80, 0, 0, 0, 39, 0, 0, +0, 114, 0, 0, 0, 44, 0, 0, 0, 58, 0, 0, 0, 229, 0, 0, 0, 173, 0, 0, 0, 244, 0, 0, 0, 221, 0, 0, 0, 45, 0, 0, 0, 247, 0, 0, 0, 92, 0, 0, 0, 68, 0, 0, 0, 181, 0, 0, 0, 91, 0, 0, 0, 33, 0, 0, 0, 163, 0, 0, 0, 137, 0, 0, 0, 95, 0, 0, 0, 150, 0, 0, 0, 69, 0, 0, 0, 202, 0, 0, 0, 77, 0, 0, 0, 164, 0, 0, 0, 33, 0, 0, 0, 153, 0, 0, 0, 112, 0, 0, 0, 218, 0, 0, 0, 196, 0, 0, 0, 196, 0, 0, 0, 160, 0, 0, 0, 229, 0, 0, 0, 244, 0, 0, 0, 236, 0, 0, 0, 10, 0, 0, 0, 7, 0, 0, 0, 104, 0, 0, 0, 33, 0, 0, 0, 101, 0, 0, +0, 233, 0, 0, 0, 8, 0, 0, 0, 160, 0, 0, 0, 11, 0, 0, 0, 106, 0, 0, 0, 74, 0, 0, 0, 186, 0, 0, 0, 181, 0, 0, 0, 128, 0, 0, 0, 175, 0, 0, 0, 208, 0, 0, 0, 27, 0, 0, 0, 197, 0, 0, 0, 245, 0, 0, 0, 75, 0, 0, 0, 115, 0, 0, 0, 80, 0, 0, 0, 96, 0, 0, 0, 45, 0, 0, 0, 113, 0, 0, 0, 105, 0, 0, 0, 97, 0, 0, 0, 14, 0, 0, 0, 192, 0, 0, 0, 32, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 117, 0, 0, 0, 87, 0, 0, 0, 59, 0, 0, 0, 235, 0, 0, 0, 92, 0, 0, 0, 20, 0, 0, 0, 86, 0, 0, 0, 80, 0, 0, 0, 201, 0, 0, 0, 79, 0, 0, 0, 184, 0, 0, 0, 184, 0, 0, 0, 30, 0, 0, 0, 163, 0, 0, 0, 244, 0, 0, 0, 171, 0, 0, 0, 245, 0, 0, 0, 169, 0, 0, 0, 32, 0, 0, 0, 21, 0, 0, 0, 148, 0, 0, 0, 130, 0, 0, 0, 218, 0, 0, 0, 150, 0, 0, 0, 28, 0, 0, 0, 155, +0, 0, 0, 89, 0, 0, 0, 140, 0, 0, 0, 255, 0, 0, 0, 244, 0, 0, 0, 81, 0, 0, 0, 193, 0, 0, 0, 58, 0, 0, 0, 134, 0, 0, 0, 215, 0, 0, 0, 176, 0, 0, 0, 6, 0, 0, 0, 132, 0, 0, 0, 127, 0, 0, 0, 27, 0, 0, 0, 189, 0, 0, 0, 212, 0, 0, 0, 7, 0, 0, 0, 120, 0, 0, 0, 128, 0, 0, 0, 46, 0, 0, 0, 177, 0, 0, 0, 180, 0, 0, 0, 238, 0, 0, 0, 82, 0, 0, 0, 56, 0, 0, 0, 238, 0, 0, 0, 154, 0, 0, 0, 249, 0, 0, 0, 246, 0, 0, 0, 243, 0, 0, 0, 65, 0, 0, 0, 110, 0, 0, 0, 212, 0, 0, 0, 136, 0, 0, 0, 149, 0, 0, 0, 172, 0, 0, 0, +53, 0, 0, 0, 65, 0, 0, 0, 151, 0, 0, 0, 191, 0, 0, 0, 113, 0, 0, 0, 106, 0, 0, 0, 155, 0, 0, 0, 114, 0, 0, 0, 236, 0, 0, 0, 243, 0, 0, 0, 248, 0, 0, 0, 107, 0, 0, 0, 230, 0, 0, 0, 14, 0, 0, 0, 108, 0, 0, 0, 105, 0, 0, 0, 165, 0, 0, 0, 47, 0, 0, 0, 104, 0, 0, 0, 82, 0, 0, 0, 216, 0, 0, 0, 97, 0, 0, 0, 129, 0, 0, 0, 192, 0, 0, 0, 99, 0, 0, 0, 63, 0, 0, 0, 166, 0, 0, 0, 60, 0, 0, 0, 19, 0, 0, 0, 144, 0, 0, 0, 230, 0, 0, 0, 141, 0, 0, 0, 86, 0, 0, 0, 232, 0, 0, 0, 57, 0, 0, 0, 48, 0, 0, 0, 119, 0, 0, +0, 35, 0, 0, 0, 177, 0, 0, 0, 253, 0, 0, 0, 27, 0, 0, 0, 61, 0, 0, 0, 62, 0, 0, 0, 116, 0, 0, 0, 77, 0, 0, 0, 127, 0, 0, 0, 174, 0, 0, 0, 91, 0, 0, 0, 58, 0, 0, 0, 180, 0, 0, 0, 101, 0, 0, 0, 14, 0, 0, 0, 58, 0, 0, 0, 67, 0, 0, 0, 220, 0, 0, 0, 220, 0, 0, 0, 65, 0, 0, 0, 71, 0, 0, 0, 230, 0, 0, 0, 232, 0, 0, 0, 146, 0, 0, 0, 9, 0, 0, 0, 34, 0, 0, 0, 72, 0, 0, 0, 76, 0, 0, 0, 133, 0, 0, 0, 87, 0, 0, 0, 159, 0, 0, 0, 181, 0, 0, 0, 200, 0, 0, 0, 6, 0, 0, 0, 178, 0, 0, 0, 159, 0, 0, 0, 71, 0, 0, 0, 63, +0, 0, 0, 240, 0, 0, 0, 250, 0, 0, 0, 230, 0, 0, 0, 169, 0, 0, 0, 177, 0, 0, 0, 155, 0, 0, 0, 111, 0, 0, 0, 150, 0, 0, 0, 125, 0, 0, 0, 249, 0, 0, 0, 164, 0, 0, 0, 101, 0, 0, 0, 9, 0, 0, 0, 117, 0, 0, 0, 50, 0, 0, 0, 166, 0, 0, 0, 108, 0, 0, 0, 127, 0, 0, 0, 71, 0, 0, 0, 75, 0, 0, 0, 47, 0, 0, 0, 79, 0, 0, 0, 52, 0, 0, 0, 233, 0, 0, 0, 89, 0, 0, 0, 147, 0, 0, 0, 157, 0, 0, 0, 38, 0, 0, 0, 128, 0, 0, 0, 84, 0, 0, 0, 242, 0, 0, 0, 204, 0, 0, 0, 60, 0, 0, 0, 194, 0, 0, 0, 37, 0, 0, 0, 133, 0, 0, 0, 227, +0, 0, 0, 106, 0, 0, 0, 193, 0, 0, 0, 98, 0, 0, 0, 4, 0, 0, 0, 167, 0, 0, 0, 8, 0, 0, 0, 50, 0, 0, 0, 109, 0, 0, 0, 161, 0, 0, 0, 57, 0, 0, 0, 132, 0, 0, 0, 138, 0, 0, 0, 59, 0, 0, 0, 135, 0, 0, 0, 95, 0, 0, 0, 17, 0, 0, 0, 19, 0, 0, 0, 218, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 102, 0, 0, 0, 196, 0, 0, 0, 12, 0, 0, 0, 115, 0, 0, 0, 110, 0, 0, 0, 188, 0, 0, 0, 36, 0, 0, 0, 181, 0, 0, 0, 249, 0, 0, 0, 112, 0, 0, 0, 129, 0, 0, 0, 82, 0, 0, 0, 233, 0, 0, 0, 244, 0, 0, 0, 124, 0, 0, 0, 35, 0, 0, 0, 221, 0, +0, 0, 159, 0, 0, 0, 184, 0, 0, 0, 70, 0, 0, 0, 239, 0, 0, 0, 29, 0, 0, 0, 34, 0, 0, 0, 85, 0, 0, 0, 125, 0, 0, 0, 113, 0, 0, 0, 196, 0, 0, 0, 66, 0, 0, 0, 51, 0, 0, 0, 197, 0, 0, 0, 55, 0, 0, 0, 105, 0, 0, 0, 91, 0, 0, 0, 168, 0, 0, 0, 198, 0, 0, 0, 157, 0, 0, 0, 164, 0, 0, 0, 252, 0, 0, 0, 97, 0, 0, 0, 110, 0, 0, 0, 104, 0, 0, 0, 70, 0, 0, 0, 234, 0, 0, 0, 215, 0, 0, 0, 28, 0, 0, 0, 103, 0, 0, 0, 210, 0, 0, 0, 125, 0, 0, 0, 250, 0, 0, 0, 241, 0, 0, 0, 204, 0, 0, 0, 84, 0, 0, 0, 141, 0, 0, 0, 54, +0, 0, 0, 53, 0, 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, 223, 0, 0, 0, 108, 0, 0, 0, 103, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 0, 0, 0, 77, 0, 0, 0, 66, 0, 0, 0, 41, 0, 0, 0, 93, 0, 0, 0, 164, 0, 0, 0, 107, 0, 0, 0, 111, 0, 0, 0, 168, 0, 0, 0, 138, 0, 0, +0, 77, 0, 0, 0, 145, 0, 0, 0, 123, 0, 0, 0, 210, 0, 0, 0, 223, 0, 0, 0, 54, 0, 0, 0, 239, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 197, 0, 0, 0, 204, 0, 0, 0, 141, 0, 0, 0, 235, 0, 0, 0, 88, 0, 0, 0, 61, 0, 0, 0, 179, 0, 0, 0, 80, 0, 0, 0, 252, 0, 0, 0, 139, 0, 0, 0, 151, 0, 0, 0, 150, 0, 0, 0, 51, 0, 0, 0, 147, 0, 0, 0, 51, 0, 0, 0, 7, 0, 0, 0, 200, 0, 0, 0, 74, 0, 0, 0, 202, 0, 0, 0, 208, 0, 0, 0, 177, 0, 0, 0, 171, 0, 0, 0, 189, 0, 0, 0, 221, 0, 0, 0, 167, 0, 0, 0, 124, 0, 0, 0, 172, 0, 0, 0, 62, 0, +0, 0, 69, 0, 0, 0, 203, 0, 0, 0, 204, 0, 0, 0, 7, 0, 0, 0, 145, 0, 0, 0, 191, 0, 0, 0, 53, 0, 0, 0, 157, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 18, 0, 0, 0, 60, 0, 0, 0, 17, 0, 0, 0, 89, 0, 0, 0, 19, 0, 0, 0, 207, 0, 0, 0, 92, 0, 0, 0, 69, 0, 0, 0, 184, 0, 0, 0, 65, 0, 0, 0, 215, 0, 0, 0, 171, 0, 0, 0, 7, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, 206, 0, 0, 0, 223, 0, 0, 0, 178, 0, 0, 0, 67, 0, 0, 0, 92, 0, 0, 0, 1, 0, 0, 0, 220, 0, 0, 0, 244, 0, 0, 0, 1, 0, 0, 0, 81, 0, 0, 0, 149, 0, 0, 0, 16, +0, 0, 0, 90, 0, 0, 0, 246, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 160, 0, 0, 0, 25, 0, 0, 0, 58, 0, 0, 0, 9, 0, 0, 0, 42, 0, 0, 0, 170, 0, 0, 0, 63, 0, 0, 0, 220, 0, 0, 0, 142, 0, 0, 0, 235, 0, 0, 0, 198, 0, 0, 0, 191, 0, 0, 0, 221, 0, 0, 0, 17, 0, 0, 0, 123, 0, 0, 0, 231, 0, 0, 0, 71, 0, 0, 0, 230, 0, 0, 0, 206, 0, 0, 0, 231, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 232, 0, 0, 0, 138, 0, 0, 0, 220, 0, 0, 0, 75, 0, 0, 0, 87, 0, 0, 0, 21, 0, 0, 0, 59, 0, 0, 0, 102, 0, 0, 0, 202, 0, 0, 0, 137, 0, 0, 0, 163, +0, 0, 0, 253, 0, 0, 0, 172, 0, 0, 0, 13, 0, 0, 0, 225, 0, 0, 0, 29, 0, 0, 0, 122, 0, 0, 0, 137, 0, 0, 0, 239, 0, 0, 0, 191, 0, 0, 0, 3, 0, 0, 0, 117, 0, 0, 0, 208, 0, 0, 0, 41, 0, 0, 0, 80, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 214, 0, 0, 0, 190, 0, 0, 0, 173, 0, 0, 0, 95, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 170, 0, 0, 0, 152, 0, 0, 0, 237, 0, 0, 0, 63, 0, 0, 0, 143, 0, 0, 0, 146, 0, 0, 0, 203, 0, 0, 0, 129, 0, 0, 0, 86, 0, 0, 0, 1, 0, 0, 0, 99, 0, 0, 0, 100, 0, 0, 0, 163, 0, 0, 0, 56, +0, 0, 0, 57, 0, 0, 0, 139, 0, 0, 0, 164, 0, 0, 0, 214, 0, 0, 0, 80, 0, 0, 0, 180, 0, 0, 0, 170, 0, 0, 0, 93, 0, 0, 0, 100, 0, 0, 0, 100, 0, 0, 0, 118, 0, 0, 0, 46, 0, 0, 0, 161, 0, 0, 0, 166, 0, 0, 0, 179, 0, 0, 0, 184, 0, 0, 0, 124, 0, 0, 0, 122, 0, 0, 0, 86, 0, 0, 0, 245, 0, 0, 0, 92, 0, 0, 0, 78, 0, 0, 0, 132, 0, 0, 0, 92, 0, 0, 0, 251, 0, 0, 0, 221, 0, 0, 0, 202, 0, 0, 0, 72, 0, 0, 0, 139, 0, 0, 0, 72, 0, 0, 0, 185, 0, 0, 0, 186, 0, 0, 0, 52, 0, 0, 0, 197, 0, 0, 0, 227, 0, 0, 0, 232, 0, 0, 0, +174, 0, 0, 0, 23, 0, 0, 0, 39, 0, 0, 0, 227, 0, 0, 0, 100, 0, 0, 0, 96, 0, 0, 0, 113, 0, 0, 0, 71, 0, 0, 0, 41, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0, 146, 0, 0, 0, 93, 0, 0, 0, 16, 0, 0, 0, 147, 0, 0, 0, 200, 0, 0, 0, 14, 0, 0, 0, 161, 0, 0, 0, 237, 0, 0, 0, 186, 0, 0, 0, 169, 0, 0, 0, 150, 0, 0, 0, 28, 0, 0, 0, 197, 0, 0, 0, 118, 0, 0, 0, 48, 0, 0, 0, 205, 0, 0, 0, 249, 0, 0, 0, 48, 0, 0, 0, 149, 0, 0, 0, 176, 0, 0, 0, 189, 0, 0, 0, 140, 0, 0, 0, 188, 0, 0, 0, 167, 0, 0, 0, 79, 0, 0, 0, 126, 0, 0, 0, +253, 0, 0, 0, 78, 0, 0, 0, 58, 0, 0, 0, 191, 0, 0, 0, 95, 0, 0, 0, 4, 0, 0, 0, 121, 0, 0, 0, 128, 0, 0, 0, 43, 0, 0, 0, 90, 0, 0, 0, 159, 0, 0, 0, 79, 0, 0, 0, 104, 0, 0, 0, 33, 0, 0, 0, 25, 0, 0, 0, 113, 0, 0, 0, 198, 0, 0, 0, 32, 0, 0, 0, 1, 0, 0, 0, 66, 0, 0, 0, 170, 0, 0, 0, 223, 0, 0, 0, 174, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 110, 0, 0, 0, 126, 0, 0, 0, 75, 0, 0, 0, 113, 0, 0, 0, 147, 0, 0, 0, 192, 0, 0, 0, 114, 0, 0, 0, 237, 0, 0, 0, 235, 0, 0, 0, 113, 0, 0, 0, 36, 0, 0, 0, 151, 0, 0, 0, 38, 0, 0, 0, 156, 0, 0, 0, 254, 0, 0, 0, 203, 0, 0, 0, 62, 0, 0, 0, 89, 0, 0, 0, 25, 0, 0, 0, 168, 0, 0, 0, 15, 0, 0, 0, 117, 0, 0, 0, 125, 0, 0, 0, 190, 0, 0, 0, 24, 0, 0, 0, 230, 0, 0, 0, 150, 0, 0, 0, 30, 0, 0, 0, 149, 0, 0, 0, 112, +0, 0, 0, 96, 0, 0, 0, 137, 0, 0, 0, 102, 0, 0, 0, 62, 0, 0, 0, 29, 0, 0, 0, 76, 0, 0, 0, 95, 0, 0, 0, 254, 0, 0, 0, 192, 0, 0, 0, 4, 0, 0, 0, 67, 0, 0, 0, 214, 0, 0, 0, 68, 0, 0, 0, 25, 0, 0, 0, 181, 0, 0, 0, 173, 0, 0, 0, 199, 0, 0, 0, 34, 0, 0, 0, 220, 0, 0, 0, 113, 0, 0, 0, 40, 0, 0, 0, 100, 0, 0, 0, 222, 0, 0, 0, 65, 0, 0, 0, 56, 0, 0, 0, 39, 0, 0, 0, 143, 0, 0, 0, 44, 0, 0, 0, 107, 0, 0, 0, 8, 0, 0, 0, 184, 0, 0, 0, 184, 0, 0, 0, 123, 0, 0, 0, 61, 0, 0, 0, 112, 0, 0, 0, 39, 0, 0, 0, 157, 0, +0, 0, 217, 0, 0, 0, 175, 0, 0, 0, 177, 0, 0, 0, 39, 0, 0, 0, 175, 0, 0, 0, 227, 0, 0, 0, 93, 0, 0, 0, 30, 0, 0, 0, 58, 0, 0, 0, 48, 0, 0, 0, 84, 0, 0, 0, 97, 0, 0, 0, 96, 0, 0, 0, 232, 0, 0, 0, 195, 0, 0, 0, 38, 0, 0, 0, 58, 0, 0, 0, 188, 0, 0, 0, 126, 0, 0, 0, 245, 0, 0, 0, 129, 0, 0, 0, 221, 0, 0, 0, 100, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 235, 0, 0, 0, 192, 0, 0, 0, 30, 0, 0, 0, 218, 0, 0, 0, 44, 0, 0, 0, 164, 0, 0, 0, 209, 0, 0, 0, 161, 0, 0, 0, 195, 0, 0, 0, 92, 0, 0, 0, 110, 0, 0, 0, 50, 0, 0, +0, 7, 0, 0, 0, 31, 0, 0, 0, 184, 0, 0, 0, 14, 0, 0, 0, 25, 0, 0, 0, 158, 0, 0, 0, 153, 0, 0, 0, 41, 0, 0, 0, 51, 0, 0, 0, 154, 0, 0, 0, 174, 0, 0, 0, 122, 0, 0, 0, 237, 0, 0, 0, 104, 0, 0, 0, 66, 0, 0, 0, 105, 0, 0, 0, 124, 0, 0, 0, 7, 0, 0, 0, 179, 0, 0, 0, 56, 0, 0, 0, 44, 0, 0, 0, 246, 0, 0, 0, 61, 0, 0, 0, 100, 0, 0, 0, 170, 0, 0, 0, 181, 0, 0, 0, 136, 0, 0, 0, 121, 0, 0, 0, 101, 0, 0, 0, 56, 0, 0, 0, 140, 0, 0, 0, 148, 0, 0, 0, 214, 0, 0, 0, 98, 0, 0, 0, 55, 0, 0, 0, 125, 0, 0, 0, 100, 0, 0, +0, 205, 0, 0, 0, 58, 0, 0, 0, 235, 0, 0, 0, 255, 0, 0, 0, 232, 0, 0, 0, 129, 0, 0, 0, 9, 0, 0, 0, 199, 0, 0, 0, 106, 0, 0, 0, 80, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 40, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 0, 154, 0, 0, 0, 147, 0, 0, 0, 10, 0, 0, 0, 66, 0, 0, 0, 163, 0, 0, 0, 241, 0, 0, 0, 197, 0, 0, 0, 180, 0, 0, 0, 15, 0, 0, 0, 216, 0, 0, 0, 200, 0, 0, 0, 141, 0, 0, 0, 21, 0, 0, 0, 49, 0, 0, 0, 189, 0, 0, 0, 248, 0, 0, 0, 7, 0, 0, 0, 139, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, 138, 0, 0, 0, 251, 0, 0, 0, +24, 0, 0, 0, 7, 0, 0, 0, 254, 0, 0, 0, 142, 0, 0, 0, 82, 0, 0, 0, 134, 0, 0, 0, 239, 0, 0, 0, 190, 0, 0, 0, 236, 0, 0, 0, 73, 0, 0, 0, 82, 0, 0, 0, 153, 0, 0, 0, 8, 0, 0, 0, 15, 0, 0, 0, 169, 0, 0, 0, 213, 0, 0, 0, 1, 0, 0, 0, 170, 0, 0, 0, 72, 0, 0, 0, 79, 0, 0, 0, 40, 0, 0, 0, 102, 0, 0, 0, 50, 0, 0, 0, 26, 0, 0, 0, 186, 0, 0, 0, 124, 0, 0, 0, 234, 0, 0, 0, 17, 0, 0, 0, 128, 0, 0, 0, 23, 0, 0, 0, 24, 0, 0, 0, 155, 0, 0, 0, 86, 0, 0, 0, 136, 0, 0, 0, 37, 0, 0, 0, 6, 0, 0, 0, 105, 0, 0, 0, 18, 0, +0, 0, 44, 0, 0, 0, 234, 0, 0, 0, 86, 0, 0, 0, 105, 0, 0, 0, 65, 0, 0, 0, 36, 0, 0, 0, 25, 0, 0, 0, 222, 0, 0, 0, 33, 0, 0, 0, 240, 0, 0, 0, 218, 0, 0, 0, 138, 0, 0, 0, 251, 0, 0, 0, 177, 0, 0, 0, 184, 0, 0, 0, 205, 0, 0, 0, 200, 0, 0, 0, 106, 0, 0, 0, 130, 0, 0, 0, 25, 0, 0, 0, 115, 0, 0, 0, 219, 0, 0, 0, 199, 0, 0, 0, 207, 0, 0, 0, 136, 0, 0, 0, 235, 0, 0, 0, 150, 0, 0, 0, 238, 0, 0, 0, 111, 0, 0, 0, 251, 0, 0, 0, 6, 0, 0, 0, 210, 0, 0, 0, 205, 0, 0, 0, 125, 0, 0, 0, 123, 0, 0, 0, 18, 0, 0, 0, 40, +0, 0, 0, 142, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, 0, 0, 68, 0, 0, 0, 151, 0, 0, 0, 206, 0, 0, 0, 40, 0, 0, 0, 255, 0, 0, 0, 58, 0, 0, 0, 64, 0, 0, 0, 196, 0, 0, 0, 245, 0, 0, 0, 246, 0, 0, 0, 155, 0, 0, 0, 244, 0, 0, 0, 107, 0, 0, 0, 7, 0, +0, 0, 132, 0, 0, 0, 251, 0, 0, 0, 152, 0, 0, 0, 216, 0, 0, 0, 236, 0, 0, 0, 140, 0, 0, 0, 3, 0, 0, 0, 87, 0, 0, 0, 236, 0, 0, 0, 73, 0, 0, 0, 237, 0, 0, 0, 99, 0, 0, 0, 182, 0, 0, 0, 170, 0, 0, 0, 255, 0, 0, 0, 152, 0, 0, 0, 40, 0, 0, 0, 61, 0, 0, 0, 22, 0, 0, 0, 53, 0, 0, 0, 243, 0, 0, 0, 70, 0, 0, 0, 188, 0, 0, 0, 179, 0, 0, 0, 244, 0, 0, 0, 198, 0, 0, 0, 182, 0, 0, 0, 79, 0, 0, 0, 250, 0, 0, 0, 244, 0, 0, 0, 160, 0, 0, 0, 19, 0, 0, 0, 230, 0, 0, 0, 87, 0, 0, 0, 69, 0, 0, 0, 147, 0, 0, 0, 185, +0, 0, 0, 188, 0, 0, 0, 214, 0, 0, 0, 89, 0, 0, 0, 231, 0, 0, 0, 119, 0, 0, 0, 148, 0, 0, 0, 108, 0, 0, 0, 171, 0, 0, 0, 150, 0, 0, 0, 59, 0, 0, 0, 79, 0, 0, 0, 9, 0, 0, 0, 90, 0, 0, 0, 247, 0, 0, 0, 107, 0, 0, 0, 1, 0, 0, 0, 18, 0, 0, 0, 79, 0, 0, 0, 81, 0, 0, 0, 193, 0, 0, 0, 112, 0, 0, 0, 132, 0, 0, 0, 148, 0, 0, 0, 71, 0, 0, 0, 178, 0, 0, 0, 1, 0, 0, 0, 108, 0, 0, 0, 113, 0, 0, 0, 215, 0, 0, 0, 204, 0, 0, 0, 23, 0, 0, 0, 102, 0, 0, 0, 15, 0, 0, 0, 89, 0, 0, 0, 93, 0, 0, 0, 93, 0, 0, 0, 16, 0, +0, 0, 1, 0, 0, 0, 87, 0, 0, 0, 17, 0, 0, 0, 245, 0, 0, 0, 221, 0, 0, 0, 226, 0, 0, 0, 52, 0, 0, 0, 38, 0, 0, 0, 217, 0, 0, 0, 31, 0, 0, 0, 92, 0, 0, 0, 88, 0, 0, 0, 172, 0, 0, 0, 139, 0, 0, 0, 3, 0, 0, 0, 210, 0, 0, 0, 195, 0, 0, 0, 133, 0, 0, 0, 15, 0, 0, 0, 58, 0, 0, 0, 195, 0, 0, 0, 127, 0, 0, 0, 109, 0, 0, 0, 142, 0, 0, 0, 134, 0, 0, 0, 205, 0, 0, 0, 82, 0, 0, 0, 116, 0, 0, 0, 143, 0, 0, 0, 85, 0, 0, 0, 119, 0, 0, 0, 23, 0, 0, 0, 183, 0, 0, 0, 142, 0, 0, 0, 183, 0, 0, 0, 136, 0, 0, 0, 234, 0, +0, 0, 218, 0, 0, 0, 27, 0, 0, 0, 182, 0, 0, 0, 234, 0, 0, 0, 14, 0, 0, 0, 64, 0, 0, 0, 147, 0, 0, 0, 32, 0, 0, 0, 121, 0, 0, 0, 53, 0, 0, 0, 106, 0, 0, 0, 97, 0, 0, 0, 132, 0, 0, 0, 90, 0, 0, 0, 7, 0, 0, 0, 109, 0, 0, 0, 249, 0, 0, 0, 119, 0, 0, 0, 111, 0, 0, 0, 237, 0, 0, 0, 105, 0, 0, 0, 28, 0, 0, 0, 13, 0, 0, 0, 37, 0, 0, 0, 118, 0, 0, 0, 204, 0, 0, 0, 240, 0, 0, 0, 219, 0, 0, 0, 187, 0, 0, 0, 197, 0, 0, 0, 173, 0, 0, 0, 226, 0, 0, 0, 38, 0, 0, 0, 87, 0, 0, 0, 207, 0, 0, 0, 232, 0, 0, 0, 14, 0, +0, 0, 107, 0, 0, 0, 150, 0, 0, 0, 125, 0, 0, 0, 237, 0, 0, 0, 39, 0, 0, 0, 209, 0, 0, 0, 60, 0, 0, 0, 169, 0, 0, 0, 217, 0, 0, 0, 80, 0, 0, 0, 169, 0, 0, 0, 152, 0, 0, 0, 132, 0, 0, 0, 94, 0, 0, 0, 134, 0, 0, 0, 239, 0, 0, 0, 214, 0, 0, 0, 240, 0, 0, 0, 248, 0, 0, 0, 14, 0, 0, 0, 137, 0, 0, 0, 5, 0, 0, 0, 47, 0, 0, 0, 217, 0, 0, 0, 95, 0, 0, 0, 21, 0, 0, 0, 95, 0, 0, 0, 115, 0, 0, 0, 121, 0, 0, 0, 200, 0, 0, 0, 92, 0, 0, 0, 22, 0, 0, 0, 254, 0, 0, 0, 237, 0, 0, 0, 159, 0, 0, 0, 38, 0, 0, 0, 86, 0, +0, 0, 246, 0, 0, 0, 75, 0, 0, 0, 159, 0, 0, 0, 167, 0, 0, 0, 10, 0, 0, 0, 133, 0, 0, 0, 254, 0, 0, 0, 165, 0, 0, 0, 140, 0, 0, 0, 135, 0, 0, 0, 221, 0, 0, 0, 152, 0, 0, 0, 206, 0, 0, 0, 78, 0, 0, 0, 195, 0, 0, 0, 88, 0, 0, 0, 85, 0, 0, 0, 178, 0, 0, 0, 123, 0, 0, 0, 61, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, 181, 0, 0, 0, 76, 0, 0, 0, 101, 0, 0, 0, 56, 0, 0, 0, 160, 0, 0, 0, 21, 0, 0, 0, 250, 0, 0, 0, 167, 0, 0, 0, 180, 0, 0, 0, 143, 0, 0, 0, 235, 0, 0, 0, 196, 0, 0, 0, 134, 0, 0, 0, 155, 0, 0, 0, +48, 0, 0, 0, 165, 0, 0, 0, 94, 0, 0, 0, 77, 0, 0, 0, 234, 0, 0, 0, 138, 0, 0, 0, 154, 0, 0, 0, 159, 0, 0, 0, 26, 0, 0, 0, 216, 0, 0, 0, 91, 0, 0, 0, 83, 0, 0, 0, 20, 0, 0, 0, 25, 0, 0, 0, 37, 0, 0, 0, 99, 0, 0, 0, 180, 0, 0, 0, 111, 0, 0, 0, 31, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172, 0, 0, 0, 143, 0, 0, 0, 188, 0, 0, 0, 30, 0, 0, 0, 125, 0, 0, 0, 139, 0, 0, 0, 90, 0, 0, 0, 11, 0, 0, 0, 141, 0, 0, 0, 175, 0, 0, 0, 118, 0, 0, 0, 46, 0, 0, 0, 113, 0, 0, 0, 227, 0, 0, 0, 59, 0, 0, 0, 111, 0, 0, 0, 83, 0, 0, 0, 47, 0, 0, 0, 62, 0, 0, 0, 144, 0, 0, 0, 149, 0, 0, 0, 212, 0, 0, 0, 53, 0, 0, 0, 20, 0, 0, 0, 79, 0, 0, 0, 140, 0, 0, 0, 60, 0, 0, 0, 206, 0, 0, 0, 87, 0, 0, 0, 28, 0, 0, 0, 118, 0, 0, 0, 73, 0, 0, 0, 168, 0, 0, 0, 80, 0, 0, 0, 225, 0, +0, 0, 97, 0, 0, 0, 107, 0, 0, 0, 87, 0, 0, 0, 53, 0, 0, 0, 235, 0, 0, 0, 68, 0, 0, 0, 11, 0, 0, 0, 12, 0, 0, 0, 110, 0, 0, 0, 249, 0, 0, 0, 37, 0, 0, 0, 128, 0, 0, 0, 116, 0, 0, 0, 242, 0, 0, 0, 143, 0, 0, 0, 111, 0, 0, 0, 122, 0, 0, 0, 62, 0, 0, 0, 127, 0, 0, 0, 45, 0, 0, 0, 243, 0, 0, 0, 78, 0, 0, 0, 9, 0, 0, 0, 101, 0, 0, 0, 16, 0, 0, 0, 94, 0, 0, 0, 3, 0, 0, 0, 37, 0, 0, 0, 50, 0, 0, 0, 169, 0, 0, 0, 96, 0, 0, 0, 220, 0, 0, 0, 15, 0, 0, 0, 100, 0, 0, 0, 229, 0, 0, 0, 29, 0, 0, 0, 226, 0, 0, 0, +141, 0, 0, 0, 79, 0, 0, 0, 121, 0, 0, 0, 47, 0, 0, 0, 14, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 119, 0, 0, 0, 67, 0, 0, 0, 37, 0, 0, 0, 61, 0, 0, 0, 106, 0, 0, 0, 199, 0, 0, 0, 183, 0, 0, 0, 191, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 101, 0, 0, 0, 244, 0, 0, 0, 57, 0, 0, 0, 75, 0, 0, 0, 101, 0, 0, 0, 150, 0, 0, 0, 25, 0, 0, 0, 18, 0, 0, 0, 107, 0, 0, 0, 106, 0, 0, 0, 183, 0, 0, 0, 227, 0, 0, 0, 220, 0, 0, 0, 69, 0, 0, 0, 155, 0, 0, 0, 219, 0, 0, 0, 180, 0, 0, 0, 168, 0, 0, 0, 174, +0, 0, 0, 220, 0, 0, 0, 168, 0, 0, 0, 20, 0, 0, 0, 68, 0, 0, 0, 101, 0, 0, 0, 98, 0, 0, 0, 206, 0, 0, 0, 52, 0, 0, 0, 154, 0, 0, 0, 132, 0, 0, 0, 24, 0, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0, 241, 0, 0, 0, 226, 0, 0, 0, 123, 0, 0, 0, 206, 0, 0, 0, 80, 0, 0, 0, 65, 0, 0, 0, 33, 0, 0, 0, 48, 0, 0, 0, 83, 0, 0, 0, 27, 0, 0, 0, 71, 0, 0, 0, 1, 0, 0, 0, 183, 0, 0, 0, 24, 0, 0, 0, 216, 0, 0, 0, 130, 0, 0, 0, 87, 0, 0, 0, 189, 0, 0, 0, 163, 0, 0, 0, 96, 0, 0, 0, 240, 0, 0, 0, 50, 0, 0, 0, 246, 0, 0, 0, 91, 0, 0, +0, 240, 0, 0, 0, 48, 0, 0, 0, 136, 0, 0, 0, 145, 0, 0, 0, 89, 0, 0, 0, 253, 0, 0, 0, 144, 0, 0, 0, 162, 0, 0, 0, 185, 0, 0, 0, 85, 0, 0, 0, 147, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 151, 0, 0, 0, 103, 0, 0, 0, 158, 0, 0, 0, 235, 0, 0, 0, 106, 0, 0, 0, 249, 0, 0, 0, 110, 0, 0, 0, 214, 0, 0, 0, 115, 0, 0, 0, 232, 0, 0, 0, 107, 0, 0, 0, 41, 0, 0, 0, 236, 0, 0, 0, 99, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 168, 0, 0, 0, 153, 0, 0, 0, 28, 0, 0, 0, 29, 0, 0, 0, 48, 0, 0, 0, 200, 0, 0, 0, 144, 0, 0, 0, 82, 0, +0, 0, 144, 0, 0, 0, 182, 0, 0, 0, 106, 0, 0, 0, 128, 0, 0, 0, 78, 0, 0, 0, 255, 0, 0, 0, 75, 0, 0, 0, 81, 0, 0, 0, 15, 0, 0, 0, 125, 0, 0, 0, 99, 0, 0, 0, 140, 0, 0, 0, 110, 0, 0, 0, 92, 0, 0, 0, 222, 0, 0, 0, 48, 0, 0, 0, 223, 0, 0, 0, 101, 0, 0, 0, 250, 0, 0, 0, 46, 0, 0, 0, 176, 0, 0, 0, 163, 0, 0, 0, 37, 0, 0, 0, 5, 0, 0, 0, 84, 0, 0, 0, 189, 0, 0, 0, 37, 0, 0, 0, 186, 0, 0, 0, 6, 0, 0, 0, 174, 0, 0, 0, 223, 0, 0, 0, 139, 0, 0, 0, 217, 0, 0, 0, 27, 0, 0, 0, 234, 0, 0, 0, 56, 0, 0, 0, 179, 0, +0, 0, 5, 0, 0, 0, 22, 0, 0, 0, 9, 0, 0, 0, 199, 0, 0, 0, 140, 0, 0, 0, 191, 0, 0, 0, 100, 0, 0, 0, 40, 0, 0, 0, 173, 0, 0, 0, 248, 0, 0, 0, 165, 0, 0, 0, 90, 0, 0, 0, 111, 0, 0, 0, 201, 0, 0, 0, 186, 0, 0, 0, 213, 0, 0, 0, 127, 0, 0, 0, 213, 0, 0, 0, 214, 0, 0, 0, 189, 0, 0, 0, 102, 0, 0, 0, 47, 0, 0, 0, 61, 0, 0, 0, 170, 0, 0, 0, 84, 0, 0, 0, 246, 0, 0, 0, 186, 0, 0, 0, 50, 0, 0, 0, 34, 0, 0, 0, 154, 0, 0, 0, 30, 0, 0, 0, 82, 0, 0, 0, 5, 0, 0, 0, 244, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 0, 0, 0, 31, 0, 0, 0, 187, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 228, 0, 0, 0, 135, 0, 0, 0, 252, 0, 0, 0, 177, 0, 0, 0, 44, 0, 0, 0, 183, 0, 0, 0, 136, 0, 0, 0, 244, 0, 0, 0, 198, 0, 0, 0, 185, 0, 0, 0, 245, 0, 0, 0, 36, 0, 0, 0, 70, 0, 0, 0, 242, 0, 0, +0, 165, 0, 0, 0, 159, 0, 0, 0, 143, 0, 0, 0, 138, 0, 0, 0, 147, 0, 0, 0, 112, 0, 0, 0, 105, 0, 0, 0, 212, 0, 0, 0, 86, 0, 0, 0, 236, 0, 0, 0, 253, 0, 0, 0, 6, 0, 0, 0, 70, 0, 0, 0, 78, 0, 0, 0, 102, 0, 0, 0, 207, 0, 0, 0, 78, 0, 0, 0, 52, 0, 0, 0, 206, 0, 0, 0, 12, 0, 0, 0, 217, 0, 0, 0, 166, 0, 0, 0, 80, 0, 0, 0, 214, 0, 0, 0, 94, 0, 0, 0, 149, 0, 0, 0, 175, 0, 0, 0, 233, 0, 0, 0, 88, 0, 0, 0, 250, 0, 0, 0, 238, 0, 0, 0, 155, 0, 0, 0, 184, 0, 0, 0, 165, 0, 0, 0, 15, 0, 0, 0, 53, 0, 0, 0, 224, 0, +0, 0, 67, 0, 0, 0, 130, 0, 0, 0, 109, 0, 0, 0, 101, 0, 0, 0, 230, 0, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 123, 0, 0, 0, 117, 0, 0, 0, 58, 0, 0, 0, 252, 0, 0, 0, 100, 0, 0, 0, 211, 0, 0, 0, 41, 0, 0, 0, 126, 0, 0, 0, 221, 0, 0, 0, 73, 0, 0, 0, 154, 0, 0, 0, 89, 0, 0, 0, 83, 0, 0, 0, 191, 0, 0, 0, 180, 0, 0, 0, 167, 0, 0, 0, 82, 0, 0, 0, 179, 0, 0, 0, 5, 0, 0, 0, 171, 0, 0, 0, 195, 0, 0, 0, 175, 0, 0, 0, 22, 0, 0, 0, 26, 0, 0, 0, 133, 0, 0, 0, 66, 0, 0, 0, 50, 0, 0, 0, 162, 0, 0, 0, 134, 0, +0, 0, 250, 0, 0, 0, 57, 0, 0, 0, 67, 0, 0, 0, 14, 0, 0, 0, 75, 0, 0, 0, 163, 0, 0, 0, 99, 0, 0, 0, 138, 0, 0, 0, 254, 0, 0, 0, 165, 0, 0, 0, 88, 0, 0, 0, 241, 0, 0, 0, 19, 0, 0, 0, 189, 0, 0, 0, 157, 0, 0, 0, 170, 0, 0, 0, 127, 0, 0, 0, 118, 0, 0, 0, 64, 0, 0, 0, 112, 0, 0, 0, 129, 0, 0, 0, 16, 0, 0, 0, 117, 0, 0, 0, 153, 0, 0, 0, 187, 0, 0, 0, 190, 0, 0, 0, 11, 0, 0, 0, 22, 0, 0, 0, 233, 0, 0, 0, 186, 0, 0, 0, 98, 0, 0, 0, 52, 0, 0, 0, 204, 0, 0, 0, 7, 0, 0, 0, 109, 0, 0, 0, 195, 0, 0, 0, 241, 0, +0, 0, 198, 0, 0, 0, 147, 0, 0, 0, 101, 0, 0, 0, 238, 0, 0, 0, 11, 0, 0, 0, 188, 0, 0, 0, 234, 0, 0, 0, 20, 0, 0, 0, 240, 0, 0, 0, 193, 0, 0, 0, 248, 0, 0, 0, 132, 0, 0, 0, 137, 0, 0, 0, 194, 0, 0, 0, 201, 0, 0, 0, 215, 0, 0, 0, 234, 0, 0, 0, 52, 0, 0, 0, 202, 0, 0, 0, 167, 0, 0, 0, 196, 0, 0, 0, 153, 0, 0, 0, 213, 0, 0, 0, 80, 0, 0, 0, 105, 0, 0, 0, 203, 0, 0, 0, 214, 0, 0, 0, 33, 0, 0, 0, 99, 0, 0, 0, 124, 0, 0, 0, 153, 0, 0, 0, 235, 0, 0, 0, 124, 0, 0, 0, 49, 0, 0, 0, 115, 0, 0, 0, 100, 0, 0, 0, +103, 0, 0, 0, 127, 0, 0, 0, 12, 0, 0, 0, 102, 0, 0, 0, 170, 0, 0, 0, 140, 0, 0, 0, 105, 0, 0, 0, 145, 0, 0, 0, 226, 0, 0, 0, 38, 0, 0, 0, 211, 0, 0, 0, 35, 0, 0, 0, 226, 0, 0, 0, 118, 0, 0, 0, 93, 0, 0, 0, 50, 0, 0, 0, 82, 0, 0, 0, 223, 0, 0, 0, 93, 0, 0, 0, 197, 0, 0, 0, 143, 0, 0, 0, 183, 0, 0, 0, 124, 0, 0, 0, 132, 0, 0, 0, 179, 0, 0, 0, 112, 0, 0, 0, 235, 0, 0, 0, 1, 0, 0, 0, 199, 0, 0, 0, 54, 0, 0, 0, 151, 0, 0, 0, 78, 0, 0, 0, 182, 0, 0, 0, 171, 0, 0, 0, 95, 0, 0, 0, 13, 0, 0, 0, 44, 0, 0, +0, 186, 0, 0, 0, 103, 0, 0, 0, 100, 0, 0, 0, 85, 0, 0, 0, 222, 0, 0, 0, 188, 0, 0, 0, 255, 0, 0, 0, 166, 0, 0, 0, 236, 0, 0, 0, 4, 0, 0, 0, 211, 0, 0, 0, 141, 0, 0, 0, 57, 0, 0, 0, 86, 0, 0, 0, 94, 0, 0, 0, 238, 0, 0, 0, 248, 0, 0, 0, 228, 0, 0, 0, 46, 0, 0, 0, 51, 0, 0, 0, 98, 0, 0, 0, 101, 0, 0, 0, 239, 0, 0, 0, 184, 0, 0, 0, 159, 0, 0, 0, 200, 0, 0, 0, 75, 0, 0, 0, 167, 0, 0, 0, 253, 0, 0, 0, 33, 0, 0, 0, 73, 0, 0, 0, 155, 0, 0, 0, 146, 0, 0, 0, 53, 0, 0, 0, 130, 0, 0, 0, 214, 0, 0, 0, 10, 0, +0, 0, 155, 0, 0, 0, 242, 0, 0, 0, 121, 0, 0, 0, 241, 0, 0, 0, 71, 0, 0, 0, 47, 0, 0, 0, 106, 0, 0, 0, 126, 0, 0, 0, 159, 0, 0, 0, 207, 0, 0, 0, 24, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 251, 0, 0, 0, 27, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, +139, 0, 0, 0, 200, 0, 0, 0, 64, 0, 0, 0, 81, 0, 0, 0, 209, 0, 0, 0, 172, 0, 0, 0, 26, 0, 0, 0, 11, 0, 0, 0, 228, 0, 0, 0, 169, 0, 0, 0, 162, 0, 0, 0, 66, 0, 0, 0, 33, 0, 0, 0, 25, 0, 0, 0, 47, 0, 0, 0, 123, 0, 0, 0, 151, 0, 0, 0, 191, 0, 0, 0, 247, 0, 0, 0, 87, 0, 0, 0, 109, 0, 0, 0, 63, 0, 0, 0, 61, 0, 0, 0, 79, 0, 0, 0, 15, 0, 0, 0, 226, 0, 0, 0, 178, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, 158, 0, 0, 0, 123, 0, 0, 0, 140, 0, 0, 0, 133, 0, 0, 0, 43, 0, 0, 0, 196, 0, 0, 0, 252, 0, 0, 0, 241, 0, 0, 0, +171, 0, 0, 0, 232, 0, 0, 0, 121, 0, 0, 0, 34, 0, 0, 0, 196, 0, 0, 0, 132, 0, 0, 0, 23, 0, 0, 0, 58, 0, 0, 0, 250, 0, 0, 0, 134, 0, 0, 0, 166, 0, 0, 0, 125, 0, 0, 0, 249, 0, 0, 0, 243, 0, 0, 0, 111, 0, 0, 0, 3, 0, 0, 0, 87, 0, 0, 0, 32, 0, 0, 0, 77, 0, 0, 0, 121, 0, 0, 0, 249, 0, 0, 0, 110, 0, 0, 0, 113, 0, 0, 0, 84, 0, 0, 0, 56, 0, 0, 0, 9, 0, 0, 0, 64, 0, 0, 0, 41, 0, 0, 0, 116, 0, 0, 0, 168, 0, 0, 0, 47, 0, 0, 0, 94, 0, 0, 0, 249, 0, 0, 0, 121, 0, 0, 0, 164, 0, 0, 0, 243, 0, 0, 0, 62, 0, 0, 0, +185, 0, 0, 0, 253, 0, 0, 0, 51, 0, 0, 0, 49, 0, 0, 0, 172, 0, 0, 0, 154, 0, 0, 0, 105, 0, 0, 0, 136, 0, 0, 0, 30, 0, 0, 0]).concat([119, 0, 0, 0, 33, 0, 0, 0, 45, 0, 0, 0, 243, 0, 0, 0, 145, 0, 0, 0, 82, 0, 0, 0, 38, 0, 0, 0, 21, 0, 0, 0, 178, 0, 0, 0, 166, 0, 0, 0, 207, 0, 0, 0, 126, 0, 0, 0, 198, 0, 0, 0, 32, 0, 0, 0, 71, 0, 0, 0, 108, 0, 0, 0, 164, 0, 0, 0, 125, 0, 0, 0, 203, 0, 0, 0, 99, 0, 0, 0, 234, 0, 0, 0, 91, 0, 0, 0, 3, 0, 0, 0, 223, 0, 0, 0, 62, 0, 0, 0, 136, 0, 0, 0, 129, 0, 0, 0, 109, +0, 0, 0, 206, 0, 0, 0, 7, 0, 0, 0, 66, 0, 0, 0, 24, 0, 0, 0, 96, 0, 0, 0, 126, 0, 0, 0, 123, 0, 0, 0, 85, 0, 0, 0, 254, 0, 0, 0, 106, 0, 0, 0, 243, 0, 0, 0, 218, 0, 0, 0, 92, 0, 0, 0, 139, 0, 0, 0, 149, 0, 0, 0, 16, 0, 0, 0, 98, 0, 0, 0, 228, 0, 0, 0, 13, 0, 0, 0, 3, 0, 0, 0, 180, 0, 0, 0, 215, 0, 0, 0, 205, 0, 0, 0, 250, 0, 0, 0, 189, 0, 0, 0, 70, 0, 0, 0, 223, 0, 0, 0, 147, 0, 0, 0, 113, 0, 0, 0, 16, 0, 0, 0, 44, 0, 0, 0, 168, 0, 0, 0, 59, 0, 0, 0, 182, 0, 0, 0, 9, 0, 0, 0, 5, 0, 0, 0, 112, 0, +0, 0, 132, 0, 0, 0, 67, 0, 0, 0, 41, 0, 0, 0, 168, 0, 0, 0, 89, 0, 0, 0, 245, 0, 0, 0, 142, 0, 0, 0, 16, 0, 0, 0, 228, 0, 0, 0, 215, 0, 0, 0, 32, 0, 0, 0, 87, 0, 0, 0, 130, 0, 0, 0, 28, 0, 0, 0, 171, 0, 0, 0, 191, 0, 0, 0, 98, 0, 0, 0, 112, 0, 0, 0, 232, 0, 0, 0, 196, 0, 0, 0, 207, 0, 0, 0, 240, 0, 0, 0, 40, 0, 0, 0, 110, 0, 0, 0, 22, 0, 0, 0, 60, 0, 0, 0, 8, 0, 0, 0, 120, 0, 0, 0, 137, 0, 0, 0, 133, 0, 0, 0, 70, 0, 0, 0, 15, 0, 0, 0, 246, 0, 0, 0, 127, 0, 0, 0, 207, 0, 0, 0, 203, 0, 0, 0, 126, 0, +0, 0, 184, 0, 0, 0, 37, 0, 0, 0, 233, 0, 0, 0, 90, 0, 0, 0, 250, 0, 0, 0, 3, 0, 0, 0, 251, 0, 0, 0, 149, 0, 0, 0, 146, 0, 0, 0, 99, 0, 0, 0, 80, 0, 0, 0, 252, 0, 0, 0, 98, 0, 0, 0, 240, 0, 0, 0, 164, 0, 0, 0, 94, 0, 0, 0, 140, 0, 0, 0, 24, 0, 0, 0, 194, 0, 0, 0, 23, 0, 0, 0, 36, 0, 0, 0, 183, 0, 0, 0, 120, 0, 0, 0, 194, 0, 0, 0, 169, 0, 0, 0, 231, 0, 0, 0, 106, 0, 0, 0, 50, 0, 0, 0, 214, 0, 0, 0, 41, 0, 0, 0, 133, 0, 0, 0, 175, 0, 0, 0, 203, 0, 0, 0, 141, 0, 0, 0, 145, 0, 0, 0, 19, 0, 0, 0, 218, +0, 0, 0, 107, 0, 0, 0, 54, 0, 0, 0, 10, 0, 0, 0, 194, 0, 0, 0, 182, 0, 0, 0, 75, 0, 0, 0, 165, 0, 0, 0, 93, 0, 0, 0, 7, 0, 0, 0, 23, 0, 0, 0, 65, 0, 0, 0, 49, 0, 0, 0, 95, 0, 0, 0, 98, 0, 0, 0, 70, 0, 0, 0, 248, 0, 0, 0, 146, 0, 0, 0, 249, 0, 0, 0, 102, 0, 0, 0, 72, 0, 0, 0, 115, 0, 0, 0, 166, 0, 0, 0, 151, 0, 0, 0, 13, 0, 0, 0, 125, 0, 0, 0, 136, 0, 0, 0, 238, 0, 0, 0, 98, 0, 0, 0, 177, 0, 0, 0, 3, 0, 0, 0, 168, 0, 0, 0, 63, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 177, 0, 0, 0, 112, 0, 0, 0, 138, 0, 0, 0, 169, 0, 0, 0, 232, 0, 0, 0, 99, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 37, 0, 0, 0, 22, 0, 0, 0, 202, 0, 0, 0, 75, 0, 0, 0, 15, 0, 0, 0, 164, 0, 0, 0, 102, 0, 0, 0, 173, 0, 0, 0, 25, 0, 0, 0, 159, 0, 0, 0, 136, 0, 0, 0, +103, 0, 0, 0, 12, 0, 0, 0, 139, 0, 0, 0, 194, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 43, 0, 0, 0, 109, 0, 0, 0, 149, 0, 0, 0, 175, 0, 0, 0, 25, 0, 0, 0, 139, 0, 0, 0, 157, 0, 0, 0, 182, 0, 0, 0, 204, 0, 0, 0, 96, 0, 0, 0, 180, 0, 0, 0, 114, 0, 0, 0, 79, 0, 0, 0, 23, 0, 0, 0, 105, 0, 0, 0, 90, 0, 0, 0, 74, 0, 0, 0, 104, 0, 0, 0, 52, 0, 0, 0, 171, 0, 0, 0, 161, 0, 0, 0, 69, 0, 0, 0, 50, 0, 0, 0, 60, 0, 0, 0, 131, 0, 0, 0, 135, 0, 0, 0, 114, 0, 0, 0, 48, 0, 0, 0, 84, 0, 0, 0, 119, 0, 0, 0, 104, 0, 0, 0, +174, 0, 0, 0, 251, 0, 0, 0, 181, 0, 0, 0, 139, 0, 0, 0, 34, 0, 0, 0, 94, 0, 0, 0, 241, 0, 0, 0, 185, 0, 0, 0, 135, 0, 0, 0, 53, 0, 0, 0, 197, 0, 0, 0, 187, 0, 0, 0, 185, 0, 0, 0, 207, 0, 0, 0, 245, 0, 0, 0, 214, 0, 0, 0, 205, 0, 0, 0, 213, 0, 0, 0, 12, 0, 0, 0, 124, 0, 0, 0, 14, 0, 0, 0, 230, 0, 0, 0, 144, 0, 0, 0, 52, 0, 0, 0, 251, 0, 0, 0, 81, 0, 0, 0, 66, 0, 0, 0, 30, 0, 0, 0, 109, 0, 0, 0, 172, 0, 0, 0, 154, 0, 0, 0, 70, 0, 0, 0, 196, 0, 0, 0, 151, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 191, 0, 0, +0, 69, 0, 0, 0, 102, 0, 0, 0, 158, 0, 0, 0, 198, 0, 0, 0, 36, 0, 0, 0, 192, 0, 0, 0, 237, 0, 0, 0, 165, 0, 0, 0, 93, 0, 0, 0, 136, 0, 0, 0, 212, 0, 0, 0, 240, 0, 0, 0, 115, 0, 0, 0, 151, 0, 0, 0, 123, 0, 0, 0, 234, 0, 0, 0, 127, 0, 0, 0, 66, 0, 0, 0, 255, 0, 0, 0, 33, 0, 0, 0, 160, 0, 0, 0, 155, 0, 0, 0, 47, 0, 0, 0, 154, 0, 0, 0, 253, 0, 0, 0, 83, 0, 0, 0, 87, 0, 0, 0, 7, 0, 0, 0, 132, 0, 0, 0, 72, 0, 0, 0, 136, 0, 0, 0, 157, 0, 0, 0, 82, 0, 0, 0, 198, 0, 0, 0, 150, 0, 0, 0, 72, 0, 0, 0, 52, 0, +0, 0, 42, 0, 0, 0, 6, 0, 0, 0, 175, 0, 0, 0, 148, 0, 0, 0, 61, 0, 0, 0, 244, 0, 0, 0, 26, 0, 0, 0, 207, 0, 0, 0, 242, 0, 0, 0, 192, 0, 0, 0, 33, 0, 0, 0, 194, 0, 0, 0, 66, 0, 0, 0, 94, 0, 0, 0, 200, 0, 0, 0, 47, 0, 0, 0, 53, 0, 0, 0, 162, 0, 0, 0, 62, 0, 0, 0, 41, 0, 0, 0, 250, 0, 0, 0, 12, 0, 0, 0, 132, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 114, 0, 0, 0, 124, 0, 0, 0, 6, 0, 0, 0, 50, 0, 0, 0, 101, 0, 0, 0, 3, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 166, 0, 0, 0, 110, 0, 0, 0, 179, 0, 0, 0, 91, 0, 0, +0, 142, 0, 0, 0, 202, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 34, 0, 0, 0, 86, 0, 0, 0, 139, 0, 0, 0, 93, 0, 0, 0, 20, 0, 0, 0, 75, 0, 0, 0, 77, 0, 0, 0, 249, 0, 0, 0, 190, 0, 0, 0, 181, 0, 0, 0, 245, 0, 0, 0, 230, 0, 0, 0, 92, 0, 0, 0, 123, 0, 0, 0, 139, 0, 0, 0, 244, 0, 0, 0, 19, 0, 0, 0, 17, 0, 0, 0, 52, 0, 0, 0, 7, 0, 0, 0, 198, 0, 0, 0, 34, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 156, 0, 0, 0, 96, 0, 0, 0, 162, 0, 0, 0, 25, 0, 0, 0, 217, 0, 0, 0, 39, 0, 0, 0, 174, 0, 0, 0, 55, 0, 0, 0, 78, 0, 0, 0, +166, 0, 0, 0, 201, 0, 0, 0, 128, 0, 0, 0, 166, 0, 0, 0, 145, 0, 0, 0, 143, 0, 0, 0, 18, 0, 0, 0, 73, 0, 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 71, 0, 0, 0, 209, 0, 0, 0, 215, 0, 0, 0, 40, 0, 0, 0, 34, 0, 0, 0, 99, 0, 0, 0, 57, 0, 0, 0, 232, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 242, 0, 0, 0, 158, 0, 0, 0, 30, 0, 0, 0, 153, 0, 0, 0, 57, 0, 0, 0, 149, 0, 0, 0, 4, 0, 0, 0, 189, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, 0, 123, 0, 0, 0, 178, 0, 0, 0, 38, 0, 0, 0, 172, 0, 0, 0, 230, 0, 0, 0, 170, +0, 0, 0, 226, 0, 0, 0, 70, 0, 0, 0, 213, 0, 0, 0, 228, 0, 0, 0, 232, 0, 0, 0, 134, 0, 0, 0, 189, 0, 0, 0, 171, 0, 0, 0, 124, 0, 0, 0, 85, 0, 0, 0, 89, 0, 0, 0, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 100, 0, 0, 0, 110, 0, 0, 0, 155, 0, 0, 0, 53, 0, +0, 0, 113, 0, 0, 0, 120, 0, 0, 0, 206, 0, 0, 0, 51, 0, 0, 0, 3, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 54, 0, 0, 0, 241, 0, 0, 0, 115, 0, 0, 0, 155, 0, 0, 0, 185, 0, 0, 0, 21, 0, 0, 0, 139, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 207, 0, 0, 0, 77, 0, 0, 0, 237, 0, 0, 0, 79, 0, 0, 0, 77, 0, 0, 0, 87, 0, 0, 0, 20, 0, 0, 0, 19, 0, 0, 0, 130, 0, 0, 0, 164, 0, 0, 0, 77, 0, 0, 0, 101, 0, 0, 0, 110, 0, 0, 0, 10, 0, 0, 0, 164, 0, 0, 0, 89, 0, 0, 0, 7, 0, 0, 0, 23, 0, 0, 0, 242, 0, 0, 0, 107, 0, 0, 0, 74, 0, 0, 0, +31, 0, 0, 0, 110, 0, 0, 0, 246, 0, 0, 0, 181, 0, 0, 0, 188, 0, 0, 0, 98, 0, 0, 0, 228, 0, 0, 0, 182, 0, 0, 0, 218, 0, 0, 0, 162, 0, 0, 0, 147, 0, 0, 0, 188, 0, 0, 0, 41, 0, 0, 0, 5, 0, 0, 0, 210, 0, 0, 0, 210, 0, 0, 0, 115, 0, 0, 0, 70, 0, 0, 0, 3, 0, 0, 0, 22, 0, 0, 0, 64, 0, 0, 0, 49, 0, 0, 0, 76, 0, 0, 0, 115, 0, 0, 0, 109, 0, 0, 0, 21, 0, 0, 0, 189, 0, 0, 0, 161, 0, 0, 0, 77, 0, 0, 0, 92, 0, 0, 0, 19, 0, 0, 0, 11, 0, 0, 0, 36, 0, 0, 0, 6, 0, 0, 0, 152, 0, 0, 0, 120, 0, 0, 0, 28, 0, 0, 0, 91, +0, 0, 0, 235, 0, 0, 0, 31, 0, 0, 0, 24, 0, 0, 0, 84, 0, 0, 0, 67, 0, 0, 0, 217, 0, 0, 0, 85, 0, 0, 0, 102, 0, 0, 0, 218, 0, 0, 0, 41, 0, 0, 0, 33, 0, 0, 0, 232, 0, 0, 0, 184, 0, 0, 0, 60, 0, 0, 0, 66, 0, 0, 0, 34, 0, 0, 0, 180, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, 111, 0, 0, 0, 21, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 0, 11, 0, 0, 0, 34, 0, 0, 0, 237, 0, 0, 0, 209, 0, 0, 0, 241, 0, 0, 0, 167, 0, 0, 0, 199, 0, 0, 0, 115, 0, 0, 0, 69, 0, 0, 0, 243, 0, 0, 0, 158, 0, 0, 0, 206, 0, 0, 0, 118, 0, 0, 0, 183, 0, +0, 0, 246, 0, 0, 0, 57, 0, 0, 0, 182, 0, 0, 0, 142, 0, 0, 0, 121, 0, 0, 0, 190, 0, 0, 0, 233, 0, 0, 0, 155, 0, 0, 0, 207, 0, 0, 0, 125, 0, 0, 0, 98, 0, 0, 0, 146, 0, 0, 0, 91, 0, 0, 0, 252, 0, 0, 0, 114, 0, 0, 0, 253, 0, 0, 0, 186, 0, 0, 0, 241, 0, 0, 0, 253, 0, 0, 0, 166, 0, 0, 0, 124, 0, 0, 0, 149, 0, 0, 0, 227, 0, 0, 0, 97, 0, 0, 0, 63, 0, 0, 0, 233, 0, 0, 0, 3, 0, 0, 0, 212, 0, 0, 0, 43, 0, 0, 0, 212, 0, 0, 0, 32, 0, 0, 0, 217, 0, 0, 0, 219, 0, 0, 0, 77, 0, 0, 0, 50, 0, 0, 0, 62, 0, 0, 0, 245, +0, 0, 0, 17, 0, 0, 0, 100, 0, 0, 0, 227, 0, 0, 0, 180, 0, 0, 0, 190, 0, 0, 0, 50, 0, 0, 0, 134, 0, 0, 0, 23, 0, 0, 0, 144, 0, 0, 0, 231, 0, 0, 0, 201, 0, 0, 0, 31, 0, 0, 0, 16, 0, 0, 0, 165, 0, 0, 0, 106, 0, 0, 0, 45, 0, 0, 0, 57, 0, 0, 0, 208, 0, 0, 0, 59, 0, 0, 0, 196, 0, 0, 0, 166, 0, 0, 0, 233, 0, 0, 0, 89, 0, 0, 0, 19, 0, 0, 0, 218, 0, 0, 0, 26, 0, 0, 0, 230, 0, 0, 0, 160, 0, 0, 0, 185, 0, 0, 0, 60, 0, 0, 0, 80, 0, 0, 0, 184, 0, 0, 0, 64, 0, 0, 0, 124, 0, 0, 0, 21, 0, 0, 0, 54, 0, 0, 0, 90, +0, 0, 0, 66, 0, 0, 0, 180, 0, 0, 0, 11, 0, 0, 0, 50, 0, 0, 0, 171, 0, 0, 0, 220, 0, 0, 0, 4, 0, 0, 0, 81, 0, 0, 0, 85, 0, 0, 0, 33, 0, 0, 0, 30, 0, 0, 0, 11, 0, 0, 0, 117, 0, 0, 0, 153, 0, 0, 0, 137, 0, 0, 0, 115, 0, 0, 0, 53, 0, 0, 0, 58, 0, 0, 0, 145, 0, 0, 0, 43, 0, 0, 0, 254, 0, 0, 0, 231, 0, 0, 0, 73, 0, 0, 0, 234, 0, 0, 0, 118, 0, 0, 0, 193, 0, 0, 0, 249, 0, 0, 0, 70, 0, 0, 0, 185, 0, 0, 0, 83, 0, 0, 0, 2, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 252, 0, 0, 0, 90, 0, 0, 0, 30, 0, 0, 0, 29, 0, 0, 0, +116, 0, 0, 0, 88, 0, 0, 0, 149, 0, 0, 0, 166, 0, 0, 0, 143, 0, 0, 0, 123, 0, 0, 0, 151, 0, 0, 0, 62, 0, 0, 0, 23, 0, 0, 0, 59, 0, 0, 0, 121, 0, 0, 0, 45, 0, 0, 0, 166, 0, 0, 0, 87, 0, 0, 0, 239, 0, 0, 0, 69, 0, 0, 0, 2, 0, 0, 0, 11, 0, 0, 0, 77, 0, 0, 0, 110, 0, 0, 0, 158, 0, 0, 0, 147, 0, 0, 0, 141, 0, 0, 0, 47, 0, 0, 0, 217, 0, 0, 0, 157, 0, 0, 0, 219, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 215, 0, 0, 0, 86, 0, 0, 0, 151, 0, 0, 0, 88, 0, 0, 0, 145, 0, 0, 0, 222, 0, 0, 0, 9, 0, 0, 0, 79, 0, 0, 0, 159, 0, 0, 0, 190, 0, 0, 0, 99, 0, 0, 0, 176, 0, 0, 0, 131, 0, 0, 0, 134, 0, 0, 0, 67, 0, 0, 0, 93, 0, 0, 0, 188, 0, 0, 0, 224, 0, 0, 0, 243, 0, 0, 0, 192, 0, 0, 0, 117, 0, 0, 0, 191, 0, 0, 0, 139, 0, 0, 0, 142, 0, 0, 0, 170, 0, 0, 0, 247, +0, 0, 0, 139, 0, 0, 0, 100, 0, 0, 0, 110, 0, 0, 0, 176, 0, 0, 0, 99, 0, 0, 0, 22, 0, 0, 0, 174, 0, 0, 0, 139, 0, 0, 0, 224, 0, 0, 0, 155, 0, 0, 0, 36, 0, 0, 0, 104, 0, 0, 0, 92, 0, 0, 0, 68, 0, 0, 0, 194, 0, 0, 0, 208, 0, 0, 0, 8, 0, 0, 0, 183, 0, 0, 0, 123, 0, 0, 0, 98, 0, 0, 0, 253, 0, 0, 0, 127, 0, 0, 0, 216, 0, 0, 0, 212, 0, 0, 0, 183, 0, 0, 0, 80, 0, 0, 0, 253, 0, 0, 0, 44, 0, 0, 0, 27, 0, 0, 0, 191, 0, 0, 0, 65, 0, 0, 0, 149, 0, 0, 0, 217, 0, 0, 0, 142, 0, 0, 0, 216, 0, 0, 0, 23, 0, 0, 0, 27, +0, 0, 0, 134, 0, 0, 0, 85, 0, 0, 0, 55, 0, 0, 0, 142, 0, 0, 0, 195, 0, 0, 0, 56, 0, 0, 0, 72, 0, 0, 0, 20, 0, 0, 0, 181, 0, 0, 0, 151, 0, 0, 0, 210, 0, 0, 0, 167, 0, 0, 0, 84, 0, 0, 0, 69, 0, 0, 0, 241, 0, 0, 0, 53, 0, 0, 0, 68, 0, 0, 0, 56, 0, 0, 0, 158, 0, 0, 0, 241, 0, 0, 0, 27, 0, 0, 0, 182, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 150, 0, 0, 0, 238, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 234, 0, 0, 0, 44, 0, 0, 0, 11, 0, 0, 0, 234, 0, 0, 0, 218, 0, 0, 0, 153, 0, 0, 0, 158, 0, 0, 0, 25, 0, 0, +0, 131, 0, 0, 0, 102, 0, 0, 0, 109, 0, 0, 0, 233, 0, 0, 0, 118, 0, 0, 0, 135, 0, 0, 0, 80, 0, 0, 0, 209, 0, 0, 0, 253, 0, 0, 0, 60, 0, 0, 0, 96, 0, 0, 0, 135, 0, 0, 0, 198, 0, 0, 0, 65, 0, 0, 0, 217, 0, 0, 0, 142, 0, 0, 0, 219, 0, 0, 0, 94, 0, 0, 0, 222, 0, 0, 0, 170, 0, 0, 0, 154, 0, 0, 0, 211, 0, 0, 0, 40, 0, 0, 0, 218, 0, 0, 0, 149, 0, 0, 0, 234, 0, 0, 0, 71, 0, 0, 0, 208, 0, 0, 0, 128, 0, 0, 0, 186, 0, 0, 0, 25, 0, 0, 0, 174, 0, 0, 0, 29, 0, 0, 0, 169, 0, 0, 0, 121, 0, 0, 0, 246, 0, 0, 0, 63, +0, 0, 0, 172, 0, 0, 0, 93, 0, 0, 0, 111, 0, 0, 0, 150, 0, 0, 0, 31, 0, 0, 0, 42, 0, 0, 0, 206, 0, 0, 0, 41, 0, 0, 0, 178, 0, 0, 0, 255, 0, 0, 0, 55, 0, 0, 0, 241, 0, 0, 0, 148, 0, 0, 0, 143, 0, 0, 0, 12, 0, 0, 0, 181, 0, 0, 0, 40, 0, 0, 0, 186, 0, 0, 0, 154, 0, 0, 0, 33, 0, 0, 0, 246, 0, 0, 0, 102, 0, 0, 0, 2, 0, 0, 0, 251, 0, 0, 0, 84, 0, 0, 0, 184, 0, 0, 0, 5, 0, 0, 0, 243, 0, 0, 0, 129, 0, 0, 0, 82, 0, 0, 0, 105, 0, 0, 0, 52, 0, 0, 0, 70, 0, 0, 0, 157, 0, 0, 0, 134, 0, 0, 0, 118, 0, 0, 0, 143, +0, 0, 0, 215, 0, 0, 0, 248, 0, 0, 0, 106, 0, 0, 0, 102, 0, 0, 0, 255, 0, 0, 0, 230, 0, 0, 0, 167, 0, 0, 0, 144, 0, 0, 0, 247, 0, 0, 0, 94, 0, 0, 0, 205, 0, 0, 0, 106, 0, 0, 0, 155, 0, 0, 0, 85, 0, 0, 0, 252, 0, 0, 0, 157, 0, 0, 0, 72, 0, 0, 0, 189, 0, 0, 0, 170, 0, 0, 0, 19, 0, 0, 0, 230, 0, 0, 0, 205, 0, 0, 0, 69, 0, 0, 0, 74, 0, 0, 0, 164, 0, 0, 0, 89, 0, 0, 0, 10, 0, 0, 0, 100, 0, 0, 0, 177, 0, 0, 0, 152, 0, 0, 0, 214, 0, 0, 0, 52, 0, 0, 0, 19, 0, 0, 0, 4, 0, 0, 0, 230, 0, 0, 0, 151, 0, 0, 0, +148, 0, 0, 0, 6, 0, 0, 0, 203, 0, 0, 0, 212, 0, 0, 0, 78, 0, 0, 0, 187, 0, 0, 0, 150, 0, 0, 0, 205, 0, 0, 0, 209, 0, 0, 0, 87, 0, 0, 0, 209, 0, 0, 0, 227, 0, 0, 0, 6, 0, 0, 0, 122, 0, 0, 0, 108, 0, 0, 0, 69, 0, 0, 0, 39, 0, 0, 0, 196, 0, 0, 0, 147, 0, 0, 0, 127, 0, 0, 0, 125, 0, 0, 0, 124, 0, 0, 0, 98, 0, 0, 0, 80, 0, 0, 0, 56, 0, 0, 0, 58, 0, 0, 0, 107, 0, 0, 0, 181, 0, 0, 0, 136, 0, 0, 0, 198, 0, 0, 0, 217, 0, 0, 0, 241, 0, 0, 0, 120, 0, 0, 0, 25, 0, 0, 0, 185, 0, 0, 0, 57, 0, 0, 0, 147, 0, 0, +0, 61, 0, 0, 0, 201, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 60, 0, 0, 0, 206, 0, 0, 0, 245, 0, 0, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 234, 0, 0, 0, 35, 0, 0, 0, 125, 0, 0, 0, 86, 0, 0, 0, 44, 0, 0, 0, 226, 0, 0, 0, 89, 0, 0, 0, 14, 0, 0, 0, 133, +0, 0, 0, 96, 0, 0, 0, 4, 0, 0, 0, 136, 0, 0, 0, 90, 0, 0, 0, 116, 0, 0, 0, 30, 0, 0, 0, 75, 0, 0, 0, 239, 0, 0, 0, 19, 0, 0, 0, 218, 0, 0, 0, 76, 0, 0, 0, 255, 0, 0, 0, 131, 0, 0, 0, 69, 0, 0, 0, 133, 0, 0, 0, 63, 0, 0, 0, 8, 0, 0, 0, 149, 0, 0, 0, 44, 0, 0, 0, 32, 0, 0, 0, 19, 0, 0, 0, 31, 0, 0, 0, 72, 0, 0, 0, 95, 0, 0, 0, 39, 0, 0, 0, 144, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0, 0, 66, 0, 0, 0, 173, 0, 0, 0, 120, 0, 0, 0, 71, 0, 0, 0, 92, 0, 0, 0, 181, 0, 0, 0, 126, 0, 0, 0, 8, 0, 0, 0, 133, 0, 0, 0, 0, +0, 0, 0, 250, 0, 0, 0, 127, 0, 0, 0, 253, 0, 0, 0, 253, 0, 0, 0, 231, 0, 0, 0, 9, 0, 0, 0, 17, 0, 0, 0, 242, 0, 0, 0, 126, 0, 0, 0, 27, 0, 0, 0, 56, 0, 0, 0, 108, 0, 0, 0, 53, 0, 0, 0, 109, 0, 0, 0, 51, 0, 0, 0, 102, 0, 0, 0, 147, 0, 0, 0, 3, 0, 0, 0, 54, 0, 0, 0, 129, 0, 0, 0, 172, 0, 0, 0, 228, 0, 0, 0, 32, 0, 0, 0, 9, 0, 0, 0, 53, 0, 0, 0, 76, 0, 0, 0, 69, 0, 0, 0, 178, 0, 0, 0, 30, 0, 0, 0, 76, 0, 0, 0, 20, 0, 0, 0, 33, 0, 0, 0, 230, 0, 0, 0, 233, 0, 0, 0, 138, 0, 0, 0, 123, 0, 0, 0, 141, 0, +0, 0, 254, 0, 0, 0, 30, 0, 0, 0, 198, 0, 0, 0, 62, 0, 0, 0, 193, 0, 0, 0, 53, 0, 0, 0, 250, 0, 0, 0, 231, 0, 0, 0, 112, 0, 0, 0, 78, 0, 0, 0, 29, 0, 0, 0, 97, 0, 0, 0, 46, 0, 0, 0, 194, 0, 0, 0, 221, 0, 0, 0, 149, 0, 0, 0, 87, 0, 0, 0, 209, 0, 0, 0, 171, 0, 0, 0, 128, 0, 0, 0, 232, 0, 0, 0, 99, 0, 0, 0, 23, 0, 0, 0, 181, 0, 0, 0, 72, 0, 0, 0, 228, 0, 0, 0, 138, 0, 0, 0, 17, 0, 0, 0, 158, 0, 0, 0, 114, 0, 0, 0, 190, 0, 0, 0, 133, 0, 0, 0, 141, 0, 0, 0, 81, 0, 0, 0, 10, 0, 0, 0, 242, 0, 0, 0, 159, +0, 0, 0, 224, 0, 0, 0, 28, 0, 0, 0, 169, 0, 0, 0, 7, 0, 0, 0, 40, 0, 0, 0, 123, 0, 0, 0, 187, 0, 0, 0, 113, 0, 0, 0, 20, 0, 0, 0, 94, 0, 0, 0, 38, 0, 0, 0, 140, 0, 0, 0, 61, 0, 0, 0, 200, 0, 0, 0, 233, 0, 0, 0, 124, 0, 0, 0, 211, 0, 0, 0, 214, 0, 0, 0, 209, 0, 0, 0, 47, 0, 0, 0, 7, 0, 0, 0, 109, 0, 0, 0, 230, 0, 0, 0, 223, 0, 0, 0, 251, 0, 0, 0, 121, 0, 0, 0, 214, 0, 0, 0, 153, 0, 0, 0, 89, 0, 0, 0, 150, 0, 0, 0, 72, 0, 0, 0, 64, 0, 0, 0, 15, 0, 0, 0, 58, 0, 0, 0, 123, 0, 0, 0, 178, 0, 0, 0, 160, +0, 0, 0, 114, 0, 0, 0, 78, 0, 0, 0, 59, 0, 0, 0, 105, 0, 0, 0, 200, 0, 0, 0, 67, 0, 0, 0, 117, 0, 0, 0, 81, 0, 0, 0, 108, 0, 0, 0, 121, 0, 0, 0, 86, 0, 0, 0, 228, 0, 0, 0, 203, 0, 0, 0, 247, 0, 0, 0, 166, 0, 0, 0, 81, 0, 0, 0, 194, 0, 0, 0, 44, 0, 0, 0, 66, 0, 0, 0, 11, 0, 0, 0, 212, 0, 0, 0, 130, 0, 0, 0, 32, 0, 0, 0, 28, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 102, 0, 0, 0, 215, 0, 0, 0, 191, 0, 0, 0, 4, 0, 0, 0, 86, 0, 0, 0, 252, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, 232, 0, 0, 0, 183, 0, 0, 0, 96, 0, 0, +0, 174, 0, 0, 0, 71, 0, 0, 0, 128, 0, 0, 0, 252, 0, 0, 0, 229, 0, 0, 0, 35, 0, 0, 0, 231, 0, 0, 0, 194, 0, 0, 0, 201, 0, 0, 0, 133, 0, 0, 0, 230, 0, 0, 0, 152, 0, 0, 0, 160, 0, 0, 0, 41, 0, 0, 0, 78, 0, 0, 0, 225, 0, 0, 0, 132, 0, 0, 0, 57, 0, 0, 0, 45, 0, 0, 0, 149, 0, 0, 0, 44, 0, 0, 0, 243, 0, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 255, 0, 0, 0, 175, 0, 0, 0, 39, 0, 0, 0, 76, 0, 0, 0, 107, 0, 0, 0, 166, 0, 0, 0, 245, 0, 0, 0, 75, 0, 0, 0, 17, 0, 0, 0, 189, 0, 0, 0, 186, 0, 0, 0, 91, 0, 0, 0, 158, 0, +0, 0, 196, 0, 0, 0, 164, 0, 0, 0, 81, 0, 0, 0, 30, 0, 0, 0, 190, 0, 0, 0, 208, 0, 0, 0, 144, 0, 0, 0, 58, 0, 0, 0, 156, 0, 0, 0, 194, 0, 0, 0, 38, 0, 0, 0, 182, 0, 0, 0, 30, 0, 0, 0, 241, 0, 0, 0, 149, 0, 0, 0, 125, 0, 0, 0, 200, 0, 0, 0, 109, 0, 0, 0, 82, 0, 0, 0, 230, 0, 0, 0, 153, 0, 0, 0, 44, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 0, 0, 0, 224, 0, 0, 0, 36, 0, 0, 0, 50, 0, 0, 0, 180, 0, 0, 0, 209, 0, 0, 0, 239, 0, 0, 0, 252, 0, 0, 0, 105, 0, 0, 0, 162, 0, 0, 0, 191, 0, 0, 0, 143, 0, 0, 0, 114, 0, 0, 0, 44, 0, 0, 0, 149, 0, 0, 0, 246, 0, 0, 0, 228, 0, 0, 0, 110, 0, 0, 0, 125, 0, 0, 0, 144, 0, 0, 0, 247, 0, 0, 0, 87, 0, 0, 0, 129, 0, 0, 0, 160, 0, 0, 0, 247, 0, 0, 0, 218, 0, 0, 0, 239, 0, 0, 0, 51, 0, 0, 0, 7, 0, 0, 0, 227, 0, 0, 0, 107, +0, 0, 0, 120, 0, 0, 0, 54, 0, 0, 0, 39, 0, 0, 0, 62, 0, 0, 0, 198, 0, 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 171, 0, 0, 0, 78, 0, 0, 0, 190, 0, 0, 0, 105, 0, 0, 0, 157, 0, 0, 0, 179, 0, 0, 0, 190, 0, 0, 0, 8, 0, 0, 0, 124, 0, 0, 0, 42, 0, 0, 0, 71, 0, 0, 0, 8, 0, 0, 0, 253, 0, 0, 0, 212, 0, 0, 0, 205, 0, 0, 0, 14, 0, 0, 0, 39, 0, 0, 0, 52, 0, 0, 0, 91, 0, 0, 0, 152, 0, 0, 0, 52, 0, 0, 0, 47, 0, 0, 0, 119, 0, 0, 0, 95, 0, 0, 0, 58, 0, 0, 0, 101, 0, 0, 0, 19, 0, 0, 0, 170, 0, 0, 0, 46, 0, 0, 0, 76, 0, 0, 0, +240, 0, 0, 0, 34, 0, 0, 0, 184, 0, 0, 0, 108, 0, 0, 0, 179, 0, 0, 0, 25, 0, 0, 0, 77, 0, 0, 0, 235, 0, 0, 0, 107, 0, 0, 0, 208, 0, 0, 0, 164, 0, 0, 0, 198, 0, 0, 0, 156, 0, 0, 0, 221, 0, 0, 0, 200, 0, 0, 0, 91, 0, 0, 0, 129, 0, 0, 0, 87, 0, 0, 0, 137, 0, 0, 0, 223, 0, 0, 0, 51, 0, 0, 0, 169, 0, 0, 0, 104, 0, 0, 0, 73, 0, 0, 0, 128, 0, 0, 0, 228, 0, 0, 0, 254, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 144, 0, 0, 0, 48, 0, 0, 0, 233, 0, 0, 0, 211, 0, 0, 0, 96, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, +194, 0, 0, 0, 114, 0, 0, 0, 137, 0, 0, 0, 122, 0, 0, 0, 54, 0, 0, 0, 165, 0, 0, 0, 189, 0, 0, 0, 57, 0, 0, 0, 131, 0, 0, 0, 133, 0, 0, 0, 80, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 108, 0, 0, 0, 65, 0, 0, 0, 29, 0, 0, 0, 181, 0, 0, 0, 44, 0, 0, 0, 7, 0, 0, 0, 64, 0, 0, 0, 119, 0, 0, 0, 11, 0, 0, 0, 80, 0, 0, 0, 100, 0, 0, 0, 52, 0, 0, 0, 236, 0, 0, 0, 192, 0, 0, 0, 158, 0, 0, 0, 68, 0, 0, 0, 65, 0, 0, 0, 175, 0, 0, 0, 160, 0, 0, 0, 54, 0, 0, 0, 5, 0, 0, 0, 109, 0, 0, 0, 234, 0, 0, 0, 48, 0, 0, 0, 37, +0, 0, 0, 70, 0, 0, 0, 53, 0, 0, 0, 36, 0, 0, 0, 157, 0, 0, 0, 134, 0, 0, 0, 189, 0, 0, 0, 149, 0, 0, 0, 241, 0, 0, 0, 106, 0, 0, 0, 70, 0, 0, 0, 215, 0, 0, 0, 148, 0, 0, 0, 84, 0, 0, 0, 249, 0, 0, 0, 59, 0, 0, 0, 189, 0, 0, 0, 93, 0, 0, 0, 119, 0, 0, 0, 91, 0, 0, 0, 226, 0, 0, 0, 55, 0, 0, 0, 199, 0, 0, 0, 225, 0, 0, 0, 124, 0, 0, 0, 19, 0, 0, 0, 140, 0, 0, 0, 159, 0, 0, 0, 123, 0, 0, 0, 123, 0, 0, 0, 42, 0, 0, 0, 206, 0, 0, 0, 66, 0, 0, 0, 163, 0, 0, 0, 185, 0, 0, 0, 42, 0, 0, 0, 153, 0, 0, 0, 168, +0, 0, 0, 192, 0, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 134, 0, 0, 0, 176, 0, 0, 0, 251, 0, 0, 0, 233, 0, 0, 0, 118, 0, 0, 0, 119, 0, 0, 0, 247, 0, 0, 0, 245, 0, 0, 0, 86, 0, 0, 0, 223, 0, 0, 0, 179, 0, 0, 0, 70, 0, 0, 0, 17, 0, 0, 0, 110, 0, 0, 0, 19, 0, 0, 0, 183, 0, 0, 0, 40, 0, 0, 0, 78, 0, 0, 0, 86, 0, 0, 0, 221, 0, 0, 0, 241, 0, 0, 0, 172, 0, 0, 0, 173, 0, 0, 0, 88, 0, 0, 0, 195, 0, 0, 0, 248, 0, 0, 0, 136, 0, 0, 0, 148, 0, 0, 0, 94, 0, 0, 0, 6, 0, 0, 0, 152, 0, 0, 0, 161, 0, 0, 0, 228, 0, 0, 0, +106, 0, 0, 0, 251, 0, 0, 0, 10, 0, 0, 0, 73, 0, 0, 0, 93, 0, 0, 0, 138, 0, 0, 0, 254, 0, 0, 0, 119, 0, 0, 0, 70, 0, 0, 0, 2, 0, 0, 0, 245, 0, 0, 0, 165, 0, 0, 0, 175, 0, 0, 0, 197, 0, 0, 0, 117, 0, 0, 0, 109, 0, 0, 0, 186, 0, 0, 0, 69, 0, 0, 0, 53, 0, 0, 0, 10, 0, 0, 0, 254, 0, 0, 0, 201, 0, 0, 0, 172, 0, 0, 0, 34, 0, 0, 0, 145, 0, 0, 0, 141, 0, 0, 0, 33, 0, 0, 0, 149, 0, 0, 0, 51, 0, 0, 0, 3, 0, 0, 0, 192, 0, 0, 0, 138, 0, 0, 0, 22, 0, 0, 0, 243, 0, 0, 0, 57, 0, 0, 0, 224, 0, 0, 0, 1, 0, 0, 0, 15, +0, 0, 0, 83, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 117, 0, 0, 0, 55, 0, 0, 0, 31, 0, 0, 0, 52, 0, 0, 0, 78, 0, 0, 0, 169, 0, 0, 0, 29, 0, 0, 0, 104, 0, 0, 0, 103, 0, 0, 0, 248, 0, 0, 0, 73, 0, 0, 0, 152, 0, 0, 0, 150, 0, 0, 0, 252, 0, 0, 0, +76, 0, 0, 0, 101, 0, 0, 0, 151, 0, 0, 0, 247, 0, 0, 0, 2, 0, 0, 0, 74, 0, 0, 0, 82, 0, 0, 0, 108, 0, 0, 0, 1, 0, 0, 0, 189, 0, 0, 0, 72, 0, 0, 0, 187, 0, 0, 0, 27, 0, 0, 0, 237, 0, 0, 0, 164, 0, 0, 0, 226, 0, 0, 0, 83, 0, 0, 0, 89, 0, 0, 0, 213, 0, 0, 0, 155, 0, 0, 0, 90, 0, 0, 0, 162, 0, 0, 0, 144, 0, 0, 0, 211, 0, 0, 0, 184, 0, 0, 0, 55, 0, 0, 0, 76, 0, 0, 0, 85, 0, 0, 0, 130, 0, 0, 0, 40, 0, 0, 0, 8, 0, 0, 0, 15, 0, 0, 0, 127, 0, 0, 0, 170, 0, 0, 0, 129, 0, 0, 0, 101, 0, 0, 0, 224, 0, 0, 0, 12, +0, 0, 0, 82, 0, 0, 0, 201, 0, 0, 0, 163, 0, 0, 0, 50, 0, 0, 0, 39, 0, 0, 0, 100, 0, 0, 0, 218, 0, 0, 0, 253, 0, 0, 0, 52, 0, 0, 0, 35, 0, 0, 0, 90, 0, 0, 0, 181, 0, 0, 0, 176, 0, 0, 0, 12, 0, 0, 0, 77, 0, 0, 0, 179, 0, 0, 0, 123, 0, 0, 0, 35, 0, 0, 0, 200, 0, 0, 0, 31, 0, 0, 0, 138, 0, 0, 0, 57, 0, 0, 0, 102, 0, 0, 0, 230, 0, 0, 0, 186, 0, 0, 0, 76, 0, 0, 0, 16, 0, 0, 0, 55, 0, 0, 0, 202, 0, 0, 0, 156, 0, 0, 0, 124, 0, 0, 0, 5, 0, 0, 0, 158, 0, 0, 0, 255, 0, 0, 0, 192, 0, 0, 0, 248, 0, 0, 0, 142, +0, 0, 0, 177, 0, 0, 0, 143, 0, 0, 0, 111, 0, 0, 0, 103, 0, 0, 0, 24, 0, 0, 0, 38, 0, 0, 0, 75, 0, 0, 0, 65, 0, 0, 0, 19, 0, 0, 0, 84, 0, 0, 0, 35, 0, 0, 0, 26, 0, 0, 0, 164, 0, 0, 0, 78, 0, 0, 0, 169, 0, 0, 0, 139, 0, 0, 0, 30, 0, 0, 0, 75, 0, 0, 0, 252, 0, 0, 0, 21, 0, 0, 0, 36, 0, 0, 0, 187, 0, 0, 0, 126, 0, 0, 0, 203, 0, 0, 0, 182, 0, 0, 0, 30, 0, 0, 0, 27, 0, 0, 0, 245, 0, 0, 0, 242, 0, 0, 0, 200, 0, 0, 0, 86, 0, 0, 0, 236, 0, 0, 0, 50, 0, 0, 0, 162, 0, 0, 0, 96, 0, 0, 0, 91, 0, 0, 0, 160, 0, +0, 0, 42, 0, 0, 0, 164, 0, 0, 0, 41, 0, 0, 0, 71, 0, 0, 0, 134, 0, 0, 0, 46, 0, 0, 0, 146, 0, 0, 0, 79, 0, 0, 0, 17, 0, 0, 0, 79, 0, 0, 0, 243, 0, 0, 0, 178, 0, 0, 0, 92, 0, 0, 0, 213, 0, 0, 0, 62, 0, 0, 0, 166, 0, 0, 0, 185, 0, 0, 0, 200, 0, 0, 0, 226, 0, 0, 0, 51, 0, 0, 0, 17, 0, 0, 0, 31, 0, 0, 0, 1, 0, 0, 0, 143, 0, 0, 0, 176, 0, 0, 0, 155, 0, 0, 0, 199, 0, 0, 0, 165, 0, 0, 0, 255, 0, 0, 0, 131, 0, 0, 0, 15, 0, 0, 0, 30, 0, 0, 0, 40, 0, 0, 0, 29, 0, 0, 0, 41, 0, 0, 0, 122, 0, 0, 0, 161, 0, 0, +0, 236, 0, 0, 0, 142, 0, 0, 0, 181, 0, 0, 0, 173, 0, 0, 0, 234, 0, 0, 0, 2, 0, 0, 0, 104, 0, 0, 0, 96, 0, 0, 0, 116, 0, 0, 0, 41, 0, 0, 0, 28, 0, 0, 0, 165, 0, 0, 0, 207, 0, 0, 0, 200, 0, 0, 0, 59, 0, 0, 0, 125, 0, 0, 0, 139, 0, 0, 0, 43, 0, 0, 0, 124, 0, 0, 0, 173, 0, 0, 0, 164, 0, 0, 0, 64, 0, 0, 0, 23, 0, 0, 0, 81, 0, 0, 0, 89, 0, 0, 0, 124, 0, 0, 0, 46, 0, 0, 0, 93, 0, 0, 0, 10, 0, 0, 0, 108, 0, 0, 0, 79, 0, 0, 0, 188, 0, 0, 0, 62, 0, 0, 0, 50, 0, 0, 0, 231, 0, 0, 0, 74, 0, 0, 0, 26, 0, 0, 0, +19, 0, 0, 0, 193, 0, 0, 0, 73, 0, 0, 0, 56, 0, 0, 0, 191, 0, 0, 0, 247, 0, 0, 0, 194, 0, 0, 0, 211, 0, 0, 0, 143, 0, 0, 0, 107, 0, 0, 0, 173, 0, 0, 0, 82, 0, 0, 0, 247, 0, 0, 0, 207, 0, 0, 0, 188, 0, 0, 0, 39, 0, 0, 0, 203, 0, 0, 0, 64, 0, 0, 0, 103, 0, 0, 0, 118, 0, 0, 0, 205, 0, 0, 0, 109, 0, 0, 0, 86, 0, 0, 0, 229, 0, 0, 0, 176, 0, 0, 0, 39, 0, 0, 0, 173, 0, 0, 0, 190, 0, 0, 0, 155, 0, 0, 0, 242, 0, 0, 0, 181, 0, 0, 0, 99, 0, 0, 0, 222, 0, 0, 0, 58, 0, 0, 0, 35, 0, 0, 0, 149, 0, 0, 0, 183, 0, +0, 0, 10, 0, 0, 0, 126, 0, 0, 0, 243, 0, 0, 0, 158, 0, 0, 0, 69, 0, 0, 0, 111, 0, 0, 0, 25, 0, 0, 0, 57, 0, 0, 0, 117, 0, 0, 0, 143, 0, 0, 0, 57, 0, 0, 0, 61, 0, 0, 0, 15, 0, 0, 0, 192, 0, 0, 0, 159, 0, 0, 0, 241, 0, 0, 0, 233, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 136, 0, 0, 0, 170, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 134, 0, 0, 0, 148, 0, 0, 0, 17, 0, 0, 0, 18, 0, 0, 0, 62, 0, 0, 0, 26, 0, 0, 0, 181, 0, 0, 0, 204, 0, 0, 0, 187, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 213, 0, 0, 0, 156, 0, 0, 0, 109, 0, 0, 0, 186, 0, 0, 0, 88, 0, 0, 0, 114, 0, 0, 0, 141, 0, 0, 0, 251, 0, 0, 0, 34, 0, 0, 0, 123, 0, 0, 0, 159, 0, 0, 0, 124, 0, 0, 0, 148, 0, 0, 0, 48, 0, 0, 0, 179, 0, 0, 0, 81, 0, 0, 0, 33, 0, 0, 0, 246, 0, 0, 0, 116, 0, 0, 0, 61, 0, 0, 0, 242, 0, +0, 0, 175, 0, 0, 0, 208, 0, 0, 0, 30, 0, 0, 0, 3, 0, 0, 0, 124, 0, 0, 0, 35, 0, 0, 0, 107, 0, 0, 0, 201, 0, 0, 0, 252, 0, 0, 0, 37, 0, 0, 0, 112, 0, 0, 0, 144, 0, 0, 0, 220, 0, 0, 0, 154, 0, 0, 0, 164, 0, 0, 0, 251, 0, 0, 0, 73, 0, 0, 0, 252, 0, 0, 0, 61, 0, 0, 0, 10, 0, 0, 0, 53, 0, 0, 0, 56, 0, 0, 0, 111, 0, 0, 0, 228, 0, 0, 0, 126, 0, 0, 0, 80, 0, 0, 0, 1, 0, 0, 0, 42, 0, 0, 0, 214, 0, 0, 0, 227, 0, 0, 0, 150, 0, 0, 0, 97, 0, 0, 0, 58, 0, 0, 0, 253, 0, 0, 0, 239, 0, 0, 0, 155, 0, 0, 0, 31, 0, +0, 0, 144, 0, 0, 0, 164, 0, 0, 0, 36, 0, 0, 0, 20, 0, 0, 0, 91, 0, 0, 0, 200, 0, 0, 0, 222, 0, 0, 0, 80, 0, 0, 0, 177, 0, 0, 0, 29, 0, 0, 0, 175, 0, 0, 0, 232, 0, 0, 0, 85, 0, 0, 0, 138, 0, 0, 0, 135, 0, 0, 0, 13, 0, 0, 0, 254, 0, 0, 0, 170, 0, 0, 0, 59, 0, 0, 0, 130, 0, 0, 0, 44, 0, 0, 0, 141, 0, 0, 0, 123, 0, 0, 0, 133, 0, 0, 0, 12, 0, 0, 0, 175, 0, 0, 0, 248, 0, 0, 0, 131, 0, 0, 0, 68, 0, 0, 0, 73, 0, 0, 0, 217, 0, 0, 0, 69, 0, 0, 0, 207, 0, 0, 0, 247, 0, 0, 0, 72, 0, 0, 0, 217, 0, 0, 0, 83, 0, +0, 0, 180, 0, 0, 0, 241, 0, 0, 0, 101, 0, 0, 0, 160, 0, 0, 0, 225, 0, 0, 0, 195, 0, 0, 0, 179, 0, 0, 0, 21, 0, 0, 0, 237, 0, 0, 0, 137, 0, 0, 0, 155, 0, 0, 0, 79, 0, 0, 0, 98, 0, 0, 0, 179, 0, 0, 0, 87, 0, 0, 0, 165, 0, 0, 0, 69, 0, 0, 0, 28, 0, 0, 0, 143, 0, 0, 0, 18, 0, 0, 0, 234, 0, 0, 0, 175, 0, 0, 0, 209, 0, 0, 0, 31, 0, 0, 0, 121, 0, 0, 0, 16, 0, 0, 0, 11, 0, 0, 0, 246, 0, 0, 0, 163, 0, 0, 0, 123, 0, 0, 0, 234, 0, 0, 0, 172, 0, 0, 0, 139, 0, 0, 0, 87, 0, 0, 0, 50, 0, 0, 0, 98, 0, 0, 0, 231, +0, 0, 0, 6, 0, 0, 0, 18, 0, 0, 0, 81, 0, 0, 0, 160, 0, 0, 0, 59, 0, 0, 0, 67, 0, 0, 0, 94, 0, 0, 0, 164, 0, 0, 0, 32, 0, 0, 0, 120, 0, 0, 0, 49, 0, 0, 0, 206, 0, 0, 0, 13, 0, 0, 0, 132, 0, 0, 0, 124, 0, 0, 0, 194, 0, 0, 0, 166, 0, 0, 0, 145, 0, 0, 0, 35, 0, 0, 0, 206, 0, 0, 0, 189, 0, 0, 0, 220, 0, 0, 0, 249, 0, 0, 0, 206, 0, 0, 0, 213, 0, 0, 0, 117, 0, 0, 0, 48, 0, 0, 0, 34, 0, 0, 0, 230, 0, 0, 0, 249, 0, 0, 0, 67, 0, 0, 0, 98, 0, 0, 0, 13, 0, 0, 0, 247, 0, 0, 0, 117, 0, 0, 0, 157, 0, 0, 0, 127, +0, 0, 0, 140, 0, 0, 0, 255, 0, 0, 0, 125, 0, 0, 0, 228, 0, 0, 0, 114, 0, 0, 0, 172, 0, 0, 0, 159, 0, 0, 0, 28, 0, 0, 0, 136, 0, 0, 0, 193, 0, 0, 0, 153, 0, 0, 0, 208, 0, 0, 0, 60, 0, 0, 0, 28, 0, 0, 0, 93, 0, 0, 0, 180, 0, 0, 0, 239, 0, 0, 0, 19, 0, 0, 0, 15, 0, 0, 0, 144, 0, 0, 0, 185, 0, 0, 0, 54, 0, 0, 0, 47, 0, 0, 0, 149, 0, 0, 0, 149, 0, 0, 0, 198, 0, 0, 0, 220, 0, 0, 0, 222, 0, 0, 0, 10, 0, 0, 0, 81, 0, 0, 0, 226, 0, 0, 0, 141, 0, 0, 0, 243, 0, 0, 0, 188, 0, 0, 0, 81, 0, 0, 0, 236, 0, 0, 0, +223, 0, 0, 0, 177, 0, 0, 0, 162, 0, 0, 0, 95, 0, 0, 0, 46, 0, 0, 0, 104, 0, 0, 0, 161, 0, 0, 0, 35, 0, 0, 0, 125, 0, 0, 0, 155, 0, 0, 0, 64, 0, 0, 0, 105, 0, 0, 0, 133, 0, 0, 0, 123, 0, 0, 0, 66, 0, 0, 0, 191, 0, 0, 0, 144, 0, 0, 0, 75, 0, 0, 0, 214, 0, 0, 0, 64, 0, 0, 0, 47, 0, 0, 0, 215, 0, 0, 0, 82, 0, 0, 0, 82, 0, 0, 0, 178, 0, 0, 0, 33, 0, 0, 0, 222, 0, 0, 0, 100, 0, 0, 0, 189, 0, 0, 0, 136, 0, 0, 0, 195, 0, 0, 0, 109, 0, 0, 0, 165, 0, 0, 0, 250, 0, 0, 0, 129, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 251, 0, 0, 0, 253, 0, 0, 0, 71, 0, 0, 0, 123, 0, 0, 0, 138, 0, 0, 0, 102, 0, 0, 0, 158, 0, 0, 0, 121, 0, 0, 0, 46, 0, 0, 0, 100, 0, 0, 0, 130, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 33, 0, 0, 0, 236, 0, 0, 0, 246, 0, 0, 0, 216, 0, 0, 0, 134, 0, +0, 0, 9, 0, 0, 0, 49, 0, 0, 0, 124, 0, 0, 0, 221, 0, 0, 0, 3, 0, 0, 0, 106, 0, 0, 0, 88, 0, 0, 0, 160, 0, 0, 0, 119, 0, 0, 0, 183, 0, 0, 0, 155, 0, 0, 0, 140, 0, 0, 0, 135, 0, 0, 0, 31, 0, 0, 0, 85, 0, 0, 0, 71, 0, 0, 0, 228, 0, 0, 0, 168, 0, 0, 0, 61, 0, 0, 0, 85, 0, 0, 0, 33, 0, 0, 0, 52, 0, 0, 0, 171, 0, 0, 0, 29, 0, 0, 0, 174, 0, 0, 0, 224, 0, 0, 0, 244, 0, 0, 0, 234, 0, 0, 0, 219, 0, 0, 0, 197, 0, 0, 0, 185, 0, 0, 0, 88, 0, 0, 0, 191, 0, 0, 0, 196, 0, 0, 0, 42, 0, 0, 0, 137, 0, 0, 0, 49, 0, +0, 0, 26, 0, 0, 0, 244, 0, 0, 0, 45, 0, 0, 0, 225, 0, 0, 0, 202, 0, 0, 0, 55, 0, 0, 0, 153, 0, 0, 0, 71, 0, 0, 0, 89, 0, 0, 0, 199, 0, 0, 0, 202, 0, 0, 0, 99, 0, 0, 0, 193, 0, 0, 0, 73, 0, 0, 0, 169, 0, 0, 0, 53, 0, 0, 0, 69, 0, 0, 0, 85, 0, 0, 0, 126, 0, 0, 0, 218, 0, 0, 0, 100, 0, 0, 0, 50, 0, 0, 0, 7, 0, 0, 0, 80, 0, 0, 0, 247, 0, 0, 0, 50, 0, 0, 0, 172, 0, 0, 0, 222, 0, 0, 0, 117, 0, 0, 0]).concat([88, 0, 0, 0, 155, 0, 0, 0, 17, 0, 0, 0, 178, 0, 0, 0, 58, 0, 0, 0, 31, 0, 0, 0, 245, 0, 0, 0, 247, +0, 0, 0, 121, 0, 0, 0, 4, 0, 0, 0, 230, 0, 0, 0, 8, 0, 0, 0, 70, 0, 0, 0, 250, 0, 0, 0, 34, 0, 0, 0, 75, 0, 0, 0, 250, 0, 0, 0, 225, 0, 0, 0, 254, 0, 0, 0, 150, 0, 0, 0, 252, 0, 0, 0, 103, 0, 0, 0, 186, 0, 0, 0, 103, 0, 0, 0, 151, 0, 0, 0, 196, 0, 0, 0, 231, 0, 0, 0, 27, 0, 0, 0, 134, 0, 0, 0, 144, 0, 0, 0, 95, 0, 0, 0, 238, 0, 0, 0, 244, 0, 0, 0, 91, 0, 0, 0, 17, 0, 0, 0, 178, 0, 0, 0, 205, 0, 0, 0, 173, 0, 0, 0, 238, 0, 0, 0, 194, 0, 0, 0, 72, 0, 0, 0, 108, 0, 0, 0, 43, 0, 0, 0, 27, 0, 0, 0, 227, +0, 0, 0, 57, 0, 0, 0, 98, 0, 0, 0, 180, 0, 0, 0, 79, 0, 0, 0, 49, 0, 0, 0, 4, 0, 0, 0, 201, 0, 0, 0, 218, 0, 0, 0, 213, 0, 0, 0, 115, 0, 0, 0, 81, 0, 0, 0, 87, 0, 0, 0, 197, 0, 0, 0, 184, 0, 0, 0, 243, 0, 0, 0, 163, 0, 0, 0, 67, 0, 0, 0, 112, 0, 0, 0, 228, 0, 0, 0, 97, 0, 0, 0, 129, 0, 0, 0, 132, 0, 0, 0, 226, 0, 0, 0, 187, 0, 0, 0, 191, 0, 0, 0, 79, 0, 0, 0, 158, 0, 0, 0, 164, 0, 0, 0, 94, 0, 0, 0, 116, 0, 0, 0, 6, 0, 0, 0, 41, 0, 0, 0, 172, 0, 0, 0, 255, 0, 0, 0, 39, 0, 0, 0, 224, 0, 0, 0, 89, +0, 0, 0, 190, 0, 0, 0, 57, 0, 0, 0, 156, 0, 0, 0, 13, 0, 0, 0, 131, 0, 0, 0, 215, 0, 0, 0, 16, 0, 0, 0, 11, 0, 0, 0, 21, 0, 0, 0, 183, 0, 0, 0, 225, 0, 0, 0, 194, 0, 0, 0, 44, 0, 0, 0, 48, 0, 0, 0, 115, 0, 0, 0, 128, 0, 0, 0, 58, 0, 0, 0, 125, 0, 0, 0, 93, 0, 0, 0, 171, 0, 0, 0, 88, 0, 0, 0, 107, 0, 0, 0, 193, 0, 0, 0, 240, 0, 0, 0, 244, 0, 0, 0, 34, 0, 0, 0, 254, 0, 0, 0, 127, 0, 0, 0, 251, 0, 0, 0, 53, 0, 0, 0, 125, 0, 0, 0, 198, 0, 0, 0, 1, 0, 0, 0, 35, 0, 0, 0, 40, 0, 0, 0, 196, 0, 0, 0, 2, 0, +0, 0, 172, 0, 0, 0, 31, 0, 0, 0, 66, 0, 0, 0, 180, 0, 0, 0, 157, 0, 0, 0, 252, 0, 0, 0, 0, 0, 0, 0, 148, 0, 0, 0, 165, 0, 0, 0, 238, 0, 0, 0, 202, 0, 0, 0, 218, 0, 0, 0, 151, 0, 0, 0, 9, 0, 0, 0, 65, 0, 0, 0, 119, 0, 0, 0, 135, 0, 0, 0, 93, 0, 0, 0, 123, 0, 0, 0, 135, 0, 0, 0, 120, 0, 0, 0, 245, 0, 0, 0, 251, 0, 0, 0, 144, 0, 0, 0, 45, 0, 0, 0, 129, 0, 0, 0, 25, 0, 0, 0, 158, 0, 0, 0, 47, 0, 0, 0, 109, 0, 0, 0, 133, 0, 0, 0, 136, 0, 0, 0, 140, 0, 0, 0, 64, 0, 0, 0, 92, 0, 0, 0, 119, 0, 0, 0, 65, +0, 0, 0, 77, 0, 0, 0, 1, 0, 0, 0, 25, 0, 0, 0, 118, 0, 0, 0, 96, 0, 0, 0, 232, 0, 0, 0, 76, 0, 0, 0, 72, 0, 0, 0, 228, 0, 0, 0, 51, 0, 0, 0, 131, 0, 0, 0, 50, 0, 0, 0, 108, 0, 0, 0, 180, 0, 0, 0, 65, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 16, +0, 0, 0, 194, 0, 0, 0, 9, 0, 0, 0, 79, 0, 0, 0, 110, 0, 0, 0, 244, 0, 0, 0, 210, 0, 0, 0, 223, 0, 0, 0, 126, 0, 0, 0, 202, 0, 0, 0, 123, 0, 0, 0, 28, 0, 0, 0, 29, 0, 0, 0, 186, 0, 0, 0, 163, 0, 0, 0, 182, 0, 0, 0, 218, 0, 0, 0, 103, 0, 0, 0, 51, 0, 0, 0, 212, 0, 0, 0, 135, 0, 0, 0, 54, 0, 0, 0, 75, 0, 0, 0, 17, 0, 0, 0, 32, 0, 0, 0, 5, 0, 0, 0, 166, 0, 0, 0, 41, 0, 0, 0, 193, 0, 0, 0, 135, 0, 0, 0, 23, 0, 0, 0, 246, 0, 0, 0, 150, 0, 0, 0, 202, 0, 0, 0, 47, 0, 0, 0, 218, 0, 0, 0, 56, 0, 0, 0, 167, +0, 0, 0, 27, 0, 0, 0, 252, 0, 0, 0, 202, 0, 0, 0, 125, 0, 0, 0, 254, 0, 0, 0, 8, 0, 0, 0, 137, 0, 0, 0, 226, 0, 0, 0, 71, 0, 0, 0, 43, 0, 0, 0, 106, 0, 0, 0, 93, 0, 0, 0, 75, 0, 0, 0, 250, 0, 0, 0, 161, 0, 0, 0, 180, 0, 0, 0, 222, 0, 0, 0, 182, 0, 0, 0, 194, 0, 0, 0, 49, 0, 0, 0, 81, 0, 0, 0, 245, 0, 0, 0, 224, 0, 0, 0, 164, 0, 0, 0, 11, 0, 0, 0, 92, 0, 0, 0, 229, 0, 0, 0, 198, 0, 0, 0, 4, 0, 0, 0, 142, 0, 0, 0, 43, 0, 0, 0, 87, 0, 0, 0, 190, 0, 0, 0, 56, 0, 0, 0, 133, 0, 0, 0, 35, 0, 0, 0, 203, +0, 0, 0, 183, 0, 0, 0, 190, 0, 0, 0, 79, 0, 0, 0, 169, 0, 0, 0, 211, 0, 0, 0, 110, 0, 0, 0, 18, 0, 0, 0, 170, 0, 0, 0, 213, 0, 0, 0, 178, 0, 0, 0, 46, 0, 0, 0, 147, 0, 0, 0, 41, 0, 0, 0, 154, 0, 0, 0, 74, 0, 0, 0, 136, 0, 0, 0, 24, 0, 0, 0, 67, 0, 0, 0, 245, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 252, 0, 0, 0, 219, 0, 0, 0, 162, 0, 0, 0, 89, 0, 0, 0, 33, 0, 0, 0, 141, 0, 0, 0, 189, 0, 0, 0, 126, 0, 0, 0, 51, 0, 0, 0, 174, 0, 0, 0, 47, 0, 0, 0, 135, 0, 0, 0, 26, 0, 0, 0, 208, 0, 0, 0, 151, 0, 0, 0, 199, +0, 0, 0, 13, 0, 0, 0, 77, 0, 0, 0, 99, 0, 0, 0, 1, 0, 0, 0, 239, 0, 0, 0, 5, 0, 0, 0, 132, 0, 0, 0, 236, 0, 0, 0, 64, 0, 0, 0, 221, 0, 0, 0, 168, 0, 0, 0, 10, 0, 0, 0, 79, 0, 0, 0, 112, 0, 0, 0, 11, 0, 0, 0, 65, 0, 0, 0, 105, 0, 0, 0, 1, 0, 0, 0, 103, 0, 0, 0, 92, 0, 0, 0, 211, 0, 0, 0, 138, 0, 0, 0, 197, 0, 0, 0, 207, 0, 0, 0, 63, 0, 0, 0, 209, 0, 0, 0, 87, 0, 0, 0, 209, 0, 0, 0, 103, 0, 0, 0, 62, 0, 0, 0, 1, 0, 0, 0, 57, 0, 0, 0, 181, 0, 0, 0, 203, 0, 0, 0, 129, 0, 0, 0, 86, 0, 0, 0, 150, 0, 0, +0, 38, 0, 0, 0, 182, 0, 0, 0, 194, 0, 0, 0, 231, 0, 0, 0, 92, 0, 0, 0, 251, 0, 0, 0, 99, 0, 0, 0, 151, 0, 0, 0, 88, 0, 0, 0, 6, 0, 0, 0, 12, 0, 0, 0, 14, 0, 0, 0, 243, 0, 0, 0, 186, 0, 0, 0, 240, 0, 0, 0, 229, 0, 0, 0, 186, 0, 0, 0, 178, 0, 0, 0, 87, 0, 0, 0, 119, 0, 0, 0, 198, 0, 0, 0, 32, 0, 0, 0, 155, 0, 0, 0, 137, 0, 0, 0, 36, 0, 0, 0, 190, 0, 0, 0, 242, 0, 0, 0, 156, 0, 0, 0, 138, 0, 0, 0, 186, 0, 0, 0, 105, 0, 0, 0, 193, 0, 0, 0, 241, 0, 0, 0, 176, 0, 0, 0, 79, 0, 0, 0, 42, 0, 0, 0, 5, 0, 0, +0, 154, 0, 0, 0, 238, 0, 0, 0, 16, 0, 0, 0, 126, 0, 0, 0, 54, 0, 0, 0, 63, 0, 0, 0, 38, 0, 0, 0, 233, 0, 0, 0, 64, 0, 0, 0, 233, 0, 0, 0, 3, 0, 0, 0, 173, 0, 0, 0, 6, 0, 0, 0, 105, 0, 0, 0, 145, 0, 0, 0, 224, 0, 0, 0, 209, 0, 0, 0, 137, 0, 0, 0, 96, 0, 0, 0, 132, 0, 0, 0, 121, 0, 0, 0, 222, 0, 0, 0, 39, 0, 0, 0, 109, 0, 0, 0, 230, 0, 0, 0, 118, 0, 0, 0, 189, 0, 0, 0, 234, 0, 0, 0, 230, 0, 0, 0, 174, 0, 0, 0, 72, 0, 0, 0, 195, 0, 0, 0, 103, 0, 0, 0, 192, 0, 0, 0, 87, 0, 0, 0, 205, 0, 0, 0, 47, 0, +0, 0, 127, 0, 0, 0, 193, 0, 0, 0, 220, 0, 0, 0, 185, 0, 0, 0, 199, 0, 0, 0, 188, 0, 0, 0, 134, 0, 0, 0, 61, 0, 0, 0, 85, 0, 0, 0, 75, 0, 0, 0, 40, 0, 0, 0, 122, 0, 0, 0, 251, 0, 0, 0, 77, 0, 0, 0, 199, 0, 0, 0, 248, 0, 0, 0, 188, 0, 0, 0, 103, 0, 0, 0, 42, 0, 0, 0, 96, 0, 0, 0, 77, 0, 0, 0, 143, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 26, 0, 0, 0, 23, 0, 0, 0, 191, 0, 0, 0, 250, 0, 0, 0, 172, 0, 0, 0, 167, 0, 0, 0, 61, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 63, 0, 0, 0, 237, 0, 0, 0, 94, 0, 0, 0, 24, 0, 0, 0, 120, 0, 0, 0, 63, 0, 0, 0, 35, 0, 0, 0, 44, 0, 0, 0, 13, 0, 0, 0, 140, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 251, 0, 0, 0, 233, 0, 0, 0, 142, 0, 0, 0, 214, 0, 0, 0, 209, 0, 0, 0, 54, 0, 0, 0, 88, 0, 0, 0, 87, 0, 0, 0, 158, +0, 0, 0, 174, 0, 0, 0, 75, 0, 0, 0, 92, 0, 0, 0, 11, 0, 0, 0, 7, 0, 0, 0, 188, 0, 0, 0, 107, 0, 0, 0, 85, 0, 0, 0, 43, 0, 0, 0, 111, 0, 0, 0, 77, 0, 0, 0, 23, 0, 0, 0, 215, 0, 0, 0, 225, 0, 0, 0, 132, 0, 0, 0, 217, 0, 0, 0, 120, 0, 0, 0, 177, 0, 0, 0, 144, 0, 0, 0, 253, 0, 0, 0, 46, 0, 0, 0, 179, 0, 0, 0, 181, 0, 0, 0, 25, 0, 0, 0, 63, 0, 0, 0, 27, 0, 0, 0, 250, 0, 0, 0, 192, 0, 0, 0, 104, 0, 0, 0, 179, 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 137, 0, 0, 0, 189, 0, 0, 0, 126, 0, 0, 0, 128, +0, 0, 0, 50, 0, 0, 0, 19, 0, 0, 0, 160, 0, 0, 0, 123, 0, 0, 0, 26, 0, 0, 0, 111, 0, 0, 0, 64, 0, 0, 0, 175, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 176, 0, 0, 0, 67, 0, 0, 0, 143, 0, 0, 0, 13, 0, 0, 0, 208, 0, 0, 0, 30, 0, 0, 0, 196, 0, 0, 0, 11, 0, 0, 0, 25, 0, 0, 0, 93, 0, 0, 0, 142, 0, 0, 0, 254, 0, 0, 0, 193, 0, 0, 0, 243, 0, 0, 0, 197, 0, 0, 0, 92, 0, 0, 0, 145, 0, 0, 0, 248, 0, 0, 0, 4, 0, 0, 0, 78, 0, 0, 0, 190, 0, 0, 0, 144, 0, 0, 0, 180, 0, 0, 0, 71, 0, 0, 0, 92, 0, 0, 0, 63, 0, 0, 0, 176, 0, +0, 0, 59, 0, 0, 0, 44, 0, 0, 0, 243, 0, 0, 0, 254, 0, 0, 0, 50, 0, 0, 0, 113, 0, 0, 0, 7, 0, 0, 0, 63, 0, 0, 0, 170, 0, 0, 0, 186, 0, 0, 0, 69, 0, 0, 0, 96, 0, 0, 0, 168, 0, 0, 0, 141, 0, 0, 0, 234, 0, 0, 0, 84, 0, 0, 0, 203, 0, 0, 0, 57, 0, 0, 0, 16, 0, 0, 0, 180, 0, 0, 0, 242, 0, 0, 0, 139, 0, 0, 0, 210, 0, 0, 0, 20, 0, 0, 0, 130, 0, 0, 0, 66, 0, 0, 0, 7, 0, 0, 0, 142, 0, 0, 0, 233, 0, 0, 0, 124, 0, 0, 0, 83, 0, 0, 0, 176, 0, 0, 0, 174, 0, 0, 0, 193, 0, 0, 0, 141, 0, 0, 0, 201, 0, 0, 0, 143, 0, +0, 0, 185, 0, 0, 0, 122, 0, 0, 0, 119, 0, 0, 0, 239, 0, 0, 0, 186, 0, 0, 0, 121, 0, 0, 0, 160, 0, 0, 0, 60, 0, 0, 0, 168, 0, 0, 0, 245, 0, 0, 0, 106, 0, 0, 0, 226, 0, 0, 0, 63, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 227, 0, 0, 0, 75, 0, 0, 0, 69, 0, 0, 0, 36, 0, 0, 0, 123, 0, 0, 0, 67, 0, 0, 0, 120, 0, 0, 0, 85, 0, 0, 0, 29, 0, 0, 0, 43, 0, 0, 0, 30, 0, 0, 0, 1, 0, 0, 0, 184, 0, 0, 0, 214, 0, 0, 0, 22, 0, 0, 0, 103, 0, 0, 0, 160, 0, 0, 0, 21, 0, 0, 0, 185, 0, 0, 0, 225, 0, 0, 0, 88, 0, 0, 0, 164, 0, 0, +0, 167, 0, 0, 0, 49, 0, 0, 0, 55, 0, 0, 0, 119, 0, 0, 0, 47, 0, 0, 0, 139, 0, 0, 0, 18, 0, 0, 0, 159, 0, 0, 0, 244, 0, 0, 0, 63, 0, 0, 0, 199, 0, 0, 0, 54, 0, 0, 0, 102, 0, 0, 0, 210, 0, 0, 0, 168, 0, 0, 0, 86, 0, 0, 0, 247, 0, 0, 0, 127, 0, 0, 0, 116, 0, 0, 0, 198, 0, 0, 0, 65, 0, 0, 0, 93, 0, 0, 0, 248, 0, 0, 0, 180, 0, 0, 0, 168, 0, 0, 0, 48, 0, 0, 0, 221, 0, 0, 0, 204, 0, 0, 0, 56, 0, 0, 0, 165, 0, 0, 0, 211, 0, 0, 0, 202, 0, 0, 0, 216, 0, 0, 0, 209, 0, 0, 0, 248, 0, 0, 0, 178, 0, 0, 0, 49, 0, +0, 0, 145, 0, 0, 0, 212, 0, 0, 0, 114, 0, 0, 0, 5, 0, 0, 0, 87, 0, 0, 0, 74, 0, 0, 0, 59, 0, 0, 0, 130, 0, 0, 0, 74, 0, 0, 0, 198, 0, 0, 0, 104, 0, 0, 0, 32, 0, 0, 0, 226, 0, 0, 0, 24, 0, 0, 0, 65, 0, 0, 0, 97, 0, 0, 0, 25, 0, 0, 0, 212, 0, 0, 0, 141, 0, 0, 0, 71, 0, 0, 0, 41, 0, 0, 0, 18, 0, 0, 0, 101, 0, 0, 0, 176, 0, 0, 0, 17, 0, 0, 0, 120, 0, 0, 0, 71, 0, 0, 0, 181, 0, 0, 0, 203, 0, 0, 0, 163, 0, 0, 0, 165, 0, 0, 0, 250, 0, 0, 0, 5, 0, 0, 0, 133, 0, 0, 0, 84, 0, 0, 0, 169, 0, 0, 0, 51, 0, 0, +0, 151, 0, 0, 0, 141, 0, 0, 0, 43, 0, 0, 0, 194, 0, 0, 0, 254, 0, 0, 0, 153, 0, 0, 0, 53, 0, 0, 0, 40, 0, 0, 0, 229, 0, 0, 0, 235, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 239, 0, 0, 0, 216, 0, 0, 0, 244, 0, 0, 0, +252, 0, 0, 0, 179, 0, 0, 0, 160, 0, 0, 0, 96, 0, 0, 0, 80, 0, 0, 0, 6, 0, 0, 0, 43, 0, 0, 0, 41, 0, 0, 0, 82, 0, 0, 0, 112, 0, 0, 0, 21, 0, 0, 0, 11, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 248, 0, 0, 0, 95, 0, 0, 0, 121, 0, 0, 0, 24, 0, 0, 0, 204, 0, 0, 0, 255, 0, 0, 0, 137, 0, 0, 0, 153, 0, 0, 0, 132, 0, 0, 0, 161, 0, 0, 0, 174, 0, 0, 0, 19, 0, 0, 0, 68, 0, 0, 0, 31, 0, 0, 0, 184, 0, 0, 0, 194, 0, 0, 0, 1, 0, 0, 0, 193, 0, 0, 0, 48, 0, 0, 0, 25, 0, 0, 0, 85, 0, 0, 0, 5, 0, 0, 0, 96, 0, 0, 0, 16, 0, +0, 0, 164, 0, 0, 0, 108, 0, 0, 0, 45, 0, 0, 0, 103, 0, 0, 0, 112, 0, 0, 0, 229, 0, 0, 0, 37, 0, 0, 0, 27, 0, 0, 0, 242, 0, 0, 0, 191, 0, 0, 0, 221, 0, 0, 0, 251, 0, 0, 0, 112, 0, 0, 0, 43, 0, 0, 0, 161, 0, 0, 0, 140, 0, 0, 0, 156, 0, 0, 0, 148, 0, 0, 0, 132, 0, 0, 0, 8, 0, 0, 0, 231, 0, 0, 0, 196, 0, 0, 0, 67, 0, 0, 0, 77, 0, 0, 0, 201, 0, 0, 0, 43, 0, 0, 0, 105, 0, 0, 0, 93, 0, 0, 0, 29, 0, 0, 0, 60, 0, 0, 0, 175, 0, 0, 0, 187, 0, 0, 0, 67, 0, 0, 0, 56, 0, 0, 0, 78, 0, 0, 0, 152, 0, 0, 0, 61, 0, +0, 0, 237, 0, 0, 0, 13, 0, 0, 0, 33, 0, 0, 0, 3, 0, 0, 0, 253, 0, 0, 0, 240, 0, 0, 0, 153, 0, 0, 0, 71, 0, 0, 0, 4, 0, 0, 0, 176, 0, 0, 0, 152, 0, 0, 0, 105, 0, 0, 0, 85, 0, 0, 0, 114, 0, 0, 0, 15, 0, 0, 0, 94, 0, 0, 0, 223, 0, 0, 0, 21, 0, 0, 0, 83, 0, 0, 0, 59, 0, 0, 0, 134, 0, 0, 0, 128, 0, 0, 0, 176, 0, 0, 0, 241, 0, 0, 0, 112, 0, 0, 0, 104, 0, 0, 0, 143, 0, 0, 0, 102, 0, 0, 0, 124, 0, 0, 0, 14, 0, 0, 0, 73, 0, 0, 0, 26, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, 254, 0, 0, 0, 78, 0, 0, 0, 239, 0, +0, 0, 202, 0, 0, 0, 71, 0, 0, 0, 212, 0, 0, 0, 3, 0, 0, 0, 193, 0, 0, 0, 55, 0, 0, 0, 80, 0, 0, 0, 156, 0, 0, 0, 193, 0, 0, 0, 22, 0, 0, 0, 205, 0, 0, 0, 36, 0, 0, 0, 198, 0, 0, 0, 62, 0, 0, 0, 12, 0, 0, 0, 130, 0, 0, 0, 155, 0, 0, 0, 145, 0, 0, 0, 43, 0, 0, 0, 97, 0, 0, 0, 74, 0, 0, 0, 178, 0, 0, 0, 15, 0, 0, 0, 136, 0, 0, 0, 85, 0, 0, 0, 95, 0, 0, 0, 90, 0, 0, 0, 87, 0, 0, 0, 255, 0, 0, 0, 229, 0, 0, 0, 116, 0, 0, 0, 11, 0, 0, 0, 19, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 107, 0, 0, 0, +207, 0, 0, 0, 210, 0, 0, 0, 21, 0, 0, 0, 3, 0, 0, 0, 44, 0, 0, 0, 220, 0, 0, 0, 255, 0, 0, 0, 21, 0, 0, 0, 97, 0, 0, 0, 47, 0, 0, 0, 74, 0, 0, 0, 47, 0, 0, 0, 98, 0, 0, 0, 242, 0, 0, 0, 4, 0, 0, 0, 47, 0, 0, 0, 181, 0, 0, 0, 12, 0, 0, 0, 183, 0, 0, 0, 30, 0, 0, 0, 63, 0, 0, 0, 116, 0, 0, 0, 26, 0, 0, 0, 15, 0, 0, 0, 215, 0, 0, 0, 234, 0, 0, 0, 205, 0, 0, 0, 217, 0, 0, 0, 125, 0, 0, 0, 246, 0, 0, 0, 18, 0, 0, 0, 14, 0, 0, 0, 47, 0, 0, 0, 219, 0, 0, 0, 90, 0, 0, 0, 59, 0, 0, 0, 22, 0, 0, 0, 27, 0, +0, 0, 55, 0, 0, 0, 71, 0, 0, 0, 227, 0, 0, 0, 245, 0, 0, 0, 158, 0, 0, 0, 234, 0, 0, 0, 44, 0, 0, 0, 42, 0, 0, 0, 231, 0, 0, 0, 130, 0, 0, 0, 54, 0, 0, 0, 244, 0, 0, 0, 31, 0, 0, 0, 129, 0, 0, 0, 71, 0, 0, 0, 146, 0, 0, 0, 75, 0, 0, 0, 105, 0, 0, 0, 14, 0, 0, 0, 17, 0, 0, 0, 140, 0, 0, 0, 93, 0, 0, 0, 83, 0, 0, 0, 91, 0, 0, 0, 129, 0, 0, 0, 39, 0, 0, 0, 8, 0, 0, 0, 188, 0, 0, 0, 160, 0, 0, 0, 174, 0, 0, 0, 37, 0, 0, 0, 105, 0, 0, 0, 50, 0, 0, 0, 161, 0, 0, 0, 5, 0, 0, 0, 17, 0, 0, 0, 66, 0, 0, 0, +0, 0, 0, 0, 210, 0, 0, 0, 89, 0, 0, 0, 172, 0, 0, 0, 77, 0, 0, 0, 98, 0, 0, 0, 139, 0, 0, 0, 19, 0, 0, 0, 226, 0, 0, 0, 80, 0, 0, 0, 93, 0, 0, 0, 160, 0, 0, 0, 157, 0, 0, 0, 155, 0, 0, 0, 253, 0, 0, 0, 187, 0, 0, 0, 18, 0, 0, 0, 65, 0, 0, 0, 117, 0, 0, 0, 65, 0, 0, 0, 158, 0, 0, 0, 204, 0, 0, 0, 220, 0, 0, 0, 199, 0, 0, 0, 220, 0, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 0, 227, 0, 0, 0, 56, 0, 0, 0, 6, 0, 0, 0, 70, 0, 0, 0, 112, 0, 0, 0, 130, 0, 0, 0, 94, 0, 0, 0, 40, 0, 0, 0, 73, 0, 0, 0, 121, 0, 0, 0, 255, 0, 0, 0, 37, 0, 0, 0, 210, 0, 0, 0, 78, 0, 0, 0, 41, 0, 0, 0, 141, 0, 0, 0, 6, 0, 0, 0, 176, 0, 0, 0, 35, 0, 0, 0, 174, 0, 0, 0, 155, 0, 0, 0, 102, 0, 0, 0, 228, 0, 0, 0, 125, 0, 0, 0, 192, 0, 0, 0, 112, 0, 0, 0, 145, 0, 0, 0, 163, +0, 0, 0, 252, 0, 0, 0, 236, 0, 0, 0, 78, 0, 0, 0, 98, 0, 0, 0, 18, 0, 0, 0, 55, 0, 0, 0, 106, 0, 0, 0, 48, 0, 0, 0, 246, 0, 0, 0, 30, 0, 0, 0, 251, 0, 0, 0, 20, 0, 0, 0, 92, 0, 0, 0, 13, 0, 0, 0, 14, 0, 0, 0, 183, 0, 0, 0, 129, 0, 0, 0, 106, 0, 0, 0, 231, 0, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 172, 0, 0, 0, 170, 0, 0, 0, 56, 0, 0, 0, 70, 0, 0, 0, 226, 0, 0, 0, 115, 0, 0, 0, 234, 0, 0, 0, 75, 0, 0, 0, 7, 0, 0, 0, 129, 0, 0, 0, 67, 0, 0, 0, 124, 0, 0, 0, 158, 0, 0, 0, 94, 0, 0, 0, 252, 0, 0, 0, 249, 0, 0, +0, 33, 0, 0, 0, 79, 0, 0, 0, 46, 0, 0, 0, 118, 0, 0, 0, 155, 0, 0, 0, 31, 0, 0, 0, 40, 0, 0, 0, 96, 0, 0, 0, 119, 0, 0, 0, 67, 0, 0, 0, 50, 0, 0, 0, 157, 0, 0, 0, 190, 0, 0, 0, 23, 0, 0, 0, 48, 0, 0, 0, 42, 0, 0, 0, 198, 0, 0, 0, 24, 0, 0, 0, 146, 0, 0, 0, 102, 0, 0, 0, 98, 0, 0, 0, 48, 0, 0, 0, 152, 0, 0, 0, 64, 0, 0, 0, 17, 0, 0, 0, 166, 0, 0, 0, 127, 0, 0, 0, 24, 0, 0, 0, 132, 0, 0, 0, 40, 0, 0, 0, 63, 0, 0, 0, 171, 0, 0, 0, 211, 0, 0, 0, 244, 0, 0, 0, 138, 0, 0, 0, 118, 0, 0, 0, 161, 0, 0, 0, +60, 0, 0, 0, 202, 0, 0, 0, 45, 0, 0, 0, 73, 0, 0, 0, 195, 0, 0, 0, 234, 0, 0, 0, 8, 0, 0, 0, 11, 0, 0, 0, 133, 0, 0, 0, 23, 0, 0, 0, 42, 0, 0, 0, 195, 0, 0, 0, 108, 0, 0, 0, 8, 0, 0, 0, 253, 0, 0, 0, 87, 0, 0, 0, 159, 0, 0, 0, 61, 0, 0, 0, 95, 0, 0, 0, 223, 0, 0, 0, 103, 0, 0, 0, 104, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 81, 0, 0, 0, 96, 0, 0, 0, 27, 0, 0, 0, 6, 0, 0, 0, 79, 0, 0, 0, 138, 0, 0, 0, 33, 0, 0, 0, 186, 0, 0, 0, 56, 0, 0, 0, 168, 0, 0, 0, 186, 0, 0, 0, 214, 0, 0, 0, 64, 0, 0, +0, 246, 0, 0, 0, 233, 0, 0, 0, 155, 0, 0, 0, 118, 0, 0, 0, 77, 0, 0, 0, 86, 0, 0, 0, 33, 0, 0, 0, 91, 0, 0, 0, 10, 0, 0, 0, 155, 0, 0, 0, 46, 0, 0, 0, 79, 0, 0, 0, 61, 0, 0, 0, 129, 0, 0, 0, 50, 0, 0, 0, 8, 0, 0, 0, 159, 0, 0, 0, 151, 0, 0, 0, 91, 0, 0, 0, 229, 0, 0, 0, 68, 0, 0, 0, 236, 0, 0, 0, 6, 0, 0, 0, 157, 0, 0, 0, 144, 0, 0, 0, 121, 0, 0, 0, 159, 0, 0, 0, 211, 0, 0, 0, 224, 0, 0, 0, 121, 0, 0, 0, 175, 0, 0, 0, 143, 0, 0, 0, 16, 0, 0, 0, 253, 0, 0, 0, 221, 0, 0, 0, 4, 0, 0, 0, 174, 0, 0, 0, +39, 0, 0, 0, 151, 0, 0, 0, 70, 0, 0, 0, 51, 0, 0, 0, 121, 0, 0, 0, 234, 0, 0, 0, 184, 0, 0, 0, 78, 0, 0, 0, 202, 0, 0, 0, 90, 0, 0, 0, 89, 0, 0, 0, 87, 0, 0, 0, 225, 0, 0, 0, 14, 0, 0, 0, 26, 0, 0, 0, 218, 0, 0, 0, 243, 0, 0, 0, 165, 0, 0, 0, 65, 0, 0, 0, 67, 0, 0, 0, 40, 0, 0, 0, 252, 0, 0, 0, 126, 0, 0, 0, 231, 0, 0, 0, 113, 0, 0, 0, 234, 0, 0, 0, 198, 0, 0, 0, 59, 0, 0, 0, 89, 0, 0, 0, 204, 0, 0, 0, 46, 0, 0, 0, 211, 0, 0, 0, 64, 0, 0, 0, 236, 0, 0, 0, 179, 0, 0, 0, 19, 0, 0, 0, 111, 0, 0, 0, +68, 0, 0, 0, 205, 0, 0, 0, 19, 0, 0, 0, 178, 0, 0, 0, 55, 0, 0, 0, 242, 0, 0, 0, 110, 0, 0, 0, 217, 0, 0, 0, 28, 0, 0, 0, 227, 0, 0, 0, 219, 0, 0, 0, 96, 0, 0, 0, 205, 0, 0, 0, 92, 0, 0, 0, 74, 0, 0, 0, 24, 0, 0, 0, 15, 0, 0, 0, 239, 0, 0, 0, 115, 0, 0, 0, 54, 0, 0, 0, 113, 0, 0, 0, 140, 0, 0, 0, 246, 0, 0, 0, 17, 0, 0, 0, 180, 0, 0, 0, 216, 0, 0, 0, 206, 0, 0, 0, 23, 0, 0, 0, 94, 0, 0, 0, 79, 0, 0, 0, 38, 0, 0, 0, 119, 0, 0, 0, 151, 0, 0, 0, 95, 0, 0, 0, 203, 0, 0, 0, 239, 0, 0, 0, 145, 0, 0, 0, +235, 0, 0, 0, 106, 0, 0, 0, 98, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 74, 0, 0, 0, 162, 0, 0, 0, 151, 0, 0, 0, 8, 0, 0, 0, 129, 0, 0, 0, 45, 0, 0, 0, 131, 0, 0, 0, 196, 0, 0, 0, 204, 0, 0, 0, 240, 0, 0, 0, 131, 0, 0, 0, 126, 0, 0, 0, 236, +0, 0, 0, 13, 0, 0, 0, 149, 0, 0, 0, 76, 0, 0, 0, 91, 0, 0, 0, 251, 0, 0, 0, 250, 0, 0, 0, 152, 0, 0, 0, 128, 0, 0, 0, 74, 0, 0, 0, 102, 0, 0, 0, 86, 0, 0, 0, 12, 0, 0, 0, 81, 0, 0, 0, 179, 0, 0, 0, 242, 0, 0, 0, 4, 0, 0, 0, 93, 0, 0, 0, 39, 0, 0, 0, 59, 0, 0, 0, 185, 0, 0, 0, 184, 0, 0, 0, 6, 0, 0, 0, 90, 0, 0, 0, 46, 0, 0, 0, 254, 0, 0, 0, 195, 0, 0, 0, 130, 0, 0, 0, 55, 0, 0, 0, 156, 0, 0, 0, 163, 0, 0, 0, 17, 0, 0, 0, 31, 0, 0, 0, 156, 0, 0, 0, 166, 0, 0, 0, 218, 0, 0, 0, 99, 0, 0, 0, 72, 0, 0, +0, 155, 0, 0, 0, 173, 0, 0, 0, 222, 0, 0, 0, 45, 0, 0, 0, 166, 0, 0, 0, 188, 0, 0, 0, 110, 0, 0, 0, 50, 0, 0, 0, 218, 0, 0, 0, 39, 0, 0, 0, 101, 0, 0, 0, 221, 0, 0, 0, 87, 0, 0, 0, 132, 0, 0, 0, 79, 0, 0, 0, 55, 0, 0, 0, 49, 0, 0, 0, 125, 0, 0, 0, 46, 0, 0, 0, 188, 0, 0, 0, 173, 0, 0, 0, 135, 0, 0, 0, 7, 0, 0, 0, 42, 0, 0, 0, 107, 0, 0, 0, 55, 0, 0, 0, 252, 0, 0, 0, 95, 0, 0, 0, 235, 0, 0, 0, 78, 0, 0, 0, 117, 0, 0, 0, 53, 0, 0, 0, 166, 0, 0, 0, 222, 0, 0, 0, 171, 0, 0, 0, 10, 0, 0, 0, 25, 0, 0, +0, 58, 0, 0, 0, 183, 0, 0, 0, 177, 0, 0, 0, 239, 0, 0, 0, 146, 0, 0, 0, 106, 0, 0, 0, 59, 0, 0, 0, 60, 0, 0, 0, 59, 0, 0, 0, 178, 0, 0, 0, 148, 0, 0, 0, 109, 0, 0, 0, 57, 0, 0, 0, 96, 0, 0, 0, 172, 0, 0, 0, 238, 0, 0, 0, 231, 0, 0, 0, 129, 0, 0, 0, 26, 0, 0, 0, 59, 0, 0, 0, 118, 0, 0, 0, 135, 0, 0, 0, 92, 0, 0, 0, 5, 0, 0, 0, 148, 0, 0, 0, 42, 0, 0, 0, 69, 0, 0, 0, 185, 0, 0, 0, 128, 0, 0, 0, 233, 0, 0, 0, 34, 0, 0, 0, 177, 0, 0, 0, 7, 0, 0, 0, 203, 0, 0, 0, 64, 0, 0, 0, 158, 0, 0, 0, 112, 0, 0, +0, 73, 0, 0, 0, 109, 0, 0, 0, 18, 0, 0, 0, 253, 0, 0, 0, 24, 0, 0, 0, 120, 0, 0, 0, 132, 0, 0, 0, 168, 0, 0, 0, 76, 0, 0, 0, 125, 0, 0, 0, 110, 0, 0, 0, 89, 0, 0, 0, 166, 0, 0, 0, 229, 0, 0, 0, 116, 0, 0, 0, 241, 0, 0, 0, 25, 0, 0, 0, 166, 0, 0, 0, 132, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 193, 0, 0, 0, 41, 0, 0, 0, 19, 0, 0, 0, 242, 0, 0, 0, 20, 0, 0, 0, 107, 0, 0, 0, 93, 0, 0, 0, 83, 0, 0, 0, 81, 0, 0, 0, 247, 0, 0, 0, 239, 0, 0, 0, 191, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 164, 0, 0, 0, 75, 0, 0, 0, +98, 0, 0, 0, 76, 0, 0, 0, 230, 0, 0, 0, 253, 0, 0, 0, 114, 0, 0, 0, 7, 0, 0, 0, 242, 0, 0, 0, 129, 0, 0, 0, 252, 0, 0, 0, 242, 0, 0, 0, 189, 0, 0, 0, 18, 0, 0, 0, 124, 0, 0, 0, 104, 0, 0, 0, 118, 0, 0, 0, 42, 0, 0, 0, 186, 0, 0, 0, 245, 0, 0, 0, 101, 0, 0, 0, 177, 0, 0, 0, 31, 0, 0, 0, 23, 0, 0, 0, 10, 0, 0, 0, 56, 0, 0, 0, 176, 0, 0, 0, 191, 0, 0, 0, 192, 0, 0, 0, 248, 0, 0, 0, 244, 0, 0, 0, 42, 0, 0, 0, 85, 0, 0, 0, 96, 0, 0, 0, 85, 0, 0, 0, 91, 0, 0, 0, 228, 0, 0, 0, 29, 0, 0, 0, 113, 0, 0, 0, +76, 0, 0, 0, 157, 0, 0, 0, 91, 0, 0, 0, 159, 0, 0, 0, 112, 0, 0, 0, 166, 0, 0, 0, 133, 0, 0, 0, 154, 0, 0, 0, 44, 0, 0, 0, 160, 0, 0, 0, 226, 0, 0, 0, 50, 0, 0, 0, 72, 0, 0, 0, 206, 0, 0, 0, 158, 0, 0, 0, 42, 0, 0, 0, 165, 0, 0, 0, 7, 0, 0, 0, 59, 0, 0, 0, 199, 0, 0, 0, 108, 0, 0, 0, 134, 0, 0, 0, 119, 0, 0, 0, 222, 0, 0, 0, 60, 0, 0, 0, 247, 0, 0, 0, 24, 0, 0, 0, 122, 0, 0, 0, 150, 0, 0, 0, 126, 0, 0, 0, 67, 0, 0, 0, 87, 0, 0, 0, 169, 0, 0, 0, 85, 0, 0, 0, 252, 0, 0, 0, 78, 0, 0, 0, 182, 0, 0, 0, +114, 0, 0, 0, 0, 0, 0, 0, 242, 0, 0, 0, 228, 0, 0, 0, 215, 0, 0, 0, 82, 0, 0, 0, 211, 0, 0, 0, 211, 0, 0, 0, 182, 0, 0, 0, 133, 0, 0, 0, 246, 0, 0, 0, 113, 0, 0, 0, 199, 0, 0, 0, 68, 0, 0, 0, 63, 0, 0, 0, 127, 0, 0, 0, 215, 0, 0, 0, 179, 0, 0, 0, 242, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0, 202, 0, 0, 0, 167, 0, 0, 0, 85, 0, 0, 0, 123, 0, 0, 0, 121, 0, 0, 0, 243, 0, 0, 0, 202, 0, 0, 0, 90, 0, 0, 0, 101, 0, 0, 0, 246, 0, 0, 0, 237, 0, 0, 0, 80, 0, 0, 0, 20, 0, 0, 0, 123, 0, 0, 0, 228, 0, 0, 0, 196, 0, 0, 0, 42, 0, 0, 0, 101, 0, 0, 0, 158, 0, 0, 0, 226, 0, 0, 0, 249, 0, 0, 0, 202, 0, 0, 0, 167, 0, 0, 0, 34, 0, 0, 0, 38, 0, 0, 0, 83, 0, 0, 0, 203, 0, 0, 0, 33, 0, 0, 0, 91, 0, 0, 0, 167, 0, 0, 0, 49, 0, 0, 0, 144, 0, 0, 0, 215, 0, 0, 0, +197, 0, 0, 0, 38, 0, 0, 0, 8, 0, 0, 0, 189, 0, 0, 0, 176, 0, 0, 0, 83, 0, 0, 0, 99, 0, 0, 0, 88, 0, 0, 0, 195, 0, 0, 0, 49, 0, 0, 0, 94, 0, 0, 0, 117, 0, 0, 0, 70, 0, 0, 0, 21, 0, 0, 0, 145, 0, 0, 0, 166, 0, 0, 0, 248, 0, 0, 0, 47, 0, 0, 0, 26, 0, 0, 0, 8, 0, 0, 0, 101, 0, 0, 0, 136, 0, 0, 0, 47, 0, 0, 0, 152, 0, 0, 0, 4, 0, 0, 0, 241, 0, 0, 0, 124, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 0, 129, 0, 0, 0, 33, 0, 0, 0, 97, 0, 0, 0, 9, 0, 0, 0, 246, 0, 0, 0, 78, 0, 0, 0, 241, 0, 0, 0, 146, 0, +0, 0, 238, 0, 0, 0, 99, 0, 0, 0, 97, 0, 0, 0, 115, 0, 0, 0, 135, 0, 0, 0, 199, 0, 0, 0, 84, 0, 0, 0, 14, 0, 0, 0, 66, 0, 0, 0, 75, 0, 0, 0, 201, 0, 0, 0, 71, 0, 0, 0, 209, 0, 0, 0, 184, 0, 0, 0, 126, 0, 0, 0, 145, 0, 0, 0, 117, 0, 0, 0, 55, 0, 0, 0, 153, 0, 0, 0, 40, 0, 0, 0, 184, 0, 0, 0, 221, 0, 0, 0, 127, 0, 0, 0, 80, 0, 0, 0, 137, 0, 0, 0, 143, 0, 0, 0, 192, 0, 0, 0, 190, 0, 0, 0, 93, 0, 0, 0, 214, 0, 0, 0, 159, 0, 0, 0, 160, 0, 0, 0, 240, 0, 0, 0, 157, 0, 0, 0, 129, 0, 0, 0, 206, 0, 0, 0, 58, +0, 0, 0, 123, 0, 0, 0, 152, 0, 0, 0, 88, 0, 0, 0, 187, 0, 0, 0, 215, 0, 0, 0, 120, 0, 0, 0, 200, 0, 0, 0, 63, 0, 0, 0, 19, 0, 0, 0, 241, 0, 0, 0, 116, 0, 0, 0, 25, 0, 0, 0, 223, 0, 0, 0, 248, 0, 0, 0, 152, 0, 0, 0, 137, 0, 0, 0, 93, 0, 0, 0, 250, 0, 0, 0, 95, 0, 0, 0, 158, 0, 0, 0, 53, 0, 0, 0, 133, 0, 0, 0, 148, 0, 0, 0, 71, 0, 0, 0, 31, 0, 0, 0, 144, 0, 0, 0, 21, 0, 0, 0, 38, 0, 0, 0, 208, 0, 0, 0, 132, 0, 0, 0, 237, 0, 0, 0, 138, 0, 0, 0, 128, 0, 0, 0, 247, 0, 0, 0, 99, 0, 0, 0, 66, 0, 0, 0, 134, +0, 0, 0, 39, 0, 0, 0, 215, 0, 0, 0, 244, 0, 0, 0, 117, 0, 0, 0, 88, 0, 0, 0, 220, 0, 0, 0, 156, 0, 0, 0, 192, 0, 0, 0, 34, 0, 0, 0, 126, 0, 0, 0, 32, 0, 0, 0, 53, 0, 0, 0, 253, 0, 0, 0, 31, 0, 0, 0, 104, 0, 0, 0, 14, 0, 0, 0, 111, 0, 0, 0, 151, 0, 0, 0, 186, 0, 0, 0, 112, 0, 0, 0, 187, 0, 0, 0, 163, 0, 0, 0, 14, 0, 0, 0, 229, 0, 0, 0, 11, 0, 0, 0, 18, 0, 0, 0, 244, 0, 0, 0, 162, 0, 0, 0, 220, 0, 0, 0, 71, 0, 0, 0, 248, 0, 0, 0, 230, 0, 0, 0, 208, 0, 0, 0, 35, 0, 0, 0, 108, 0, 0, 0, 51, 0, 0, 0, 168, +0, 0, 0, 153, 0, 0, 0, 70, 0, 0, 0, 110, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 186, 0, 0, 0, 118, 0, 0, 0, 72, 0, 0, 0, 15, 0, 0, 0, 163, 0, 0, 0, 42, 0, 0, 0, 97, 0, 0, 0, 55, 0, 0, 0, 226, 0, 0, 0, 89, 0, 0, 0, 18, 0, 0, 0, 14, 0, 0, 0, 39, 0, 0, 0, 186, 0, 0, 0, 100, 0, 0, 0, 67, 0, 0, 0, 174, 0, 0, 0, 192, 0, 0, 0, 66, 0, 0, 0, 105, 0, 0, 0, 121, 0, 0, 0, 164, 0, 0, 0, 30, 0, 0, 0, 41, 0, 0, 0, 139, 0, 0, 0, 21, 0, 0, 0, 235, 0, 0, 0, 248, 0, 0, 0, 175, 0, 0, 0, 212, 0, 0, 0, 162, 0, 0, 0, 104, +0, 0, 0, 51, 0, 0, 0, 181, 0, 0, 0, 122, 0, 0, 0, 36, 0, 0, 0, 44, 0, 0, 0, 25, 0, 0, 0, 51, 0, 0, 0, 221, 0, 0, 0, 27, 0, 0, 0, 171, 0, 0, 0, 236, 0, 0, 0, 1, 0, 0, 0, 176, 0, 0, 0, 35, 0, 0, 0, 248, 0, 0, 0, 66, 0, 0, 0, 43, 0, 0, 0, 6, 0, 0, 0, 136, 0, 0, 0, 234, 0, 0, 0, 61, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 120, 0, 0, 0, 69, 0, 0, 0, 77, 0, 0, 0, 56, 0, 0, 0, 237, 0, 0, 0, 46, 0, 0, 0, 46, 0, 0, 0, 68, 0, 0, 0, 73, 0, 0, 0, 237, 0, 0, 0, 203, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 104, 0, 0, 0, 232, 0, 0, 0, 65, 0, 0, 0, 143, 0, 0, 0, 145, 0, 0, 0, 248, 0, 0, 0, 17, 0, 0, 0, 19, 0, 0, 0, 144, 0, 0, 0, 46, 0, 0, 0, 167, 0, 0, 0, 171, 0, 0, 0, 48, 0, 0, 0, 239, 0, 0, 0, 173, 0, 0, 0, 160, 0, 0, 0, 97, 0, 0, 0, 0, +0, 0, 0, 136, 0, 0, 0, 239, 0, 0, 0, 219, 0, 0, 0, 206, 0, 0, 0, 91, 0, 0, 0, 92, 0, 0, 0, 187, 0, 0, 0, 98, 0, 0, 0, 200, 0, 0, 0, 86, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0, 115, 0, 0, 0, 63, 0, 0, 0, 96, 0, 0, 0, 193, 0, 0, 0, 130, 0, 0, 0, 45, 0, 0, 0, 163, 0, 0, 0, 40, 0, 0, 0, 88, 0, 0, 0, 36, 0, 0, 0, 158, 0, 0, 0, 159, 0, 0, 0, 227, 0, 0, 0, 112, 0, 0, 0, 204, 0, 0, 0, 9, 0, 0, 0, 78, 0, 0, 0, 26, 0, 0, 0, 63, 0, 0, 0, 17, 0, 0, 0, 17, 0, 0, 0, 21, 0, 0, 0, 7, 0, 0, 0, 60, 0, 0, 0, 164, 0, 0, +0, 65, 0, 0, 0, 224, 0, 0, 0, 101, 0, 0, 0, 163, 0, 0, 0, 10, 0, 0, 0, 65, 0, 0, 0, 109, 0, 0, 0, 17, 0, 0, 0, 49, 0, 0, 0, 64, 0, 0, 0, 1, 0, 0, 0, 82, 0, 0, 0, 86, 0, 0, 0, 148, 0, 0, 0, 91, 0, 0, 0, 40, 0, 0, 0, 138, 0, 0, 0, 170, 0, 0, 0, 82, 0, 0, 0, 238, 0, 0, 0, 216, 0, 0, 0, 10, 0, 0, 0, 5, 0, 0, 0, 141, 0, 0, 0, 205, 0, 0, 0, 181, 0, 0, 0, 170, 0, 0, 0, 46, 0, 0, 0, 56, 0, 0, 0, 170, 0, 0, 0, 183, 0, 0, 0, 135, 0, 0, 0, 247, 0, 0, 0, 43, 0, 0, 0, 251, 0, 0, 0, 4, 0, 0, 0, 203, 0, 0, 0, 132, +0, 0, 0, 61, 0, 0, 0, 84, 0, 0, 0, 32, 0, 0, 0, 239, 0, 0, 0, 89, 0, 0, 0, 222, 0, 0, 0, 164, 0, 0, 0, 43, 0, 0, 0, 147, 0, 0, 0, 110, 0, 0, 0, 46, 0, 0, 0, 236, 0, 0, 0, 66, 0, 0, 0, 154, 0, 0, 0, 212, 0, 0, 0, 45, 0, 0, 0, 244, 0, 0, 0, 70, 0, 0, 0, 88, 0, 0, 0, 39, 0, 0, 0, 43, 0, 0, 0, 24, 0, 0, 0, 143, 0, 0, 0, 131, 0, 0, 0, 61, 0, 0, 0, 105, 0, 0, 0, 158, 0, 0, 0, 212, 0, 0, 0, 62, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 253, 0, 0, 0, 88, 0, 0, 0, 3, 0, 0, 0, 51, 0, 0, 0, 137, 0, 0, 0, 201, 0, +0, 0, 99, 0, 0, 0, 98, 0, 0, 0, 28, 0, 0, 0, 23, 0, 0, 0, 180, 0, 0, 0, 96, 0, 0, 0, 196, 0, 0, 0, 38, 0, 0, 0, 104, 0, 0, 0, 9, 0, 0, 0, 195, 0, 0, 0, 46, 0, 0, 0, 55, 0, 0, 0, 15, 0, 0, 0, 123, 0, 0, 0, 180, 0, 0, 0, 156, 0, 0, 0, 182, 0, 0, 0, 249, 0, 0, 0, 251, 0, 0, 0, 212, 0, 0, 0, 81, 0, 0, 0, 120, 0, 0, 0, 200, 0, 0, 0, 99, 0, 0, 0, 234, 0, 0, 0, 119, 0, 0, 0, 71, 0, 0, 0, 7, 0, 0, 0, 50, 0, 0, 0, 180, 0, 0, 0, 24, 0, 0, 0, 71, 0, 0, 0, 121, 0, 0, 0, 203, 0, 0, 0, 212, 0, 0, 0, 90, 0, 0, +0, 7, 0, 0, 0, 20, 0, 0, 0, 15, 0, 0, 0, 160, 0, 0, 0, 213, 0, 0, 0, 172, 0, 0, 0, 208, 0, 0, 0, 65, 0, 0, 0, 64, 0, 0, 0, 171, 0, 0, 0, 97, 0, 0, 0, 35, 0, 0, 0, 229, 0, 0, 0, 42, 0, 0, 0, 42, 0, 0, 0, 111, 0, 0, 0, 247, 0, 0, 0, 168, 0, 0, 0, 212, 0, 0, 0, 118, 0, 0, 0, 239, 0, 0, 0, 231, 0, 0, 0, 69, 0, 0, 0, 108, 0, 0, 0, 161, 0, 0, 0, 94, 0, 0, 0, 96, 0, 0, 0, 79, 0, 0, 0, 251, 0, 0, 0, 225, 0, 0, 0, 112, 0, 0, 0, 106, 0, 0, 0, 31, 0, 0, 0, 85, 0, 0, 0, 79, 0, 0, 0, 9, 0, 0, 0, 180, 0, 0, 0, +149, 0, 0, 0, 51, 0, 0, 0, 54, 0, 0, 0, 198, 0, 0, 0, 129, 0, 0, 0, 1, 0, 0, 0, 24, 0, 0, 0, 6, 0, 0, 0, 37, 0, 0, 0, 39, 0, 0, 0, 164, 0, 0, 0, 180, 0, 0, 0, 36, 0, 0, 0, 164, 0, 0, 0, 134, 0, 0, 0, 3, 0, 0, 0, 76, 0, 0, 0, 172, 0, 0, 0, 2, 0, 0, 0, 119, 0, 0, 0, 56, 0, 0, 0, 222, 0, 0, 0, 215, 0, 0, 0, 96, 0, 0, 0, 72, 0, 0, 0, 7, 0, 0, 0, 240, 0, 0, 0, 116, 0, 0, 0, 168, 0, 0, 0, 255, 0, 0, 0, 84, 0, 0, 0, 229, 0, 0, 0, 48, 0, 0, 0, 67, 0, 0, 0, 255, 0, 0, 0, 119, 0, 0, 0, 251, 0, 0, 0, 33, 0, +0, 0, 7, 0, 0, 0, 255, 0, 0, 0, 178, 0, 0, 0, 7, 0, 0, 0, 107, 0, 0, 0, 228, 0, 0, 0, 229, 0, 0, 0, 48, 0, 0, 0, 252, 0, 0, 0, 25, 0, 0, 0, 108, 0, 0, 0, 163, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 197, 0, 0, 0, 44, 0, 0, 0, 172, 0, 0, 0, +211, 0, 0, 0, 131, 0, 0, 0, 130, 0, 0, 0, 124, 0, 0, 0, 41, 0, 0, 0, 247, 0, 0, 0, 5, 0, 0, 0, 165, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 31, 0, 0, 0, 134, 0, 0, 0, 85, 0, 0, 0, 244, 0, 0, 0, 214, 0, 0, 0, 47, 0, 0, 0, 12, 0, 0, 0, 153, 0, 0, 0, 208, 0, 0, 0, 101, 0, 0, 0, 155, 0, 0, 0, 107, 0, 0, 0, 70, 0, 0, 0, 13, 0, 0, 0, 67, 0, 0, 0, 248, 0, 0, 0, 22, 0, 0, 0, 40, 0, 0, 0, 30, 0, 0, 0, 127, 0, 0, 0, 180, 0, 0, 0, 116, 0, 0, 0, 126, 0, 0, 0, 177, 0, 0, 0, 137, 0, 0, 0, 79, 0, 0, 0, 24, 0, 0, 0, +90, 0, 0, 0, 171, 0, 0, 0, 100, 0, 0, 0, 6, 0, 0, 0, 223, 0, 0, 0, 69, 0, 0, 0, 135, 0, 0, 0, 224, 0, 0, 0, 106, 0, 0, 0, 198, 0, 0, 0, 240, 0, 0, 0, 14, 0, 0, 0, 201, 0, 0, 0, 36, 0, 0, 0, 53, 0, 0, 0, 56, 0, 0, 0, 234, 0, 0, 0, 48, 0, 0, 0, 84, 0, 0, 0, 180, 0, 0, 0, 196, 0, 0, 0, 82, 0, 0, 0, 84, 0, 0, 0, 233, 0, 0, 0, 159, 0, 0, 0, 220, 0, 0, 0, 63, 0, 0, 0, 193, 0, 0, 0, 137, 0, 0, 0, 68, 0, 0, 0, 116, 0, 0, 0, 39, 0, 0, 0, 228, 0, 0, 0, 193, 0, 0, 0, 144, 0, 0, 0, 255, 0, 0, 0, 74, 0, 0, 0, +167, 0, 0, 0, 60, 0, 0, 0, 238, 0, 0, 0, 205, 0, 0, 0, 244, 0, 0, 0, 29, 0, 0, 0]).concat([37, 0, 0, 0, 148, 0, 0, 0, 127, 0, 0, 0, 99, 0, 0, 0, 22, 0, 0, 0, 72, 0, 0, 0, 188, 0, 0, 0, 100, 0, 0, 0, 254, 0, 0, 0, 149, 0, 0, 0, 196, 0, 0, 0, 12, 0, 0, 0, 139, 0, 0, 0, 25, 0, 0, 0, 117, 0, 0, 0, 110, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 94, 0, 0, 0, 106, 0, 0, 0, 111, 0, 0, 0, 26, 0, 0, 0, 140, 0, 0, 0, 227, 0, 0, 0, 211, 0, 0, 0, 40, 0, 0, 0, 242, 0, 0, 0, 224, 0, 0, 0, 185, 0, 0, 0, 122, 0, 0, 0, 67, +0, 0, 0, 105, 0, 0, 0, 230, 0, 0, 0, 211, 0, 0, 0, 192, 0, 0, 0, 254, 0, 0, 0, 126, 0, 0, 0, 151, 0, 0, 0, 171, 0, 0, 0, 108, 0, 0, 0, 123, 0, 0, 0, 142, 0, 0, 0, 19, 0, 0, 0, 66, 0, 0, 0, 212, 0, 0, 0, 202, 0, 0, 0, 112, 0, 0, 0, 61, 0, 0, 0, 171, 0, 0, 0, 251, 0, 0, 0, 95, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 204, 0, 0, 0, 119, 0, 0, 0, 34, 0, 0, 0, 248, 0, 0, 0, 120, 0, 0, 0, 85, 0, 0, 0, 174, 0, 0, 0, 98, 0, 0, 0, 53, 0, 0, 0, 251, 0, 0, 0, 154, 0, 0, 0, 198, 0, 0, 0, 3, 0, 0, 0, 228, +0, 0, 0, 12, 0, 0, 0, 238, 0, 0, 0, 171, 0, 0, 0, 199, 0, 0, 0, 192, 0, 0, 0, 137, 0, 0, 0, 135, 0, 0, 0, 84, 0, 0, 0, 50, 0, 0, 0, 173, 0, 0, 0, 174, 0, 0, 0, 133, 0, 0, 0, 88, 0, 0, 0, 67, 0, 0, 0, 184, 0, 0, 0, 177, 0, 0, 0, 230, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0, 0, 120, 0, 0, 0, 136, 0, 0, 0, 86, 0, 0, 0, 219, 0, 0, 0, 156, 0, 0, 0, 252, 0, 0, 0, 121, 0, 0, 0, 246, 0, 0, 0, 249, 0, 0, 0, 65, 0, 0, 0, 95, 0, 0, 0, 183, 0, 0, 0, 188, 0, 0, 0, 17, 0, 0, 0, 249, 0, 0, 0, 32, 0, 0, 0, 54, +0, 0, 0, 28, 0, 0, 0, 83, 0, 0, 0, 43, 0, 0, 0, 90, 0, 0, 0, 32, 0, 0, 0, 91, 0, 0, 0, 161, 0, 0, 0, 165, 0, 0, 0, 68, 0, 0, 0, 145, 0, 0, 0, 36, 0, 0, 0, 2, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 100, 0, 0, 0, 184, 0, 0, 0, 85, 0, 0, 0, 246, 0, 0, 0, 222, 0, 0, 0, 44, 0, 0, 0, 219, 0, 0, 0, 71, 0, 0, 0, 184, 0, 0, 0, 198, 0, 0, 0, 10, 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 120, 0, 0, 0, 147, 0, 0, 0, 216, 0, 0, 0, 245, 0, 0, 0, 245, 0, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0, 10, 0, 0, 0, 214, 0, 0, 0, 27, 0, 0, +0, 154, 0, 0, 0, 108, 0, 0, 0, 229, 0, 0, 0, 70, 0, 0, 0, 234, 0, 0, 0, 112, 0, 0, 0, 150, 0, 0, 0, 141, 0, 0, 0, 78, 0, 0, 0, 42, 0, 0, 0, 82, 0, 0, 0, 33, 0, 0, 0, 38, 0, 0, 0, 75, 0, 0, 0, 177, 0, 0, 0, 187, 0, 0, 0, 15, 0, 0, 0, 124, 0, 0, 0, 169, 0, 0, 0, 155, 0, 0, 0, 4, 0, 0, 0, 187, 0, 0, 0, 81, 0, 0, 0, 8, 0, 0, 0, 241, 0, 0, 0, 154, 0, 0, 0, 164, 0, 0, 0, 118, 0, 0, 0, 124, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 148, 0, 0, 0, 247, 0, 0, 0, 64, 0, 0, 0, 208, 0, 0, 0, 215, 0, 0, 0, 235, 0, 0, 0, 169, 0, 0, 0, 130, 0, 0, 0, 54, 0, 0, 0, 213, 0, 0, 0, 21, 0, 0, 0, 185, 0, 0, 0, 51, 0, 0, 0, 122, 0, 0, 0, 191, 0, 0, 0, 138, 0, 0, 0, 242, 0, 0, 0, 99, 0, 0, 0, 170, 0, 0, 0, 55, 0, 0, 0, 245, 0, 0, 0, 89, 0, 0, 0, 172, 0, 0, 0, +189, 0, 0, 0, 187, 0, 0, 0, 50, 0, 0, 0, 54, 0, 0, 0, 190, 0, 0, 0, 115, 0, 0, 0, 153, 0, 0, 0, 56, 0, 0, 0, 44, 0, 0, 0, 179, 0, 0, 0, 218, 0, 0, 0, 122, 0, 0, 0, 216, 0, 0, 0, 61, 0, 0, 0, 153, 0, 0, 0, 202, 0, 0, 0, 210, 0, 0, 0, 244, 0, 0, 0, 218, 0, 0, 0, 153, 0, 0, 0, 142, 0, 0, 0, 79, 0, 0, 0, 152, 0, 0, 0, 183, 0, 0, 0, 244, 0, 0, 0, 174, 0, 0, 0, 62, 0, 0, 0, 159, 0, 0, 0, 142, 0, 0, 0, 53, 0, 0, 0, 96, 0, 0, 0, 164, 0, 0, 0, 51, 0, 0, 0, 117, 0, 0, 0, 164, 0, 0, 0, 4, 0, 0, 0, 147, 0, 0, +0, 177, 0, 0, 0, 107, 0, 0, 0, 77, 0, 0, 0, 151, 0, 0, 0, 157, 0, 0, 0, 168, 0, 0, 0, 205, 0, 0, 0, 151, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 185, 0, 0, 0, 231, 0, 0, 0, 165, 0, 0, 0, 239, 0, 0, 0, 253, 0, 0, 0, 168, 0, 0, 0, 66, 0, 0, 0, 107, 0, 0, 0, 195, 0, 0, 0, 98, 0, 0, 0, 100, 0, 0, 0, 125, 0, 0, 0, 165, 0, 0, 0, 27, 0, 0, 0, 201, 0, 0, 0, 158, 0, 0, 0, 210, 0, 0, 0, 69, 0, 0, 0, 185, 0, 0, 0, 238, 0, 0, 0, 3, 0, 0, 0, 176, 0, 0, 0, 191, 0, 0, 0, 192, 0, 0, 0, 104, 0, 0, 0, 237, 0, 0, 0, 183, +0, 0, 0, 132, 0, 0, 0, 44, 0, 0, 0, 246, 0, 0, 0, 211, 0, 0, 0, 161, 0, 0, 0, 107, 0, 0, 0, 36, 0, 0, 0, 109, 0, 0, 0, 135, 0, 0, 0, 86, 0, 0, 0, 151, 0, 0, 0, 89, 0, 0, 0, 121, 0, 0, 0, 98, 0, 0, 0, 159, 0, 0, 0, 172, 0, 0, 0, 237, 0, 0, 0, 243, 0, 0, 0, 201, 0, 0, 0, 137, 0, 0, 0, 33, 0, 0, 0, 46, 0, 0, 0, 4, 0, 0, 0, 179, 0, 0, 0, 204, 0, 0, 0, 47, 0, 0, 0, 190, 0, 0, 0, 214, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0, 57, 0, 0, 0, 97, 0, 0, 0, 5, 0, 0, 0, 237, 0, 0, 0, 37, 0, 0, 0, 137, 0, 0, 0, 139, +0, 0, 0, 93, 0, 0, 0, 27, 0, 0, 0, 203, 0, 0, 0, 12, 0, 0, 0, 85, 0, 0, 0, 244, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 70, 0, 0, 0, 232, 0, 0, 0, 30, 0, 0, 0, 198, 0, 0, 0, 131, 0, 0, 0, 200, 0, 0, 0, 90, 0, 0, 0, 118, 0, 0, 0, 219, 0, 0, 0, 204, 0, 0, 0, 25, 0, 0, 0, 122, 0, 0, 0, 204, 0, 0, 0, 103, 0, 0, 0, 70, 0, 0, 0, 11, 0, 0, 0, 83, 0, 0, 0, 207, 0, 0, 0, 194, 0, 0, 0, 161, 0, 0, 0, 173, 0, 0, 0, 106, 0, 0, 0, 243, 0, 0, 0, 205, 0, 0, 0, 143, 0, 0, 0, 201, 0, 0, 0, 222, 0, 0, 0, 28, +0, 0, 0, 248, 0, 0, 0, 108, 0, 0, 0, 143, 0, 0, 0, 248, 0, 0, 0, 118, 0, 0, 0, 66, 0, 0, 0, 231, 0, 0, 0, 254, 0, 0, 0, 178, 0, 0, 0, 114, 0, 0, 0, 33, 0, 0, 0, 10, 0, 0, 0, 102, 0, 0, 0, 116, 0, 0, 0, 143, 0, 0, 0, 183, 0, 0, 0, 235, 0, 0, 0, 228, 0, 0, 0, 111, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 140, 0, 0, 0, 107, 0, 0, 0, 190, 0, 0, 0, 252, 0, 0, 0, 77, 0, 0, 0, 112, 0, 0, 0, 98, 0, 0, 0, 110, 0, 0, 0, 82, 0, 0, 0, 119, 0, 0, 0, 153, 0, 0, 0, 136, 0, 0, 0, 126, 0, 0, 0, 123, 0, 0, 0, 87, 0, 0, 0, +122, 0, 0, 0, 13, 0, 0, 0, 254, 0, 0, 0, 220, 0, 0, 0, 114, 0, 0, 0, 146, 0, 0, 0, 241, 0, 0, 0, 104, 0, 0, 0, 29, 0, 0, 0, 151, 0, 0, 0, 215, 0, 0, 0, 124, 0, 0, 0, 141, 0, 0, 0, 83, 0, 0, 0, 16, 0, 0, 0, 55, 0, 0, 0, 83, 0, 0, 0, 136, 0, 0, 0, 119, 0, 0, 0, 2, 0, 0, 0, 202, 0, 0, 0, 39, 0, 0, 0, 168, 0, 0, 0, 229, 0, 0, 0, 69, 0, 0, 0, 226, 0, 0, 0, 168, 0, 0, 0, 72, 0, 0, 0, 42, 0, 0, 0, 171, 0, 0, 0, 24, 0, 0, 0, 202, 0, 0, 0, 234, 0, 0, 0, 45, 0, 0, 0, 42, 0, 0, 0, 84, 0, 0, 0, 23, 0, 0, 0, +55, 0, 0, 0, 50, 0, 0, 0, 9, 0, 0, 0, 220, 0, 0, 0, 224, 0, 0, 0, 74, 0, 0, 0, 183, 0, 0, 0, 125, 0, 0, 0, 130, 0, 0, 0, 16, 0, 0, 0, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 0, 0, 0, 100, 0, 0, 0, 30, 0, 0, 0, 20, 0, 0, 0, 10, 0, 0, 0, 87, 0, 0, 0, 212, 0, +0, 0, 218, 0, 0, 0, 92, 0, 0, 0, 150, 0, 0, 0, 155, 0, 0, 0, 1, 0, 0, 0, 76, 0, 0, 0, 103, 0, 0, 0, 191, 0, 0, 0, 139, 0, 0, 0, 48, 0, 0, 0, 254, 0, 0, 0, 8, 0, 0, 0, 219, 0, 0, 0, 13, 0, 0, 0, 213, 0, 0, 0, 168, 0, 0, 0, 215, 0, 0, 0, 9, 0, 0, 0, 17, 0, 0, 0, 133, 0, 0, 0, 162, 0, 0, 0, 211, 0, 0, 0, 69, 0, 0, 0, 251, 0, 0, 0, 126, 0, 0, 0, 218, 0, 0, 0, 140, 0, 0, 0, 194, 0, 0, 0, 208, 0, 0, 0, 172, 0, 0, 0, 24, 0, 0, 0, 232, 0, 0, 0, 82, 0, 0, 0, 54, 0, 0, 0, 212, 0, 0, 0, 33, 0, 0, 0, 163, 0, +0, 0, 221, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0, 121, 0, 0, 0, 183, 0, 0, 0, 248, 0, 0, 0, 113, 0, 0, 0, 157, 0, 0, 0, 198, 0, 0, 0, 145, 0, 0, 0, 112, 0, 0, 0, 134, 0, 0, 0, 86, 0, 0, 0, 191, 0, 0, 0, 161, 0, 0, 0, 17, 0, 0, 0, 139, 0, 0, 0, 25, 0, 0, 0, 225, 0, 0, 0, 15, 0, 0, 0, 24, 0, 0, 0, 50, 0, 0, 0, 152, 0, 0, 0, 44, 0, 0, 0, 143, 0, 0, 0, 145, 0, 0, 0, 174, 0, 0, 0, 18, 0, 0, 0, 240, 0, 0, 0, 140, 0, 0, 0, 234, 0, 0, 0, 243, 0, 0, 0, 60, 0, 0, 0, 185, 0, 0, 0, 93, 0, 0, 0, 228, 0, 0, 0, 105, +0, 0, 0, 237, 0, 0, 0, 178, 0, 0, 0, 71, 0, 0, 0, 24, 0, 0, 0, 189, 0, 0, 0, 206, 0, 0, 0, 22, 0, 0, 0, 82, 0, 0, 0, 92, 0, 0, 0, 35, 0, 0, 0, 226, 0, 0, 0, 165, 0, 0, 0, 37, 0, 0, 0, 82, 0, 0, 0, 93, 0, 0, 0, 185, 0, 0, 0, 177, 0, 0, 0, 231, 0, 0, 0, 93, 0, 0, 0, 78, 0, 0, 0, 188, 0, 0, 0, 238, 0, 0, 0, 187, 0, 0, 0, 64, 0, 0, 0, 129, 0, 0, 0, 119, 0, 0, 0, 130, 0, 0, 0, 25, 0, 0, 0, 171, 0, 0, 0, 181, 0, 0, 0, 198, 0, 0, 0, 238, 0, 0, 0, 171, 0, 0, 0, 91, 0, 0, 0, 107, 0, 0, 0, 99, 0, 0, 0, 146, +0, 0, 0, 138, 0, 0, 0, 52, 0, 0, 0, 141, 0, 0, 0, 205, 0, 0, 0, 238, 0, 0, 0, 79, 0, 0, 0, 73, 0, 0, 0, 229, 0, 0, 0, 201, 0, 0, 0, 126, 0, 0, 0, 33, 0, 0, 0, 172, 0, 0, 0, 139, 0, 0, 0, 34, 0, 0, 0, 205, 0, 0, 0, 195, 0, 0, 0, 154, 0, 0, 0, 233, 0, 0, 0, 94, 0, 0, 0, 120, 0, 0, 0, 189, 0, 0, 0, 222, 0, 0, 0, 186, 0, 0, 0, 173, 0, 0, 0, 171, 0, 0, 0, 191, 0, 0, 0, 117, 0, 0, 0, 65, 0, 0, 0, 9, 0, 0, 0, 197, 0, 0, 0, 88, 0, 0, 0, 164, 0, 0, 0, 125, 0, 0, 0, 146, 0, 0, 0, 176, 0, 0, 0, 127, 0, 0, 0, +242, 0, 0, 0, 161, 0, 0, 0, 209, 0, 0, 0, 192, 0, 0, 0, 179, 0, 0, 0, 109, 0, 0, 0, 98, 0, 0, 0, 79, 0, 0, 0, 208, 0, 0, 0, 117, 0, 0, 0, 119, 0, 0, 0, 186, 0, 0, 0, 118, 0, 0, 0, 119, 0, 0, 0, 215, 0, 0, 0, 184, 0, 0, 0, 216, 0, 0, 0, 146, 0, 0, 0, 111, 0, 0, 0, 152, 0, 0, 0, 52, 0, 0, 0, 61, 0, 0, 0, 214, 0, 0, 0, 78, 0, 0, 0, 28, 0, 0, 0, 15, 0, 0, 0, 240, 0, 0, 0, 143, 0, 0, 0, 46, 0, 0, 0, 241, 0, 0, 0, 179, 0, 0, 0, 189, 0, 0, 0, 177, 0, 0, 0, 185, 0, 0, 0, 236, 0, 0, 0, 153, 0, 0, 0, 180, +0, 0, 0, 7, 0, 0, 0, 96, 0, 0, 0, 87, 0, 0, 0, 46, 0, 0, 0, 154, 0, 0, 0, 114, 0, 0, 0, 29, 0, 0, 0, 107, 0, 0, 0, 110, 0, 0, 0, 88, 0, 0, 0, 51, 0, 0, 0, 36, 0, 0, 0, 140, 0, 0, 0, 72, 0, 0, 0, 57, 0, 0, 0, 70, 0, 0, 0, 142, 0, 0, 0, 137, 0, 0, 0, 106, 0, 0, 0, 136, 0, 0, 0, 81, 0, 0, 0, 35, 0, 0, 0, 98, 0, 0, 0, 181, 0, 0, 0, 50, 0, 0, 0, 9, 0, 0, 0, 54, 0, 0, 0, 227, 0, 0, 0, 87, 0, 0, 0, 245, 0, 0, 0, 152, 0, 0, 0, 222, 0, 0, 0, 111, 0, 0, 0, 139, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, +74, 0, 0, 0, 249, 0, 0, 0, 91, 0, 0, 0, 135, 0, 0, 0, 105, 0, 0, 0, 82, 0, 0, 0, 229, 0, 0, 0, 91, 0, 0, 0, 209, 0, 0, 0, 177, 0, 0, 0, 229, 0, 0, 0, 37, 0, 0, 0, 37, 0, 0, 0, 224, 0, 0, 0, 156, 0, 0, 0, 194, 0, 0, 0, 19, 0, 0, 0, 68, 0, 0, 0, 232, 0, 0, 0, 185, 0, 0, 0, 10, 0, 0, 0, 112, 0, 0, 0, 173, 0, 0, 0, 189, 0, 0, 0, 15, 0, 0, 0, 81, 0, 0, 0, 148, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 162, 0, 0, 0, 220, 0, 0, 0, 171, 0, 0, 0, 169, 0, 0, 0, 37, 0, 0, 0, 45, 0, 0, 0, 172, 0, 0, 0, 95, 0, 0, 0, 3, 0, 0, 0, 51, 0, 0, 0, 8, 0, 0, 0, 231, 0, 0, 0, 126, 0, 0, 0, 254, 0, 0, 0, 149, 0, 0, 0, 54, 0, 0, 0, 60, 0, 0, 0, 91, 0, 0, 0, 58, 0, 0, 0, 211, 0, 0, 0, 5, 0, 0, 0, 130, 0, 0, 0, 28, 0, 0, 0, 149, 0, 0, 0, 45, 0, 0, 0, 216, 0, 0, 0, 119, 0, +0, 0, 126, 0, 0, 0, 2, 0, 0, 0, 217, 0, 0, 0, 91, 0, 0, 0, 112, 0, 0, 0, 194, 0, 0, 0, 254, 0, 0, 0, 27, 0, 0, 0, 12, 0, 0, 0, 103, 0, 0, 0, 205, 0, 0, 0, 214, 0, 0, 0, 224, 0, 0, 0, 81, 0, 0, 0, 142, 0, 0, 0, 44, 0, 0, 0, 224, 0, 0, 0, 121, 0, 0, 0, 136, 0, 0, 0, 240, 0, 0, 0, 207, 0, 0, 0, 65, 0, 0, 0, 74, 0, 0, 0, 173, 0, 0, 0, 35, 0, 0, 0, 212, 0, 0, 0, 70, 0, 0, 0, 202, 0, 0, 0, 148, 0, 0, 0, 161, 0, 0, 0, 195, 0, 0, 0, 235, 0, 0, 0, 40, 0, 0, 0, 6, 0, 0, 0, 250, 0, 0, 0, 23, 0, 0, 0, 20, 0, +0, 0, 123, 0, 0, 0, 170, 0, 0, 0, 112, 0, 0, 0, 10, 0, 0, 0, 75, 0, 0, 0, 251, 0, 0, 0, 245, 0, 0, 0, 191, 0, 0, 0, 128, 0, 0, 0, 197, 0, 0, 0, 207, 0, 0, 0, 8, 0, 0, 0, 122, 0, 0, 0, 221, 0, 0, 0, 161, 0, 0, 0, 244, 0, 0, 0, 157, 0, 0, 0, 84, 0, 0, 0, 80, 0, 0, 0, 83, 0, 0, 0, 35, 0, 0, 0, 119, 0, 0, 0, 35, 0, 0, 0, 245, 0, 0, 0, 52, 0, 0, 0, 165, 0, 0, 0, 34, 0, 0, 0, 209, 0, 0, 0, 13, 0, 0, 0, 150, 0, 0, 0, 46, 0, 0, 0, 71, 0, 0, 0, 204, 0, 0, 0, 183, 0, 0, 0, 50, 0, 0, 0, 137, 0, 0, 0, 87, 0, +0, 0, 208, 0, 0, 0, 152, 0, 0, 0, 117, 0, 0, 0, 228, 0, 0, 0, 55, 0, 0, 0, 153, 0, 0, 0, 169, 0, 0, 0, 232, 0, 0, 0, 186, 0, 0, 0, 237, 0, 0, 0, 186, 0, 0, 0, 235, 0, 0, 0, 199, 0, 0, 0, 79, 0, 0, 0, 21, 0, 0, 0, 118, 0, 0, 0, 7, 0, 0, 0, 12, 0, 0, 0, 76, 0, 0, 0, 239, 0, 0, 0, 159, 0, 0, 0, 82, 0, 0, 0, 252, 0, 0, 0, 4, 0, 0, 0, 93, 0, 0, 0, 88, 0, 0, 0, 16, 0, 0, 0, 206, 0, 0, 0, 130, 0, 0, 0, 240, 0, 0, 0, 143, 0, 0, 0, 121, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 209, 0, 0, 0, 218, 0, 0, 0, 20, 0, +0, 0, 9, 0, 0, 0, 72, 0, 0, 0, 238, 0, 0, 0, 138, 0, 0, 0, 64, 0, 0, 0, 152, 0, 0, 0, 118, 0, 0, 0, 96, 0, 0, 0, 84, 0, 0, 0, 90, 0, 0, 0, 222, 0, 0, 0, 3, 0, 0, 0, 36, 0, 0, 0, 245, 0, 0, 0, 230, 0, 0, 0, 47, 0, 0, 0, 225, 0, 0, 0, 3, 0, 0, 0, 191, 0, 0, 0, 104, 0, 0, 0, 130, 0, 0, 0, 127, 0, 0, 0, 100, 0, 0, 0, 233, 0, 0, 0, 40, 0, 0, 0, 199, 0, 0, 0, 164, 0, 0, 0, 207, 0, 0, 0, 42, 0, 0, 0, 249, 0, 0, 0, 144, 0, 0, 0, 100, 0, 0, 0, 114, 0, 0, 0, 44, 0, 0, 0, 139, 0, 0, 0, 235, 0, 0, 0, 236, 0, +0, 0, 160, 0, 0, 0, 242, 0, 0, 0, 125, 0, 0, 0, 53, 0, 0, 0, 181, 0, 0, 0, 144, 0, 0, 0, 77, 0, 0, 0, 127, 0, 0, 0, 91, 0, 0, 0, 74, 0, 0, 0, 73, 0, 0, 0, 228, 0, 0, 0, 184, 0, 0, 0, 59, 0, 0, 0, 200, 0, 0, 0, 161, 0, 0, 0, 47, 0, 0, 0, 139, 0, 0, 0, 197, 0, 0, 0, 204, 0, 0, 0, 61, 0, 0, 0, 105, 0, 0, 0, 166, 0, 0, 0, 161, 0, 0, 0, 24, 0, 0, 0, 68, 0, 0, 0, 188, 0, 0, 0, 77, 0, 0, 0, 119, 0, 0, 0, 55, 0, 0, 0, 199, 0, 0, 0, 134, 0, 0, 0, 236, 0, 0, 0, 12, 0, 0, 0, 201, 0, 0, 0, 214, 0, 0, 0, 68, +0, 0, 0, 169, 0, 0, 0, 35, 0, 0, 0, 39, 0, 0, 0, 185, 0, 0, 0, 3, 0, 0, 0, 52, 0, 0, 0, 167, 0, 0, 0, 10, 0, 0, 0, 213, 0, 0, 0, 199, 0, 0, 0, 52, 0, 0, 0, 55, 0, 0, 0, 249, 0, 0, 0, 126, 0, 0, 0, 62, 0, 0, 0, 102, 0, 0, 0, 238, 0, 0, 0, 249, 0, 0, 0, 153, 0, 0, 0, 40, 0, 0, 0, 255, 0, 0, 0, 173, 0, 0, 0, 17, 0, 0, 0, 216, 0, 0, 0, 226, 0, 0, 0, 102, 0, 0, 0, 197, 0, 0, 0, 205, 0, 0, 0, 15, 0, 0, 0, 13, 0, 0, 0, 11, 0, 0, 0, 106, 0, 0, 0, 252, 0, 0, 0, 124, 0, 0, 0, 36, 0, 0, 0, 168, 0, 0, 0, 79, +0, 0, 0, 168, 0, 0, 0, 94, 0, 0, 0, 128, 0, 0, 0, 69, 0, 0, 0, 139, 0, 0, 0, 108, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 239, 0, 0, 0, 30, 0, 0, 0, 236, 0, 0, 0, 247, 0, 0, 0, 141, 0, 0, 0, 119, 0, 0, 0, 242, 0, 0, 0, 234, 0, 0, 0, 219, 0, 0, 0, 96, 0, +0, 0, 3, 0, 0, 0, 33, 0, 0, 0, 192, 0, 0, 0, 255, 0, 0, 0, 94, 0, 0, 0, 103, 0, 0, 0, 195, 0, 0, 0, 113, 0, 0, 0, 11, 0, 0, 0, 33, 0, 0, 0, 180, 0, 0, 0, 65, 0, 0, 0, 160, 0, 0, 0, 104, 0, 0, 0, 56, 0, 0, 0, 198, 0, 0, 0, 1, 0, 0, 0, 163, 0, 0, 0, 211, 0, 0, 0, 81, 0, 0, 0, 60, 0, 0, 0, 60, 0, 0, 0, 146, 0, 0, 0, 248, 0, 0, 0, 214, 0, 0, 0, 75, 0, 0, 0, 239, 0, 0, 0, 66, 0, 0, 0, 19, 0, 0, 0, 178, 0, 0, 0, 74, 0, 0, 0, 196, 0, 0, 0, 46, 0, 0, 0, 114, 0, 0, 0, 63, 0, 0, 0, 201, 0, 0, 0, 17, 0, 0, +0, 189, 0, 0, 0, 116, 0, 0, 0, 2, 0, 0, 0, 14, 0, 0, 0, 245, 0, 0, 0, 19, 0, 0, 0, 157, 0, 0, 0, 131, 0, 0, 0, 26, 0, 0, 0, 27, 0, 0, 0, 213, 0, 0, 0, 84, 0, 0, 0, 222, 0, 0, 0, 196, 0, 0, 0, 30, 0, 0, 0, 22, 0, 0, 0, 108, 0, 0, 0, 39, 0, 0, 0, 82, 0, 0, 0, 228, 0, 0, 0, 99, 0, 0, 0, 170, 0, 0, 0, 148, 0, 0, 0, 230, 0, 0, 0, 195, 0, 0, 0, 40, 0, 0, 0, 156, 0, 0, 0, 198, 0, 0, 0, 86, 0, 0, 0, 172, 0, 0, 0, 250, 0, 0, 0, 182, 0, 0, 0, 189, 0, 0, 0, 226, 0, 0, 0, 204, 0, 0, 0, 118, 0, 0, 0, 198, 0, +0, 0, 39, 0, 0, 0, 39, 0, 0, 0, 162, 0, 0, 0, 142, 0, 0, 0, 120, 0, 0, 0, 43, 0, 0, 0, 132, 0, 0, 0, 114, 0, 0, 0, 16, 0, 0, 0, 189, 0, 0, 0, 78, 0, 0, 0, 42, 0, 0, 0, 234, 0, 0, 0, 167, 0, 0, 0, 35, 0, 0, 0, 239, 0, 0, 0, 4, 0, 0, 0, 97, 0, 0, 0, 128, 0, 0, 0, 80, 0, 0, 0, 201, 0, 0, 0, 110, 0, 0, 0, 165, 0, 0, 0, 150, 0, 0, 0, 209, 0, 0, 0, 209, 0, 0, 0, 200, 0, 0, 0, 195, 0, 0, 0, 24, 0, 0, 0, 215, 0, 0, 0, 45, 0, 0, 0, 253, 0, 0, 0, 38, 0, 0, 0, 189, 0, 0, 0, 203, 0, 0, 0, 123, 0, 0, 0, 146, +0, 0, 0, 81, 0, 0, 0, 14, 0, 0, 0, 74, 0, 0, 0, 101, 0, 0, 0, 87, 0, 0, 0, 184, 0, 0, 0, 73, 0, 0, 0, 171, 0, 0, 0, 85, 0, 0, 0, 54, 0, 0, 0, 195, 0, 0, 0, 236, 0, 0, 0, 99, 0, 0, 0, 85, 0, 0, 0, 17, 0, 0, 0, 85, 0, 0, 0, 246, 0, 0, 0, 165, 0, 0, 0, 199, 0, 0, 0, 1, 0, 0, 0, 95, 0, 0, 0, 254, 0, 0, 0, 121, 0, 0, 0, 216, 0, 0, 0, 10, 0, 0, 0, 247, 0, 0, 0, 3, 0, 0, 0, 216, 0, 0, 0, 152, 0, 0, 0, 153, 0, 0, 0, 245, 0, 0, 0, 208, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 107, 0, 0, 0, 102, 0, 0, 0, 40, 0, 0, +0, 245, 0, 0, 0, 37, 0, 0, 0, 122, 0, 0, 0, 141, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 112, 0, 0, 0, 93, 0, 0, 0, 81, 0, 0, 0, 39, 0, 0, 0, 238, 0, 0, 0, 48, 0, 0, 0, 101, 0, 0, 0, 86, 0, 0, 0, 149, 0, 0, 0, 70, 0, 0, 0, 222, 0, 0, 0, 189, 0, 0, 0, 3, 0, 0, 0, 117, 0, 0, 0, 180, 0, 0, 0, 87, 0, 0, 0, 89, 0, 0, 0, 137, 0, 0, 0, 235, 0, 0, 0, 2, 0, 0, 0, 158, 0, 0, 0, 204, 0, 0, 0, 137, 0, 0, 0, 25, 0, 0, 0, 167, 0, 0, 0, 203, 0, 0, 0, 23, 0, 0, 0, 103, 0, 0, 0, 106, 0, 0, 0, 235, 0, 0, 0, 252, 0, 0, +0, 154, 0, 0, 0, 154, 0, 0, 0, 16, 0, 0, 0, 206, 0, 0, 0, 219, 0, 0, 0, 58, 0, 0, 0, 28, 0, 0, 0, 60, 0, 0, 0, 106, 0, 0, 0, 157, 0, 0, 0, 234, 0, 0, 0, 70, 0, 0, 0, 188, 0, 0, 0, 69, 0, 0, 0, 73, 0, 0, 0, 172, 0, 0, 0, 227, 0, 0, 0, 65, 0, 0, 0, 18, 0, 0, 0, 124, 0, 0, 0, 240, 0, 0, 0, 247, 0, 0, 0, 79, 0, 0, 0, 249, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 44, 0, 0, 0, 137, 0, 0, 0, 4, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 84, 0, 0, 0, 26, 0, 0, 0, 70, 0, 0, 0, 202, 0, 0, 0, 230, 0, 0, 0, 198, 0, 0, 0, +203, 0, 0, 0, 226, 0, 0, 0, 195, 0, 0, 0, 193, 0, 0, 0, 139, 0, 0, 0, 117, 0, 0, 0, 129, 0, 0, 0, 190, 0, 0, 0, 238, 0, 0, 0, 248, 0, 0, 0, 163, 0, 0, 0, 17, 0, 0, 0, 28, 0, 0, 0, 37, 0, 0, 0, 163, 0, 0, 0, 167, 0, 0, 0, 53, 0, 0, 0, 81, 0, 0, 0, 85, 0, 0, 0, 226, 0, 0, 0, 37, 0, 0, 0, 170, 0, 0, 0, 226, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 72, 0, 0, 0, 16, 0, 0, 0, 159, 0, 0, 0, 138, 0, 0, 0, 9, 0, 0, 0, 118, 0, 0, 0, 250, 0, 0, 0, 240, 0, 0, 0, 122, 0, 0, 0, 176, 0, 0, 0, 112, 0, 0, 0, 247, 0, 0, 0, 131, 0, 0, 0, 128, 0, 0, 0, 82, 0, 0, 0, 132, 0, 0, 0, 43, 0, 0, 0, 38, 0, 0, 0, 162, 0, 0, 0, 196, 0, 0, 0, 93, 0, 0, 0, 79, 0, 0, 0, 186, 0, 0, 0, 177, 0, 0, 0, 200, 0, 0, 0, 64, 0, 0, 0, 13, 0, 0, 0, 120, 0, 0, 0, 151, 0, 0, 0, +196, 0, 0, 0, 96, 0, 0, 0, 212, 0, 0, 0, 177, 0, 0, 0, 108, 0, 0, 0, 8, 0, 0, 0, 199, 0, 0, 0, 64, 0, 0, 0, 56, 0, 0, 0, 115, 0, 0, 0, 95, 0, 0, 0, 11, 0, 0, 0, 243, 0, 0, 0, 118, 0, 0, 0, 93, 0, 0, 0, 178, 0, 0, 0, 165, 0, 0, 0, 47, 0, 0, 0, 87, 0, 0, 0, 87, 0, 0, 0, 7, 0, 0, 0, 237, 0, 0, 0, 8, 0, 0, 0, 162, 0, 0, 0, 108, 0, 0, 0, 79, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 181, 0, 0, 0, 14, 0, 0, 0, 238, 0, 0, 0, 68, 0, 0, 0, 250, 0, 0, 0, 34, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 166, 0, 0, +0, 4, 0, 0, 0, 25, 0, 0, 0, 86, 0, 0, 0, 101, 0, 0, 0, 49, 0, 0, 0, 127, 0, 0, 0, 139, 0, 0, 0, 235, 0, 0, 0, 13, 0, 0, 0, 225, 0, 0, 0, 71, 0, 0, 0, 137, 0, 0, 0, 151, 0, 0, 0, 22, 0, 0, 0, 83, 0, 0, 0, 250, 0, 0, 0, 129, 0, 0, 0, 167, 0, 0, 0, 170, 0, 0, 0, 178, 0, 0, 0, 191, 0, 0, 0, 103, 0, 0, 0, 235, 0, 0, 0, 114, 0, 0, 0, 96, 0, 0, 0, 129, 0, 0, 0, 13, 0, 0, 0, 72, 0, 0, 0, 126, 0, 0, 0, 19, 0, 0, 0, 51, 0, 0, 0, 205, 0, 0, 0, 168, 0, 0, 0, 132, 0, 0, 0, 86, 0, 0, 0, 30, 0, 0, 0, 103, 0, 0, +0, 175, 0, 0, 0, 107, 0, 0, 0, 67, 0, 0, 0, 172, 0, 0, 0, 23, 0, 0, 0, 175, 0, 0, 0, 22, 0, 0, 0, 192, 0, 0, 0, 82, 0, 0, 0, 153, 0, 0, 0, 73, 0, 0, 0, 91, 0, 0, 0, 135, 0, 0, 0, 115, 0, 0, 0, 126, 0, 0, 0, 181, 0, 0, 0, 67, 0, 0, 0, 218, 0, 0, 0, 107, 0, 0, 0, 29, 0, 0, 0, 15, 0, 0, 0, 45, 0, 0, 0, 85, 0, 0, 0, 233, 0, 0, 0, 88, 0, 0, 0, 31, 0, 0, 0, 255, 0, 0, 0, 132, 0, 0, 0, 63, 0, 0, 0, 147, 0, 0, 0, 28, 0, 0, 0, 203, 0, 0, 0, 225, 0, 0, 0, 48, 0, 0, 0, 105, 0, 0, 0, 165, 0, 0, 0, 117, 0, 0, +0, 25, 0, 0, 0, 126, 0, 0, 0, 20, 0, 0, 0, 95, 0, 0, 0, 248, 0, 0, 0, 252, 0, 0, 0, 9, 0, 0, 0, 221, 0, 0, 0, 168, 0, 0, 0, 120, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 89, 0, 0, 0, 139, 0, 0, 0, 209, 0, 0, 0, 48, 0, 0, 0, 1, 0, 0, 0, 19, 0, 0, 0, 255, 0, 0, 0, 118, 0, 0, 0, 3, 0, 0, 0, 197, 0, 0, 0, 75, 0, 0, 0, 137, 0, 0, 0, 153, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 112, 0, 0, 0, 156, 0, 0, 0, 213, 0, 0, 0, 217, 0, 0, 0, 17, 0, 0, 0, 137, 0, 0, 0, 90, 0, 0, 0, 70, 0, 0, 0, 254, 0, 0, 0, +239, 0, 0, 0, 220, 0, 0, 0, 217, 0, 0, 0, 85, 0, 0, 0, 43, 0, 0, 0, 69, 0, 0, 0, 167, 0, 0, 0, 176, 0, 0, 0, 45, 0, 0, 0, 251, 0, 0, 0, 36, 0, 0, 0, 194, 0, 0, 0, 41, 0, 0, 0, 56, 0, 0, 0, 6, 0, 0, 0, 248, 0, 0, 0, 11, 0, 0, 0, 172, 0, 0, 0, 130, 0, 0, 0, 196, 0, 0, 0, 151, 0, 0, 0, 43, 0, 0, 0, 144, 0, 0, 0, 224, 0, 0, 0, 247, 0, 0, 0, 168, 0, 0, 0, 171, 0, 0, 0, 108, 0, 0, 0, 8, 0, 0, 0, 128, 0, 0, 0, 102, 0, 0, 0, 144, 0, 0, 0, 70, 0, 0, 0, 247, 0, 0, 0, 38, 0, 0, 0, 45, 0, 0, 0, 248, 0, 0, 0, +241, 0, 0, 0, 196, 0, 0, 0, 107, 0, 0, 0, 74, 0, 0, 0, 130, 0, 0, 0, 152, 0, 0, 0, 142, 0, 0, 0, 55, 0, 0, 0, 142, 0, 0, 0, 180, 0, 0, 0, 238, 0, 0, 0, 184, 0, 0, 0, 212, 0, 0, 0, 63, 0, 0, 0, 178, 0, 0, 0, 27, 0, 0, 0, 224, 0, 0, 0, 10, 0, 0, 0, 61, 0, 0, 0, 117, 0, 0, 0, 52, 0, 0, 0, 40, 0, 0, 0, 162, 0, 0, 0, 142, 0, 0, 0, 196, 0, 0, 0, 146, 0, 0, 0, 123, 0, 0, 0, 254, 0, 0, 0, 96, 0, 0, 0, 110, 0, 0, 0, 109, 0, 0, 0, 184, 0, 0, 0, 49, 0, 0, 0, 29, 0, 0, 0, 98, 0, 0, 0, 13, 0, 0, 0, 120, 0, 0, +0, 20, 0, 0, 0, 66, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, 0, 168, 0, 0, 0, 216, 0, 0, 0, 4, 0, 0, 0, 155, 0, 0, 0, 115, 0, 0, 0, 201, 0, 0, 0, 201, 0, 0, 0, 220, 0, 0, 0, 13, 0, 0, 0, 115, 0, 0, 0, 191, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 115, +0, 0, 0, 255, 0, 0, 0, 24, 0, 0, 0, 31, 0, 0, 0, 156, 0, 0, 0, 81, 0, 0, 0, 170, 0, 0, 0, 198, 0, 0, 0, 241, 0, 0, 0, 131, 0, 0, 0, 37, 0, 0, 0, 253, 0, 0, 0, 171, 0, 0, 0, 163, 0, 0, 0, 17, 0, 0, 0, 211, 0, 0, 0, 1, 0, 0, 0, 36, 0, 0, 0, 77, 0, 0, 0, 227, 0, 0, 0, 126, 0, 0, 0, 56, 0, 0, 0, 98, 0, 0, 0, 94, 0, 0, 0, 100, 0, 0, 0, 187, 0, 0, 0, 43, 0, 0, 0, 83, 0, 0, 0, 181, 0, 0, 0, 3, 0, 0, 0, 104, 0, 0, 0, 196, 0, 0, 0, 242, 0, 0, 0, 43, 0, 0, 0, 90, 0, 0, 0, 3, 0, 0, 0, 50, 0, 0, 0, 153, 0, 0, +0, 74, 0, 0, 0, 65, 0, 0, 0, 154, 0, 0, 0, 225, 0, 0, 0, 26, 0, 0, 0, 174, 0, 0, 0, 140, 0, 0, 0, 72, 0, 0, 0, 243, 0, 0, 0, 36, 0, 0, 0, 50, 0, 0, 0, 101, 0, 0, 0, 232, 0, 0, 0, 221, 0, 0, 0, 173, 0, 0, 0, 58, 0, 0, 0, 140, 0, 0, 0, 234, 0, 0, 0, 244, 0, 0, 0, 179, 0, 0, 0, 178, 0, 0, 0, 229, 0, 0, 0, 115, 0, 0, 0, 242, 0, 0, 0, 237, 0, 0, 0, 139, 0, 0, 0, 191, 0, 0, 0, 237, 0, 0, 0, 177, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 251, 0, 0, 0, 43, 0, 0, 0, 241, 0, 0, 0, 1, 0, 0, 0, 72, 0, 0, 0, 232, 0, +0, 0, 38, 0, 0, 0, 3, 0, 0, 0, 142, 0, 0, 0, 39, 0, 0, 0, 77, 0, 0, 0, 150, 0, 0, 0, 114, 0, 0, 0, 200, 0, 0, 0, 9, 0, 0, 0, 59, 0, 0, 0, 96, 0, 0, 0, 201, 0, 0, 0, 38, 0, 0, 0, 77, 0, 0, 0, 124, 0, 0, 0, 242, 0, 0, 0, 156, 0, 0, 0, 212, 0, 0, 0, 161, 0, 0, 0, 59, 0, 0, 0, 38, 0, 0, 0, 194, 0, 0, 0, 4, 0, 0, 0, 51, 0, 0, 0, 68, 0, 0, 0, 118, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0, 0, 187, 0, 0, 0, 17, 0, 0, 0, 66, 0, 0, 0, 12, 0, 0, 0, 34, 0, 0, 0, 183, 0, 0, 0, 198, 0, 0, 0, 225, 0, 0, 0, 172, 0, 0, 0, 180, +0, 0, 0, 14, 0, 0, 0, 111, 0, 0, 0, 133, 0, 0, 0, 231, 0, 0, 0, 239, 0, 0, 0, 222, 0, 0, 0, 103, 0, 0, 0, 48, 0, 0, 0, 252, 0, 0, 0, 191, 0, 0, 0, 90, 0, 0, 0, 224, 0, 0, 0, 123, 0, 0, 0, 122, 0, 0, 0, 42, 0, 0, 0, 84, 0, 0, 0, 107, 0, 0, 0, 93, 0, 0, 0, 98, 0, 0, 0, 133, 0, 0, 0, 161, 0, 0, 0, 248, 0, 0, 0, 22, 0, 0, 0, 136, 0, 0, 0, 236, 0, 0, 0, 97, 0, 0, 0, 185, 0, 0, 0, 150, 0, 0, 0, 181, 0, 0, 0, 239, 0, 0, 0, 45, 0, 0, 0, 67, 0, 0, 0, 77, 0, 0, 0, 124, 0, 0, 0, 49, 0, 0, 0, 51, 0, 0, 0, 204, +0, 0, 0, 228, 0, 0, 0, 207, 0, 0, 0, 108, 0, 0, 0, 255, 0, 0, 0, 128, 0, 0, 0, 71, 0, 0, 0, 119, 0, 0, 0, 209, 0, 0, 0, 216, 0, 0, 0, 233, 0, 0, 0, 105, 0, 0, 0, 151, 0, 0, 0, 152, 0, 0, 0, 127, 0, 0, 0, 32, 0, 0, 0, 87, 0, 0, 0, 29, 0, 0, 0, 29, 0, 0, 0, 79, 0, 0, 0, 8, 0, 0, 0, 39, 0, 0, 0, 200, 0, 0, 0, 53, 0, 0, 0, 87, 0, 0, 0, 64, 0, 0, 0, 198, 0, 0, 0, 33, 0, 0, 0, 12, 0, 0, 0, 210, 0, 0, 0, 142, 0, 0, 0, 155, 0, 0, 0, 250, 0, 0, 0, 66, 0, 0, 0, 142, 0, 0, 0, 223, 0, 0, 0, 143, 0, 0, 0, 199, +0, 0, 0, 134, 0, 0, 0, 249, 0, 0, 0, 164, 0, 0, 0, 202, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 157, 0, 0, 0, 33, 0, 0, 0, 191, 0, 0, 0, 236, 0, 0, 0, 87, 0, 0, 0, 98, 0, 0, 0, 48, 0, 0, 0, 88, 0, 0, 0, 140, 0, 0, 0, 13, 0, 0, 0, 53, 0, 0, 0, 219, 0, 0, 0, 93, 0, 0, 0, 139, 0, 0, 0, 106, 0, 0, 0, 160, 0, 0, 0, 90, 0, 0, 0, 193, 0, 0, 0, 88, 0, 0, 0, 124, 0, 0, 0, 13, 0, 0, 0, 32, 0, 0, 0, 221, 0, 0, 0, 17, 0, 0, 0, 38, 0, 0, 0, 95, 0, 0, 0, 137, 0, 0, 0, 59, 0, 0, 0, 151, 0, 0, 0, 88, 0, 0, 0, 248, 0, +0, 0, 139, 0, 0, 0, 227, 0, 0, 0, 223, 0, 0, 0, 50, 0, 0, 0, 226, 0, 0, 0, 252, 0, 0, 0, 216, 0, 0, 0, 103, 0, 0, 0, 242, 0, 0, 0, 165, 0, 0, 0, 55, 0, 0, 0, 30, 0, 0, 0, 109, 0, 0, 0, 236, 0, 0, 0, 124, 0, 0, 0, 39, 0, 0, 0, 32, 0, 0, 0, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 233, 0, 0, 0, 192, 0, 0, 0, 250, 0, 0, 0, 149, 0, 0, 0, 69, 0, 0, 0, 35, 0, 0, 0, 150, 0, 0, 0, 241, 0, 0, 0, 44, 0, 0, 0, 121, 0, 0, 0, 37, 0, 0, 0, 20, 0, 0, 0, 206, 0, 0, 0, 64, 0, 0, 0, 20, 0, 0, 0, 68, 0, 0, 0, 44, 0, 0, 0, 54, 0, 0, 0, 80, 0, 0, 0, 217, 0, 0, 0, 99, 0, 0, 0, 86, 0, 0, 0, 183, 0, 0, 0, 86, 0, 0, 0, 59, 0, 0, 0, 158, 0, 0, 0, 167, 0, 0, 0, 239, 0, 0, 0, 137, 0, 0, 0, 187, 0, 0, 0, 14, 0, 0, 0, 206, 0, 0, 0, 127, 0, 0, 0, 220, 0, 0, 0, 10, 0, 0, +0, 204, 0, 0, 0, 130, 0, 0, 0, 28, 0, 0, 0, 10, 0, 0, 0, 120, 0, 0, 0, 113, 0, 0, 0, 232, 0, 0, 0, 116, 0, 0, 0, 141, 0, 0, 0, 1, 0, 0, 0, 48, 0, 0, 0, 15, 0, 0, 0, 167, 0, 0, 0, 17, 0, 0, 0, 76, 0, 0, 0, 223, 0, 0, 0, 56, 0, 0, 0, 215, 0, 0, 0, 167, 0, 0, 0, 13, 0, 0, 0, 248, 0, 0, 0, 72, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 123, 0, 0, 0, 95, 0, 0, 0, 14, 0, 0, 0, 37, 0, 0, 0, 131, 0, 0, 0, 230, 0, 0, 0, 148, 0, 0, 0, 123, 0, 0, 0, 129, 0, 0, 0, 178, 0, 0, 0, 145, 0, 0, 0, 174, 0, 0, +0, 14, 0, 0, 0, 5, 0, 0, 0, 201, 0, 0, 0, 163, 0, 0, 0, 104, 0, 0, 0, 45, 0, 0, 0, 217, 0, 0, 0, 136, 0, 0, 0, 37, 0, 0, 0, 25, 0, 0, 0, 42, 0, 0, 0, 97, 0, 0, 0, 97, 0, 0, 0, 33, 0, 0, 0, 151, 0, 0, 0, 21, 0, 0, 0, 161, 0, 0, 0, 53, 0, 0, 0, 165, 0, 0, 0, 70, 0, 0, 0, 200, 0, 0, 0, 162, 0, 0, 0, 14, 0, 0, 0, 27, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 0, 139, 0, 0, 0, 90, 0, 0, 0, 27, 0, 0, 0, 151, 0, 0, 0, 75, 0, 0, 0, 242, 0, 0, 0, 22, 0, 0, 0, 49, 0, 0, 0, 61, 0, 0, 0, 31, 0, 0, 0, 51, 0, 0, 0, 160, 0, +0, 0, 80, 0, 0, 0, 58, 0, 0, 0, 24, 0, 0, 0, 190, 0, 0, 0, 19, 0, 0, 0, 161, 0, 0, 0, 118, 0, 0, 0, 193, 0, 0, 0, 186, 0, 0, 0, 27, 0, 0, 0, 241, 0, 0, 0, 5, 0, 0, 0, 123, 0, 0, 0, 51, 0, 0, 0, 168, 0, 0, 0, 130, 0, 0, 0, 59, 0, 0, 0, 186, 0, 0, 0, 54, 0, 0, 0, 123, 0, 0, 0, 109, 0, 0, 0, 169, 0, 0, 0, 234, 0, 0, 0, 20, 0, 0, 0, 18, 0, 0, 0, 197, 0, 0, 0, 250, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 155, 0, 0, 0, 153, 0, 0, 0, 204, 0, 0, 0, 86, 0, 0, 0, 2, 0, 0, 0, 233, 0, 0, 0, 160, 0, +0, 0, 38, 0, 0, 0, 64, 0, 0, 0, 102, 0, 0, 0, 140, 0, 0, 0, 196, 0, 0, 0, 248, 0, 0, 0, 133, 0, 0, 0, 51, 0, 0, 0, 104, 0, 0, 0, 231, 0, 0, 0, 3, 0, 0, 0, 32, 0, 0, 0, 80, 0, 0, 0, 91, 0, 0, 0, 255, 0, 0, 0, 169, 0, 0, 0, 178, 0, 0, 0, 241, 0, 0, 0, 241, 0, 0, 0, 120, 0, 0, 0, 207, 0, 0, 0, 20, 0, 0, 0, 164, 0, 0, 0, 169, 0, 0, 0, 252, 0, 0, 0, 9, 0, 0, 0, 70, 0, 0, 0, 148, 0, 0, 0, 84, 0, 0, 0, 101, 0, 0, 0, 13, 0, 0, 0, 156, 0, 0, 0, 95, 0, 0, 0, 114, 0, 0, 0, 33, 0, 0, 0, 226, 0, 0, 0, 151, 0, +0, 0, 165, 0, 0, 0, 45, 0, 0, 0, 129, 0, 0, 0, 206, 0, 0, 0, 74, 0, 0, 0, 95, 0, 0, 0, 121, 0, 0, 0, 61, 0, 0, 0, 95, 0, 0, 0, 92, 0, 0, 0, 210, 0, 0, 0, 188, 0, 0, 0, 125, 0, 0, 0, 119, 0, 0, 0, 14, 0, 0, 0, 42, 0, 0, 0, 109, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0, 132, 0, 0, 0, 6, 0, 0, 0, 196, 0, 0, 0, 221, 0, 0, 0, 198, 0, 0, 0, 166, 0, 0, 0, 198, 0, 0, 0, 215, 0, 0, 0, 73, 0, 0, 0, 173, 0, 0, 0, 109, 0, 0, 0, 135, 0, 0, 0, 145, 0, 0, 0, 14, 0, 0, 0, 58, 0, 0, 0, 103, 0, 0, 0, 29, 0, 0, 0, 44, 0, +0, 0, 29, 0, 0, 0, 86, 0, 0, 0, 254, 0, 0, 0, 122, 0, 0, 0, 116, 0, 0, 0, 207, 0, 0, 0, 212, 0, 0, 0, 210, 0, 0, 0, 229, 0, 0, 0, 25, 0, 0, 0, 222, 0, 0, 0, 208, 0, 0, 0, 219, 0, 0, 0, 112, 0, 0, 0, 35, 0, 0, 0, 105, 0, 0, 0, 230, 0, 0, 0, 109, 0, 0, 0, 236, 0, 0, 0, 236, 0, 0, 0, 204, 0, 0, 0, 9, 0, 0, 0, 51, 0, 0, 0, 106, 0, 0, 0, 119, 0, 0, 0, 220, 0, 0, 0, 107, 0, 0, 0, 34, 0, 0, 0, 118, 0, 0, 0, 93, 0, 0, 0, 146, 0, 0, 0, 9, 0, 0, 0, 172, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 21, 0, 0, 0, 23, 0, 0, 0, 235, 0, 0, 0, 211, 0, 0, 0, 219, 0, 0, 0, 18, 0, 0, 0, 94, 0, 0, 0, 1, 0, 0, 0, 240, 0, 0, 0, 145, 0, 0, 0, 171, 0, 0, 0, 44, 0, 0, 0, 65, 0, 0, 0, 206, 0, 0, 0, 172, 0, 0, 0, 237, 0, 0, 0, 27, 0, 0, 0, 75, 0, 0, 0, 45, 0, 0, 0, +188, 0, 0, 0, 219, 0, 0, 0, 23, 0, 0, 0, 102, 0, 0, 0, 137, 0, 0, 0, 70, 0, 0, 0, 173, 0, 0, 0, 75, 0, 0, 0, 30, 0, 0, 0, 111, 0, 0, 0, 11, 0, 0, 0, 20, 0, 0, 0, 17, 0, 0, 0, 206, 0, 0, 0, 191, 0, 0, 0, 182, 0, 0, 0, 119, 0, 0, 0, 45, 0, 0, 0, 72, 0, 0, 0, 34, 0, 0, 0, 24, 0, 0, 0, 79, 0, 0, 0, 163, 0, 0, 0, 93, 0, 0, 0, 74, 0, 0, 0, 176, 0, 0, 0, 112, 0, 0, 0, 18, 0, 0, 0, 62, 0, 0, 0, 84, 0, 0, 0, 215, 0, 0, 0, 216, 0, 0, 0, 14, 0, 0, 0, 43, 0, 0, 0, 39, 0, 0, 0, 220, 0, 0, 0, 83, 0, 0, 0, 255, +0, 0, 0, 202, 0, 0, 0, 140, 0, 0, 0, 89, 0, 0, 0, 179, 0, 0, 0, 78, 0, 0, 0, 68, 0, 0, 0, 7, 0, 0, 0, 118, 0, 0, 0, 97, 0, 0, 0, 15, 0, 0, 0, 102, 0, 0, 0, 178, 0, 0, 0, 33, 0, 0, 0, 57, 0, 0, 0, 126, 0, 0, 0, 192, 0, 0, 0, 236, 0, 0, 0, 69, 0, 0, 0, 40, 0, 0, 0, 130, 0, 0, 0, 161, 0, 0, 0, 41, 0, 0, 0, 50, 0, 0, 0, 68, 0, 0, 0, 53, 0, 0, 0, 19, 0, 0, 0]).concat([94, 0, 0, 0, 97, 0, 0, 0, 94, 0, 0, 0, 84, 0, 0, 0, 203, 0, 0, 0, 124, 0, 0, 0, 239, 0, 0, 0, 246, 0, 0, 0, 65, 0, 0, 0, 207, 0, 0, 0, +159, 0, 0, 0, 10, 0, 0, 0, 221, 0, 0, 0, 249, 0, 0, 0, 218, 0, 0, 0, 132, 0, 0, 0, 195, 0, 0, 0, 230, 0, 0, 0, 138, 0, 0, 0, 159, 0, 0, 0, 36, 0, 0, 0, 210, 0, 0, 0, 150, 0, 0, 0, 93, 0, 0, 0, 57, 0, 0, 0, 111, 0, 0, 0, 88, 0, 0, 0, 140, 0, 0, 0, 193, 0, 0, 0, 86, 0, 0, 0, 147, 0, 0, 0, 171, 0, 0, 0, 181, 0, 0, 0, 121, 0, 0, 0, 59, 0, 0, 0, 210, 0, 0, 0, 168, 0, 0, 0, 115, 0, 0, 0, 22, 0, 0, 0, 237, 0, 0, 0, 250, 0, 0, 0, 180, 0, 0, 0, 47, 0, 0, 0, 115, 0, 0, 0, 139, 0, 0, 0, 177, 0, 0, 0, 149, 0, +0, 0, 229, 0, 0, 0, 146, 0, 0, 0, 80, 0, 0, 0, 53, 0, 0, 0, 17, 0, 0, 0, 118, 0, 0, 0, 172, 0, 0, 0, 244, 0, 0, 0, 77, 0, 0, 0, 36, 0, 0, 0, 195, 0, 0, 0, 50, 0, 0, 0, 230, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 44, 0, 0, 0, 135, 0, 0, 0, 196, 0, 0, 0, 241, 0, 0, 0, 86, 0, 0, 0, 196, 0, 0, 0, 117, 0, 0, 0, 36, 0, 0, 0, 122, 0, 0, 0, 86, 0, 0, 0, 133, 0, 0, 0, 90, 0, 0, 0, 58, 0, 0, 0, 19, 0, 0, 0, 13, 0, 0, 0, 22, 0, 0, 0, 172, 0, 0, 0, 60, 0, 0, 0, 74, 0, 0, 0, 88, 0, 0, 0, 134, 0, 0, 0, 58, 0, 0, +0, 70, 0, 0, 0, 127, 0, 0, 0, 108, 0, 0, 0, 163, 0, 0, 0, 82, 0, 0, 0, 110, 0, 0, 0, 55, 0, 0, 0, 228, 0, 0, 0, 150, 0, 0, 0, 156, 0, 0, 0, 233, 0, 0, 0, 92, 0, 0, 0, 102, 0, 0, 0, 65, 0, 0, 0, 103, 0, 0, 0, 228, 0, 0, 0, 251, 0, 0, 0, 121, 0, 0, 0, 12, 0, 0, 0, 5, 0, 0, 0, 246, 0, 0, 0, 100, 0, 0, 0, 213, 0, 0, 0, 124, 0, 0, 0, 40, 0, 0, 0, 193, 0, 0, 0, 225, 0, 0, 0, 84, 0, 0, 0, 115, 0, 0, 0, 242, 0, 0, 0, 191, 0, 0, 0, 118, 0, 0, 0, 116, 0, 0, 0, 25, 0, 0, 0, 25, 0, 0, 0, 27, 0, 0, 0, 228, 0, +0, 0, 185, 0, 0, 0, 168, 0, 0, 0, 70, 0, 0, 0, 101, 0, 0, 0, 115, 0, 0, 0, 243, 0, 0, 0, 119, 0, 0, 0, 155, 0, 0, 0, 41, 0, 0, 0, 116, 0, 0, 0, 91, 0, 0, 0, 198, 0, 0, 0, 137, 0, 0, 0, 108, 0, 0, 0, 44, 0, 0, 0, 124, 0, 0, 0, 248, 0, 0, 0, 179, 0, 0, 0, 15, 0, 0, 0, 247, 0, 0, 0, 213, 0, 0, 0, 233, 0, 0, 0, 116, 0, 0, 0, 93, 0, 0, 0, 184, 0, 0, 0, 37, 0, 0, 0, 22, 0, 0, 0, 181, 0, 0, 0, 48, 0, 0, 0, 188, 0, 0, 0, 132, 0, 0, 0, 197, 0, 0, 0, 240, 0, 0, 0, 173, 0, 0, 0, 202, 0, 0, 0, 18, 0, 0, 0, 40, +0, 0, 0, 188, 0, 0, 0, 157, 0, 0, 0, 212, 0, 0, 0, 250, 0, 0, 0, 130, 0, 0, 0, 230, 0, 0, 0, 227, 0, 0, 0, 191, 0, 0, 0, 162, 0, 0, 0, 21, 0, 0, 0, 44, 0, 0, 0, 212, 0, 0, 0, 52, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, 0, 0, 177, 0, 0, 0, 70, 0, +0, 0, 186, 0, 0, 0, 14, 0, 0, 0, 49, 0, 0, 0, 165, 0, 0, 0, 103, 0, 0, 0, 108, 0, 0, 0, 127, 0, 0, 0, 214, 0, 0, 0, 217, 0, 0, 0, 39, 0, 0, 0, 133, 0, 0, 0, 15, 0, 0, 0, 121, 0, 0, 0, 20, 0, 0, 0, 200, 0, 0, 0, 108, 0, 0, 0, 47, 0, 0, 0, 95, 0, 0, 0, 91, 0, 0, 0, 156, 0, 0, 0, 53, 0, 0, 0, 61, 0, 0, 0, 56, 0, 0, 0, 134, 0, 0, 0, 119, 0, 0, 0, 101, 0, 0, 0, 85, 0, 0, 0, 106, 0, 0, 0, 123, 0, 0, 0, 211, 0, 0, 0, 176, 0, 0, 0, 58, 0, 0, 0, 102, 0, 0, 0, 96, 0, 0, 0, 27, 0, 0, 0, 67, 0, 0, 0, 241, 0, +0, 0, 38, 0, 0, 0, 88, 0, 0, 0, 153, 0, 0, 0, 9, 0, 0, 0, 143, 0, 0, 0, 45, 0, 0, 0, 163, 0, 0, 0, 20, 0, 0, 0, 113, 0, 0, 0, 133, 0, 0, 0, 219, 0, 0, 0, 237, 0, 0, 0, 246, 0, 0, 0, 38, 0, 0, 0, 213, 0, 0, 0, 97, 0, 0, 0, 154, 0, 0, 0, 115, 0, 0, 0, 172, 0, 0, 0, 14, 0, 0, 0, 234, 0, 0, 0, 172, 0, 0, 0, 183, 0, 0, 0, 12, 0, 0, 0, 94, 0, 0, 0, 244, 0, 0, 0, 229, 0, 0, 0, 23, 0, 0, 0, 14, 0, 0, 0, 16, 0, 0, 0, 159, 0, 0, 0, 231, 0, 0, 0, 67, 0, 0, 0, 95, 0, 0, 0, 103, 0, 0, 0, 92, 0, 0, 0, 172, 0, +0, 0, 75, 0, 0, 0, 229, 0, 0, 0, 20, 0, 0, 0, 65, 0, 0, 0, 210, 0, 0, 0, 191, 0, 0, 0, 72, 0, 0, 0, 245, 0, 0, 0, 20, 0, 0, 0, 176, 0, 0, 0, 113, 0, 0, 0, 198, 0, 0, 0, 97, 0, 0, 0, 193, 0, 0, 0, 178, 0, 0, 0, 112, 0, 0, 0, 88, 0, 0, 0, 210, 0, 0, 0, 90, 0, 0, 0, 45, 0, 0, 0, 186, 0, 0, 0, 22, 0, 0, 0, 7, 0, 0, 0, 146, 0, 0, 0, 148, 0, 0, 0, 220, 0, 0, 0, 189, 0, 0, 0, 80, 0, 0, 0, 43, 0, 0, 0, 201, 0, 0, 0, 127, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 97, 0, 0, 0, 237, 0, 0, 0, 248, 0, 0, +0, 67, 0, 0, 0, 237, 0, 0, 0, 245, 0, 0, 0, 249, 0, 0, 0, 64, 0, 0, 0, 96, 0, 0, 0, 178, 0, 0, 0, 176, 0, 0, 0, 130, 0, 0, 0, 203, 0, 0, 0, 237, 0, 0, 0, 117, 0, 0, 0, 199, 0, 0, 0, 101, 0, 0, 0, 128, 0, 0, 0, 186, 0, 0, 0, 13, 0, 0, 0, 9, 0, 0, 0, 64, 0, 0, 0, 167, 0, 0, 0, 57, 0, 0, 0, 166, 0, 0, 0, 103, 0, 0, 0, 52, 0, 0, 0, 126, 0, 0, 0, 102, 0, 0, 0, 190, 0, 0, 0, 86, 0, 0, 0, 251, 0, 0, 0, 83, 0, 0, 0, 120, 0, 0, 0, 196, 0, 0, 0, 70, 0, 0, 0, 232, 0, 0, 0, 237, 0, 0, 0, 104, 0, 0, 0, 108, 0, +0, 0, 127, 0, 0, 0, 206, 0, 0, 0, 232, 0, 0, 0, 159, 0, 0, 0, 206, 0, 0, 0, 162, 0, 0, 0, 100, 0, 0, 0, 88, 0, 0, 0, 83, 0, 0, 0, 232, 0, 0, 0, 193, 0, 0, 0, 169, 0, 0, 0, 194, 0, 0, 0, 123, 0, 0, 0, 89, 0, 0, 0, 33, 0, 0, 0, 51, 0, 0, 0, 226, 0, 0, 0, 67, 0, 0, 0, 115, 0, 0, 0, 43, 0, 0, 0, 172, 0, 0, 0, 45, 0, 0, 0, 193, 0, 0, 0, 137, 0, 0, 0, 59, 0, 0, 0, 21, 0, 0, 0, 226, 0, 0, 0, 213, 0, 0, 0, 192, 0, 0, 0, 151, 0, 0, 0, 138, 0, 0, 0, 253, 0, 0, 0, 111, 0, 0, 0, 54, 0, 0, 0, 51, 0, 0, 0, 183, +0, 0, 0, 185, 0, 0, 0, 195, 0, 0, 0, 136, 0, 0, 0, 9, 0, 0, 0, 208, 0, 0, 0, 182, 0, 0, 0, 86, 0, 0, 0, 48, 0, 0, 0, 92, 0, 0, 0, 174, 0, 0, 0, 179, 0, 0, 0, 117, 0, 0, 0, 68, 0, 0, 0, 164, 0, 0, 0, 131, 0, 0, 0, 81, 0, 0, 0, 110, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 0, 239, 0, 0, 0, 69, 0, 0, 0, 118, 0, 0, 0, 230, 0, 0, 0, 245, 0, 0, 0, 162, 0, 0, 0, 13, 0, 0, 0, 212, 0, 0, 0, 22, 0, 0, 0, 59, 0, 0, 0, 88, 0, 0, 0, 47, 0, 0, 0, 242, 0, 0, 0, 47, 0, 0, 0, 54, 0, 0, 0, 24, 0, 0, 0, 63, 0, 0, 0, 253, 0, +0, 0, 47, 0, 0, 0, 224, 0, 0, 0, 155, 0, 0, 0, 30, 0, 0, 0, 140, 0, 0, 0, 197, 0, 0, 0, 24, 0, 0, 0, 169, 0, 0, 0, 202, 0, 0, 0, 212, 0, 0, 0, 43, 0, 0, 0, 53, 0, 0, 0, 182, 0, 0, 0, 149, 0, 0, 0, 10, 0, 0, 0, 159, 0, 0, 0, 126, 0, 0, 0, 251, 0, 0, 0, 196, 0, 0, 0, 239, 0, 0, 0, 136, 0, 0, 0, 123, 0, 0, 0, 35, 0, 0, 0, 67, 0, 0, 0, 236, 0, 0, 0, 47, 0, 0, 0, 13, 0, 0, 0, 15, 0, 0, 0, 122, 0, 0, 0, 252, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, 0, 210, 0, 0, 0, 218, 0, 0, 0, 199, 0, 0, 0, 68, 0, 0, 0, 214, 0, 0, 0, 122, 0, 0, 0, 219, 0, 0, 0, 38, 0, 0, 0, 125, 0, 0, 0, 29, 0, 0, 0, 184, 0, 0, 0, 225, 0, 0, 0, 222, 0, 0, 0, 157, 0, 0, 0, 122, 0, 0, 0, 125, 0, 0, 0, 23, 0, 0, 0, 126, 0, 0, 0, 28, 0, 0, 0, 55, 0, 0, 0, 4, 0, 0, 0, 141, 0, 0, +0, 45, 0, 0, 0, 124, 0, 0, 0, 94, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 30, 0, 0, 0, 175, 0, 0, 0, 199, 0, 0, 0, 27, 0, 0, 0, 51, 0, 0, 0, 72, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 246, 0, 0, 0, 242, 0, 0, 0, 202, 0, 0, 0, 15, 0, 0, 0, 39, 0, 0, 0, 27, 0, 0, 0, 99, 0, 0, 0, 18, 0, 0, 0, 126, 0, 0, 0, 2, 0, 0, 0, 29, 0, 0, 0, 73, 0, 0, 0, 192, 0, 0, 0, 93, 0, 0, 0, 121, 0, 0, 0, 135, 0, 0, 0, 239, 0, 0, 0, 94, 0, 0, 0, 122, 0, 0, 0, 47, 0, 0, 0, 31, 0, 0, 0, 102, 0, 0, 0, 85, 0, 0, 0, 216, 0, +0, 0, 9, 0, 0, 0, 217, 0, 0, 0, 97, 0, 0, 0, 84, 0, 0, 0, 131, 0, 0, 0, 2, 0, 0, 0, 24, 0, 0, 0, 130, 0, 0, 0, 147, 0, 0, 0, 153, 0, 0, 0, 7, 0, 0, 0, 208, 0, 0, 0, 167, 0, 0, 0, 218, 0, 0, 0, 216, 0, 0, 0, 117, 0, 0, 0, 137, 0, 0, 0, 250, 0, 0, 0, 242, 0, 0, 0, 217, 0, 0, 0, 163, 0, 0, 0, 184, 0, 0, 0, 107, 0, 0, 0, 90, 0, 0, 0, 53, 0, 0, 0, 40, 0, 0, 0, 210, 0, 0, 0, 107, 0, 0, 0, 89, 0, 0, 0, 194, 0, 0, 0, 248, 0, 0, 0, 69, 0, 0, 0, 226, 0, 0, 0, 188, 0, 0, 0, 6, 0, 0, 0, 101, 0, 0, 0, 192, 0, +0, 0, 163, 0, 0, 0, 136, 0, 0, 0, 81, 0, 0, 0, 149, 0, 0, 0, 252, 0, 0, 0, 150, 0, 0, 0, 148, 0, 0, 0, 120, 0, 0, 0, 232, 0, 0, 0, 13, 0, 0, 0, 139, 0, 0, 0, 65, 0, 0, 0, 201, 0, 0, 0, 194, 0, 0, 0, 88, 0, 0, 0, 72, 0, 0, 0, 117, 0, 0, 0, 16, 0, 0, 0, 47, 0, 0, 0, 205, 0, 0, 0, 42, 0, 0, 0, 201, 0, 0, 0, 160, 0, 0, 0, 109, 0, 0, 0, 15, 0, 0, 0, 221, 0, 0, 0, 156, 0, 0, 0, 152, 0, 0, 0, 38, 0, 0, 0, 61, 0, 0, 0, 47, 0, 0, 0, 102, 0, 0, 0, 41, 0, 0, 0, 27, 0, 0, 0, 4, 0, 0, 0, 137, 0, 0, 0, 189, 0, +0, 0, 126, 0, 0, 0, 238, 0, 0, 0, 110, 0, 0, 0, 221, 0, 0, 0, 183, 0, 0, 0, 14, 0, 0, 0, 239, 0, 0, 0, 176, 0, 0, 0, 12, 0, 0, 0, 180, 0, 0, 0, 252, 0, 0, 0, 127, 0, 0, 0, 194, 0, 0, 0, 201, 0, 0, 0, 58, 0, 0, 0, 60, 0, 0, 0, 100, 0, 0, 0, 239, 0, 0, 0, 69, 0, 0, 0, 68, 0, 0, 0, 175, 0, 0, 0, 138, 0, 0, 0, 144, 0, 0, 0, 101, 0, 0, 0, 118, 0, 0, 0, 161, 0, 0, 0, 76, 0, 0, 0, 112, 0, 0, 0, 75, 0, 0, 0, 14, 0, 0, 0, 160, 0, 0, 0, 131, 0, 0, 0, 112, 0, 0, 0, 19, 0, 0, 0, 164, 0, 0, 0, 175, 0, 0, 0, 184, +0, 0, 0, 56, 0, 0, 0, 25, 0, 0, 0, 34, 0, 0, 0, 101, 0, 0, 0, 9, 0, 0, 0, 180, 0, 0, 0, 2, 0, 0, 0, 79, 0, 0, 0, 6, 0, 0, 0, 248, 0, 0, 0, 23, 0, 0, 0, 206, 0, 0, 0, 70, 0, 0, 0, 69, 0, 0, 0, 218, 0, 0, 0, 80, 0, 0, 0, 124, 0, 0, 0, 138, 0, 0, 0, 209, 0, 0, 0, 78, 0, 0, 0, 247, 0, 0, 0, 212, 0, 0, 0, 22, 0, 0, 0, 108, 0, 0, 0, 78, 0, 0, 0, 149, 0, 0, 0, 157, 0, 0, 0, 93, 0, 0, 0, 15, 0, 0, 0, 145, 0, 0, 0, 43, 0, 0, 0, 82, 0, 0, 0, 254, 0, 0, 0, 92, 0, 0, 0, 52, 0, 0, 0, 229, 0, 0, 0, 48, 0, 0, 0, +230, 0, 0, 0, 164, 0, 0, 0, 59, 0, 0, 0, 243, 0, 0, 0, 243, 0, 0, 0, 52, 0, 0, 0, 8, 0, 0, 0, 169, 0, 0, 0, 74, 0, 0, 0, 160, 0, 0, 0, 181, 0, 0, 0, 110, 0, 0, 0, 179, 0, 0, 0, 9, 0, 0, 0, 10, 0, 0, 0, 38, 0, 0, 0, 217, 0, 0, 0, 94, 0, 0, 0, 163, 0, 0, 0, 15, 0, 0, 0, 235, 0, 0, 0, 162, 0, 0, 0, 243, 0, 0, 0, 32, 0, 0, 0, 59, 0, 0, 0, 55, 0, 0, 0, 212, 0, 0, 0, 228, 0, 0, 0, 158, 0, 0, 0, 206, 0, 0, 0, 6, 0, 0, 0, 61, 0, 0, 0, 83, 0, 0, 0, 237, 0, 0, 0, 174, 0, 0, 0, 43, 0, 0, 0, 235, 0, 0, 0, 182, +0, 0, 0, 36, 0, 0, 0, 10, 0, 0, 0, 17, 0, 0, 0, 163, 0, 0, 0, 15, 0, 0, 0, 214, 0, 0, 0, 127, 0, 0, 0, 164, 0, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 219, 0, 0, 0, 159, 0, 0, 0, 44, 0, 0, 0, 252, 0, 0, 0, 214, 0, 0, 0, 178, 0, 0, 0, 30, 0, 0, 0, 46, 0, 0, +0, 82, 0, 0, 0, 122, 0, 0, 0, 6, 0, 0, 0, 135, 0, 0, 0, 45, 0, 0, 0, 134, 0, 0, 0, 114, 0, 0, 0, 43, 0, 0, 0, 109, 0, 0, 0, 144, 0, 0, 0, 119, 0, 0, 0, 70, 0, 0, 0, 67, 0, 0, 0, 181, 0, 0, 0, 122, 0, 0, 0, 248, 0, 0, 0, 96, 0, 0, 0, 125, 0, 0, 0, 145, 0, 0, 0, 96, 0, 0, 0, 91, 0, 0, 0, 157, 0, 0, 0, 158, 0, 0, 0, 7, 0, 0, 0, 151, 0, 0, 0, 135, 0, 0, 0, 199, 0, 0, 0, 4, 0, 0, 0, 28, 0, 0, 0, 56, 0, 0, 0, 1, 0, 0, 0, 57, 0, 0, 0, 88, 0, 0, 0, 199, 0, 0, 0, 133, 0, 0, 0, 163, 0, 0, 0, 252, 0, 0, 0, +100, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 37, 0, 0, 0, 162, 0, 0, 0, 191, 0, 0, 0, 80, 0, 0, 0, 148, 0, 0, 0, 202, 0, 0, 0, 38, 0, 0, 0, 49, 0, 0, 0, 69, 0, 0, 0, 10, 0, 0, 0, 36, 0, 0, 0, 210, 0, 0, 0, 81, 0, 0, 0, 41, 0, 0, 0, 81, 0, 0, 0, 22, 0, 0, 0, 77, 0, 0, 0, 74, 0, 0, 0, 215, 0, 0, 0, 152, 0, 0, 0, 113, 0, 0, 0, 87, 0, 0, 0, 172, 0, 0, 0, 125, 0, 0, 0, 139, 0, 0, 0, 55, 0, 0, 0, 189, 0, 0, 0, 99, 0, 0, 0, 255, 0, 0, 0, 135, 0, 0, 0, 177, 0, 0, 0, 73, 0, 0, 0, 149, 0, 0, 0, 32, 0, 0, 0, 124, +0, 0, 0, 207, 0, 0, 0, 124, 0, 0, 0, 89, 0, 0, 0, 196, 0, 0, 0, 145, 0, 0, 0, 156, 0, 0, 0, 239, 0, 0, 0, 208, 0, 0, 0, 219, 0, 0, 0, 96, 0, 0, 0, 9, 0, 0, 0, 157, 0, 0, 0, 70, 0, 0, 0, 203, 0, 0, 0, 120, 0, 0, 0, 148, 0, 0, 0, 144, 0, 0, 0, 228, 0, 0, 0, 69, 0, 0, 0, 179, 0, 0, 0, 246, 0, 0, 0, 217, 0, 0, 0, 246, 0, 0, 0, 87, 0, 0, 0, 116, 0, 0, 0, 213, 0, 0, 0, 248, 0, 0, 0, 131, 0, 0, 0, 79, 0, 0, 0, 57, 0, 0, 0, 201, 0, 0, 0, 189, 0, 0, 0, 136, 0, 0, 0, 194, 0, 0, 0, 87, 0, 0, 0, 33, 0, 0, 0, +31, 0, 0, 0, 36, 0, 0, 0, 50, 0, 0, 0, 104, 0, 0, 0, 248, 0, 0, 0, 199, 0, 0, 0, 33, 0, 0, 0, 95, 0, 0, 0, 11, 0, 0, 0, 42, 0, 0, 0, 54, 0, 0, 0, 104, 0, 0, 0, 252, 0, 0, 0, 95, 0, 0, 0, 182, 0, 0, 0, 79, 0, 0, 0, 165, 0, 0, 0, 227, 0, 0, 0, 157, 0, 0, 0, 36, 0, 0, 0, 47, 0, 0, 0, 192, 0, 0, 0, 147, 0, 0, 0, 97, 0, 0, 0, 207, 0, 0, 0, 248, 0, 0, 0, 10, 0, 0, 0, 237, 0, 0, 0, 225, 0, 0, 0, 219, 0, 0, 0, 39, 0, 0, 0, 236, 0, 0, 0, 14, 0, 0, 0, 20, 0, 0, 0, 50, 0, 0, 0, 95, 0, 0, 0, 142, 0, 0, 0, 161, +0, 0, 0, 98, 0, 0, 0, 65, 0, 0, 0, 22, 0, 0, 0, 149, 0, 0, 0, 33, 0, 0, 0, 1, 0, 0, 0, 206, 0, 0, 0, 149, 0, 0, 0, 91, 0, 0, 0, 14, 0, 0, 0, 87, 0, 0, 0, 199, 0, 0, 0, 185, 0, 0, 0, 98, 0, 0, 0, 181, 0, 0, 0, 40, 0, 0, 0, 202, 0, 0, 0, 17, 0, 0, 0, 236, 0, 0, 0, 180, 0, 0, 0, 70, 0, 0, 0, 6, 0, 0, 0, 115, 0, 0, 0, 38, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 102, 0, 0, 0, 125, 0, 0, 0, 238, 0, 0, 0, 95, 0, 0, 0, 178, 0, 0, 0, 86, 0, 0, 0, 253, 0, 0, 0, 42, 0, 0, 0, 8, 0, 0, 0, 146, 0, 0, 0, 103, 0, 0, +0, 119, 0, 0, 0, 86, 0, 0, 0, 161, 0, 0, 0, 255, 0, 0, 0, 196, 0, 0, 0, 197, 0, 0, 0, 149, 0, 0, 0, 240, 0, 0, 0, 227, 0, 0, 0, 58, 0, 0, 0, 10, 0, 0, 0, 202, 0, 0, 0, 148, 0, 0, 0, 77, 0, 0, 0, 158, 0, 0, 0, 126, 0, 0, 0, 61, 0, 0, 0, 185, 0, 0, 0, 110, 0, 0, 0, 182, 0, 0, 0, 176, 0, 0, 0, 206, 0, 0, 0, 164, 0, 0, 0, 48, 0, 0, 0, 137, 0, 0, 0, 153, 0, 0, 0, 233, 0, 0, 0, 173, 0, 0, 0, 17, 0, 0, 0, 89, 0, 0, 0, 246, 0, 0, 0, 72, 0, 0, 0, 149, 0, 0, 0, 161, 0, 0, 0, 111, 0, 0, 0, 95, 0, 0, 0, 183, +0, 0, 0, 165, 0, 0, 0, 187, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 210, 0, 0, 0, 138, 0, 0, 0, 214, 0, 0, 0, 37, 0, 0, 0, 38, 0, 0, 0, 27, 0, 0, 0, 178, 0, 0, 0, 13, 0, 0, 0, 55, 0, 0, 0, 106, 0, 0, 0, 5, 0, 0, 0, 244, 0, 0, 0, 157, 0, 0, 0, 62, 0, 0, 0, 23, 0, 0, 0, 42, 0, 0, 0, 67, 0, 0, 0, 210, 0, 0, 0, 58, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 153, 0, 0, 0, 147, 0, 0, 0, 209, 0, 0, 0, 154, 0, 0, 0, 114, 0, 0, 0, 243, 0, 0, 0, 169, 0, 0, 0, 22, 0, 0, 0, 189, 0, 0, 0, 180, 0, 0, 0, 76, 0, 0, 0, 221, 0, 0, 0, 249, 0, 0, 0, 212, 0, 0, 0, 178, 0, 0, 0, 100, 0, 0, 0, 154, 0, 0, 0, 211, 0, 0, 0, 5, 0, 0, 0, 228, 0, 0, 0, 163, 0, 0, 0, 115, 0, 0, 0, 28, 0, 0, 0, 203, 0, 0, 0, 126, 0, 0, 0, 87, 0, 0, 0, 103, 0, 0, 0, 255, 0, 0, +0, 4, 0, 0, 0, 179, 0, 0, 0, 16, 0, 0, 0, 185, 0, 0, 0, 75, 0, 0, 0, 164, 0, 0, 0, 173, 0, 0, 0, 208, 0, 0, 0, 109, 0, 0, 0, 97, 0, 0, 0, 35, 0, 0, 0, 180, 0, 0, 0, 175, 0, 0, 0, 52, 0, 0, 0, 169, 0, 0, 0, 170, 0, 0, 0, 101, 0, 0, 0, 236, 0, 0, 0, 217, 0, 0, 0, 105, 0, 0, 0, 227, 0, 0, 0, 133, 0, 0, 0, 205, 0, 0, 0, 204, 0, 0, 0, 231, 0, 0, 0, 176, 0, 0, 0, 155, 0, 0, 0, 65, 0, 0, 0, 193, 0, 0, 0, 28, 0, 0, 0, 249, 0, 0, 0, 160, 0, 0, 0, 250, 0, 0, 0, 183, 0, 0, 0, 19, 0, 0, 0, 4, 0, 0, 0, 253, 0, +0, 0, 136, 0, 0, 0, 60, 0, 0, 0, 12, 0, 0, 0, 208, 0, 0, 0, 9, 0, 0, 0, 82, 0, 0, 0, 81, 0, 0, 0, 79, 0, 0, 0, 6, 0, 0, 0, 25, 0, 0, 0, 204, 0, 0, 0, 195, 0, 0, 0, 187, 0, 0, 0, 222, 0, 0, 0, 128, 0, 0, 0, 197, 0, 0, 0, 51, 0, 0, 0, 188, 0, 0, 0, 249, 0, 0, 0, 243, 0, 0, 0, 23, 0, 0, 0, 54, 0, 0, 0, 221, 0, 0, 0, 198, 0, 0, 0, 222, 0, 0, 0, 232, 0, 0, 0, 155, 0, 0, 0, 93, 0, 0, 0, 121, 0, 0, 0, 27, 0, 0, 0, 101, 0, 0, 0, 10, 0, 0, 0, 190, 0, 0, 0, 81, 0, 0, 0, 87, 0, 0, 0, 173, 0, 0, 0, 80, 0, 0, +0, 121, 0, 0, 0, 8, 0, 0, 0, 113, 0, 0, 0, 155, 0, 0, 0, 7, 0, 0, 0, 149, 0, 0, 0, 143, 0, 0, 0, 251, 0, 0, 0, 174, 0, 0, 0, 75, 0, 0, 0, 56, 0, 0, 0, 186, 0, 0, 0, 207, 0, 0, 0, 83, 0, 0, 0, 42, 0, 0, 0, 134, 0, 0, 0, 30, 0, 0, 0, 192, 0, 0, 0, 80, 0, 0, 0, 92, 0, 0, 0, 103, 0, 0, 0, 27, 0, 0, 0, 246, 0, 0, 0, 135, 0, 0, 0, 108, 0, 0, 0, 79, 0, 0, 0, 0, 0, 0, 0, 178, 0, 0, 0, 102, 0, 0, 0, 85, 0, 0, 0, 237, 0, 0, 0, 74, 0, 0, 0, 237, 0, 0, 0, 141, 0, 0, 0, 225, 0, 0, 0, 102, 0, 0, 0, 24, 0, 0, 0, +178, 0, 0, 0, 20, 0, 0, 0, 116, 0, 0, 0, 141, 0, 0, 0, 253, 0, 0, 0, 26, 0, 0, 0, 54, 0, 0, 0, 15, 0, 0, 0, 38, 0, 0, 0, 92, 0, 0, 0, 139, 0, 0, 0, 137, 0, 0, 0, 243, 0, 0, 0, 171, 0, 0, 0, 242, 0, 0, 0, 243, 0, 0, 0, 36, 0, 0, 0, 103, 0, 0, 0, 253, 0, 0, 0, 112, 0, 0, 0, 253, 0, 0, 0, 78, 0, 0, 0, 42, 0, 0, 0, 193, 0, 0, 0, 58, 0, 0, 0, 202, 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, 0, 216, 0, 0, 0, 236, 0, 0, 0, 116, 0, 0, 0, 103, 0, 0, 0, 239, 0, 0, 0, 97, 0, 0, 0, 224, 0, 0, 0, 40, 0, 0, 0, 208, 0, 0, +0, 150, 0, 0, 0, 244, 0, 0, 0, 72, 0, 0, 0, 222, 0, 0, 0, 129, 0, 0, 0, 227, 0, 0, 0, 239, 0, 0, 0, 220, 0, 0, 0, 170, 0, 0, 0, 125, 0, 0, 0, 243, 0, 0, 0, 182, 0, 0, 0, 85, 0, 0, 0, 166, 0, 0, 0, 101, 0, 0, 0, 235, 0, 0, 0, 203, 0, 0, 0, 197, 0, 0, 0, 112, 0, 0, 0, 145, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 147, 0, 0, 0, 13, 0, 0, 0, 200, 0, 0, 0, 208, 0, 0, 0, 239, 0, 0, 0, 98, 0, 0, 0, 232, 0, 0, 0, 111, 0, 0, 0, 130, 0, 0, 0, 227, 0, 0, 0, 105, 0, 0, 0, 61, 0, 0, 0, 145, 0, 0, 0, 127, 0, 0, 0, 49, +0, 0, 0, 225, 0, 0, 0, 38, 0, 0, 0, 53, 0, 0, 0, 60, 0, 0, 0, 74, 0, 0, 0, 47, 0, 0, 0, 171, 0, 0, 0, 196, 0, 0, 0, 154, 0, 0, 0, 94, 0, 0, 0, 171, 0, 0, 0, 27, 0, 0, 0, 181, 0, 0, 0, 229, 0, 0, 0, 43, 0, 0, 0, 195, 0, 0, 0, 14, 0, 0, 0, 41, 0, 0, 0, 176, 0, 0, 0, 208, 0, 0, 0, 115, 0, 0, 0, 230, 0, 0, 0, 79, 0, 0, 0, 100, 0, 0, 0, 242, 0, 0, 0, 188, 0, 0, 0, 228, 0, 0, 0, 228, 0, 0, 0, 225, 0, 0, 0, 154, 0, 0, 0, 82, 0, 0, 0, 51, 0, 0, 0, 47, 0, 0, 0, 189, 0, 0, 0, 204, 0, 0, 0, 3, 0, 0, 0, 238, +0, 0, 0, 138, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 246, 0, 0, 0, 219, 0, 0, 0, 13, 0, 0, 0, 34, 0, 0, 0, 61, 0, 0, 0, 181, 0, 0, 0, 20, 0, 0, 0, 117, 0, 0, 0, 49, 0, 0, 0, 240, 0, 0, 0, 129, 0, 0, 0, 226, 0, 0, +0, 185, 0, 0, 0, 55, 0, 0, 0, 162, 0, 0, 0, 169, 0, 0, 0, 132, 0, 0, 0, 17, 0, 0, 0, 154, 0, 0, 0, 7, 0, 0, 0, 181, 0, 0, 0, 83, 0, 0, 0, 137, 0, 0, 0, 120, 0, 0, 0, 169, 0, 0, 0, 48, 0, 0, 0, 39, 0, 0, 0, 161, 0, 0, 0, 241, 0, 0, 0, 78, 0, 0, 0, 92, 0, 0, 0, 46, 0, 0, 0, 139, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 251, 0, 0, 0, 77, 0, 0, 0, 220, 0, 0, 0, 203, 0, 0, 0, 23, 0, 0, 0, 53, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 183, 0, 0, 0, 140, 0, 0, 0, 254, 0, 0, 0, 74, 0, 0, 0, 228, 0, 0, 0, 78, 0, 0, 0, +153, 0, 0, 0, 78, 0, 0, 0, 168, 0, 0, 0, 116, 0, 0, 0, 84, 0, 0, 0, 93, 0, 0, 0, 92, 0, 0, 0, 150, 0, 0, 0, 163, 0, 0, 0, 18, 0, 0, 0, 85, 0, 0, 0, 54, 0, 0, 0, 49, 0, 0, 0, 23, 0, 0, 0, 92, 0, 0, 0, 206, 0, 0, 0, 36, 0, 0, 0, 239, 0, 0, 0, 123, 0, 0, 0, 134, 0, 0, 0, 242, 0, 0, 0, 15, 0, 0, 0, 119, 0, 0, 0, 232, 0, 0, 0, 92, 0, 0, 0, 125, 0, 0, 0, 135, 0, 0, 0, 56, 0, 0, 0, 45, 0, 0, 0, 239, 0, 0, 0, 175, 0, 0, 0, 242, 0, 0, 0, 140, 0, 0, 0, 114, 0, 0, 0, 46, 0, 0, 0, 235, 0, 0, 0, 182, 0, 0, 0, +85, 0, 0, 0, 75, 0, 0, 0, 110, 0, 0, 0, 241, 0, 0, 0, 78, 0, 0, 0, 138, 0, 0, 0, 14, 0, 0, 0, 154, 0, 0, 0, 108, 0, 0, 0, 76, 0, 0, 0, 37, 0, 0, 0, 234, 0, 0, 0, 134, 0, 0, 0, 194, 0, 0, 0, 209, 0, 0, 0, 79, 0, 0, 0, 183, 0, 0, 0, 62, 0, 0, 0, 168, 0, 0, 0, 92, 0, 0, 0, 141, 0, 0, 0, 102, 0, 0, 0, 129, 0, 0, 0, 37, 0, 0, 0, 237, 0, 0, 0, 197, 0, 0, 0, 76, 0, 0, 0, 5, 0, 0, 0, 185, 0, 0, 0, 216, 0, 0, 0, 214, 0, 0, 0, 112, 0, 0, 0, 190, 0, 0, 0, 115, 0, 0, 0, 130, 0, 0, 0, 232, 0, 0, 0, 161, 0, 0, +0, 229, 0, 0, 0, 30, 0, 0, 0, 113, 0, 0, 0, 213, 0, 0, 0, 38, 0, 0, 0, 78, 0, 0, 0, 109, 0, 0, 0, 195, 0, 0, 0, 167, 0, 0, 0, 79, 0, 0, 0, 34, 0, 0, 0, 69, 0, 0, 0, 38, 0, 0, 0, 162, 0, 0, 0, 126, 0, 0, 0, 22, 0, 0, 0, 247, 0, 0, 0, 247, 0, 0, 0, 99, 0, 0, 0, 220, 0, 0, 0, 134, 0, 0, 0, 1, 0, 0, 0, 42, 0, 0, 0, 113, 0, 0, 0, 56, 0, 0, 0, 92, 0, 0, 0, 51, 0, 0, 0, 195, 0, 0, 0, 206, 0, 0, 0, 48, 0, 0, 0, 255, 0, 0, 0, 249, 0, 0, 0, 44, 0, 0, 0, 145, 0, 0, 0, 113, 0, 0, 0, 138, 0, 0, 0, 114, 0, 0, +0, 140, 0, 0, 0, 68, 0, 0, 0, 9, 0, 0, 0, 40, 0, 0, 0, 213, 0, 0, 0, 35, 0, 0, 0, 201, 0, 0, 0, 143, 0, 0, 0, 243, 0, 0, 0, 132, 0, 0, 0, 69, 0, 0, 0, 198, 0, 0, 0, 154, 0, 0, 0, 94, 0, 0, 0, 255, 0, 0, 0, 210, 0, 0, 0, 199, 0, 0, 0, 87, 0, 0, 0, 147, 0, 0, 0, 163, 0, 0, 0, 193, 0, 0, 0, 105, 0, 0, 0, 221, 0, 0, 0, 98, 0, 0, 0, 15, 0, 0, 0, 218, 0, 0, 0, 92, 0, 0, 0, 48, 0, 0, 0, 89, 0, 0, 0, 93, 0, 0, 0, 233, 0, 0, 0, 76, 0, 0, 0, 146, 0, 0, 0, 126, 0, 0, 0, 80, 0, 0, 0, 39, 0, 0, 0, 114, 0, 0, +0, 215, 0, 0, 0, 12, 0, 0, 0, 214, 0, 0, 0, 105, 0, 0, 0, 150, 0, 0, 0, 129, 0, 0, 0, 53, 0, 0, 0, 132, 0, 0, 0, 148, 0, 0, 0, 53, 0, 0, 0, 139, 0, 0, 0, 108, 0, 0, 0, 170, 0, 0, 0, 98, 0, 0, 0, 134, 0, 0, 0, 110, 0, 0, 0, 28, 0, 0, 0, 21, 0, 0, 0, 243, 0, 0, 0, 108, 0, 0, 0, 179, 0, 0, 0, 255, 0, 0, 0, 101, 0, 0, 0, 27, 0, 0, 0, 162, 0, 0, 0, 155, 0, 0, 0, 89, 0, 0, 0, 226, 0, 0, 0, 169, 0, 0, 0, 101, 0, 0, 0, 136, 0, 0, 0, 196, 0, 0, 0, 80, 0, 0, 0, 250, 0, 0, 0, 187, 0, 0, 0, 59, 0, 0, 0, 110, +0, 0, 0, 95, 0, 0, 0, 68, 0, 0, 0, 1, 0, 0, 0, 202, 0, 0, 0, 151, 0, 0, 0, 212, 0, 0, 0, 221, 0, 0, 0, 246, 0, 0, 0, 205, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 229, 0, 0, 0, 151, 0, 0, 0, 103, 0, 0, 0, 43, 0, 0, 0, 140, 0, 0, 0, 102, 0, 0, 0, 15, 0, 0, 0, 53, 0, 0, 0, 155, 0, 0, 0, 245, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 89, 0, 0, 0, 39, 0, 0, 0, 216, 0, 0, 0, 219, 0, 0, 0, 90, 0, 0, 0, 17, 0, 0, 0, 94, 0, 0, 0, 130, 0, 0, 0, 243, 0, 0, 0, 56, 0, 0, 0, 255, 0, 0, 0, 28, 0, 0, 0, 237, 0, 0, 0, 254, 0, 0, 0, 63, 0, 0, 0, 100, 0, 0, 0, 84, 0, 0, 0, 63, 0, 0, 0, 127, 0, 0, 0, 209, 0, 0, 0, 129, 0, 0, 0, 237, 0, 0, 0, 239, 0, 0, 0, 101, 0, 0, 0, 197, 0, 0, 0, 203, 0, 0, 0, 253, 0, 0, 0, 225, 0, 0, 0, 128, 0, 0, 0, 205, 0, 0, 0, 17, 0, +0, 0, 224, 0, 0, 0, 219, 0, 0, 0, 34, 0, 0, 0, 40, 0, 0, 0, 230, 0, 0, 0, 255, 0, 0, 0, 97, 0, 0, 0, 157, 0, 0, 0, 65, 0, 0, 0, 20, 0, 0, 0, 45, 0, 0, 0, 59, 0, 0, 0, 38, 0, 0, 0, 34, 0, 0, 0, 223, 0, 0, 0, 241, 0, 0, 0, 52, 0, 0, 0, 129, 0, 0, 0, 233, 0, 0, 0, 69, 0, 0, 0, 238, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 139, 0, 0, 0, 166, 0, 0, 0, 63, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 67, 0, 0, 0, 25, 0, 0, 0, 241, 0, 0, 0, 67, 0, 0, 0, 238, 0, 0, 0, 243, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 80, 0, 0, +0, 222, 0, 0, 0, 192, 0, 0, 0, 182, 0, 0, 0, 1, 0, 0, 0, 227, 0, 0, 0, 140, 0, 0, 0, 60, 0, 0, 0, 77, 0, 0, 0, 49, 0, 0, 0, 210, 0, 0, 0, 176, 0, 0, 0, 88, 0, 0, 0, 205, 0, 0, 0, 237, 0, 0, 0, 16, 0, 0, 0, 74, 0, 0, 0, 122, 0, 0, 0, 239, 0, 0, 0, 128, 0, 0, 0, 169, 0, 0, 0, 25, 0, 0, 0, 50, 0, 0, 0, 243, 0, 0, 0, 216, 0, 0, 0, 51, 0, 0, 0, 140, 0, 0, 0, 6, 0, 0, 0, 203, 0, 0, 0, 125, 0, 0, 0, 79, 0, 0, 0, 255, 0, 0, 0, 48, 0, 0, 0, 216, 0, 0, 0, 18, 0, 0, 0, 59, 0, 0, 0, 57, 0, 0, 0, 28, 0, 0, 0, +6, 0, 0, 0, 249, 0, 0, 0, 76, 0, 0, 0, 52, 0, 0, 0, 53, 0, 0, 0, 113, 0, 0, 0, 181, 0, 0, 0, 22, 0, 0, 0, 148, 0, 0, 0, 103, 0, 0, 0, 223, 0, 0, 0, 238, 0, 0, 0, 17, 0, 0, 0, 222, 0, 0, 0, 164, 0, 0, 0, 29, 0, 0, 0, 136, 0, 0, 0, 147, 0, 0, 0, 53, 0, 0, 0, 169, 0, 0, 0, 50, 0, 0, 0, 16, 0, 0, 0, 233, 0, 0, 0, 195, 0, 0, 0, 188, 0, 0, 0, 123, 0, 0, 0, 92, 0, 0, 0, 252, 0, 0, 0, 178, 0, 0, 0, 249, 0, 0, 0, 201, 0, 0, 0, 47, 0, 0, 0, 229, 0, 0, 0, 186, 0, 0, 0, 58, 0, 0, 0, 11, 0, 0, 0, 171, 0, 0, 0, +100, 0, 0, 0, 56, 0, 0, 0, 111, 0, 0, 0, 91, 0, 0, 0, 75, 0, 0, 0, 147, 0, 0, 0, 218, 0, 0, 0, 100, 0, 0, 0, 236, 0, 0, 0, 77, 0, 0, 0, 61, 0, 0, 0, 160, 0, 0, 0, 245, 0, 0, 0, 187, 0, 0, 0, 186, 0, 0, 0, 71, 0, 0, 0, 72, 0, 0, 0, 96, 0, 0, 0, 188, 0, 0, 0, 69, 0, 0, 0, 31, 0, 0, 0, 35, 0, 0, 0, 162, 0, 0, 0, 59, 0, 0, 0, 112, 0, 0, 0, 118, 0, 0, 0, 230, 0, 0, 0, 151, 0, 0, 0, 153, 0, 0, 0, 79, 0, 0, 0, 119, 0, 0, 0, 84, 0, 0, 0, 103, 0, 0, 0, 48, 0, 0, 0, 154, 0, 0, 0, 231, 0, 0, 0, 102, 0, 0, 0, +214, 0, 0, 0, 205, 0, 0, 0, 46, 0, 0, 0, 81, 0, 0, 0, 36, 0, 0, 0, 44, 0, 0, 0, 66, 0, 0, 0, 74, 0, 0, 0, 17, 0, 0, 0, 254, 0, 0, 0, 111, 0, 0, 0, 126, 0, 0, 0, 135, 0, 0, 0, 192, 0, 0, 0, 177, 0, 0, 0, 240, 0, 0, 0, 163, 0, 0, 0, 111, 0, 0, 0, 12, 0, 0, 0, 147, 0, 0, 0, 169, 0, 0, 0, 10, 0, 0, 0, 114, 0, 0, 0, 239, 0, 0, 0, 92, 0, 0, 0, 190, 0, 0, 0, 101, 0, 0, 0, 53, 0, 0, 0, 167, 0, 0, 0, 106, 0, 0, 0, 78, 0, 0, 0, 44, 0, 0, 0, 191, 0, 0, 0, 33, 0, 0, 0, 35, 0, 0, 0, 232, 0, 0, 0, 47, 0, 0, 0, +151, 0, 0, 0, 199, 0, 0, 0, 62, 0, 0, 0, 200, 0, 0, 0, 23, 0, 0, 0, 172, 0, 0, 0, 30, 0, 0, 0, 123, 0, 0, 0, 239, 0, 0, 0, 33, 0, 0, 0, 229, 0, 0, 0, 64, 0, 0, 0, 204, 0, 0, 0, 30, 0, 0, 0, 220, 0, 0, 0, 214, 0, 0, 0, 189, 0, 0, 0, 151, 0, 0, 0, 122, 0, 0, 0, 124, 0, 0, 0, 117, 0, 0, 0, 134, 0, 0, 0, 122, 0, 0, 0, 37, 0, 0, 0, 90, 0, 0, 0, 110, 0, 0, 0, 124, 0, 0, 0, 229, 0, 0, 0, 81, 0, 0, 0, 60, 0, 0, 0, 27, 0, 0, 0, 91, 0, 0, 0, 130, 0, 0, 0, 154, 0, 0, 0, 7, 0, 0, 0, 96, 0, 0, 0, 161, 0, 0, 0, +25, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 136, 0, 0, 0, 166, 0, 0, 0, 171, 0, 0, 0, 143, 0, 0, 0, 227, 0, 0, 0, 58, 0, 0, 0, 73, 0, 0, 0, 248, 0, 0, 0, 254, 0, 0, 0, 52, 0, 0, 0, 231, 0, 0, 0, 106, 0, 0, 0, 178, 0, 0, 0, 254, 0, 0, 0, 64, +0, 0, 0, 38, 0, 0, 0, 116, 0, 0, 0, 87, 0, 0, 0, 76, 0, 0, 0, 246, 0, 0, 0, 212, 0, 0, 0, 153, 0, 0, 0, 206, 0, 0, 0, 93, 0, 0, 0, 123, 0, 0, 0, 47, 0, 0, 0, 103, 0, 0, 0, 214, 0, 0, 0, 90, 0, 0, 0, 228, 0, 0, 0, 78, 0, 0, 0, 92, 0, 0, 0, 130, 0, 0, 0, 179, 0, 0, 0, 189, 0, 0, 0, 85, 0, 0, 0, 37, 0, 0, 0, 246, 0, 0, 0, 106, 0, 0, 0, 147, 0, 0, 0, 164, 0, 0, 0, 2, 0, 0, 0, 198, 0, 0, 0, 125, 0, 0, 0, 92, 0, 0, 0, 177, 0, 0, 0, 43, 0, 0, 0, 91, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 86, 0, 0, 0, 248, +0, 0, 0, 1, 0, 0, 0, 65, 0, 0, 0, 144, 0, 0, 0, 198, 0, 0, 0, 182, 0, 0, 0, 172, 0, 0, 0, 79, 0, 0, 0, 254, 0, 0, 0, 167, 0, 0, 0, 65, 0, 0, 0, 112, 0, 0, 0, 219, 0, 0, 0, 250, 0, 0, 0, 155, 0, 0, 0, 44, 0, 0, 0, 212, 0, 0, 0, 35, 0, 0, 0, 103, 0, 0, 0, 44, 0, 0, 0, 138, 0, 0, 0, 99, 0, 0, 0, 108, 0, 0, 0, 7, 0, 0, 0, 38, 0, 0, 0, 72, 0, 0, 0, 79, 0, 0, 0, 194, 0, 0, 0, 3, 0, 0, 0, 210, 0, 0, 0, 83, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 237, 0, 0, 0, 101, 0, 0, 0, 113, 0, 0, 0, 71, 0, 0, 0, 169, 0, +0, 0, 22, 0, 0, 0, 22, 0, 0, 0, 18, 0, 0, 0, 188, 0, 0, 0, 40, 0, 0, 0, 51, 0, 0, 0, 57, 0, 0, 0, 192, 0, 0, 0, 250, 0, 0, 0, 250, 0, 0, 0, 205, 0, 0, 0, 51, 0, 0, 0, 67, 0, 0, 0, 199, 0, 0, 0, 151, 0, 0, 0, 118, 0, 0, 0, 155, 0, 0, 0, 147, 0, 0, 0, 145, 0, 0, 0, 114, 0, 0, 0, 235, 0, 0, 0, 197, 0, 0, 0, 24, 0, 0, 0, 103, 0, 0, 0, 76, 0, 0, 0, 17, 0, 0, 0, 240, 0, 0, 0, 244, 0, 0, 0, 229, 0, 0, 0, 115, 0, 0, 0, 178, 0, 0, 0, 92, 0, 0, 0, 27, 0, 0, 0, 194, 0, 0, 0, 38, 0, 0, 0, 63, 0, 0, 0, 191, 0, +0, 0, 43, 0, 0, 0, 134, 0, 0, 0, 230, 0, 0, 0, 140, 0, 0, 0, 29, 0, 0, 0, 223, 0, 0, 0, 202, 0, 0, 0, 252, 0, 0, 0, 213, 0, 0, 0, 248, 0, 0, 0, 58, 0, 0, 0, 195, 0, 0, 0, 68, 0, 0, 0, 114, 0, 0, 0, 230, 0, 0, 0, 120, 0, 0, 0, 157, 0, 0, 0, 43, 0, 0, 0, 151, 0, 0, 0, 248, 0, 0, 0, 40, 0, 0, 0, 69, 0, 0, 0, 180, 0, 0, 0, 32, 0, 0, 0, 201, 0, 0, 0, 42, 0, 0, 0, 140, 0, 0, 0, 103, 0, 0, 0, 170, 0, 0, 0, 17, 0, 0, 0, 197, 0, 0, 0, 91, 0, 0, 0, 47, 0, 0, 0, 23, 0, 0, 0, 15, 0, 0, 0, 134, 0, 0, 0, 82, 0, +0, 0, 215, 0, 0, 0, 157, 0, 0, 0, 195, 0, 0, 0, 68, 0, 0, 0, 81, 0, 0, 0, 118, 0, 0, 0, 50, 0, 0, 0, 101, 0, 0, 0, 180, 0, 0, 0, 55, 0, 0, 0, 129, 0, 0, 0, 153, 0, 0, 0, 70, 0, 0, 0, 55, 0, 0, 0, 98, 0, 0, 0, 237, 0, 0, 0, 207, 0, 0, 0, 100, 0, 0, 0, 157, 0, 0, 0, 114, 0, 0, 0, 64, 0, 0, 0, 122, 0, 0, 0, 76, 0, 0, 0, 11, 0, 0, 0, 118, 0, 0, 0, 42, 0, 0, 0, 251, 0, 0, 0, 86, 0, 0, 0, 51, 0, 0, 0, 167, 0, 0, 0, 144, 0, 0, 0, 124, 0, 0, 0, 195, 0, 0, 0, 111, 0, 0, 0, 23, 0, 0, 0, 165, 0, 0, 0, 160, +0, 0, 0, 103, 0, 0, 0, 114, 0, 0, 0, 23, 0, 0, 0, 234, 0, 0, 0, 126, 0, 0, 0, 99, 0, 0, 0, 20, 0, 0, 0, 131, 0, 0, 0, 222, 0, 0, 0, 193, 0, 0, 0, 113, 0, 0, 0, 45, 0, 0, 0, 65, 0, 0, 0, 50, 0, 0, 0, 122, 0, 0, 0, 243, 0, 0, 0, 209, 0, 0, 0, 43, 0, 0, 0, 216, 0, 0, 0, 42, 0, 0, 0, 166, 0, 0, 0, 70, 0, 0, 0, 54, 0, 0, 0, 172, 0, 0, 0, 204, 0, 0, 0, 107, 0, 0, 0, 124, 0, 0, 0, 249, 0, 0, 0, 184, 0, 0, 0, 139, 0, 0, 0, 8, 0, 0, 0, 92, 0, 0, 0, 208, 0, 0, 0, 125, 0, 0, 0, 143, 0, 0, 0, 115, 0, 0, 0, 234, +0, 0, 0, 32, 0, 0, 0, 218, 0, 0, 0, 134, 0, 0, 0, 202, 0, 0, 0, 0, 0, 0, 0, 199, 0, 0, 0, 173, 0, 0, 0, 115, 0, 0, 0, 77, 0, 0, 0, 233, 0, 0, 0, 232, 0, 0, 0, 169, 0, 0, 0, 218, 0, 0, 0, 31, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 221, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 156, 0, 0, 0, 178, 0, 0, 0, 97, 0, 0, 0, 10, 0, 0, 0, 152, 0, 0, 0, 42, 0, 0, 0, 165, 0, 0, 0, 215, 0, 0, 0, 238, 0, 0, 0, 169, 0, 0, 0, 172, 0, 0, 0, 101, 0, 0, 0, 203, 0, 0, 0, 10, 0, 0, 0, 30, 0, 0, 0, 226, 0, 0, 0, 190, 0, 0, 0, 220, 0, 0, 0, 133, 0, 0, 0, 89, 0, 0, 0, 15, 0, 0, 0, 156, 0, 0, 0, 166, 0, 0, 0, 87, 0, 0, 0, 52, 0, 0, 0, 165, 0, 0, 0, 135, 0, 0, 0, 235, 0, 0, 0, 123, 0, 0, 0, 30, 0, 0, 0, 12, 0, 0, 0, 60, 0, 0, 0, 47, 0, 0, 0, 189, 0, 0, 0, 132, 0, 0, 0, 99, 0, 0, +0, 13, 0, 0, 0, 181, 0, 0, 0, 160, 0, 0, 0, 240, 0, 0, 0, 75, 0, 0, 0, 158, 0, 0, 0, 147, 0, 0, 0, 198, 0, 0, 0, 52, 0, 0, 0, 154, 0, 0, 0, 52, 0, 0, 0, 255, 0, 0, 0, 115, 0, 0, 0, 25, 0, 0, 0, 47, 0, 0, 0, 110, 0, 0, 0, 84, 0, 0, 0, 69, 0, 0, 0, 44, 0, 0, 0, 146, 0, 0, 0, 49, 0, 0, 0, 118, 0, 0, 0, 52, 0, 0, 0, 241, 0, 0, 0, 178, 0, 0, 0, 38, 0, 0, 0, 232, 0, 0, 0, 116, 0, 0, 0, 10, 0, 0, 0, 103, 0, 0, 0, 144, 0, 0, 0, 109, 0, 0, 0, 12, 0, 0, 0, 76, 0, 0, 0, 204, 0, 0, 0, 192, 0, 0, 0, 230, 0, 0, +0, 189, 0, 0, 0, 167, 0, 0, 0, 94, 0, 0, 0, 85, 0, 0, 0, 140, 0, 0, 0, 205, 0, 0, 0, 88, 0, 0, 0, 155, 0, 0, 0, 17, 0, 0, 0, 162, 0, 0, 0, 187, 0, 0, 0]).concat([75, 0, 0, 0, 177, 0, 0, 0, 67, 0, 0, 0, 4, 0, 0, 0, 60, 0, 0, 0, 85, 0, 0, 0, 237, 0, 0, 0, 35, 0, 0, 0, 254, 0, 0, 0, 205, 0, 0, 0, 177, 0, 0, 0, 83, 0, 0, 0, 5, 0, 0, 0, 251, 0, 0, 0, 117, 0, 0, 0, 245, 0, 0, 0, 1, 0, 0, 0, 175, 0, 0, 0, 56, 0, 0, 0, 114, 0, 0, 0, 88, 0, 0, 0, 252, 0, 0, 0, 4, 0, 0, 0, 41, 0, 0, 0, 52, 0, 0, 0, 122, 0, +0, 0, 103, 0, 0, 0, 162, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 110, 0, 0, 0, 208, 0, 0, 0, 43, 0, 0, 0, 115, 0, 0, 0, 213, 0, 0, 0, 184, 0, 0, 0, 228, 0, 0, 0, 48, 0, 0, 0, 150, 0, 0, 0, 173, 0, 0, 0, 69, 0, 0, 0, 223, 0, 0, 0, 166, 0, 0, 0, 92, 0, 0, 0, 13, 0, 0, 0, 136, 0, 0, 0, 26, 0, 0, 0, 144, 0, 0, 0, 126, 0, 0, 0, 220, 0, 0, 0, 216, 0, 0, 0, 254, 0, 0, 0, 193, 0, 0, 0, 47, 0, 0, 0, 93, 0, 0, 0, 103, 0, 0, 0, 238, 0, 0, 0, 103, 0, 0, 0, 47, 0, 0, 0, 237, 0, 0, 0, 111, 0, 0, 0, 85, 0, 0, 0, 67, +0, 0, 0, 95, 0, 0, 0, 135, 0, 0, 0, 20, 0, 0, 0, 53, 0, 0, 0, 66, 0, 0, 0, 211, 0, 0, 0, 117, 0, 0, 0, 174, 0, 0, 0, 213, 0, 0, 0, 211, 0, 0, 0, 133, 0, 0, 0, 26, 0, 0, 0, 118, 0, 0, 0, 135, 0, 0, 0, 200, 0, 0, 0, 160, 0, 0, 0, 110, 0, 0, 0, 225, 0, 0, 0, 176, 0, 0, 0, 173, 0, 0, 0, 106, 0, 0, 0, 74, 0, 0, 0, 52, 0, 0, 0, 113, 0, 0, 0, 237, 0, 0, 0, 124, 0, 0, 0, 214, 0, 0, 0, 68, 0, 0, 0, 3, 0, 0, 0, 101, 0, 0, 0, 74, 0, 0, 0, 92, 0, 0, 0, 92, 0, 0, 0, 4, 0, 0, 0, 245, 0, 0, 0, 36, 0, 0, 0, 63, +0, 0, 0, 176, 0, 0, 0, 22, 0, 0, 0, 94, 0, 0, 0, 140, 0, 0, 0, 178, 0, 0, 0, 210, 0, 0, 0, 197, 0, 0, 0, 32, 0, 0, 0, 152, 0, 0, 0, 131, 0, 0, 0, 194, 0, 0, 0, 55, 0, 0, 0, 160, 0, 0, 0, 65, 0, 0, 0, 168, 0, 0, 0, 72, 0, 0, 0, 92, 0, 0, 0, 95, 0, 0, 0, 191, 0, 0, 0, 200, 0, 0, 0, 250, 0, 0, 0, 36, 0, 0, 0, 224, 0, 0, 0, 89, 0, 0, 0, 44, 0, 0, 0, 189, 0, 0, 0, 246, 0, 0, 0, 129, 0, 0, 0, 126, 0, 0, 0, 136, 0, 0, 0, 230, 0, 0, 0, 202, 0, 0, 0, 4, 0, 0, 0, 216, 0, 0, 0, 93, 0, 0, 0, 96, 0, 0, 0, 187, +0, 0, 0, 116, 0, 0, 0, 167, 0, 0, 0, 11, 0, 0, 0, 33, 0, 0, 0, 19, 0, 0, 0, 145, 0, 0, 0, 191, 0, 0, 0, 119, 0, 0, 0, 122, 0, 0, 0, 51, 0, 0, 0, 188, 0, 0, 0, 233, 0, 0, 0, 7, 0, 0, 0, 57, 0, 0, 0, 10, 0, 0, 0, 221, 0, 0, 0, 125, 0, 0, 0, 6, 0, 0, 0, 16, 0, 0, 0, 154, 0, 0, 0, 238, 0, 0, 0, 71, 0, 0, 0, 115, 0, 0, 0, 27, 0, 0, 0, 21, 0, 0, 0, 90, 0, 0, 0, 251, 0, 0, 0, 205, 0, 0, 0, 77, 0, 0, 0, 208, 0, 0, 0, 210, 0, 0, 0, 58, 0, 0, 0, 1, 0, 0, 0, 186, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 213, 0, 0, 0, 57, 0, 0, 0, 74, 0, 0, 0, 11, 0, 0, 0, 32, 0, 0, 0, 106, 0, 0, 0, 67, 0, 0, 0, 160, 0, 0, 0, 7, 0, 0, 0, 130, 0, 0, 0, 94, 0, 0, 0, 73, 0, 0, 0, 124, 0, 0, 0, 201, 0, 0, 0, 71, 0, 0, 0, 241, 0, 0, 0, 124, 0, 0, 0, 55, 0, 0, 0, 185, +0, 0, 0, 35, 0, 0, 0, 239, 0, 0, 0, 107, 0, 0, 0, 70, 0, 0, 0, 69, 0, 0, 0, 140, 0, 0, 0, 69, 0, 0, 0, 118, 0, 0, 0, 223, 0, 0, 0, 20, 0, 0, 0, 107, 0, 0, 0, 110, 0, 0, 0, 66, 0, 0, 0, 201, 0, 0, 0, 202, 0, 0, 0, 41, 0, 0, 0, 76, 0, 0, 0, 118, 0, 0, 0, 55, 0, 0, 0, 218, 0, 0, 0, 138, 0, 0, 0, 45, 0, 0, 0, 124, 0, 0, 0, 58, 0, 0, 0, 88, 0, 0, 0, 242, 0, 0, 0, 3, 0, 0, 0, 180, 0, 0, 0, 181, 0, 0, 0, 185, 0, 0, 0, 26, 0, 0, 0, 19, 0, 0, 0, 45, 0, 0, 0, 222, 0, 0, 0, 95, 0, 0, 0, 107, 0, 0, 0, 157, 0, +0, 0, 186, 0, 0, 0, 82, 0, 0, 0, 201, 0, 0, 0, 93, 0, 0, 0, 179, 0, 0, 0, 243, 0, 0, 0, 48, 0, 0, 0, 76, 0, 0, 0, 111, 0, 0, 0, 254, 0, 0, 0, 107, 0, 0, 0, 12, 0, 0, 0, 98, 0, 0, 0, 215, 0, 0, 0, 72, 0, 0, 0, 113, 0, 0, 0, 239, 0, 0, 0, 177, 0, 0, 0, 133, 0, 0, 0, 121, 0, 0, 0, 192, 0, 0, 0, 237, 0, 0, 0, 36, 0, 0, 0, 177, 0, 0, 0, 8, 0, 0, 0, 147, 0, 0, 0, 118, 0, 0, 0, 142, 0, 0, 0, 247, 0, 0, 0, 56, 0, 0, 0, 142, 0, 0, 0, 235, 0, 0, 0, 254, 0, 0, 0, 128, 0, 0, 0, 64, 0, 0, 0, 175, 0, 0, 0, 144, +0, 0, 0, 100, 0, 0, 0, 73, 0, 0, 0, 74, 0, 0, 0, 136, 0, 0, 0, 218, 0, 0, 0, 193, 0, 0, 0, 152, 0, 0, 0, 68, 0, 0, 0, 60, 0, 0, 0, 83, 0, 0, 0, 78, 0, 0, 0, 219, 0, 0, 0, 75, 0, 0, 0, 185, 0, 0, 0, 18, 0, 0, 0, 95, 0, 0, 0, 205, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 239, 0, 0, 0, 117, 0, 0, 0, 231, 0, 0, 0, 177, 0, 0, 0, 58, 0, 0, 0, 229, 0, 0, 0, 7, 0, 0, 0, 250, 0, 0, 0, 202, 0, 0, 0, 101, 0, 0, 0, 123, 0, 0, 0, 114, 0, 0, 0, 16, 0, 0, 0, 100, 0, 0, 0, 127, 0, 0, 0, 61, 0, 0, 0, 129, 0, 0, 0, 240, 0, +0, 0, 235, 0, 0, 0, 22, 0, 0, 0, 253, 0, 0, 0, 88, 0, 0, 0, 51, 0, 0, 0, 141, 0, 0, 0, 124, 0, 0, 0, 26, 0, 0, 0, 251, 0, 0, 0, 32, 0, 0, 0, 44, 0, 0, 0, 138, 0, 0, 0, 238, 0, 0, 0, 144, 0, 0, 0, 187, 0, 0, 0, 51, 0, 0, 0, 109, 0, 0, 0, 69, 0, 0, 0, 233, 0, 0, 0, 142, 0, 0, 0, 153, 0, 0, 0, 133, 0, 0, 0, 225, 0, 0, 0, 8, 0, 0, 0, 31, 0, 0, 0, 197, 0, 0, 0, 241, 0, 0, 0, 181, 0, 0, 0, 70, 0, 0, 0, 228, 0, 0, 0, 231, 0, 0, 0, 67, 0, 0, 0, 75, 0, 0, 0, 160, 0, 0, 0, 63, 0, 0, 0, 43, 0, 0, 0, 6, 0, 0, +0, 186, 0, 0, 0, 23, 0, 0, 0, 174, 0, 0, 0, 61, 0, 0, 0, 230, 0, 0, 0, 206, 0, 0, 0, 189, 0, 0, 0, 184, 0, 0, 0, 237, 0, 0, 0, 116, 0, 0, 0, 17, 0, 0, 0, 53, 0, 0, 0, 236, 0, 0, 0, 150, 0, 0, 0, 254, 0, 0, 0, 49, 0, 0, 0, 227, 0, 0, 0, 14, 0, 0, 0, 122, 0, 0, 0, 78, 0, 0, 0, 201, 0, 0, 0, 29, 0, 0, 0, 203, 0, 0, 0, 32, 0, 0, 0, 224, 0, 0, 0, 103, 0, 0, 0, 233, 0, 0, 0, 123, 0, 0, 0, 219, 0, 0, 0, 150, 0, 0, 0, 92, 0, 0, 0, 176, 0, 0, 0, 50, 0, 0, 0, 208, 0, 0, 0, 89, 0, 0, 0, 49, 0, 0, 0, 144, 0, +0, 0, 220, 0, 0, 0, 146, 0, 0, 0, 151, 0, 0, 0, 172, 0, 0, 0, 9, 0, 0, 0, 56, 0, 0, 0, 49, 0, 0, 0, 15, 0, 0, 0, 126, 0, 0, 0, 214, 0, 0, 0, 93, 0, 0, 0, 208, 0, 0, 0, 6, 0, 0, 0, 182, 0, 0, 0, 31, 0, 0, 0, 234, 0, 0, 0, 240, 0, 0, 0, 91, 0, 0, 0, 7, 0, 0, 0, 129, 0, 0, 0, 159, 0, 0, 0, 199, 0, 0, 0, 222, 0, 0, 0, 107, 0, 0, 0, 65, 0, 0, 0, 34, 0, 0, 0, 53, 0, 0, 0, 20, 0, 0, 0, 103, 0, 0, 0, 119, 0, 0, 0, 62, 0, 0, 0, 144, 0, 0, 0, 129, 0, 0, 0, 176, 0, 0, 0, 217, 0, 0, 0, 133, 0, 0, 0, 76, 0, 0, +0, 202, 0, 0, 0, 155, 0, 0, 0, 63, 0, 0, 0, 4, 0, 0, 0, 89, 0, 0, 0, 214, 0, 0, 0, 170, 0, 0, 0, 23, 0, 0, 0, 195, 0, 0, 0, 136, 0, 0, 0, 52, 0, 0, 0, 55, 0, 0, 0, 186, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 0, 0, 0, 182, 0, 0, 0, 105, 0, 0, 0, 200, +0, 0, 0, 129, 0, 0, 0, 149, 0, 0, 0, 148, 0, 0, 0, 51, 0, 0, 0, 146, 0, 0, 0, 52, 0, 0, 0, 233, 0, 0, 0, 60, 0, 0, 0, 132, 0, 0, 0, 13, 0, 0, 0, 61, 0, 0, 0, 90, 0, 0, 0, 55, 0, 0, 0, 156, 0, 0, 0, 34, 0, 0, 0, 160, 0, 0, 0, 170, 0, 0, 0, 101, 0, 0, 0, 206, 0, 0, 0, 180, 0, 0, 0, 194, 0, 0, 0, 45, 0, 0, 0, 102, 0, 0, 0, 103, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 116, 0, 0, 0, 16, 0, 0, 0, 34, 0, 0, 0, 176, 0, 0, 0, 213, 0, 0, 0, 230, 0, 0, 0, 199, 0, 0, 0, 239, 0, 0, 0, 177, 0, 0, 0, 167, 0, 0, 0, 19, +0, 0, 0, 218, 0, 0, 0, 96, 0, 0, 0, 180, 0, 0, 0, 128, 0, 0, 0, 193, 0, 0, 0, 66, 0, 0, 0, 125, 0, 0, 0, 16, 0, 0, 0, 112, 0, 0, 0, 151, 0, 0, 0, 4, 0, 0, 0, 77, 0, 0, 0, 218, 0, 0, 0, 35, 0, 0, 0, 137, 0, 0, 0, 194, 0, 0, 0, 14, 0, 0, 0, 104, 0, 0, 0, 203, 0, 0, 0, 222, 0, 0, 0, 224, 0, 0, 0, 155, 0, 0, 0, 41, 0, 0, 0, 51, 0, 0, 0, 254, 0, 0, 0, 66, 0, 0, 0, 42, 0, 0, 0, 54, 0, 0, 0, 43, 0, 0, 0, 46, 0, 0, 0, 54, 0, 0, 0, 100, 0, 0, 0, 92, 0, 0, 0, 139, 0, 0, 0, 204, 0, 0, 0, 129, 0, 0, 0, 106, +0, 0, 0, 21, 0, 0, 0, 8, 0, 0, 0, 161, 0, 0, 0, 39, 0, 0, 0, 232, 0, 0, 0, 87, 0, 0, 0, 229, 0, 0, 0, 120, 0, 0, 0, 142, 0, 0, 0, 242, 0, 0, 0, 88, 0, 0, 0, 25, 0, 0, 0, 18, 0, 0, 0, 66, 0, 0, 0, 174, 0, 0, 0, 196, 0, 0, 0, 99, 0, 0, 0, 62, 0, 0, 0, 120, 0, 0, 0, 150, 0, 0, 0, 156, 0, 0, 0, 167, 0, 0, 0, 202, 0, 0, 0, 128, 0, 0, 0, 174, 0, 0, 0, 2, 0, 0, 0, 133, 0, 0, 0, 177, 0, 0, 0, 124, 0, 0, 0, 4, 0, 0, 0, 92, 0, 0, 0, 193, 0, 0, 0, 91, 0, 0, 0, 38, 0, 0, 0, 193, 0, 0, 0, 186, 0, 0, 0, 237, 0, +0, 0, 165, 0, 0, 0, 89, 0, 0, 0, 112, 0, 0, 0, 133, 0, 0, 0, 140, 0, 0, 0, 140, 0, 0, 0, 232, 0, 0, 0, 135, 0, 0, 0, 172, 0, 0, 0, 106, 0, 0, 0, 40, 0, 0, 0, 153, 0, 0, 0, 53, 0, 0, 0, 159, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 40, 0, 0, 0, 190, 0, 0, 0, 135, 0, 0, 0, 218, 0, 0, 0, 128, 0, 0, 0, 40, 0, 0, 0, 56, 0, 0, 0, 222, 0, 0, 0, 159, 0, 0, 0, 205, 0, 0, 0, 228, 0, 0, 0, 227, 0, 0, 0, 98, 0, 0, 0, 251, 0, 0, 0, 46, 0, 0, 0, 70, 0, 0, 0, 141, 0, 0, 0, 1, 0, 0, 0, 179, 0, 0, 0, 6, 0, 0, 0, 81, 0, 0, +0, 212, 0, 0, 0, 25, 0, 0, 0, 59, 0, 0, 0, 17, 0, 0, 0, 250, 0, 0, 0, 226, 0, 0, 0, 173, 0, 0, 0, 30, 0, 0, 0, 160, 0, 0, 0, 32, 0, 0, 0, 153, 0, 0, 0, 105, 0, 0, 0, 10, 0, 0, 0, 174, 0, 0, 0, 163, 0, 0, 0, 112, 0, 0, 0, 78, 0, 0, 0, 100, 0, 0, 0, 128, 0, 0, 0, 183, 0, 0, 0, 133, 0, 0, 0, 156, 0, 0, 0, 135, 0, 0, 0, 84, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 85, 0, 0, 0, 128, 0, 0, 0, 109, 0, 0, 0, 141, 0, 0, 0, 124, 0, 0, 0, 169, 0, 0, 0, 100, 0, 0, 0, 202, 0, 0, 0, 108, 0, 0, 0, 46, 0, 0, 0, 33, 0, +0, 0, 216, 0, 0, 0, 200, 0, 0, 0, 108, 0, 0, 0, 145, 0, 0, 0, 74, 0, 0, 0, 7, 0, 0, 0, 173, 0, 0, 0, 8, 0, 0, 0, 117, 0, 0, 0, 193, 0, 0, 0, 79, 0, 0, 0, 164, 0, 0, 0, 178, 0, 0, 0, 195, 0, 0, 0, 111, 0, 0, 0, 70, 0, 0, 0, 62, 0, 0, 0, 177, 0, 0, 0, 206, 0, 0, 0, 82, 0, 0, 0, 171, 0, 0, 0, 103, 0, 0, 0, 9, 0, 0, 0, 84, 0, 0, 0, 72, 0, 0, 0, 107, 0, 0, 0, 108, 0, 0, 0, 215, 0, 0, 0, 29, 0, 0, 0, 113, 0, 0, 0, 118, 0, 0, 0, 203, 0, 0, 0, 255, 0, 0, 0, 221, 0, 0, 0, 49, 0, 0, 0, 54, 0, 0, 0, 136, 0, +0, 0, 250, 0, 0, 0, 253, 0, 0, 0, 240, 0, 0, 0, 54, 0, 0, 0, 111, 0, 0, 0, 7, 0, 0, 0, 116, 0, 0, 0, 136, 0, 0, 0, 80, 0, 0, 0, 208, 0, 0, 0, 149, 0, 0, 0, 56, 0, 0, 0, 74, 0, 0, 0, 72, 0, 0, 0, 46, 0, 0, 0, 7, 0, 0, 0, 100, 0, 0, 0, 151, 0, 0, 0, 17, 0, 0, 0, 118, 0, 0, 0, 1, 0, 0, 0, 26, 0, 0, 0, 39, 0, 0, 0, 77, 0, 0, 0, 142, 0, 0, 0, 37, 0, 0, 0, 154, 0, 0, 0, 155, 0, 0, 0, 28, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 0, 0, 0, 87, 0, 0, 0, 189, 0, 0, 0, 14, 0, 0, 0, 15, 0, 0, 0, 172, 0, 0, 0, 94, 0, 0, 0, 118, 0, 0, 0, 163, 0, 0, 0, 113, 0, 0, 0, 173, 0, 0, 0, 43, 0, 0, 0, 16, 0, 0, 0, 69, 0, 0, 0, 2, 0, 0, 0, 236, 0, 0, 0, 89, 0, 0, 0, 213, 0, 0, 0, 93, 0, 0, 0, 169, 0, 0, 0, 68, 0, 0, 0, 204, 0, 0, 0, 37, 0, 0, 0, 76, 0, 0, 0, 179, 0, +0, 0, 60, 0, 0, 0, 91, 0, 0, 0, 105, 0, 0, 0, 7, 0, 0, 0, 85, 0, 0, 0, 38, 0, 0, 0, 107, 0, 0, 0, 48, 0, 0, 0, 107, 0, 0, 0, 212, 0, 0, 0, 167, 0, 0, 0, 81, 0, 0, 0, 41, 0, 0, 0, 227, 0, 0, 0, 249, 0, 0, 0, 122, 0, 0, 0, 117, 0, 0, 0, 42, 0, 0, 0, 130, 0, 0, 0, 47, 0, 0, 0, 214, 0, 0, 0, 29, 0, 0, 0, 153, 0, 0, 0, 43, 0, 0, 0, 128, 0, 0, 0, 213, 0, 0, 0, 103, 0, 0, 0, 30, 0, 0, 0, 21, 0, 0, 0, 157, 0, 0, 0, 202, 0, 0, 0, 253, 0, 0, 0, 235, 0, 0, 0, 172, 0, 0, 0, 151, 0, 0, 0, 53, 0, 0, 0, 9, 0, 0, +0, 127, 0, 0, 0, 63, 0, 0, 0, 53, 0, 0, 0, 13, 0, 0, 0, 52, 0, 0, 0, 10, 0, 0, 0, 184, 0, 0, 0, 103, 0, 0, 0, 86, 0, 0, 0, 41, 0, 0, 0, 32, 0, 0, 0, 243, 0, 0, 0, 25, 0, 0, 0, 95, 0, 0, 0, 226, 0, 0, 0, 131, 0, 0, 0, 66, 0, 0, 0, 115, 0, 0, 0, 83, 0, 0, 0, 168, 0, 0, 0, 197, 0, 0, 0, 2, 0, 0, 0, 25, 0, 0, 0, 51, 0, 0, 0, 180, 0, 0, 0, 100, 0, 0, 0, 189, 0, 0, 0, 195, 0, 0, 0, 135, 0, 0, 0, 140, 0, 0, 0, 215, 0, 0, 0, 118, 0, 0, 0, 237, 0, 0, 0, 37, 0, 0, 0, 71, 0, 0, 0, 57, 0, 0, 0, 55, 0, 0, 0, +118, 0, 0, 0, 13, 0, 0, 0, 29, 0, 0, 0, 12, 0, 0, 0, 245, 0, 0, 0, 90, 0, 0, 0, 109, 0, 0, 0, 67, 0, 0, 0, 136, 0, 0, 0, 153, 0, 0, 0, 21, 0, 0, 0, 180, 0, 0, 0, 82, 0, 0, 0, 15, 0, 0, 0, 42, 0, 0, 0, 179, 0, 0, 0, 176, 0, 0, 0, 63, 0, 0, 0, 166, 0, 0, 0, 179, 0, 0, 0, 38, 0, 0, 0, 179, 0, 0, 0, 199, 0, 0, 0, 69, 0, 0, 0, 245, 0, 0, 0, 146, 0, 0, 0, 95, 0, 0, 0, 155, 0, 0, 0, 23, 0, 0, 0, 157, 0, 0, 0, 35, 0, 0, 0, 189, 0, 0, 0, 21, 0, 0, 0, 254, 0, 0, 0, 82, 0, 0, 0, 82, 0, 0, 0, 21, 0, 0, 0, 38, +0, 0, 0, 121, 0, 0, 0, 134, 0, 0, 0, 186, 0, 0, 0, 6, 0, 0, 0, 86, 0, 0, 0, 102, 0, 0, 0, 187, 0, 0, 0, 140, 0, 0, 0, 46, 0, 0, 0, 16, 0, 0, 0, 17, 0, 0, 0, 213, 0, 0, 0, 74, 0, 0, 0, 24, 0, 0, 0, 82, 0, 0, 0, 218, 0, 0, 0, 132, 0, 0, 0, 68, 0, 0, 0, 240, 0, 0, 0, 62, 0, 0, 0, 233, 0, 0, 0, 140, 0, 0, 0, 53, 0, 0, 0, 173, 0, 0, 0, 160, 0, 0, 0, 65, 0, 0, 0, 236, 0, 0, 0, 200, 0, 0, 0, 77, 0, 0, 0, 185, 0, 0, 0, 210, 0, 0, 0, 110, 0, 0, 0, 150, 0, 0, 0, 78, 0, 0, 0, 91, 0, 0, 0, 197, 0, 0, 0, 194, +0, 0, 0, 160, 0, 0, 0, 27, 0, 0, 0, 207, 0, 0, 0, 12, 0, 0, 0, 191, 0, 0, 0, 23, 0, 0, 0, 102, 0, 0, 0, 87, 0, 0, 0, 193, 0, 0, 0, 23, 0, 0, 0, 144, 0, 0, 0, 69, 0, 0, 0, 113, 0, 0, 0, 194, 0, 0, 0, 225, 0, 0, 0, 36, 0, 0, 0, 235, 0, 0, 0, 39, 0, 0, 0, 44, 0, 0, 0, 185, 0, 0, 0, 66, 0, 0, 0, 164, 0, 0, 0, 175, 0, 0, 0, 59, 0, 0, 0, 66, 0, 0, 0, 14, 0, 0, 0, 194, 0, 0, 0, 15, 0, 0, 0, 242, 0, 0, 0, 234, 0, 0, 0, 131, 0, 0, 0, 175, 0, 0, 0, 154, 0, 0, 0, 19, 0, 0, 0, 23, 0, 0, 0, 176, 0, 0, 0, 189, +0, 0, 0, 137, 0, 0, 0, 23, 0, 0, 0, 227, 0, 0, 0, 114, 0, 0, 0, 203, 0, 0, 0, 14, 0, 0, 0, 118, 0, 0, 0, 126, 0, 0, 0, 65, 0, 0, 0, 99, 0, 0, 0, 4, 0, 0, 0, 136, 0, 0, 0, 113, 0, 0, 0, 117, 0, 0, 0, 120, 0, 0, 0, 56, 0, 0, 0, 134, 0, 0, 0, 87, 0, 0, 0, 221, 0, 0, 0, 159, 0, 0, 0, 238, 0, 0, 0, 84, 0, 0, 0, 112, 0, 0, 0, 101, 0, 0, 0, 191, 0, 0, 0, 241, 0, 0, 0, 44, 0, 0, 0, 224, 0, 0, 0, 57, 0, 0, 0, 13, 0, 0, 0, 227, 0, 0, 0, 137, 0, 0, 0, 253, 0, 0, 0, 142, 0, 0, 0, 147, 0, 0, 0, 79, 0, 0, 0, 67, +0, 0, 0, 220, 0, 0, 0, 213, 0, 0, 0, 91, 0, 0, 0, 222, 0, 0, 0, 249, 0, 0, 0, 152, 0, 0, 0, 229, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 59, 0, 0, 0, 101, 0, 0, 0, 17, 0, 0, 0, 223, 0, 0, 0, 178, 0, 0, 0, 242, 0, 0, 0, 99, 0, 0, 0, 148, +0, 0, 0, 18, 0, 0, 0, 111, 0, 0, 0, 92, 0, 0, 0, 158, 0, 0, 0, 119, 0, 0, 0, 193, 0, 0, 0, 182, 0, 0, 0, 216, 0, 0, 0, 171, 0, 0, 0, 88, 0, 0, 0, 122, 0, 0, 0, 29, 0, 0, 0, 149, 0, 0, 0, 115, 0, 0, 0, 221, 0, 0, 0, 231, 0, 0, 0, 227, 0, 0, 0, 111, 0, 0, 0, 242, 0, 0, 0, 3, 0, 0, 0, 29, 0, 0, 0, 219, 0, 0, 0, 118, 0, 0, 0, 174, 0, 0, 0, 6, 0, 0, 0, 78, 0, 0, 0, 44, 0, 0, 0, 82, 0, 0, 0, 27, 0, 0, 0, 188, 0, 0, 0, 90, 0, 0, 0, 90, 0, 0, 0, 165, 0, 0, 0, 190, 0, 0, 0, 39, 0, 0, 0, 189, 0, 0, 0, 235, +0, 0, 0, 225, 0, 0, 0, 20, 0, 0, 0, 23, 0, 0, 0, 104, 0, 0, 0, 38, 0, 0, 0, 7, 0, 0, 0, 3, 0, 0, 0, 209, 0, 0, 0, 24, 0, 0, 0, 11, 0, 0, 0, 223, 0, 0, 0, 241, 0, 0, 0, 6, 0, 0, 0, 92, 0, 0, 0, 166, 0, 0, 0, 27, 0, 0, 0, 185, 0, 0, 0, 36, 0, 0, 0, 197, 0, 0, 0, 102, 0, 0, 0, 128, 0, 0, 0, 19, 0, 0, 0, 14, 0, 0, 0, 72, 0, 0, 0, 140, 0, 0, 0, 135, 0, 0, 0, 49, 0, 0, 0, 132, 0, 0, 0, 180, 0, 0, 0, 96, 0, 0, 0, 237, 0, 0, 0, 197, 0, 0, 0, 236, 0, 0, 0, 182, 0, 0, 0, 197, 0, 0, 0, 5, 0, 0, 0, 51, 0, 0, +0, 95, 0, 0, 0, 47, 0, 0, 0, 125, 0, 0, 0, 64, 0, 0, 0, 182, 0, 0, 0, 50, 0, 0, 0, 29, 0, 0, 0, 56, 0, 0, 0, 116, 0, 0, 0, 27, 0, 0, 0, 241, 0, 0, 0, 9, 0, 0, 0, 61, 0, 0, 0, 212, 0, 0, 0, 105, 0, 0, 0, 130, 0, 0, 0, 188, 0, 0, 0, 141, 0, 0, 0, 248, 0, 0, 0, 52, 0, 0, 0, 54, 0, 0, 0, 117, 0, 0, 0, 85, 0, 0, 0, 24, 0, 0, 0, 85, 0, 0, 0, 88, 0, 0, 0, 60, 0, 0, 0, 121, 0, 0, 0, 175, 0, 0, 0, 38, 0, 0, 0, 128, 0, 0, 0, 171, 0, 0, 0, 155, 0, 0, 0, 149, 0, 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 203, 0, 0, 0, +218, 0, 0, 0, 193, 0, 0, 0, 159, 0, 0, 0, 246, 0, 0, 0, 47, 0, 0, 0, 162, 0, 0, 0, 244, 0, 0, 0, 69, 0, 0, 0, 23, 0, 0, 0, 190, 0, 0, 0, 235, 0, 0, 0, 133, 0, 0, 0, 237, 0, 0, 0, 158, 0, 0, 0, 205, 0, 0, 0, 86, 0, 0, 0, 245, 0, 0, 0, 23, 0, 0, 0, 69, 0, 0, 0, 66, 0, 0, 0, 180, 0, 0, 0, 31, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 5, 0, 0, 0, 116, 0, 0, 0, 21, 0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 106, 0, 0, 0, 61, 0, 0, 0, 36, 0, 0, 0, 9, 0, 0, 0, 13, 0, 0, 0, 88, 0, 0, 0, 177, 0, 0, 0, 66, 0, +0, 0, 215, 0, 0, 0, 4, 0, 0, 0, 141, 0, 0, 0, 189, 0, 0, 0, 163, 0, 0, 0, 196, 0, 0, 0, 6, 0, 0, 0, 155, 0, 0, 0, 31, 0, 0, 0, 144, 0, 0, 0, 88, 0, 0, 0, 96, 0, 0, 0, 116, 0, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 0, 60, 0, 0, 0, 210, 0, 0, 0, 218, 0, 0, 0, 130, 0, 0, 0, 187, 0, 0, 0, 16, 0, 0, 0, 144, 0, 0, 0, 105, 0, 0, 0, 146, 0, 0, 0, 169, 0, 0, 0, 180, 0, 0, 0, 48, 0, 0, 0, 129, 0, 0, 0, 227, 0, 0, 0, 124, 0, 0, 0, 168, 0, 0, 0, 137, 0, 0, 0, 69, 0, 0, 0, 63, 0, 0, 0, 220, 0, 0, 0, 5, 0, +0, 0, 203, 0, 0, 0, 65, 0, 0, 0, 60, 0, 0, 0, 200, 0, 0, 0, 35, 0, 0, 0, 4, 0, 0, 0, 44, 0, 0, 0, 56, 0, 0, 0, 153, 0, 0, 0, 227, 0, 0, 0, 104, 0, 0, 0, 85, 0, 0, 0, 249, 0, 0, 0, 211, 0, 0, 0, 50, 0, 0, 0, 199, 0, 0, 0, 191, 0, 0, 0, 250, 0, 0, 0, 212, 0, 0, 0, 27, 0, 0, 0, 93, 0, 0, 0, 222, 0, 0, 0, 220, 0, 0, 0, 16, 0, 0, 0, 66, 0, 0, 0, 192, 0, 0, 0, 66, 0, 0, 0, 217, 0, 0, 0, 117, 0, 0, 0, 45, 0, 0, 0, 171, 0, 0, 0, 53, 0, 0, 0, 78, 0, 0, 0, 135, 0, 0, 0, 196, 0, 0, 0, 101, 0, 0, 0, 151, 0, +0, 0, 103, 0, 0, 0, 36, 0, 0, 0, 164, 0, 0, 0, 71, 0, 0, 0, 173, 0, 0, 0, 63, 0, 0, 0, 142, 0, 0, 0, 243, 0, 0, 0, 203, 0, 0, 0, 49, 0, 0, 0, 23, 0, 0, 0, 119, 0, 0, 0, 197, 0, 0, 0, 226, 0, 0, 0, 215, 0, 0, 0, 143, 0, 0, 0, 60, 0, 0, 0, 193, 0, 0, 0, 205, 0, 0, 0, 86, 0, 0, 0, 72, 0, 0, 0, 193, 0, 0, 0, 108, 0, 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 174, 0, 0, 0, 95, 0, 0, 0, 136, 0, 0, 0, 123, 0, 0, 0, 165, 0, 0, 0, 144, 0, 0, 0, 223, 0, 0, 0, 16, 0, 0, 0, 178, 0, 0, 0, 139, 0, 0, 0, 94, 0, 0, 0, 36, 0, 0, 0, 23, 0, 0, 0, 195, 0, 0, 0, 163, 0, 0, 0, 212, 0, 0, 0, 15, 0, 0, 0, 146, 0, 0, 0, 97, 0, 0, 0, 26, 0, 0, 0, 25, 0, 0, 0, 90, 0, 0, 0, 173, 0, 0, 0, 118, 0, 0, 0, 189, 0, 0, 0, 216, 0, 0, 0, 28, 0, 0, 0, 221, 0, 0, 0, 224, 0, +0, 0, 18, 0, 0, 0, 109, 0, 0, 0, 142, 0, 0, 0, 189, 0, 0, 0, 112, 0, 0, 0, 143, 0, 0, 0, 2, 0, 0, 0, 163, 0, 0, 0, 36, 0, 0, 0, 77, 0, 0, 0, 90, 0, 0, 0, 103, 0, 0, 0, 196, 0, 0, 0, 218, 0, 0, 0, 247, 0, 0, 0, 32, 0, 0, 0, 15, 0, 0, 0, 129, 0, 0, 0, 91, 0, 0, 0, 122, 0, 0, 0, 5, 0, 0, 0, 36, 0, 0, 0, 103, 0, 0, 0, 131, 0, 0, 0, 11, 0, 0, 0, 42, 0, 0, 0, 128, 0, 0, 0, 231, 0, 0, 0, 253, 0, 0, 0, 116, 0, 0, 0, 75, 0, 0, 0, 158, 0, 0, 0, 92, 0, 0, 0, 13, 0, 0, 0, 148, 0, 0, 0, 213, 0, 0, 0, 95, 0, 0, +0, 31, 0, 0, 0, 162, 0, 0, 0, 251, 0, 0, 0, 235, 0, 0, 0, 225, 0, 0, 0, 7, 0, 0, 0, 52, 0, 0, 0, 248, 0, 0, 0, 32, 0, 0, 0, 173, 0, 0, 0, 129, 0, 0, 0, 48, 0, 0, 0, 6, 0, 0, 0, 45, 0, 0, 0, 161, 0, 0, 0, 129, 0, 0, 0, 149, 0, 0, 0, 54, 0, 0, 0, 207, 0, 0, 0, 17, 0, 0, 0, 11, 0, 0, 0, 175, 0, 0, 0, 193, 0, 0, 0, 43, 0, 0, 0, 154, 0, 0, 0, 108, 0, 0, 0, 85, 0, 0, 0, 193, 0, 0, 0, 22, 0, 0, 0, 54, 0, 0, 0, 79, 0, 0, 0, 241, 0, 0, 0, 94, 0, 0, 0, 116, 0, 0, 0, 53, 0, 0, 0, 19, 0, 0, 0, 40, 0, 0, 0, 215, +0, 0, 0, 17, 0, 0, 0, 207, 0, 0, 0, 184, 0, 0, 0, 222, 0, 0, 0, 147, 0, 0, 0, 179, 0, 0, 0, 5, 0, 0, 0, 184, 0, 0, 0, 181, 0, 0, 0, 115, 0, 0, 0, 233, 0, 0, 0, 235, 0, 0, 0, 173, 0, 0, 0, 25, 0, 0, 0, 30, 0, 0, 0, 137, 0, 0, 0, 15, 0, 0, 0, 139, 0, 0, 0, 21, 0, 0, 0, 213, 0, 0, 0, 140, 0, 0, 0, 227, 0, 0, 0, 35, 0, 0, 0, 51, 0, 0, 0, 121, 0, 0, 0, 231, 0, 0, 0, 24, 0, 0, 0, 230, 0, 0, 0, 15, 0, 0, 0, 87, 0, 0, 0, 147, 0, 0, 0, 21, 0, 0, 0, 160, 0, 0, 0, 167, 0, 0, 0, 170, 0, 0, 0, 196, 0, 0, 0, 191, +0, 0, 0, 79, 0, 0, 0, 48, 0, 0, 0, 116, 0, 0, 0, 149, 0, 0, 0, 94, 0, 0, 0, 105, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 69, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, 35, 0, 0, 0, 116, 0, 0, 0, 76, 0, 0, 0, 223, 0, 0, 0, 107, 0, 0, 0, 69, 0, 0, 0, 151, 0, 0, 0, 41, 0, 0, 0, 108, 0, 0, 0, 196, 0, 0, 0, 66, 0, 0, 0, 11, 0, 0, 0, 221, 0, 0, 0, 192, 0, 0, 0, 41, 0, 0, 0, 92, 0, 0, 0, 155, 0, 0, 0, 52, 0, 0, 0, 151, 0, 0, 0, 208, 0, 0, 0, 199, 0, 0, 0, 121, 0, 0, 0, 128, 0, 0, 0, 99, 0, 0, 0, 116, 0, +0, 0, 228, 0, 0, 0, 142, 0, 0, 0, 55, 0, 0, 0, 176, 0, 0, 0, 43, 0, 0, 0, 124, 0, 0, 0, 232, 0, 0, 0, 104, 0, 0, 0, 108, 0, 0, 0, 195, 0, 0, 0, 130, 0, 0, 0, 151, 0, 0, 0, 87, 0, 0, 0, 34, 0, 0, 0, 190, 0, 0, 0, 131, 0, 0, 0, 182, 0, 0, 0, 75, 0, 0, 0, 128, 0, 0, 0, 107, 0, 0, 0, 67, 0, 0, 0, 36, 0, 0, 0, 94, 0, 0, 0, 239, 0, 0, 0, 153, 0, 0, 0, 155, 0, 0, 0, 168, 0, 0, 0, 252, 0, 0, 0, 37, 0, 0, 0, 141, 0, 0, 0, 59, 0, 0, 0, 3, 0, 0, 0, 148, 0, 0, 0, 43, 0, 0, 0, 62, 0, 0, 0, 231, 0, 0, 0, 149, +0, 0, 0, 118, 0, 0, 0, 155, 0, 0, 0, 204, 0, 0, 0, 21, 0, 0, 0, 219, 0, 0, 0, 50, 0, 0, 0, 230, 0, 0, 0, 102, 0, 0, 0, 132, 0, 0, 0, 240, 0, 0, 0, 74, 0, 0, 0, 19, 0, 0, 0, 166, 0, 0, 0, 214, 0, 0, 0, 250, 0, 0, 0, 147, 0, 0, 0, 70, 0, 0, 0, 7, 0, 0, 0, 246, 0, 0, 0, 126, 0, 0, 0, 92, 0, 0, 0, 109, 0, 0, 0, 94, 0, 0, 0, 246, 0, 0, 0, 166, 0, 0, 0, 231, 0, 0, 0, 72, 0, 0, 0, 240, 0, 0, 0, 6, 0, 0, 0, 234, 0, 0, 0, 255, 0, 0, 0, 144, 0, 0, 0, 193, 0, 0, 0, 204, 0, 0, 0, 76, 0, 0, 0, 25, 0, 0, 0, 156, +0, 0, 0, 60, 0, 0, 0, 78, 0, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 80, 0, 0, 0, 227, 0, 0, 0, 7, 0, 0, 0, 21, 0, 0, 0, 89, 0, 0, 0, 242, 0, 0, 0, 139, 0, 0, 0, 129, 0, 0, 0, 242, 0, 0, 0, 243, 0, 0, 0, 211, 0, 0, 0, 108, 0, 0, 0, 153, 0, 0, +0, 140, 0, 0, 0, 112, 0, 0, 0, 103, 0, 0, 0, 236, 0, 0, 0, 204, 0, 0, 0, 238, 0, 0, 0, 158, 0, 0, 0, 89, 0, 0, 0, 69, 0, 0, 0, 89, 0, 0, 0, 125, 0, 0, 0, 71, 0, 0, 0, 117, 0, 0, 0, 105, 0, 0, 0, 245, 0, 0, 0, 36, 0, 0, 0, 147, 0, 0, 0, 93, 0, 0, 0, 106, 0, 0, 0, 79, 0, 0, 0, 27, 0, 0, 0, 190, 0, 0, 0, 107, 0, 0, 0, 48, 0, 0, 0, 207, 0, 0, 0, 117, 0, 0, 0, 70, 0, 0, 0, 227, 0, 0, 0, 123, 0, 0, 0, 157, 0, 0, 0, 252, 0, 0, 0, 205, 0, 0, 0, 216, 0, 0, 0, 92, 0, 0, 0, 31, 0, 0, 0, 180, 0, 0, 0, 200, 0, +0, 0, 226, 0, 0, 0, 36, 0, 0, 0, 236, 0, 0, 0, 26, 0, 0, 0, 40, 0, 0, 0, 5, 0, 0, 0, 50, 0, 0, 0, 87, 0, 0, 0, 253, 0, 0, 0, 60, 0, 0, 0, 90, 0, 0, 0, 152, 0, 0, 0, 16, 0, 0, 0, 163, 0, 0, 0, 219, 0, 0, 0, 247, 0, 0, 0, 48, 0, 0, 0, 216, 0, 0, 0, 194, 0, 0, 0, 154, 0, 0, 0, 225, 0, 0, 0, 211, 0, 0, 0, 206, 0, 0, 0, 34, 0, 0, 0, 229, 0, 0, 0, 128, 0, 0, 0, 30, 0, 0, 0, 217, 0, 0, 0, 228, 0, 0, 0, 31, 0, 0, 0, 171, 0, 0, 0, 192, 0, 0, 0, 113, 0, 0, 0, 26, 0, 0, 0, 134, 0, 0, 0, 14, 0, 0, 0, 39, 0, +0, 0, 153, 0, 0, 0, 91, 0, 0, 0, 250, 0, 0, 0, 118, 0, 0, 0, 153, 0, 0, 0, 176, 0, 0, 0, 8, 0, 0, 0, 60, 0, 0, 0, 42, 0, 0, 0, 147, 0, 0, 0, 210, 0, 0, 0, 133, 0, 0, 0, 27, 0, 0, 0, 106, 0, 0, 0, 93, 0, 0, 0, 166, 0, 0, 0, 238, 0, 0, 0, 209, 0, 0, 0, 209, 0, 0, 0, 51, 0, 0, 0, 189, 0, 0, 0, 106, 0, 0, 0, 54, 0, 0, 0, 115, 0, 0, 0, 55, 0, 0, 0, 58, 0, 0, 0, 68, 0, 0, 0, 180, 0, 0, 0, 236, 0, 0, 0, 169, 0, 0, 0, 122, 0, 0, 0, 222, 0, 0, 0, 131, 0, 0, 0, 64, 0, 0, 0, 215, 0, 0, 0, 223, 0, 0, 0, 40, +0, 0, 0, 186, 0, 0, 0, 162, 0, 0, 0, 48, 0, 0, 0, 211, 0, 0, 0, 181, 0, 0, 0, 109, 0, 0, 0, 5, 0, 0, 0, 63, 0, 0, 0, 159, 0, 0, 0, 243, 0, 0, 0, 21, 0, 0, 0, 141, 0, 0, 0, 124, 0, 0, 0, 202, 0, 0, 0, 201, 0, 0, 0, 252, 0, 0, 0, 138, 0, 0, 0, 124, 0, 0, 0, 148, 0, 0, 0, 176, 0, 0, 0, 99, 0, 0, 0, 54, 0, 0, 0, 155, 0, 0, 0, 120, 0, 0, 0, 209, 0, 0, 0, 145, 0, 0, 0, 31, 0, 0, 0, 147, 0, 0, 0, 216, 0, 0, 0, 87, 0, 0, 0, 67, 0, 0, 0, 222, 0, 0, 0, 118, 0, 0, 0, 163, 0, 0, 0, 67, 0, 0, 0, 155, 0, 0, 0, +53, 0, 0, 0, 226, 0, 0, 0, 169, 0, 0, 0, 61, 0, 0, 0, 50, 0, 0, 0, 30, 0, 0, 0, 187, 0, 0, 0, 22, 0, 0, 0, 40, 0, 0, 0, 112, 0, 0, 0, 233, 0, 0, 0, 69, 0, 0, 0, 47, 0, 0, 0, 143, 0, 0, 0, 112, 0, 0, 0, 127, 0, 0, 0, 8, 0, 0, 0, 126, 0, 0, 0, 83, 0, 0, 0, 196, 0, 0, 0, 122, 0, 0, 0, 191, 0, 0, 0, 247, 0, 0, 0, 225, 0, 0, 0, 164, 0, 0, 0, 106, 0, 0, 0, 216, 0, 0, 0, 172, 0, 0, 0, 100, 0, 0, 0, 27, 0, 0, 0, 17, 0, 0, 0, 178, 0, 0, 0, 235, 0, 0, 0, 71, 0, 0, 0, 70, 0, 0, 0, 24, 0, 0, 0, 62, 0, 0, 0, +31, 0, 0, 0, 153, 0, 0, 0, 12, 0, 0, 0, 204, 0, 0, 0, 241, 0, 0, 0, 44, 0, 0, 0, 224, 0, 0, 0, 231, 0, 0, 0, 143, 0, 0, 0, 224, 0, 0, 0, 1, 0, 0, 0, 126, 0, 0, 0, 101, 0, 0, 0, 184, 0, 0, 0, 12, 0, 0, 0, 208, 0, 0, 0, 251, 0, 0, 0, 200, 0, 0, 0, 185, 0, 0, 0, 144, 0, 0, 0, 152, 0, 0, 0, 51, 0, 0, 0, 97, 0, 0, 0, 59, 0, 0, 0, 216, 0, 0, 0, 39, 0, 0, 0, 160, 0, 0, 0, 190, 0, 0, 0, 114, 0, 0, 0, 58, 0, 0, 0, 80, 0, 0, 0, 75, 0, 0, 0, 116, 0, 0, 0, 171, 0, 0, 0, 1, 0, 0, 0, 200, 0, 0, 0, 147, 0, 0, 0, +197, 0, 0, 0, 228, 0, 0, 0, 199, 0, 0, 0, 8, 0, 0, 0, 108, 0, 0, 0, 180, 0, 0, 0, 202, 0, 0, 0, 238, 0, 0, 0, 235, 0, 0, 0, 142, 0, 0, 0, 215, 0, 0, 0, 78, 0, 0, 0, 38, 0, 0, 0, 198, 0, 0, 0, 29, 0, 0, 0, 226, 0, 0, 0, 113, 0, 0, 0, 175, 0, 0, 0, 137, 0, 0, 0, 160, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 152, 0, 0, 0, 11, 0, 0, 0, 228, 0, 0, 0, 222, 0, 0, 0, 219, 0, 0, 0, 168, 0, 0, 0, 250, 0, 0, 0, 130, 0, 0, 0, 116, 0, 0, 0, 6, 0, 0, 0, 82, 0, 0, 0, 109, 0, 0, 0, 8, 0, 0, 0, 82, 0, 0, 0, 138, 0, 0, 0, 255, 0, 0, 0, 98, 0, 0, 0, 197, 0, 0, 0, 106, 0, 0, 0, 68, 0, 0, 0, 15, 0, 0, 0, 81, 0, 0, 0, 140, 0, 0, 0, 31, 0, 0, 0, 110, 0, 0, 0, 182, 0, 0, 0, 198, 0, 0, 0, 44, 0, 0, 0, 129, 0, 0, 0, 211, 0, 0, 0, 118, 0, 0, 0, 70, 0, 0, 0, 244, 0, 0, 0, +41, 0, 0, 0, 116, 0, 0, 0, 46, 0, 0, 0, 128, 0, 0, 0, 167, 0, 0, 0, 26, 0, 0, 0, 143, 0, 0, 0, 246, 0, 0, 0, 189, 0, 0, 0, 214, 0, 0, 0, 142, 0, 0, 0, 191, 0, 0, 0, 193, 0, 0, 0, 149, 0, 0, 0, 42, 0, 0, 0, 235, 0, 0, 0, 160, 0, 0, 0, 127, 0, 0, 0, 69, 0, 0, 0, 160, 0, 0, 0, 80, 0, 0, 0, 20, 0, 0, 0, 5, 0, 0, 0, 177, 0, 0, 0, 87, 0, 0, 0, 76, 0, 0, 0, 116, 0, 0, 0, 183, 0, 0, 0, 226, 0, 0, 0, 137, 0, 0, 0, 125, 0, 0, 0, 7, 0, 0, 0, 238, 0, 0, 0, 167, 0, 0, 0, 173, 0, 0, 0, 183, 0, 0, 0, 9, 0, 0, 0, +11, 0, 0, 0, 73, 0, 0, 0, 78, 0, 0, 0, 191, 0, 0, 0, 202, 0, 0, 0, 229, 0, 0, 0, 33, 0, 0, 0, 230, 0, 0, 0, 230, 0, 0, 0, 175, 0, 0, 0, 213, 0, 0, 0, 103, 0, 0, 0, 243, 0, 0, 0, 206, 0, 0, 0, 126, 0, 0, 0, 124, 0, 0, 0, 147, 0, 0, 0, 123, 0, 0, 0, 90, 0, 0, 0, 16, 0, 0, 0, 18, 0, 0, 0, 14, 0, 0, 0, 108, 0, 0, 0, 6, 0, 0, 0, 17, 0, 0, 0, 117, 0, 0, 0, 213, 0, 0, 0, 252, 0, 0, 0, 134, 0, 0, 0, 163, 0, 0, 0, 59, 0, 0, 0, 163, 0, 0, 0, 62, 0, 0, 0, 10, 0, 0, 0, 251, 0, 0, 0, 11, 0, 0, 0, 247, 0, 0, 0, +54, 0, 0, 0, 177, 0, 0, 0, 91, 0, 0, 0, 218, 0, 0, 0, 112, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 167, 0, 0, 0, 218, 0, 0, 0, 136, 0, 0, 0, 143, 0, 0, 0, 132, 0, 0, 0, 168, 0, 0, 0, 188, 0, 0, 0, 28, 0, 0, 0, 57, 0, 0, 0, 184, 0, 0, 0, 101, 0, 0, 0, 243, 0, 0, 0, 77, 0, 0, 0, 96, 0, 0, 0, 150, 0, 0, 0, 157, 0, 0, 0, 49, 0, 0, 0, 244, 0, 0, 0, 162, 0, 0, 0, 190, 0, 0, 0, 129, 0, 0, 0, 185, 0, 0, 0, 165, 0, 0, 0, 89, 0, 0, 0, 158, 0, 0, 0, 186, 0, 0, 0, 7, 0, 0, 0, 190, 0, 0, 0, 116, 0, 0, 0, 88, 0, 0, +0, 216, 0, 0, 0, 235, 0, 0, 0, 197, 0, 0, 0, 159, 0, 0, 0, 61, 0, 0, 0, 209, 0, 0, 0, 244, 0, 0, 0, 174, 0, 0, 0, 206, 0, 0, 0, 83, 0, 0, 0, 223, 0, 0, 0, 79, 0, 0, 0, 199, 0, 0, 0, 42, 0, 0, 0, 137, 0, 0, 0, 77, 0, 0, 0, 41, 0, 0, 0, 216, 0, 0, 0, 242, 0, 0, 0, 170, 0, 0, 0, 233, 0, 0, 0, 14, 0, 0, 0, 247, 0, 0, 0, 46, 0, 0, 0, 95, 0, 0, 0, 157, 0, 0, 0, 138, 0, 0, 0, 91, 0, 0, 0, 9, 0, 0, 0, 237, 0, 0, 0, 201, 0, 0, 0, 36, 0, 0, 0, 34, 0, 0, 0, 244, 0, 0, 0, 15, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, +0, 28, 0, 0, 0, 132, 0, 0, 0, 110, 0, 0, 0, 52, 0, 0, 0, 20, 0, 0, 0, 108, 0, 0, 0, 234, 0, 0, 0, 179, 0, 0, 0, 134, 0, 0, 0, 93, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 152, 0, 0, 0, 97, 0, 0, 0, 232, 0, 0, 0, 106, 0, 0, 0, 210, 0, 0, 0, 129, 0, 0, 0, 73, 0, 0, 0, 37, 0, 0, 0, 213, 0, 0, 0, 91, 0, 0, 0, 24, 0, 0, 0, 199, 0, 0, 0, 53, 0, 0, 0, 82, 0, 0, 0, 81, 0, 0, 0, 164, 0, 0, 0, 70, 0, 0, 0, 173, 0, 0, 0, 24, 0, 0, 0, 13, 0, 0, 0, 201, 0, 0, 0, 95, 0, 0, 0, 24, 0, 0, 0, 145, 0, 0, 0, 59, 0, 0, 0, 180, +0, 0, 0, 192, 0, 0, 0, 96, 0, 0, 0, 89, 0, 0, 0, 141, 0, 0, 0, 102, 0, 0, 0, 3, 0, 0, 0, 27, 0, 0, 0, 121, 0, 0, 0, 83, 0, 0, 0, 110, 0, 0, 0, 36, 0, 0, 0, 174, 0, 0, 0, 87, 0, 0, 0, 217, 0, 0, 0, 88, 0, 0, 0, 9, 0, 0, 0, 133, 0, 0, 0, 72, 0, 0, 0, 162, 0, 0, 0, 211, 0, 0, 0, 181, 0, 0, 0, 226, 0, 0, 0, 77, 0, 0, 0, 17, 0, 0, 0, 130, 0, 0, 0, 230, 0, 0, 0, 134, 0, 0, 0, 60, 0, 0, 0, 233, 0, 0, 0, 177, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 194, 0, 0, 0, 87, 0, 0, 0, 247, 0, 0, 0, 102, 0, 0, 0, 122, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 227, 0, 0, 0, 137, 0, 0, 0, 3, 0, 0, 0, 215, 0, 0, 0, 34, 0, 0, 0, 149, 0, 0, 0, 159, 0, 0, 0, 202, 0, 0, 0, 180, 0, 0, 0, 141, 0, 0, 0, 158, 0, 0, 0, 109, 0, 0, 0, 151, 0, 0, 0, 255, 0, 0, 0, 141, 0, 0, 0, 33, 0, 0, +0, 89, 0, 0, 0, 7, 0, 0, 0, 239, 0, 0, 0, 3, 0, 0, 0, 45, 0, 0, 0, 94, 0, 0, 0, 248, 0, 0, 0, 68, 0, 0, 0, 70, 0, 0, 0, 231, 0, 0, 0, 133, 0, 0, 0, 128, 0, 0, 0, 197, 0, 0, 0, 137, 0, 0, 0, 80, 0, 0, 0, 139, 0, 0, 0, 216, 0, 0, 0, 83, 0, 0, 0, 134, 0, 0, 0, 36, 0, 0, 0, 134, 0, 0, 0, 41, 0, 0, 0, 82, 0, 0, 0, 1, 0, 0, 0, 250, 0, 0, 0, 32, 0, 0, 0, 195, 0, 0, 0, 78, 0, 0, 0, 149, 0, 0, 0, 203, 0, 0, 0, 173, 0, 0, 0, 123, 0, 0, 0, 52, 0, 0, 0, 148, 0, 0, 0, 48, 0, 0, 0, 183, 0, 0, 0, 122, 0, 0, 0, +250, 0, 0, 0, 150, 0, 0, 0, 65, 0, 0, 0, 96, 0, 0, 0, 43, 0, 0, 0, 203, 0, 0, 0, 89, 0, 0, 0, 185, 0, 0, 0, 202, 0, 0, 0, 80, 0, 0, 0, 194, 0, 0, 0, 91, 0, 0, 0, 155, 0, 0, 0, 120, 0, 0, 0, 35, 0, 0, 0, 27, 0, 0, 0, 58, 0, 0, 0, 136, 0, 0, 0, 148, 0, 0, 0, 95, 0, 0, 0, 10, 0, 0, 0, 155, 0, 0, 0, 152, 0, 0, 0, 43, 0, 0, 0, 110, 0, 0, 0, 83, 0, 0, 0, 17, 0, 0, 0, 246, 0, 0, 0, 255, 0, 0, 0, 198, 0, 0, 0]).concat([125, 0, 0, 0, 66, 0, 0, 0, 204, 0, 0, 0, 2, 0, 0, 0, 128, 0, 0, 0, 64, 0, 0, 0, 13, 0, +0, 0, 30, 0, 0, 0, 251, 0, 0, 0, 175, 0, 0, 0, 97, 0, 0, 0, 7, 0, 0, 0, 176, 0, 0, 0, 230, 0, 0, 0, 47, 0, 0, 0, 129, 0, 0, 0, 112, 0, 0, 0, 161, 0, 0, 0, 46, 0, 0, 0, 57, 0, 0, 0, 4, 0, 0, 0, 124, 0, 0, 0, 196, 0, 0, 0, 44, 0, 0, 0, 135, 0, 0, 0, 69, 0, 0, 0, 74, 0, 0, 0, 91, 0, 0, 0, 105, 0, 0, 0, 151, 0, 0, 0, 172, 0, 0, 0, 109, 0, 0, 0, 44, 0, 0, 0, 16, 0, 0, 0, 66, 0, 0, 0, 124, 0, 0, 0, 59, 0, 0, 0, 21, 0, 0, 0, 112, 0, 0, 0, 96, 0, 0, 0, 14, 0, 0, 0, 17, 0, 0, 0, 109, 0, 0, 0, 58, 0, 0, 0, +155, 0, 0, 0, 24, 0, 0, 0, 128, 0, 0, 0, 94, 0, 0, 0, 219, 0, 0, 0, 5, 0, 0, 0, 189, 0, 0, 0, 198, 0, 0, 0, 183, 0, 0, 0, 60, 0, 0, 0, 194, 0, 0, 0, 64, 0, 0, 0, 77, 0, 0, 0, 93, 0, 0, 0, 206, 0, 0, 0, 151, 0, 0, 0, 138, 0, 0, 0, 52, 0, 0, 0, 21, 0, 0, 0, 171, 0, 0, 0, 40, 0, 0, 0, 93, 0, 0, 0, 16, 0, 0, 0, 240, 0, 0, 0, 55, 0, 0, 0, 12, 0, 0, 0, 204, 0, 0, 0, 22, 0, 0, 0, 250, 0, 0, 0, 31, 0, 0, 0, 51, 0, 0, 0, 13, 0, 0, 0, 25, 0, 0, 0, 249, 0, 0, 0, 53, 0, 0, 0, 170, 0, 0, 0, 89, 0, 0, 0, 26, 0, +0, 0, 12, 0, 0, 0, 92, 0, 0, 0, 6, 0, 0, 0, 252, 0, 0, 0, 106, 0, 0, 0, 11, 0, 0, 0, 151, 0, 0, 0, 83, 0, 0, 0, 54, 0, 0, 0, 252, 0, 0, 0, 42, 0, 0, 0, 165, 0, 0, 0, 90, 0, 0, 0, 155, 0, 0, 0, 48, 0, 0, 0, 239, 0, 0, 0, 35, 0, 0, 0, 175, 0, 0, 0, 57, 0, 0, 0, 93, 0, 0, 0, 154, 0, 0, 0, 107, 0, 0, 0, 117, 0, 0, 0, 87, 0, 0, 0, 72, 0, 0, 0, 11, 0, 0, 0, 38, 0, 0, 0, 220, 0, 0, 0, 118, 0, 0, 0, 59, 0, 0, 0, 252, 0, 0, 0, 249, 0, 0, 0, 156, 0, 0, 0, 63, 0, 0, 0, 137, 0, 0, 0, 11, 0, 0, 0, 98, 0, 0, 0, +83, 0, 0, 0, 175, 0, 0, 0, 131, 0, 0, 0, 1, 0, 0, 0, 46, 0, 0, 0, 188, 0, 0, 0, 106, 0, 0, 0, 198, 0, 0, 0, 3, 0, 0, 0, 13, 0, 0, 0, 117, 0, 0, 0, 42, 0, 0, 0, 13, 0, 0, 0, 230, 0, 0, 0, 148, 0, 0, 0, 84, 0, 0, 0, 207, 0, 0, 0, 179, 0, 0, 0, 229, 0, 0, 0, 150, 0, 0, 0, 37, 0, 0, 0, 254, 0, 0, 0, 130, 0, 0, 0, 177, 0, 0, 0, 116, 0, 0, 0, 49, 0, 0, 0, 138, 0, 0, 0, 167, 0, 0, 0, 111, 0, 0, 0, 86, 0, 0, 0, 189, 0, 0, 0, 141, 0, 0, 0, 244, 0, 0, 0, 224, 0, 0, 0, 148, 0, 0, 0, 81, 0, 0, 0, 89, 0, 0, 0, +222, 0, 0, 0, 44, 0, 0, 0, 90, 0, 0, 0, 244, 0, 0, 0, 132, 0, 0, 0, 107, 0, 0, 0, 74, 0, 0, 0, 136, 0, 0, 0, 147, 0, 0, 0, 192, 0, 0, 0, 12, 0, 0, 0, 154, 0, 0, 0, 172, 0, 0, 0, 167, 0, 0, 0, 160, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 13, +0, 0, 0, 214, 0, 0, 0, 199, 0, 0, 0, 35, 0, 0, 0, 71, 0, 0, 0, 16, 0, 0, 0, 173, 0, 0, 0, 199, 0, 0, 0, 8, 0, 0, 0, 92, 0, 0, 0, 135, 0, 0, 0, 135, 0, 0, 0, 147, 0, 0, 0, 152, 0, 0, 0, 24, 0, 0, 0, 184, 0, 0, 0, 211, 0, 0, 0, 156, 0, 0, 0, 172, 0, 0, 0, 90, 0, 0, 0, 61, 0, 0, 0, 197, 0, 0, 0, 117, 0, 0, 0, 248, 0, 0, 0, 73, 0, 0, 0, 50, 0, 0, 0, 20, 0, 0, 0, 204, 0, 0, 0, 81, 0, 0, 0, 150, 0, 0, 0, 36, 0, 0, 0, 101, 0, 0, 0, 156, 0, 0, 0, 93, 0, 0, 0, 240, 0, 0, 0, 55, 0, 0, 0, 4, 0, 0, 0, 240, 0, +0, 0, 52, 0, 0, 0, 105, 0, 0, 0, 42, 0, 0, 0, 240, 0, 0, 0, 165, 0, 0, 0, 100, 0, 0, 0, 202, 0, 0, 0, 222, 0, 0, 0, 43, 0, 0, 0, 91, 0, 0, 0, 21, 0, 0, 0, 16, 0, 0, 0, 210, 0, 0, 0, 171, 0, 0, 0, 6, 0, 0, 0, 221, 0, 0, 0, 196, 0, 0, 0, 176, 0, 0, 0, 182, 0, 0, 0, 91, 0, 0, 0, 193, 0, 0, 0, 23, 0, 0, 0, 223, 0, 0, 0, 143, 0, 0, 0, 2, 0, 0, 0, 189, 0, 0, 0, 89, 0, 0, 0, 61, 0, 0, 0, 191, 0, 0, 0, 92, 0, 0, 0, 49, 0, 0, 0, 68, 0, 0, 0, 44, 0, 0, 0, 50, 0, 0, 0, 148, 0, 0, 0, 4, 0, 0, 0, 96, 0, 0, 0, +132, 0, 0, 0, 15, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 182, 0, 0, 0, 143, 0, 0, 0, 201, 0, 0, 0, 29, 0, 0, 0, 204, 0, 0, 0, 92, 0, 0, 0, 162, 0, 0, 0, 73, 0, 0, 0, 14, 0, 0, 0, 80, 0, 0, 0, 145, 0, 0, 0, 8, 0, 0, 0, 154, 0, 0, 0, 67, 0, 0, 0, 85, 0, 0, 0, 5, 0, 0, 0, 93, 0, 0, 0, 147, 0, 0, 0, 85, 0, 0, 0, 223, 0, 0, 0, 155, 0, 0, 0, 18, 0, 0, 0, 25, 0, 0, 0, 236, 0, 0, 0, 147, 0, 0, 0, 133, 0, 0, 0, 66, 0, 0, 0, 158, 0, 0, 0, 102, 0, 0, 0, 15, 0, 0, 0, 157, 0, 0, 0, 175, 0, 0, 0, 153, 0, 0, 0, 175, +0, 0, 0, 38, 0, 0, 0, 137, 0, 0, 0, 188, 0, 0, 0, 97, 0, 0, 0, 253, 0, 0, 0, 255, 0, 0, 0, 206, 0, 0, 0, 75, 0, 0, 0, 244, 0, 0, 0, 51, 0, 0, 0, 149, 0, 0, 0, 201, 0, 0, 0, 53, 0, 0, 0, 88, 0, 0, 0, 18, 0, 0, 0, 85, 0, 0, 0, 249, 0, 0, 0, 218, 0, 0, 0, 203, 0, 0, 0, 68, 0, 0, 0, 167, 0, 0, 0, 220, 0, 0, 0, 87, 0, 0, 0, 226, 0, 0, 0, 249, 0, 0, 0, 154, 0, 0, 0, 230, 0, 0, 0, 7, 0, 0, 0, 35, 0, 0, 0, 96, 0, 0, 0, 84, 0, 0, 0, 167, 0, 0, 0, 57, 0, 0, 0, 165, 0, 0, 0, 155, 0, 0, 0, 132, 0, 0, 0, 86, +0, 0, 0, 110, 0, 0, 0, 170, 0, 0, 0, 139, 0, 0, 0, 143, 0, 0, 0, 176, 0, 0, 0, 44, 0, 0, 0, 135, 0, 0, 0, 175, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 76, 0, 0, 0, 178, 0, 0, 0, 18, 0, 0, 0, 248, 0, 0, 0, 50, 0, 0, 0, 168, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 73, 0, 0, 0, 50, 0, 0, 0, 186, 0, 0, 0, 31, 0, 0, 0, 93, 0, 0, 0, 68, 0, 0, 0, 142, 0, 0, 0, 68, 0, 0, 0, 122, 0, 0, 0, 220, 0, 0, 0, 17, 0, 0, 0, 251, 0, 0, 0, 57, 0, 0, 0, 8, 0, 0, 0, 87, 0, 0, 0, 135, 0, 0, 0, 165, 0, +0, 0, 18, 0, 0, 0, 66, 0, 0, 0, 147, 0, 0, 0, 14, 0, 0, 0, 23, 0, 0, 0, 180, 0, 0, 0, 174, 0, 0, 0, 114, 0, 0, 0, 89, 0, 0, 0, 208, 0, 0, 0, 170, 0, 0, 0, 168, 0, 0, 0, 22, 0, 0, 0, 139, 0, 0, 0, 99, 0, 0, 0, 17, 0, 0, 0, 179, 0, 0, 0, 67, 0, 0, 0, 4, 0, 0, 0, 218, 0, 0, 0, 12, 0, 0, 0, 168, 0, 0, 0, 183, 0, 0, 0, 104, 0, 0, 0, 221, 0, 0, 0, 78, 0, 0, 0, 84, 0, 0, 0, 231, 0, 0, 0, 175, 0, 0, 0, 93, 0, 0, 0, 93, 0, 0, 0, 5, 0, 0, 0, 118, 0, 0, 0, 54, 0, 0, 0, 236, 0, 0, 0, 13, 0, 0, 0, 109, 0, 0, +0, 124, 0, 0, 0, 130, 0, 0, 0, 50, 0, 0, 0, 56, 0, 0, 0, 85, 0, 0, 0, 87, 0, 0, 0, 116, 0, 0, 0, 91, 0, 0, 0, 125, 0, 0, 0, 195, 0, 0, 0, 196, 0, 0, 0, 251, 0, 0, 0, 6, 0, 0, 0, 41, 0, 0, 0, 240, 0, 0, 0, 19, 0, 0, 0, 85, 0, 0, 0, 84, 0, 0, 0, 198, 0, 0, 0, 167, 0, 0, 0, 220, 0, 0, 0, 76, 0, 0, 0, 159, 0, 0, 0, 152, 0, 0, 0, 73, 0, 0, 0, 32, 0, 0, 0, 168, 0, 0, 0, 195, 0, 0, 0, 141, 0, 0, 0, 250, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, 71, 0, 0, 0, 157, 0, 0, 0, 233, 0, 0, 0, 37, 0, 0, 0, 213, 0, 0, 0, 227, 0, 0, 0, 71, 0, 0, 0, 120, 0, 0, 0, 223, 0, 0, 0, 133, 0, 0, 0, 167, 0, 0, 0, 133, 0, 0, 0, 94, 0, 0, 0, 122, 0, 0, 0, 76, 0, 0, 0, 95, 0, 0, 0, 121, 0, 0, 0, 26, 0, 0, 0, 243, 0, 0, 0, 162, 0, 0, 0, 178, 0, 0, 0, 40, 0, 0, 0, 160, +0, 0, 0, 156, 0, 0, 0, 221, 0, 0, 0, 48, 0, 0, 0, 64, 0, 0, 0, 212, 0, 0, 0, 56, 0, 0, 0, 189, 0, 0, 0, 40, 0, 0, 0, 252, 0, 0, 0, 187, 0, 0, 0, 213, 0, 0, 0, 120, 0, 0, 0, 109, 0, 0, 0, 29, 0, 0, 0, 212, 0, 0, 0, 153, 0, 0, 0, 180, 0, 0, 0, 170, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 122, 0, 0, 0, 27, 0, 0, 0, 216, 0, 0, 0, 254, 0, 0, 0, 180, 0, 0, 0, 153, 0, 0, 0, 185, 0, 0, 0, 204, 0, 0, 0, 231, 0, 0, 0, 196, 0, 0, 0, 211, 0, 0, 0, 58, 0, 0, 0, 115, 0, 0, 0, 131, 0, 0, 0, 65, 0, 0, 0, 92, 0, 0, 0, +64, 0, 0, 0, 215, 0, 0, 0, 45, 0, 0, 0, 85, 0, 0, 0, 38, 0, 0, 0, 225, 0, 0, 0, 123, 0, 0, 0, 95, 0, 0, 0, 229, 0, 0, 0, 220, 0, 0, 0, 63, 0, 0, 0, 125, 0, 0, 0, 161, 0, 0, 0, 167, 0, 0, 0, 38, 0, 0, 0, 68, 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 192, 0, 0, 0, 143, 0, 0, 0, 125, 0, 0, 0, 241, 0, 0, 0, 181, 0, 0, 0, 17, 0, 0, 0, 71, 0, 0, 0, 123, 0, 0, 0, 25, 0, 0, 0, 212, 0, 0, 0, 117, 0, 0, 0, 111, 0, 0, 0, 30, 0, 0, 0, 165, 0, 0, 0, 39, 0, 0, 0, 254, 0, 0, 0, 200, 0, 0, 0, 14, 0, 0, 0, 211, 0, 0, 0, +17, 0, 0, 0, 61, 0, 0, 0, 171, 0, 0, 0, 239, 0, 0, 0, 44, 0, 0, 0, 237, 0, 0, 0, 177, 0, 0, 0, 61, 0, 0, 0, 124, 0, 0, 0, 50, 0, 0, 0, 129, 0, 0, 0, 107, 0, 0, 0, 254, 0, 0, 0, 248, 0, 0, 0, 28, 0, 0, 0, 60, 0, 0, 0, 123, 0, 0, 0, 192, 0, 0, 0, 97, 0, 0, 0, 223, 0, 0, 0, 184, 0, 0, 0, 117, 0, 0, 0, 118, 0, 0, 0, 127, 0, 0, 0, 170, 0, 0, 0, 216, 0, 0, 0, 147, 0, 0, 0, 175, 0, 0, 0, 61, 0, 0, 0, 232, 0, 0, 0, 61, 0, 0, 0, 253, 0, 0, 0, 91, 0, 0, 0, 78, 0, 0, 0, 141, 0, 0, 0, 182, 0, 0, 0, 126, 0, 0, +0, 130, 0, 0, 0, 155, 0, 0, 0, 239, 0, 0, 0, 206, 0, 0, 0, 4, 0, 0, 0, 105, 0, 0, 0, 81, 0, 0, 0, 82, 0, 0, 0, 255, 0, 0, 0, 239, 0, 0, 0, 160, 0, 0, 0, 82, 0, 0, 0, 181, 0, 0, 0, 121, 0, 0, 0, 23, 0, 0, 0, 94, 0, 0, 0, 47, 0, 0, 0, 222, 0, 0, 0, 214, 0, 0, 0, 60, 0, 0, 0, 45, 0, 0, 0, 160, 0, 0, 0, 67, 0, 0, 0, 180, 0, 0, 0, 11, 0, 0, 0, 25, 0, 0, 0, 192, 0, 0, 0, 97, 0, 0, 0, 72, 0, 0, 0, 72, 0, 0, 0, 23, 0, 0, 0, 244, 0, 0, 0, 158, 0, 0, 0, 24, 0, 0, 0, 81, 0, 0, 0, 45, 0, 0, 0, 234, 0, 0, 0, +47, 0, 0, 0, 242, 0, 0, 0, 242, 0, 0, 0, 224, 0, 0, 0, 163, 0, 0, 0, 20, 0, 0, 0, 183, 0, 0, 0, 139, 0, 0, 0, 58, 0, 0, 0, 48, 0, 0, 0, 245, 0, 0, 0, 129, 0, 0, 0, 193, 0, 0, 0, 93, 0, 0, 0, 113, 0, 0, 0, 57, 0, 0, 0, 98, 0, 0, 0, 85, 0, 0, 0, 31, 0, 0, 0, 96, 0, 0, 0, 90, 0, 0, 0, 229, 0, 0, 0, 137, 0, 0, 0, 138, 0, 0, 0, 118, 0, 0, 0, 108, 0, 0, 0, 219, 0, 0, 0, 77, 0, 0, 0, 10, 0, 0, 0, 91, 0, 0, 0, 114, 0, 0, 0, 157, 0, 0, 0, 89, 0, 0, 0, 110, 0, 0, 0, 99, 0, 0, 0, 99, 0, 0, 0, 24, 0, 0, 0, 124, +0, 0, 0, 227, 0, 0, 0, 250, 0, 0, 0, 226, 0, 0, 0, 219, 0, 0, 0, 161, 0, 0, 0, 141, 0, 0, 0, 244, 0, 0, 0, 165, 0, 0, 0, 215, 0, 0, 0, 22, 0, 0, 0, 178, 0, 0, 0, 208, 0, 0, 0, 179, 0, 0, 0, 63, 0, 0, 0, 57, 0, 0, 0, 206, 0, 0, 0, 96, 0, 0, 0, 9, 0, 0, 0, 108, 0, 0, 0, 245, 0, 0, 0, 118, 0, 0, 0, 23, 0, 0, 0, 36, 0, 0, 0, 128, 0, 0, 0, 58, 0, 0, 0, 150, 0, 0, 0, 199, 0, 0, 0, 148, 0, 0, 0, 46, 0, 0, 0, 247, 0, 0, 0, 107, 0, 0, 0, 239, 0, 0, 0, 181, 0, 0, 0, 5, 0, 0, 0, 150, 0, 0, 0, 239, 0, 0, 0, +211, 0, 0, 0, 123, 0, 0, 0, 81, 0, 0, 0, 218, 0, 0, 0, 5, 0, 0, 0, 68, 0, 0, 0, 103, 0, 0, 0, 188, 0, 0, 0, 7, 0, 0, 0, 33, 0, 0, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 115, 0, 0, 0, 111, 0, 0, 0, 33, 0, 0, 0, 185, 0, 0, 0, 222, 0, 0, 0, 34, 0, +0, 0, 125, 0, 0, 0, 235, 0, 0, 0, 151, 0, 0, 0, 49, 0, 0, 0, 16, 0, 0, 0, 163, 0, 0, 0, 234, 0, 0, 0, 225, 0, 0, 0, 198, 0, 0, 0, 55, 0, 0, 0, 235, 0, 0, 0, 143, 0, 0, 0, 67, 0, 0, 0, 88, 0, 0, 0, 222, 0, 0, 0, 65, 0, 0, 0, 100, 0, 0, 0, 14, 0, 0, 0, 62, 0, 0, 0, 7, 0, 0, 0, 153, 0, 0, 0, 61, 0, 0, 0, 241, 0, 0, 0, 223, 0, 0, 0, 30, 0, 0, 0, 248, 0, 0, 0, 173, 0, 0, 0, 67, 0, 0, 0, 194, 0, 0, 0, 23, 0, 0, 0, 6, 0, 0, 0, 226, 0, 0, 0, 228, 0, 0, 0, 169, 0, 0, 0, 134, 0, 0, 0, 205, 0, 0, 0, 24, 0, +0, 0, 215, 0, 0, 0, 120, 0, 0, 0, 200, 0, 0, 0, 116, 0, 0, 0, 102, 0, 0, 0, 210, 0, 0, 0, 9, 0, 0, 0, 24, 0, 0, 0, 165, 0, 0, 0, 241, 0, 0, 0, 202, 0, 0, 0, 166, 0, 0, 0, 98, 0, 0, 0, 146, 0, 0, 0, 193, 0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, 66, 0, 0, 0, 46, 0, 0, 0, 123, 0, 0, 0, 52, 0, 0, 0, 36, 0, 0, 0, 76, 0, 0, 0, 207, 0, 0, 0, 56, 0, 0, 0, 229, 0, 0, 0, 108, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 44, 0, 0, 0, 34, 0, 0, 0, 11, 0, 0, 0, 36, 0, 0, 0, 56, 0, 0, 0, 173, 0, 0, 0, 36, 0, 0, 0, +126, 0, 0, 0, 25, 0, 0, 0, 240, 0, 0, 0, 108, 0, 0, 0, 249, 0, 0, 0, 49, 0, 0, 0, 244, 0, 0, 0, 53, 0, 0, 0, 17, 0, 0, 0, 246, 0, 0, 0, 70, 0, 0, 0, 51, 0, 0, 0, 58, 0, 0, 0, 35, 0, 0, 0, 89, 0, 0, 0, 32, 0, 0, 0, 11, 0, 0, 0, 161, 0, 0, 0, 8, 0, 0, 0, 25, 0, 0, 0, 173, 0, 0, 0, 57, 0, 0, 0, 84, 0, 0, 0, 234, 0, 0, 0, 62, 0, 0, 0, 35, 0, 0, 0, 9, 0, 0, 0, 182, 0, 0, 0, 226, 0, 0, 0, 210, 0, 0, 0, 188, 0, 0, 0, 77, 0, 0, 0, 252, 0, 0, 0, 156, 0, 0, 0, 240, 0, 0, 0, 19, 0, 0, 0, 22, 0, 0, 0, 34, 0, +0, 0, 63, 0, 0, 0, 185, 0, 0, 0, 210, 0, 0, 0, 17, 0, 0, 0, 134, 0, 0, 0, 144, 0, 0, 0, 85, 0, 0, 0, 206, 0, 0, 0, 60, 0, 0, 0, 196, 0, 0, 0, 11, 0, 0, 0, 75, 0, 0, 0, 98, 0, 0, 0, 153, 0, 0, 0, 55, 0, 0, 0, 132, 0, 0, 0, 63, 0, 0, 0, 116, 0, 0, 0, 162, 0, 0, 0, 249, 0, 0, 0, 206, 0, 0, 0, 226, 0, 0, 0, 11, 0, 0, 0, 15, 0, 0, 0, 42, 0, 0, 0, 61, 0, 0, 0, 163, 0, 0, 0, 227, 0, 0, 0, 219, 0, 0, 0, 90, 0, 0, 0, 157, 0, 0, 0, 147, 0, 0, 0, 204, 0, 0, 0, 165, 0, 0, 0, 239, 0, 0, 0, 130, 0, 0, 0, 145, +0, 0, 0, 29, 0, 0, 0, 230, 0, 0, 0, 108, 0, 0, 0, 104, 0, 0, 0, 163, 0, 0, 0, 100, 0, 0, 0, 23, 0, 0, 0, 155, 0, 0, 0, 139, 0, 0, 0, 200, 0, 0, 0, 58, 0, 0, 0, 97, 0, 0, 0, 230, 0, 0, 0, 157, 0, 0, 0, 198, 0, 0, 0, 237, 0, 0, 0, 123, 0, 0, 0, 3, 0, 0, 0, 82, 0, 0, 0, 38, 0, 0, 0, 157, 0, 0, 0, 58, 0, 0, 0, 179, 0, 0, 0, 19, 0, 0, 0, 204, 0, 0, 0, 138, 0, 0, 0, 253, 0, 0, 0, 44, 0, 0, 0, 26, 0, 0, 0, 29, 0, 0, 0, 237, 0, 0, 0, 19, 0, 0, 0, 208, 0, 0, 0, 85, 0, 0, 0, 87, 0, 0, 0, 14, 0, 0, 0, 26, 0, +0, 0, 234, 0, 0, 0, 191, 0, 0, 0, 253, 0, 0, 0, 74, 0, 0, 0, 60, 0, 0, 0, 142, 0, 0, 0, 236, 0, 0, 0, 41, 0, 0, 0, 126, 0, 0, 0, 119, 0, 0, 0, 119, 0, 0, 0, 18, 0, 0, 0, 153, 0, 0, 0, 215, 0, 0, 0, 132, 0, 0, 0, 249, 0, 0, 0, 85, 0, 0, 0, 127, 0, 0, 0, 241, 0, 0, 0, 139, 0, 0, 0, 180, 0, 0, 0, 210, 0, 0, 0, 149, 0, 0, 0, 163, 0, 0, 0, 141, 0, 0, 0, 240, 0, 0, 0, 138, 0, 0, 0, 167, 0, 0, 0, 235, 0, 0, 0, 130, 0, 0, 0, 75, 0, 0, 0, 44, 0, 0, 0, 40, 0, 0, 0, 244, 0, 0, 0, 58, 0, 0, 0, 246, 0, 0, 0, +222, 0, 0, 0, 10, 0, 0, 0, 224, 0, 0, 0, 65, 0, 0, 0, 68, 0, 0, 0, 35, 0, 0, 0, 248, 0, 0, 0, 63, 0, 0, 0, 3, 0, 0, 0, 100, 0, 0, 0, 159, 0, 0, 0, 195, 0, 0, 0, 85, 0, 0, 0, 76, 0, 0, 0, 198, 0, 0, 0, 193, 0, 0, 0, 148, 0, 0, 0, 28, 0, 0, 0, 36, 0, 0, 0, 93, 0, 0, 0, 95, 0, 0, 0, 146, 0, 0, 0, 69, 0, 0, 0, 150, 0, 0, 0, 87, 0, 0, 0, 55, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 205, 0, 0, 0, 144, 0, 0, 0, 102, 0, 0, 0, 185, 0, 0, 0, 118, 0, 0, 0, 160, 0, 0, 0, 91, 0, 0, 0, 165, 0, 0, 0, 133, 0, 0, 0, 117, 0, 0, 0, 35, 0, 0, 0, 249, 0, 0, 0, 137, 0, 0, 0, 165, 0, 0, 0, 130, 0, 0, 0, 178, 0, 0, 0, 111, 0, 0, 0, 177, 0, 0, 0, 235, 0, 0, 0, 196, 0, 0, 0, 105, 0, 0, 0, 111, 0, 0, 0, 24, 0, 0, 0, 90, 0, 0, 0, 237, 0, 0, 0, 148, 0, 0, 0, 61, +0, 0, 0, 157, 0, 0, 0, 217, 0, 0, 0, 44, 0, 0, 0, 26, 0, 0, 0, 53, 0, 0, 0, 176, 0, 0, 0, 230, 0, 0, 0, 115, 0, 0, 0, 6, 0, 0, 0, 183, 0, 0, 0, 55, 0, 0, 0, 224, 0, 0, 0, 248, 0, 0, 0, 176, 0, 0, 0, 34, 0, 0, 0, 232, 0, 0, 0, 210, 0, 0, 0, 237, 0, 0, 0, 11, 0, 0, 0, 239, 0, 0, 0, 230, 0, 0, 0, 198, 0, 0, 0, 90, 0, 0, 0, 153, 0, 0, 0, 158, 0, 0, 0, 26, 0, 0, 0, 159, 0, 0, 0, 4, 0, 0, 0, 151, 0, 0, 0, 228, 0, 0, 0, 77, 0, 0, 0, 11, 0, 0, 0, 190, 0, 0, 0, 186, 0, 0, 0, 68, 0, 0, 0, 64, 0, 0, 0, 193, +0, 0, 0, 86, 0, 0, 0, 150, 0, 0, 0, 145, 0, 0, 0, 95, 0, 0, 0, 31, 0, 0, 0, 187, 0, 0, 0, 84, 0, 0, 0, 111, 0, 0, 0, 136, 0, 0, 0, 137, 0, 0, 0, 10, 0, 0, 0, 178, 0, 0, 0, 214, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 106, 0, 0, 0, 130, 0, 0, 0, 238, 0, 0, 0, 20, 0, 0, 0, 170, 0, 0, 0, 118, 0, 0, 0, 48, 0, 0, 0, 101, 0, 0, 0, 15, 0, 0, 0, 103, 0, 0, 0, 57, 0, 0, 0, 166, 0, 0, 0, 81, 0, 0, 0, 124, 0, 0, 0, 73, 0, 0, 0, 36, 0, 0, 0, 53, 0, 0, 0, 163, 0, 0, 0, 120, 0, 0, 0, 209, 0, 0, 0, 17, 0, 0, 0, 15, +0, 0, 0, 117, 0, 0, 0, 211, 0, 0, 0, 112, 0, 0, 0, 70, 0, 0, 0, 219, 0, 0, 0, 32, 0, 0, 0, 81, 0, 0, 0, 203, 0, 0, 0, 146, 0, 0, 0, 128, 0, 0, 0, 84, 0, 0, 0, 16, 0, 0, 0, 116, 0, 0, 0, 54, 0, 0, 0, 134, 0, 0, 0, 169, 0, 0, 0, 215, 0, 0, 0, 163, 0, 0, 0, 8, 0, 0, 0, 120, 0, 0, 0, 241, 0, 0, 0, 1, 0, 0, 0, 41, 0, 0, 0, 248, 0, 0, 0, 128, 0, 0, 0, 59, 0, 0, 0, 219, 0, 0, 0, 167, 0, 0, 0, 157, 0, 0, 0, 157, 0, 0, 0, 191, 0, 0, 0, 160, 0, 0, 0, 204, 0, 0, 0, 237, 0, 0, 0, 83, 0, 0, 0, 162, 0, 0, 0, 162, +0, 0, 0, 25, 0, 0, 0, 57, 0, 0, 0, 72, 0, 0, 0, 131, 0, 0, 0, 25, 0, 0, 0, 55, 0, 0, 0, 88, 0, 0, 0, 209, 0, 0, 0, 4, 0, 0, 0, 40, 0, 0, 0, 64, 0, 0, 0, 247, 0, 0, 0, 138, 0, 0, 0, 194, 0, 0, 0, 8, 0, 0, 0, 183, 0, 0, 0, 165, 0, 0, 0, 66, 0, 0, 0, 207, 0, 0, 0, 83, 0, 0, 0, 76, 0, 0, 0, 167, 0, 0, 0, 187, 0, 0, 0, 246, 0, 0, 0, 142, 0, 0, 0, 173, 0, 0, 0, 221, 0, 0, 0, 247, 0, 0, 0, 144, 0, 0, 0, 221, 0, 0, 0, 95, 0, 0, 0, 147, 0, 0, 0, 137, 0, 0, 0, 174, 0, 0, 0, 4, 0, 0, 0, 55, 0, 0, 0, 230, 0, +0, 0, 154, 0, 0, 0, 183, 0, 0, 0, 232, 0, 0, 0, 192, 0, 0, 0, 223, 0, 0, 0, 22, 0, 0, 0, 42, 0, 0, 0, 191, 0, 0, 0, 196, 0, 0, 0, 58, 0, 0, 0, 60, 0, 0, 0, 65, 0, 0, 0, 213, 0, 0, 0, 137, 0, 0, 0, 114, 0, 0, 0, 90, 0, 0, 0, 31, 0, 0, 0, 150, 0, 0, 0, 255, 0, 0, 0, 52, 0, 0, 0, 44, 0, 0, 0, 19, 0, 0, 0, 33, 0, 0, 0, 203, 0, 0, 0, 10, 0, 0, 0, 137, 0, 0, 0, 133, 0, 0, 0, 190, 0, 0, 0, 179, 0, 0, 0, 112, 0, 0, 0, 158, 0, 0, 0, 30, 0, 0, 0, 222, 0, 0, 0, 151, 0, 0, 0, 175, 0, 0, 0, 150, 0, 0, 0, 48, +0, 0, 0, 247, 0, 0, 0, 72, 0, 0, 0, 137, 0, 0, 0, 64, 0, 0, 0, 141, 0, 0, 0, 7, 0, 0, 0, 241, 0, 0, 0, 37, 0, 0, 0, 240, 0, 0, 0, 48, 0, 0, 0, 88, 0, 0, 0, 30, 0, 0, 0, 212, 0, 0, 0, 147, 0, 0, 0, 87, 0, 0, 0, 226, 0, 0, 0, 23, 0, 0, 0, 231, 0, 0, 0, 157, 0, 0, 0, 171, 0, 0, 0, 60, 0, 0, 0, 85, 0, 0, 0, 3, 0, 0, 0, 130, 0, 0, 0, 47, 0, 0, 0, 43, 0, 0, 0, 219, 0, 0, 0, 86, 0, 0, 0, 30, 0, 0, 0, 48, 0, 0, 0, 46, 0, 0, 0, 36, 0, 0, 0, 71, 0, 0, 0, 110, 0, 0, 0, 230, 0, 0, 0, 255, 0, 0, 0, 51, 0, 0, +0, 36, 0, 0, 0, 44, 0, 0, 0, 117, 0, 0, 0, 81, 0, 0, 0, 212, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 6, 0, 0, 0, 217, 0, 0, 0, 161, 0, 0, 0, 93, 0, 0, 0, 225, 0, 0, 0, 244, 0, 0, 0, 209, 0, 0, 0, 30, 0, 0, 0, 60, 0, 0, 0, 154, 0, 0, 0, 198, +0, 0, 0, 41, 0, 0, 0, 43, 0, 0, 0, 19, 0, 0, 0, 19, 0, 0, 0, 120, 0, 0, 0, 192, 0, 0, 0, 216, 0, 0, 0, 22, 0, 0, 0, 23, 0, 0, 0, 45, 0, 0, 0, 158, 0, 0, 0, 169, 0, 0, 0, 201, 0, 0, 0, 121, 0, 0, 0, 87, 0, 0, 0, 171, 0, 0, 0, 36, 0, 0, 0, 145, 0, 0, 0, 146, 0, 0, 0, 25, 0, 0, 0, 105, 0, 0, 0, 251, 0, 0, 0, 161, 0, 0, 0, 156, 0, 0, 0, 166, 0, 0, 0, 117, 0, 0, 0, 73, 0, 0, 0, 125, 0, 0, 0, 96, 0, 0, 0, 115, 0, 0, 0, 64, 0, 0, 0, 66, 0, 0, 0, 196, 0, 0, 0, 19, 0, 0, 0, 10, 0, 0, 0, 149, 0, 0, 0, 121, +0, 0, 0, 30, 0, 0, 0, 4, 0, 0, 0, 131, 0, 0, 0, 148, 0, 0, 0, 153, 0, 0, 0, 155, 0, 0, 0, 30, 0, 0, 0, 12, 0, 0, 0, 232, 0, 0, 0, 31, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 203, 0, 0, 0, 192, 0, 0, 0, 82, 0, 0, 0, 20, 0, 0, 0, 137, 0, 0, 0, 115, 0, 0, 0, 161, 0, 0, 0, 55, 0, 0, 0, 135, 0, 0, 0, 106, 0, 0, 0, 122, 0, 0, 0, 207, 0, 0, 0, 29, 0, 0, 0, 217, 0, 0, 0, 46, 0, 0, 0, 26, 0, 0, 0, 103, 0, 0, 0, 237, 0, 0, 0, 116, 0, 0, 0, 192, 0, 0, 0, 240, 0, 0, 0, 156, 0, 0, 0, 51, 0, 0, 0, 221, 0, 0, 0, 223, +0, 0, 0, 8, 0, 0, 0, 191, 0, 0, 0, 123, 0, 0, 0, 209, 0, 0, 0, 102, 0, 0, 0, 218, 0, 0, 0, 230, 0, 0, 0, 201, 0, 0, 0, 73, 0, 0, 0, 8, 0, 0, 0, 233, 0, 0, 0, 221, 0, 0, 0, 94, 0, 0, 0, 85, 0, 0, 0, 176, 0, 0, 0, 10, 0, 0, 0, 222, 0, 0, 0, 33, 0, 0, 0, 76, 0, 0, 0, 90, 0, 0, 0, 46, 0, 0, 0, 212, 0, 0, 0, 128, 0, 0, 0, 58, 0, 0, 0, 87, 0, 0, 0, 146, 0, 0, 0, 122, 0, 0, 0, 241, 0, 0, 0, 196, 0, 0, 0, 44, 0, 0, 0, 64, 0, 0, 0, 175, 0, 0, 0, 47, 0, 0, 0, 201, 0, 0, 0, 146, 0, 0, 0, 3, 0, 0, 0, 229, 0, +0, 0, 90, 0, 0, 0, 188, 0, 0, 0, 220, 0, 0, 0, 244, 0, 0, 0, 9, 0, 0, 0, 243, 0, 0, 0, 225, 0, 0, 0, 43, 0, 0, 0, 124, 0, 0, 0, 5, 0, 0, 0, 134, 0, 0, 0, 128, 0, 0, 0, 147, 0, 0, 0, 74, 0, 0, 0, 173, 0, 0, 0, 180, 0, 0, 0, 143, 0, 0, 0, 126, 0, 0, 0, 153, 0, 0, 0, 12, 0, 0, 0, 253, 0, 0, 0, 205, 0, 0, 0, 239, 0, 0, 0, 209, 0, 0, 0, 255, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 52, 0, 0, 0, 19, 0, 0, 0, 65, 0, 0, 0, 100, 0, 0, 0, 207, 0, 0, 0, 59, 0, 0, 0, 208, 0, 0, 0, 144, 0, 0, 0, 9, 0, 0, 0, 30, 0, +0, 0, 157, 0, 0, 0, 69, 0, 0, 0, 214, 0, 0, 0, 128, 0, 0, 0, 230, 0, 0, 0, 69, 0, 0, 0, 170, 0, 0, 0, 244, 0, 0, 0, 21, 0, 0, 0, 170, 0, 0, 0, 92, 0, 0, 0, 52, 0, 0, 0, 135, 0, 0, 0, 153, 0, 0, 0, 162, 0, 0, 0, 140, 0, 0, 0, 38, 0, 0, 0, 132, 0, 0, 0, 98, 0, 0, 0, 125, 0, 0, 0, 182, 0, 0, 0, 41, 0, 0, 0, 192, 0, 0, 0, 82, 0, 0, 0, 234, 0, 0, 0, 245, 0, 0, 0, 129, 0, 0, 0, 24, 0, 0, 0, 15, 0, 0, 0, 53, 0, 0, 0, 169, 0, 0, 0, 14, 0, 0, 0, 231, 0, 0, 0, 32, 0, 0, 0, 114, 0, 0, 0, 124, 0, 0, 0, 109, +0, 0, 0, 148, 0, 0, 0, 95, 0, 0, 0, 82, 0, 0, 0, 68, 0, 0, 0, 84, 0, 0, 0, 227, 0, 0, 0, 241, 0, 0, 0, 178, 0, 0, 0, 176, 0, 0, 0, 54, 0, 0, 0, 70, 0, 0, 0, 15, 0, 0, 0, 174, 0, 0, 0, 146, 0, 0, 0, 232, 0, 0, 0, 112, 0, 0, 0, 157, 0, 0, 0, 110, 0, 0, 0, 121, 0, 0, 0, 177, 0, 0, 0, 173, 0, 0, 0, 55, 0, 0, 0, 169, 0, 0, 0, 95, 0, 0, 0, 192, 0, 0, 0, 222, 0, 0, 0, 3, 0, 0, 0, 21, 0, 0, 0, 85, 0, 0, 0, 55, 0, 0, 0, 198, 0, 0, 0, 28, 0, 0, 0, 39, 0, 0, 0, 28, 0, 0, 0, 109, 0, 0, 0, 20, 0, 0, 0, 79, 0, +0, 0, 202, 0, 0, 0, 164, 0, 0, 0, 196, 0, 0, 0, 136, 0, 0, 0, 37, 0, 0, 0, 70, 0, 0, 0, 57, 0, 0, 0, 252, 0, 0, 0, 90, 0, 0, 0, 229, 0, 0, 0, 254, 0, 0, 0, 41, 0, 0, 0, 17, 0, 0, 0, 105, 0, 0, 0, 245, 0, 0, 0, 114, 0, 0, 0, 132, 0, 0, 0, 77, 0, 0, 0, 120, 0, 0, 0, 159, 0, 0, 0, 148, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, 0, 211, 0, 0, 0, 255, 0, 0, 0, 87, 0, 0, 0, 11, 0, 0, 0, 176, 0, 0, 0, 178, 0, 0, 0, 220, 0, 0, 0, 248, 0, 0, 0, 79, 0, 0, 0, 226, 0, 0, 0, 18, 0, 0, 0, 213, 0, 0, 0, 54, 0, 0, 0, 190, 0, 0, 0, 107, 0, 0, 0, 9, 0, 0, 0, 67, 0, 0, 0, 109, 0, 0, 0, 163, 0, 0, 0, 77, 0, 0, 0, 144, 0, 0, 0, 45, 0, 0, 0, 184, 0, 0, 0, 116, 0, 0, 0, 232, 0, 0, 0, 113, 0, 0, 0, 69, 0, 0, 0, 25, 0, 0, 0, 139, 0, 0, 0, 12, 0, 0, 0, 106, 0, +0, 0, 184, 0, 0, 0, 66, 0, 0, 0, 28, 0, 0, 0, 3, 0, 0, 0, 173, 0, 0, 0, 44, 0, 0, 0, 3, 0, 0, 0, 142, 0, 0, 0, 172, 0, 0, 0, 215, 0, 0, 0, 152, 0, 0, 0, 41, 0, 0, 0, 19, 0, 0, 0, 198, 0, 0, 0, 2, 0, 0, 0, 41, 0, 0, 0, 181, 0, 0, 0, 212, 0, 0, 0, 231, 0, 0, 0, 207, 0, 0, 0, 204, 0, 0, 0, 139, 0, 0, 0, 131, 0, 0, 0, 236, 0, 0, 0, 53, 0, 0, 0, 199, 0, 0, 0, 156, 0, 0, 0, 116, 0, 0, 0, 183, 0, 0, 0, 173, 0, 0, 0, 133, 0, 0, 0, 95, 0, 0, 0, 120, 0, 0, 0, 132, 0, 0, 0, 225, 0, 0, 0, 86, 0, 0, 0, 69, 0, +0, 0, 105, 0, 0, 0, 104, 0, 0, 0, 90, 0, 0, 0, 79, 0, 0, 0, 184, 0, 0, 0, 177, 0, 0, 0, 41, 0, 0, 0, 255, 0, 0, 0, 51, 0, 0, 0, 3, 0, 0, 0, 49, 0, 0, 0, 183, 0, 0, 0, 203, 0, 0, 0, 150, 0, 0, 0, 37, 0, 0, 0, 230, 0, 0, 0, 230, 0, 0, 0, 65, 0, 0, 0, 152, 0, 0, 0, 26, 0, 0, 0, 187, 0, 0, 0, 3, 0, 0, 0, 86, 0, 0, 0, 242, 0, 0, 0, 178, 0, 0, 0, 145, 0, 0, 0, 52, 0, 0, 0, 44, 0, 0, 0, 108, 0, 0, 0, 247, 0, 0, 0, 102, 0, 0, 0, 164, 0, 0, 0, 98, 0, 0, 0, 107, 0, 0, 0, 57, 0, 0, 0, 179, 0, 0, 0, 186, 0, +0, 0, 101, 0, 0, 0, 211, 0, 0, 0, 28, 0, 0, 0, 248, 0, 0, 0, 17, 0, 0, 0, 170, 0, 0, 0, 190, 0, 0, 0, 220, 0, 0, 0, 128, 0, 0, 0, 89, 0, 0, 0, 135, 0, 0, 0, 245, 0, 0, 0, 123, 0, 0, 0, 229, 0, 0, 0, 227, 0, 0, 0, 179, 0, 0, 0, 62, 0, 0, 0, 57, 0, 0, 0, 218, 0, 0, 0, 190, 0, 0, 0, 136, 0, 0, 0, 9, 0, 0, 0, 139, 0, 0, 0, 241, 0, 0, 0, 160, 0, 0, 0, 245, 0, 0, 0, 220, 0, 0, 0, 41, 0, 0, 0, 180, 0, 0, 0, 226, 0, 0, 0, 7, 0, 0, 0, 198, 0, 0, 0, 122, 0, 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, 137, 0, 0, 0, 23, +0, 0, 0, 81, 0, 0, 0, 212, 0, 0, 0, 187, 0, 0, 0, 212, 0, 0, 0, 34, 0, 0, 0, 234, 0, 0, 0, 126, 0, 0, 0, 125, 0, 0, 0, 124, 0, 0, 0, 36, 0, 0, 0, 234, 0, 0, 0, 242, 0, 0, 0, 232, 0, 0, 0, 34, 0, 0, 0, 18, 0, 0, 0, 149, 0, 0, 0, 6, 0, 0, 0, 218, 0, 0, 0, 124, 0, 0, 0, 164, 0, 0, 0, 12, 0, 0, 0, 244, 0, 0, 0, 186, 0, 0, 0, 110, 0, 0, 0, 225, 0, 0, 0, 137, 0, 0, 0, 181, 0, 0, 0, 89, 0, 0, 0, 202, 0, 0, 0, 241, 0, 0, 0, 192, 0, 0, 0, 41, 0, 0, 0, 54, 0, 0, 0, 9, 0, 0, 0, 68, 0, 0, 0, 226, 0, 0, 0, 127, +0, 0, 0, 209, 0, 0, 0, 99, 0, 0, 0, 21, 0, 0, 0, 153, 0, 0, 0, 234, 0, 0, 0, 37, 0, 0, 0, 207, 0, 0, 0, 12, 0, 0, 0, 157, 0, 0, 0, 192, 0, 0, 0, 68, 0, 0, 0, 111, 0, 0, 0, 29, 0, 0, 0, 134, 0, 0, 0, 78, 0, 0, 0, 207, 0, 0, 0, 247, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 18, 0, 0, 0, 251, 0, 0, 0, 25, 0, 0, 0, 251, 0, 0, 0, 224, 0, 0, 0, 237, 0, 0, 0, 16, 0, 0, 0, 200, 0, 0, 0, 226, 0, 0, 0, 245, 0, 0, 0, 117, 0, 0, 0, 177, 0, 0, 0, 51, 0, 0, 0, 192, 0, 0, 0, 150, 0, 0, 0, 13, +0, 0, 0, 251, 0, 0, 0, 21, 0, 0, 0, 108, 0, 0, 0, 13, 0, 0, 0, 7, 0, 0, 0, 95, 0, 0, 0, 5, 0, 0, 0, 105, 0, 0, 0, 62, 0, 0, 0, 71, 0, 0, 0, 151, 0, 0, 0, 44, 0, 0, 0, 175, 0, 0, 0, 82, 0, 0, 0, 124, 0, 0, 0, 120, 0, 0, 0, 131, 0, 0, 0, 173, 0, 0, 0, 27, 0, 0, 0, 57, 0, 0, 0, 130, 0, 0, 0, 47, 0, 0, 0, 2, 0, 0, 0, 111, 0, 0, 0, 71, 0, 0, 0, 219, 0, 0, 0, 42, 0, 0, 0, 176, 0, 0, 0, 225, 0, 0, 0, 145, 0, 0, 0, 153, 0, 0, 0, 85, 0, 0, 0, 184, 0, 0, 0, 153, 0, 0, 0, 58, 0, 0, 0, 160, 0, 0, 0, 68, 0, 0, +0, 17, 0, 0, 0, 81, 0, 0, 0, 163, 120, 89, 19, 202, 77, 235, 117, 171, 216, 65, 65, 77, 10, 112, 0, 152, 232, 121, 119, 121, 64, 199, 140, 115, 254, 111, 43, 238, 108, 3, 82, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 15, 10, 5, 0, 14, 9, 4, 3, 13, 8, 7, 2, 12, 11, 6, 1, 1, 2, 3, 0, 6, 7, 4, 5, 11, 8, 9, 10, 12, 13, 14, 15, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 12, 8, 4, 0, 13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3, 15, 11, 7, 3, 14, 10, 6, 2, 13, 9, 5, 1, 12, 8, 4, 0, 3, 3, 3, +3, 7, 7, 7, 7, 11, 11, 11, 11, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31, 26, 0, 0, 0, 213, 0, 0, 0, 37, 0, 0, 0, 143, 0, 0, 0, 96, 0, 0, 0, 45, 0, 0, 0, 86, 0, 0, 0, 201, 0, 0, 0, 178, 0, 0, 0, 167, 0, 0, 0, 37, 0, 0, 0, 149, 0, 0, 0, 96, 0, 0, 0, 199, 0, 0, 0, 44, 0, 0, 0, 105, 0, 0, 0, 92, 0, 0, 0, 220, 0, 0, 0, 214, 0, 0, 0, 253, 0, 0, 0, 49, 0, 0, 0, 226, +0, 0, 0, 164, 0, 0, 0, 192, 0, 0, 0, 254, 0, 0, 0, 83, 0, 0, 0, 110, 0, 0, 0, 205, 0, 0, 0, 211, 0, 0, 0, 54, 0, 0, 0, 105, 0, 0, 0, 33, 0, 0, 0, 88, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, +0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 163, 0, 0, 0, 221, 0, 0, 0, +183, 0, 0, 0, 165, 0, 0, 0, 179, 0, 0, 0, 138, 0, 0, 0, 222, 0, 0, 0, 109, 0, 0, 0, 245, 0, 0, 0, 82, 0, 0, 0, 81, 0, 0, 0, 119, 0, 0, 0, 128, 0, 0, 0, 159, 0, 0, 0, 240, 0, 0, 0, 32, 0, 0, 0, 125, 0, 0, 0, 227, 0, 0, 0, 171, 0, 0, 0, 100, 0, 0, 0, 142, 0, 0, 0, 78, 0, 0, 0, 234, 0, 0, 0, 102, 0, 0, 0, 101, 0, 0, 0, 118, 0, 0, 0, 139, 0, 0, 0, 215, 0, 0, 0, 15, 0, 0, 0, 95, 0, 0, 0, 135, 0, 0, 0, 103, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 97, 109, 98, 105, 103, 117, 111, 117, 115, 32, 111, 112, 116, 105, 111, 110, 32, 45, 45, 32, 37, 46, 42, 115, 0, 0, 0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 80, 79, 83, 73, 88, 76, 89, 95, 67, 79, 82, 82, 69, 67, 84, 0, 115, 116, 100, 58, 58, 98, 97, 100, 95, 97, 108, 108, 111, 99, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 37, 115, 10, 0, 0, 0, 0, 0, 105, 110, 32, 117, 115, 101, 32, 98, 121, 116, 101, 115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, +0, 0, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 37, 115, 58, 32, 0, 0, 0, 0, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 58, 32, 0, 0, 0, 0, 0, 0, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, 115, 32, 32, 32, 32, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, 109, 97, 120, 32, 115, 121, 115, 116, 101, 109, 32, 98, 121, 116, 101, 115, 32, 61, 32, 37, 49, 48, 108, 117, 10, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 120, 181, 1, 0, 6, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 181, 1, 0, 6, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 116, 57, 101, 120, 99, 101, 112, 116, 105, 111, 110, 0, 0, 0, 0, 83, 116, 57, 98, 97, 100, 95, 97, 108, 108, 111, 99, 0, 0, 0, 0, 83, 116, 50, 48, 98, 97, 100, 95, 97, 114, 114, 97, 121, 95, 110, 101, 119, 95, 108, 101, 110, 103, 116, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 181, 1, 0, 0, 0, 0, 0, 64, 181, 1, 0, 112, 181, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 181, 1, 0, 120, 181, 1, 0, 0, 0, 0, 0]), "i8", Na, 8); var qb = xa(F(12, "i8", E), 8); v(0 == qb % 8); @@ -1198,14 +1199,14 @@ var vb = 0; function M(a) { return B[vb >> 2] = a } -var N = {L:1, ca:2, Bd:3, sc:4, I:5, za:6, Jb:7, Sc:8, $:9, Zb:10, ua:11, Ld:11, $a:12, Ya:13, kc:14, ed:15, Wb:16, va:17, Md:18, wa:19, gd:20, aa:21, A:22, Mc:23, Za:24, ld:25, Id:26, lc:27, ad:28, da:29, yd:30, Fc:31, rd:32, hc:33, ab:34, Wc:35, pc:36, $b:37, vc:38, wc:39, xc:40, Ec:41, Jd:42, Qc:43, uc:44, ec:45, Tc:46, Pb:50, Sb:51, Nd:52, Oc:53, Tb:54, Ub:55, fc:56, Vb:57, cd:60, Rc:61, Fd:62, bd:63, Xc:64, Yc:65, xd:66, Uc:67, Mb:68, Cd:69, ac:70, td:71, Hc:74, yc:75, ic:76, Rb:77, mc:79, md:80, -Qb:81, wd:82, zc:83, Ac:84, Dc:85, Cc:86, Bc:87, dd:88, Nc:89, ya:90, Ic:91, ba:92, nd:95, qd:96, dc:104, Pc:105, Nb:106, vd:107, jd:108, Zc:109, zd:110, cc:111, Kb:112, bc:113, Lc:114, Jc:115, Gd:116, nc:117, oc:118, rc:119, Ob:120, gc:121, Gc:122, ud:123, Ad:124, Lb:125, Kc:126, tc:127, fd:128, Hd:129, sd:130, Kd:131, jc:132, Dd:133, kd:134, Vc:135, $c:136, Yb:137, qc:138, od:139, Xb:140, hd:141, pd:142, Ed:143}, wb = {"0":"Success", 1:"Not super-user", 2:"No such file or directory", 3:"No such process", -4:"Interrupted system call", 5:"I/O error", 6:"No such device or address", 7:"Arg list too long", 8:"Exec format error", 9:"Bad file number", 10:"No children", 11:"No more processes", 12:"Not enough core", 13:"Permission denied", 14:"Bad address", 15:"Block device required", 16:"Mount device busy", 17:"File exists", 18:"Cross-device link", 19:"No such device", 20:"Not a directory", 21:"Is a directory", 22:"Invalid argument", 23:"Too many open files in system", 24:"Too many open files", 25:"Not a typewriter", -26:"Text file busy", 27:"File too large", 28:"No space left on device", 29:"Illegal seek", 30:"Read only file system", 31:"Too many links", 32:"Broken pipe", 33:"Math arg out of domain of func", 34:"Math result not representable", 35:"No message of desired type", 36:"Identifier removed", 37:"Channel number out of range", 38:"Level 2 not synchronized", 39:"Level 3 halted", 40:"Level 3 reset", 41:"Link number out of range", 42:"Protocol driver not attached", 43:"No CSI structure available", 44:"Level 2 halted", -45:"Deadlock condition", 46:"No record locks available", 50:"Invalid exchange", 51:"Invalid request descriptor", 52:"Exchange full", 53:"No anode", 54:"Invalid request code", 55:"Invalid slot", 56:"File locking deadlock error", 57:"Bad font file fmt", 60:"Device not a stream", 61:"No data (for no delay io)", 62:"Timer expired", 63:"Out of streams resources", 64:"Machine is not on the network", 65:"Package not installed", 66:"The object is remote", 67:"The link has been severed", 68:"Advertise error", -69:"Srmount error", 70:"Communication error on send", 71:"Protocol error", 74:"Multihop attempted", 75:"Inode is remote (not really error)", 76:"Cross mount point (not really error)", 77:"Trying to read unreadable message", 79:"Inappropriate file type or format", 80:"Given log. name not unique", 81:"f.d. invalid for this operation", 82:"Remote address changed", 83:"Can\t access a needed shared lib", 84:"Accessing a corrupted shared lib", 85:".lib section in a.out corrupted", 86:"Attempting to link in too many libs", -87:"Attempting to exec a shared library", 88:"Function not implemented", 89:"No more files", 90:"Directory not empty", 91:"File or path name too long", 92:"Too many symbolic links", 95:"Operation not supported on transport endpoint", 96:"Protocol family not supported", 104:"Connection reset by peer", 105:"No buffer space available", 106:"Address family not supported by protocol family", 107:"Protocol wrong type for socket", 108:"Socket operation on non-socket", 109:"Protocol not available", 110:"Can't send after socket shutdown", -111:"Connection refused", 112:"Address already in use", 113:"Connection aborted", 114:"Network is unreachable", 115:"Network interface is not configured", 116:"Connection timed out", 117:"Host is down", 118:"Host is unreachable", 119:"Connection already in progress", 120:"Socket already connected", 121:"Destination address required", 122:"Message too long", 123:"Unknown protocol", 124:"Socket type not supported", 125:"Address not available", 126:"ENETRESET", 127:"Socket is already connected", 128:"Socket is not connected", +var N = {L:1, ca:2, Bd:3, sc:4, I:5, za:6, Jb:7, Sc:8, $:9, Zb:10, ua:11, Ld:11, $a:12, Ya:13, kc:14, ed:15, Wb:16, va:17, Md:18, wa:19, gd:20, aa:21, A:22, Mc:23, Za:24, ld:25, Id:26, lc:27, ad:28, da:29, yd:30, Fc:31, rd:32, hc:33, ab:34, Wc:35, pc:36, $b:37, vc:38, wc:39, xc:40, Ec:41, Jd:42, Qc:43, uc:44, ec:45, Tc:46, Pb:50, Sb:51, Nd:52, Oc:53, Tb:54, Ub:55, fc:56, Vb:57, cd:60, Rc:61, Fd:62, bd:63, Xc:64, Yc:65, xd:66, Uc:67, Mb:68, Cd:69, ac:70, td:71, Hc:74, yc:75, ic:76, Rb:77, mc:79, md:80, +Qb:81, wd:82, zc:83, Ac:84, Dc:85, Cc:86, Bc:87, dd:88, Nc:89, ya:90, Ic:91, ba:92, nd:95, qd:96, dc:104, Pc:105, Nb:106, vd:107, jd:108, Zc:109, zd:110, cc:111, Kb:112, bc:113, Lc:114, Jc:115, Gd:116, nc:117, oc:118, rc:119, Ob:120, gc:121, Gc:122, ud:123, Ad:124, Lb:125, Kc:126, tc:127, fd:128, Hd:129, sd:130, Kd:131, jc:132, Dd:133, kd:134, Vc:135, $c:136, Yb:137, qc:138, od:139, Xb:140, hd:141, pd:142, Ed:143}, wb = {"0":"Success", 1:"Not super-user", 2:"No such file or directory", 3:"No such process", +4:"Interrupted system call", 5:"I/O error", 6:"No such device or address", 7:"Arg list too long", 8:"Exec format error", 9:"Bad file number", 10:"No children", 11:"No more processes", 12:"Not enough core", 13:"Permission denied", 14:"Bad address", 15:"Block device required", 16:"Mount device busy", 17:"File exists", 18:"Cross-device link", 19:"No such device", 20:"Not a directory", 21:"Is a directory", 22:"Invalid argument", 23:"Too many open files in system", 24:"Too many open files", 25:"Not a typewriter", +26:"Text file busy", 27:"File too large", 28:"No space left on device", 29:"Illegal seek", 30:"Read only file system", 31:"Too many links", 32:"Broken pipe", 33:"Math arg out of domain of func", 34:"Math result not representable", 35:"No message of desired type", 36:"Identifier removed", 37:"Channel number out of range", 38:"Level 2 not synchronized", 39:"Level 3 halted", 40:"Level 3 reset", 41:"Link number out of range", 42:"Protocol driver not attached", 43:"No CSI structure available", 44:"Level 2 halted", +45:"Deadlock condition", 46:"No record locks available", 50:"Invalid exchange", 51:"Invalid request descriptor", 52:"Exchange full", 53:"No anode", 54:"Invalid request code", 55:"Invalid slot", 56:"File locking deadlock error", 57:"Bad font file fmt", 60:"Device not a stream", 61:"No data (for no delay io)", 62:"Timer expired", 63:"Out of streams resources", 64:"Machine is not on the network", 65:"Package not installed", 66:"The object is remote", 67:"The link has been severed", 68:"Advertise error", +69:"Srmount error", 70:"Communication error on send", 71:"Protocol error", 74:"Multihop attempted", 75:"Inode is remote (not really error)", 76:"Cross mount point (not really error)", 77:"Trying to read unreadable message", 79:"Inappropriate file type or format", 80:"Given log. name not unique", 81:"f.d. invalid for this operation", 82:"Remote address changed", 83:"Can\t access a needed shared lib", 84:"Accessing a corrupted shared lib", 85:".lib section in a.out corrupted", 86:"Attempting to link in too many libs", +87:"Attempting to exec a shared library", 88:"Function not implemented", 89:"No more files", 90:"Directory not empty", 91:"File or path name too long", 92:"Too many symbolic links", 95:"Operation not supported on transport endpoint", 96:"Protocol family not supported", 104:"Connection reset by peer", 105:"No buffer space available", 106:"Address family not supported by protocol family", 107:"Protocol wrong type for socket", 108:"Socket operation on non-socket", 109:"Protocol not available", 110:"Can't send after socket shutdown", +111:"Connection refused", 112:"Address already in use", 113:"Connection aborted", 114:"Network is unreachable", 115:"Network interface is not configured", 116:"Connection timed out", 117:"Host is down", 118:"Host is unreachable", 119:"Connection already in progress", 120:"Socket already connected", 121:"Destination address required", 122:"Message too long", 123:"Unknown protocol", 124:"Socket type not supported", 125:"Address not available", 126:"ENETRESET", 127:"Socket is already connected", 128:"Socket is not connected", 129:"TOOMANYREFS", 130:"EPROCLIM", 131:"EUSERS", 132:"EDQUOT", 133:"ESTALE", 134:"Not supported", 135:"No medium (in tape drive)", 136:"No such host or network path", 137:"Filename exists with different case", 138:"EILSEQ", 139:"Value too large for defined data type", 140:"Operation canceled", 141:"State not recoverable", 142:"Previous owner died", 143:"Streams pipe error"}; function xb(a, b, c) { var d = O(a, {parent:l}).d, a = "/" === a ? "/" : yb(a)[2], f = zb(d, a); @@ -1518,22 +1519,22 @@ var Qb = {open:function(a) { return{te:d, Xd:f} }}}, Vb = F(1, "i32*", E), Wb = F(1, "i32*", E); nb = F(1, "i32*", E); -var Xb = m, Pb = [m], R = [m], Yb = 1, Zb = [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , -, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +var Xb = m, Pb = [m], R = [m], Yb = 1, Zb = [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ], $b = l; function Q(a) { this.mb = a; @@ -2625,9 +2626,9 @@ Sa = u = xa(sa); Ta = Sa + 5242880; Ua = x = xa(Ta); v(Ua < va); -var Xc = F([8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", 3), Yc = F([8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, -2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, +var Xc = F([8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "i8", 3), Yc = F([8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, +2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0], "i8", 3), Zc = Math.min; var V = (function(global,env,buffer) { // EMSCRIPTEN_START_ASM diff --git a/www/js/vendor/ng-cordova.min.js b/www/js/vendor/ng-cordova.min.js new file mode 100644 index 0000000000000000000000000000000000000000..4ae32822d7219ee0176b83737f144bc7e320d900 --- /dev/null +++ b/www/js/vendor/ng-cordova.min.js @@ -0,0 +1,9 @@ +/*! + * ngCordova + * v0.1.26-alpha + * Copyright 2015 Drifty Co. http://drifty.com/ + * See LICENSE in this repository for license information + */ +!function(){angular.module("ngCordova",["ngCordova.plugins"]),angular.module("ngCordova.plugins.actionSheet",[]).factory("$cordovaActionSheet",["$q","$window",function(e,n){return{show:function(r){var o=e.defer();return n.plugins.actionsheet.show(r,function(e){o.resolve(e)}),o.promise},hide:function(){return n.plugins.actionsheet.hide()}}}]),angular.module("ngCordova.plugins.adMob",[]).factory("$cordovaAdMob",["$q","$window",function(e,n){return{createBannerView:function(r){var o=e.defer();return n.plugins.AdMob.createBannerView(r,function(){o.resolve()},function(){o.reject()}),o.promise},createInterstitialView:function(r){var o=e.defer();return n.plugins.AdMob.createInterstitialView(r,function(){o.resolve()},function(){o.reject()}),o.promise},requestAd:function(r){var o=e.defer();return n.plugins.AdMob.requestAd(r,function(){o.resolve()},function(){o.reject()}),o.promise},showAd:function(r){var o=e.defer();return n.plugins.AdMob.showAd(r,function(){o.resolve()},function(){o.reject()}),o.promise},requestInterstitialAd:function(r){var o=e.defer();return n.plugins.AdMob.requestInterstitialAd(r,function(){o.resolve()},function(){o.reject()}),o.promise}}}]),angular.module("ngCordova.plugins.appAvailability",[]).factory("$cordovaAppAvailability",["$q",function(e){return{check:function(n){var r=e.defer();return appAvailability.check(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.appRate",[]).provider("$cordovaAppRate",[function(){this.setPreferences=function(e){e&&angular.isObject(e)&&(AppRate.preferences.useLanguage=e.language||null,AppRate.preferences.displayAppName=e.appName||"",AppRate.preferences.promptAgainForEachNewVersion=e.promptForNewVersion||!0,AppRate.preferences.openStoreInApp=e.openStoreInApp||!1,AppRate.preferences.usesUntilPrompt=e.usesUntilPrompt||3,AppRate.preferences.useCustomRateDialog=e.useCustomRateDialog||!1,AppRate.preferences.storeAppURL.ios=e.iosURL||null,AppRate.preferences.storeAppURL.android=e.androidURL||null,AppRate.preferences.storeAppURL.blackberry=e.blackberryURL||null,AppRate.preferences.storeAppURL.windows8=e.windowsURL||null)},this.setCustomLocale=function(e){var n={title:"Rate %@",message:"If you enjoy using %@, would you mind taking a moment to rate it? It won’t take more than a minute. Thanks for your support!",cancelButtonLabel:"No, Thanks",laterButtonLabel:"Remind Me Later",rateButtonLabel:"Rate It Now"};n=angular.extend(n,e),AppRate.preferences.customLocale=n},this.$get=["$q",function(e){return{promptForRating:function(n){var r=e.defer(),o=AppRate.promptForRating(n);return r.resolve(o),r.promise},navigateToAppStore:function(){var n=e.defer(),r=AppRate.navigateToAppStore();return n.resolve(r),n.promise},onButtonClicked:function(e){AppRate.onButtonClicked=function(n){e.call(this,n)}},onRateDialogShow:function(e){AppRate.onRateDialogShow=e()}}}]}]),angular.module("ngCordova.plugins.appVersion",[]).factory("$cordovaAppVersion",["$q",function(e){return{getAppName:function(){var n=e.defer();return cordova.getAppVersion.getAppName(function(e){n.resolve(e)}),n.promise},getPackageName:function(){var n=e.defer();return cordova.getAppVersion.getPackageName(function(e){n.resolve(e)}),n.promise},getVersionNumber:function(){var n=e.defer();return cordova.getAppVersion.getVersionNumber(function(e){n.resolve(e)}),n.promise},getVersionCode:function(){var n=e.defer();return cordova.getAppVersion.getVersionCode(function(e){n.resolve(e)}),n.promise}}}]),angular.module("ngCordova.plugins.backgroundGeolocation",[]).factory("$cordovaBackgroundGeolocation",["$q","$window",function(e,n){return{init:function(){n.navigator.geolocation.getCurrentPosition(function(e){return e})},configure:function(r){this.init();var o=e.defer();return n.plugins.backgroundGeoLocation.configure(function(e){o.notify(e),n.plugins.backgroundGeoLocation.finish()},function(e){o.reject(e)},r),this.start(),o.promise},start:function(){var r=e.defer();return n.plugins.backgroundGeoLocation.start(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},stop:function(){var r=e.defer();return n.plugins.backgroundGeoLocation.stop(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.badge",[]).factory("$cordovaBadge",["$q",function(e){return{hasPermission:function(){var n=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?n.resolve(!0):n.reject("You do not have permission")}),n.promise},promptForPermission:function(){return cordova.plugins.notification.badge.promptForPermission()},set:function(n,r,o){var t=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?t.resolve(cordova.plugins.notification.badge.set(n,r,o)):t.reject("You do not have permission to set Badge")}),t.promise},get:function(){var n=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?cordova.plugins.notification.badge.get(function(e){n.resolve(e)}):n.reject("You do not have permission to get Badge")}),n.promise},clear:function(n,r){var o=e.defer();return cordova.plugins.notification.badge.hasPermission(function(e){e?o.resolve(cordova.plugins.notification.badge.clear(n,r)):o.reject("You do not have permission to clear Badge")}),o.promise},increase:function(n,r,o){var t=e.defer();return this.hasPermission().then(function(){t.resolve(cordova.plugins.notification.badge.increase(n,r,o))},function(){t.reject("You do not have permission to increase Badge")}),t.promise},decrease:function(n,r,o){var t=e.defer();return this.hasPermission().then(function(){t.resolve(cordova.plugins.notification.badge.decrease(n,r,o))},function(){t.reject("You do not have permission to decrease Badge")}),t.promise},configure:function(e){return cordova.plugins.notification.badge.configure(e)}}}]),angular.module("ngCordova.plugins.barcodeScanner",[]).factory("$cordovaBarcodeScanner",["$q",function(e){return{scan:function(n){var r=e.defer();return cordova.plugins.barcodeScanner.scan(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},encode:function(n,r){var o=e.defer();return n=n||"TEXT_TYPE",cordova.plugins.barcodeScanner.encode(n,r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.batteryStatus",[]).factory("$cordovaBatteryStatus",["$rootScope","$window","$timeout",function(e,n,r){var o=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:status",n)})},t=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:critical",n)})},i=function(n){r(function(){e.$broadcast("$cordovaBatteryStatus:low",n)})};return document.addEventListener("deviceready",function(){navigator.battery&&(n.addEventListener("batterystatus",o,!1),n.addEventListener("batterycritical",t,!1),n.addEventListener("batterylow",i,!1))},!1),!0}]).run(["$injector",function(e){e.get("$cordovaBatteryStatus")}]),angular.module("ngCordova.plugins.beacon",[]).factory("$cordovaBeacon",["$window","$rootScope","$timeout","$q",function(e,n,r,o){var t=null,i=null,a=null,c=null,u=null,s=null,l=null,f=null;return document.addEventListener("deviceready",function(){if(e.cordova&&e.cordova.plugins&&e.cordova.plugins.locationManager){var o=new e.cordova.plugins.locationManager.Delegate;o.didDetermineStateForRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didDetermineStateForRegion",e)}),t&&t(e)},o.didStartMonitoringForRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didStartMonitoringForRegion",e)}),i&&i(e)},o.didExitRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didExitRegion",e)}),a&&a(e)},o.didEnterRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didEnterRegion",e)}),c&&c(e)},o.didRangeBeaconsInRegion=function(e){r(function(){n.$broadcast("$cordovaBeacon:didRangeBeaconsInRegion",e)}),u&&u(e)},o.peripheralManagerDidStartAdvertising=function(e){r(function(){n.$broadcast("$cordovaBeacon:peripheralManagerDidStartAdvertising",e)}),s&&s(e)},o.peripheralManagerDidUpdateState=function(e){r(function(){n.$broadcast("$cordovaBeacon:peripheralManagerDidUpdateState",e)}),l&&l(e)},o.didChangeAuthorizationStatus=function(e){r(function(){n.$broadcast("$cordovaBeacon:didChangeAuthorizationStatus",e)}),f&&f(e)},e.cordova.plugins.locationManager.setDelegate(o)}},!1),{setCallbackDidDetermineStateForRegion:function(e){t=e},setCallbackDidStartMonitoringForRegion:function(e){i=e},setCallbackDidExitRegion:function(e){a=e},setCallbackDidEnterRegion:function(e){c=e},setCallbackDidRangeBeaconsInRegion:function(e){u=e},setCallbackPeripheralManagerDidStartAdvertising:function(e){s=e},setCallbackPeripheralManagerDidUpdateState:function(e){l=e},setCallbackDidChangeAuthorizationStatus:function(e){f=e},createBeaconRegion:function(n,r,o,t,i){return o=o||void 0,t=t||void 0,new e.cordova.plugins.locationManager.BeaconRegion(n,r,o,t,i)},isBluetoothEnabled:function(){return o.when(e.cordova.plugins.locationManager.isBluetoothEnabled())},enableBluetooth:function(){return o.when(e.cordova.plugins.locationManager.enableBluetooth())},disableBluetooth:function(){return o.when(e.cordova.plugins.locationManager.disableBluetooth())},startMonitoringForRegion:function(n){return o.when(e.cordova.plugins.locationManager.startMonitoringForRegion(n))},stopMonitoringForRegion:function(n){return o.when(e.cordova.plugins.locationManager.stopMonitoringForRegion(n))},requestStateForRegion:function(n){return o.when(e.cordova.plugins.locationManager.requestStateForRegion(n))},startRangingBeaconsInRegion:function(n){return o.when(e.cordova.plugins.locationManager.startRangingBeaconsInRegion(n))},stopRangingBeaconsInRegion:function(n){return o.when(e.cordova.plugins.locationManager.stopRangingBeaconsInRegion(n))},getAuthorizationStatus:function(){return o.when(e.cordova.plugins.locationManager.getAuthorizationStatus())},requestWhenInUseAuthorization:function(){return o.when(e.cordova.plugins.locationManager.requestWhenInUseAuthorization())},requestAlwaysAuthorization:function(){return o.when(e.cordova.plugins.locationManager.requestAlwaysAuthorization())},getMonitoredRegions:function(){return o.when(e.cordova.plugins.locationManager.getMonitoredRegions())},getRangedRegions:function(){return o.when(e.cordova.plugins.locationManager.getRangedRegions())},isRangingAvailable:function(){return o.when(e.cordova.plugins.locationManager.isRangingAvailable())},isMonitoringAvailableForClass:function(n){return o.when(e.cordova.plugins.locationManager.isMonitoringAvailableForClass(n))},startAdvertising:function(n,r){return o.when(e.cordova.plugins.locationManager.startAdvertising(n,r))},stopAdvertising:function(){return o.when(e.cordova.plugins.locationManager.stopAdvertising())},isAdvertisingAvailable:function(){return o.when(e.cordova.plugins.locationManager.isAdvertisingAvailable())},isAdvertising:function(){return o.when(e.cordova.plugins.locationManager.isAdvertising())},disableDebugLogs:function(){return o.when(e.cordova.plugins.locationManager.disableDebugLogs())},enableDebugNotifications:function(){return o.when(e.cordova.plugins.locationManager.enableDebugNotifications())},disableDebugNotifications:function(){return o.when(e.cordova.plugins.locationManager.disableDebugNotifications())},enableDebugLogs:function(){return o.when(e.cordova.plugins.locationManager.enableDebugLogs())},appendToDeviceLog:function(n){return o.when(e.cordova.plugins.locationManager.appendToDeviceLog(n))}}}]),angular.module("ngCordova.plugins.ble",[]).factory("$cordovaBLE",["$q","$timeout","$log",function(e,n,r){return{scan:function(r,o){var t=e.defer();return ble.startScan(r,function(e){t.notify(e)},function(e){t.reject(e)}),n(function(){ble.stopScan(function(){t.resolve()},function(e){t.reject(e)})},1e3*o),t.promise},startScan:function(e,n,r){return ble.startScan(e,n,r)},stopScan:function(){var n=e.defer();return ble.stopScan(function(){n.resolve()},function(e){n.reject(e)}),n.promise},connect:function(n){var r=e.defer();return ble.connect(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},disconnect:function(n){var r=e.defer();return ble.disconnect(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},read:function(n,r,o){var t=e.defer();return ble.read(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},write:function(n,r,o,t){var i=e.defer();return ble.write(n,r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},writeWithoutResponse:function(n,r,o,t){var i=e.defer();return ble.writeWithoutResponse(n,r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},writeCommand:function(e,n,o,t){return r.warning("writeCommand is deprecated, use writeWithoutResponse"),this.writeWithoutResponse(e,n,o,t)},startNotification:function(e,n,r,o,t){return ble.startNotification(e,n,r,o,t)},stopNotification:function(n,r,o){var t=e.defer();return ble.stopNotification(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},isConnected:function(n){var r=e.defer();return ble.isConnected(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},enable:function(){var n=e.defer();return ble.enable(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},isEnabled:function(){var n=e.defer();return ble.isEnabled(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.bluetoothSerial",[]).factory("$cordovaBluetoothSerial",["$q","$window",function(e,n){return{connect:function(r){var o=e.defer(),t=e.defer(),i=!1;return n.bluetoothSerial.connect(r,function(){i=!0,o.resolve(t)},function(e){i===!1&&t.reject(e),o.reject(e)}),o.promise},connectInsecure:function(r){var o=e.defer();return n.bluetoothSerial.connectInsecure(r,function(){o.resolve()},function(e){o.reject(e)}),o.promise},disconnect:function(){var r=e.defer();return n.bluetoothSerial.disconnect(function(){r.resolve()},function(e){r.reject(e)}),r.promise},list:function(){var r=e.defer();return n.bluetoothSerial.list(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},discoverUnpaired:function(){var r=e.defer();return n.bluetoothSerial.discoverUnpaired(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},setDeviceDiscoveredListener:function(){var r=e.defer();return n.bluetoothSerial.setDeviceDiscoveredListener(function(e){r.notify(e)}),r.promise},clearDeviceDiscoveredListener:function(){n.bluetoothSerial.clearDeviceDiscoveredListener()},showBluetoothSettings:function(){var r=e.defer();return n.bluetoothSerial.showBluetoothSettings(function(){r.resolve()},function(e){r.reject(e)}),r.promise},isEnabled:function(){var r=e.defer();return n.bluetoothSerial.isEnabled(function(){r.resolve()},function(){r.reject()}),r.promise},enable:function(){var r=e.defer();return n.bluetoothSerial.enable(function(){r.resolve()},function(){r.reject()}),r.promise},isConnected:function(){var r=e.defer();return n.bluetoothSerial.isConnected(function(){r.resolve()},function(){r.reject()}),r.promise},available:function(){var r=e.defer();return n.bluetoothSerial.available(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},read:function(){var r=e.defer();return n.bluetoothSerial.read(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},readUntil:function(r){var o=e.defer();return n.bluetoothSerial.readUntil(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},write:function(r){var o=e.defer();return n.bluetoothSerial.write(r,function(){o.resolve()},function(e){o.reject(e)}),o.promise},subscribe:function(r){var o=e.defer();return n.bluetoothSerial.subscribe(r,function(e){o.notify(e)},function(e){o.reject(e)}),o.promise},subscribeRawData:function(){var r=e.defer();return n.bluetoothSerial.subscribeRawData(function(e){r.notify(e)},function(e){r.reject(e)}),r.promise},unsubscribe:function(){var r=e.defer();return n.bluetoothSerial.unsubscribe(function(){r.resolve()},function(e){r.reject(e)}),r.promise},unsubscribeRawData:function(){var r=e.defer();return n.bluetoothSerial.unsubscribeRawData(function(){r.resolve()},function(e){r.reject(e)}),r.promise},clear:function(){var r=e.defer();return n.bluetoothSerial.clear(function(){r.resolve()},function(e){r.reject(e)}),r.promise},readRSSI:function(){var r=e.defer();return n.bluetoothSerial.readRSSI(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.brightness",[]).factory("$cordovaBrightness",["$q","$window",function(e,n){return{get:function(){var r=e.defer();return n.cordova?n.cordova.plugins.brightness.getBrightness(function(e){r.resolve(e)},function(e){r.reject(e)}):r.reject("Not supported without cordova.js"),r.promise},set:function(r){var o=e.defer();return n.cordova?n.cordova.plugins.brightness.setBrightness(r,function(e){o.resolve(e)},function(e){o.reject(e)}):o.reject("Not supported without cordova.js"),o.promise},setKeepScreenOn:function(r){var o=e.defer();return n.cordova?n.cordova.plugins.brightness.setKeepScreenOn(r,function(e){o.resolve(e)},function(e){o.reject(e)}):o.reject("Not supported without cordova.js"),o.promise}}}]),angular.module("ngCordova.plugins.calendar",[]).factory("$cordovaCalendar",["$q","$window",function(e,n){return{createCalendar:function(r){var o=e.defer(),t=n.plugins.calendar.getCreateCalendarOptions();return"string"==typeof r?t.calendarName=r:t=angular.extend(t,r),n.plugins.calendar.createCalendar(t,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},deleteCalendar:function(r){var o=e.defer();return n.plugins.calendar.deleteCalendar(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.createEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventWithOptions:function(r){var o=e.defer(),t=[],i=window.plugins.calendar.getCalendarOptions(),a={title:null,location:null,notes:null,startDate:null,endDate:null};t=Object.keys(a);for(var c in r)-1===t.indexOf(c)?i[c]=r[c]:a[c]=r[c];return n.plugins.calendar.createEventWithOptions(a.title,a.location,a.notes,new Date(a.startDate),new Date(a.endDate),i,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventInteractively:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.createEventInteractively(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},createEventInNamedCalendar:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null,calendarName:null};return t=angular.extend(t,r),n.plugins.calendar.createEventInNamedCalendar(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),t.calendarName,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},findEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.findEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},listEventsInRange:function(r,o){var t=e.defer();return n.plugins.calendar.listEventsInRange(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},listCalendars:function(){var r=e.defer();return n.plugins.calendar.listCalendars(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},findAllEventsInNamedCalendar:function(r){var o=e.defer();return n.plugins.calendar.findAllEventsInNamedCalendar(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},modifyEvent:function(r){var o=e.defer(),t={title:null,location:null,notes:null,startDate:null,endDate:null,newTitle:null,newLocation:null,newNotes:null,newStartDate:null,newEndDate:null};return t=angular.extend(t,r),n.plugins.calendar.modifyEvent(t.title,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),t.newTitle,t.newLocation,t.newNotes,new Date(t.newStartDate),new Date(t.newEndDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},deleteEvent:function(r){var o=e.defer(),t={newTitle:null,location:null,notes:null,startDate:null,endDate:null};return t=angular.extend(t,r),n.plugins.calendar.deleteEvent(t.newTitle,t.location,t.notes,new Date(t.startDate),new Date(t.endDate),function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.camera",[]).factory("$cordovaCamera",["$q",function(e){return{getPicture:function(n){var r=e.defer();return navigator.camera?(navigator.camera.getPicture(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},cleanup:function(){var n=e.defer();return navigator.camera.cleanup(function(){n.resolve()},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.capture",[]).factory("$cordovaCapture",["$q",function(e){return{captureAudio:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureAudio(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},captureImage:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureImage(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)},captureVideo:function(n){var r=e.defer();return navigator.device.capture?(navigator.device.capture.captureVideo(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise):(r.resolve(null),r.promise)}}}]),angular.module("ngCordova.plugins.cardIO",[]).provider("$cordovaNgCardIO",[function(){var e=["card_type","redacted_card_number","card_number","expiry_month","expiry_year","short_expiry_year","cvv","zip"],n={expiry:!0,cvv:!0,zip:!1,suppressManual:!1,suppressConfirm:!1,hideLogo:!0};this.setCardIOResponseFields=function(n){n&&angular.isArray(n)&&(e=n)},this.setScanerConfig=function(e){e&&angular.isObject(e)&&(n.expiry=e.expiry||!0,n.cvv=e.cvv||!0,n.zip=e.zip||!1,n.suppressManual=e.suppressManual||!1,n.suppressConfirm=e.suppressConfirm||!1,n.hideLogo=e.hideLogo||!0)},this.$get=["$q",function(r){return{scanCard:function(){var o=r.defer();return CardIO.scan(n,function(n){if(null===n)o.reject(null);else{for(var r={},t=0,i=e.length;i>t;t++){var a=e[t];"short_expiry_year"===a?r[a]=String(n.expiry_year).substr(2,2)||"":r[a]=n[a]||""}o.resolve(r)}},function(){o.reject(null)}),o.promise}}}]}]),angular.module("ngCordova.plugins.clipboard",[]).factory("$cordovaClipboard",["$q","$window",function(e,n){return{copy:function(r){var o=e.defer();return n.cordova.plugins.clipboard.copy(r,function(){o.resolve()},function(){o.reject()}),o.promise},paste:function(){var r=e.defer();return n.cordova.plugins.clipboard.paste(function(e){r.resolve(e)},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.contacts",[]).factory("$cordovaContacts",["$q",function(e){return{save:function(n){var r=e.defer(),o=navigator.contacts.create(n);return o.save(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},remove:function(n){var r=e.defer(),o=navigator.contacts.create(n);return o.remove(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},clone:function(e){var n=navigator.contacts.create(e);return n.clone(e)},find:function(n){var r=e.defer(),o=n.fields||["id","displayName"];return delete n.fields,0===Object.keys(n).length?navigator.contacts.find(o,function(e){r.resolve(e)},function(e){r.reject(e)}):navigator.contacts.find(o,function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},pickContact:function(){var n=e.defer();return navigator.contacts.pickContact(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.datePicker",[]).factory("$cordovaDatePicker",["$window","$q",function(e,n){return{show:function(r){var o=n.defer();return r=r||{date:new Date,mode:"date"},e.datePicker.show(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.device",[]).factory("$cordovaDevice",[function(){return{getDevice:function(){return device},getCordova:function(){return device.cordova},getModel:function(){return device.model},getName:function(){return device.name},getPlatform:function(){return device.platform},getUUID:function(){return device.uuid},getVersion:function(){return device.version},getManufacturer:function(){return device.manufacturer}}}]),angular.module("ngCordova.plugins.deviceMotion",[]).factory("$cordovaDeviceMotion",["$q",function(e){return{getCurrentAcceleration:function(){var n=e.defer();return angular.isUndefined(navigator.accelerometer)||!angular.isFunction(navigator.accelerometer.getCurrentAcceleration)?(n.reject("Device do not support watchAcceleration"),n.promise):(navigator.accelerometer.getCurrentAcceleration(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise)},watchAcceleration:function(n){var r=e.defer();if(angular.isUndefined(navigator.accelerometer)||!angular.isFunction(navigator.accelerometer.watchAcceleration))return r.reject("Device do not support watchAcceleration"),r.promise;var o=navigator.accelerometer.watchAcceleration(function(e){r.notify(e)},function(e){r.reject(e)},n);return r.promise.cancel=function(){navigator.accelerometer.clearWatch(o)},r.promise.clearWatch=function(e){navigator.accelerometer.clearWatch(e||o)},r.promise.watchID=o,r.promise},clearWatch:function(e){return navigator.accelerometer.clearWatch(e)}}}]),angular.module("ngCordova.plugins.deviceOrientation",[]).factory("$cordovaDeviceOrientation",["$q",function(e){var n={frequency:3e3};return{getCurrentHeading:function(){var n=e.defer();return navigator.compass?(navigator.compass.getCurrentHeading(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise):(n.reject("No compass on Device"),n.promise)},watchHeading:function(r){var o=e.defer();if(!navigator.compass)return o.reject("No compass on Device"),o.promise;var t=angular.extend(n,r),i=navigator.compass.watchHeading(function(e){o.notify(e)},function(e){o.reject(e)},t);return o.promise.cancel=function(){navigator.compass.clearWatch(i)},o.promise.clearWatch=function(e){navigator.compass.clearWatch(e||i)},o.promise.watchID=i,o.promise},clearWatch:function(e){return navigator.compass.clearWatch(e)}}}]),angular.module("ngCordova.plugins.dialogs",[]).factory("$cordovaDialogs",["$q","$window",function(e,n){return{alert:function(r,o,t){var i=e.defer();return n.navigator.notification?navigator.notification.alert(r,function(){i.resolve()},o,t):(n.alert(r),i.resolve()),i.promise},confirm:function(r,o,t){var i=e.defer();return n.navigator.notification?navigator.notification.confirm(r,function(e){i.resolve(e)},o,t):n.confirm(r)?i.resolve(1):i.resolve(2),i.promise},prompt:function(r,o,t,i){var a=e.defer();if(n.navigator.notification)navigator.notification.prompt(r,function(e){a.resolve(e)},o,t,i);else{var c=n.prompt(r,i);null!==c?a.resolve({input1:c,buttonIndex:1}):a.resolve({input1:c,buttonIndex:2})}return a.promise},beep:function(e){return navigator.notification.beep(e)},activityStart:function(n,r){var o=e.defer();return"android"===cordova.platformId?(navigator.notification.activityStart(r,n),o.resolve()):o.reject(n,r),o.promise},activityStop:function(){var n=e.defer();return"android"===cordova.platformId?(navigator.notification.activityStop(),n.resolve()):n.reject(),n.promise},progressStart:function(n,r){var o=e.defer();return"android"===cordova.platformId?(navigator.notification.progressStart(r,n),o.resolve()):o.reject(n,r),o.promise},progressStop:function(){var n=e.defer();return"android"===cordova.platformId?(navigator.notification.progressStop(),n.resolve()):n.reject(),n.promise},progressValue:function(n){var r=e.defer();return"android"===cordova.platformId?(navigator.notification.progressValue(n),r.resolve()):r.reject(n),r.promise}}}]),angular.module("ngCordova.plugins.emailComposer",[]).factory("$cordovaEmailComposer",["$q",function(e){return{isAvailable:function(){var n=e.defer();return cordova.plugins.email.isAvailable(function(e){e?n.resolve():n.reject()}),n.promise},open:function(n){var r=e.defer();return cordova.plugins.email.open(n,function(){r.reject()}),r.promise},addAlias:function(e,n){cordova.plugins.email.addAlias(e,n)}}}]),angular.module("ngCordova.plugins.facebook",[]).provider("$cordovaFacebook",[function(){this.browserInit=function(e,n){this.appID=e,this.appVersion=n||"v2.0",facebookConnectPlugin.browserInit(this.appID,this.appVersion)},this.$get=["$q",function(e){return{login:function(n){var r=e.defer();return facebookConnectPlugin.login(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},showDialog:function(n){var r=e.defer();return facebookConnectPlugin.showDialog(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},api:function(n,r){var o=e.defer();return facebookConnectPlugin.api(n,r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},getAccessToken:function(){var n=e.defer();return facebookConnectPlugin.getAccessToken(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getLoginStatus:function(){var n=e.defer();return facebookConnectPlugin.getLoginStatus(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},logout:function(){var n=e.defer();return facebookConnectPlugin.logout(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]}]),angular.module("ngCordova.plugins.facebookAds",[]).factory("$cordovaFacebookAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.FacebookAds.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.FacebookAds.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.FacebookAds.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.FacebookAds.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.FacebookAds.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.FacebookAds.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.FacebookAds.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.FacebookAds.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.file",[]).constant("$cordovaFileError",{1:"NOT_FOUND_ERR",2:"SECURITY_ERR",3:"ABORT_ERR",4:"NOT_READABLE_ERR",5:"ENCODING_ERR",6:"NO_MODIFICATION_ALLOWED_ERR",7:"INVALID_STATE_ERR",8:"SYNTAX_ERR",9:"INVALID_MODIFICATION_ERR",10:"QUOTA_EXCEEDED_ERR",11:"TYPE_MISMATCH_ERR",12:"PATH_EXISTS_ERR"}).provider("$cordovaFile",[function(){this.$get=["$q","$window","$cordovaFileError",function(e,n,r){return{getFreeDiskSpace:function(){var n=e.defer();return cordova.exec(function(e){n.resolve(e)},function(e){n.reject(e)},"File","getFreeDiskSpace",[]),n.promise},checkDir:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.isDirectory===!0?i.resolve(e):i.reject({code:13,message:"input is not a directory"})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise},checkFile:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.isFile===!0?i.resolve(e):i.reject({code:13,message:"input is not a file"})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise},createDir:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("directory cannot start with /"), +i=i?!1:!0;var c={create:!0,exclusive:i};try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,c,function(e){a.resolve(e)},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(u){u.message=r[u.code],a.reject(u)}return a.promise},createFile:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("file-name cannot start with /"),i=i?!1:!0;var c={create:!0,exclusive:i};try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,c,function(e){a.resolve(e)},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(u){u.message=r[u.code],a.reject(u)}return a.promise},removeDir:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1},function(e){e.remove(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},removeFile:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.remove(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},removeRecursively:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1},function(e){e.removeRecursively(function(){i.resolve({success:!0,fileRemoved:e})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},writeFile:function(o,t,i,a){var c=e.defer();/^\//.test(t)&&c.reject("file-name cannot start with /"),a=a?!1:!0;var u={create:!0,exclusive:a};try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,u,function(e){e.createWriter(function(e){u.append===!0&&e.seek(e.length),u.truncate&&e.truncate(u.truncate),e.onwriteend=function(e){this.error?c.reject(this.error):c.resolve(e)},e.write(i),c.promise.abort=function(){e.abort()}})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(s){s.message=r[s.code],c.reject(s)}return c.promise},writeExistingFile:function(o,t,i){var a=e.defer();/^\//.test(t)&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.createWriter(function(e){e.seek(e.length),e.onwriteend=function(e){this.error?a.reject(this.error):a.resolve(e)},e.write(i),a.promise.abort=function(){e.abort()}})},function(e){e.message=r[e.code],a.reject(e)})},function(e){e.message=r[e.code],a.reject(e)})}catch(c){c.message=r[c.code],a.reject(c)}return a.promise},readAsText:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsText(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsDataURL:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsDataURL(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsBinaryString:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsBinaryString(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},readAsArrayBuffer:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1},function(e){e.file(function(e){var n=new FileReader;n.onloadend=function(e){void 0!==e.target.result||null!==e.target.result?i.resolve(e.target.result):void 0!==e.target.error||null!==e.target.error?i.reject(e.target.error):i.reject({code:null,message:"READER_ONLOADEND_ERR"})},n.readAsArrayBuffer(e)})},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(a){a.message=r[a.code],i.reject(a)}return i.promise},moveFile:function(r,o,t,i){var a=e.defer();i=i||o,(/^\//.test(o)||/^\//.test(i))&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(r,function(e){e.getFile(o,{create:!1},function(e){n.resolveLocalFileSystemURL(t,function(n){e.moveTo(n,i,function(e){a.resolve(e)},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})}catch(c){a.reject(c)}return a.promise},moveDir:function(r,o,t,i){var a=e.defer();i=i||o,(/^\//.test(o)||/^\//.test(i))&&a.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(r,function(e){e.getDirectory(o,{create:!1},function(e){n.resolveLocalFileSystemURL(t,function(n){e.moveTo(n,i,function(e){a.resolve(e)},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})},function(e){a.reject(e)})}catch(c){a.reject(c)}return a.promise},copyDir:function(o,t,i,a){var c=e.defer();a=a||t,(/^\//.test(t)||/^\//.test(a))&&c.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getDirectory(t,{create:!1,exclusive:!1},function(e){n.resolveLocalFileSystemURL(i,function(n){e.copyTo(n,a,function(e){c.resolve(e)},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(u){u.message=r[u.code],c.reject(u)}return c.promise},copyFile:function(o,t,i,a){var c=e.defer();a=a||t,/^\//.test(t)&&c.reject("file-name cannot start with /");try{n.resolveLocalFileSystemURL(o,function(e){e.getFile(t,{create:!1,exclusive:!1},function(e){n.resolveLocalFileSystemURL(i,function(n){e.copyTo(n,a,function(e){c.resolve(e)},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})},function(e){e.message=r[e.code],c.reject(e)})}catch(u){u.message=r[u.code],c.reject(u)}return c.promise},readFileMetadata:function(o,t){var i=e.defer();/^\//.test(t)&&i.reject("directory cannot start with /");try{var a=o+t;n.resolveLocalFileSystemURL(a,function(e){e.file(function(e){i.resolve(e)},function(e){e.message=r[e.code],i.reject(e)})},function(e){e.message=r[e.code],i.reject(e)})}catch(c){c.message=r[c.code],i.reject(c)}return i.promise}}}]}]),angular.module("ngCordova.plugins.fileOpener2",[]).factory("$cordovaFileOpener2",["$q",function(e){return{open:function(n,r){var o=e.defer();return cordova.plugins.fileOpener2.open(n,r,{error:function(e){o.reject(e)},success:function(){o.resolve()}}),o.promise},uninstall:function(n){var r=e.defer();return cordova.plugins.fileOpener2.uninstall(n,{error:function(e){r.reject(e)},success:function(){r.resolve()}}),r.promise},appIsInstalled:function(n){var r=e.defer();return cordova.plugins.fileOpener2.appIsInstalled(n,{success:function(e){r.resolve(e)}}),r.promise}}}]),angular.module("ngCordova.plugins.fileTransfer",[]).factory("$cordovaFileTransfer",["$q","$timeout",function(e,n){return{download:function(r,o,t,i){var a=e.defer(),c=new FileTransfer,u=t&&t.encodeURI===!1?r:encodeURI(r);return t&&void 0!==t.timeout&&null!==t.timeout&&(n(function(){c.abort()},t.timeout),t.timeout=null),c.onprogress=function(e){a.notify(e)},a.promise.abort=function(){c.abort()},c.download(u,o,a.resolve,a.reject,i,t),a.promise},upload:function(r,o,t,i){var a=e.defer(),c=new FileTransfer,u=t&&t.encodeURI===!1?r:encodeURI(r);return t&&void 0!==t.timeout&&null!==t.timeout&&(n(function(){c.abort()},t.timeout),t.timeout=null),c.onprogress=function(e){a.notify(e)},a.promise.abort=function(){c.abort()},c.upload(o,u,a.resolve,a.reject,t,i),a.promise}}}]),angular.module("ngCordova.plugins.flashlight",[]).factory("$cordovaFlashlight",["$q","$window",function(e,n){return{available:function(){var r=e.defer();return n.plugins.flashlight.available(function(e){r.resolve(e)}),r.promise},switchOn:function(){var r=e.defer();return n.plugins.flashlight.switchOn(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},switchOff:function(){var r=e.defer();return n.plugins.flashlight.switchOff(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},toggle:function(){var r=e.defer();return n.plugins.flashlight.toggle(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.flurryAds",[]).factory("$cordovaFlurryAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.FlurryAds.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.FlurryAds.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.FlurryAds.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.FlurryAds.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.FlurryAds.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.FlurryAds.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.FlurryAds.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.FlurryAds.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.ga",[]).factory("$cordovaGA",["$q","$window",function(e,n){return{init:function(r,o){var t=e.defer();return o=o>=0?o:10,n.plugins.gaPlugin.init(function(e){t.resolve(e)},function(e){t.reject(e)},r,o),t.promise},trackEvent:function(r,o,t,i,a,c){var u=e.defer();return n.plugins.gaPlugin.trackEvent(function(e){u.resolve(e)},function(e){u.reject(e)},t,i,a,c),u.promise},trackPage:function(r,o,t){var i=e.defer();return n.plugins.gaPlugin.trackPage(function(e){i.resolve(e)},function(e){i.reject(e)},t),i.promise},setVariable:function(r,o,t,i){var a=e.defer();return n.plugins.gaPlugin.setVariable(function(e){a.resolve(e)},function(e){a.reject(e)},t,i),a.promise},exit:function(){var r=e.defer();return n.plugins.gaPlugin.exit(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.geolocation",[]).factory("$cordovaGeolocation",["$q",function(e){return{getCurrentPosition:function(n){var r=e.defer();return navigator.geolocation.getCurrentPosition(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},watchPosition:function(n){var r=e.defer(),o=navigator.geolocation.watchPosition(function(e){r.notify(e)},function(e){r.reject(e)},n);return r.promise.cancel=function(){navigator.geolocation.clearWatch(o)},r.promise.clearWatch=function(e){navigator.geolocation.clearWatch(e||o)},r.promise.watchID=o,r.promise},clearWatch:function(e){return navigator.geolocation.clearWatch(e)}}}]),angular.module("ngCordova.plugins.globalization",[]).factory("$cordovaGlobalization",["$q",function(e){return{getPreferredLanguage:function(){var n=e.defer();return navigator.globalization.getPreferredLanguage(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getLocaleName:function(){var n=e.defer();return navigator.globalization.getLocaleName(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getFirstDayOfWeek:function(){var n=e.defer();return navigator.globalization.getFirstDayOfWeek(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},dateToString:function(n,r){var o=e.defer();return navigator.globalization.dateToString(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},stringToDate:function(n,r){var o=e.defer();return navigator.globalization.stringToDate(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},getDatePattern:function(n){var r=e.defer();return navigator.globalization.getDatePattern(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},getDateNames:function(n){var r=e.defer();return navigator.globalization.getDateNames(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},isDayLightSavingsTime:function(n){var r=e.defer();return navigator.globalization.isDayLightSavingsTime(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},numberToString:function(n,r){var o=e.defer();return navigator.globalization.numberToString(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},stringToNumber:function(n,r){var o=e.defer();return navigator.globalization.stringToNumber(n,function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},getNumberPattern:function(n){var r=e.defer();return navigator.globalization.getNumberPattern(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},getCurrencyPattern:function(n){var r=e.defer();return navigator.globalization.getCurrencyPattern(n,function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.googleAds",[]).factory("$cordovaGoogleAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.AdMob.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.AdMob.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.AdMob.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.AdMob.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.AdMob.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.AdMob.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.AdMob.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.AdMob.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.googleAnalytics",[]).factory("$cordovaGoogleAnalytics",["$q","$window",function(e,n){return{startTrackerWithId:function(r){var o=e.defer();return n.analytics.startTrackerWithId(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},setUserId:function(r){var o=e.defer();return n.analytics.setUserId(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},debugMode:function(){var r=e.defer();return n.analytics.debugMode(function(e){r.resolve(e)},function(){r.reject()}),r.promise},trackView:function(r){var o=e.defer();return n.analytics.trackView(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},addCustomDimension:function(r,o){var t=e.defer();return n.analytics.addCustomDimension(r,o,function(){t.resolve()},function(e){t.reject(e)}),t.promise},trackEvent:function(r,o,t,i){var a=e.defer();return n.analytics.trackEvent(r,o,t,i,function(e){a.resolve(e)},function(e){a.reject(e)}),a.promise},trackException:function(r,o){var t=e.defer();return n.analytics.trackException(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},trackTiming:function(r,o,t,i){var a=e.defer();return n.analytics.trackTiming(r,o,t,i,function(e){a.resolve(e)},function(e){a.reject(e)}),a.promise},addTransaction:function(r,o,t,i,a,c){var u=e.defer();return n.analytics.addTransaction(r,o,t,i,a,c,function(e){u.resolve(e)},function(e){u.reject(e)}),u.promise},addTransactionItem:function(r,o,t,i,a,c,u){var s=e.defer();return n.analytics.addTransactionItem(r,o,t,i,a,c,u,function(e){s.resolve(e)},function(e){s.reject(e)}),s.promise}}}]),angular.module("ngCordova.plugins.googleMap",[]).factory("$cordovaGoogleMap",["$q","$window",function(e,n){var r=null;return{getMap:function(o){var t=e.defer();if(n.plugin.google.maps){var i=document.getElementById("map_canvas");r=n.plugin.google.maps.Map.getMap(o),r.setDiv(i),t.resolve(r)}else t.reject(null);return t.promise},isMapLoaded:function(){return!!r},addMarker:function(n){var o=e.defer();return r.addMarker(n,function(e){o.resolve(e)}),o.promise},getMapTypeIds:function(){return n.plugin.google.maps.mapTypeId},setVisible:function(n){var o=e.defer();return r.setVisible(n),o.promise},cleanup:function(){r=null}}}]),angular.module("ngCordova.plugins.googlePlayGame",[]).factory("$cordovaGooglePlayGame",["$q",function(e){return{auth:function(){var n=e.defer();return googleplaygame.auth(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},signout:function(){var n=e.defer();return googleplaygame.signout(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},isSignedIn:function(){var n=e.defer();return googleplaygame.isSignedIn(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},showPlayer:function(){var n=e.defer();return googleplaygame.showPlayer(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},submitScore:function(n){var r=e.defer();return googleplaygame.submitScore(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},showAllLeaderboards:function(){var n=e.defer();return googleplaygame.showAllLeaderboards(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise},showLeaderboard:function(n){var r=e.defer();return googleplaygame.showLeaderboard(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},unlockAchievement:function(n){var r=e.defer();return googleplaygame.unlockAchievement(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},incrementAchievement:function(n){var r=e.defer();return googleplaygame.incrementAchievement(n,function(e){return r.resolve(e)},function(e){return r.reject(e)}),r.promise},showAchievements:function(){var n=e.defer();return googleplaygame.showAchievements(function(e){return n.resolve(e)},function(e){return n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.googlePlus",[]).factory("$cordovaGooglePlus",["$q","$window",function(e,n){return{login:function(r){var o=e.defer();return void 0===r&&(r={}),n.plugins.googleplus.login({iOSApiKey:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},silentLogin:function(r){var o=e.defer();return void 0===r&&(r={}),n.plugins.googleplus.trySilentLogin({iOSApiKey:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},logout:function(){var r=e.defer();n.plugins.googleplus.logout(function(e){r.resolve(e)})},disconnect:function(){var r=e.defer();n.plugins.googleplus.disconnect(function(e){r.resolve(e)})},isAvailable:function(){var r=e.defer();return n.plugins.googleplus.isAvailable(function(e){e?r.resolve(e):r.reject(e)}),r.promise}}}]),angular.module("ngCordova.plugins.healthKit",[]).factory("$cordovaHealthKit",["$q","$window",function(e,n){return{isAvailable:function(){var r=e.defer();return n.plugins.healthkit.available(function(e){r.resolve(e)},function(e){r.reject(e)}),r.promise},checkAuthStatus:function(r){var o=e.defer();return r=r||"HKQuantityTypeIdentifierHeight",n.plugins.healthkit.checkAuthStatus({type:r},function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},requestAuthorization:function(r,o){var t=e.defer();return r=r||["HKCharacteristicTypeIdentifierDateOfBirth","HKQuantityTypeIdentifierActiveEnergyBurned","HKQuantityTypeIdentifierHeight"],o=o||["HKQuantityTypeIdentifierActiveEnergyBurned","HKQuantityTypeIdentifierHeight","HKQuantityTypeIdentifierDistanceCycling"],n.plugins.healthkit.requestAuthorization({readTypes:r,writeTypes:o},function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},readDateOfBirth:function(){var r=e.defer();return n.plugins.healthkit.readDateOfBirth(function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},readGender:function(){var r=e.defer();return n.plugins.healthkit.readGender(function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},saveWeight:function(r,o,t){var i=e.defer();return n.plugins.healthkit.saveWeight({unit:o||"lb",amount:r,date:t||new Date},function(e){i.resolve(e)},function(e){i.resolve(e)}),i.promise},readWeight:function(r){var o=e.defer();return n.plugins.healthkit.readWeight({unit:r||"lb"},function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},saveHeight:function(r,o,t){var i=e.defer();return n.plugins.healthkit.saveHeight({unit:o||"in",amount:r,date:t||new Date},function(e){i.resolve(e)},function(e){i.resolve(e)}),i.promise},readHeight:function(r){var o=e.defer();return n.plugins.healthkit.readHeight({unit:r||"in"},function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},findWorkouts:function(){var r=e.defer();return n.plugins.healthkit.findWorkouts({},function(e){r.resolve(e)},function(e){r.resolve(e)}),r.promise},saveWorkout:function(r){var o=e.defer();return n.plugins.healthkit.saveWorkout(r,function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise},querySampleType:function(r){var o=e.defer();return n.plugins.healthkit.querySampleType(r,function(e){o.resolve(e)},function(e){o.resolve(e)}),o.promise}}}]),angular.module("ngCordova.plugins.httpd",[]).factory("$cordovaHttpd",["$q",function(e){return{startServer:function(n){var r=e.defer();return cordova.plugins.CorHttpd.startServer(n,function(){r.resolve()},function(){r.reject()}),r.promise},stopServer:function(){var n=e.defer();return cordova.plugins.CorHttpd.stopServer(function(){n.resolve()},function(){n.reject()}),n.promise},getURL:function(){var n=e.defer();return cordova.plugins.CorHttpd.getURL(function(e){n.resolve(e)},function(){n.reject()}),n.promise},getLocalPath:function(){var n=e.defer();return cordova.plugins.CorHttpd.getLocalPath(function(e){n.resolve(e)},function(){n.reject()}),n.promise}}}]),angular.module("ngCordova.plugins.iAd",[]).factory("$cordovaiAd",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.iAd.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.iAd.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.iAd.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.iAd.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.iAd.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.iAd.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.iAd.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.iAd.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.imagePicker",[]).factory("$cordovaImagePicker",["$q","$window",function(e,n){return{getPictures:function(r){var o=e.defer();return n.imagePicker.getPictures(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise}}}]),angular.module("ngCordova.plugins.inAppBrowser",[]).provider("$cordovaInAppBrowser",[function(){var e,n=this.defaultOptions={};this.setDefaultOptions=function(e){n=angular.extend(n,e)},this.$get=["$rootScope","$q","$window","$timeout",function(r,o,t,i){return{open:function(a,c,u){var s=o.defer();if(u&&!angular.isObject(u))return s.reject("options must be an object"),s.promise;var l=angular.extend({},n,u),f=[];angular.forEach(l,function(e,n){f.push(n+"="+e)});var d=f.join();return e=t.open(a,c,d),e.addEventListener("loadstart",function(e){i(function(){r.$broadcast("$cordovaInAppBrowser:loadstart",e)})},!1),e.addEventListener("loadstop",function(e){s.resolve(e),i(function(){r.$broadcast("$cordovaInAppBrowser:loadstop",e)})},!1),e.addEventListener("loaderror",function(e){s.reject(e),i(function(){r.$broadcast("$cordovaInAppBrowser:loaderror",e)})},!1),e.addEventListener("exit",function(e){i(function(){r.$broadcast("$cordovaInAppBrowser:exit",e)})},!1),s.promise},close:function(){e.close(),e=null},show:function(){e.show()},executeScript:function(n){var r=o.defer();return e.executeScript(n,function(e){r.resolve(e)}),r.promise},insertCSS:function(n){var r=o.defer();return e.insertCSS(n,function(e){r.resolve(e)}),r.promise}}}]}]),angular.module("ngCordova.plugins.insomnia",[]).factory("$cordovaInsomnia",["$window",function(e){return{keepAwake:function(){return e.plugins.insomnia.keepAwake()},allowSleepAgain:function(){return e.plugins.insomnia.allowSleepAgain()}}}]),angular.module("ngCordova.plugins.instagram",[]).factory("$cordovaInstagram",["$q",function(e){return{share:function(n){var r=e.defer();return window.Instagram?(Instagram.share(n.image,n.caption,function(e){e?r.reject(e):r.resolve(!0)}),r.promise):(console.error("Tried to call Instagram.share but the Instagram plugin isn't installed!"),r.resolve(null),r.promise)},isInstalled:function(){var n=e.defer();return window.Instagram?(Instagram.isInstalled(function(e,r){e?n.reject(e):n.resolve(r)}),n.promise):(console.error("Tried to call Instagram.isInstalled but the Instagram plugin isn't installed!"),n.resolve(null),n.promise)}}}]),angular.module("ngCordova.plugins.keyboard",[]).factory("$cordovaKeyboard",["$rootScope",function(e){var n=function(){e.$evalAsync(function(){e.$broadcast("$cordovaKeyboard:show")})},r=function(){e.$evalAsync(function(){e.$broadcast("$cordovaKeyboard:hide")})};return document.addEventListener("deviceready",function(){cordova.plugins.Keyboard&&(window.addEventListener("native.keyboardshow",n,!1),window.addEventListener("native.keyboardhide",r,!1))}),{hideAccessoryBar:function(e){return cordova.plugins.Keyboard.hideKeyboardAccessoryBar(e)},close:function(){return cordova.plugins.Keyboard.close()},show:function(){return cordova.plugins.Keyboard.show()},disableScroll:function(e){return cordova.plugins.Keyboard.disableScroll(e)},isVisible:function(){return cordova.plugins.Keyboard.isVisible},clearShowWatch:function(){document.removeEventListener("native.keyboardshow",n),e.$$listeners["$cordovaKeyboard:show"]=[]},clearHideWatch:function(){document.removeEventListener("native.keyboardhide",r),e.$$listeners["$cordovaKeyboard:hide"]=[]}}}]),angular.module("ngCordova.plugins.keychain",[]).factory("$cordovaKeychain",["$q",function(e){return{getForKey:function(n,r){var o=e.defer(),t=new Keychain;return t.getForKey(o.resolve,o.reject,n,r),o.promise},setForKey:function(n,r,o){var t=e.defer(),i=new Keychain;return i.setForKey(t.resolve,t.reject,n,r,o),t.promise},removeForKey:function(n,r){var o=e.defer(),t=new Keychain;return t.removeForKey(o.resolve,o.reject,n,r),o.promise}}}]),angular.module("ngCordova.plugins.launchNavigator",[]).factory("$cordovaLaunchNavigator",["$q",function(e){return{navigate:function(n,r,o){var t=e.defer();return launchnavigator.navigate(n,r,function(){t.resolve()},function(e){t.reject(e)},o),t.promise}}}]),angular.module("ngCordova.plugins.localNotification",[]).factory("$cordovaLocalNotification",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return document.addEventListener("deviceready",function(){n.cordova&&n.cordova.plugins&&n.cordova.plugins.notification&&n.cordova.plugins.notification.local&&(n.cordova.plugins.notification.local.on("schedule",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:schedule",e,n)})}),n.cordova.plugins.notification.local.on("trigger",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:trigger",e,n)})}),n.cordova.plugins.notification.local.on("update",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:update",e,n)})}),n.cordova.plugins.notification.local.on("clear",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:clear",e,n)})}),n.cordova.plugins.notification.local.on("clearall",function(e){o(function(){r.$broadcast("$cordovaLocalNotification:clearall",e)})}),n.cordova.plugins.notification.local.on("cancel",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:cancel",e,n)})}),n.cordova.plugins.notification.local.on("cancelall",function(e){o(function(){r.$broadcast("$cordovaLocalNotification:cancelall",e)})}),n.cordova.plugins.notification.local.on("click",function(e,n){o(function(){r.$broadcast("$cordovaLocalNotification:click",e,n)})}))},!1),{schedule:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.schedule(r,function(e){t.resolve(e)},o),t.promise},add:function(r,o){console.warn('Deprecated: use "schedule" instead.');var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.schedule(r,function(e){t.resolve(e)},o),t.promise},update:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.update(r,function(e){t.resolve(e)},o),t.promise},clear:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.clear(r,function(e){t.resolve(e)},o),t.promise},clearAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.clearAll(function(e){o.resolve(e)},r),o.promise},cancel:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.cancel(r,function(e){t.resolve(e)},o),t.promise},cancelAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.cancelAll(function(e){o.resolve(e)},r),o.promise},isPresent:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isPresent(r,function(e){t.resolve(e)},o),t.promise},isScheduled:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isScheduled(r,function(e){t.resolve(e)},o),t.promise},isTriggered:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.isTriggered(r,function(e){t.resolve(e)},o),t.promise},hasPermission:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.hasPermission(function(e){e?o.resolve(e):o.reject(e)},r),o.promise},registerPermission:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.registerPermission(function(e){e?o.resolve(e):o.reject(e)},r),o.promise},promptForPermission:function(r){console.warn('Deprecated: use "registerPermission" instead.');var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.registerPermission(function(e){ +e?o.resolve(e):o.reject(e)},r),o.promise},getAllIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllIds(function(e){o.resolve(e)},r),o.promise},getIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getIds(function(e){o.resolve(e)},r),o.promise},getScheduledIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getScheduledIds(function(e){o.resolve(e)},r),o.promise},getTriggeredIds:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getTriggeredIds(function(e){o.resolve(e)},r),o.promise},get:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.get(r,function(e){t.resolve(e)},o),t.promise},getAll:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAll(function(e){o.resolve(e)},r),o.promise},getScheduled:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.getScheduled(r,function(e){t.resolve(e)},o),t.promise},getAllScheduled:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllScheduled(function(e){o.resolve(e)},r),o.promise},getTriggered:function(r,o){var t=e.defer();return o=o||null,n.cordova.plugins.notification.local.getTriggered(r,function(e){t.resolve(e)},o),t.promise},getAllTriggered:function(r){var o=e.defer();return r=r||null,n.cordova.plugins.notification.local.getAllTriggered(function(e){o.resolve(e)},r),o.promise},getDefaults:function(){return n.cordova.plugins.notification.local.getDefaults()},setDefaults:function(e){n.cordova.plugins.notification.local.setDefaults(e)}}}]),angular.module("ngCordova.plugins.mMediaAds",[]).factory("$cordovaMMediaAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.mMedia.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.mMedia.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.mMedia.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.mMedia.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.mMedia.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.mMedia.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.mMedia.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.mMedia.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.media",[]).service("NewMedia",["$q","$interval",function(e,n){function r(e){angular.isDefined(s)||(s=n(function(){0>d&&(d=e.getDuration(),a&&d>0&&a.notify({duration:d})),e.getCurrentPosition(function(e){e>-1&&(f=e)},function(e){console.log("Error getting pos="+e)}),a&&a.notify({position:f})},1e3))}function o(){angular.isDefined(s)&&(n.cancel(s),s=void 0)}function t(){f=-1,d=-1}function i(e){this.media=new Media(e,function(e){o(),t(),a.resolve(e)},function(e){o(),t(),a.reject(e)},function(e){l=e,a.notify({status:l})})}var a,c,u,s,l=null,f=-1,d=-1;return i.prototype.play=function(n){return a=e.defer(),"object"!=typeof n&&(n={}),this.media.play(n),r(this.media),a.promise},i.prototype.pause=function(){o(),this.media.pause()},i.prototype.stop=function(){this.media.stop()},i.prototype.release=function(){this.media.release(),this.media=void 0},i.prototype.seekTo=function(e){this.media.seekTo(e)},i.prototype.setVolume=function(e){this.media.setVolume(e)},i.prototype.startRecord=function(){this.media.startRecord()},i.prototype.stopRecord=function(){this.media.stopRecord()},i.prototype.currentTime=function(){return c=e.defer(),this.media.getCurrentPosition(function(e){c.resolve(e)}),c.promise},i.prototype.getDuration=function(){return u=e.defer(),this.media.getDuration(function(e){u.resolve(e)}),u.promise},i}]).factory("$cordovaMedia",["NewMedia",function(e){return{newMedia:function(n){return new e(n)}}}]),angular.module("ngCordova.plugins.mobfoxAds",[]).factory("$cordovaMobFoxAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.MobFox.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.MobFox.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.MobFox.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.MobFox.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.MobFox.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.MobFox.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.MobFox.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.MobFox.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins",["ngCordova.plugins.actionSheet","ngCordova.plugins.adMob","ngCordova.plugins.appAvailability","ngCordova.plugins.appRate","ngCordova.plugins.appVersion","ngCordova.plugins.backgroundGeolocation","ngCordova.plugins.badge","ngCordova.plugins.barcodeScanner","ngCordova.plugins.batteryStatus","ngCordova.plugins.beacon","ngCordova.plugins.ble","ngCordova.plugins.bluetoothSerial","ngCordova.plugins.brightness","ngCordova.plugins.calendar","ngCordova.plugins.camera","ngCordova.plugins.capture","ngCordova.plugins.clipboard","ngCordova.plugins.contacts","ngCordova.plugins.datePicker","ngCordova.plugins.device","ngCordova.plugins.deviceMotion","ngCordova.plugins.deviceOrientation","ngCordova.plugins.dialogs","ngCordova.plugins.emailComposer","ngCordova.plugins.facebook","ngCordova.plugins.facebookAds","ngCordova.plugins.file","ngCordova.plugins.fileTransfer","ngCordova.plugins.fileOpener2","ngCordova.plugins.flashlight","ngCordova.plugins.flurryAds","ngCordova.plugins.ga","ngCordova.plugins.geolocation","ngCordova.plugins.globalization","ngCordova.plugins.googleAds","ngCordova.plugins.googleAnalytics","ngCordova.plugins.googleMap","ngCordova.plugins.googlePlayGame","ngCordova.plugins.googlePlus","ngCordova.plugins.healthKit","ngCordova.plugins.httpd","ngCordova.plugins.iAd","ngCordova.plugins.imagePicker","ngCordova.plugins.inAppBrowser","ngCordova.plugins.instagram","ngCordova.plugins.keyboard","ngCordova.plugins.keychain","ngCordova.plugins.launchNavigator","ngCordova.plugins.localNotification","ngCordova.plugins.media","ngCordova.plugins.mMediaAds","ngCordova.plugins.mobfoxAds","ngCordova.plugins.mopubAds","ngCordova.plugins.nativeAudio","ngCordova.plugins.network","ngCordova.plugins.pinDialog","ngCordova.plugins.preferences","ngCordova.plugins.printer","ngCordova.plugins.progressIndicator","ngCordova.plugins.push","ngCordova.plugins.push_v5","ngCordova.plugins.sms","ngCordova.plugins.socialSharing","ngCordova.plugins.spinnerDialog","ngCordova.plugins.splashscreen","ngCordova.plugins.sqlite","ngCordova.plugins.statusbar","ngCordova.plugins.toast","ngCordova.plugins.touchid","ngCordova.plugins.vibration","ngCordova.plugins.videoCapturePlus","ngCordova.plugins.zip","ngCordova.plugins.insomnia"]),angular.module("ngCordova.plugins.mopubAds",[]).factory("$cordovaMoPubAds",["$q","$window",function(e,n){return{setOptions:function(r){var o=e.defer();return n.MoPub.setOptions(r,function(){o.resolve()},function(){o.reject()}),o.promise},createBanner:function(r){var o=e.defer();return n.MoPub.createBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},removeBanner:function(){var r=e.defer();return n.MoPub.removeBanner(function(){r.resolve()},function(){r.reject()}),r.promise},showBanner:function(r){var o=e.defer();return n.MoPub.showBanner(r,function(){o.resolve()},function(){o.reject()}),o.promise},showBannerAtXY:function(r,o){var t=e.defer();return n.MoPub.showBannerAtXY(r,o,function(){t.resolve()},function(){t.reject()}),t.promise},hideBanner:function(){var r=e.defer();return n.MoPub.hideBanner(function(){r.resolve()},function(){r.reject()}),r.promise},prepareInterstitial:function(r){var o=e.defer();return n.MoPub.prepareInterstitial(r,function(){o.resolve()},function(){o.reject()}),o.promise},showInterstitial:function(){var r=e.defer();return n.MoPub.showInterstitial(function(){r.resolve()},function(){r.reject()}),r.promise}}}]),angular.module("ngCordova.plugins.nativeAudio",[]).factory("$cordovaNativeAudio",["$q","$window",function(e,n){return{preloadSimple:function(r,o){var t=e.defer();return n.plugins.NativeAudio.preloadSimple(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise},preloadComplex:function(r,o,t,i,a){var c=e.defer();return n.plugins.NativeAudio.preloadComplex(r,o,t,i,a,function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise},play:function(r,o){var t=e.defer();return n.plugins.NativeAudio.play(r,function(e){t.resolve(e)},function(e){t.reject(e)},o),t.promise},stop:function(r){var o=e.defer();return n.plugins.NativeAudio.stop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},loop:function(r){var o=e.defer();return n.plugins.NativeAudio.loop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},unload:function(r){var o=e.defer();return n.plugins.NativeAudio.unload(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},setVolumeForComplexAsset:function(r,o){var t=e.defer();return n.plugins.NativeAudio.setVolumeForComplexAsset(r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise}}}]),angular.module("ngCordova.plugins.network",[]).factory("$cordovaNetwork",["$rootScope","$timeout",function(e,n){var r=function(){var r=navigator.connection.type;n(function(){e.$broadcast("$cordovaNetwork:offline",r)})},o=function(){var r=navigator.connection.type;n(function(){e.$broadcast("$cordovaNetwork:online",r)})};return document.addEventListener("deviceready",function(){navigator.connection&&(document.addEventListener("offline",r,!1),document.addEventListener("online",o,!1))}),{getNetwork:function(){return navigator.connection.type},isOnline:function(){var e=navigator.connection.type;return e!==Connection.UNKNOWN&&e!==Connection.NONE},isOffline:function(){var e=navigator.connection.type;return e===Connection.UNKNOWN||e===Connection.NONE},clearOfflineWatch:function(){document.removeEventListener("offline",r),e.$$listeners["$cordovaNetwork:offline"]=[]},clearOnlineWatch:function(){document.removeEventListener("online",o),e.$$listeners["$cordovaNetwork:online"]=[]}}}]).run(["$injector",function(e){e.get("$cordovaNetwork")}]),angular.module("ngCordova.plugins.pinDialog",[]).factory("$cordovaPinDialog",["$q","$window",function(e,n){return{prompt:function(r,o,t){var i=e.defer();return n.plugins.pinDialog.prompt(r,function(e){i.resolve(e)},o,t),i.promise}}}]),angular.module("ngCordova.plugins.preferences",[]).factory("$cordovaPreferences",["$window","$q",function(e,n){return{pluginNotEnabledMessage:"Plugin not enabled",decoratePromise:function(e){e.success=function(n){return e.then(n),e},e.error=function(n){return e.then(null,n),e}},store:function(r,o,t){function i(e){c.resolve(e)}function a(e){c.reject(new Error(e))}var c=n.defer(),u=c.promise;if(e.plugins){var s;s=3===arguments.length?e.plugins.appPreferences.store(t,r,o):e.plugins.appPreferences.store(r,o),s.then(i,a)}else c.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(u),u},fetch:function(r,o){function t(e){a.resolve(e)}function i(e){a.reject(new Error(e))}var a=n.defer(),c=a.promise;if(e.plugins){var u;u=2===arguments.length?e.plugins.appPreferences.fetch(o,r):e.plugins.appPreferences.fetch(r),u.then(t,i)}else a.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(c),c},remove:function(r,o){function t(e){a.resolve(e)}function i(e){a.reject(new Error(e))}var a=n.defer(),c=a.promise;if(e.plugins){var u;u=2===arguments.length?e.plugins.appPreferences.remove(o,r):e.plugins.appPreferences.remove(r),u.then(t,i)}else a.reject(new Error(this.pluginNotEnabledMessage));return this.decoratePromise(c),c},show:function(){function r(e){t.resolve(e)}function o(e){t.reject(new Error(e))}var t=n.defer(),i=t.promise;return e.plugins?e.plugins.appPreferences.show().then(r,o):t.reject(new Error(this.pluginNotEnabledMessage)),this.decoratePromise(i),i}}}]),angular.module("ngCordova.plugins.printer",[]).factory("$cordovaPrinter",["$q","$window",function(e,n){return{isAvailable:function(){var r=e.defer();return n.plugin.printer.isAvailable(function(e){r.resolve(e)}),r.promise},print:function(r,o){var t=e.defer();return n.plugin.printer.print(r,o,function(){t.resolve()}),t.promise}}}]),angular.module("ngCordova.plugins.progressIndicator",[]).factory("$cordovaProgress",[function(){return{show:function(e){var n=e||"Please wait...";return ProgressIndicator.show(n)},showSimple:function(e){var n=e||!1;return ProgressIndicator.showSimple(n)},showSimpleWithLabel:function(e,n){var r=e||!1,o=n||"Loading...";return ProgressIndicator.showSimpleWithLabel(r,o)},showSimpleWithLabelDetail:function(e,n,r){var o=e||!1,t=n||"Loading...",i=r||"Please wait";return ProgressIndicator.showSimpleWithLabelDetail(o,t,i)},showDeterminate:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showDeterminate(r,o)},showDeterminateWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showDeterminateWithLabel(o,t,i)},showAnnular:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showAnnular(r,o)},showAnnularWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showAnnularWithLabel(o,t,i)},showBar:function(e,n){var r=e||!1,o=n||5e4;return ProgressIndicator.showBar(r,o)},showBarWithLabel:function(e,n,r){var o=e||!1,t=n||5e4,i=r||"Loading...";return ProgressIndicator.showBarWithLabel(o,t,i)},showSuccess:function(e,n){var r=e||!1,o=n||"Success";return ProgressIndicator.showSuccess(r,o)},showText:function(e,n,r){var o=e||!1,t=n||"Warning",i=r||"center";return ProgressIndicator.showText(o,t,i)},hide:function(){return ProgressIndicator.hide()}}}]),angular.module("ngCordova.plugins.push",[]).factory("$cordovaPush",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return{onNotification:function(e){o(function(){r.$broadcast("$cordovaPush:notificationReceived",e)})},register:function(r){var o,t=e.defer();return void 0!==r&&void 0===r.ecb&&(o=null===document.querySelector("[ng-app]")?"document.body":"document.querySelector('[ng-app]')",r.ecb="angular.element("+o+").injector().get('$cordovaPush').onNotification"),n.plugins.pushNotification.register(function(e){t.resolve(e)},function(e){t.reject(e)},r),t.promise},unregister:function(r){var o=e.defer();return n.plugins.pushNotification.unregister(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise},setBadgeNumber:function(r){var o=e.defer();return n.plugins.pushNotification.setApplicationIconBadgeNumber(function(e){o.resolve(e)},function(e){o.reject(e)},r),o.promise}}}]),angular.module("ngCordova.plugins.push_v5",[]).factory("$cordovaPushV5",["$q","$rootScope","$timeout",function(e,n,r){var o;return{initialize:function(n){var r=e.defer();return o=PushNotification.init(n),r.resolve(o),r.promise},onNotification:function(){r(function(){o.on("notification",function(e){n.$emit("$cordovaPushV5:notificationReceived",e)})})},onError:function(){r(function(){o.on("error",function(e){n.$emit("$cordovaPushV5:errorOccurred",e)})})},register:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.on("registration",function(e){n.resolve(e.registrationId)}),n.promise},unregister:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.unregister(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},getBadgeNumber:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.getApplicationIconBadgeNumber(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise},setBadgeNumber:function(n){var r=e.defer();return void 0===o?r.reject(new Error("init must be called before any other operation")):o.setApplicationIconBadgeNumber(function(e){r.resolve(e)},function(e){r.reject(e)},n),r.promise},finish:function(){var n=e.defer();return void 0===o?n.reject(new Error("init must be called before any other operation")):o.finish(function(e){n.resolve(e)},function(e){n.reject(e)}),n.promise}}}]),angular.module("ngCordova.plugins.screenshot",[]).factory("$cordovaScreenshot",["$q",function(e){return{captureToFile:function(n){var r=n||{},o=r.extension||"jpg",t=r.quality||"100",i=e.defer();return navigator.screenshot?(navigator.screenshot.save(function(e,n){e?i.reject(e):i.resolve(n.filePath)},o,t,r.filename),i.promise):(i.resolve(null),i.promise)},captureToUri:function(n){var r=n||{},o=r.extension||"jpg",t=r.quality||"100",i=e.defer();return navigator.screenshot?(navigator.screenshot.URI(function(e,n){e?i.reject(e):i.resolve(n.URI)},o,t,r.filename),i.promise):(i.resolve(null),i.promise)}}}]),angular.module("ngCordova.plugins.sms",[]).factory("$cordovaSms",["$q",function(e){return{send:function(n,r,o){var t=e.defer();return sms.send(n,r,o,function(e){t.resolve(e)},function(e){t.reject(e)}),t.promise}}}]),angular.module("ngCordova.plugins.socialSharing",[]).factory("$cordovaSocialSharing",["$q","$window",function(e,n){return{share:function(r,o,t,i){var a=e.defer();return o=o||null,t=t||null,i=i||null,n.plugins.socialsharing.share(r,o,t,i,function(){a.resolve(!0)},function(){a.reject(!1)}),a.promise},shareViaTwitter:function(r,o,t){var i=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaTwitter(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaWhatsApp:function(r,o,t){var i=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaWhatsApp(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaFacebook:function(r,o,t){var i=e.defer();return r=r||null,o=o||null,t=t||null,n.plugins.socialsharing.shareViaFacebook(r,o,t,function(){i.resolve(!0)},function(){i.reject(!1)}),i.promise},shareViaFacebookWithPasteMessageHint:function(r,o,t,i){var a=e.defer();return o=o||null,t=t||null,n.plugins.socialsharing.shareViaFacebookWithPasteMessageHint(r,o,t,i,function(){a.resolve(!0)},function(){a.reject(!1)}),a.promise},shareViaSMS:function(r,o){var t=e.defer();return n.plugins.socialsharing.shareViaSMS(r,o,function(){t.resolve(!0)},function(){t.reject(!1)}),t.promise},shareViaEmail:function(r,o,t,i,a,c){var u=e.defer();return t=t||null,i=i||null,a=a||null,c=c||null,n.plugins.socialsharing.shareViaEmail(r,o,t,i,a,c,function(){u.resolve(!0)},function(){u.reject(!1)}),u.promise},shareVia:function(r,o,t,i,a){var c=e.defer();return o=o||null,t=t||null,i=i||null,a=a||null,n.plugins.socialsharing.shareVia(r,o,t,i,a,function(){c.resolve(!0)},function(){c.reject(!1)}),c.promise},canShareViaEmail:function(){var r=e.defer();return n.plugins.socialsharing.canShareViaEmail(function(){r.resolve(!0)},function(){r.reject(!1)}),r.promise},canShareVia:function(r,o,t,i,a){var c=e.defer();return n.plugins.socialsharing.canShareVia(r,o,t,i,a,function(e){c.resolve(e)},function(e){c.reject(e)}),c.promise},available:function(){var n=e.defer();return window.plugins.socialsharing.available(function(e){e?n.resolve():n.reject()}),n.promise}}}]),angular.module("ngCordova.plugins.spinnerDialog",[]).factory("$cordovaSpinnerDialog",["$window",function(e){return{show:function(n,r,o){return o=o||!1,e.plugins.spinnerDialog.show(n,r,o)},hide:function(){return e.plugins.spinnerDialog.hide()}}}]),angular.module("ngCordova.plugins.splashscreen",[]).factory("$cordovaSplashscreen",[function(){return{hide:function(){return navigator.splashscreen.hide()},show:function(){return navigator.splashscreen.show()}}}]),angular.module("ngCordova.plugins.sqlite",[]).factory("$cordovaSQLite",["$q","$window",function(e,n){return{openDB:function(e,r){return angular.isObject(e)&&!angular.isString(e)?("undefined"!=typeof r&&(e.bgType=r),n.sqlitePlugin.openDatabase(e)):n.sqlitePlugin.openDatabase({name:e,bgType:r})},execute:function(n,r,o){var t=e.defer();return n.transaction(function(e){e.executeSql(r,o,function(e,n){t.resolve(n)},function(e,n){t.reject(n)})}),t.promise},insertCollection:function(n,r,o){var t=e.defer(),i=o.slice(0);return n.transaction(function(e){!function n(){var o=i.splice(0,1)[0];try{e.executeSql(r,o,function(e,r){0===i.length?t.resolve(r):n()},function(e,n){t.reject(n)})}catch(a){t.reject(a)}}()}),t.promise},nestedExecute:function(n,r,o,t,i){var a=e.defer();return n.transaction(function(e){e.executeSql(r,t,function(e,n){a.resolve(n),e.executeSql(o,i,function(e,n){a.resolve(n)})})},function(e,n){a.reject(n)}),a.promise},deleteDB:function(r){var o=e.defer();return n.sqlitePlugin.deleteDatabase(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise}}}]),angular.module("ngCordova.plugins.statusbar",[]).factory("$cordovaStatusbar",[function(){return{overlaysWebView:function(e){return StatusBar.overlaysWebView(!!e)},STYLES:{DEFAULT:0,LIGHT_CONTENT:1,BLACK_TRANSLUCENT:2,BLACK_OPAQUE:3},style:function(e){switch(e){case 0:return StatusBar.styleDefault();case 1:return StatusBar.styleLightContent();case 2:return StatusBar.styleBlackTranslucent();case 3:return StatusBar.styleBlackOpaque();default:return StatusBar.styleDefault()}},styleColor:function(e){return StatusBar.backgroundColorByName(e)},styleHex:function(e){return StatusBar.backgroundColorByHexString(e)},hide:function(){return StatusBar.hide()},show:function(){return StatusBar.show()},isVisible:function(){return StatusBar.isVisible}}}]),angular.module("ngCordova.plugins.toast",[]).factory("$cordovaToast",["$q","$window",function(e,n){return{showShortTop:function(r){var o=e.defer();return n.plugins.toast.showShortTop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showShortCenter:function(r){var o=e.defer();return n.plugins.toast.showShortCenter(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showShortBottom:function(r){var o=e.defer();return n.plugins.toast.showShortBottom(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongTop:function(r){var o=e.defer();return n.plugins.toast.showLongTop(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongCenter:function(r){var o=e.defer();return n.plugins.toast.showLongCenter(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},showLongBottom:function(r){var o=e.defer();return n.plugins.toast.showLongBottom(r,function(e){o.resolve(e)},function(e){o.reject(e)}),o.promise},show:function(r,o,t){var i=e.defer();return n.plugins.toast.show(r,o,t,function(e){i.resolve(e)},function(e){i.reject(e)}),i.promise},hide:function(){var r=e.defer();try{n.plugins.toast.hide(),r.resolve()}catch(o){r.reject(o&&o.message)}return r.promise}}}]),angular.module("ngCordova.plugins.touchid",[]).factory("$cordovaTouchID",["$q",function(e){return{checkSupport:function(){var n=e.defer();return window.cordova?touchid.checkSupport(function(e){n.resolve(e)},function(e){n.reject(e)}):n.reject("Not supported without cordova.js"),n.promise},authenticate:function(n){var r=e.defer();return window.cordova?touchid.authenticate(function(e){r.resolve(e)},function(e){r.reject(e)},n):r.reject("Not supported without cordova.js"),r.promise}}}]),angular.module("ngCordova.plugins.upsPush",[]).factory("$cordovaUpsPush",["$q","$window","$rootScope","$timeout",function(e,n,r,o){return{register:function(t){var i=e.defer();return n.push.register(function(e){o(function(){r.$broadcast("$cordovaUpsPush:notificationReceived",e)})},function(){i.resolve()},function(e){i.reject(e)},t),i.promise},unregister:function(r){var o=e.defer();return n.push.unregister(function(){o.resolve()},function(e){o.reject(e)},r),o.promise},setBadgeNumber:function(r){var o=e.defer();return n.push.setApplicationIconBadgeNumber(function(){o.resolve()},r),o.promise}}}]),angular.module("ngCordova.plugins.vibration",[]).factory("$cordovaVibration",[function(){return{vibrate:function(e){return navigator.notification.vibrate(e)},vibrateWithPattern:function(e,n){return navigator.notification.vibrateWithPattern(e,n)},cancelVibration:function(){return navigator.notification.cancelVibration()}}}]),angular.module("ngCordova.plugins.videoCapturePlus",[]).provider("$cordovaVideoCapturePlus",[function(){var e={};this.setLimit=function(n){e.limit=n},this.setMaxDuration=function(n){e.duration=n},this.setHighQuality=function(n){e.highquality=n},this.useFrontCamera=function(n){e.frontcamera=n},this.setPortraitOverlay=function(n){e.portraitOverlay=n},this.setLandscapeOverlay=function(n){e.landscapeOverlay=n},this.setOverlayText=function(n){e.overlayText=n},this.$get=["$q","$window",function(n,r){return{captureVideo:function(o){var t=n.defer();return r.plugins.videocaptureplus?(r.plugins.videocaptureplus.captureVideo(t.resolve,t.reject,angular.extend({},e,o)),t.promise):(t.resolve(null),t.promise)}}}]}]),angular.module("ngCordova.plugins.zip",[]).factory("$cordovaZip",["$q","$window",function(e,n){return{unzip:function(r,o){var t=e.defer();return n.zip.unzip(r,o,function(e){0===e?t.resolve():t.reject()},function(e){t.notify(e)}),t.promise}}}])}(); \ No newline at end of file diff --git a/www/lib/crypto-js/.bower.json b/www/lib/crypto-js/.bower.json new file mode 100644 index 0000000000000000000000000000000000000000..b1df67527cf6184fdf6596a74efb288a3418dadd --- /dev/null +++ b/www/lib/crypto-js/.bower.json @@ -0,0 +1,45 @@ +{ + "name": "crypto-js", + "version": "3.1.6", + "description": "JavaScript library of crypto standards.", + "license": "MIT", + "homepage": "http://github.com/brix/crypto-js", + "repository": { + "type": "git", + "url": "http://github.com/brix/crypto-js.git" + }, + "keywords": [ + "security", + "crypto", + "Hash", + "MD5", + "SHA1", + "SHA-1", + "SHA256", + "SHA-256", + "RC4", + "Rabbit", + "AES", + "DES", + "PBKDF2", + "HMAC", + "OFB", + "CFB", + "CTR", + "CBC", + "Base64" + ], + "main": "index.js", + "dependencies": {}, + "ignore": [], + "_release": "3.1.6", + "_resolution": { + "type": "version", + "tag": "3.1.6", + "commit": "f92d7ed1c322b305d04c4b6fcd8970644da89111" + }, + "_source": "https://github.com/brix/crypto-js.git", + "_target": "^3.1.6", + "_originalSource": "crypto-js", + "_direct": true +} \ No newline at end of file diff --git a/www/lib/crypto-js/CONTRIBUTING.md b/www/lib/crypto-js/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..09bf774aaab77809f2ffcd19027731e3ee0aedd1 --- /dev/null +++ b/www/lib/crypto-js/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contribution + +# Git Flow + +The crypto-js project uses [git flow](https://github.com/nvie/gitflow) to manage branches. +Do your changes on the `develop` or even better on a `feature/*` branch. Don't do any changes on the `master` branch. + +# Pull request + +Target your pull request on `develop` branch. Other pull request won't be accepted. + +# How to build + +1. Clone + +2. Run + + ```sh + npm install + ``` + +3. Run + + ```sh + npm run build + ``` + +4. Check `build` folder \ No newline at end of file diff --git a/www/lib/crypto-js/LICENSE b/www/lib/crypto-js/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..b0828e52a6b3f0716727bc4e03c4634d25a7568c --- /dev/null +++ b/www/lib/crypto-js/LICENSE @@ -0,0 +1,24 @@ +# License + +[The MIT License (MIT)](http://opensource.org/licenses/MIT) + +Copyright (c) 2009-2013 Jeff Mott +Copyright (c) 2013-2016 Evan Vosberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/lib/crypto-js/README.md b/www/lib/crypto-js/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0ec682f0a92c01dc41f158f51c01f2bb3edad35a --- /dev/null +++ b/www/lib/crypto-js/README.md @@ -0,0 +1,198 @@ +# crypto-js + +JavaScript library of crypto standards. + +## Node.js (Install) + +Requirements: + +- Node.js +- npm (Node.js package manager) + +```bash +npm install crypto-js +``` + +### Usage + +Modular include: + +```javascript +var AES = require("crypto-js/aes"); +var SHA256 = require("crypto-js/sha256"); +... +console.log(SHA256("Message")); +``` + +Including all libraries, for access to extra methods: + +```javascript +var CryptoJS = require("crypto-js"); +console.log(CryptoJS.HmacSHA1("Message", "Key")); +``` + +## Client (browser) + +Requirements: + +- Node.js +- Bower (package manager for frontend) + +```bash +bower install crypto-js +``` + +### Usage + +Modular include: + +```javascript +require.config({ + packages: [ + { + name: 'crypto-js', + location: 'path-to/bower_components/crypto-js', + main: 'index' + } + ] +}); + +require(["crypto-js/aes", "crypto-js/sha256"], function (AES, SHA256) { + console.log(SHA256("Message")); +}); +``` + +Including all libraries, for access to extra methods: + +```javascript +// Above-mentioned will work or use this simple form +require.config({ + paths: { + 'require-js': 'path-to/bower_components/crypto-js/crypto-js' + } +}); + +require(["crypto-js"], function (CryptoJS) { + console.log(CryptoJS.HmacSHA1("Message", "Key")); +}); +``` + +### Usage without RequireJS + +```html +<script type="text/javascript" src="path-to/bower_components/crypto-js/crypto-js.js"></script> +<script type="text/javascript"> + var encrypted = CryptoJS.AES(...); + var encrypted = CryptoJS.SHA256(...); +</script> +``` + +## API + +See: https://code.google.com/p/crypto-js + +### AES Encryption + +#### Plain text encryption + +```javascript +var CryptoJS = require("crypto-js"); + +// Encrypt +var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123'); + +// Decrypt +var bytes = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123'); +var plaintext = bytes.toString(CryptoJS.enc.Utf8); + +console.log(plaintext); +``` + +#### Object encryption + +```javascript +var CryptoJS = require("crypto-js"); + +var data = [{id: 1}, {id: 2}] + +// Encrypt +var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123'); + +// Decrypt +var bytes = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123'); +var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); + +console.log(decryptedData); +``` + +### List of modules + + +- ```crypto-js/core``` +- ```crypto-js/x64-core``` +- ```crypto-js/lib-typedarrays``` + +--- + +- ```crypto-js/md5``` +- ```crypto-js/sha1``` +- ```crypto-js/sha256``` +- ```crypto-js/sha224``` +- ```crypto-js/sha512``` +- ```crypto-js/sha384``` +- ```crypto-js/sha3``` +- ```crypto-js/ripemd160``` + +--- + +- ```crypto-js/hmac-md5``` +- ```crypto-js/hmac-sha1``` +- ```crypto-js/hmac-sha256``` +- ```crypto-js/hmac-sha224``` +- ```crypto-js/hmac-sha512``` +- ```crypto-js/hmac-sha384``` +- ```crypto-js/hmac-sha3``` +- ```crypto-js/hmac-ripemd160``` + +--- + +- ```crypto-js/pbkdf2``` + +--- + +- ```crypto-js/aes``` +- ```crypto-js/tripledes``` +- ```crypto-js/rc4``` +- ```crypto-js/rabbit``` +- ```crypto-js/rabbit-legacy``` +- ```crypto-js/evpkdf``` + +--- + +- ```crypto-js/format-openssl``` +- ```crypto-js/format-hex``` + +--- + +- ```crypto-js/enc-latin1``` +- ```crypto-js/enc-utf8``` +- ```crypto-js/enc-hex``` +- ```crypto-js/enc-utf16``` +- ```crypto-js/enc-base64``` + +--- + +- ```crypto-js/mode-cfb``` +- ```crypto-js/mode-ctr``` +- ```crypto-js/mode-ctr-gladman``` +- ```crypto-js/mode-ofb``` +- ```crypto-js/mode-ecb``` + +--- + +- ```crypto-js/pad-pkcs7``` +- ```crypto-js/pad-ansix923``` +- ```crypto-js/pad-iso10126``` +- ```crypto-js/pad-iso97971``` +- ```crypto-js/pad-zeropadding``` +- ```crypto-js/pad-nopadding``` diff --git a/www/lib/crypto-js/aes.js b/www/lib/crypto-js/aes.js new file mode 100644 index 0000000000000000000000000000000000000000..ff0d2085e68cb1b76c77e7e9f32b04e320a00eff --- /dev/null +++ b/www/lib/crypto-js/aes.js @@ -0,0 +1,227 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Lookup tables + var SBOX = []; + var INV_SBOX = []; + var SUB_MIX_0 = []; + var SUB_MIX_1 = []; + var SUB_MIX_2 = []; + var SUB_MIX_3 = []; + var INV_SUB_MIX_0 = []; + var INV_SUB_MIX_1 = []; + var INV_SUB_MIX_2 = []; + var INV_SUB_MIX_3 = []; + + // Compute lookup tables + (function () { + // Compute double table + var d = []; + for (var i = 0; i < 256; i++) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } + } + + // Walk GF(2^8) + var x = 0; + var xi = 0; + for (var i = 0; i < 256; i++) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + var x2 = d[x]; + var x4 = d[x2]; + var x8 = d[x4]; + + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100); + SUB_MIX_0[x] = (t << 24) | (t >>> 8); + SUB_MIX_1[x] = (t << 16) | (t >>> 16); + SUB_MIX_2[x] = (t << 8) | (t >>> 24); + SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + x = xi = 1; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } + } + }()); + + // Precomputed Rcon lookup + var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + + /** + * AES block cipher algorithm. + */ + var AES = C_algo.AES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + // Compute number of rounds + var nRounds = this._nRounds = keySize + 6 + + // Compute number of key schedule rows + var ksRows = (nRounds + 1) * 4; + + // Compute key schedule + var keySchedule = this._keySchedule = []; + for (var ksRow = 0; ksRow < ksRows; ksRow++) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + var t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize == 4) { + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + var invKeySchedule = this._invKeySchedule = []; + for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { + var ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + var t = keySchedule[ksRow]; + } else { + var t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ + INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; + } + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); + }, + + decryptBlock: function (M, offset) { + // Swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + + this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); + + // Inv swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + }, + + _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + // Shortcut + var nRounds = this._nRounds; + + // Get input, add round key + var s0 = M[offset] ^ keySchedule[0]; + var s1 = M[offset + 1] ^ keySchedule[1]; + var s2 = M[offset + 2] ^ keySchedule[2]; + var s3 = M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + var ksRow = 4; + + // Rounds + for (var round = 1; round < nRounds; round++) { + // Shift rows, sub bytes, mix columns, add round key + var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; + var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; + var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; + var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; + var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; + var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; + var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; + + // Set output + M[offset] = t0; + M[offset + 1] = t1; + M[offset + 2] = t2; + M[offset + 3] = t3; + }, + + keySize: 256/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ + C.AES = BlockCipher._createHelper(AES); + }()); + + + return CryptoJS.AES; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/bower.json b/www/lib/crypto-js/bower.json new file mode 100644 index 0000000000000000000000000000000000000000..c09f8518ca917bcd66b1a7e62f8441e614b75c68 --- /dev/null +++ b/www/lib/crypto-js/bower.json @@ -0,0 +1,35 @@ +{ + "name": "crypto-js", + "version": "3.1.6", + "description": "JavaScript library of crypto standards.", + "license": "MIT", + "homepage": "http://github.com/brix/crypto-js", + "repository": { + "type": "git", + "url": "http://github.com/brix/crypto-js.git" + }, + "keywords": [ + "security", + "crypto", + "Hash", + "MD5", + "SHA1", + "SHA-1", + "SHA256", + "SHA-256", + "RC4", + "Rabbit", + "AES", + "DES", + "PBKDF2", + "HMAC", + "OFB", + "CFB", + "CTR", + "CBC", + "Base64" + ], + "main": "index.js", + "dependencies": {}, + "ignore": [] +} diff --git a/www/lib/crypto-js/cipher-core.js b/www/lib/crypto-js/cipher-core.js new file mode 100644 index 0000000000000000000000000000000000000000..4fad5699163083147d6d62e11669a5208c86ff50 --- /dev/null +++ b/www/lib/crypto-js/cipher-core.js @@ -0,0 +1,875 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Cipher core components. + */ + CryptoJS.lib.Cipher || (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var Base64 = C_enc.Base64; + var C_algo = C.algo; + var EvpKDF = C_algo.EvpKDF; + + /** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ + var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base.extend(), + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + createEncryptor: function (key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + }, + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + createDecryptor: function (key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + }, + + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); + */ + init: function (xformMode, key, cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + }, + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + }, + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * var encrypted = cipher.process('data'); + * var encrypted = cipher.process(wordArray); + */ + process: function (dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + }, + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * var encrypted = cipher.finalize(); + * var encrypted = cipher.finalize('data'); + * var encrypted = cipher.finalize(wordArray); + */ + finalize: function (dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + var finalProcessedData = this._doFinalize(); + + return finalProcessedData; + }, + + keySize: 128/32, + + ivSize: 128/32, + + _ENC_XFORM_MODE: 1, + + _DEC_XFORM_MODE: 2, + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + _createHelper: (function () { + function selectCipherStrategy(key) { + if (typeof key == 'string') { + return PasswordBasedCipher; + } else { + return SerializableCipher; + } + } + + return function (cipher) { + return { + encrypt: function (message, key, cfg) { + return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); + }, + + decrypt: function (ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); + } + }; + }; + }()) + }); + + /** + * Abstract base stream cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ + var StreamCipher = C_lib.StreamCipher = Cipher.extend({ + _doFinalize: function () { + // Process partial blocks + var finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + }, + + blockSize: 1 + }); + + /** + * Mode namespace. + */ + var C_mode = C.mode = {}; + + /** + * Abstract base block cipher mode template. + */ + var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + createEncryptor: function (cipher, iv) { + return this.Encryptor.create(cipher, iv); + }, + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + createDecryptor: function (cipher, iv) { + return this.Decryptor.create(cipher, iv); + }, + + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + init: function (cipher, iv) { + this._cipher = cipher; + this._iv = iv; + } + }); + + /** + * Cipher Block Chaining mode. + */ + var CBC = C_mode.CBC = (function () { + /** + * Abstract base CBC mode. + */ + var CBC = BlockCipherMode.extend(); + + /** + * CBC encryptor. + */ + CBC.Encryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + /** + * CBC decryptor. + */ + CBC.Decryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function xorBlock(words, offset, blockSize) { + // Shortcut + var iv = this._iv; + + // Choose mixing block + if (iv) { + var block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + var block = this._prevBlock; + } + + // XOR blocks + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= block[i]; + } + } + + return CBC; + }()); + + /** + * Padding namespace. + */ + var C_pad = C.pad = {}; + + /** + * PKCS #5/7 padding strategy. + */ + var Pkcs7 = C_pad.Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Create padding word + var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; + + // Create padding + var paddingWords = []; + for (var i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + var padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + /** + * Abstract base block cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ + var BlockCipher = C_lib.BlockCipher = Cipher.extend({ + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + cfg: Cipher.cfg.extend({ + mode: CBC, + padding: Pkcs7 + }), + + reset: function () { + // Reset cipher + Cipher.reset.call(this); + + // Shortcuts + var cfg = this.cfg; + var iv = cfg.iv; + var mode = cfg.mode; + + // Reset block mode + if (this._xformMode == this._ENC_XFORM_MODE) { + var modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + var modeCreator = mode.createDecryptor; + + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + this._mode = modeCreator.call(mode, this, iv && iv.words); + }, + + _doProcessBlock: function (words, offset) { + this._mode.processBlock(words, offset); + }, + + _doFinalize: function () { + // Shortcut + var padding = this.cfg.padding; + + // Finalize + if (this._xformMode == this._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + var finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + var finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + }, + + blockSize: 128/32 + }); + + /** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. + */ + var CipherParams = C_lib.CipherParams = Base.extend({ + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + init: function (cipherParams) { + this.mixIn(cipherParams); + }, + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString: function (formatter) { + return (formatter || this.formatter).stringify(this); + } + }); + + /** + * Format namespace. + */ + var C_format = C.format = {}; + + /** + * OpenSSL formatting strategy. + */ + var OpenSSLFormatter = C_format.OpenSSL = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify: function (cipherParams) { + // Shortcuts + var ciphertext = cipherParams.ciphertext; + var salt = cipherParams.salt; + + // Format + if (salt) { + var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + var wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse: function (openSSLStr) { + // Parse base64 + var ciphertext = Base64.parse(openSSLStr); + + // Shortcut + var ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { + // Extract salt + var salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext: ciphertext, salt: salt }); + } + }; + + /** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ + var SerializableCipher = C_lib.SerializableCipher = Base.extend({ + /** + * Configuration options. + * + * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL + */ + cfg: Base.extend({ + format: OpenSSLFormatter + }), + + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Encrypt + var encryptor = cipher.createEncryptor(key, cfg); + var ciphertext = encryptor.finalize(message); + + // Shortcut + var cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext: ciphertext, + key: key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: cipher.blockSize, + formatter: cfg.format + }); + }, + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Decrypt + var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); + + return plaintext; + }, + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); + */ + _parse: function (ciphertext, format) { + if (typeof ciphertext == 'string') { + return format.parse(ciphertext, this); + } else { + return ciphertext; + } + } + }); + + /** + * Key derivation function namespace. + */ + var C_kdf = C.kdf = {}; + + /** + * OpenSSL key derivation function. + */ + var OpenSSLKdf = C_kdf.OpenSSL = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute: function (password, keySize, ivSize, salt) { + // Generate random salt + if (!salt) { + salt = WordArray.random(64/8); + } + + // Derive key and IV + var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt); + + // Separate key and IV + var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key: key, iv: iv, salt: salt }); + } + }; + + /** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ + var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ + /** + * Configuration options. + * + * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL + */ + cfg: SerializableCipher.cfg.extend({ + kdf: OpenSSLKdf + }), + + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Encrypt + var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + }, + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Decrypt + var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); + + return plaintext; + } + }); + }()); + + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/core.js b/www/lib/crypto-js/core.js new file mode 100644 index 0000000000000000000000000000000000000000..8b0128bc1a325cb39e62c7e422866ab775a4c353 --- /dev/null +++ b/www/lib/crypto-js/core.js @@ -0,0 +1,742 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(); + } + else if (typeof define === "function" && define.amd) { + // AMD + define([], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(); + } +}(this, function () { + + /** + * CryptoJS core components. + */ + var CryptoJS = CryptoJS || (function (Math, undefined) { + /** + * CryptoJS namespace. + */ + var C = {}; + + /** + * Library namespace. + */ + var C_lib = C.lib = {}; + + /** + * Base object for prototypal inheritance. + */ + var Base = C_lib.Base = (function () { + function F() {} + + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function (overrides) { + // Spawn + F.prototype = this; + var subtype = new F(); + + // Augment + if (overrides) { + subtype.mixIn(overrides); + } + + // Create default initializer + if (!subtype.hasOwnProperty('init')) { + subtype.init = function () { + subtype.$super.init.apply(this, arguments); + }; + } + + // Initializer's prototype is the subtype object + subtype.init.prototype = subtype; + + // Reference supertype + subtype.$super = this; + + return subtype; + }, + + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function () { + var instance = this.extend(); + instance.init.apply(instance, arguments); + + return instance; + }, + + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function () { + }, + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function (properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + + // IE won't copy toString using the loop above + if (properties.hasOwnProperty('toString')) { + this.toString = properties.toString; + } + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function () { + return this.init.prototype.extend(this); + } + }; + }()); + + /** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var WordArray = C_lib.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function (encoder) { + return (encoder || Hex).stringify(this); + }, + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function (wordArray) { + // Shortcuts + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (var i = 0; i < thatSigBytes; i += 4) { + thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + }, + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function () { + // Shortcuts + var words = this.words; + var sigBytes = this.sigBytes; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + }, + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + }, + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function (nBytes) { + var words = []; + + var r = (function (m_w) { + var m_w = m_w; + var m_z = 0x3ade68b1; + var mask = 0xffffffff; + + return function () { + m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask; + m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask; + var result = ((m_z << 0x10) + m_w) & mask; + result /= 0x100000000; + result += 0.5; + return result * (Math.random() > .5 ? 1 : -1); + } + }); + + for (var i = 0, rcache; i < nBytes; i += 4) { + var _r = r((rcache || Math.random()) * 0x100000000); + + rcache = _r() * 0x3ade67b7; + words.push((_r() * 0x100000000) | 0); + } + + return new WordArray.init(words, nBytes); + } + }); + + /** + * Encoder namespace. + */ + var C_enc = C.enc = {}; + + /** + * Hex encoding strategy. + */ + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function (hexStr) { + // Shortcut + var hexStrLength = hexStr.length; + + // Convert + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray.init(words, hexStrLength / 2); + } + }; + + /** + * Latin1 encoding strategy. + */ + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function (latin1Str) { + // Shortcut + var latin1StrLength = latin1Str.length; + + // Convert + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray.init(words, latin1StrLength); + } + }; + + /** + * UTF-8 encoding strategy. + */ + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function (wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function (utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + + /** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function () { + // Initial values + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function (data) { + // Convert string to WordArray, else assume WordArray already + if (typeof data == 'string') { + data = Utf8.parse(data); + } + + // Append + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function (doFlush) { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + + // Count blocks ready + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + var nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + var processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray.init(processedWords, nBytesReady); + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone._data = this._data.clone(); + + return clone; + }, + + _minBufferSize: 0 + }); + + /** + * Abstract hasher template. + * + * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base.extend(), + + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function (cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Set initial values + this.reset(); + }, + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + }, + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function (messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + }, + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + var hash = this._doFinalize(); + + return hash; + }, + + blockSize: 512/32, + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function (hasher) { + return function (message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function (hasher) { + return function (message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + + /** + * Algorithm namespace. + */ + var C_algo = C.algo = {}; + + return C; + }(Math)); + + + return CryptoJS; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/crypto-js.js b/www/lib/crypto-js/crypto-js.js new file mode 100644 index 0000000000000000000000000000000000000000..2f535fcc0d9ffcdc52481bdaa7047ac8b5003131 --- /dev/null +++ b/www/lib/crypto-js/crypto-js.js @@ -0,0 +1,5949 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(); + } + else if (typeof define === "function" && define.amd) { + // AMD + define([], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(); + } +}(this, function () { + + /** + * CryptoJS core components. + */ + var CryptoJS = CryptoJS || (function (Math, undefined) { + /** + * CryptoJS namespace. + */ + var C = {}; + + /** + * Library namespace. + */ + var C_lib = C.lib = {}; + + /** + * Base object for prototypal inheritance. + */ + var Base = C_lib.Base = (function () { + function F() {} + + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function (overrides) { + // Spawn + F.prototype = this; + var subtype = new F(); + + // Augment + if (overrides) { + subtype.mixIn(overrides); + } + + // Create default initializer + if (!subtype.hasOwnProperty('init')) { + subtype.init = function () { + subtype.$super.init.apply(this, arguments); + }; + } + + // Initializer's prototype is the subtype object + subtype.init.prototype = subtype; + + // Reference supertype + subtype.$super = this; + + return subtype; + }, + + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function () { + var instance = this.extend(); + instance.init.apply(instance, arguments); + + return instance; + }, + + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function () { + }, + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function (properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + + // IE won't copy toString using the loop above + if (properties.hasOwnProperty('toString')) { + this.toString = properties.toString; + } + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function () { + return this.init.prototype.extend(this); + } + }; + }()); + + /** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var WordArray = C_lib.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function (encoder) { + return (encoder || Hex).stringify(this); + }, + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function (wordArray) { + // Shortcuts + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (var i = 0; i < thatSigBytes; i += 4) { + thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + }, + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function () { + // Shortcuts + var words = this.words; + var sigBytes = this.sigBytes; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + }, + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + }, + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function (nBytes) { + var words = []; + + var r = (function (m_w) { + var m_w = m_w; + var m_z = 0x3ade68b1; + var mask = 0xffffffff; + + return function () { + m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask; + m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask; + var result = ((m_z << 0x10) + m_w) & mask; + result /= 0x100000000; + result += 0.5; + return result * (Math.random() > .5 ? 1 : -1); + } + }); + + for (var i = 0, rcache; i < nBytes; i += 4) { + var _r = r((rcache || Math.random()) * 0x100000000); + + rcache = _r() * 0x3ade67b7; + words.push((_r() * 0x100000000) | 0); + } + + return new WordArray.init(words, nBytes); + } + }); + + /** + * Encoder namespace. + */ + var C_enc = C.enc = {}; + + /** + * Hex encoding strategy. + */ + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function (hexStr) { + // Shortcut + var hexStrLength = hexStr.length; + + // Convert + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray.init(words, hexStrLength / 2); + } + }; + + /** + * Latin1 encoding strategy. + */ + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function (latin1Str) { + // Shortcut + var latin1StrLength = latin1Str.length; + + // Convert + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray.init(words, latin1StrLength); + } + }; + + /** + * UTF-8 encoding strategy. + */ + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function (wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function (utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + + /** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function () { + // Initial values + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function (data) { + // Convert string to WordArray, else assume WordArray already + if (typeof data == 'string') { + data = Utf8.parse(data); + } + + // Append + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function (doFlush) { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + + // Count blocks ready + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + var nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + var processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray.init(processedWords, nBytesReady); + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone._data = this._data.clone(); + + return clone; + }, + + _minBufferSize: 0 + }); + + /** + * Abstract hasher template. + * + * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base.extend(), + + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function (cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Set initial values + this.reset(); + }, + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + }, + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function (messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + }, + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + var hash = this._doFinalize(); + + return hash; + }, + + blockSize: 512/32, + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function (hasher) { + return function (message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function (hasher) { + return function (message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + + /** + * Algorithm namespace. + */ + var C_algo = C.algo = {}; + + return C; + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64 encoding strategy. + */ + var Base64 = C_enc.Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse: function (base64Str) { + // Shortcuts + var base64StrLength = base64Str.length; + var map = this._map; + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex != -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2); + var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= (bitsCombined) << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + + return WordArray.create(words, nBytes); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' + }; + }()); + + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var T = []; + + // Compute constants + (function () { + for (var i = 0; i < 64; i++) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; + } + }()); + + /** + * MD5 hash algorithm. + */ + var MD5 = C_algo.MD5 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + var H = this._hash.words; + + var M_offset_0 = M[offset + 0]; + var M_offset_1 = M[offset + 1]; + var M_offset_2 = M[offset + 2]; + var M_offset_3 = M[offset + 3]; + var M_offset_4 = M[offset + 4]; + var M_offset_5 = M[offset + 5]; + var M_offset_6 = M[offset + 6]; + var M_offset_7 = M[offset + 7]; + var M_offset_8 = M[offset + 8]; + var M_offset_9 = M[offset + 9]; + var M_offset_10 = M[offset + 10]; + var M_offset_11 = M[offset + 11]; + var M_offset_12 = M[offset + 12]; + var M_offset_13 = M[offset + 13]; + var M_offset_14 = M[offset + 14]; + var M_offset_15 = M[offset + 15]; + + // Working varialbes + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + + var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + var nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | + (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | + (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 4; i++) { + // Shortcut + var H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + function FF(a, b, c, d, x, s, t) { + var n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function GG(a, b, c, d, x, s, t) { + var n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function HH(a, b, c, d, x, s, t) { + var n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function II(a, b, c, d, x, s, t) { + var n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ + C.MD5 = Hasher._createHelper(MD5); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ + C.HmacMD5 = Hasher._createHmacHelper(MD5); + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Reusable object + var W = []; + + /** + * SHA-1 hash algorithm. + */ + var SHA1 = C_algo.SHA1 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476, + 0xc3d2e1f0 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + + // Computation + for (var i = 0; i < 80; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + var t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ + C.SHA1 = Hasher._createHelper(SHA1); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ + C.HmacSHA1 = Hasher._createHmacHelper(SHA1); + }()); + + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Initialization and round constants tables + var H = []; + var K = []; + + // Compute constants + (function () { + function isPrime(n) { + var sqrtN = Math.sqrt(n); + for (var factor = 2; factor <= sqrtN; factor++) { + if (!(n % factor)) { + return false; + } + } + + return true; + } + + function getFractionalBits(n) { + return ((n - (n | 0)) * 0x100000000) | 0; + } + + var n = 2; + var nPrime = 0; + while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); + } + K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); + + nPrime++; + } + + n++; + } + }()); + + // Reusable object + var W = []; + + /** + * SHA-256 hash algorithm. + */ + var SHA256 = C_algo.SHA256 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init(H.slice(0)); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + var f = H[5]; + var g = H[6]; + var h = H[7]; + + // Computation + for (var i = 0; i < 64; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var gamma0x = W[i - 15]; + var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ + ((gamma0x << 14) | (gamma0x >>> 18)) ^ + (gamma0x >>> 3); + + var gamma1x = W[i - 2]; + var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ + ((gamma1x << 13) | (gamma1x >>> 19)) ^ + (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + var ch = (e & f) ^ (~e & g); + var maj = (a & b) ^ (a & c) ^ (b & c); + + var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + var t1 = h + sigma1 + ch + K[i] + W[i]; + var t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + H[5] = (H[5] + f) | 0; + H[6] = (H[6] + g) | 0; + H[7] = (H[7] + h) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ + C.SHA256 = Hasher._createHelper(SHA256); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ + C.HmacSHA256 = Hasher._createHmacHelper(SHA256); + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * UTF-16 BE encoding strategy. + */ + var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * var utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + /** + * UTF-16 LE encoding strategy. + */ + C_enc.Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + function swapEndian(word) { + return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + } + }()); + + + (function () { + // Check if typed arrays are supported + if (typeof ArrayBuffer != 'function') { + return; + } + + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + + // Reference original init + var superInit = WordArray.init; + + // Augment WordArray.init to handle typed arrays + var subInit = WordArray.init = function (typedArray) { + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array || + (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) || + typedArray instanceof Int16Array || + typedArray instanceof Uint16Array || + typedArray instanceof Int32Array || + typedArray instanceof Uint32Array || + typedArray instanceof Float32Array || + typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + var typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + var words = []; + for (var i = 0; i < typedArrayByteLength; i++) { + words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + superInit.call(this, words, typedArrayByteLength); + } else { + // Else call normal init + superInit.apply(this, arguments); + } + }; + + subInit.prototype = WordArray; + }()); + + + /** @preserve + (c) 2012 by Cédric Mesnil. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); + var _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); + var _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]); + var _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]); + + var _hl = WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); + var _hr = WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + + /** + * RIPEMD160 hash algorithm. + */ + var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({ + _doReset: function () { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + }, + + _doProcessBlock: function (M, offset) { + + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + // Swap + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + var H = this._hash.words; + var hl = _hl.words; + var hr = _hr.words; + var zl = _zl.words; + var zr = _zr.words; + var sl = _sl.words; + var sr = _sr.words; + + // Working variables + var al, bl, cl, dl, el; + var ar, br, cr, dr, er; + + ar = al = H[0]; + br = bl = H[1]; + cr = cl = H[2]; + dr = dl = H[3]; + er = el = H[4]; + // Computation + var t; + for (var i = 0; i < 80; i += 1) { + t = (al + M[offset+zl[i]])|0; + if (i<16){ + t += f1(bl,cl,dl) + hl[0]; + } else if (i<32) { + t += f2(bl,cl,dl) + hl[1]; + } else if (i<48) { + t += f3(bl,cl,dl) + hl[2]; + } else if (i<64) { + t += f4(bl,cl,dl) + hl[3]; + } else {// if (i<80) { + t += f5(bl,cl,dl) + hl[4]; + } + t = t|0; + t = rotl(t,sl[i]); + t = (t+el)|0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + M[offset+zr[i]])|0; + if (i<16){ + t += f5(br,cr,dr) + hr[0]; + } else if (i<32) { + t += f4(br,cr,dr) + hr[1]; + } else if (i<48) { + t += f3(br,cr,dr) + hr[2]; + } else if (i<64) { + t += f2(br,cr,dr) + hr[3]; + } else {// if (i<80) { + t += f1(br,cr,dr) + hr[4]; + } + t = t|0; + t = rotl(t,sr[i]) ; + t = (t+er)|0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr)|0; + H[1] = (H[2] + dl + er)|0; + H[2] = (H[3] + el + ar)|0; + H[3] = (H[4] + al + br)|0; + H[4] = (H[0] + bl + cr)|0; + H[0] = t; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) | + (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 5; i++) { + // Shortcut + var H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + + function f1(x, y, z) { + return ((x) ^ (y) ^ (z)); + + } + + function f2(x, y, z) { + return (((x)&(y)) | ((~x)&(z))); + } + + function f3(x, y, z) { + return (((x) | (~(y))) ^ (z)); + } + + function f4(x, y, z) { + return (((x) & (z)) | ((y)&(~(z)))); + } + + function f5(x, y, z) { + return ((x) ^ ((y) |(~(z)))); + + } + + function rotl(x,n) { + return (x<<n) | (x>>>(32-n)); + } + + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ + C.RIPEMD160 = Hasher._createHelper(RIPEMD160); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ + C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160); + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var C_algo = C.algo; + + /** + * HMAC algorithm. + */ + var HMAC = C_algo.HMAC = Base.extend({ + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} hasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + init: function (hasher, key) { + // Init hasher + hasher = this._hasher = new hasher.init(); + + // Convert string to WordArray, else assume WordArray already + if (typeof key == 'string') { + key = Utf8.parse(key); + } + + // Shortcuts + var hasherBlockSize = hasher.blockSize; + var hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (key.sigBytes > hasherBlockSizeBytes) { + key = hasher.finalize(key); + } + + // Clamp excess bits + key.clamp(); + + // Clone key for inner and outer pads + var oKey = this._oKey = key.clone(); + var iKey = this._iKey = key.clone(); + + // Shortcuts + var oKeyWords = oKey.words; + var iKeyWords = iKey.words; + + // XOR keys with pad constants + for (var i = 0; i < hasherBlockSize; i++) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + }, + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset: function () { + // Shortcut + var hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + }, + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update: function (messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + }, + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Shortcut + var hasher = this._hasher; + + // Compute HMAC + var innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + var hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } + }); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA1 = C_algo.SHA1; + var HMAC = C_algo.HMAC; + + /** + * Password-Based Key Derivation Function 2 algorithm. + */ + var PBKDF2 = C_algo.PBKDF2 = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA1 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: SHA1, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.PBKDF2.create(); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init HMAC + var hmac = HMAC.create(cfg.hasher, password); + + // Initial values + var derivedKey = WordArray.create(); + var blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var blockIndexWords = blockIndex.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + var block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + var blockWords = block.words; + var blockWordsLength = blockWords.length; + + // Iterations + var intermediate = block; + for (var i = 1; i < iterations; i++) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + var intermediateWords = intermediate.words; + + // XOR intermediate with block + for (var j = 0; j < blockWordsLength; j++) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0]++; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.PBKDF2 = function (password, salt, cfg) { + return PBKDF2.create(cfg).compute(password, salt); + }; + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var MD5 = C_algo.MD5; + + /** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ + var EvpKDF = C_algo.EvpKDF = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: MD5, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.EvpKDF.create(); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init hasher + var hasher = cfg.hasher.create(); + + // Initial values + var derivedKey = WordArray.create(); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + var block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (var i = 1; i < iterations; i++) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.EvpKDF = function (password, salt, cfg) { + return EvpKDF.create(cfg).compute(password, salt); + }; + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + + /** + * SHA-224 hash algorithm. + */ + var SHA224 = C_algo.SHA224 = SHA256.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + ]); + }, + + _doFinalize: function () { + var hash = SHA256._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ + C.SHA224 = SHA256._createHelper(SHA224); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ + C.HmacSHA224 = SHA256._createHmacHelper(SHA224); + }()); + + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var X32WordArray = C_lib.WordArray; + + /** + * x64 namespace. + */ + var C_x64 = C.x64 = {}; + + /** + * A 64-bit word. + */ + var X64Word = C_x64.Word = Base.extend({ + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + init: function (high, low) { + this.high = high; + this.low = low; + } + + /** + * Bitwise NOTs this word. + * + * @return {X64Word} A new x64-Word object after negating. + * + * @example + * + * var negated = x64Word.not(); + */ + // not: function () { + // var high = ~this.high; + // var low = ~this.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ANDs this word with the passed word. + * + * @param {X64Word} word The x64-Word to AND with this word. + * + * @return {X64Word} A new x64-Word object after ANDing. + * + * @example + * + * var anded = x64Word.and(anotherX64Word); + */ + // and: function (word) { + // var high = this.high & word.high; + // var low = this.low & word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to OR with this word. + * + * @return {X64Word} A new x64-Word object after ORing. + * + * @example + * + * var ored = x64Word.or(anotherX64Word); + */ + // or: function (word) { + // var high = this.high | word.high; + // var low = this.low | word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise XORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to XOR with this word. + * + * @return {X64Word} A new x64-Word object after XORing. + * + * @example + * + * var xored = x64Word.xor(anotherX64Word); + */ + // xor: function (word) { + // var high = this.high ^ word.high; + // var low = this.low ^ word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the left. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftL(25); + */ + // shiftL: function (n) { + // if (n < 32) { + // var high = (this.high << n) | (this.low >>> (32 - n)); + // var low = this.low << n; + // } else { + // var high = this.low << (n - 32); + // var low = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the right. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftR(7); + */ + // shiftR: function (n) { + // if (n < 32) { + // var low = (this.low >>> n) | (this.high << (32 - n)); + // var high = this.high >>> n; + // } else { + // var low = this.high >>> (n - 32); + // var high = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Rotates this word n bits to the left. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotL(25); + */ + // rotL: function (n) { + // return this.shiftL(n).or(this.shiftR(64 - n)); + // }, + + /** + * Rotates this word n bits to the right. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotR(7); + */ + // rotR: function (n) { + // return this.shiftR(n).or(this.shiftL(64 - n)); + // }, + + /** + * Adds this word with the passed word. + * + * @param {X64Word} word The x64-Word to add with this word. + * + * @return {X64Word} A new x64-Word object after adding. + * + * @example + * + * var added = x64Word.add(anotherX64Word); + */ + // add: function (word) { + // var low = (this.low + word.low) | 0; + // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0; + // var high = (this.high + word.high + carry) | 0; + + // return X64Word.create(high, low); + // } + }); + + /** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var X64WordArray = C_x64.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 8; + } + }, + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32: function () { + // Shortcuts + var x64Words = this.words; + var x64WordsLength = x64Words.length; + + // Convert + var x32Words = []; + for (var i = 0; i < x64WordsLength; i++) { + var x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + }, + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + + // Clone "words" array + var words = clone.words = this.words.slice(0); + + // Clone each X64Word object + var wordsLength = words.length; + for (var i = 0; i < wordsLength; i++) { + words[i] = words[i].clone(); + } + + return clone; + } + }); + }()); + + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var C_algo = C.algo; + + // Constants tables + var RHO_OFFSETS = []; + var PI_INDEXES = []; + var ROUND_CONSTANTS = []; + + // Compute Constants + (function () { + // Compute rho offset constants + var x = 1, y = 0; + for (var t = 0; t < 24; t++) { + RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64; + + var newX = y % 5; + var newY = (2 * x + 3 * y) % 5; + x = newX; + y = newY; + } + + // Compute pi index constants + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } + } + + // Compute round constants + var LFSR = 0x01; + for (var i = 0; i < 24; i++) { + var roundConstantMsw = 0; + var roundConstantLsw = 0; + + for (var j = 0; j < 7; j++) { + if (LFSR & 0x01) { + var bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); + } + }()); + + // Reusable objects for temporary values + var T = []; + (function () { + for (var i = 0; i < 25; i++) { + T[i] = X64Word.create(); + } + }()); + + /** + * SHA-3 hash algorithm. + */ + var SHA3 = C_algo.SHA3 = Hasher.extend({ + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + cfg: Hasher.cfg.extend({ + outputLength: 512 + }), + + _doReset: function () { + var state = this._state = [] + for (var i = 0; i < 25; i++) { + state[i] = new X64Word.init(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var state = this._state; + var nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (var i = 0; i < nBlockSizeLanes; i++) { + // Shortcuts + var M2i = M[offset + 2 * i]; + var M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = ( + (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) | + (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00) + ); + M2i1 = ( + (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) | + (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00) + ); + + // Absorb message into state + var lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (var round = 0; round < 24; round++) { + // Theta + for (var x = 0; x < 5; x++) { + // Mix column lanes + var tMsw = 0, tLsw = 0; + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + var Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (var x = 0; x < 5; x++) { + // Shortcuts + var Tx4 = T[(x + 4) % 5]; + var Tx1 = T[(x + 1) % 5]; + var Tx1Msw = Tx1.high; + var Tx1Lsw = Tx1.low; + + // Mix surrounding columns + var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (var laneIndex = 1; laneIndex < 25; laneIndex++) { + // Shortcuts + var lane = state[laneIndex]; + var laneMsw = lane.high; + var laneLsw = lane.low; + var rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + var tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + var tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + var tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + var tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + var TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + var T0 = T[0]; + var state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + // Shortcuts + var laneIndex = x + 5 * y; + var lane = state[laneIndex]; + var TLane = T[laneIndex]; + var Tx1Lane = T[((x + 1) % 5) + 5 * y]; + var Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + var lane = state[0]; + var roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low;; + } + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + var blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var state = this._state; + var outputLengthBytes = this.cfg.outputLength / 8; + var outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + var hashWords = []; + for (var i = 0; i < outputLengthLanes; i++) { + // Shortcuts + var lane = state[i]; + var laneMsw = lane.high; + var laneLsw = lane.low; + + // Swap endian + laneMsw = ( + (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) | + (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00) + ); + laneLsw = ( + (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) | + (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00) + ); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray.init(hashWords, outputLengthBytes); + }, + + clone: function () { + var clone = Hasher.clone.call(this); + + var state = clone._state = this._state.slice(0); + for (var i = 0; i < 25; i++) { + state[i] = state[i].clone(); + } + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ + C.SHA3 = Hasher._createHelper(SHA3); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ + C.HmacSHA3 = Hasher._createHmacHelper(SHA3); + }(Math)); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + + function X64Word_create() { + return X64Word.create.apply(X64Word, arguments); + } + + // Constants + var K = [ + X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd), + X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc), + X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019), + X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118), + X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe), + X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2), + X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1), + X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694), + X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3), + X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65), + X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483), + X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5), + X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210), + X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4), + X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725), + X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70), + X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926), + X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df), + X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8), + X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b), + X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001), + X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30), + X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910), + X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8), + X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53), + X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8), + X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb), + X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3), + X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60), + X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec), + X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9), + X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b), + X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207), + X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178), + X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6), + X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b), + X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493), + X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c), + X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a), + X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817) + ]; + + // Reusable objects + var W = []; + (function () { + for (var i = 0; i < 80; i++) { + W[i] = X64Word_create(); + } + }()); + + /** + * SHA-512 hash algorithm. + */ + var SHA512 = C_algo.SHA512 = Hasher.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b), + new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1), + new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f), + new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179) + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var H = this._hash.words; + + var H0 = H[0]; + var H1 = H[1]; + var H2 = H[2]; + var H3 = H[3]; + var H4 = H[4]; + var H5 = H[5]; + var H6 = H[6]; + var H7 = H[7]; + + var H0h = H0.high; + var H0l = H0.low; + var H1h = H1.high; + var H1l = H1.low; + var H2h = H2.high; + var H2l = H2.low; + var H3h = H3.high; + var H3l = H3.low; + var H4h = H4.high; + var H4l = H4.low; + var H5h = H5.high; + var H5l = H5.low; + var H6h = H6.high; + var H6l = H6.low; + var H7h = H7.high; + var H7l = H7.low; + + // Working variables + var ah = H0h; + var al = H0l; + var bh = H1h; + var bl = H1l; + var ch = H2h; + var cl = H2l; + var dh = H3h; + var dl = H3l; + var eh = H4h; + var el = H4l; + var fh = H5h; + var fl = H5l; + var gh = H6h; + var gl = H6l; + var hh = H7h; + var hl = H7l; + + // Rounds + for (var i = 0; i < 80; i++) { + // Shortcut + var Wi = W[i]; + + // Extend message + if (i < 16) { + var Wih = Wi.high = M[offset + i * 2] | 0; + var Wil = Wi.low = M[offset + i * 2 + 1] | 0; + } else { + // Gamma0 + var gamma0x = W[i - 15]; + var gamma0xh = gamma0x.high; + var gamma0xl = gamma0x.low; + var gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7); + var gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + var gamma1x = W[i - 2]; + var gamma1xh = gamma1x.high; + var gamma1xl = gamma1x.low; + var gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6); + var gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + var Wi7 = W[i - 7]; + var Wi7h = Wi7.high; + var Wi7l = Wi7.low; + + var Wi16 = W[i - 16]; + var Wi16h = Wi16.high; + var Wi16l = Wi16.low; + + var Wil = gamma0l + Wi7l; + var Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + var Wil = Wil + gamma1l; + var Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + var Wil = Wil + Wi16l; + var Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + var chh = (eh & fh) ^ (~eh & gh); + var chl = (el & fl) ^ (~el & gl); + var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + var majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + var sigma0h = ((ah >>> 28) | (al << 4)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7)); + var sigma0l = ((al >>> 28) | (ah << 4)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7)); + var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9)); + var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + var Ki = K[i]; + var Kih = Ki.high; + var Kil = Ki.low; + + var t1l = hl + sigma1l; + var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + var t1l = t1l + chl; + var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + var t1l = t1l + Kil; + var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + var t1l = t1l + Wil; + var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + var t2l = sigma0l + majl; + var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0l = H0.low = (H0l + al); + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1l = H1.low = (H1l + bl); + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2l = H2.low = (H2l + cl); + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3l = H3.low = (H3l + dl); + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4l = H4.low = (H4l + el); + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5l = H5.low = (H5l + fl); + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6l = H6.low = (H6l + gl); + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7l = H7.low = (H7l + hl); + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + var hash = this._hash.toX32(); + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + }, + + blockSize: 1024/32 + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ + C.SHA512 = Hasher._createHelper(SHA512); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ + C.HmacSHA512 = Hasher._createHmacHelper(SHA512); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + var SHA512 = C_algo.SHA512; + + /** + * SHA-384 hash algorithm. + */ + var SHA384 = C_algo.SHA384 = SHA512.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507), + new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939), + new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511), + new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4) + ]); + }, + + _doFinalize: function () { + var hash = SHA512._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ + C.SHA384 = SHA512._createHelper(SHA384); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ + C.HmacSHA384 = SHA512._createHmacHelper(SHA384); + }()); + + + /** + * Cipher core components. + */ + CryptoJS.lib.Cipher || (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var Base64 = C_enc.Base64; + var C_algo = C.algo; + var EvpKDF = C_algo.EvpKDF; + + /** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ + var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base.extend(), + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + createEncryptor: function (key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + }, + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + createDecryptor: function (key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + }, + + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); + */ + init: function (xformMode, key, cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + }, + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + }, + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * var encrypted = cipher.process('data'); + * var encrypted = cipher.process(wordArray); + */ + process: function (dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + }, + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * var encrypted = cipher.finalize(); + * var encrypted = cipher.finalize('data'); + * var encrypted = cipher.finalize(wordArray); + */ + finalize: function (dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + var finalProcessedData = this._doFinalize(); + + return finalProcessedData; + }, + + keySize: 128/32, + + ivSize: 128/32, + + _ENC_XFORM_MODE: 1, + + _DEC_XFORM_MODE: 2, + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + _createHelper: (function () { + function selectCipherStrategy(key) { + if (typeof key == 'string') { + return PasswordBasedCipher; + } else { + return SerializableCipher; + } + } + + return function (cipher) { + return { + encrypt: function (message, key, cfg) { + return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); + }, + + decrypt: function (ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); + } + }; + }; + }()) + }); + + /** + * Abstract base stream cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ + var StreamCipher = C_lib.StreamCipher = Cipher.extend({ + _doFinalize: function () { + // Process partial blocks + var finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + }, + + blockSize: 1 + }); + + /** + * Mode namespace. + */ + var C_mode = C.mode = {}; + + /** + * Abstract base block cipher mode template. + */ + var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + createEncryptor: function (cipher, iv) { + return this.Encryptor.create(cipher, iv); + }, + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + createDecryptor: function (cipher, iv) { + return this.Decryptor.create(cipher, iv); + }, + + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + init: function (cipher, iv) { + this._cipher = cipher; + this._iv = iv; + } + }); + + /** + * Cipher Block Chaining mode. + */ + var CBC = C_mode.CBC = (function () { + /** + * Abstract base CBC mode. + */ + var CBC = BlockCipherMode.extend(); + + /** + * CBC encryptor. + */ + CBC.Encryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + /** + * CBC decryptor. + */ + CBC.Decryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function xorBlock(words, offset, blockSize) { + // Shortcut + var iv = this._iv; + + // Choose mixing block + if (iv) { + var block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + var block = this._prevBlock; + } + + // XOR blocks + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= block[i]; + } + } + + return CBC; + }()); + + /** + * Padding namespace. + */ + var C_pad = C.pad = {}; + + /** + * PKCS #5/7 padding strategy. + */ + var Pkcs7 = C_pad.Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Create padding word + var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; + + // Create padding + var paddingWords = []; + for (var i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + var padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + /** + * Abstract base block cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ + var BlockCipher = C_lib.BlockCipher = Cipher.extend({ + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + cfg: Cipher.cfg.extend({ + mode: CBC, + padding: Pkcs7 + }), + + reset: function () { + // Reset cipher + Cipher.reset.call(this); + + // Shortcuts + var cfg = this.cfg; + var iv = cfg.iv; + var mode = cfg.mode; + + // Reset block mode + if (this._xformMode == this._ENC_XFORM_MODE) { + var modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + var modeCreator = mode.createDecryptor; + + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + this._mode = modeCreator.call(mode, this, iv && iv.words); + }, + + _doProcessBlock: function (words, offset) { + this._mode.processBlock(words, offset); + }, + + _doFinalize: function () { + // Shortcut + var padding = this.cfg.padding; + + // Finalize + if (this._xformMode == this._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + var finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + var finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + }, + + blockSize: 128/32 + }); + + /** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. + */ + var CipherParams = C_lib.CipherParams = Base.extend({ + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + init: function (cipherParams) { + this.mixIn(cipherParams); + }, + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString: function (formatter) { + return (formatter || this.formatter).stringify(this); + } + }); + + /** + * Format namespace. + */ + var C_format = C.format = {}; + + /** + * OpenSSL formatting strategy. + */ + var OpenSSLFormatter = C_format.OpenSSL = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify: function (cipherParams) { + // Shortcuts + var ciphertext = cipherParams.ciphertext; + var salt = cipherParams.salt; + + // Format + if (salt) { + var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + var wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse: function (openSSLStr) { + // Parse base64 + var ciphertext = Base64.parse(openSSLStr); + + // Shortcut + var ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { + // Extract salt + var salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext: ciphertext, salt: salt }); + } + }; + + /** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ + var SerializableCipher = C_lib.SerializableCipher = Base.extend({ + /** + * Configuration options. + * + * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL + */ + cfg: Base.extend({ + format: OpenSSLFormatter + }), + + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Encrypt + var encryptor = cipher.createEncryptor(key, cfg); + var ciphertext = encryptor.finalize(message); + + // Shortcut + var cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext: ciphertext, + key: key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: cipher.blockSize, + formatter: cfg.format + }); + }, + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Decrypt + var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); + + return plaintext; + }, + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); + */ + _parse: function (ciphertext, format) { + if (typeof ciphertext == 'string') { + return format.parse(ciphertext, this); + } else { + return ciphertext; + } + } + }); + + /** + * Key derivation function namespace. + */ + var C_kdf = C.kdf = {}; + + /** + * OpenSSL key derivation function. + */ + var OpenSSLKdf = C_kdf.OpenSSL = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute: function (password, keySize, ivSize, salt) { + // Generate random salt + if (!salt) { + salt = WordArray.random(64/8); + } + + // Derive key and IV + var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt); + + // Separate key and IV + var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key: key, iv: iv, salt: salt }); + } + }; + + /** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ + var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ + /** + * Configuration options. + * + * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL + */ + cfg: SerializableCipher.cfg.extend({ + kdf: OpenSSLKdf + }), + + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Encrypt + var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + }, + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Decrypt + var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); + + return plaintext; + } + }); + }()); + + + /** + * Cipher Feedback block mode. + */ + CryptoJS.mode.CFB = (function () { + var CFB = CryptoJS.lib.BlockCipherMode.extend(); + + CFB.Encryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + CFB.Decryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + // Shortcut + var iv = this._iv; + + // Generate keystream + if (iv) { + var keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + var keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + + return CFB; + }()); + + + /** + * Electronic Codebook block mode. + */ + CryptoJS.mode.ECB = (function () { + var ECB = CryptoJS.lib.BlockCipherMode.extend(); + + ECB.Encryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.encryptBlock(words, offset); + } + }); + + ECB.Decryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.decryptBlock(words, offset); + } + }); + + return ECB; + }()); + + + /** + * ANSI X.923 padding strategy. + */ + CryptoJS.pad.AnsiX923 = { + pad: function (data, blockSize) { + // Shortcuts + var dataSigBytes = data.sigBytes; + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes; + + // Compute last byte position + var lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + data.clamp(); + data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + data.sigBytes += nPaddingBytes; + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + /** + * ISO 10126 padding strategy. + */ + CryptoJS.pad.Iso10126 = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Pad + data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)). + concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + /** + * ISO/IEC 9797-1 Padding Method 2. + */ + CryptoJS.pad.Iso97971 = { + pad: function (data, blockSize) { + // Add 0x80 byte + data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1)); + + // Zero pad the rest + CryptoJS.pad.ZeroPadding.pad(data, blockSize); + }, + + unpad: function (data) { + // Remove zero padding + CryptoJS.pad.ZeroPadding.unpad(data); + + // Remove one more byte -- the 0x80 byte + data.sigBytes--; + } + }; + + + /** + * Output Feedback block mode. + */ + CryptoJS.mode.OFB = (function () { + var OFB = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = OFB.Encryptor = OFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var keystream = this._keystream; + + // Generate keystream + if (iv) { + keystream = this._keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + OFB.Decryptor = Encryptor; + + return OFB; + }()); + + + /** + * A noop padding strategy. + */ + CryptoJS.pad.NoPadding = { + pad: function () { + }, + + unpad: function () { + } + }; + + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var CipherParams = C_lib.CipherParams; + var C_enc = C.enc; + var Hex = C_enc.Hex; + var C_format = C.format; + + var HexFormatter = C_format.Hex = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify: function (cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse: function (input) { + var ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext: ciphertext }); + } + }; + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Lookup tables + var SBOX = []; + var INV_SBOX = []; + var SUB_MIX_0 = []; + var SUB_MIX_1 = []; + var SUB_MIX_2 = []; + var SUB_MIX_3 = []; + var INV_SUB_MIX_0 = []; + var INV_SUB_MIX_1 = []; + var INV_SUB_MIX_2 = []; + var INV_SUB_MIX_3 = []; + + // Compute lookup tables + (function () { + // Compute double table + var d = []; + for (var i = 0; i < 256; i++) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } + } + + // Walk GF(2^8) + var x = 0; + var xi = 0; + for (var i = 0; i < 256; i++) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + var x2 = d[x]; + var x4 = d[x2]; + var x8 = d[x4]; + + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100); + SUB_MIX_0[x] = (t << 24) | (t >>> 8); + SUB_MIX_1[x] = (t << 16) | (t >>> 16); + SUB_MIX_2[x] = (t << 8) | (t >>> 24); + SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + x = xi = 1; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } + } + }()); + + // Precomputed Rcon lookup + var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + + /** + * AES block cipher algorithm. + */ + var AES = C_algo.AES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + // Compute number of rounds + var nRounds = this._nRounds = keySize + 6 + + // Compute number of key schedule rows + var ksRows = (nRounds + 1) * 4; + + // Compute key schedule + var keySchedule = this._keySchedule = []; + for (var ksRow = 0; ksRow < ksRows; ksRow++) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + var t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize == 4) { + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + var invKeySchedule = this._invKeySchedule = []; + for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { + var ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + var t = keySchedule[ksRow]; + } else { + var t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ + INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; + } + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); + }, + + decryptBlock: function (M, offset) { + // Swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + + this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); + + // Inv swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + }, + + _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + // Shortcut + var nRounds = this._nRounds; + + // Get input, add round key + var s0 = M[offset] ^ keySchedule[0]; + var s1 = M[offset + 1] ^ keySchedule[1]; + var s2 = M[offset + 2] ^ keySchedule[2]; + var s3 = M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + var ksRow = 4; + + // Rounds + for (var round = 1; round < nRounds; round++) { + // Shift rows, sub bytes, mix columns, add round key + var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; + var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; + var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; + var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; + var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; + var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; + var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; + + // Set output + M[offset] = t0; + M[offset + 1] = t1; + M[offset + 2] = t2; + M[offset + 3] = t3; + }, + + keySize: 256/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ + C.AES = BlockCipher._createHelper(AES); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Permuted Choice 1 constants + var PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4 + ]; + + // Permuted Choice 2 constants + var PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + ]; + + // Cumulative bit shift constants + var BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + + // SBOXes and round permutation constants + var SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002 + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000 + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100 + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040 + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080 + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008 + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001 + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800 + } + ]; + + // Masks that select the SBOX input + var SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f + ]; + + /** + * DES block cipher algorithm. + */ + var DES = C_algo.DES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + + // Select 56 bits according to PC1 + var keyBits = []; + for (var i = 0; i < 56; i++) { + var keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1; + } + + // Assemble 16 subkeys + var subKeys = this._subKeys = []; + for (var nSubKey = 0; nSubKey < 16; nSubKey++) { + // Create subkey + var subKey = subKeys[nSubKey] = []; + + // Shortcut + var bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (var i = 0; i < 24; i++) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (var i = 1; i < 7; i++) { + subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + var invSubKeys = this._invSubKeys = []; + for (var i = 0; i < 16; i++) { + invSubKeys[i] = subKeys[15 - i]; + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + }, + + decryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + }, + + _doCryptBlock: function (M, offset, subKeys) { + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (var round = 0; round < 16; round++) { + // Shortcuts + var subKey = subKeys[round]; + var lBlock = this._lBlock; + var rBlock = this._rBlock; + + // Feistel function + var f = 0; + for (var i = 0; i < 8; i++) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + var t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + M[offset] = this._lBlock; + M[offset + 1] = this._rBlock; + }, + + keySize: 64/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + // Swap bits across the left and right words + function exchangeLR(offset, mask) { + var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; + } + + function exchangeRL(offset, mask) { + var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ + C.DES = BlockCipher._createHelper(DES); + + /** + * Triple-DES block cipher algorithm. + */ + var TripleDES = C_algo.TripleDES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + + // Create DES instances + this._des1 = DES.createEncryptor(WordArray.create(keyWords.slice(0, 2))); + this._des2 = DES.createEncryptor(WordArray.create(keyWords.slice(2, 4))); + this._des3 = DES.createEncryptor(WordArray.create(keyWords.slice(4, 6))); + }, + + encryptBlock: function (M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + }, + + decryptBlock: function (M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + }, + + keySize: 192/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ + C.TripleDES = BlockCipher._createHelper(TripleDES); + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + /** + * RC4 stream cipher algorithm. + */ + var RC4 = C_algo.RC4 = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + var keySigBytes = key.sigBytes; + + // Init sbox + var S = this._S = []; + for (var i = 0; i < 256; i++) { + S[i] = i; + } + + // Key setup + for (var i = 0, j = 0; i < 256; i++) { + var keyByteIndex = i % keySigBytes; + var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._i = this._j = 0; + }, + + _doProcessBlock: function (M, offset) { + M[offset] ^= generateKeystreamWord.call(this); + }, + + keySize: 256/32, + + ivSize: 0 + }); + + function generateKeystreamWord() { + // Shortcuts + var S = this._S; + var i = this._i; + var j = this._j; + + // Generate keystream word + var keystreamWord = 0; + for (var n = 0; n < 4; n++) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ + C.RC4 = StreamCipher._createHelper(RC4); + + /** + * Modified RC4 stream cipher algorithm. + */ + var RC4Drop = C_algo.RC4Drop = RC4.extend({ + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + cfg: RC4.cfg.extend({ + drop: 192 + }), + + _doReset: function () { + RC4._doReset.call(this); + + // Drop + for (var i = this.cfg.drop; i > 0; i--) { + generateKeystreamWord.call(this); + } + } + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ + C.RC4Drop = StreamCipher._createHelper(RC4Drop); + }()); + + + /** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ + CryptoJS.mode.CTRGladman = (function () { + var CTRGladman = CryptoJS.lib.BlockCipherMode.extend(); + + function incWord(word) + { + if (((word >> 24) & 0xff) === 0xff) { //overflow + var b1 = (word >> 16)&0xff; + var b2 = (word >> 8)&0xff; + var b3 = word & 0xff; + + if (b1 === 0xff) // overflow b1 + { + b1 = 0; + if (b2 === 0xff) + { + b2 = 0; + if (b3 === 0xff) + { + b3 = 0; + } + else + { + ++b3; + } + } + else + { + ++b2; + } + } + else + { + ++b1; + } + + word = 0; + word += (b1 << 16); + word += (b2 << 8); + word += b3; + } + else + { + word += (0x01 << 24); + } + return word; + } + + function incCounter(counter) + { + if ((counter[0] = incWord(counter[0])) === 0) + { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + counter[1] = incWord(counter[1]); + } + return counter; + } + + var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTRGladman.Decryptor = Encryptor; + + return CTRGladman; + }()); + + + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm + */ + var Rabbit = C_algo.Rabbit = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Swap endian + for (var i = 0; i < 4; i++) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) | + (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ + C.Rabbit = StreamCipher._createHelper(Rabbit); + }()); + + + /** + * Counter block mode. + */ + CryptoJS.mode.CTR = (function () { + var CTR = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = CTR.Encryptor = CTR.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0 + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTR.Decryptor = Encryptor; + + return CTR; + }()); + + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ + var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ + C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy); + }()); + + + /** + * Zero padding strategy. + */ + CryptoJS.pad.ZeroPadding = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Pad + data.clamp(); + data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad: function (data) { + // Shortcut + var dataWords = data.words; + + // Unpad + var i = data.sigBytes - 1; + while (!((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + i--; + } + data.sigBytes = i + 1; + } + }; + + + return CryptoJS; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/docs/QuickStartGuide.wiki b/www/lib/crypto-js/docs/QuickStartGuide.wiki new file mode 100644 index 0000000000000000000000000000000000000000..2bee35d2894c4f912b49c7accc9901c2f88f34a5 --- /dev/null +++ b/www/lib/crypto-js/docs/QuickStartGuide.wiki @@ -0,0 +1,470 @@ +<wiki:toc/> + +---- + += Quick-start Guide = + +== Hashers == + +=== The Hasher Algorithms === + +==== MD5 ==== + +MD5 is a widely used hash function. It's been used in a variety of security applications and is also commonly used to check the integrity of files. Though, MD5 is not collision resistant, and it isn't suitable for applications like SSL certificates or digital signatures that rely on this property. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/md5.js"></script> +<script> + var hash = CryptoJS.MD5("Message"); +</script> +}}} + +==== SHA-1 ==== + +The SHA hash functions were designed by the National Security Agency (NSA). SHA-1 is the most established of the existing SHA hash functions, and it's used in a variety of security applications and protocols. Though, SHA-1's collision resistance has been weakening as new attacks are discovered or improved. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha1.js"></script> +<script> + var hash = CryptoJS.SHA1("Message"); +</script> +}}} + +==== SHA-2 ==== + +SHA-256 is one of the four variants in the SHA-2 set. It isn't as widely used as SHA-1, though it appears to provide much better security. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script> +<script> + var hash = CryptoJS.SHA256("Message"); +</script> +}}} + +SHA-512 is largely identical to SHA-256 but operates on 64-bit words rather than 32. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha512.js"></script> +<script> + var hash = CryptoJS.SHA512("Message"); +</script> +}}} + +CryptoJS also supports SHA-224 and SHA-384, which are largely identical but truncated versions of SHA-256 and SHA-512 respectively. + +==== SHA-3 ==== + +SHA-3 is the winner of a five-year competition to select a new cryptographic hash algorithm where 64 competing designs were evaluated. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha3.js"></script> +<script> + var hash = CryptoJS.SHA3("Message"); +</script> +}}} + +SHA-3 can be configured to output hash lengths of one of 224, 256, 384, or 512 bits. The default is 512 bits. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha3.js"></script> +<script> + var hash = CryptoJS.SHA3("Message", { outputLength: 512 }); + var hash = CryptoJS.SHA3("Message", { outputLength: 384 }); + var hash = CryptoJS.SHA3("Message", { outputLength: 256 }); + var hash = CryptoJS.SHA3("Message", { outputLength: 224 }); +</script> +}}} + +==== RIPEMD-160 ==== + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/ripemd160.js"></script> +<script> + var hash = CryptoJS.RIPEMD160("Message"); +</script> +}}} + +=== The Hasher Input === + +The hash algorithms accept either strings or instances of CryptoJS.lib.WordArray. A WordArray object represents an array of 32-bit words. When you pass a string, it's automatically converted to a WordArray encoded as UTF-8. + +=== The Hasher Output === + +The hash you get back isn't a string yet. It's a WordArray object. When you use a WordArray object in a string context, it's automatically converted to a hex string. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script> +<script> + var hash = CryptoJS.SHA256("Message"); + + alert(typeof hash); // object + + alert(hash); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91 +</script> +}}} + +You can convert a WordArray object to other formats by explicitly calling the toString method and passing an encoder. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-base64-min.js"></script> +<script> + var hash = CryptoJS.SHA256("Message"); + + alert(hash.toString(CryptoJS.enc.Base64)); // L3dmip37+NWEi57rSnFFypTG7ZI25Kdz9tyvpRMrL5E= + + alert(hash.toString(CryptoJS.enc.Latin1)); // /wf��ûøÕ���ëJqEÊ�ÆÃ�6ä§söܯ¥+/� + + alert(hash.toString(CryptoJS.enc.Hex)); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91 +</script> +}}} + +=== Progressive Hashing === + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script> +<script> + var sha256 = CryptoJS.algo.SHA256.create(); + + sha256.update("Message Part 1"); + sha256.update("Message Part 2"); + sha256.update("Message Part 3"); + + var hash = sha256.finalize(); +</script> +}}} + +== HMAC == + +Keyed-hash message authentication codes (HMAC) is a mechanism for message authentication using cryptographic hash functions. + +HMAC can be used in combination with any iterated cryptographic hash function. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-md5.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha1.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha256.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha512.js"></script> +<script> + var hash = CryptoJS.HmacMD5("Message", "Secret Passphrase"); + var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase"); + var hash = CryptoJS.HmacSHA256("Message", "Secret Passphrase"); + var hash = CryptoJS.HmacSHA512("Message", "Secret Passphrase"); +</script> +}}} + +=== Progressive HMAC Hashing === + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha256.js"></script> +<script> + var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "Secret Passphrase"); + + hmac.update("Message Part 1"); + hmac.update("Message Part 2"); + hmac.update("Message Part 3"); + + var hash = hmac.finalize(); +</script> +}}} + +== PBKDF2 == + +PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required. + +A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/pbkdf2.js"></script> +<script> + var salt = CryptoJS.lib.WordArray.random(128/8); + + var key128Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32 }); + var key256Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 256/32 }); + var key512Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32 }); + + var key512Bits1000Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32, iterations: 1000 }); +</script> +}}} + +== Ciphers == + +=== The Cipher Algorithms === + +==== AES ==== + +The Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script> +<script> + var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase"); + + var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase"); +</script> +}}} + +CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key. + +==== DES, Triple DES ==== + +DES is a previously dominant algorithm for encryption, and was published as an official Federal Information Processing Standard (FIPS). DES is now considered to be insecure due to the small key size. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/tripledes.js"></script> +<script> + var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase"); + + var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase"); +</script> +}}} + +Triple DES applies DES three times to each block to increase the key size. The algorithm is believed to be secure in this form. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/tripledes.js"></script> +<script> + var encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase"); + + var decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase"); +</script> +}}} + +==== Rabbit ==== + +Rabbit is a high-performance stream cipher and a finalist in the eSTREAM Portfolio. It is one of the four designs selected after a 3 1/2-year process where 22 designs were evaluated. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rabbit.js"></script> +<script> + var encrypted = CryptoJS.Rabbit.encrypt("Message", "Secret Passphrase"); + + var decrypted = CryptoJS.Rabbit.decrypt(encrypted, "Secret Passphrase"); +</script> +}}} + +==== RC4, RC4Drop ==== + +RC4 is a widely-used stream cipher. It's used in popular protocols such as SSL and WEP. Although remarkable for its simplicity and speed, the algorithm's history doesn't inspire confidence in its security. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rc4.js"></script> +<script> + var encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase"); + + var decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase"); +</script> +}}} + +It was discovered that the first few bytes of keystream are strongly non-random and leak information about the key. We can defend against this attack by discarding the initial portion of the keystream. This modified algorithm is traditionally called RC4-drop. + +By default, 192 words (768 bytes) are dropped, but you can configure the algorithm to drop any number of words. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rc4.js"></script> +<script> + var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase"); + + var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase", { drop: 3072/4 }); + + var decrypted = CryptoJS.RC4Drop.decrypt(encrypted, "Secret Passphrase", { drop: 3072/4 }); +</script> +}}} + +=== Custom Key and IV === + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script> +<script> + var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f'); + var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f'); + + var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv }); +</script> +}}} + +=== Block Modes and Padding === + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-cfb-min.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-ansix923-min.js"></script> +<script> + var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", { mode: CryptoJS.mode.CFB, padding: CryptoJS.pad.AnsiX923 }); +</script> +}}} + +CryptoJS supports the following modes: + + * CBC (the default) + * CFB + * CTR + * OFB + * ECB + +And CryptoJS supports the following padding schemes: + + * Pkcs7 (the default) + * Iso97971 + * AnsiX923 + * Iso10126 + * ZeroPadding + * NoPadding + +=== The Cipher Input === + +For the plaintext message, the cipher algorithms accept either strings or instances of CryptoJS.lib.WordArray. + +For the key, when you pass a string, it's treated as a passphrase and used to derive an actual key and IV. Or you can pass a WordArray that represents the actual key. If you pass the actual key, you must also pass the actual IV. + +For the ciphertext, the cipher algorithms accept either strings or instances of CryptoJS.lib.CipherParams. A CipherParams object represents a collection of parameters such as the IV, a salt, and the raw ciphertext itself. When you pass a string, it's automatically converted to a CipherParams object according to a configurable format strategy. + +=== The Cipher Output === + +The plaintext you get back after decryption is a WordArray object. See Hashers' Output for more detail. + +The ciphertext you get back after encryption isn't a string yet. It's a CipherParams object. A CipherParams object gives you access to all the parameters used during encryption. When you use a CipherParams object in a string context, it's automatically converted to a string according to a format strategy. The default is an OpenSSL-compatible format. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script> +<script> + var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase"); + + alert(encrypted.key); // 74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223 + alert(encrypted.iv); // 7781157e2629b094f0e3dd48c4d786115 + alert(encrypted.salt); // 7a25f9132ec6a8b34 + alert(encrypted.ciphertext); // 73e54154a15d1beeb509d9e12f1e462a0 + + alert(encrypted); // U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA= +</script> +}}} + +You can define your own formats in order to be compatible with other crypto implementations. A format is an object with two methods—stringify and parse—that converts between CipherParams objects and ciphertext strings. + +Here's how you might write a JSON formatter: + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script> +<script> + var JsonFormatter = { + stringify: function (cipherParams) { + // create json object with ciphertext + var jsonObj = { + ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64) + }; + + // optionally add iv and salt + if (cipherParams.iv) { + jsonObj.iv = cipherParams.iv.toString(); + } + if (cipherParams.salt) { + jsonObj.s = cipherParams.salt.toString(); + } + + // stringify json object + return JSON.stringify(jsonObj); + }, + + parse: function (jsonStr) { + // parse json string + var jsonObj = JSON.parse(jsonStr); + + // extract ciphertext from json object, and create cipher params object + var cipherParams = CryptoJS.lib.CipherParams.create({ + ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct) + }); + + // optionally extract iv and salt + if (jsonObj.iv) { + cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv) + } + if (jsonObj.s) { + cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s) + } + + return cipherParams; + } + }; + + var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", { format: JsonFormatter }); + + alert(encrypted); // {"ct":"tZ4MsEnfbcDOwqau68aOrQ==","iv":"8a8c8fd8fe33743d3638737ea4a00698","s":"ba06373c8f57179c"} + + var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase", { format: JsonFormatter }); + + alert(decrypted.toString(CryptoJS.enc.Utf8)); // Message +</script> +}}} + +=== Progressive Ciphering === + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script> +<script> + var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f'); + var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f'); + + var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv }); + + var ciphertextPart1 = aesEncryptor.process("Message Part 1"); + var ciphertextPart2 = aesEncryptor.process("Message Part 2"); + var ciphertextPart3 = aesEncryptor.process("Message Part 3"); + var ciphertextPart4 = aesEncryptor.finalize(); + + var aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv }); + + var plaintextPart1 = aesDecryptor.process(ciphertextPart1); + var plaintextPart2 = aesDecryptor.process(ciphertextPart2); + var plaintextPart3 = aesDecryptor.process(ciphertextPart3); + var plaintextPart4 = aesDecryptor.process(ciphertextPart4); + var plaintextPart5 = aesDecryptor.finalize(); +</script> +}}} + +=== Interoperability === + +==== With OpenSSL ==== + +Encrypt with OpenSSL: + +{{{ +openssl enc -aes-256-cbc -in infile -out outfile -pass pass:"Secret Passphrase" -e -base64 +}}} + +Decrypt with CryptoJS: + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script> +<script> + var decrypted = CryptoJS.AES.decrypt(openSSLEncrypted, "Secret Passphrase"); +</script> +}}} + +== Encoders == + +CryptoJS can convert from encoding formats such as Base64, Latin1 or Hex to WordArray objects and vica versa. + +{{{ +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/core-min.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-utf16-min.js"></script> +<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-base64-min.js"></script> +<script> + var words = CryptoJS.enc.Base64.parse('SGVsbG8sIFdvcmxkIQ=='); + var base64 = CryptoJS.enc.Base64.stringify(words); + + var words = CryptoJS.enc.Latin1.parse('Hello, World!'); + var latin1 = CryptoJS.enc.Latin1.stringify(words); + + var words = CryptoJS.enc.Hex.parse('48656c6c6f2c20576f726c6421'); + var hex = CryptoJS.enc.Hex.stringify(words); + + var words = CryptoJS.enc.Utf8.parse('ð¤¢'); + var utf8 = CryptoJS.enc.Utf8.stringify(words); + + var words = CryptoJS.enc.Utf16.parse('Hello, World!'); + var utf16 = CryptoJS.enc.Utf16.stringify(words); + + var words = CryptoJS.enc.Utf16LE.parse('Hello, World!'); + var utf16 = CryptoJS.enc.Utf16LE.stringify(words); +</script> +}}} \ No newline at end of file diff --git a/www/lib/crypto-js/enc-base64.js b/www/lib/crypto-js/enc-base64.js new file mode 100644 index 0000000000000000000000000000000000000000..e16a3cbbdf8f0182cdbb650e1aab48b03f07afe6 --- /dev/null +++ b/www/lib/crypto-js/enc-base64.js @@ -0,0 +1,124 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64 encoding strategy. + */ + var Base64 = C_enc.Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse: function (base64Str) { + // Shortcuts + var base64StrLength = base64Str.length; + var map = this._map; + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex != -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = map.indexOf(base64Str.charAt(i - 1)) << ((i % 4) * 2); + var bits2 = map.indexOf(base64Str.charAt(i)) >>> (6 - (i % 4) * 2); + var bitsCombined = bits1 | bits2; + words[nBytes >>> 2] |= (bitsCombined) << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + + return WordArray.create(words, nBytes); + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' + }; + }()); + + + return CryptoJS.enc.Base64; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/enc-hex.js b/www/lib/crypto-js/enc-hex.js new file mode 100644 index 0000000000000000000000000000000000000000..88161ff5f629c5b7a14598614c4e9df7a677e4f8 --- /dev/null +++ b/www/lib/crypto-js/enc-hex.js @@ -0,0 +1,18 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.enc.Hex; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/enc-latin1.js b/www/lib/crypto-js/enc-latin1.js new file mode 100644 index 0000000000000000000000000000000000000000..ade56dcd49425fdaac7bd87645f5592a39d31d9a --- /dev/null +++ b/www/lib/crypto-js/enc-latin1.js @@ -0,0 +1,18 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.enc.Latin1; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/enc-utf16.js b/www/lib/crypto-js/enc-utf16.js new file mode 100644 index 0000000000000000000000000000000000000000..7de62457a52e57f3cf3dc53db0023764bc522920 --- /dev/null +++ b/www/lib/crypto-js/enc-utf16.js @@ -0,0 +1,149 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * UTF-16 BE encoding strategy. + */ + var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = { + /** + * Converts a word array to a UTF-16 BE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 BE string. + * + * @static + * + * @example + * + * var utf16String = CryptoJS.enc.Utf16.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 BE string to a word array. + * + * @param {string} utf16Str The UTF-16 BE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16.parse(utf16String); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + /** + * UTF-16 LE encoding strategy. + */ + C_enc.Utf16LE = { + /** + * Converts a word array to a UTF-16 LE string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-16 LE string. + * + * @static + * + * @example + * + * var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var utf16Chars = []; + for (var i = 0; i < sigBytes; i += 2) { + var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); + utf16Chars.push(String.fromCharCode(codePoint)); + } + + return utf16Chars.join(''); + }, + + /** + * Converts a UTF-16 LE string to a word array. + * + * @param {string} utf16Str The UTF-16 LE string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str); + */ + parse: function (utf16Str) { + // Shortcut + var utf16StrLength = utf16Str.length; + + // Convert + var words = []; + for (var i = 0; i < utf16StrLength; i++) { + words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); + } + + return WordArray.create(words, utf16StrLength * 2); + } + }; + + function swapEndian(word) { + return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); + } + }()); + + + return CryptoJS.enc.Utf16; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/enc-utf8.js b/www/lib/crypto-js/enc-utf8.js new file mode 100644 index 0000000000000000000000000000000000000000..e7a251d885bd88af5a67078b3e65b866fd8de36d --- /dev/null +++ b/www/lib/crypto-js/enc-utf8.js @@ -0,0 +1,18 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.enc.Utf8; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/evpkdf.js b/www/lib/crypto-js/evpkdf.js new file mode 100644 index 0000000000000000000000000000000000000000..3fe5c01c843aa766a8138a08981740e0fbd9eb65 --- /dev/null +++ b/www/lib/crypto-js/evpkdf.js @@ -0,0 +1,132 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha1", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var MD5 = C_algo.MD5; + + /** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ + var EvpKDF = C_algo.EvpKDF = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: MD5, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.EvpKDF.create(); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init hasher + var hasher = cfg.hasher.create(); + + // Initial values + var derivedKey = WordArray.create(); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + var block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (var i = 1; i < iterations; i++) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.EvpKDF = function (password, salt, cfg) { + return EvpKDF.create(cfg).compute(password, salt); + }; + }()); + + + return CryptoJS.EvpKDF; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/format-hex.js b/www/lib/crypto-js/format-hex.js new file mode 100644 index 0000000000000000000000000000000000000000..2e9a861f0cbaedcdc97a65034acb7ae590cd70e3 --- /dev/null +++ b/www/lib/crypto-js/format-hex.js @@ -0,0 +1,66 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var CipherParams = C_lib.CipherParams; + var C_enc = C.enc; + var Hex = C_enc.Hex; + var C_format = C.format; + + var HexFormatter = C_format.Hex = { + /** + * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The hexadecimally encoded string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.format.Hex.stringify(cipherParams); + */ + stringify: function (cipherParams) { + return cipherParams.ciphertext.toString(Hex); + }, + + /** + * Converts a hexadecimally encoded ciphertext string to a cipher params object. + * + * @param {string} input The hexadecimally encoded string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.Hex.parse(hexString); + */ + parse: function (input) { + var ciphertext = Hex.parse(input); + return CipherParams.create({ ciphertext: ciphertext }); + } + }; + }()); + + + return CryptoJS.format.Hex; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/format-openssl.js b/www/lib/crypto-js/format-openssl.js new file mode 100644 index 0000000000000000000000000000000000000000..3373edc6a66fbaaaa5f31e22d230bb56ca7e1a42 --- /dev/null +++ b/www/lib/crypto-js/format-openssl.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.format.OpenSSL; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-md5.js b/www/lib/crypto-js/hmac-md5.js new file mode 100644 index 0000000000000000000000000000000000000000..ad7a90adc27f6b407f7d278d5c4bb21d0dd5ad0d --- /dev/null +++ b/www/lib/crypto-js/hmac-md5.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./md5"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./md5", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacMD5; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-ripemd160.js b/www/lib/crypto-js/hmac-ripemd160.js new file mode 100644 index 0000000000000000000000000000000000000000..73d55a77013f5d8b318d2e6bc550e203aae78697 --- /dev/null +++ b/www/lib/crypto-js/hmac-ripemd160.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./ripemd160"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./ripemd160", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacRIPEMD160; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-sha1.js b/www/lib/crypto-js/hmac-sha1.js new file mode 100644 index 0000000000000000000000000000000000000000..0b570cbc31a5651d1a9287028848a1252b7f56c3 --- /dev/null +++ b/www/lib/crypto-js/hmac-sha1.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha1", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA1; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-sha224.js b/www/lib/crypto-js/hmac-sha224.js new file mode 100644 index 0000000000000000000000000000000000000000..3778863ac416f03e7ffff1dc69c13f35628e7e5c --- /dev/null +++ b/www/lib/crypto-js/hmac-sha224.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256"), require("./sha224"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256", "./sha224", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA224; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-sha256.js b/www/lib/crypto-js/hmac-sha256.js new file mode 100644 index 0000000000000000000000000000000000000000..33b0c9fec202fd6a2262ace762f4e32156eb4c40 --- /dev/null +++ b/www/lib/crypto-js/hmac-sha256.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA256; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-sha3.js b/www/lib/crypto-js/hmac-sha3.js new file mode 100644 index 0000000000000000000000000000000000000000..1248804966613af18ce1ab4d65f19edaef32e11e --- /dev/null +++ b/www/lib/crypto-js/hmac-sha3.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha3"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha3", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA3; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-sha384.js b/www/lib/crypto-js/hmac-sha384.js new file mode 100644 index 0000000000000000000000000000000000000000..0036e2b887c69f0ae89073354a3792b88c20dfdd --- /dev/null +++ b/www/lib/crypto-js/hmac-sha384.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./sha384"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha512", "./sha384", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA384; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac-sha512.js b/www/lib/crypto-js/hmac-sha512.js new file mode 100644 index 0000000000000000000000000000000000000000..c1005b6ac5223132073e0183e090c4c02eb9cb87 --- /dev/null +++ b/www/lib/crypto-js/hmac-sha512.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha512", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.HmacSHA512; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/hmac.js b/www/lib/crypto-js/hmac.js new file mode 100644 index 0000000000000000000000000000000000000000..8c098511429d0c01ebd7adb44df4acaacdf2ae25 --- /dev/null +++ b/www/lib/crypto-js/hmac.js @@ -0,0 +1,143 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var C_algo = C.algo; + + /** + * HMAC algorithm. + */ + var HMAC = C_algo.HMAC = Base.extend({ + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} hasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + init: function (hasher, key) { + // Init hasher + hasher = this._hasher = new hasher.init(); + + // Convert string to WordArray, else assume WordArray already + if (typeof key == 'string') { + key = Utf8.parse(key); + } + + // Shortcuts + var hasherBlockSize = hasher.blockSize; + var hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (key.sigBytes > hasherBlockSizeBytes) { + key = hasher.finalize(key); + } + + // Clamp excess bits + key.clamp(); + + // Clone key for inner and outer pads + var oKey = this._oKey = key.clone(); + var iKey = this._iKey = key.clone(); + + // Shortcuts + var oKeyWords = oKey.words; + var iKeyWords = iKey.words; + + // XOR keys with pad constants + for (var i = 0; i < hasherBlockSize; i++) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + }, + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset: function () { + // Shortcut + var hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + }, + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update: function (messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + }, + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Shortcut + var hasher = this._hasher; + + // Compute HMAC + var innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + var hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } + }); + }()); + + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/index.js b/www/lib/crypto-js/index.js new file mode 100644 index 0000000000000000000000000000000000000000..c93556a71598fddb82ab62ed06c5d51e44cdb1de --- /dev/null +++ b/www/lib/crypto-js/index.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./lib-typedarrays"), require("./enc-utf16"), require("./enc-base64"), require("./md5"), require("./sha1"), require("./sha256"), require("./sha224"), require("./sha512"), require("./sha384"), require("./sha3"), require("./ripemd160"), require("./hmac"), require("./pbkdf2"), require("./evpkdf"), require("./cipher-core"), require("./mode-cfb"), require("./mode-ctr"), require("./mode-ctr-gladman"), require("./mode-ofb"), require("./mode-ecb"), require("./pad-ansix923"), require("./pad-iso10126"), require("./pad-iso97971"), require("./pad-zeropadding"), require("./pad-nopadding"), require("./format-hex"), require("./aes"), require("./tripledes"), require("./rc4"), require("./rabbit"), require("./rabbit-legacy")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./lib-typedarrays", "./enc-utf16", "./enc-base64", "./md5", "./sha1", "./sha256", "./sha224", "./sha512", "./sha384", "./sha3", "./ripemd160", "./hmac", "./pbkdf2", "./evpkdf", "./cipher-core", "./mode-cfb", "./mode-ctr", "./mode-ctr-gladman", "./mode-ofb", "./mode-ecb", "./pad-ansix923", "./pad-iso10126", "./pad-iso97971", "./pad-zeropadding", "./pad-nopadding", "./format-hex", "./aes", "./tripledes", "./rc4", "./rabbit", "./rabbit-legacy"], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/lib-typedarrays.js b/www/lib/crypto-js/lib-typedarrays.js new file mode 100644 index 0000000000000000000000000000000000000000..264b210742682d09a07094f3ccda90064fb6b0cf --- /dev/null +++ b/www/lib/crypto-js/lib-typedarrays.js @@ -0,0 +1,76 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Check if typed arrays are supported + if (typeof ArrayBuffer != 'function') { + return; + } + + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + + // Reference original init + var superInit = WordArray.init; + + // Augment WordArray.init to handle typed arrays + var subInit = WordArray.init = function (typedArray) { + // Convert buffers to uint8 + if (typedArray instanceof ArrayBuffer) { + typedArray = new Uint8Array(typedArray); + } + + // Convert other array views to uint8 + if ( + typedArray instanceof Int8Array || + (typeof Uint8ClampedArray !== "undefined" && typedArray instanceof Uint8ClampedArray) || + typedArray instanceof Int16Array || + typedArray instanceof Uint16Array || + typedArray instanceof Int32Array || + typedArray instanceof Uint32Array || + typedArray instanceof Float32Array || + typedArray instanceof Float64Array + ) { + typedArray = new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + } + + // Handle Uint8Array + if (typedArray instanceof Uint8Array) { + // Shortcut + var typedArrayByteLength = typedArray.byteLength; + + // Extract bytes + var words = []; + for (var i = 0; i < typedArrayByteLength; i++) { + words[i >>> 2] |= typedArray[i] << (24 - (i % 4) * 8); + } + + // Initialize this word array + superInit.call(this, words, typedArrayByteLength); + } else { + // Else call normal init + superInit.apply(this, arguments); + } + }; + + subInit.prototype = WordArray; + }()); + + + return CryptoJS.lib.WordArray; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/md5.js b/www/lib/crypto-js/md5.js new file mode 100644 index 0000000000000000000000000000000000000000..12b0fdd4b4f00066c52969ead2bac439f668df2d --- /dev/null +++ b/www/lib/crypto-js/md5.js @@ -0,0 +1,268 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var T = []; + + // Compute constants + (function () { + for (var i = 0; i < 64; i++) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; + } + }()); + + /** + * MD5 hash algorithm. + */ + var MD5 = C_algo.MD5 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + var H = this._hash.words; + + var M_offset_0 = M[offset + 0]; + var M_offset_1 = M[offset + 1]; + var M_offset_2 = M[offset + 2]; + var M_offset_3 = M[offset + 3]; + var M_offset_4 = M[offset + 4]; + var M_offset_5 = M[offset + 5]; + var M_offset_6 = M[offset + 6]; + var M_offset_7 = M[offset + 7]; + var M_offset_8 = M[offset + 8]; + var M_offset_9 = M[offset + 9]; + var M_offset_10 = M[offset + 10]; + var M_offset_11 = M[offset + 11]; + var M_offset_12 = M[offset + 12]; + var M_offset_13 = M[offset + 13]; + var M_offset_14 = M[offset + 14]; + var M_offset_15 = M[offset + 15]; + + // Working varialbes + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + + var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + var nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | + (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | + (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 4; i++) { + // Shortcut + var H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + function FF(a, b, c, d, x, s, t) { + var n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function GG(a, b, c, d, x, s, t) { + var n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function HH(a, b, c, d, x, s, t) { + var n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function II(a, b, c, d, x, s, t) { + var n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ + C.MD5 = Hasher._createHelper(MD5); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ + C.HmacMD5 = Hasher._createHmacHelper(MD5); + }(Math)); + + + return CryptoJS.MD5; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/mode-cfb.js b/www/lib/crypto-js/mode-cfb.js new file mode 100644 index 0000000000000000000000000000000000000000..86231f1b3f1e376f25fb566e654e742f6f860d28 --- /dev/null +++ b/www/lib/crypto-js/mode-cfb.js @@ -0,0 +1,78 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Cipher Feedback block mode. + */ + CryptoJS.mode.CFB = (function () { + var CFB = CryptoJS.lib.BlockCipherMode.extend(); + + CFB.Encryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + CFB.Decryptor = CFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { + // Shortcut + var iv = this._iv; + + // Generate keystream + if (iv) { + var keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + var keystream = this._prevBlock; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + + return CFB; + }()); + + + return CryptoJS.mode.CFB; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/mode-ctr-gladman.js b/www/lib/crypto-js/mode-ctr-gladman.js new file mode 100644 index 0000000000000000000000000000000000000000..bbc56876e3cf854f7620aae07c2125eb3dbb19a5 --- /dev/null +++ b/www/lib/crypto-js/mode-ctr-gladman.js @@ -0,0 +1,116 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** @preserve + * Counter block mode compatible with Dr Brian Gladman fileenc.c + * derived from CryptoJS.mode.CTR + * Jan Hruby jhruby.web@gmail.com + */ + CryptoJS.mode.CTRGladman = (function () { + var CTRGladman = CryptoJS.lib.BlockCipherMode.extend(); + + function incWord(word) + { + if (((word >> 24) & 0xff) === 0xff) { //overflow + var b1 = (word >> 16)&0xff; + var b2 = (word >> 8)&0xff; + var b3 = word & 0xff; + + if (b1 === 0xff) // overflow b1 + { + b1 = 0; + if (b2 === 0xff) + { + b2 = 0; + if (b3 === 0xff) + { + b3 = 0; + } + else + { + ++b3; + } + } + else + { + ++b2; + } + } + else + { + ++b1; + } + + word = 0; + word += (b1 << 16); + word += (b2 << 8); + word += b3; + } + else + { + word += (0x01 << 24); + } + return word; + } + + function incCounter(counter) + { + if ((counter[0] = incWord(counter[0])) === 0) + { + // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 + counter[1] = incWord(counter[1]); + } + return counter; + } + + var Encryptor = CTRGladman.Encryptor = CTRGladman.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + + incCounter(counter); + + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTRGladman.Decryptor = Encryptor; + + return CTRGladman; + }()); + + + + + return CryptoJS.mode.CTRGladman; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/mode-ctr.js b/www/lib/crypto-js/mode-ctr.js new file mode 100644 index 0000000000000000000000000000000000000000..c3d470a6fac667465c5fe460a85bd3a7ad1c70a5 --- /dev/null +++ b/www/lib/crypto-js/mode-ctr.js @@ -0,0 +1,58 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Counter block mode. + */ + CryptoJS.mode.CTR = (function () { + var CTR = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = CTR.Encryptor = CTR.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var counter = this._counter; + + // Generate keystream + if (iv) { + counter = this._counter = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + var keystream = counter.slice(0); + cipher.encryptBlock(keystream, 0); + + // Increment counter + counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0 + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + CTR.Decryptor = Encryptor; + + return CTR; + }()); + + + return CryptoJS.mode.CTR; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/mode-ecb.js b/www/lib/crypto-js/mode-ecb.js new file mode 100644 index 0000000000000000000000000000000000000000..ff0692175b6dd588c023f25b10798ee25bd6d374 --- /dev/null +++ b/www/lib/crypto-js/mode-ecb.js @@ -0,0 +1,40 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Electronic Codebook block mode. + */ + CryptoJS.mode.ECB = (function () { + var ECB = CryptoJS.lib.BlockCipherMode.extend(); + + ECB.Encryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.encryptBlock(words, offset); + } + }); + + ECB.Decryptor = ECB.extend({ + processBlock: function (words, offset) { + this._cipher.decryptBlock(words, offset); + } + }); + + return ECB; + }()); + + + return CryptoJS.mode.ECB; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/mode-ofb.js b/www/lib/crypto-js/mode-ofb.js new file mode 100644 index 0000000000000000000000000000000000000000..c01314c2284da6d92910ccb4d98e76f5e5fe1564 --- /dev/null +++ b/www/lib/crypto-js/mode-ofb.js @@ -0,0 +1,54 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Output Feedback block mode. + */ + CryptoJS.mode.OFB = (function () { + var OFB = CryptoJS.lib.BlockCipherMode.extend(); + + var Encryptor = OFB.Encryptor = OFB.extend({ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher + var blockSize = cipher.blockSize; + var iv = this._iv; + var keystream = this._keystream; + + // Generate keystream + if (iv) { + keystream = this._keystream = iv.slice(0); + + // Remove IV for subsequent blocks + this._iv = undefined; + } + cipher.encryptBlock(keystream, 0); + + // Encrypt + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= keystream[i]; + } + } + }); + + OFB.Decryptor = Encryptor; + + return OFB; + }()); + + + return CryptoJS.mode.OFB; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/package.json b/www/lib/crypto-js/package.json new file mode 100644 index 0000000000000000000000000000000000000000..6cfc41d6c383a5bf9cfa1d9c61c4be07527736fe --- /dev/null +++ b/www/lib/crypto-js/package.json @@ -0,0 +1,38 @@ +{ + "name": "crypto-js", + "version": "3.1.6", + "description": "JavaScript library of crypto standards.", + "license": "MIT", + "author": { + "name": "Evan Vosberg", + "url": "http://github.com/evanvosberg" + }, + "homepage": "http://github.com/brix/crypto-js", + "repository": { + "type": "git", + "url": "http://github.com/brix/crypto-js.git" + }, + "keywords": [ + "security", + "crypto", + "Hash", + "MD5", + "SHA1", + "SHA-1", + "SHA256", + "SHA-256", + "RC4", + "Rabbit", + "AES", + "DES", + "PBKDF2", + "HMAC", + "OFB", + "CFB", + "CTR", + "CBC", + "Base64" + ], + "main": "index.js", + "dependencies": {} +} diff --git a/www/lib/crypto-js/pad-ansix923.js b/www/lib/crypto-js/pad-ansix923.js new file mode 100644 index 0000000000000000000000000000000000000000..f01f21e45cc2e54e78fe9968a42e4e0f9c5372e1 --- /dev/null +++ b/www/lib/crypto-js/pad-ansix923.js @@ -0,0 +1,49 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ANSI X.923 padding strategy. + */ + CryptoJS.pad.AnsiX923 = { + pad: function (data, blockSize) { + // Shortcuts + var dataSigBytes = data.sigBytes; + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - dataSigBytes % blockSizeBytes; + + // Compute last byte position + var lastBytePos = dataSigBytes + nPaddingBytes - 1; + + // Pad + data.clamp(); + data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); + data.sigBytes += nPaddingBytes; + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + return CryptoJS.pad.Ansix923; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/pad-iso10126.js b/www/lib/crypto-js/pad-iso10126.js new file mode 100644 index 0000000000000000000000000000000000000000..6e2aefd8394228ed4573b4294ff7f7a6a65649f1 --- /dev/null +++ b/www/lib/crypto-js/pad-iso10126.js @@ -0,0 +1,44 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ISO 10126 padding strategy. + */ + CryptoJS.pad.Iso10126 = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Pad + data.concat(CryptoJS.lib.WordArray.random(nPaddingBytes - 1)). + concat(CryptoJS.lib.WordArray.create([nPaddingBytes << 24], 1)); + }, + + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + + return CryptoJS.pad.Iso10126; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/pad-iso97971.js b/www/lib/crypto-js/pad-iso97971.js new file mode 100644 index 0000000000000000000000000000000000000000..41049b45fc335ce11af619c9af5622fc5cda4621 --- /dev/null +++ b/www/lib/crypto-js/pad-iso97971.js @@ -0,0 +1,40 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * ISO/IEC 9797-1 Padding Method 2. + */ + CryptoJS.pad.Iso97971 = { + pad: function (data, blockSize) { + // Add 0x80 byte + data.concat(CryptoJS.lib.WordArray.create([0x80000000], 1)); + + // Zero pad the rest + CryptoJS.pad.ZeroPadding.pad(data, blockSize); + }, + + unpad: function (data) { + // Remove zero padding + CryptoJS.pad.ZeroPadding.unpad(data); + + // Remove one more byte -- the 0x80 byte + data.sigBytes--; + } + }; + + + return CryptoJS.pad.Iso97971; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/pad-nopadding.js b/www/lib/crypto-js/pad-nopadding.js new file mode 100644 index 0000000000000000000000000000000000000000..c7787c94d2e01d979ba45d2163b90ed05e902e35 --- /dev/null +++ b/www/lib/crypto-js/pad-nopadding.js @@ -0,0 +1,30 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * A noop padding strategy. + */ + CryptoJS.pad.NoPadding = { + pad: function () { + }, + + unpad: function () { + } + }; + + + return CryptoJS.pad.NoPadding; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/pad-pkcs7.js b/www/lib/crypto-js/pad-pkcs7.js new file mode 100644 index 0000000000000000000000000000000000000000..3555168566e57e7baf9e13cdd48002ed92f8ea3e --- /dev/null +++ b/www/lib/crypto-js/pad-pkcs7.js @@ -0,0 +1,18 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.pad.Pkcs7; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/pad-zeropadding.js b/www/lib/crypto-js/pad-zeropadding.js new file mode 100644 index 0000000000000000000000000000000000000000..0e8a859cfdcf13f16127ff18e7988e2c4f745a5b --- /dev/null +++ b/www/lib/crypto-js/pad-zeropadding.js @@ -0,0 +1,45 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Zero padding strategy. + */ + CryptoJS.pad.ZeroPadding = { + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Pad + data.clamp(); + data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); + }, + + unpad: function (data) { + // Shortcut + var dataWords = data.words; + + // Unpad + var i = data.sigBytes - 1; + while (!((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { + i--; + } + data.sigBytes = i + 1; + } + }; + + + return CryptoJS.pad.ZeroPadding; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/pbkdf2.js b/www/lib/crypto-js/pbkdf2.js new file mode 100644 index 0000000000000000000000000000000000000000..1258251a58f9c46b68d9d7552680fa2010c25704 --- /dev/null +++ b/www/lib/crypto-js/pbkdf2.js @@ -0,0 +1,145 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha1", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA1 = C_algo.SHA1; + var HMAC = C_algo.HMAC; + + /** + * Password-Based Key Derivation Function 2 algorithm. + */ + var PBKDF2 = C_algo.PBKDF2 = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hasher to use. Default: SHA1 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: SHA1, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.PBKDF2.create(); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.PBKDF2.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init HMAC + var hmac = HMAC.create(cfg.hasher, password); + + // Initial values + var derivedKey = WordArray.create(); + var blockIndex = WordArray.create([0x00000001]); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var blockIndexWords = blockIndex.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + var block = hmac.update(salt).finalize(blockIndex); + hmac.reset(); + + // Shortcuts + var blockWords = block.words; + var blockWordsLength = blockWords.length; + + // Iterations + var intermediate = block; + for (var i = 1; i < iterations; i++) { + intermediate = hmac.finalize(intermediate); + hmac.reset(); + + // Shortcut + var intermediateWords = intermediate.words; + + // XOR intermediate with block + for (var j = 0; j < blockWordsLength; j++) { + blockWords[j] ^= intermediateWords[j]; + } + } + + derivedKey.concat(block); + blockIndexWords[0]++; + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Computes the Password-Based Key Derivation Function 2. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.PBKDF2(password, salt); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8 }); + * var key = CryptoJS.PBKDF2(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.PBKDF2 = function (password, salt, cfg) { + return PBKDF2.create(cfg).compute(password, salt); + }; + }()); + + + return CryptoJS.PBKDF2; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/rabbit-legacy.js b/www/lib/crypto-js/rabbit-legacy.js new file mode 100644 index 0000000000000000000000000000000000000000..e118b6b6a28b3ddc6d1547e42f16f8f34715e486 --- /dev/null +++ b/www/lib/crypto-js/rabbit-legacy.js @@ -0,0 +1,190 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm. + * + * This is a legacy version that neglected to convert the key to little-endian. + * This error doesn't affect the cipher's security, + * but it does affect its compatibility with other implementations. + */ + var RabbitLegacy = C_algo.RabbitLegacy = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RabbitLegacy.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RabbitLegacy.decrypt(ciphertext, key, cfg); + */ + C.RabbitLegacy = StreamCipher._createHelper(RabbitLegacy); + }()); + + + return CryptoJS.RabbitLegacy; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/rabbit.js b/www/lib/crypto-js/rabbit.js new file mode 100644 index 0000000000000000000000000000000000000000..1b0683362026c7143324e142515310e6f80fde00 --- /dev/null +++ b/www/lib/crypto-js/rabbit.js @@ -0,0 +1,192 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + // Reusable objects + var S = []; + var C_ = []; + var G = []; + + /** + * Rabbit stream cipher algorithm + */ + var Rabbit = C_algo.Rabbit = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var K = this._key.words; + var iv = this.cfg.iv; + + // Swap endian + for (var i = 0; i < 4; i++) { + K[i] = (((K[i] << 8) | (K[i] >>> 24)) & 0x00ff00ff) | + (((K[i] << 24) | (K[i] >>> 8)) & 0xff00ff00); + } + + // Generate initial state values + var X = this._X = [ + K[0], (K[3] << 16) | (K[2] >>> 16), + K[1], (K[0] << 16) | (K[3] >>> 16), + K[2], (K[1] << 16) | (K[0] >>> 16), + K[3], (K[2] << 16) | (K[1] >>> 16) + ]; + + // Generate initial counter values + var C = this._C = [ + (K[2] << 16) | (K[2] >>> 16), (K[0] & 0xffff0000) | (K[1] & 0x0000ffff), + (K[3] << 16) | (K[3] >>> 16), (K[1] & 0xffff0000) | (K[2] & 0x0000ffff), + (K[0] << 16) | (K[0] >>> 16), (K[2] & 0xffff0000) | (K[3] & 0x0000ffff), + (K[1] << 16) | (K[1] >>> 16), (K[3] & 0xffff0000) | (K[0] & 0x0000ffff) + ]; + + // Carry bit + this._b = 0; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + + // Modify the counters + for (var i = 0; i < 8; i++) { + C[i] ^= X[(i + 4) & 7]; + } + + // IV setup + if (iv) { + // Shortcuts + var IV = iv.words; + var IV_0 = IV[0]; + var IV_1 = IV[1]; + + // Generate four subvectors + var i0 = (((IV_0 << 8) | (IV_0 >>> 24)) & 0x00ff00ff) | (((IV_0 << 24) | (IV_0 >>> 8)) & 0xff00ff00); + var i2 = (((IV_1 << 8) | (IV_1 >>> 24)) & 0x00ff00ff) | (((IV_1 << 24) | (IV_1 >>> 8)) & 0xff00ff00); + var i1 = (i0 >>> 16) | (i2 & 0xffff0000); + var i3 = (i2 << 16) | (i0 & 0x0000ffff); + + // Modify counter values + C[0] ^= i0; + C[1] ^= i1; + C[2] ^= i2; + C[3] ^= i3; + C[4] ^= i0; + C[5] ^= i1; + C[6] ^= i2; + C[7] ^= i3; + + // Iterate the system four times + for (var i = 0; i < 4; i++) { + nextState.call(this); + } + } + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var X = this._X; + + // Iterate the system + nextState.call(this); + + // Generate four keystream words + S[0] = X[0] ^ (X[5] >>> 16) ^ (X[3] << 16); + S[1] = X[2] ^ (X[7] >>> 16) ^ (X[5] << 16); + S[2] = X[4] ^ (X[1] >>> 16) ^ (X[7] << 16); + S[3] = X[6] ^ (X[3] >>> 16) ^ (X[1] << 16); + + for (var i = 0; i < 4; i++) { + // Swap endian + S[i] = (((S[i] << 8) | (S[i] >>> 24)) & 0x00ff00ff) | + (((S[i] << 24) | (S[i] >>> 8)) & 0xff00ff00); + + // Encrypt + M[offset + i] ^= S[i]; + } + }, + + blockSize: 128/32, + + ivSize: 64/32 + }); + + function nextState() { + // Shortcuts + var X = this._X; + var C = this._C; + + // Save old counter values + for (var i = 0; i < 8; i++) { + C_[i] = C[i]; + } + + // Calculate new counter values + C[0] = (C[0] + 0x4d34d34d + this._b) | 0; + C[1] = (C[1] + 0xd34d34d3 + ((C[0] >>> 0) < (C_[0] >>> 0) ? 1 : 0)) | 0; + C[2] = (C[2] + 0x34d34d34 + ((C[1] >>> 0) < (C_[1] >>> 0) ? 1 : 0)) | 0; + C[3] = (C[3] + 0x4d34d34d + ((C[2] >>> 0) < (C_[2] >>> 0) ? 1 : 0)) | 0; + C[4] = (C[4] + 0xd34d34d3 + ((C[3] >>> 0) < (C_[3] >>> 0) ? 1 : 0)) | 0; + C[5] = (C[5] + 0x34d34d34 + ((C[4] >>> 0) < (C_[4] >>> 0) ? 1 : 0)) | 0; + C[6] = (C[6] + 0x4d34d34d + ((C[5] >>> 0) < (C_[5] >>> 0) ? 1 : 0)) | 0; + C[7] = (C[7] + 0xd34d34d3 + ((C[6] >>> 0) < (C_[6] >>> 0) ? 1 : 0)) | 0; + this._b = (C[7] >>> 0) < (C_[7] >>> 0) ? 1 : 0; + + // Calculate the g-values + for (var i = 0; i < 8; i++) { + var gx = X[i] + C[i]; + + // Construct high and low argument for squaring + var ga = gx & 0xffff; + var gb = gx >>> 16; + + // Calculate high and low result of squaring + var gh = ((((ga * ga) >>> 17) + ga * gb) >>> 15) + gb * gb; + var gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); + + // High XOR low + G[i] = gh ^ gl; + } + + // Calculate new state values + X[0] = (G[0] + ((G[7] << 16) | (G[7] >>> 16)) + ((G[6] << 16) | (G[6] >>> 16))) | 0; + X[1] = (G[1] + ((G[0] << 8) | (G[0] >>> 24)) + G[7]) | 0; + X[2] = (G[2] + ((G[1] << 16) | (G[1] >>> 16)) + ((G[0] << 16) | (G[0] >>> 16))) | 0; + X[3] = (G[3] + ((G[2] << 8) | (G[2] >>> 24)) + G[1]) | 0; + X[4] = (G[4] + ((G[3] << 16) | (G[3] >>> 16)) + ((G[2] << 16) | (G[2] >>> 16))) | 0; + X[5] = (G[5] + ((G[4] << 8) | (G[4] >>> 24)) + G[3]) | 0; + X[6] = (G[6] + ((G[5] << 16) | (G[5] >>> 16)) + ((G[4] << 16) | (G[4] >>> 16))) | 0; + X[7] = (G[7] + ((G[6] << 8) | (G[6] >>> 24)) + G[5]) | 0; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.Rabbit.encrypt(message, key, cfg); + * var plaintext = CryptoJS.Rabbit.decrypt(ciphertext, key, cfg); + */ + C.Rabbit = StreamCipher._createHelper(Rabbit); + }()); + + + return CryptoJS.Rabbit; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/rc4.js b/www/lib/crypto-js/rc4.js new file mode 100644 index 0000000000000000000000000000000000000000..0e4bdff517f01602ac862305889b2fbaeee1bf36 --- /dev/null +++ b/www/lib/crypto-js/rc4.js @@ -0,0 +1,139 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var StreamCipher = C_lib.StreamCipher; + var C_algo = C.algo; + + /** + * RC4 stream cipher algorithm. + */ + var RC4 = C_algo.RC4 = StreamCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + var keySigBytes = key.sigBytes; + + // Init sbox + var S = this._S = []; + for (var i = 0; i < 256; i++) { + S[i] = i; + } + + // Key setup + for (var i = 0, j = 0; i < 256; i++) { + var keyByteIndex = i % keySigBytes; + var keyByte = (keyWords[keyByteIndex >>> 2] >>> (24 - (keyByteIndex % 4) * 8)) & 0xff; + + j = (j + S[i] + keyByte) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + } + + // Counters + this._i = this._j = 0; + }, + + _doProcessBlock: function (M, offset) { + M[offset] ^= generateKeystreamWord.call(this); + }, + + keySize: 256/32, + + ivSize: 0 + }); + + function generateKeystreamWord() { + // Shortcuts + var S = this._S; + var i = this._i; + var j = this._j; + + // Generate keystream word + var keystreamWord = 0; + for (var n = 0; n < 4; n++) { + i = (i + 1) % 256; + j = (j + S[i]) % 256; + + // Swap + var t = S[i]; + S[i] = S[j]; + S[j] = t; + + keystreamWord |= S[(S[i] + S[j]) % 256] << (24 - n * 8); + } + + // Update counters + this._i = i; + this._j = j; + + return keystreamWord; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4.decrypt(ciphertext, key, cfg); + */ + C.RC4 = StreamCipher._createHelper(RC4); + + /** + * Modified RC4 stream cipher algorithm. + */ + var RC4Drop = C_algo.RC4Drop = RC4.extend({ + /** + * Configuration options. + * + * @property {number} drop The number of keystream words to drop. Default 192 + */ + cfg: RC4.cfg.extend({ + drop: 192 + }), + + _doReset: function () { + RC4._doReset.call(this); + + // Drop + for (var i = this.cfg.drop; i > 0; i--) { + generateKeystreamWord.call(this); + } + } + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.RC4Drop.encrypt(message, key, cfg); + * var plaintext = CryptoJS.RC4Drop.decrypt(ciphertext, key, cfg); + */ + C.RC4Drop = StreamCipher._createHelper(RC4Drop); + }()); + + + return CryptoJS.RC4; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/ripemd160.js b/www/lib/crypto-js/ripemd160.js new file mode 100644 index 0000000000000000000000000000000000000000..24feb47c75f2ba14079a0fe0b2ec44e7bfc5f8b3 --- /dev/null +++ b/www/lib/crypto-js/ripemd160.js @@ -0,0 +1,267 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** @preserve + (c) 2012 by Cédric Mesnil. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var _zl = WordArray.create([ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13]); + var _zr = WordArray.create([ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]); + var _sl = WordArray.create([ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ]); + var _sr = WordArray.create([ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ]); + + var _hl = WordArray.create([ 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E]); + var _hr = WordArray.create([ 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000]); + + /** + * RIPEMD160 hash algorithm. + */ + var RIPEMD160 = C_algo.RIPEMD160 = Hasher.extend({ + _doReset: function () { + this._hash = WordArray.create([0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]); + }, + + _doProcessBlock: function (M, offset) { + + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + // Swap + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + // Shortcut + var H = this._hash.words; + var hl = _hl.words; + var hr = _hr.words; + var zl = _zl.words; + var zr = _zr.words; + var sl = _sl.words; + var sr = _sr.words; + + // Working variables + var al, bl, cl, dl, el; + var ar, br, cr, dr, er; + + ar = al = H[0]; + br = bl = H[1]; + cr = cl = H[2]; + dr = dl = H[3]; + er = el = H[4]; + // Computation + var t; + for (var i = 0; i < 80; i += 1) { + t = (al + M[offset+zl[i]])|0; + if (i<16){ + t += f1(bl,cl,dl) + hl[0]; + } else if (i<32) { + t += f2(bl,cl,dl) + hl[1]; + } else if (i<48) { + t += f3(bl,cl,dl) + hl[2]; + } else if (i<64) { + t += f4(bl,cl,dl) + hl[3]; + } else {// if (i<80) { + t += f5(bl,cl,dl) + hl[4]; + } + t = t|0; + t = rotl(t,sl[i]); + t = (t+el)|0; + al = el; + el = dl; + dl = rotl(cl, 10); + cl = bl; + bl = t; + + t = (ar + M[offset+zr[i]])|0; + if (i<16){ + t += f5(br,cr,dr) + hr[0]; + } else if (i<32) { + t += f4(br,cr,dr) + hr[1]; + } else if (i<48) { + t += f3(br,cr,dr) + hr[2]; + } else if (i<64) { + t += f2(br,cr,dr) + hr[3]; + } else {// if (i<80) { + t += f1(br,cr,dr) + hr[4]; + } + t = t|0; + t = rotl(t,sr[i]) ; + t = (t+er)|0; + ar = er; + er = dr; + dr = rotl(cr, 10); + cr = br; + br = t; + } + // Intermediate hash value + t = (H[1] + cl + dr)|0; + H[1] = (H[2] + dl + er)|0; + H[2] = (H[3] + el + ar)|0; + H[3] = (H[4] + al + br)|0; + H[4] = (H[0] + bl + cr)|0; + H[0] = t; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotal << 8) | (nBitsTotal >>> 24)) & 0x00ff00ff) | + (((nBitsTotal << 24) | (nBitsTotal >>> 8)) & 0xff00ff00) + ); + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 5; i++) { + // Shortcut + var H_i = H[i]; + + // Swap + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + + function f1(x, y, z) { + return ((x) ^ (y) ^ (z)); + + } + + function f2(x, y, z) { + return (((x)&(y)) | ((~x)&(z))); + } + + function f3(x, y, z) { + return (((x) | (~(y))) ^ (z)); + } + + function f4(x, y, z) { + return (((x) & (z)) | ((y)&(~(z)))); + } + + function f5(x, y, z) { + return ((x) ^ ((y) |(~(z)))); + + } + + function rotl(x,n) { + return (x<<n) | (x>>>(32-n)); + } + + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.RIPEMD160('message'); + * var hash = CryptoJS.RIPEMD160(wordArray); + */ + C.RIPEMD160 = Hasher._createHelper(RIPEMD160); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacRIPEMD160(message, key); + */ + C.HmacRIPEMD160 = Hasher._createHmacHelper(RIPEMD160); + }(Math)); + + + return CryptoJS.RIPEMD160; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/sha1.js b/www/lib/crypto-js/sha1.js new file mode 100644 index 0000000000000000000000000000000000000000..669114962a3ffcaebcf98cff345d2043f6ae5e45 --- /dev/null +++ b/www/lib/crypto-js/sha1.js @@ -0,0 +1,150 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Reusable object + var W = []; + + /** + * SHA-1 hash algorithm. + */ + var SHA1 = C_algo.SHA1 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476, + 0xc3d2e1f0 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + + // Computation + for (var i = 0; i < 80; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + var t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ + C.SHA1 = Hasher._createHelper(SHA1); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ + C.HmacSHA1 = Hasher._createHmacHelper(SHA1); + }()); + + + return CryptoJS.SHA1; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/sha224.js b/www/lib/crypto-js/sha224.js new file mode 100644 index 0000000000000000000000000000000000000000..d8ce9885268313ae356a655ed641c71f5163c4f2 --- /dev/null +++ b/www/lib/crypto-js/sha224.js @@ -0,0 +1,80 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha256")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha256"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var SHA256 = C_algo.SHA256; + + /** + * SHA-224 hash algorithm. + */ + var SHA224 = C_algo.SHA224 = SHA256.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 + ]); + }, + + _doFinalize: function () { + var hash = SHA256._doFinalize.call(this); + + hash.sigBytes -= 4; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA224('message'); + * var hash = CryptoJS.SHA224(wordArray); + */ + C.SHA224 = SHA256._createHelper(SHA224); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA224(message, key); + */ + C.HmacSHA224 = SHA256._createHmacHelper(SHA224); + }()); + + + return CryptoJS.SHA224; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/sha256.js b/www/lib/crypto-js/sha256.js new file mode 100644 index 0000000000000000000000000000000000000000..de2d7fca1019d0e23a0f85055f28aaf51b7e0f21 --- /dev/null +++ b/www/lib/crypto-js/sha256.js @@ -0,0 +1,199 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Initialization and round constants tables + var H = []; + var K = []; + + // Compute constants + (function () { + function isPrime(n) { + var sqrtN = Math.sqrt(n); + for (var factor = 2; factor <= sqrtN; factor++) { + if (!(n % factor)) { + return false; + } + } + + return true; + } + + function getFractionalBits(n) { + return ((n - (n | 0)) * 0x100000000) | 0; + } + + var n = 2; + var nPrime = 0; + while (nPrime < 64) { + if (isPrime(n)) { + if (nPrime < 8) { + H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2)); + } + K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3)); + + nPrime++; + } + + n++; + } + }()); + + // Reusable object + var W = []; + + /** + * SHA-256 hash algorithm. + */ + var SHA256 = C_algo.SHA256 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init(H.slice(0)); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + var f = H[5]; + var g = H[6]; + var h = H[7]; + + // Computation + for (var i = 0; i < 64; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var gamma0x = W[i - 15]; + var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ + ((gamma0x << 14) | (gamma0x >>> 18)) ^ + (gamma0x >>> 3); + + var gamma1x = W[i - 2]; + var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ + ((gamma1x << 13) | (gamma1x >>> 19)) ^ + (gamma1x >>> 10); + + W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; + } + + var ch = (e & f) ^ (~e & g); + var maj = (a & b) ^ (a & c) ^ (b & c); + + var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22)); + var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25)); + + var t1 = h + sigma1 + ch + K[i] + W[i]; + var t2 = sigma0 + maj; + + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + H[5] = (H[5] + f) | 0; + H[6] = (H[6] + g) | 0; + H[7] = (H[7] + h) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA256('message'); + * var hash = CryptoJS.SHA256(wordArray); + */ + C.SHA256 = Hasher._createHelper(SHA256); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA256(message, key); + */ + C.HmacSHA256 = Hasher._createHmacHelper(SHA256); + }(Math)); + + + return CryptoJS.SHA256; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/sha3.js b/www/lib/crypto-js/sha3.js new file mode 100644 index 0000000000000000000000000000000000000000..4fb27fe45e180331a225ada078d3311bab123bc8 --- /dev/null +++ b/www/lib/crypto-js/sha3.js @@ -0,0 +1,323 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var C_algo = C.algo; + + // Constants tables + var RHO_OFFSETS = []; + var PI_INDEXES = []; + var ROUND_CONSTANTS = []; + + // Compute Constants + (function () { + // Compute rho offset constants + var x = 1, y = 0; + for (var t = 0; t < 24; t++) { + RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64; + + var newX = y % 5; + var newY = (2 * x + 3 * y) % 5; + x = newX; + y = newY; + } + + // Compute pi index constants + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5; + } + } + + // Compute round constants + var LFSR = 0x01; + for (var i = 0; i < 24; i++) { + var roundConstantMsw = 0; + var roundConstantLsw = 0; + + for (var j = 0; j < 7; j++) { + if (LFSR & 0x01) { + var bitPosition = (1 << j) - 1; + if (bitPosition < 32) { + roundConstantLsw ^= 1 << bitPosition; + } else /* if (bitPosition >= 32) */ { + roundConstantMsw ^= 1 << (bitPosition - 32); + } + } + + // Compute next LFSR + if (LFSR & 0x80) { + // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1 + LFSR = (LFSR << 1) ^ 0x71; + } else { + LFSR <<= 1; + } + } + + ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw); + } + }()); + + // Reusable objects for temporary values + var T = []; + (function () { + for (var i = 0; i < 25; i++) { + T[i] = X64Word.create(); + } + }()); + + /** + * SHA-3 hash algorithm. + */ + var SHA3 = C_algo.SHA3 = Hasher.extend({ + /** + * Configuration options. + * + * @property {number} outputLength + * The desired number of bits in the output hash. + * Only values permitted are: 224, 256, 384, 512. + * Default: 512 + */ + cfg: Hasher.cfg.extend({ + outputLength: 512 + }), + + _doReset: function () { + var state = this._state = [] + for (var i = 0; i < 25; i++) { + state[i] = new X64Word.init(); + } + + this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32; + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var state = this._state; + var nBlockSizeLanes = this.blockSize / 2; + + // Absorb + for (var i = 0; i < nBlockSizeLanes; i++) { + // Shortcuts + var M2i = M[offset + 2 * i]; + var M2i1 = M[offset + 2 * i + 1]; + + // Swap endian + M2i = ( + (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) | + (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00) + ); + M2i1 = ( + (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) | + (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00) + ); + + // Absorb message into state + var lane = state[i]; + lane.high ^= M2i1; + lane.low ^= M2i; + } + + // Rounds + for (var round = 0; round < 24; round++) { + // Theta + for (var x = 0; x < 5; x++) { + // Mix column lanes + var tMsw = 0, tLsw = 0; + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + tMsw ^= lane.high; + tLsw ^= lane.low; + } + + // Temporary values + var Tx = T[x]; + Tx.high = tMsw; + Tx.low = tLsw; + } + for (var x = 0; x < 5; x++) { + // Shortcuts + var Tx4 = T[(x + 4) % 5]; + var Tx1 = T[(x + 1) % 5]; + var Tx1Msw = Tx1.high; + var Tx1Lsw = Tx1.low; + + // Mix surrounding columns + var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31)); + var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31)); + for (var y = 0; y < 5; y++) { + var lane = state[x + 5 * y]; + lane.high ^= tMsw; + lane.low ^= tLsw; + } + } + + // Rho Pi + for (var laneIndex = 1; laneIndex < 25; laneIndex++) { + // Shortcuts + var lane = state[laneIndex]; + var laneMsw = lane.high; + var laneLsw = lane.low; + var rhoOffset = RHO_OFFSETS[laneIndex]; + + // Rotate lanes + if (rhoOffset < 32) { + var tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset)); + var tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset)); + } else /* if (rhoOffset >= 32) */ { + var tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset)); + var tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset)); + } + + // Transpose lanes + var TPiLane = T[PI_INDEXES[laneIndex]]; + TPiLane.high = tMsw; + TPiLane.low = tLsw; + } + + // Rho pi at x = y = 0 + var T0 = T[0]; + var state0 = state[0]; + T0.high = state0.high; + T0.low = state0.low; + + // Chi + for (var x = 0; x < 5; x++) { + for (var y = 0; y < 5; y++) { + // Shortcuts + var laneIndex = x + 5 * y; + var lane = state[laneIndex]; + var TLane = T[laneIndex]; + var Tx1Lane = T[((x + 1) % 5) + 5 * y]; + var Tx2Lane = T[((x + 2) % 5) + 5 * y]; + + // Mix rows + lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high); + lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low); + } + } + + // Iota + var lane = state[0]; + var roundConstant = ROUND_CONSTANTS[round]; + lane.high ^= roundConstant.high; + lane.low ^= roundConstant.low;; + } + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + var blockSizeBits = this.blockSize * 32; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32); + dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var state = this._state; + var outputLengthBytes = this.cfg.outputLength / 8; + var outputLengthLanes = outputLengthBytes / 8; + + // Squeeze + var hashWords = []; + for (var i = 0; i < outputLengthLanes; i++) { + // Shortcuts + var lane = state[i]; + var laneMsw = lane.high; + var laneLsw = lane.low; + + // Swap endian + laneMsw = ( + (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) | + (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00) + ); + laneLsw = ( + (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) | + (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00) + ); + + // Squeeze state to retrieve hash + hashWords.push(laneLsw); + hashWords.push(laneMsw); + } + + // Return final computed hash + return new WordArray.init(hashWords, outputLengthBytes); + }, + + clone: function () { + var clone = Hasher.clone.call(this); + + var state = clone._state = this._state.slice(0); + for (var i = 0; i < 25; i++) { + state[i] = state[i].clone(); + } + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA3('message'); + * var hash = CryptoJS.SHA3(wordArray); + */ + C.SHA3 = Hasher._createHelper(SHA3); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA3(message, key); + */ + C.HmacSHA3 = Hasher._createHmacHelper(SHA3); + }(Math)); + + + return CryptoJS.SHA3; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/sha384.js b/www/lib/crypto-js/sha384.js new file mode 100644 index 0000000000000000000000000000000000000000..a0b95bf6328b2dae9d44554f35dfce7c82d57407 --- /dev/null +++ b/www/lib/crypto-js/sha384.js @@ -0,0 +1,83 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core"), require("./sha512")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core", "./sha512"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + var SHA512 = C_algo.SHA512; + + /** + * SHA-384 hash algorithm. + */ + var SHA384 = C_algo.SHA384 = SHA512.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0xcbbb9d5d, 0xc1059ed8), new X64Word.init(0x629a292a, 0x367cd507), + new X64Word.init(0x9159015a, 0x3070dd17), new X64Word.init(0x152fecd8, 0xf70e5939), + new X64Word.init(0x67332667, 0xffc00b31), new X64Word.init(0x8eb44a87, 0x68581511), + new X64Word.init(0xdb0c2e0d, 0x64f98fa7), new X64Word.init(0x47b5481d, 0xbefa4fa4) + ]); + }, + + _doFinalize: function () { + var hash = SHA512._doFinalize.call(this); + + hash.sigBytes -= 16; + + return hash; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA384('message'); + * var hash = CryptoJS.SHA384(wordArray); + */ + C.SHA384 = SHA512._createHelper(SHA384); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA384(message, key); + */ + C.HmacSHA384 = SHA512._createHmacHelper(SHA384); + }()); + + + return CryptoJS.SHA384; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/sha512.js b/www/lib/crypto-js/sha512.js new file mode 100644 index 0000000000000000000000000000000000000000..335931585567e61d38c9fd4e1dfa96d3008051e1 --- /dev/null +++ b/www/lib/crypto-js/sha512.js @@ -0,0 +1,323 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./x64-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./x64-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Hasher = C_lib.Hasher; + var C_x64 = C.x64; + var X64Word = C_x64.Word; + var X64WordArray = C_x64.WordArray; + var C_algo = C.algo; + + function X64Word_create() { + return X64Word.create.apply(X64Word, arguments); + } + + // Constants + var K = [ + X64Word_create(0x428a2f98, 0xd728ae22), X64Word_create(0x71374491, 0x23ef65cd), + X64Word_create(0xb5c0fbcf, 0xec4d3b2f), X64Word_create(0xe9b5dba5, 0x8189dbbc), + X64Word_create(0x3956c25b, 0xf348b538), X64Word_create(0x59f111f1, 0xb605d019), + X64Word_create(0x923f82a4, 0xaf194f9b), X64Word_create(0xab1c5ed5, 0xda6d8118), + X64Word_create(0xd807aa98, 0xa3030242), X64Word_create(0x12835b01, 0x45706fbe), + X64Word_create(0x243185be, 0x4ee4b28c), X64Word_create(0x550c7dc3, 0xd5ffb4e2), + X64Word_create(0x72be5d74, 0xf27b896f), X64Word_create(0x80deb1fe, 0x3b1696b1), + X64Word_create(0x9bdc06a7, 0x25c71235), X64Word_create(0xc19bf174, 0xcf692694), + X64Word_create(0xe49b69c1, 0x9ef14ad2), X64Word_create(0xefbe4786, 0x384f25e3), + X64Word_create(0x0fc19dc6, 0x8b8cd5b5), X64Word_create(0x240ca1cc, 0x77ac9c65), + X64Word_create(0x2de92c6f, 0x592b0275), X64Word_create(0x4a7484aa, 0x6ea6e483), + X64Word_create(0x5cb0a9dc, 0xbd41fbd4), X64Word_create(0x76f988da, 0x831153b5), + X64Word_create(0x983e5152, 0xee66dfab), X64Word_create(0xa831c66d, 0x2db43210), + X64Word_create(0xb00327c8, 0x98fb213f), X64Word_create(0xbf597fc7, 0xbeef0ee4), + X64Word_create(0xc6e00bf3, 0x3da88fc2), X64Word_create(0xd5a79147, 0x930aa725), + X64Word_create(0x06ca6351, 0xe003826f), X64Word_create(0x14292967, 0x0a0e6e70), + X64Word_create(0x27b70a85, 0x46d22ffc), X64Word_create(0x2e1b2138, 0x5c26c926), + X64Word_create(0x4d2c6dfc, 0x5ac42aed), X64Word_create(0x53380d13, 0x9d95b3df), + X64Word_create(0x650a7354, 0x8baf63de), X64Word_create(0x766a0abb, 0x3c77b2a8), + X64Word_create(0x81c2c92e, 0x47edaee6), X64Word_create(0x92722c85, 0x1482353b), + X64Word_create(0xa2bfe8a1, 0x4cf10364), X64Word_create(0xa81a664b, 0xbc423001), + X64Word_create(0xc24b8b70, 0xd0f89791), X64Word_create(0xc76c51a3, 0x0654be30), + X64Word_create(0xd192e819, 0xd6ef5218), X64Word_create(0xd6990624, 0x5565a910), + X64Word_create(0xf40e3585, 0x5771202a), X64Word_create(0x106aa070, 0x32bbd1b8), + X64Word_create(0x19a4c116, 0xb8d2d0c8), X64Word_create(0x1e376c08, 0x5141ab53), + X64Word_create(0x2748774c, 0xdf8eeb99), X64Word_create(0x34b0bcb5, 0xe19b48a8), + X64Word_create(0x391c0cb3, 0xc5c95a63), X64Word_create(0x4ed8aa4a, 0xe3418acb), + X64Word_create(0x5b9cca4f, 0x7763e373), X64Word_create(0x682e6ff3, 0xd6b2b8a3), + X64Word_create(0x748f82ee, 0x5defb2fc), X64Word_create(0x78a5636f, 0x43172f60), + X64Word_create(0x84c87814, 0xa1f0ab72), X64Word_create(0x8cc70208, 0x1a6439ec), + X64Word_create(0x90befffa, 0x23631e28), X64Word_create(0xa4506ceb, 0xde82bde9), + X64Word_create(0xbef9a3f7, 0xb2c67915), X64Word_create(0xc67178f2, 0xe372532b), + X64Word_create(0xca273ece, 0xea26619c), X64Word_create(0xd186b8c7, 0x21c0c207), + X64Word_create(0xeada7dd6, 0xcde0eb1e), X64Word_create(0xf57d4f7f, 0xee6ed178), + X64Word_create(0x06f067aa, 0x72176fba), X64Word_create(0x0a637dc5, 0xa2c898a6), + X64Word_create(0x113f9804, 0xbef90dae), X64Word_create(0x1b710b35, 0x131c471b), + X64Word_create(0x28db77f5, 0x23047d84), X64Word_create(0x32caab7b, 0x40c72493), + X64Word_create(0x3c9ebe0a, 0x15c9bebc), X64Word_create(0x431d67c4, 0x9c100d4c), + X64Word_create(0x4cc5d4be, 0xcb3e42b6), X64Word_create(0x597f299c, 0xfc657e2a), + X64Word_create(0x5fcb6fab, 0x3ad6faec), X64Word_create(0x6c44198c, 0x4a475817) + ]; + + // Reusable objects + var W = []; + (function () { + for (var i = 0; i < 80; i++) { + W[i] = X64Word_create(); + } + }()); + + /** + * SHA-512 hash algorithm. + */ + var SHA512 = C_algo.SHA512 = Hasher.extend({ + _doReset: function () { + this._hash = new X64WordArray.init([ + new X64Word.init(0x6a09e667, 0xf3bcc908), new X64Word.init(0xbb67ae85, 0x84caa73b), + new X64Word.init(0x3c6ef372, 0xfe94f82b), new X64Word.init(0xa54ff53a, 0x5f1d36f1), + new X64Word.init(0x510e527f, 0xade682d1), new X64Word.init(0x9b05688c, 0x2b3e6c1f), + new X64Word.init(0x1f83d9ab, 0xfb41bd6b), new X64Word.init(0x5be0cd19, 0x137e2179) + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcuts + var H = this._hash.words; + + var H0 = H[0]; + var H1 = H[1]; + var H2 = H[2]; + var H3 = H[3]; + var H4 = H[4]; + var H5 = H[5]; + var H6 = H[6]; + var H7 = H[7]; + + var H0h = H0.high; + var H0l = H0.low; + var H1h = H1.high; + var H1l = H1.low; + var H2h = H2.high; + var H2l = H2.low; + var H3h = H3.high; + var H3l = H3.low; + var H4h = H4.high; + var H4l = H4.low; + var H5h = H5.high; + var H5l = H5.low; + var H6h = H6.high; + var H6l = H6.low; + var H7h = H7.high; + var H7l = H7.low; + + // Working variables + var ah = H0h; + var al = H0l; + var bh = H1h; + var bl = H1l; + var ch = H2h; + var cl = H2l; + var dh = H3h; + var dl = H3l; + var eh = H4h; + var el = H4l; + var fh = H5h; + var fl = H5l; + var gh = H6h; + var gl = H6l; + var hh = H7h; + var hl = H7l; + + // Rounds + for (var i = 0; i < 80; i++) { + // Shortcut + var Wi = W[i]; + + // Extend message + if (i < 16) { + var Wih = Wi.high = M[offset + i * 2] | 0; + var Wil = Wi.low = M[offset + i * 2 + 1] | 0; + } else { + // Gamma0 + var gamma0x = W[i - 15]; + var gamma0xh = gamma0x.high; + var gamma0xl = gamma0x.low; + var gamma0h = ((gamma0xh >>> 1) | (gamma0xl << 31)) ^ ((gamma0xh >>> 8) | (gamma0xl << 24)) ^ (gamma0xh >>> 7); + var gamma0l = ((gamma0xl >>> 1) | (gamma0xh << 31)) ^ ((gamma0xl >>> 8) | (gamma0xh << 24)) ^ ((gamma0xl >>> 7) | (gamma0xh << 25)); + + // Gamma1 + var gamma1x = W[i - 2]; + var gamma1xh = gamma1x.high; + var gamma1xl = gamma1x.low; + var gamma1h = ((gamma1xh >>> 19) | (gamma1xl << 13)) ^ ((gamma1xh << 3) | (gamma1xl >>> 29)) ^ (gamma1xh >>> 6); + var gamma1l = ((gamma1xl >>> 19) | (gamma1xh << 13)) ^ ((gamma1xl << 3) | (gamma1xh >>> 29)) ^ ((gamma1xl >>> 6) | (gamma1xh << 26)); + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + var Wi7 = W[i - 7]; + var Wi7h = Wi7.high; + var Wi7l = Wi7.low; + + var Wi16 = W[i - 16]; + var Wi16h = Wi16.high; + var Wi16l = Wi16.low; + + var Wil = gamma0l + Wi7l; + var Wih = gamma0h + Wi7h + ((Wil >>> 0) < (gamma0l >>> 0) ? 1 : 0); + var Wil = Wil + gamma1l; + var Wih = Wih + gamma1h + ((Wil >>> 0) < (gamma1l >>> 0) ? 1 : 0); + var Wil = Wil + Wi16l; + var Wih = Wih + Wi16h + ((Wil >>> 0) < (Wi16l >>> 0) ? 1 : 0); + + Wi.high = Wih; + Wi.low = Wil; + } + + var chh = (eh & fh) ^ (~eh & gh); + var chl = (el & fl) ^ (~el & gl); + var majh = (ah & bh) ^ (ah & ch) ^ (bh & ch); + var majl = (al & bl) ^ (al & cl) ^ (bl & cl); + + var sigma0h = ((ah >>> 28) | (al << 4)) ^ ((ah << 30) | (al >>> 2)) ^ ((ah << 25) | (al >>> 7)); + var sigma0l = ((al >>> 28) | (ah << 4)) ^ ((al << 30) | (ah >>> 2)) ^ ((al << 25) | (ah >>> 7)); + var sigma1h = ((eh >>> 14) | (el << 18)) ^ ((eh >>> 18) | (el << 14)) ^ ((eh << 23) | (el >>> 9)); + var sigma1l = ((el >>> 14) | (eh << 18)) ^ ((el >>> 18) | (eh << 14)) ^ ((el << 23) | (eh >>> 9)); + + // t1 = h + sigma1 + ch + K[i] + W[i] + var Ki = K[i]; + var Kih = Ki.high; + var Kil = Ki.low; + + var t1l = hl + sigma1l; + var t1h = hh + sigma1h + ((t1l >>> 0) < (hl >>> 0) ? 1 : 0); + var t1l = t1l + chl; + var t1h = t1h + chh + ((t1l >>> 0) < (chl >>> 0) ? 1 : 0); + var t1l = t1l + Kil; + var t1h = t1h + Kih + ((t1l >>> 0) < (Kil >>> 0) ? 1 : 0); + var t1l = t1l + Wil; + var t1h = t1h + Wih + ((t1l >>> 0) < (Wil >>> 0) ? 1 : 0); + + // t2 = sigma0 + maj + var t2l = sigma0l + majl; + var t2h = sigma0h + majh + ((t2l >>> 0) < (sigma0l >>> 0) ? 1 : 0); + + // Update working variables + hh = gh; + hl = gl; + gh = fh; + gl = fl; + fh = eh; + fl = el; + el = (dl + t1l) | 0; + eh = (dh + t1h + ((el >>> 0) < (dl >>> 0) ? 1 : 0)) | 0; + dh = ch; + dl = cl; + ch = bh; + cl = bl; + bh = ah; + bl = al; + al = (t1l + t2l) | 0; + ah = (t1h + t2h + ((al >>> 0) < (t1l >>> 0) ? 1 : 0)) | 0; + } + + // Intermediate hash value + H0l = H0.low = (H0l + al); + H0.high = (H0h + ah + ((H0l >>> 0) < (al >>> 0) ? 1 : 0)); + H1l = H1.low = (H1l + bl); + H1.high = (H1h + bh + ((H1l >>> 0) < (bl >>> 0) ? 1 : 0)); + H2l = H2.low = (H2l + cl); + H2.high = (H2h + ch + ((H2l >>> 0) < (cl >>> 0) ? 1 : 0)); + H3l = H3.low = (H3l + dl); + H3.high = (H3h + dh + ((H3l >>> 0) < (dl >>> 0) ? 1 : 0)); + H4l = H4.low = (H4l + el); + H4.high = (H4h + eh + ((H4l >>> 0) < (el >>> 0) ? 1 : 0)); + H5l = H5.low = (H5l + fl); + H5.high = (H5h + fh + ((H5l >>> 0) < (fl >>> 0) ? 1 : 0)); + H6l = H6.low = (H6l + gl); + H6.high = (H6h + gh + ((H6l >>> 0) < (gl >>> 0) ? 1 : 0)); + H7l = H7.low = (H7l + hl); + H7.high = (H7h + hh + ((H7l >>> 0) < (hl >>> 0) ? 1 : 0)); + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 30] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 128) >>> 10) << 5) + 31] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Convert hash to 32-bit word array before returning + var hash = this._hash.toX32(); + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + }, + + blockSize: 1024/32 + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA512('message'); + * var hash = CryptoJS.SHA512(wordArray); + */ + C.SHA512 = Hasher._createHelper(SHA512); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA512(message, key); + */ + C.HmacSHA512 = Hasher._createHmacHelper(SHA512); + }()); + + + return CryptoJS.SHA512; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/tripledes.js b/www/lib/crypto-js/tripledes.js new file mode 100644 index 0000000000000000000000000000000000000000..c7becf3b70ad64bd271e718a73db61286f114356 --- /dev/null +++ b/www/lib/crypto-js/tripledes.js @@ -0,0 +1,770 @@ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Permuted Choice 1 constants + var PC1 = [ + 57, 49, 41, 33, 25, 17, 9, 1, + 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 27, 19, 11, 3, + 60, 52, 44, 36, 63, 55, 47, 39, + 31, 23, 15, 7, 62, 54, 46, 38, + 30, 22, 14, 6, 61, 53, 45, 37, + 29, 21, 13, 5, 28, 20, 12, 4 + ]; + + // Permuted Choice 2 constants + var PC2 = [ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + ]; + + // Cumulative bit shift constants + var BIT_SHIFTS = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]; + + // SBOXes and round permutation constants + var SBOX_P = [ + { + 0x0: 0x808200, + 0x10000000: 0x8000, + 0x20000000: 0x808002, + 0x30000000: 0x2, + 0x40000000: 0x200, + 0x50000000: 0x808202, + 0x60000000: 0x800202, + 0x70000000: 0x800000, + 0x80000000: 0x202, + 0x90000000: 0x800200, + 0xa0000000: 0x8200, + 0xb0000000: 0x808000, + 0xc0000000: 0x8002, + 0xd0000000: 0x800002, + 0xe0000000: 0x0, + 0xf0000000: 0x8202, + 0x8000000: 0x0, + 0x18000000: 0x808202, + 0x28000000: 0x8202, + 0x38000000: 0x8000, + 0x48000000: 0x808200, + 0x58000000: 0x200, + 0x68000000: 0x808002, + 0x78000000: 0x2, + 0x88000000: 0x800200, + 0x98000000: 0x8200, + 0xa8000000: 0x808000, + 0xb8000000: 0x800202, + 0xc8000000: 0x800002, + 0xd8000000: 0x8002, + 0xe8000000: 0x202, + 0xf8000000: 0x800000, + 0x1: 0x8000, + 0x10000001: 0x2, + 0x20000001: 0x808200, + 0x30000001: 0x800000, + 0x40000001: 0x808002, + 0x50000001: 0x8200, + 0x60000001: 0x200, + 0x70000001: 0x800202, + 0x80000001: 0x808202, + 0x90000001: 0x808000, + 0xa0000001: 0x800002, + 0xb0000001: 0x8202, + 0xc0000001: 0x202, + 0xd0000001: 0x800200, + 0xe0000001: 0x8002, + 0xf0000001: 0x0, + 0x8000001: 0x808202, + 0x18000001: 0x808000, + 0x28000001: 0x800000, + 0x38000001: 0x200, + 0x48000001: 0x8000, + 0x58000001: 0x800002, + 0x68000001: 0x2, + 0x78000001: 0x8202, + 0x88000001: 0x8002, + 0x98000001: 0x800202, + 0xa8000001: 0x202, + 0xb8000001: 0x808200, + 0xc8000001: 0x800200, + 0xd8000001: 0x0, + 0xe8000001: 0x8200, + 0xf8000001: 0x808002 + }, + { + 0x0: 0x40084010, + 0x1000000: 0x4000, + 0x2000000: 0x80000, + 0x3000000: 0x40080010, + 0x4000000: 0x40000010, + 0x5000000: 0x40084000, + 0x6000000: 0x40004000, + 0x7000000: 0x10, + 0x8000000: 0x84000, + 0x9000000: 0x40004010, + 0xa000000: 0x40000000, + 0xb000000: 0x84010, + 0xc000000: 0x80010, + 0xd000000: 0x0, + 0xe000000: 0x4010, + 0xf000000: 0x40080000, + 0x800000: 0x40004000, + 0x1800000: 0x84010, + 0x2800000: 0x10, + 0x3800000: 0x40004010, + 0x4800000: 0x40084010, + 0x5800000: 0x40000000, + 0x6800000: 0x80000, + 0x7800000: 0x40080010, + 0x8800000: 0x80010, + 0x9800000: 0x0, + 0xa800000: 0x4000, + 0xb800000: 0x40080000, + 0xc800000: 0x40000010, + 0xd800000: 0x84000, + 0xe800000: 0x40084000, + 0xf800000: 0x4010, + 0x10000000: 0x0, + 0x11000000: 0x40080010, + 0x12000000: 0x40004010, + 0x13000000: 0x40084000, + 0x14000000: 0x40080000, + 0x15000000: 0x10, + 0x16000000: 0x84010, + 0x17000000: 0x4000, + 0x18000000: 0x4010, + 0x19000000: 0x80000, + 0x1a000000: 0x80010, + 0x1b000000: 0x40000010, + 0x1c000000: 0x84000, + 0x1d000000: 0x40004000, + 0x1e000000: 0x40000000, + 0x1f000000: 0x40084010, + 0x10800000: 0x84010, + 0x11800000: 0x80000, + 0x12800000: 0x40080000, + 0x13800000: 0x4000, + 0x14800000: 0x40004000, + 0x15800000: 0x40084010, + 0x16800000: 0x10, + 0x17800000: 0x40000000, + 0x18800000: 0x40084000, + 0x19800000: 0x40000010, + 0x1a800000: 0x40004010, + 0x1b800000: 0x80010, + 0x1c800000: 0x0, + 0x1d800000: 0x4010, + 0x1e800000: 0x40080010, + 0x1f800000: 0x84000 + }, + { + 0x0: 0x104, + 0x100000: 0x0, + 0x200000: 0x4000100, + 0x300000: 0x10104, + 0x400000: 0x10004, + 0x500000: 0x4000004, + 0x600000: 0x4010104, + 0x700000: 0x4010000, + 0x800000: 0x4000000, + 0x900000: 0x4010100, + 0xa00000: 0x10100, + 0xb00000: 0x4010004, + 0xc00000: 0x4000104, + 0xd00000: 0x10000, + 0xe00000: 0x4, + 0xf00000: 0x100, + 0x80000: 0x4010100, + 0x180000: 0x4010004, + 0x280000: 0x0, + 0x380000: 0x4000100, + 0x480000: 0x4000004, + 0x580000: 0x10000, + 0x680000: 0x10004, + 0x780000: 0x104, + 0x880000: 0x4, + 0x980000: 0x100, + 0xa80000: 0x4010000, + 0xb80000: 0x10104, + 0xc80000: 0x10100, + 0xd80000: 0x4000104, + 0xe80000: 0x4010104, + 0xf80000: 0x4000000, + 0x1000000: 0x4010100, + 0x1100000: 0x10004, + 0x1200000: 0x10000, + 0x1300000: 0x4000100, + 0x1400000: 0x100, + 0x1500000: 0x4010104, + 0x1600000: 0x4000004, + 0x1700000: 0x0, + 0x1800000: 0x4000104, + 0x1900000: 0x4000000, + 0x1a00000: 0x4, + 0x1b00000: 0x10100, + 0x1c00000: 0x4010000, + 0x1d00000: 0x104, + 0x1e00000: 0x10104, + 0x1f00000: 0x4010004, + 0x1080000: 0x4000000, + 0x1180000: 0x104, + 0x1280000: 0x4010100, + 0x1380000: 0x0, + 0x1480000: 0x10004, + 0x1580000: 0x4000100, + 0x1680000: 0x100, + 0x1780000: 0x4010004, + 0x1880000: 0x10000, + 0x1980000: 0x4010104, + 0x1a80000: 0x10104, + 0x1b80000: 0x4000004, + 0x1c80000: 0x4000104, + 0x1d80000: 0x4010000, + 0x1e80000: 0x4, + 0x1f80000: 0x10100 + }, + { + 0x0: 0x80401000, + 0x10000: 0x80001040, + 0x20000: 0x401040, + 0x30000: 0x80400000, + 0x40000: 0x0, + 0x50000: 0x401000, + 0x60000: 0x80000040, + 0x70000: 0x400040, + 0x80000: 0x80000000, + 0x90000: 0x400000, + 0xa0000: 0x40, + 0xb0000: 0x80001000, + 0xc0000: 0x80400040, + 0xd0000: 0x1040, + 0xe0000: 0x1000, + 0xf0000: 0x80401040, + 0x8000: 0x80001040, + 0x18000: 0x40, + 0x28000: 0x80400040, + 0x38000: 0x80001000, + 0x48000: 0x401000, + 0x58000: 0x80401040, + 0x68000: 0x0, + 0x78000: 0x80400000, + 0x88000: 0x1000, + 0x98000: 0x80401000, + 0xa8000: 0x400000, + 0xb8000: 0x1040, + 0xc8000: 0x80000000, + 0xd8000: 0x400040, + 0xe8000: 0x401040, + 0xf8000: 0x80000040, + 0x100000: 0x400040, + 0x110000: 0x401000, + 0x120000: 0x80000040, + 0x130000: 0x0, + 0x140000: 0x1040, + 0x150000: 0x80400040, + 0x160000: 0x80401000, + 0x170000: 0x80001040, + 0x180000: 0x80401040, + 0x190000: 0x80000000, + 0x1a0000: 0x80400000, + 0x1b0000: 0x401040, + 0x1c0000: 0x80001000, + 0x1d0000: 0x400000, + 0x1e0000: 0x40, + 0x1f0000: 0x1000, + 0x108000: 0x80400000, + 0x118000: 0x80401040, + 0x128000: 0x0, + 0x138000: 0x401000, + 0x148000: 0x400040, + 0x158000: 0x80000000, + 0x168000: 0x80001040, + 0x178000: 0x40, + 0x188000: 0x80000040, + 0x198000: 0x1000, + 0x1a8000: 0x80001000, + 0x1b8000: 0x80400040, + 0x1c8000: 0x1040, + 0x1d8000: 0x80401000, + 0x1e8000: 0x400000, + 0x1f8000: 0x401040 + }, + { + 0x0: 0x80, + 0x1000: 0x1040000, + 0x2000: 0x40000, + 0x3000: 0x20000000, + 0x4000: 0x20040080, + 0x5000: 0x1000080, + 0x6000: 0x21000080, + 0x7000: 0x40080, + 0x8000: 0x1000000, + 0x9000: 0x20040000, + 0xa000: 0x20000080, + 0xb000: 0x21040080, + 0xc000: 0x21040000, + 0xd000: 0x0, + 0xe000: 0x1040080, + 0xf000: 0x21000000, + 0x800: 0x1040080, + 0x1800: 0x21000080, + 0x2800: 0x80, + 0x3800: 0x1040000, + 0x4800: 0x40000, + 0x5800: 0x20040080, + 0x6800: 0x21040000, + 0x7800: 0x20000000, + 0x8800: 0x20040000, + 0x9800: 0x0, + 0xa800: 0x21040080, + 0xb800: 0x1000080, + 0xc800: 0x20000080, + 0xd800: 0x21000000, + 0xe800: 0x1000000, + 0xf800: 0x40080, + 0x10000: 0x40000, + 0x11000: 0x80, + 0x12000: 0x20000000, + 0x13000: 0x21000080, + 0x14000: 0x1000080, + 0x15000: 0x21040000, + 0x16000: 0x20040080, + 0x17000: 0x1000000, + 0x18000: 0x21040080, + 0x19000: 0x21000000, + 0x1a000: 0x1040000, + 0x1b000: 0x20040000, + 0x1c000: 0x40080, + 0x1d000: 0x20000080, + 0x1e000: 0x0, + 0x1f000: 0x1040080, + 0x10800: 0x21000080, + 0x11800: 0x1000000, + 0x12800: 0x1040000, + 0x13800: 0x20040080, + 0x14800: 0x20000000, + 0x15800: 0x1040080, + 0x16800: 0x80, + 0x17800: 0x21040000, + 0x18800: 0x40080, + 0x19800: 0x21040080, + 0x1a800: 0x0, + 0x1b800: 0x21000000, + 0x1c800: 0x1000080, + 0x1d800: 0x40000, + 0x1e800: 0x20040000, + 0x1f800: 0x20000080 + }, + { + 0x0: 0x10000008, + 0x100: 0x2000, + 0x200: 0x10200000, + 0x300: 0x10202008, + 0x400: 0x10002000, + 0x500: 0x200000, + 0x600: 0x200008, + 0x700: 0x10000000, + 0x800: 0x0, + 0x900: 0x10002008, + 0xa00: 0x202000, + 0xb00: 0x8, + 0xc00: 0x10200008, + 0xd00: 0x202008, + 0xe00: 0x2008, + 0xf00: 0x10202000, + 0x80: 0x10200000, + 0x180: 0x10202008, + 0x280: 0x8, + 0x380: 0x200000, + 0x480: 0x202008, + 0x580: 0x10000008, + 0x680: 0x10002000, + 0x780: 0x2008, + 0x880: 0x200008, + 0x980: 0x2000, + 0xa80: 0x10002008, + 0xb80: 0x10200008, + 0xc80: 0x0, + 0xd80: 0x10202000, + 0xe80: 0x202000, + 0xf80: 0x10000000, + 0x1000: 0x10002000, + 0x1100: 0x10200008, + 0x1200: 0x10202008, + 0x1300: 0x2008, + 0x1400: 0x200000, + 0x1500: 0x10000000, + 0x1600: 0x10000008, + 0x1700: 0x202000, + 0x1800: 0x202008, + 0x1900: 0x0, + 0x1a00: 0x8, + 0x1b00: 0x10200000, + 0x1c00: 0x2000, + 0x1d00: 0x10002008, + 0x1e00: 0x10202000, + 0x1f00: 0x200008, + 0x1080: 0x8, + 0x1180: 0x202000, + 0x1280: 0x200000, + 0x1380: 0x10000008, + 0x1480: 0x10002000, + 0x1580: 0x2008, + 0x1680: 0x10202008, + 0x1780: 0x10200000, + 0x1880: 0x10202000, + 0x1980: 0x10200008, + 0x1a80: 0x2000, + 0x1b80: 0x202008, + 0x1c80: 0x200008, + 0x1d80: 0x0, + 0x1e80: 0x10000000, + 0x1f80: 0x10002008 + }, + { + 0x0: 0x100000, + 0x10: 0x2000401, + 0x20: 0x400, + 0x30: 0x100401, + 0x40: 0x2100401, + 0x50: 0x0, + 0x60: 0x1, + 0x70: 0x2100001, + 0x80: 0x2000400, + 0x90: 0x100001, + 0xa0: 0x2000001, + 0xb0: 0x2100400, + 0xc0: 0x2100000, + 0xd0: 0x401, + 0xe0: 0x100400, + 0xf0: 0x2000000, + 0x8: 0x2100001, + 0x18: 0x0, + 0x28: 0x2000401, + 0x38: 0x2100400, + 0x48: 0x100000, + 0x58: 0x2000001, + 0x68: 0x2000000, + 0x78: 0x401, + 0x88: 0x100401, + 0x98: 0x2000400, + 0xa8: 0x2100000, + 0xb8: 0x100001, + 0xc8: 0x400, + 0xd8: 0x2100401, + 0xe8: 0x1, + 0xf8: 0x100400, + 0x100: 0x2000000, + 0x110: 0x100000, + 0x120: 0x2000401, + 0x130: 0x2100001, + 0x140: 0x100001, + 0x150: 0x2000400, + 0x160: 0x2100400, + 0x170: 0x100401, + 0x180: 0x401, + 0x190: 0x2100401, + 0x1a0: 0x100400, + 0x1b0: 0x1, + 0x1c0: 0x0, + 0x1d0: 0x2100000, + 0x1e0: 0x2000001, + 0x1f0: 0x400, + 0x108: 0x100400, + 0x118: 0x2000401, + 0x128: 0x2100001, + 0x138: 0x1, + 0x148: 0x2000000, + 0x158: 0x100000, + 0x168: 0x401, + 0x178: 0x2100400, + 0x188: 0x2000001, + 0x198: 0x2100000, + 0x1a8: 0x0, + 0x1b8: 0x2100401, + 0x1c8: 0x100401, + 0x1d8: 0x400, + 0x1e8: 0x2000400, + 0x1f8: 0x100001 + }, + { + 0x0: 0x8000820, + 0x1: 0x20000, + 0x2: 0x8000000, + 0x3: 0x20, + 0x4: 0x20020, + 0x5: 0x8020820, + 0x6: 0x8020800, + 0x7: 0x800, + 0x8: 0x8020000, + 0x9: 0x8000800, + 0xa: 0x20800, + 0xb: 0x8020020, + 0xc: 0x820, + 0xd: 0x0, + 0xe: 0x8000020, + 0xf: 0x20820, + 0x80000000: 0x800, + 0x80000001: 0x8020820, + 0x80000002: 0x8000820, + 0x80000003: 0x8000000, + 0x80000004: 0x8020000, + 0x80000005: 0x20800, + 0x80000006: 0x20820, + 0x80000007: 0x20, + 0x80000008: 0x8000020, + 0x80000009: 0x820, + 0x8000000a: 0x20020, + 0x8000000b: 0x8020800, + 0x8000000c: 0x0, + 0x8000000d: 0x8020020, + 0x8000000e: 0x8000800, + 0x8000000f: 0x20000, + 0x10: 0x20820, + 0x11: 0x8020800, + 0x12: 0x20, + 0x13: 0x800, + 0x14: 0x8000800, + 0x15: 0x8000020, + 0x16: 0x8020020, + 0x17: 0x20000, + 0x18: 0x0, + 0x19: 0x20020, + 0x1a: 0x8020000, + 0x1b: 0x8000820, + 0x1c: 0x8020820, + 0x1d: 0x20800, + 0x1e: 0x820, + 0x1f: 0x8000000, + 0x80000010: 0x20000, + 0x80000011: 0x800, + 0x80000012: 0x8020020, + 0x80000013: 0x20820, + 0x80000014: 0x20, + 0x80000015: 0x8020000, + 0x80000016: 0x8000000, + 0x80000017: 0x8000820, + 0x80000018: 0x8020820, + 0x80000019: 0x8000020, + 0x8000001a: 0x8000800, + 0x8000001b: 0x0, + 0x8000001c: 0x20800, + 0x8000001d: 0x820, + 0x8000001e: 0x20020, + 0x8000001f: 0x8020800 + } + ]; + + // Masks that select the SBOX input + var SBOX_MASK = [ + 0xf8000001, 0x1f800000, 0x01f80000, 0x001f8000, + 0x0001f800, 0x00001f80, 0x000001f8, 0x8000001f + ]; + + /** + * DES block cipher algorithm. + */ + var DES = C_algo.DES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + + // Select 56 bits according to PC1 + var keyBits = []; + for (var i = 0; i < 56; i++) { + var keyBitPos = PC1[i] - 1; + keyBits[i] = (keyWords[keyBitPos >>> 5] >>> (31 - keyBitPos % 32)) & 1; + } + + // Assemble 16 subkeys + var subKeys = this._subKeys = []; + for (var nSubKey = 0; nSubKey < 16; nSubKey++) { + // Create subkey + var subKey = subKeys[nSubKey] = []; + + // Shortcut + var bitShift = BIT_SHIFTS[nSubKey]; + + // Select 48 bits according to PC2 + for (var i = 0; i < 24; i++) { + // Select from the left 28 key bits + subKey[(i / 6) | 0] |= keyBits[((PC2[i] - 1) + bitShift) % 28] << (31 - i % 6); + + // Select from the right 28 key bits + subKey[4 + ((i / 6) | 0)] |= keyBits[28 + (((PC2[i + 24] - 1) + bitShift) % 28)] << (31 - i % 6); + } + + // Since each subkey is applied to an expanded 32-bit input, + // the subkey can be broken into 8 values scaled to 32-bits, + // which allows the key to be used without expansion + subKey[0] = (subKey[0] << 1) | (subKey[0] >>> 31); + for (var i = 1; i < 7; i++) { + subKey[i] = subKey[i] >>> ((i - 1) * 4 + 3); + } + subKey[7] = (subKey[7] << 5) | (subKey[7] >>> 27); + } + + // Compute inverse subkeys + var invSubKeys = this._invSubKeys = []; + for (var i = 0; i < 16; i++) { + invSubKeys[i] = subKeys[15 - i]; + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._subKeys); + }, + + decryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._invSubKeys); + }, + + _doCryptBlock: function (M, offset, subKeys) { + // Get input + this._lBlock = M[offset]; + this._rBlock = M[offset + 1]; + + // Initial permutation + exchangeLR.call(this, 4, 0x0f0f0f0f); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeRL.call(this, 2, 0x33333333); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeLR.call(this, 1, 0x55555555); + + // Rounds + for (var round = 0; round < 16; round++) { + // Shortcuts + var subKey = subKeys[round]; + var lBlock = this._lBlock; + var rBlock = this._rBlock; + + // Feistel function + var f = 0; + for (var i = 0; i < 8; i++) { + f |= SBOX_P[i][((rBlock ^ subKey[i]) & SBOX_MASK[i]) >>> 0]; + } + this._lBlock = rBlock; + this._rBlock = lBlock ^ f; + } + + // Undo swap from last round + var t = this._lBlock; + this._lBlock = this._rBlock; + this._rBlock = t; + + // Final permutation + exchangeLR.call(this, 1, 0x55555555); + exchangeRL.call(this, 8, 0x00ff00ff); + exchangeRL.call(this, 2, 0x33333333); + exchangeLR.call(this, 16, 0x0000ffff); + exchangeLR.call(this, 4, 0x0f0f0f0f); + + // Set output + M[offset] = this._lBlock; + M[offset + 1] = this._rBlock; + }, + + keySize: 64/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + // Swap bits across the left and right words + function exchangeLR(offset, mask) { + var t = ((this._lBlock >>> offset) ^ this._rBlock) & mask; + this._rBlock ^= t; + this._lBlock ^= t << offset; + } + + function exchangeRL(offset, mask) { + var t = ((this._rBlock >>> offset) ^ this._lBlock) & mask; + this._lBlock ^= t; + this._rBlock ^= t << offset; + } + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.DES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.DES.decrypt(ciphertext, key, cfg); + */ + C.DES = BlockCipher._createHelper(DES); + + /** + * Triple-DES block cipher algorithm. + */ + var TripleDES = C_algo.TripleDES = BlockCipher.extend({ + _doReset: function () { + // Shortcuts + var key = this._key; + var keyWords = key.words; + + // Create DES instances + this._des1 = DES.createEncryptor(WordArray.create(keyWords.slice(0, 2))); + this._des2 = DES.createEncryptor(WordArray.create(keyWords.slice(2, 4))); + this._des3 = DES.createEncryptor(WordArray.create(keyWords.slice(4, 6))); + }, + + encryptBlock: function (M, offset) { + this._des1.encryptBlock(M, offset); + this._des2.decryptBlock(M, offset); + this._des3.encryptBlock(M, offset); + }, + + decryptBlock: function (M, offset) { + this._des3.decryptBlock(M, offset); + this._des2.encryptBlock(M, offset); + this._des1.decryptBlock(M, offset); + }, + + keySize: 192/32, + + ivSize: 64/32, + + blockSize: 64/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.TripleDES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.TripleDES.decrypt(ciphertext, key, cfg); + */ + C.TripleDES = BlockCipher._createHelper(TripleDES); + }()); + + + return CryptoJS.TripleDES; + +})); \ No newline at end of file diff --git a/www/lib/crypto-js/x64-core.js b/www/lib/crypto-js/x64-core.js new file mode 100644 index 0000000000000000000000000000000000000000..57dcc144b042207243d12dc0a488545ea4d794e6 --- /dev/null +++ b/www/lib/crypto-js/x64-core.js @@ -0,0 +1,304 @@ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var X32WordArray = C_lib.WordArray; + + /** + * x64 namespace. + */ + var C_x64 = C.x64 = {}; + + /** + * A 64-bit word. + */ + var X64Word = C_x64.Word = Base.extend({ + /** + * Initializes a newly created 64-bit word. + * + * @param {number} high The high 32 bits. + * @param {number} low The low 32 bits. + * + * @example + * + * var x64Word = CryptoJS.x64.Word.create(0x00010203, 0x04050607); + */ + init: function (high, low) { + this.high = high; + this.low = low; + } + + /** + * Bitwise NOTs this word. + * + * @return {X64Word} A new x64-Word object after negating. + * + * @example + * + * var negated = x64Word.not(); + */ + // not: function () { + // var high = ~this.high; + // var low = ~this.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ANDs this word with the passed word. + * + * @param {X64Word} word The x64-Word to AND with this word. + * + * @return {X64Word} A new x64-Word object after ANDing. + * + * @example + * + * var anded = x64Word.and(anotherX64Word); + */ + // and: function (word) { + // var high = this.high & word.high; + // var low = this.low & word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise ORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to OR with this word. + * + * @return {X64Word} A new x64-Word object after ORing. + * + * @example + * + * var ored = x64Word.or(anotherX64Word); + */ + // or: function (word) { + // var high = this.high | word.high; + // var low = this.low | word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Bitwise XORs this word with the passed word. + * + * @param {X64Word} word The x64-Word to XOR with this word. + * + * @return {X64Word} A new x64-Word object after XORing. + * + * @example + * + * var xored = x64Word.xor(anotherX64Word); + */ + // xor: function (word) { + // var high = this.high ^ word.high; + // var low = this.low ^ word.low; + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the left. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftL(25); + */ + // shiftL: function (n) { + // if (n < 32) { + // var high = (this.high << n) | (this.low >>> (32 - n)); + // var low = this.low << n; + // } else { + // var high = this.low << (n - 32); + // var low = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Shifts this word n bits to the right. + * + * @param {number} n The number of bits to shift. + * + * @return {X64Word} A new x64-Word object after shifting. + * + * @example + * + * var shifted = x64Word.shiftR(7); + */ + // shiftR: function (n) { + // if (n < 32) { + // var low = (this.low >>> n) | (this.high << (32 - n)); + // var high = this.high >>> n; + // } else { + // var low = this.high >>> (n - 32); + // var high = 0; + // } + + // return X64Word.create(high, low); + // }, + + /** + * Rotates this word n bits to the left. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotL(25); + */ + // rotL: function (n) { + // return this.shiftL(n).or(this.shiftR(64 - n)); + // }, + + /** + * Rotates this word n bits to the right. + * + * @param {number} n The number of bits to rotate. + * + * @return {X64Word} A new x64-Word object after rotating. + * + * @example + * + * var rotated = x64Word.rotR(7); + */ + // rotR: function (n) { + // return this.shiftR(n).or(this.shiftL(64 - n)); + // }, + + /** + * Adds this word with the passed word. + * + * @param {X64Word} word The x64-Word to add with this word. + * + * @return {X64Word} A new x64-Word object after adding. + * + * @example + * + * var added = x64Word.add(anotherX64Word); + */ + // add: function (word) { + // var low = (this.low + word.low) | 0; + // var carry = (low >>> 0) < (this.low >>> 0) ? 1 : 0; + // var high = (this.high + word.high + carry) | 0; + + // return X64Word.create(high, low); + // } + }); + + /** + * An array of 64-bit words. + * + * @property {Array} words The array of CryptoJS.x64.Word objects. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var X64WordArray = C_x64.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of CryptoJS.x64.Word objects. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.x64.WordArray.create(); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ]); + * + * var wordArray = CryptoJS.x64.WordArray.create([ + * CryptoJS.x64.Word.create(0x00010203, 0x04050607), + * CryptoJS.x64.Word.create(0x18191a1b, 0x1c1d1e1f) + * ], 10); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 8; + } + }, + + /** + * Converts this 64-bit word array to a 32-bit word array. + * + * @return {CryptoJS.lib.WordArray} This word array's data as a 32-bit word array. + * + * @example + * + * var x32WordArray = x64WordArray.toX32(); + */ + toX32: function () { + // Shortcuts + var x64Words = this.words; + var x64WordsLength = x64Words.length; + + // Convert + var x32Words = []; + for (var i = 0; i < x64WordsLength; i++) { + var x64Word = x64Words[i]; + x32Words.push(x64Word.high); + x32Words.push(x64Word.low); + } + + return X32WordArray.create(x32Words, this.sigBytes); + }, + + /** + * Creates a copy of this word array. + * + * @return {X64WordArray} The clone. + * + * @example + * + * var clone = x64WordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + + // Clone "words" array + var words = clone.words = this.words.slice(0); + + // Clone each X64Word object + var wordsLength = words.length; + for (var i = 0; i < wordsLength; i++) { + words[i] = words[i].clone(); + } + + return clone; + } + }); + }()); + + + return CryptoJS; + +})); \ No newline at end of file diff --git a/www/lib/ionic/css/ionic.css b/www/lib/ionic/css/ionic.css index 52f7ecf5651925add15c4a46828e0036959e3dc7..9a4be179c2711fb04e1fb7f5f7e6af0aa6d1b264 100644 --- a/www/lib/ionic/css/ionic.css +++ b/www/lib/ionic/css/ionic.css @@ -1,8 +1,9 @@ +@charset "UTF-8"; /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -29,7 +30,740 @@ font-weight: normal; font-style: normal; } -.ion, .ionicons, .ion-alert:before, .ion-alert-circled:before, .ion-android-add:before, .ion-android-add-circle:before, .ion-android-alarm-clock:before, .ion-android-alert:before, .ion-android-apps:before, .ion-android-archive:before, .ion-android-arrow-back:before, .ion-android-arrow-down:before, .ion-android-arrow-dropdown:before, .ion-android-arrow-dropdown-circle:before, .ion-android-arrow-dropleft:before, .ion-android-arrow-dropleft-circle:before, .ion-android-arrow-dropright:before, .ion-android-arrow-dropright-circle:before, .ion-android-arrow-dropup:before, .ion-android-arrow-dropup-circle:before, .ion-android-arrow-forward:before, .ion-android-arrow-up:before, .ion-android-attach:before, .ion-android-bar:before, .ion-android-bicycle:before, .ion-android-boat:before, .ion-android-bookmark:before, .ion-android-bulb:before, .ion-android-bus:before, .ion-android-calendar:before, .ion-android-call:before, .ion-android-camera:before, .ion-android-cancel:before, .ion-android-car:before, .ion-android-cart:before, .ion-android-chat:before, .ion-android-checkbox:before, .ion-android-checkbox-blank:before, .ion-android-checkbox-outline:before, .ion-android-checkbox-outline-blank:before, .ion-android-checkmark-circle:before, .ion-android-clipboard:before, .ion-android-close:before, .ion-android-cloud:before, .ion-android-cloud-circle:before, .ion-android-cloud-done:before, .ion-android-cloud-outline:before, .ion-android-color-palette:before, .ion-android-compass:before, .ion-android-contact:before, .ion-android-contacts:before, .ion-android-contract:before, .ion-android-create:before, .ion-android-delete:before, .ion-android-desktop:before, .ion-android-document:before, .ion-android-done:before, .ion-android-done-all:before, .ion-android-download:before, .ion-android-drafts:before, .ion-android-exit:before, .ion-android-expand:before, .ion-android-favorite:before, .ion-android-favorite-outline:before, .ion-android-film:before, .ion-android-folder:before, .ion-android-folder-open:before, .ion-android-funnel:before, .ion-android-globe:before, .ion-android-hand:before, .ion-android-hangout:before, .ion-android-happy:before, .ion-android-home:before, .ion-android-image:before, .ion-android-laptop:before, .ion-android-list:before, .ion-android-locate:before, .ion-android-lock:before, .ion-android-mail:before, .ion-android-map:before, .ion-android-menu:before, .ion-android-microphone:before, .ion-android-microphone-off:before, .ion-android-more-horizontal:before, .ion-android-more-vertical:before, .ion-android-navigate:before, .ion-android-notifications:before, .ion-android-notifications-none:before, .ion-android-notifications-off:before, .ion-android-open:before, .ion-android-options:before, .ion-android-people:before, .ion-android-person:before, .ion-android-person-add:before, .ion-android-phone-landscape:before, .ion-android-phone-portrait:before, .ion-android-pin:before, .ion-android-plane:before, .ion-android-playstore:before, .ion-android-print:before, .ion-android-radio-button-off:before, .ion-android-radio-button-on:before, .ion-android-refresh:before, .ion-android-remove:before, .ion-android-remove-circle:before, .ion-android-restaurant:before, .ion-android-sad:before, .ion-android-search:before, .ion-android-send:before, .ion-android-settings:before, .ion-android-share:before, .ion-android-share-alt:before, .ion-android-star:before, .ion-android-star-half:before, .ion-android-star-outline:before, .ion-android-stopwatch:before, .ion-android-subway:before, .ion-android-sunny:before, .ion-android-sync:before, .ion-android-textsms:before, .ion-android-time:before, .ion-android-train:before, .ion-android-unlock:before, .ion-android-upload:before, .ion-android-volume-down:before, .ion-android-volume-mute:before, .ion-android-volume-off:before, .ion-android-volume-up:before, .ion-android-walk:before, .ion-android-warning:before, .ion-android-watch:before, .ion-android-wifi:before, .ion-aperture:before, .ion-archive:before, .ion-arrow-down-a:before, .ion-arrow-down-b:before, .ion-arrow-down-c:before, .ion-arrow-expand:before, .ion-arrow-graph-down-left:before, .ion-arrow-graph-down-right:before, .ion-arrow-graph-up-left:before, .ion-arrow-graph-up-right:before, .ion-arrow-left-a:before, .ion-arrow-left-b:before, .ion-arrow-left-c:before, .ion-arrow-move:before, .ion-arrow-resize:before, .ion-arrow-return-left:before, .ion-arrow-return-right:before, .ion-arrow-right-a:before, .ion-arrow-right-b:before, .ion-arrow-right-c:before, .ion-arrow-shrink:before, .ion-arrow-swap:before, .ion-arrow-up-a:before, .ion-arrow-up-b:before, .ion-arrow-up-c:before, .ion-asterisk:before, .ion-at:before, .ion-backspace:before, .ion-backspace-outline:before, .ion-bag:before, .ion-battery-charging:before, .ion-battery-empty:before, .ion-battery-full:before, .ion-battery-half:before, .ion-battery-low:before, .ion-beaker:before, .ion-beer:before, .ion-bluetooth:before, .ion-bonfire:before, .ion-bookmark:before, .ion-bowtie:before, .ion-briefcase:before, .ion-bug:before, .ion-calculator:before, .ion-calendar:before, .ion-camera:before, .ion-card:before, .ion-cash:before, .ion-chatbox:before, .ion-chatbox-working:before, .ion-chatboxes:before, .ion-chatbubble:before, .ion-chatbubble-working:before, .ion-chatbubbles:before, .ion-checkmark:before, .ion-checkmark-circled:before, .ion-checkmark-round:before, .ion-chevron-down:before, .ion-chevron-left:before, .ion-chevron-right:before, .ion-chevron-up:before, .ion-clipboard:before, .ion-clock:before, .ion-close:before, .ion-close-circled:before, .ion-close-round:before, .ion-closed-captioning:before, .ion-cloud:before, .ion-code:before, .ion-code-download:before, .ion-code-working:before, .ion-coffee:before, .ion-compass:before, .ion-compose:before, .ion-connection-bars:before, .ion-contrast:before, .ion-crop:before, .ion-cube:before, .ion-disc:before, .ion-document:before, .ion-document-text:before, .ion-drag:before, .ion-earth:before, .ion-easel:before, .ion-edit:before, .ion-egg:before, .ion-eject:before, .ion-email:before, .ion-email-unread:before, .ion-erlenmeyer-flask:before, .ion-erlenmeyer-flask-bubbles:before, .ion-eye:before, .ion-eye-disabled:before, .ion-female:before, .ion-filing:before, .ion-film-marker:before, .ion-fireball:before, .ion-flag:before, .ion-flame:before, .ion-flash:before, .ion-flash-off:before, .ion-folder:before, .ion-fork:before, .ion-fork-repo:before, .ion-forward:before, .ion-funnel:before, .ion-gear-a:before, .ion-gear-b:before, .ion-grid:before, .ion-hammer:before, .ion-happy:before, .ion-happy-outline:before, .ion-headphone:before, .ion-heart:before, .ion-heart-broken:before, .ion-help:before, .ion-help-buoy:before, .ion-help-circled:before, .ion-home:before, .ion-icecream:before, .ion-image:before, .ion-images:before, .ion-information:before, .ion-information-circled:before, .ion-ionic:before, .ion-ios-alarm:before, .ion-ios-alarm-outline:before, .ion-ios-albums:before, .ion-ios-albums-outline:before, .ion-ios-americanfootball:before, .ion-ios-americanfootball-outline:before, .ion-ios-analytics:before, .ion-ios-analytics-outline:before, .ion-ios-arrow-back:before, .ion-ios-arrow-down:before, .ion-ios-arrow-forward:before, .ion-ios-arrow-left:before, .ion-ios-arrow-right:before, .ion-ios-arrow-thin-down:before, .ion-ios-arrow-thin-left:before, .ion-ios-arrow-thin-right:before, .ion-ios-arrow-thin-up:before, .ion-ios-arrow-up:before, .ion-ios-at:before, .ion-ios-at-outline:before, .ion-ios-barcode:before, .ion-ios-barcode-outline:before, .ion-ios-baseball:before, .ion-ios-baseball-outline:before, .ion-ios-basketball:before, .ion-ios-basketball-outline:before, .ion-ios-bell:before, .ion-ios-bell-outline:before, .ion-ios-body:before, .ion-ios-body-outline:before, .ion-ios-bolt:before, .ion-ios-bolt-outline:before, .ion-ios-book:before, .ion-ios-book-outline:before, .ion-ios-bookmarks:before, .ion-ios-bookmarks-outline:before, .ion-ios-box:before, .ion-ios-box-outline:before, .ion-ios-briefcase:before, .ion-ios-briefcase-outline:before, .ion-ios-browsers:before, .ion-ios-browsers-outline:before, .ion-ios-calculator:before, .ion-ios-calculator-outline:before, .ion-ios-calendar:before, .ion-ios-calendar-outline:before, .ion-ios-camera:before, .ion-ios-camera-outline:before, .ion-ios-cart:before, .ion-ios-cart-outline:before, .ion-ios-chatboxes:before, .ion-ios-chatboxes-outline:before, .ion-ios-chatbubble:before, .ion-ios-chatbubble-outline:before, .ion-ios-checkmark:before, .ion-ios-checkmark-empty:before, .ion-ios-checkmark-outline:before, .ion-ios-circle-filled:before, .ion-ios-circle-outline:before, .ion-ios-clock:before, .ion-ios-clock-outline:before, .ion-ios-close:before, .ion-ios-close-empty:before, .ion-ios-close-outline:before, .ion-ios-cloud:before, .ion-ios-cloud-download:before, .ion-ios-cloud-download-outline:before, .ion-ios-cloud-outline:before, .ion-ios-cloud-upload:before, .ion-ios-cloud-upload-outline:before, .ion-ios-cloudy:before, .ion-ios-cloudy-night:before, .ion-ios-cloudy-night-outline:before, .ion-ios-cloudy-outline:before, .ion-ios-cog:before, .ion-ios-cog-outline:before, .ion-ios-color-filter:before, .ion-ios-color-filter-outline:before, .ion-ios-color-wand:before, .ion-ios-color-wand-outline:before, .ion-ios-compose:before, .ion-ios-compose-outline:before, .ion-ios-contact:before, .ion-ios-contact-outline:before, .ion-ios-copy:before, .ion-ios-copy-outline:before, .ion-ios-crop:before, .ion-ios-crop-strong:before, .ion-ios-download:before, .ion-ios-download-outline:before, .ion-ios-drag:before, .ion-ios-email:before, .ion-ios-email-outline:before, .ion-ios-eye:before, .ion-ios-eye-outline:before, .ion-ios-fastforward:before, .ion-ios-fastforward-outline:before, .ion-ios-filing:before, .ion-ios-filing-outline:before, .ion-ios-film:before, .ion-ios-film-outline:before, .ion-ios-flag:before, .ion-ios-flag-outline:before, .ion-ios-flame:before, .ion-ios-flame-outline:before, .ion-ios-flask:before, .ion-ios-flask-outline:before, .ion-ios-flower:before, .ion-ios-flower-outline:before, .ion-ios-folder:before, .ion-ios-folder-outline:before, .ion-ios-football:before, .ion-ios-football-outline:before, .ion-ios-game-controller-a:before, .ion-ios-game-controller-a-outline:before, .ion-ios-game-controller-b:before, .ion-ios-game-controller-b-outline:before, .ion-ios-gear:before, .ion-ios-gear-outline:before, .ion-ios-glasses:before, .ion-ios-glasses-outline:before, .ion-ios-grid-view:before, .ion-ios-grid-view-outline:before, .ion-ios-heart:before, .ion-ios-heart-outline:before, .ion-ios-help:before, .ion-ios-help-empty:before, .ion-ios-help-outline:before, .ion-ios-home:before, .ion-ios-home-outline:before, .ion-ios-infinite:before, .ion-ios-infinite-outline:before, .ion-ios-information:before, .ion-ios-information-empty:before, .ion-ios-information-outline:before, .ion-ios-ionic-outline:before, .ion-ios-keypad:before, .ion-ios-keypad-outline:before, .ion-ios-lightbulb:before, .ion-ios-lightbulb-outline:before, .ion-ios-list:before, .ion-ios-list-outline:before, .ion-ios-location:before, .ion-ios-location-outline:before, .ion-ios-locked:before, .ion-ios-locked-outline:before, .ion-ios-loop:before, .ion-ios-loop-strong:before, .ion-ios-medical:before, .ion-ios-medical-outline:before, .ion-ios-medkit:before, .ion-ios-medkit-outline:before, .ion-ios-mic:before, .ion-ios-mic-off:before, .ion-ios-mic-outline:before, .ion-ios-minus:before, .ion-ios-minus-empty:before, .ion-ios-minus-outline:before, .ion-ios-monitor:before, .ion-ios-monitor-outline:before, .ion-ios-moon:before, .ion-ios-moon-outline:before, .ion-ios-more:before, .ion-ios-more-outline:before, .ion-ios-musical-note:before, .ion-ios-musical-notes:before, .ion-ios-navigate:before, .ion-ios-navigate-outline:before, .ion-ios-nutrition:before, .ion-ios-nutrition-outline:before, .ion-ios-paper:before, .ion-ios-paper-outline:before, .ion-ios-paperplane:before, .ion-ios-paperplane-outline:before, .ion-ios-partlysunny:before, .ion-ios-partlysunny-outline:before, .ion-ios-pause:before, .ion-ios-pause-outline:before, .ion-ios-paw:before, .ion-ios-paw-outline:before, .ion-ios-people:before, .ion-ios-people-outline:before, .ion-ios-person:before, .ion-ios-person-outline:before, .ion-ios-personadd:before, .ion-ios-personadd-outline:before, .ion-ios-photos:before, .ion-ios-photos-outline:before, .ion-ios-pie:before, .ion-ios-pie-outline:before, .ion-ios-pint:before, .ion-ios-pint-outline:before, .ion-ios-play:before, .ion-ios-play-outline:before, .ion-ios-plus:before, .ion-ios-plus-empty:before, .ion-ios-plus-outline:before, .ion-ios-pricetag:before, .ion-ios-pricetag-outline:before, .ion-ios-pricetags:before, .ion-ios-pricetags-outline:before, .ion-ios-printer:before, .ion-ios-printer-outline:before, .ion-ios-pulse:before, .ion-ios-pulse-strong:before, .ion-ios-rainy:before, .ion-ios-rainy-outline:before, .ion-ios-recording:before, .ion-ios-recording-outline:before, .ion-ios-redo:before, .ion-ios-redo-outline:before, .ion-ios-refresh:before, .ion-ios-refresh-empty:before, .ion-ios-refresh-outline:before, .ion-ios-reload:before, .ion-ios-reverse-camera:before, .ion-ios-reverse-camera-outline:before, .ion-ios-rewind:before, .ion-ios-rewind-outline:before, .ion-ios-rose:before, .ion-ios-rose-outline:before, .ion-ios-search:before, .ion-ios-search-strong:before, .ion-ios-settings:before, .ion-ios-settings-strong:before, .ion-ios-shuffle:before, .ion-ios-shuffle-strong:before, .ion-ios-skipbackward:before, .ion-ios-skipbackward-outline:before, .ion-ios-skipforward:before, .ion-ios-skipforward-outline:before, .ion-ios-snowy:before, .ion-ios-speedometer:before, .ion-ios-speedometer-outline:before, .ion-ios-star:before, .ion-ios-star-half:before, .ion-ios-star-outline:before, .ion-ios-stopwatch:before, .ion-ios-stopwatch-outline:before, .ion-ios-sunny:before, .ion-ios-sunny-outline:before, .ion-ios-telephone:before, .ion-ios-telephone-outline:before, .ion-ios-tennisball:before, .ion-ios-tennisball-outline:before, .ion-ios-thunderstorm:before, .ion-ios-thunderstorm-outline:before, .ion-ios-time:before, .ion-ios-time-outline:before, .ion-ios-timer:before, .ion-ios-timer-outline:before, .ion-ios-toggle:before, .ion-ios-toggle-outline:before, .ion-ios-trash:before, .ion-ios-trash-outline:before, .ion-ios-undo:before, .ion-ios-undo-outline:before, .ion-ios-unlocked:before, .ion-ios-unlocked-outline:before, .ion-ios-upload:before, .ion-ios-upload-outline:before, .ion-ios-videocam:before, .ion-ios-videocam-outline:before, .ion-ios-volume-high:before, .ion-ios-volume-low:before, .ion-ios-wineglass:before, .ion-ios-wineglass-outline:before, .ion-ios-world:before, .ion-ios-world-outline:before, .ion-ipad:before, .ion-iphone:before, .ion-ipod:before, .ion-jet:before, .ion-key:before, .ion-knife:before, .ion-laptop:before, .ion-leaf:before, .ion-levels:before, .ion-lightbulb:before, .ion-link:before, .ion-load-a:before, .ion-load-b:before, .ion-load-c:before, .ion-load-d:before, .ion-location:before, .ion-lock-combination:before, .ion-locked:before, .ion-log-in:before, .ion-log-out:before, .ion-loop:before, .ion-magnet:before, .ion-male:before, .ion-man:before, .ion-map:before, .ion-medkit:before, .ion-merge:before, .ion-mic-a:before, .ion-mic-b:before, .ion-mic-c:before, .ion-minus:before, .ion-minus-circled:before, .ion-minus-round:before, .ion-model-s:before, .ion-monitor:before, .ion-more:before, .ion-mouse:before, .ion-music-note:before, .ion-navicon:before, .ion-navicon-round:before, .ion-navigate:before, .ion-network:before, .ion-no-smoking:before, .ion-nuclear:before, .ion-outlet:before, .ion-paintbrush:before, .ion-paintbucket:before, .ion-paper-airplane:before, .ion-paperclip:before, .ion-pause:before, .ion-person:before, .ion-person-add:before, .ion-person-stalker:before, .ion-pie-graph:before, .ion-pin:before, .ion-pinpoint:before, .ion-pizza:before, .ion-plane:before, .ion-planet:before, .ion-play:before, .ion-playstation:before, .ion-plus:before, .ion-plus-circled:before, .ion-plus-round:before, .ion-podium:before, .ion-pound:before, .ion-power:before, .ion-pricetag:before, .ion-pricetags:before, .ion-printer:before, .ion-pull-request:before, .ion-qr-scanner:before, .ion-quote:before, .ion-radio-waves:before, .ion-record:before, .ion-refresh:before, .ion-reply:before, .ion-reply-all:before, .ion-ribbon-a:before, .ion-ribbon-b:before, .ion-sad:before, .ion-sad-outline:before, .ion-scissors:before, .ion-search:before, .ion-settings:before, .ion-share:before, .ion-shuffle:before, .ion-skip-backward:before, .ion-skip-forward:before, .ion-social-android:before, .ion-social-android-outline:before, .ion-social-angular:before, .ion-social-angular-outline:before, .ion-social-apple:before, .ion-social-apple-outline:before, .ion-social-bitcoin:before, .ion-social-bitcoin-outline:before, .ion-social-buffer:before, .ion-social-buffer-outline:before, .ion-social-chrome:before, .ion-social-chrome-outline:before, .ion-social-codepen:before, .ion-social-codepen-outline:before, .ion-social-css3:before, .ion-social-css3-outline:before, .ion-social-designernews:before, .ion-social-designernews-outline:before, .ion-social-dribbble:before, .ion-social-dribbble-outline:before, .ion-social-dropbox:before, .ion-social-dropbox-outline:before, .ion-social-euro:before, .ion-social-euro-outline:before, .ion-social-facebook:before, .ion-social-facebook-outline:before, .ion-social-foursquare:before, .ion-social-foursquare-outline:before, .ion-social-freebsd-devil:before, .ion-social-github:before, .ion-social-github-outline:before, .ion-social-google:before, .ion-social-google-outline:before, .ion-social-googleplus:before, .ion-social-googleplus-outline:before, .ion-social-hackernews:before, .ion-social-hackernews-outline:before, .ion-social-html5:before, .ion-social-html5-outline:before, .ion-social-instagram:before, .ion-social-instagram-outline:before, .ion-social-javascript:before, .ion-social-javascript-outline:before, .ion-social-linkedin:before, .ion-social-linkedin-outline:before, .ion-social-markdown:before, .ion-social-nodejs:before, .ion-social-octocat:before, .ion-social-pinterest:before, .ion-social-pinterest-outline:before, .ion-social-python:before, .ion-social-reddit:before, .ion-social-reddit-outline:before, .ion-social-rss:before, .ion-social-rss-outline:before, .ion-social-sass:before, .ion-social-skype:before, .ion-social-skype-outline:before, .ion-social-snapchat:before, .ion-social-snapchat-outline:before, .ion-social-tumblr:before, .ion-social-tumblr-outline:before, .ion-social-tux:before, .ion-social-twitch:before, .ion-social-twitch-outline:before, .ion-social-twitter:before, .ion-social-twitter-outline:before, .ion-social-usd:before, .ion-social-usd-outline:before, .ion-social-vimeo:before, .ion-social-vimeo-outline:before, .ion-social-whatsapp:before, .ion-social-whatsapp-outline:before, .ion-social-windows:before, .ion-social-windows-outline:before, .ion-social-wordpress:before, .ion-social-wordpress-outline:before, .ion-social-yahoo:before, .ion-social-yahoo-outline:before, .ion-social-yen:before, .ion-social-yen-outline:before, .ion-social-youtube:before, .ion-social-youtube-outline:before, .ion-soup-can:before, .ion-soup-can-outline:before, .ion-speakerphone:before, .ion-speedometer:before, .ion-spoon:before, .ion-star:before, .ion-stats-bars:before, .ion-steam:before, .ion-stop:before, .ion-thermometer:before, .ion-thumbsdown:before, .ion-thumbsup:before, .ion-toggle:before, .ion-toggle-filled:before, .ion-transgender:before, .ion-trash-a:before, .ion-trash-b:before, .ion-trophy:before, .ion-tshirt:before, .ion-tshirt-outline:before, .ion-umbrella:before, .ion-university:before, .ion-unlocked:before, .ion-upload:before, .ion-usb:before, .ion-videocamera:before, .ion-volume-high:before, .ion-volume-low:before, .ion-volume-medium:before, .ion-volume-mute:before, .ion-wand:before, .ion-waterdrop:before, .ion-wifi:before, .ion-wineglass:before, .ion-woman:before, .ion-wrench:before, .ion-xbox:before { +.ion, .ionicons, +.ion-alert:before, +.ion-alert-circled:before, +.ion-android-add:before, +.ion-android-add-circle:before, +.ion-android-alarm-clock:before, +.ion-android-alert:before, +.ion-android-apps:before, +.ion-android-archive:before, +.ion-android-arrow-back:before, +.ion-android-arrow-down:before, +.ion-android-arrow-dropdown:before, +.ion-android-arrow-dropdown-circle:before, +.ion-android-arrow-dropleft:before, +.ion-android-arrow-dropleft-circle:before, +.ion-android-arrow-dropright:before, +.ion-android-arrow-dropright-circle:before, +.ion-android-arrow-dropup:before, +.ion-android-arrow-dropup-circle:before, +.ion-android-arrow-forward:before, +.ion-android-arrow-up:before, +.ion-android-attach:before, +.ion-android-bar:before, +.ion-android-bicycle:before, +.ion-android-boat:before, +.ion-android-bookmark:before, +.ion-android-bulb:before, +.ion-android-bus:before, +.ion-android-calendar:before, +.ion-android-call:before, +.ion-android-camera:before, +.ion-android-cancel:before, +.ion-android-car:before, +.ion-android-cart:before, +.ion-android-chat:before, +.ion-android-checkbox:before, +.ion-android-checkbox-blank:before, +.ion-android-checkbox-outline:before, +.ion-android-checkbox-outline-blank:before, +.ion-android-checkmark-circle:before, +.ion-android-clipboard:before, +.ion-android-close:before, +.ion-android-cloud:before, +.ion-android-cloud-circle:before, +.ion-android-cloud-done:before, +.ion-android-cloud-outline:before, +.ion-android-color-palette:before, +.ion-android-compass:before, +.ion-android-contact:before, +.ion-android-contacts:before, +.ion-android-contract:before, +.ion-android-create:before, +.ion-android-delete:before, +.ion-android-desktop:before, +.ion-android-document:before, +.ion-android-done:before, +.ion-android-done-all:before, +.ion-android-download:before, +.ion-android-drafts:before, +.ion-android-exit:before, +.ion-android-expand:before, +.ion-android-favorite:before, +.ion-android-favorite-outline:before, +.ion-android-film:before, +.ion-android-folder:before, +.ion-android-folder-open:before, +.ion-android-funnel:before, +.ion-android-globe:before, +.ion-android-hand:before, +.ion-android-hangout:before, +.ion-android-happy:before, +.ion-android-home:before, +.ion-android-image:before, +.ion-android-laptop:before, +.ion-android-list:before, +.ion-android-locate:before, +.ion-android-lock:before, +.ion-android-mail:before, +.ion-android-map:before, +.ion-android-menu:before, +.ion-android-microphone:before, +.ion-android-microphone-off:before, +.ion-android-more-horizontal:before, +.ion-android-more-vertical:before, +.ion-android-navigate:before, +.ion-android-notifications:before, +.ion-android-notifications-none:before, +.ion-android-notifications-off:before, +.ion-android-open:before, +.ion-android-options:before, +.ion-android-people:before, +.ion-android-person:before, +.ion-android-person-add:before, +.ion-android-phone-landscape:before, +.ion-android-phone-portrait:before, +.ion-android-pin:before, +.ion-android-plane:before, +.ion-android-playstore:before, +.ion-android-print:before, +.ion-android-radio-button-off:before, +.ion-android-radio-button-on:before, +.ion-android-refresh:before, +.ion-android-remove:before, +.ion-android-remove-circle:before, +.ion-android-restaurant:before, +.ion-android-sad:before, +.ion-android-search:before, +.ion-android-send:before, +.ion-android-settings:before, +.ion-android-share:before, +.ion-android-share-alt:before, +.ion-android-star:before, +.ion-android-star-half:before, +.ion-android-star-outline:before, +.ion-android-stopwatch:before, +.ion-android-subway:before, +.ion-android-sunny:before, +.ion-android-sync:before, +.ion-android-textsms:before, +.ion-android-time:before, +.ion-android-train:before, +.ion-android-unlock:before, +.ion-android-upload:before, +.ion-android-volume-down:before, +.ion-android-volume-mute:before, +.ion-android-volume-off:before, +.ion-android-volume-up:before, +.ion-android-walk:before, +.ion-android-warning:before, +.ion-android-watch:before, +.ion-android-wifi:before, +.ion-aperture:before, +.ion-archive:before, +.ion-arrow-down-a:before, +.ion-arrow-down-b:before, +.ion-arrow-down-c:before, +.ion-arrow-expand:before, +.ion-arrow-graph-down-left:before, +.ion-arrow-graph-down-right:before, +.ion-arrow-graph-up-left:before, +.ion-arrow-graph-up-right:before, +.ion-arrow-left-a:before, +.ion-arrow-left-b:before, +.ion-arrow-left-c:before, +.ion-arrow-move:before, +.ion-arrow-resize:before, +.ion-arrow-return-left:before, +.ion-arrow-return-right:before, +.ion-arrow-right-a:before, +.ion-arrow-right-b:before, +.ion-arrow-right-c:before, +.ion-arrow-shrink:before, +.ion-arrow-swap:before, +.ion-arrow-up-a:before, +.ion-arrow-up-b:before, +.ion-arrow-up-c:before, +.ion-asterisk:before, +.ion-at:before, +.ion-backspace:before, +.ion-backspace-outline:before, +.ion-bag:before, +.ion-battery-charging:before, +.ion-battery-empty:before, +.ion-battery-full:before, +.ion-battery-half:before, +.ion-battery-low:before, +.ion-beaker:before, +.ion-beer:before, +.ion-bluetooth:before, +.ion-bonfire:before, +.ion-bookmark:before, +.ion-bowtie:before, +.ion-briefcase:before, +.ion-bug:before, +.ion-calculator:before, +.ion-calendar:before, +.ion-camera:before, +.ion-card:before, +.ion-cash:before, +.ion-chatbox:before, +.ion-chatbox-working:before, +.ion-chatboxes:before, +.ion-chatbubble:before, +.ion-chatbubble-working:before, +.ion-chatbubbles:before, +.ion-checkmark:before, +.ion-checkmark-circled:before, +.ion-checkmark-round:before, +.ion-chevron-down:before, +.ion-chevron-left:before, +.ion-chevron-right:before, +.ion-chevron-up:before, +.ion-clipboard:before, +.ion-clock:before, +.ion-close:before, +.ion-close-circled:before, +.ion-close-round:before, +.ion-closed-captioning:before, +.ion-cloud:before, +.ion-code:before, +.ion-code-download:before, +.ion-code-working:before, +.ion-coffee:before, +.ion-compass:before, +.ion-compose:before, +.ion-connection-bars:before, +.ion-contrast:before, +.ion-crop:before, +.ion-cube:before, +.ion-disc:before, +.ion-document:before, +.ion-document-text:before, +.ion-drag:before, +.ion-earth:before, +.ion-easel:before, +.ion-edit:before, +.ion-egg:before, +.ion-eject:before, +.ion-email:before, +.ion-email-unread:before, +.ion-erlenmeyer-flask:before, +.ion-erlenmeyer-flask-bubbles:before, +.ion-eye:before, +.ion-eye-disabled:before, +.ion-female:before, +.ion-filing:before, +.ion-film-marker:before, +.ion-fireball:before, +.ion-flag:before, +.ion-flame:before, +.ion-flash:before, +.ion-flash-off:before, +.ion-folder:before, +.ion-fork:before, +.ion-fork-repo:before, +.ion-forward:before, +.ion-funnel:before, +.ion-gear-a:before, +.ion-gear-b:before, +.ion-grid:before, +.ion-hammer:before, +.ion-happy:before, +.ion-happy-outline:before, +.ion-headphone:before, +.ion-heart:before, +.ion-heart-broken:before, +.ion-help:before, +.ion-help-buoy:before, +.ion-help-circled:before, +.ion-home:before, +.ion-icecream:before, +.ion-image:before, +.ion-images:before, +.ion-information:before, +.ion-information-circled:before, +.ion-ionic:before, +.ion-ios-alarm:before, +.ion-ios-alarm-outline:before, +.ion-ios-albums:before, +.ion-ios-albums-outline:before, +.ion-ios-americanfootball:before, +.ion-ios-americanfootball-outline:before, +.ion-ios-analytics:before, +.ion-ios-analytics-outline:before, +.ion-ios-arrow-back:before, +.ion-ios-arrow-down:before, +.ion-ios-arrow-forward:before, +.ion-ios-arrow-left:before, +.ion-ios-arrow-right:before, +.ion-ios-arrow-thin-down:before, +.ion-ios-arrow-thin-left:before, +.ion-ios-arrow-thin-right:before, +.ion-ios-arrow-thin-up:before, +.ion-ios-arrow-up:before, +.ion-ios-at:before, +.ion-ios-at-outline:before, +.ion-ios-barcode:before, +.ion-ios-barcode-outline:before, +.ion-ios-baseball:before, +.ion-ios-baseball-outline:before, +.ion-ios-basketball:before, +.ion-ios-basketball-outline:before, +.ion-ios-bell:before, +.ion-ios-bell-outline:before, +.ion-ios-body:before, +.ion-ios-body-outline:before, +.ion-ios-bolt:before, +.ion-ios-bolt-outline:before, +.ion-ios-book:before, +.ion-ios-book-outline:before, +.ion-ios-bookmarks:before, +.ion-ios-bookmarks-outline:before, +.ion-ios-box:before, +.ion-ios-box-outline:before, +.ion-ios-briefcase:before, +.ion-ios-briefcase-outline:before, +.ion-ios-browsers:before, +.ion-ios-browsers-outline:before, +.ion-ios-calculator:before, +.ion-ios-calculator-outline:before, +.ion-ios-calendar:before, +.ion-ios-calendar-outline:before, +.ion-ios-camera:before, +.ion-ios-camera-outline:before, +.ion-ios-cart:before, +.ion-ios-cart-outline:before, +.ion-ios-chatboxes:before, +.ion-ios-chatboxes-outline:before, +.ion-ios-chatbubble:before, +.ion-ios-chatbubble-outline:before, +.ion-ios-checkmark:before, +.ion-ios-checkmark-empty:before, +.ion-ios-checkmark-outline:before, +.ion-ios-circle-filled:before, +.ion-ios-circle-outline:before, +.ion-ios-clock:before, +.ion-ios-clock-outline:before, +.ion-ios-close:before, +.ion-ios-close-empty:before, +.ion-ios-close-outline:before, +.ion-ios-cloud:before, +.ion-ios-cloud-download:before, +.ion-ios-cloud-download-outline:before, +.ion-ios-cloud-outline:before, +.ion-ios-cloud-upload:before, +.ion-ios-cloud-upload-outline:before, +.ion-ios-cloudy:before, +.ion-ios-cloudy-night:before, +.ion-ios-cloudy-night-outline:before, +.ion-ios-cloudy-outline:before, +.ion-ios-cog:before, +.ion-ios-cog-outline:before, +.ion-ios-color-filter:before, +.ion-ios-color-filter-outline:before, +.ion-ios-color-wand:before, +.ion-ios-color-wand-outline:before, +.ion-ios-compose:before, +.ion-ios-compose-outline:before, +.ion-ios-contact:before, +.ion-ios-contact-outline:before, +.ion-ios-copy:before, +.ion-ios-copy-outline:before, +.ion-ios-crop:before, +.ion-ios-crop-strong:before, +.ion-ios-download:before, +.ion-ios-download-outline:before, +.ion-ios-drag:before, +.ion-ios-email:before, +.ion-ios-email-outline:before, +.ion-ios-eye:before, +.ion-ios-eye-outline:before, +.ion-ios-fastforward:before, +.ion-ios-fastforward-outline:before, +.ion-ios-filing:before, +.ion-ios-filing-outline:before, +.ion-ios-film:before, +.ion-ios-film-outline:before, +.ion-ios-flag:before, +.ion-ios-flag-outline:before, +.ion-ios-flame:before, +.ion-ios-flame-outline:before, +.ion-ios-flask:before, +.ion-ios-flask-outline:before, +.ion-ios-flower:before, +.ion-ios-flower-outline:before, +.ion-ios-folder:before, +.ion-ios-folder-outline:before, +.ion-ios-football:before, +.ion-ios-football-outline:before, +.ion-ios-game-controller-a:before, +.ion-ios-game-controller-a-outline:before, +.ion-ios-game-controller-b:before, +.ion-ios-game-controller-b-outline:before, +.ion-ios-gear:before, +.ion-ios-gear-outline:before, +.ion-ios-glasses:before, +.ion-ios-glasses-outline:before, +.ion-ios-grid-view:before, +.ion-ios-grid-view-outline:before, +.ion-ios-heart:before, +.ion-ios-heart-outline:before, +.ion-ios-help:before, +.ion-ios-help-empty:before, +.ion-ios-help-outline:before, +.ion-ios-home:before, +.ion-ios-home-outline:before, +.ion-ios-infinite:before, +.ion-ios-infinite-outline:before, +.ion-ios-information:before, +.ion-ios-information-empty:before, +.ion-ios-information-outline:before, +.ion-ios-ionic-outline:before, +.ion-ios-keypad:before, +.ion-ios-keypad-outline:before, +.ion-ios-lightbulb:before, +.ion-ios-lightbulb-outline:before, +.ion-ios-list:before, +.ion-ios-list-outline:before, +.ion-ios-location:before, +.ion-ios-location-outline:before, +.ion-ios-locked:before, +.ion-ios-locked-outline:before, +.ion-ios-loop:before, +.ion-ios-loop-strong:before, +.ion-ios-medical:before, +.ion-ios-medical-outline:before, +.ion-ios-medkit:before, +.ion-ios-medkit-outline:before, +.ion-ios-mic:before, +.ion-ios-mic-off:before, +.ion-ios-mic-outline:before, +.ion-ios-minus:before, +.ion-ios-minus-empty:before, +.ion-ios-minus-outline:before, +.ion-ios-monitor:before, +.ion-ios-monitor-outline:before, +.ion-ios-moon:before, +.ion-ios-moon-outline:before, +.ion-ios-more:before, +.ion-ios-more-outline:before, +.ion-ios-musical-note:before, +.ion-ios-musical-notes:before, +.ion-ios-navigate:before, +.ion-ios-navigate-outline:before, +.ion-ios-nutrition:before, +.ion-ios-nutrition-outline:before, +.ion-ios-paper:before, +.ion-ios-paper-outline:before, +.ion-ios-paperplane:before, +.ion-ios-paperplane-outline:before, +.ion-ios-partlysunny:before, +.ion-ios-partlysunny-outline:before, +.ion-ios-pause:before, +.ion-ios-pause-outline:before, +.ion-ios-paw:before, +.ion-ios-paw-outline:before, +.ion-ios-people:before, +.ion-ios-people-outline:before, +.ion-ios-person:before, +.ion-ios-person-outline:before, +.ion-ios-personadd:before, +.ion-ios-personadd-outline:before, +.ion-ios-photos:before, +.ion-ios-photos-outline:before, +.ion-ios-pie:before, +.ion-ios-pie-outline:before, +.ion-ios-pint:before, +.ion-ios-pint-outline:before, +.ion-ios-play:before, +.ion-ios-play-outline:before, +.ion-ios-plus:before, +.ion-ios-plus-empty:before, +.ion-ios-plus-outline:before, +.ion-ios-pricetag:before, +.ion-ios-pricetag-outline:before, +.ion-ios-pricetags:before, +.ion-ios-pricetags-outline:before, +.ion-ios-printer:before, +.ion-ios-printer-outline:before, +.ion-ios-pulse:before, +.ion-ios-pulse-strong:before, +.ion-ios-rainy:before, +.ion-ios-rainy-outline:before, +.ion-ios-recording:before, +.ion-ios-recording-outline:before, +.ion-ios-redo:before, +.ion-ios-redo-outline:before, +.ion-ios-refresh:before, +.ion-ios-refresh-empty:before, +.ion-ios-refresh-outline:before, +.ion-ios-reload:before, +.ion-ios-reverse-camera:before, +.ion-ios-reverse-camera-outline:before, +.ion-ios-rewind:before, +.ion-ios-rewind-outline:before, +.ion-ios-rose:before, +.ion-ios-rose-outline:before, +.ion-ios-search:before, +.ion-ios-search-strong:before, +.ion-ios-settings:before, +.ion-ios-settings-strong:before, +.ion-ios-shuffle:before, +.ion-ios-shuffle-strong:before, +.ion-ios-skipbackward:before, +.ion-ios-skipbackward-outline:before, +.ion-ios-skipforward:before, +.ion-ios-skipforward-outline:before, +.ion-ios-snowy:before, +.ion-ios-speedometer:before, +.ion-ios-speedometer-outline:before, +.ion-ios-star:before, +.ion-ios-star-half:before, +.ion-ios-star-outline:before, +.ion-ios-stopwatch:before, +.ion-ios-stopwatch-outline:before, +.ion-ios-sunny:before, +.ion-ios-sunny-outline:before, +.ion-ios-telephone:before, +.ion-ios-telephone-outline:before, +.ion-ios-tennisball:before, +.ion-ios-tennisball-outline:before, +.ion-ios-thunderstorm:before, +.ion-ios-thunderstorm-outline:before, +.ion-ios-time:before, +.ion-ios-time-outline:before, +.ion-ios-timer:before, +.ion-ios-timer-outline:before, +.ion-ios-toggle:before, +.ion-ios-toggle-outline:before, +.ion-ios-trash:before, +.ion-ios-trash-outline:before, +.ion-ios-undo:before, +.ion-ios-undo-outline:before, +.ion-ios-unlocked:before, +.ion-ios-unlocked-outline:before, +.ion-ios-upload:before, +.ion-ios-upload-outline:before, +.ion-ios-videocam:before, +.ion-ios-videocam-outline:before, +.ion-ios-volume-high:before, +.ion-ios-volume-low:before, +.ion-ios-wineglass:before, +.ion-ios-wineglass-outline:before, +.ion-ios-world:before, +.ion-ios-world-outline:before, +.ion-ipad:before, +.ion-iphone:before, +.ion-ipod:before, +.ion-jet:before, +.ion-key:before, +.ion-knife:before, +.ion-laptop:before, +.ion-leaf:before, +.ion-levels:before, +.ion-lightbulb:before, +.ion-link:before, +.ion-load-a:before, +.ion-load-b:before, +.ion-load-c:before, +.ion-load-d:before, +.ion-location:before, +.ion-lock-combination:before, +.ion-locked:before, +.ion-log-in:before, +.ion-log-out:before, +.ion-loop:before, +.ion-magnet:before, +.ion-male:before, +.ion-man:before, +.ion-map:before, +.ion-medkit:before, +.ion-merge:before, +.ion-mic-a:before, +.ion-mic-b:before, +.ion-mic-c:before, +.ion-minus:before, +.ion-minus-circled:before, +.ion-minus-round:before, +.ion-model-s:before, +.ion-monitor:before, +.ion-more:before, +.ion-mouse:before, +.ion-music-note:before, +.ion-navicon:before, +.ion-navicon-round:before, +.ion-navigate:before, +.ion-network:before, +.ion-no-smoking:before, +.ion-nuclear:before, +.ion-outlet:before, +.ion-paintbrush:before, +.ion-paintbucket:before, +.ion-paper-airplane:before, +.ion-paperclip:before, +.ion-pause:before, +.ion-person:before, +.ion-person-add:before, +.ion-person-stalker:before, +.ion-pie-graph:before, +.ion-pin:before, +.ion-pinpoint:before, +.ion-pizza:before, +.ion-plane:before, +.ion-planet:before, +.ion-play:before, +.ion-playstation:before, +.ion-plus:before, +.ion-plus-circled:before, +.ion-plus-round:before, +.ion-podium:before, +.ion-pound:before, +.ion-power:before, +.ion-pricetag:before, +.ion-pricetags:before, +.ion-printer:before, +.ion-pull-request:before, +.ion-qr-scanner:before, +.ion-quote:before, +.ion-radio-waves:before, +.ion-record:before, +.ion-refresh:before, +.ion-reply:before, +.ion-reply-all:before, +.ion-ribbon-a:before, +.ion-ribbon-b:before, +.ion-sad:before, +.ion-sad-outline:before, +.ion-scissors:before, +.ion-search:before, +.ion-settings:before, +.ion-share:before, +.ion-shuffle:before, +.ion-skip-backward:before, +.ion-skip-forward:before, +.ion-social-android:before, +.ion-social-android-outline:before, +.ion-social-angular:before, +.ion-social-angular-outline:before, +.ion-social-apple:before, +.ion-social-apple-outline:before, +.ion-social-bitcoin:before, +.ion-social-bitcoin-outline:before, +.ion-social-buffer:before, +.ion-social-buffer-outline:before, +.ion-social-chrome:before, +.ion-social-chrome-outline:before, +.ion-social-codepen:before, +.ion-social-codepen-outline:before, +.ion-social-css3:before, +.ion-social-css3-outline:before, +.ion-social-designernews:before, +.ion-social-designernews-outline:before, +.ion-social-dribbble:before, +.ion-social-dribbble-outline:before, +.ion-social-dropbox:before, +.ion-social-dropbox-outline:before, +.ion-social-euro:before, +.ion-social-euro-outline:before, +.ion-social-facebook:before, +.ion-social-facebook-outline:before, +.ion-social-foursquare:before, +.ion-social-foursquare-outline:before, +.ion-social-freebsd-devil:before, +.ion-social-github:before, +.ion-social-github-outline:before, +.ion-social-google:before, +.ion-social-google-outline:before, +.ion-social-googleplus:before, +.ion-social-googleplus-outline:before, +.ion-social-hackernews:before, +.ion-social-hackernews-outline:before, +.ion-social-html5:before, +.ion-social-html5-outline:before, +.ion-social-instagram:before, +.ion-social-instagram-outline:before, +.ion-social-javascript:before, +.ion-social-javascript-outline:before, +.ion-social-linkedin:before, +.ion-social-linkedin-outline:before, +.ion-social-markdown:before, +.ion-social-nodejs:before, +.ion-social-octocat:before, +.ion-social-pinterest:before, +.ion-social-pinterest-outline:before, +.ion-social-python:before, +.ion-social-reddit:before, +.ion-social-reddit-outline:before, +.ion-social-rss:before, +.ion-social-rss-outline:before, +.ion-social-sass:before, +.ion-social-skype:before, +.ion-social-skype-outline:before, +.ion-social-snapchat:before, +.ion-social-snapchat-outline:before, +.ion-social-tumblr:before, +.ion-social-tumblr-outline:before, +.ion-social-tux:before, +.ion-social-twitch:before, +.ion-social-twitch-outline:before, +.ion-social-twitter:before, +.ion-social-twitter-outline:before, +.ion-social-usd:before, +.ion-social-usd-outline:before, +.ion-social-vimeo:before, +.ion-social-vimeo-outline:before, +.ion-social-whatsapp:before, +.ion-social-whatsapp-outline:before, +.ion-social-windows:before, +.ion-social-windows-outline:before, +.ion-social-wordpress:before, +.ion-social-wordpress-outline:before, +.ion-social-yahoo:before, +.ion-social-yahoo-outline:before, +.ion-social-yen:before, +.ion-social-yen-outline:before, +.ion-social-youtube:before, +.ion-social-youtube-outline:before, +.ion-soup-can:before, +.ion-soup-can-outline:before, +.ion-speakerphone:before, +.ion-speedometer:before, +.ion-spoon:before, +.ion-star:before, +.ion-stats-bars:before, +.ion-steam:before, +.ion-stop:before, +.ion-thermometer:before, +.ion-thumbsdown:before, +.ion-thumbsup:before, +.ion-toggle:before, +.ion-toggle-filled:before, +.ion-transgender:before, +.ion-trash-a:before, +.ion-trash-b:before, +.ion-trophy:before, +.ion-tshirt:before, +.ion-tshirt-outline:before, +.ion-umbrella:before, +.ion-university:before, +.ion-unlocked:before, +.ion-upload:before, +.ion-usb:before, +.ion-videocamera:before, +.ion-volume-high:before, +.ion-volume-low:before, +.ion-volume-medium:before, +.ion-volume-mute:before, +.ion-wand:before, +.ion-waterdrop:before, +.ion-wifi:before, +.ion-wineglass:before, +.ion-woman:before, +.ion-wrench:before, +.ion-xbox:before { display: inline-block; font-family: "Ionicons"; speak: none; @@ -43,2203 +777,2203 @@ -moz-osx-font-smoothing: grayscale; } .ion-alert:before { - content: "\f101"; } + content: "ï„"; } .ion-alert-circled:before { - content: "\f100"; } + content: "ï„€"; } .ion-android-add:before { - content: "\f2c7"; } + content: ""; } .ion-android-add-circle:before { - content: "\f359"; } + content: "ï™"; } .ion-android-alarm-clock:before { - content: "\f35a"; } + content: "ïš"; } .ion-android-alert:before { - content: "\f35b"; } + content: "ï›"; } .ion-android-apps:before { - content: "\f35c"; } + content: "ïœ"; } .ion-android-archive:before { - content: "\f2c9"; } + content: ""; } .ion-android-arrow-back:before { - content: "\f2ca"; } + content: ""; } .ion-android-arrow-down:before { - content: "\f35d"; } + content: "ï"; } .ion-android-arrow-dropdown:before { - content: "\f35f"; } + content: "ïŸ"; } .ion-android-arrow-dropdown-circle:before { - content: "\f35e"; } + content: "ïž"; } .ion-android-arrow-dropleft:before { - content: "\f361"; } + content: "ï¡"; } .ion-android-arrow-dropleft-circle:before { - content: "\f360"; } + content: "ï "; } .ion-android-arrow-dropright:before { - content: "\f363"; } + content: "ï£"; } .ion-android-arrow-dropright-circle:before { - content: "\f362"; } + content: "ï¢"; } .ion-android-arrow-dropup:before { - content: "\f365"; } + content: "ï¥"; } .ion-android-arrow-dropup-circle:before { - content: "\f364"; } + content: "ï¤"; } .ion-android-arrow-forward:before { - content: "\f30f"; } + content: "ïŒ"; } .ion-android-arrow-up:before { - content: "\f366"; } + content: "ï¦"; } .ion-android-attach:before { - content: "\f367"; } + content: "ï§"; } .ion-android-bar:before { - content: "\f368"; } + content: "ï¨"; } .ion-android-bicycle:before { - content: "\f369"; } + content: "ï©"; } .ion-android-boat:before { - content: "\f36a"; } + content: "ïª"; } .ion-android-bookmark:before { - content: "\f36b"; } + content: "ï«"; } .ion-android-bulb:before { - content: "\f36c"; } + content: "ï¬"; } .ion-android-bus:before { - content: "\f36d"; } + content: "ï"; } .ion-android-calendar:before { - content: "\f2d1"; } + content: "ï‹‘"; } .ion-android-call:before { - content: "\f2d2"; } + content: "ï‹’"; } .ion-android-camera:before { - content: "\f2d3"; } + content: "ï‹“"; } .ion-android-cancel:before { - content: "\f36e"; } + content: "ï®"; } .ion-android-car:before { - content: "\f36f"; } + content: "ï¯"; } .ion-android-cart:before { - content: "\f370"; } + content: "ï°"; } .ion-android-chat:before { - content: "\f2d4"; } + content: "ï‹”"; } .ion-android-checkbox:before { - content: "\f374"; } + content: "ï´"; } .ion-android-checkbox-blank:before { - content: "\f371"; } + content: "ï±"; } .ion-android-checkbox-outline:before { - content: "\f373"; } + content: "ï³"; } .ion-android-checkbox-outline-blank:before { - content: "\f372"; } + content: "ï²"; } .ion-android-checkmark-circle:before { - content: "\f375"; } + content: "ïµ"; } .ion-android-clipboard:before { - content: "\f376"; } + content: "ï¶"; } .ion-android-close:before { - content: "\f2d7"; } + content: "ï‹—"; } .ion-android-cloud:before { - content: "\f37a"; } + content: "ïº"; } .ion-android-cloud-circle:before { - content: "\f377"; } + content: "ï·"; } .ion-android-cloud-done:before { - content: "\f378"; } + content: "ï¸"; } .ion-android-cloud-outline:before { - content: "\f379"; } + content: "ï¹"; } .ion-android-color-palette:before { - content: "\f37b"; } + content: "ï»"; } .ion-android-compass:before { - content: "\f37c"; } + content: "ï¼"; } .ion-android-contact:before { - content: "\f2d8"; } + content: ""; } .ion-android-contacts:before { - content: "\f2d9"; } + content: "ï‹™"; } .ion-android-contract:before { - content: "\f37d"; } + content: "ï½"; } .ion-android-create:before { - content: "\f37e"; } + content: "ï¾"; } .ion-android-delete:before { - content: "\f37f"; } + content: "ï¿"; } .ion-android-desktop:before { - content: "\f380"; } + content: ""; } .ion-android-document:before { - content: "\f381"; } + content: "ïŽ"; } .ion-android-done:before { - content: "\f383"; } + content: ""; } .ion-android-done-all:before { - content: "\f382"; } + content: ""; } .ion-android-download:before { - content: "\f2dd"; } + content: "ï‹"; } .ion-android-drafts:before { - content: "\f384"; } + content: ""; } .ion-android-exit:before { - content: "\f385"; } + content: ""; } .ion-android-expand:before { - content: "\f386"; } + content: ""; } .ion-android-favorite:before { - content: "\f388"; } + content: ""; } .ion-android-favorite-outline:before { - content: "\f387"; } + content: ""; } .ion-android-film:before { - content: "\f389"; } + content: ""; } .ion-android-folder:before { - content: "\f2e0"; } + content: "ï‹ "; } .ion-android-folder-open:before { - content: "\f38a"; } + content: ""; } .ion-android-funnel:before { - content: "\f38b"; } + content: ""; } .ion-android-globe:before { - content: "\f38c"; } + content: ""; } .ion-android-hand:before { - content: "\f2e3"; } + content: "ï‹£"; } .ion-android-hangout:before { - content: "\f38d"; } + content: "ïŽ"; } .ion-android-happy:before { - content: "\f38e"; } + content: ""; } .ion-android-home:before { - content: "\f38f"; } + content: "ïŽ"; } .ion-android-image:before { - content: "\f2e4"; } + content: ""; } .ion-android-laptop:before { - content: "\f390"; } + content: "ïŽ"; } .ion-android-list:before { - content: "\f391"; } + content: ""; } .ion-android-locate:before { - content: "\f2e9"; } + content: "ï‹©"; } .ion-android-lock:before { - content: "\f392"; } + content: ""; } .ion-android-mail:before { - content: "\f2eb"; } + content: "ï‹«"; } .ion-android-map:before { - content: "\f393"; } + content: ""; } .ion-android-menu:before { - content: "\f394"; } + content: ""; } .ion-android-microphone:before { - content: "\f2ec"; } + content: ""; } .ion-android-microphone-off:before { - content: "\f395"; } + content: ""; } .ion-android-more-horizontal:before { - content: "\f396"; } + content: ""; } .ion-android-more-vertical:before { - content: "\f397"; } + content: ""; } .ion-android-navigate:before { - content: "\f398"; } + content: ""; } .ion-android-notifications:before { - content: "\f39b"; } + content: ""; } .ion-android-notifications-none:before { - content: "\f399"; } + content: ""; } .ion-android-notifications-off:before { - content: "\f39a"; } + content: ""; } .ion-android-open:before { - content: "\f39c"; } + content: ""; } .ion-android-options:before { - content: "\f39d"; } + content: "ïŽ"; } .ion-android-people:before { - content: "\f39e"; } + content: ""; } .ion-android-person:before { - content: "\f3a0"; } + content: "ïŽ "; } .ion-android-person-add:before { - content: "\f39f"; } + content: ""; } .ion-android-phone-landscape:before { - content: "\f3a1"; } + content: ""; } .ion-android-phone-portrait:before { - content: "\f3a2"; } + content: ""; } .ion-android-pin:before { - content: "\f3a3"; } + content: ""; } .ion-android-plane:before { - content: "\f3a4"; } + content: ""; } .ion-android-playstore:before { - content: "\f2f0"; } + content: "ï‹°"; } .ion-android-print:before { - content: "\f3a5"; } + content: ""; } .ion-android-radio-button-off:before { - content: "\f3a6"; } + content: ""; } .ion-android-radio-button-on:before { - content: "\f3a7"; } + content: ""; } .ion-android-refresh:before { - content: "\f3a8"; } + content: ""; } .ion-android-remove:before { - content: "\f2f4"; } + content: "ï‹´"; } .ion-android-remove-circle:before { - content: "\f3a9"; } + content: ""; } .ion-android-restaurant:before { - content: "\f3aa"; } + content: ""; } .ion-android-sad:before { - content: "\f3ab"; } + content: ""; } .ion-android-search:before { - content: "\f2f5"; } + content: ""; } .ion-android-send:before { - content: "\f2f6"; } + content: "ï‹¶"; } .ion-android-settings:before { - content: "\f2f7"; } + content: "ï‹·"; } .ion-android-share:before { - content: "\f2f8"; } + content: ""; } .ion-android-share-alt:before { - content: "\f3ac"; } + content: ""; } .ion-android-star:before { - content: "\f2fc"; } + content: ""; } .ion-android-star-half:before { - content: "\f3ad"; } + content: "ïŽ"; } .ion-android-star-outline:before { - content: "\f3ae"; } + content: ""; } .ion-android-stopwatch:before { - content: "\f2fd"; } + content: ""; } .ion-android-subway:before { - content: "\f3af"; } + content: ""; } .ion-android-sunny:before { - content: "\f3b0"; } + content: ""; } .ion-android-sync:before { - content: "\f3b1"; } + content: ""; } .ion-android-textsms:before { - content: "\f3b2"; } + content: ""; } .ion-android-time:before { - content: "\f3b3"; } + content: ""; } .ion-android-train:before { - content: "\f3b4"; } + content: ""; } .ion-android-unlock:before { - content: "\f3b5"; } + content: ""; } .ion-android-upload:before { - content: "\f3b6"; } + content: ""; } .ion-android-volume-down:before { - content: "\f3b7"; } + content: ""; } .ion-android-volume-mute:before { - content: "\f3b8"; } + content: ""; } .ion-android-volume-off:before { - content: "\f3b9"; } + content: ""; } .ion-android-volume-up:before { - content: "\f3ba"; } + content: ""; } .ion-android-walk:before { - content: "\f3bb"; } + content: ""; } .ion-android-warning:before { - content: "\f3bc"; } + content: ""; } .ion-android-watch:before { - content: "\f3bd"; } + content: ""; } .ion-android-wifi:before { - content: "\f305"; } + content: ""; } .ion-aperture:before { - content: "\f313"; } + content: ""; } .ion-archive:before { - content: "\f102"; } + content: "ï„‚"; } .ion-arrow-down-a:before { - content: "\f103"; } + content: ""; } .ion-arrow-down-b:before { - content: "\f104"; } + content: "ï„„"; } .ion-arrow-down-c:before { - content: "\f105"; } + content: "ï„…"; } .ion-arrow-expand:before { - content: "\f25e"; } + content: ""; } .ion-arrow-graph-down-left:before { - content: "\f25f"; } + content: ""; } .ion-arrow-graph-down-right:before { - content: "\f260"; } + content: "ï‰ "; } .ion-arrow-graph-up-left:before { - content: "\f261"; } + content: ""; } .ion-arrow-graph-up-right:before { - content: "\f262"; } + content: ""; } .ion-arrow-left-a:before { - content: "\f106"; } + content: ""; } .ion-arrow-left-b:before { - content: "\f107"; } + content: ""; } .ion-arrow-left-c:before { - content: "\f108"; } + content: ""; } .ion-arrow-move:before { - content: "\f263"; } + content: ""; } .ion-arrow-resize:before { - content: "\f264"; } + content: ""; } .ion-arrow-return-left:before { - content: "\f265"; } + content: ""; } .ion-arrow-return-right:before { - content: "\f266"; } + content: ""; } .ion-arrow-right-a:before { - content: "\f109"; } + content: ""; } .ion-arrow-right-b:before { - content: "\f10a"; } + content: ""; } .ion-arrow-right-c:before { - content: "\f10b"; } + content: "ï„‹"; } .ion-arrow-shrink:before { - content: "\f267"; } + content: ""; } .ion-arrow-swap:before { - content: "\f268"; } + content: ""; } .ion-arrow-up-a:before { - content: "\f10c"; } + content: ""; } .ion-arrow-up-b:before { - content: "\f10d"; } + content: "ï„"; } .ion-arrow-up-c:before { - content: "\f10e"; } + content: ""; } .ion-asterisk:before { - content: "\f314"; } + content: ""; } .ion-at:before { - content: "\f10f"; } + content: "ï„"; } .ion-backspace:before { - content: "\f3bf"; } + content: ""; } .ion-backspace-outline:before { - content: "\f3be"; } + content: ""; } .ion-bag:before { - content: "\f110"; } + content: "ï„"; } .ion-battery-charging:before { - content: "\f111"; } + content: "ï„‘"; } .ion-battery-empty:before { - content: "\f112"; } + content: "ï„’"; } .ion-battery-full:before { - content: "\f113"; } + content: "ï„“"; } .ion-battery-half:before { - content: "\f114"; } + content: "ï„”"; } .ion-battery-low:before { - content: "\f115"; } + content: "ï„•"; } .ion-beaker:before { - content: "\f269"; } + content: ""; } .ion-beer:before { - content: "\f26a"; } + content: ""; } .ion-bluetooth:before { - content: "\f116"; } + content: "ï„–"; } .ion-bonfire:before { - content: "\f315"; } + content: ""; } .ion-bookmark:before { - content: "\f26b"; } + content: ""; } .ion-bowtie:before { - content: "\f3c0"; } + content: "ï€"; } .ion-briefcase:before { - content: "\f26c"; } + content: ""; } .ion-bug:before { - content: "\f2be"; } + content: ""; } .ion-calculator:before { - content: "\f26d"; } + content: "ï‰"; } .ion-calendar:before { - content: "\f117"; } + content: "ï„—"; } .ion-camera:before { - content: "\f118"; } + content: ""; } .ion-card:before { - content: "\f119"; } + content: "ï„™"; } .ion-cash:before { - content: "\f316"; } + content: ""; } .ion-chatbox:before { - content: "\f11b"; } + content: "ï„›"; } .ion-chatbox-working:before { - content: "\f11a"; } + content: ""; } .ion-chatboxes:before { - content: "\f11c"; } + content: ""; } .ion-chatbubble:before { - content: "\f11e"; } + content: ""; } .ion-chatbubble-working:before { - content: "\f11d"; } + content: "ï„"; } .ion-chatbubbles:before { - content: "\f11f"; } + content: ""; } .ion-checkmark:before { - content: "\f122"; } + content: "ï„¢"; } .ion-checkmark-circled:before { - content: "\f120"; } + content: "ï„ "; } .ion-checkmark-round:before { - content: "\f121"; } + content: "ï„¡"; } .ion-chevron-down:before { - content: "\f123"; } + content: "ï„£"; } .ion-chevron-left:before { - content: "\f124"; } + content: ""; } .ion-chevron-right:before { - content: "\f125"; } + content: "ï„¥"; } .ion-chevron-up:before { - content: "\f126"; } + content: ""; } .ion-clipboard:before { - content: "\f127"; } + content: "ï„§"; } .ion-clock:before { - content: "\f26e"; } + content: ""; } .ion-close:before { - content: "\f12a"; } + content: ""; } .ion-close-circled:before { - content: "\f128"; } + content: ""; } .ion-close-round:before { - content: "\f129"; } + content: "ï„©"; } .ion-closed-captioning:before { - content: "\f317"; } + content: ""; } .ion-cloud:before { - content: "\f12b"; } + content: "ï„«"; } .ion-code:before { - content: "\f271"; } + content: ""; } .ion-code-download:before { - content: "\f26f"; } + content: ""; } .ion-code-working:before { - content: "\f270"; } + content: ""; } .ion-coffee:before { - content: "\f272"; } + content: ""; } .ion-compass:before { - content: "\f273"; } + content: ""; } .ion-compose:before { - content: "\f12c"; } + content: ""; } .ion-connection-bars:before { - content: "\f274"; } + content: ""; } .ion-contrast:before { - content: "\f275"; } + content: ""; } .ion-crop:before { - content: "\f3c1"; } + content: "ï"; } .ion-cube:before { - content: "\f318"; } + content: ""; } .ion-disc:before { - content: "\f12d"; } + content: "ï„"; } .ion-document:before { - content: "\f12f"; } + content: ""; } .ion-document-text:before { - content: "\f12e"; } + content: "ï„®"; } .ion-drag:before { - content: "\f130"; } + content: "ï„°"; } .ion-earth:before { - content: "\f276"; } + content: ""; } .ion-easel:before { - content: "\f3c2"; } + content: "ï‚"; } .ion-edit:before { - content: "\f2bf"; } + content: ""; } .ion-egg:before { - content: "\f277"; } + content: ""; } .ion-eject:before { - content: "\f131"; } + content: ""; } .ion-email:before { - content: "\f132"; } + content: ""; } .ion-email-unread:before { - content: "\f3c3"; } + content: "ïƒ"; } .ion-erlenmeyer-flask:before { - content: "\f3c5"; } + content: "ï…"; } .ion-erlenmeyer-flask-bubbles:before { - content: "\f3c4"; } + content: "ï„"; } .ion-eye:before { - content: "\f133"; } + content: ""; } .ion-eye-disabled:before { - content: "\f306"; } + content: ""; } .ion-female:before { - content: "\f278"; } + content: ""; } .ion-filing:before { - content: "\f134"; } + content: "ï„´"; } .ion-film-marker:before { - content: "\f135"; } + content: ""; } .ion-fireball:before { - content: "\f319"; } + content: ""; } .ion-flag:before { - content: "\f279"; } + content: ""; } .ion-flame:before { - content: "\f31a"; } + content: ""; } .ion-flash:before { - content: "\f137"; } + content: "ï„·"; } .ion-flash-off:before { - content: "\f136"; } + content: "ï„¶"; } .ion-folder:before { - content: "\f139"; } + content: ""; } .ion-fork:before { - content: "\f27a"; } + content: ""; } .ion-fork-repo:before { - content: "\f2c0"; } + content: "ï‹€"; } .ion-forward:before { - content: "\f13a"; } + content: ""; } .ion-funnel:before { - content: "\f31b"; } + content: ""; } .ion-gear-a:before { - content: "\f13d"; } + content: ""; } .ion-gear-b:before { - content: "\f13e"; } + content: ""; } .ion-grid:before { - content: "\f13f"; } + content: "ï„¿"; } .ion-hammer:before { - content: "\f27b"; } + content: ""; } .ion-happy:before { - content: "\f31c"; } + content: ""; } .ion-happy-outline:before { - content: "\f3c6"; } + content: "ï†"; } .ion-headphone:before { - content: "\f140"; } + content: "ï…€"; } .ion-heart:before { - content: "\f141"; } + content: "ï…"; } .ion-heart-broken:before { - content: "\f31d"; } + content: "ïŒ"; } .ion-help:before { - content: "\f143"; } + content: "ï…ƒ"; } .ion-help-buoy:before { - content: "\f27c"; } + content: ""; } .ion-help-circled:before { - content: "\f142"; } + content: "ï…‚"; } .ion-home:before { - content: "\f144"; } + content: "ï…„"; } .ion-icecream:before { - content: "\f27d"; } + content: ""; } .ion-image:before { - content: "\f147"; } + content: "ï…‡"; } .ion-images:before { - content: "\f148"; } + content: "ï…ˆ"; } .ion-information:before { - content: "\f14a"; } + content: "ï…Š"; } .ion-information-circled:before { - content: "\f149"; } + content: "ï…‰"; } .ion-ionic:before { - content: "\f14b"; } + content: "ï…‹"; } .ion-ios-alarm:before { - content: "\f3c8"; } + content: "ïˆ"; } .ion-ios-alarm-outline:before { - content: "\f3c7"; } + content: "ï‡"; } .ion-ios-albums:before { - content: "\f3ca"; } + content: "ïŠ"; } .ion-ios-albums-outline:before { - content: "\f3c9"; } + content: "ï‰"; } .ion-ios-americanfootball:before { - content: "\f3cc"; } + content: "ïŒ"; } .ion-ios-americanfootball-outline:before { - content: "\f3cb"; } + content: "ï‹"; } .ion-ios-analytics:before { - content: "\f3ce"; } + content: "ïŽ"; } .ion-ios-analytics-outline:before { - content: "\f3cd"; } + content: "ï"; } .ion-ios-arrow-back:before { - content: "\f3cf"; } + content: "ï"; } .ion-ios-arrow-down:before { - content: "\f3d0"; } + content: "ï"; } .ion-ios-arrow-forward:before { - content: "\f3d1"; } + content: "ï‘"; } .ion-ios-arrow-left:before { - content: "\f3d2"; } + content: "ï’"; } .ion-ios-arrow-right:before { - content: "\f3d3"; } + content: "ï“"; } .ion-ios-arrow-thin-down:before { - content: "\f3d4"; } + content: "ï”"; } .ion-ios-arrow-thin-left:before { - content: "\f3d5"; } + content: "ï•"; } .ion-ios-arrow-thin-right:before { - content: "\f3d6"; } + content: "ï–"; } .ion-ios-arrow-thin-up:before { - content: "\f3d7"; } + content: "ï—"; } .ion-ios-arrow-up:before { - content: "\f3d8"; } + content: "ï˜"; } .ion-ios-at:before { - content: "\f3da"; } + content: "ïš"; } .ion-ios-at-outline:before { - content: "\f3d9"; } + content: "ï™"; } .ion-ios-barcode:before { - content: "\f3dc"; } + content: "ïœ"; } .ion-ios-barcode-outline:before { - content: "\f3db"; } + content: "ï›"; } .ion-ios-baseball:before { - content: "\f3de"; } + content: "ïž"; } .ion-ios-baseball-outline:before { - content: "\f3dd"; } + content: "ï"; } .ion-ios-basketball:before { - content: "\f3e0"; } + content: "ï "; } .ion-ios-basketball-outline:before { - content: "\f3df"; } + content: "ïŸ"; } .ion-ios-bell:before { - content: "\f3e2"; } + content: "ï¢"; } .ion-ios-bell-outline:before { - content: "\f3e1"; } + content: "ï¡"; } .ion-ios-body:before { - content: "\f3e4"; } + content: "ï¤"; } .ion-ios-body-outline:before { - content: "\f3e3"; } + content: "ï£"; } .ion-ios-bolt:before { - content: "\f3e6"; } + content: "ï¦"; } .ion-ios-bolt-outline:before { - content: "\f3e5"; } + content: "ï¥"; } .ion-ios-book:before { - content: "\f3e8"; } + content: "ï¨"; } .ion-ios-book-outline:before { - content: "\f3e7"; } + content: "ï§"; } .ion-ios-bookmarks:before { - content: "\f3ea"; } + content: "ïª"; } .ion-ios-bookmarks-outline:before { - content: "\f3e9"; } + content: "ï©"; } .ion-ios-box:before { - content: "\f3ec"; } + content: "ï¬"; } .ion-ios-box-outline:before { - content: "\f3eb"; } + content: "ï«"; } .ion-ios-briefcase:before { - content: "\f3ee"; } + content: "ï®"; } .ion-ios-briefcase-outline:before { - content: "\f3ed"; } + content: "ï"; } .ion-ios-browsers:before { - content: "\f3f0"; } + content: "ï°"; } .ion-ios-browsers-outline:before { - content: "\f3ef"; } + content: "ï¯"; } .ion-ios-calculator:before { - content: "\f3f2"; } + content: "ï²"; } .ion-ios-calculator-outline:before { - content: "\f3f1"; } + content: "ï±"; } .ion-ios-calendar:before { - content: "\f3f4"; } + content: "ï´"; } .ion-ios-calendar-outline:before { - content: "\f3f3"; } + content: "ï³"; } .ion-ios-camera:before { - content: "\f3f6"; } + content: "ï¶"; } .ion-ios-camera-outline:before { - content: "\f3f5"; } + content: "ïµ"; } .ion-ios-cart:before { - content: "\f3f8"; } + content: "ï¸"; } .ion-ios-cart-outline:before { - content: "\f3f7"; } + content: "ï·"; } .ion-ios-chatboxes:before { - content: "\f3fa"; } + content: "ïº"; } .ion-ios-chatboxes-outline:before { - content: "\f3f9"; } + content: "ï¹"; } .ion-ios-chatbubble:before { - content: "\f3fc"; } + content: "ï¼"; } .ion-ios-chatbubble-outline:before { - content: "\f3fb"; } + content: "ï»"; } .ion-ios-checkmark:before { - content: "\f3ff"; } + content: "ï¿"; } .ion-ios-checkmark-empty:before { - content: "\f3fd"; } + content: "ï½"; } .ion-ios-checkmark-outline:before { - content: "\f3fe"; } + content: "ï¾"; } .ion-ios-circle-filled:before { - content: "\f400"; } + content: "ï€"; } .ion-ios-circle-outline:before { - content: "\f401"; } + content: "ï"; } .ion-ios-clock:before { - content: "\f403"; } + content: "ïƒ"; } .ion-ios-clock-outline:before { - content: "\f402"; } + content: "ï‚"; } .ion-ios-close:before { - content: "\f406"; } + content: "ï†"; } .ion-ios-close-empty:before { - content: "\f404"; } + content: "ï„"; } .ion-ios-close-outline:before { - content: "\f405"; } + content: "ï…"; } .ion-ios-cloud:before { - content: "\f40c"; } + content: "ïŒ"; } .ion-ios-cloud-download:before { - content: "\f408"; } + content: "ïˆ"; } .ion-ios-cloud-download-outline:before { - content: "\f407"; } + content: "ï‡"; } .ion-ios-cloud-outline:before { - content: "\f409"; } + content: "ï‰"; } .ion-ios-cloud-upload:before { - content: "\f40b"; } + content: "ï‹"; } .ion-ios-cloud-upload-outline:before { - content: "\f40a"; } + content: "ïŠ"; } .ion-ios-cloudy:before { - content: "\f410"; } + content: "ï"; } .ion-ios-cloudy-night:before { - content: "\f40e"; } + content: "ïŽ"; } .ion-ios-cloudy-night-outline:before { - content: "\f40d"; } + content: "ï"; } .ion-ios-cloudy-outline:before { - content: "\f40f"; } + content: "ï"; } .ion-ios-cog:before { - content: "\f412"; } + content: "ï’"; } .ion-ios-cog-outline:before { - content: "\f411"; } + content: "ï‘"; } .ion-ios-color-filter:before { - content: "\f414"; } + content: "ï”"; } .ion-ios-color-filter-outline:before { - content: "\f413"; } + content: "ï“"; } .ion-ios-color-wand:before { - content: "\f416"; } + content: "ï–"; } .ion-ios-color-wand-outline:before { - content: "\f415"; } + content: "ï•"; } .ion-ios-compose:before { - content: "\f418"; } + content: "ï˜"; } .ion-ios-compose-outline:before { - content: "\f417"; } + content: "ï—"; } .ion-ios-contact:before { - content: "\f41a"; } + content: "ïš"; } .ion-ios-contact-outline:before { - content: "\f419"; } + content: "ï™"; } .ion-ios-copy:before { - content: "\f41c"; } + content: "ïœ"; } .ion-ios-copy-outline:before { - content: "\f41b"; } + content: "ï›"; } .ion-ios-crop:before { - content: "\f41e"; } + content: "ïž"; } .ion-ios-crop-strong:before { - content: "\f41d"; } + content: "ï"; } .ion-ios-download:before { - content: "\f420"; } + content: "ï "; } .ion-ios-download-outline:before { - content: "\f41f"; } + content: "ïŸ"; } .ion-ios-drag:before { - content: "\f421"; } + content: "ï¡"; } .ion-ios-email:before { - content: "\f423"; } + content: "ï£"; } .ion-ios-email-outline:before { - content: "\f422"; } + content: "ï¢"; } .ion-ios-eye:before { - content: "\f425"; } + content: "ï¥"; } .ion-ios-eye-outline:before { - content: "\f424"; } + content: "ï¤"; } .ion-ios-fastforward:before { - content: "\f427"; } + content: "ï§"; } .ion-ios-fastforward-outline:before { - content: "\f426"; } + content: "ï¦"; } .ion-ios-filing:before { - content: "\f429"; } + content: "ï©"; } .ion-ios-filing-outline:before { - content: "\f428"; } + content: "ï¨"; } .ion-ios-film:before { - content: "\f42b"; } + content: "ï«"; } .ion-ios-film-outline:before { - content: "\f42a"; } + content: "ïª"; } .ion-ios-flag:before { - content: "\f42d"; } + content: "ï"; } .ion-ios-flag-outline:before { - content: "\f42c"; } + content: "ï¬"; } .ion-ios-flame:before { - content: "\f42f"; } + content: "ï¯"; } .ion-ios-flame-outline:before { - content: "\f42e"; } + content: "ï®"; } .ion-ios-flask:before { - content: "\f431"; } + content: "ï±"; } .ion-ios-flask-outline:before { - content: "\f430"; } + content: "ï°"; } .ion-ios-flower:before { - content: "\f433"; } + content: "ï³"; } .ion-ios-flower-outline:before { - content: "\f432"; } + content: "ï²"; } .ion-ios-folder:before { - content: "\f435"; } + content: "ïµ"; } .ion-ios-folder-outline:before { - content: "\f434"; } + content: "ï´"; } .ion-ios-football:before { - content: "\f437"; } + content: "ï·"; } .ion-ios-football-outline:before { - content: "\f436"; } + content: "ï¶"; } .ion-ios-game-controller-a:before { - content: "\f439"; } + content: "ï¹"; } .ion-ios-game-controller-a-outline:before { - content: "\f438"; } + content: "ï¸"; } .ion-ios-game-controller-b:before { - content: "\f43b"; } + content: "ï»"; } .ion-ios-game-controller-b-outline:before { - content: "\f43a"; } + content: "ïº"; } .ion-ios-gear:before { - content: "\f43d"; } + content: "ï½"; } .ion-ios-gear-outline:before { - content: "\f43c"; } + content: "ï¼"; } .ion-ios-glasses:before { - content: "\f43f"; } + content: "ï¿"; } .ion-ios-glasses-outline:before { - content: "\f43e"; } + content: "ï¾"; } .ion-ios-grid-view:before { - content: "\f441"; } + content: "ï‘"; } .ion-ios-grid-view-outline:before { - content: "\f440"; } + content: "ï‘€"; } .ion-ios-heart:before { - content: "\f443"; } + content: ""; } .ion-ios-heart-outline:before { - content: "\f442"; } + content: "ï‘‚"; } .ion-ios-help:before { - content: "\f446"; } + content: ""; } .ion-ios-help-empty:before { - content: "\f444"; } + content: "ï‘„"; } .ion-ios-help-outline:before { - content: "\f445"; } + content: "ï‘…"; } .ion-ios-home:before { - content: "\f448"; } + content: ""; } .ion-ios-home-outline:before { - content: "\f447"; } + content: ""; } .ion-ios-infinite:before { - content: "\f44a"; } + content: ""; } .ion-ios-infinite-outline:before { - content: "\f449"; } + content: ""; } .ion-ios-information:before { - content: "\f44d"; } + content: "ï‘"; } .ion-ios-information-empty:before { - content: "\f44b"; } + content: "ï‘‹"; } .ion-ios-information-outline:before { - content: "\f44c"; } + content: ""; } .ion-ios-ionic-outline:before { - content: "\f44e"; } + content: ""; } .ion-ios-keypad:before { - content: "\f450"; } + content: "ï‘"; } .ion-ios-keypad-outline:before { - content: "\f44f"; } + content: "ï‘"; } .ion-ios-lightbulb:before { - content: "\f452"; } + content: "ï‘’"; } .ion-ios-lightbulb-outline:before { - content: "\f451"; } + content: "ï‘‘"; } .ion-ios-list:before { - content: "\f454"; } + content: "ï‘”"; } .ion-ios-list-outline:before { - content: "\f453"; } + content: "ï‘“"; } .ion-ios-location:before { - content: "\f456"; } + content: "ï‘–"; } .ion-ios-location-outline:before { - content: "\f455"; } + content: "ï‘•"; } .ion-ios-locked:before { - content: "\f458"; } + content: ""; } .ion-ios-locked-outline:before { - content: "\f457"; } + content: "ï‘—"; } .ion-ios-loop:before { - content: "\f45a"; } + content: ""; } .ion-ios-loop-strong:before { - content: "\f459"; } + content: "ï‘™"; } .ion-ios-medical:before { - content: "\f45c"; } + content: ""; } .ion-ios-medical-outline:before { - content: "\f45b"; } + content: "ï‘›"; } .ion-ios-medkit:before { - content: "\f45e"; } + content: ""; } .ion-ios-medkit-outline:before { - content: "\f45d"; } + content: "ï‘"; } .ion-ios-mic:before { - content: "\f461"; } + content: "ï‘¡"; } .ion-ios-mic-off:before { - content: "\f45f"; } + content: ""; } .ion-ios-mic-outline:before { - content: "\f460"; } + content: "ï‘ "; } .ion-ios-minus:before { - content: "\f464"; } + content: ""; } .ion-ios-minus-empty:before { - content: "\f462"; } + content: "ï‘¢"; } .ion-ios-minus-outline:before { - content: "\f463"; } + content: "ï‘£"; } .ion-ios-monitor:before { - content: "\f466"; } + content: ""; } .ion-ios-monitor-outline:before { - content: "\f465"; } + content: "ï‘¥"; } .ion-ios-moon:before { - content: "\f468"; } + content: ""; } .ion-ios-moon-outline:before { - content: "\f467"; } + content: "ï‘§"; } .ion-ios-more:before { - content: "\f46a"; } + content: ""; } .ion-ios-more-outline:before { - content: "\f469"; } + content: "ï‘©"; } .ion-ios-musical-note:before { - content: "\f46b"; } + content: "ï‘«"; } .ion-ios-musical-notes:before { - content: "\f46c"; } + content: ""; } .ion-ios-navigate:before { - content: "\f46e"; } + content: "ï‘®"; } .ion-ios-navigate-outline:before { - content: "\f46d"; } + content: "ï‘"; } .ion-ios-nutrition:before { - content: "\f470"; } + content: "ï‘°"; } .ion-ios-nutrition-outline:before { - content: "\f46f"; } + content: ""; } .ion-ios-paper:before { - content: "\f472"; } + content: ""; } .ion-ios-paper-outline:before { - content: "\f471"; } + content: ""; } .ion-ios-paperplane:before { - content: "\f474"; } + content: "ï‘´"; } .ion-ios-paperplane-outline:before { - content: "\f473"; } + content: ""; } .ion-ios-partlysunny:before { - content: "\f476"; } + content: "ï‘¶"; } .ion-ios-partlysunny-outline:before { - content: "\f475"; } + content: ""; } .ion-ios-pause:before { - content: "\f478"; } + content: ""; } .ion-ios-pause-outline:before { - content: "\f477"; } + content: "ï‘·"; } .ion-ios-paw:before { - content: "\f47a"; } + content: ""; } .ion-ios-paw-outline:before { - content: "\f479"; } + content: ""; } .ion-ios-people:before { - content: "\f47c"; } + content: ""; } .ion-ios-people-outline:before { - content: "\f47b"; } + content: "ï‘»"; } .ion-ios-person:before { - content: "\f47e"; } + content: ""; } .ion-ios-person-outline:before { - content: "\f47d"; } + content: ""; } .ion-ios-personadd:before { - content: "\f480"; } + content: "ï’€"; } .ion-ios-personadd-outline:before { - content: "\f47f"; } + content: "ï‘¿"; } .ion-ios-photos:before { - content: "\f482"; } + content: "ï’‚"; } .ion-ios-photos-outline:before { - content: "\f481"; } + content: "ï’"; } .ion-ios-pie:before { - content: "\f484"; } + content: "ï’„"; } .ion-ios-pie-outline:before { - content: "\f483"; } + content: "ï’ƒ"; } .ion-ios-pint:before { - content: "\f486"; } + content: "ï’†"; } .ion-ios-pint-outline:before { - content: "\f485"; } + content: "ï’…"; } .ion-ios-play:before { - content: "\f488"; } + content: "ï’ˆ"; } .ion-ios-play-outline:before { - content: "\f487"; } + content: "ï’‡"; } .ion-ios-plus:before { - content: "\f48b"; } + content: "ï’‹"; } .ion-ios-plus-empty:before { - content: "\f489"; } + content: "ï’‰"; } .ion-ios-plus-outline:before { - content: "\f48a"; } + content: "ï’Š"; } .ion-ios-pricetag:before { - content: "\f48d"; } + content: "ï’"; } .ion-ios-pricetag-outline:before { - content: "\f48c"; } + content: "ï’Œ"; } .ion-ios-pricetags:before { - content: "\f48f"; } + content: "ï’"; } .ion-ios-pricetags-outline:before { - content: "\f48e"; } + content: "ï’Ž"; } .ion-ios-printer:before { - content: "\f491"; } + content: "ï’‘"; } .ion-ios-printer-outline:before { - content: "\f490"; } + content: "ï’"; } .ion-ios-pulse:before { - content: "\f493"; } + content: "ï’“"; } .ion-ios-pulse-strong:before { - content: "\f492"; } + content: "ï’’"; } .ion-ios-rainy:before { - content: "\f495"; } + content: "ï’•"; } .ion-ios-rainy-outline:before { - content: "\f494"; } + content: "ï’”"; } .ion-ios-recording:before { - content: "\f497"; } + content: "ï’—"; } .ion-ios-recording-outline:before { - content: "\f496"; } + content: "ï’–"; } .ion-ios-redo:before { - content: "\f499"; } + content: "ï’™"; } .ion-ios-redo-outline:before { - content: "\f498"; } + content: "ï’˜"; } .ion-ios-refresh:before { - content: "\f49c"; } + content: "ï’œ"; } .ion-ios-refresh-empty:before { - content: "\f49a"; } + content: "ï’š"; } .ion-ios-refresh-outline:before { - content: "\f49b"; } + content: "ï’›"; } .ion-ios-reload:before { - content: "\f49d"; } + content: "ï’"; } .ion-ios-reverse-camera:before { - content: "\f49f"; } + content: "ï’Ÿ"; } .ion-ios-reverse-camera-outline:before { - content: "\f49e"; } + content: "ï’ž"; } .ion-ios-rewind:before { - content: "\f4a1"; } + content: "ï’¡"; } .ion-ios-rewind-outline:before { - content: "\f4a0"; } + content: "ï’ "; } .ion-ios-rose:before { - content: "\f4a3"; } + content: "ï’£"; } .ion-ios-rose-outline:before { - content: "\f4a2"; } + content: "ï’¢"; } .ion-ios-search:before { - content: "\f4a5"; } + content: "ï’¥"; } .ion-ios-search-strong:before { - content: "\f4a4"; } + content: "ï’¤"; } .ion-ios-settings:before { - content: "\f4a7"; } + content: "ï’§"; } .ion-ios-settings-strong:before { - content: "\f4a6"; } + content: "ï’¦"; } .ion-ios-shuffle:before { - content: "\f4a9"; } + content: "ï’©"; } .ion-ios-shuffle-strong:before { - content: "\f4a8"; } + content: "ï’¨"; } .ion-ios-skipbackward:before { - content: "\f4ab"; } + content: "ï’«"; } .ion-ios-skipbackward-outline:before { - content: "\f4aa"; } + content: "ï’ª"; } .ion-ios-skipforward:before { - content: "\f4ad"; } + content: "ï’"; } .ion-ios-skipforward-outline:before { - content: "\f4ac"; } + content: "ï’¬"; } .ion-ios-snowy:before { - content: "\f4ae"; } + content: "ï’®"; } .ion-ios-speedometer:before { - content: "\f4b0"; } + content: "ï’°"; } .ion-ios-speedometer-outline:before { - content: "\f4af"; } + content: "ï’¯"; } .ion-ios-star:before { - content: "\f4b3"; } + content: "ï’³"; } .ion-ios-star-half:before { - content: "\f4b1"; } + content: "ï’±"; } .ion-ios-star-outline:before { - content: "\f4b2"; } + content: "ï’²"; } .ion-ios-stopwatch:before { - content: "\f4b5"; } + content: "ï’µ"; } .ion-ios-stopwatch-outline:before { - content: "\f4b4"; } + content: "ï’´"; } .ion-ios-sunny:before { - content: "\f4b7"; } + content: "ï’·"; } .ion-ios-sunny-outline:before { - content: "\f4b6"; } + content: "ï’¶"; } .ion-ios-telephone:before { - content: "\f4b9"; } + content: "ï’¹"; } .ion-ios-telephone-outline:before { - content: "\f4b8"; } + content: "ï’¸"; } .ion-ios-tennisball:before { - content: "\f4bb"; } + content: "ï’»"; } .ion-ios-tennisball-outline:before { - content: "\f4ba"; } + content: "ï’º"; } .ion-ios-thunderstorm:before { - content: "\f4bd"; } + content: "ï’½"; } .ion-ios-thunderstorm-outline:before { - content: "\f4bc"; } + content: "ï’¼"; } .ion-ios-time:before { - content: "\f4bf"; } + content: "ï’¿"; } .ion-ios-time-outline:before { - content: "\f4be"; } + content: "ï’¾"; } .ion-ios-timer:before { - content: "\f4c1"; } + content: "ï“"; } .ion-ios-timer-outline:before { - content: "\f4c0"; } + content: "ï“€"; } .ion-ios-toggle:before { - content: "\f4c3"; } + content: ""; } .ion-ios-toggle-outline:before { - content: "\f4c2"; } + content: "ï“‚"; } .ion-ios-trash:before { - content: "\f4c5"; } + content: "ï“…"; } .ion-ios-trash-outline:before { - content: "\f4c4"; } + content: "ï“„"; } .ion-ios-undo:before { - content: "\f4c7"; } + content: ""; } .ion-ios-undo-outline:before { - content: "\f4c6"; } + content: ""; } .ion-ios-unlocked:before { - content: "\f4c9"; } + content: ""; } .ion-ios-unlocked-outline:before { - content: "\f4c8"; } + content: ""; } .ion-ios-upload:before { - content: "\f4cb"; } + content: "ï“‹"; } .ion-ios-upload-outline:before { - content: "\f4ca"; } + content: ""; } .ion-ios-videocam:before { - content: "\f4cd"; } + content: "ï“"; } .ion-ios-videocam-outline:before { - content: "\f4cc"; } + content: ""; } .ion-ios-volume-high:before { - content: "\f4ce"; } + content: ""; } .ion-ios-volume-low:before { - content: "\f4cf"; } + content: "ï“"; } .ion-ios-wineglass:before { - content: "\f4d1"; } + content: "ï“‘"; } .ion-ios-wineglass-outline:before { - content: "\f4d0"; } + content: "ï“"; } .ion-ios-world:before { - content: "\f4d3"; } + content: "ï““"; } .ion-ios-world-outline:before { - content: "\f4d2"; } + content: "ï“’"; } .ion-ipad:before { - content: "\f1f9"; } + content: ""; } .ion-iphone:before { - content: "\f1fa"; } + content: ""; } .ion-ipod:before { - content: "\f1fb"; } + content: ""; } .ion-jet:before { - content: "\f295"; } + content: ""; } .ion-key:before { - content: "\f296"; } + content: ""; } .ion-knife:before { - content: "\f297"; } + content: ""; } .ion-laptop:before { - content: "\f1fc"; } + content: ""; } .ion-leaf:before { - content: "\f1fd"; } + content: ""; } .ion-levels:before { - content: "\f298"; } + content: ""; } .ion-lightbulb:before { - content: "\f299"; } + content: ""; } .ion-link:before { - content: "\f1fe"; } + content: ""; } .ion-load-a:before { - content: "\f29a"; } + content: ""; } .ion-load-b:before { - content: "\f29b"; } + content: ""; } .ion-load-c:before { - content: "\f29c"; } + content: ""; } .ion-load-d:before { - content: "\f29d"; } + content: "ïŠ"; } .ion-location:before { - content: "\f1ff"; } + content: ""; } .ion-lock-combination:before { - content: "\f4d4"; } + content: "ï“”"; } .ion-locked:before { - content: "\f200"; } + content: ""; } .ion-log-in:before { - content: "\f29e"; } + content: ""; } .ion-log-out:before { - content: "\f29f"; } + content: ""; } .ion-loop:before { - content: "\f201"; } + content: "ïˆ"; } .ion-magnet:before { - content: "\f2a0"; } + content: "ïŠ "; } .ion-male:before { - content: "\f2a1"; } + content: ""; } .ion-man:before { - content: "\f202"; } + content: ""; } .ion-map:before { - content: "\f203"; } + content: ""; } .ion-medkit:before { - content: "\f2a2"; } + content: ""; } .ion-merge:before { - content: "\f33f"; } + content: ""; } .ion-mic-a:before { - content: "\f204"; } + content: ""; } .ion-mic-b:before { - content: "\f205"; } + content: ""; } .ion-mic-c:before { - content: "\f206"; } + content: ""; } .ion-minus:before { - content: "\f209"; } + content: ""; } .ion-minus-circled:before { - content: "\f207"; } + content: ""; } .ion-minus-round:before { - content: "\f208"; } + content: ""; } .ion-model-s:before { - content: "\f2c1"; } + content: "ï‹"; } .ion-monitor:before { - content: "\f20a"; } + content: ""; } .ion-more:before { - content: "\f20b"; } + content: ""; } .ion-mouse:before { - content: "\f340"; } + content: "ï€"; } .ion-music-note:before { - content: "\f20c"; } + content: ""; } .ion-navicon:before { - content: "\f20e"; } + content: ""; } .ion-navicon-round:before { - content: "\f20d"; } + content: "ïˆ"; } .ion-navigate:before { - content: "\f2a3"; } + content: ""; } .ion-network:before { - content: "\f341"; } + content: "ï"; } .ion-no-smoking:before { - content: "\f2c2"; } + content: "ï‹‚"; } .ion-nuclear:before { - content: "\f2a4"; } + content: ""; } .ion-outlet:before { - content: "\f342"; } + content: "ï‚"; } .ion-paintbrush:before { - content: "\f4d5"; } + content: "ï“•"; } .ion-paintbucket:before { - content: "\f4d6"; } + content: "ï“–"; } .ion-paper-airplane:before { - content: "\f2c3"; } + content: ""; } .ion-paperclip:before { - content: "\f20f"; } + content: "ïˆ"; } .ion-pause:before { - content: "\f210"; } + content: "ïˆ"; } .ion-person:before { - content: "\f213"; } + content: ""; } .ion-person-add:before { - content: "\f211"; } + content: ""; } .ion-person-stalker:before { - content: "\f212"; } + content: ""; } .ion-pie-graph:before { - content: "\f2a5"; } + content: ""; } .ion-pin:before { - content: "\f2a6"; } + content: ""; } .ion-pinpoint:before { - content: "\f2a7"; } + content: ""; } .ion-pizza:before { - content: "\f2a8"; } + content: ""; } .ion-plane:before { - content: "\f214"; } + content: ""; } .ion-planet:before { - content: "\f343"; } + content: "ïƒ"; } .ion-play:before { - content: "\f215"; } + content: ""; } .ion-playstation:before { - content: "\f30a"; } + content: ""; } .ion-plus:before { - content: "\f218"; } + content: ""; } .ion-plus-circled:before { - content: "\f216"; } + content: ""; } .ion-plus-round:before { - content: "\f217"; } + content: ""; } .ion-podium:before { - content: "\f344"; } + content: "ï„"; } .ion-pound:before { - content: "\f219"; } + content: ""; } .ion-power:before { - content: "\f2a9"; } + content: ""; } .ion-pricetag:before { - content: "\f2aa"; } + content: ""; } .ion-pricetags:before { - content: "\f2ab"; } + content: ""; } .ion-printer:before { - content: "\f21a"; } + content: ""; } .ion-pull-request:before { - content: "\f345"; } + content: "ï…"; } .ion-qr-scanner:before { - content: "\f346"; } + content: "ï†"; } .ion-quote:before { - content: "\f347"; } + content: "ï‡"; } .ion-radio-waves:before { - content: "\f2ac"; } + content: ""; } .ion-record:before { - content: "\f21b"; } + content: ""; } .ion-refresh:before { - content: "\f21c"; } + content: ""; } .ion-reply:before { - content: "\f21e"; } + content: ""; } .ion-reply-all:before { - content: "\f21d"; } + content: "ïˆ"; } .ion-ribbon-a:before { - content: "\f348"; } + content: "ïˆ"; } .ion-ribbon-b:before { - content: "\f349"; } + content: "ï‰"; } .ion-sad:before { - content: "\f34a"; } + content: "ïŠ"; } .ion-sad-outline:before { - content: "\f4d7"; } + content: "ï“—"; } .ion-scissors:before { - content: "\f34b"; } + content: "ï‹"; } .ion-search:before { - content: "\f21f"; } + content: ""; } .ion-settings:before { - content: "\f2ad"; } + content: "ïŠ"; } .ion-share:before { - content: "\f220"; } + content: "ïˆ "; } .ion-shuffle:before { - content: "\f221"; } + content: ""; } .ion-skip-backward:before { - content: "\f222"; } + content: ""; } .ion-skip-forward:before { - content: "\f223"; } + content: ""; } .ion-social-android:before { - content: "\f225"; } + content: ""; } .ion-social-android-outline:before { - content: "\f224"; } + content: ""; } .ion-social-angular:before { - content: "\f4d9"; } + content: "ï“™"; } .ion-social-angular-outline:before { - content: "\f4d8"; } + content: ""; } .ion-social-apple:before { - content: "\f227"; } + content: ""; } .ion-social-apple-outline:before { - content: "\f226"; } + content: ""; } .ion-social-bitcoin:before { - content: "\f2af"; } + content: ""; } .ion-social-bitcoin-outline:before { - content: "\f2ae"; } + content: ""; } .ion-social-buffer:before { - content: "\f229"; } + content: ""; } .ion-social-buffer-outline:before { - content: "\f228"; } + content: ""; } .ion-social-chrome:before { - content: "\f4db"; } + content: "ï“›"; } .ion-social-chrome-outline:before { - content: "\f4da"; } + content: ""; } .ion-social-codepen:before { - content: "\f4dd"; } + content: "ï“"; } .ion-social-codepen-outline:before { - content: "\f4dc"; } + content: ""; } .ion-social-css3:before { - content: "\f4df"; } + content: ""; } .ion-social-css3-outline:before { - content: "\f4de"; } + content: ""; } .ion-social-designernews:before { - content: "\f22b"; } + content: ""; } .ion-social-designernews-outline:before { - content: "\f22a"; } + content: ""; } .ion-social-dribbble:before { - content: "\f22d"; } + content: "ïˆ"; } .ion-social-dribbble-outline:before { - content: "\f22c"; } + content: ""; } .ion-social-dropbox:before { - content: "\f22f"; } + content: ""; } .ion-social-dropbox-outline:before { - content: "\f22e"; } + content: ""; } .ion-social-euro:before { - content: "\f4e1"; } + content: "ï“¡"; } .ion-social-euro-outline:before { - content: "\f4e0"; } + content: "ï“ "; } .ion-social-facebook:before { - content: "\f231"; } + content: ""; } .ion-social-facebook-outline:before { - content: "\f230"; } + content: ""; } .ion-social-foursquare:before { - content: "\f34d"; } + content: "ï"; } .ion-social-foursquare-outline:before { - content: "\f34c"; } + content: "ïŒ"; } .ion-social-freebsd-devil:before { - content: "\f2c4"; } + content: "ï‹„"; } .ion-social-github:before { - content: "\f233"; } + content: ""; } .ion-social-github-outline:before { - content: "\f232"; } + content: ""; } .ion-social-google:before { - content: "\f34f"; } + content: "ï"; } .ion-social-google-outline:before { - content: "\f34e"; } + content: "ïŽ"; } .ion-social-googleplus:before { - content: "\f235"; } + content: ""; } .ion-social-googleplus-outline:before { - content: "\f234"; } + content: ""; } .ion-social-hackernews:before { - content: "\f237"; } + content: ""; } .ion-social-hackernews-outline:before { - content: "\f236"; } + content: ""; } .ion-social-html5:before { - content: "\f4e3"; } + content: "ï“£"; } .ion-social-html5-outline:before { - content: "\f4e2"; } + content: "ï“¢"; } .ion-social-instagram:before { - content: "\f351"; } + content: "ï‘"; } .ion-social-instagram-outline:before { - content: "\f350"; } + content: "ï"; } .ion-social-javascript:before { - content: "\f4e5"; } + content: "ï“¥"; } .ion-social-javascript-outline:before { - content: "\f4e4"; } + content: ""; } .ion-social-linkedin:before { - content: "\f239"; } + content: ""; } .ion-social-linkedin-outline:before { - content: "\f238"; } + content: ""; } .ion-social-markdown:before { - content: "\f4e6"; } + content: ""; } .ion-social-nodejs:before { - content: "\f4e7"; } + content: "ï“§"; } .ion-social-octocat:before { - content: "\f4e8"; } + content: ""; } .ion-social-pinterest:before { - content: "\f2b1"; } + content: ""; } .ion-social-pinterest-outline:before { - content: "\f2b0"; } + content: ""; } .ion-social-python:before { - content: "\f4e9"; } + content: "ï“©"; } .ion-social-reddit:before { - content: "\f23b"; } + content: ""; } .ion-social-reddit-outline:before { - content: "\f23a"; } + content: ""; } .ion-social-rss:before { - content: "\f23d"; } + content: ""; } .ion-social-rss-outline:before { - content: "\f23c"; } + content: ""; } .ion-social-sass:before { - content: "\f4ea"; } + content: ""; } .ion-social-skype:before { - content: "\f23f"; } + content: ""; } .ion-social-skype-outline:before { - content: "\f23e"; } + content: ""; } .ion-social-snapchat:before { - content: "\f4ec"; } + content: ""; } .ion-social-snapchat-outline:before { - content: "\f4eb"; } + content: "ï“«"; } .ion-social-tumblr:before { - content: "\f241"; } + content: "ï‰"; } .ion-social-tumblr-outline:before { - content: "\f240"; } + content: ""; } .ion-social-tux:before { - content: "\f2c5"; } + content: "ï‹…"; } .ion-social-twitch:before { - content: "\f4ee"; } + content: "ï“®"; } .ion-social-twitch-outline:before { - content: "\f4ed"; } + content: "ï“"; } .ion-social-twitter:before { - content: "\f243"; } + content: ""; } .ion-social-twitter-outline:before { - content: "\f242"; } + content: ""; } .ion-social-usd:before { - content: "\f353"; } + content: "ï“"; } .ion-social-usd-outline:before { - content: "\f352"; } + content: "ï’"; } .ion-social-vimeo:before { - content: "\f245"; } + content: ""; } .ion-social-vimeo-outline:before { - content: "\f244"; } + content: ""; } .ion-social-whatsapp:before { - content: "\f4f0"; } + content: "ï“°"; } .ion-social-whatsapp-outline:before { - content: "\f4ef"; } + content: ""; } .ion-social-windows:before { - content: "\f247"; } + content: ""; } .ion-social-windows-outline:before { - content: "\f246"; } + content: ""; } .ion-social-wordpress:before { - content: "\f249"; } + content: ""; } .ion-social-wordpress-outline:before { - content: "\f248"; } + content: ""; } .ion-social-yahoo:before { - content: "\f24b"; } + content: ""; } .ion-social-yahoo-outline:before { - content: "\f24a"; } + content: ""; } .ion-social-yen:before { - content: "\f4f2"; } + content: ""; } .ion-social-yen-outline:before { - content: "\f4f1"; } + content: ""; } .ion-social-youtube:before { - content: "\f24d"; } + content: "ï‰"; } .ion-social-youtube-outline:before { - content: "\f24c"; } + content: ""; } .ion-soup-can:before { - content: "\f4f4"; } + content: "ï“´"; } .ion-soup-can-outline:before { - content: "\f4f3"; } + content: ""; } .ion-speakerphone:before { - content: "\f2b2"; } + content: ""; } .ion-speedometer:before { - content: "\f2b3"; } + content: ""; } .ion-spoon:before { - content: "\f2b4"; } + content: ""; } .ion-star:before { - content: "\f24e"; } + content: ""; } .ion-stats-bars:before { - content: "\f2b5"; } + content: ""; } .ion-steam:before { - content: "\f30b"; } + content: ""; } .ion-stop:before { - content: "\f24f"; } + content: "ï‰"; } .ion-thermometer:before { - content: "\f2b6"; } + content: ""; } .ion-thumbsdown:before { - content: "\f250"; } + content: "ï‰"; } .ion-thumbsup:before { - content: "\f251"; } + content: ""; } .ion-toggle:before { - content: "\f355"; } + content: "ï•"; } .ion-toggle-filled:before { - content: "\f354"; } + content: "ï”"; } .ion-transgender:before { - content: "\f4f5"; } + content: ""; } .ion-trash-a:before { - content: "\f252"; } + content: ""; } .ion-trash-b:before { - content: "\f253"; } + content: ""; } .ion-trophy:before { - content: "\f356"; } + content: "ï–"; } .ion-tshirt:before { - content: "\f4f7"; } + content: "ï“·"; } .ion-tshirt-outline:before { - content: "\f4f6"; } + content: "ï“¶"; } .ion-umbrella:before { - content: "\f2b7"; } + content: ""; } .ion-university:before { - content: "\f357"; } + content: "ï—"; } .ion-unlocked:before { - content: "\f254"; } + content: ""; } .ion-upload:before { - content: "\f255"; } + content: ""; } .ion-usb:before { - content: "\f2b8"; } + content: ""; } .ion-videocamera:before { - content: "\f256"; } + content: ""; } .ion-volume-high:before { - content: "\f257"; } + content: ""; } .ion-volume-low:before { - content: "\f258"; } + content: ""; } .ion-volume-medium:before { - content: "\f259"; } + content: ""; } .ion-volume-mute:before { - content: "\f25a"; } + content: ""; } .ion-wand:before { - content: "\f358"; } + content: "ï˜"; } .ion-waterdrop:before { - content: "\f25b"; } + content: ""; } .ion-wifi:before { - content: "\f25c"; } + content: ""; } .ion-wineglass:before { - content: "\f2b9"; } + content: ""; } .ion-woman:before { - content: "\f25d"; } + content: "ï‰"; } .ion-wrench:before { - content: "\f2ba"; } + content: ""; } .ion-xbox:before { - content: "\f30c"; } + content: ""; } /** * Resets @@ -2254,7 +2988,19 @@ * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) * http://cssreset.com */ -html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, i, u, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, fieldset, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, i, u, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, fieldset, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { margin: 0; padding: 0; border: 0; @@ -2268,7 +3014,8 @@ ol, ul { blockquote, q { quotes: none; } -blockquote:before, blockquote:after, q:before, q:after { +blockquote:before, blockquote:after, +q:before, q:after { content: ''; content: none; } @@ -2283,7 +3030,8 @@ audio:not([controls]) { /** * Hide the `template` element in IE, Safari, and Firefox < 22. */ -[hidden], template { +[hidden], +template { display: none; } script { @@ -2320,7 +3068,13 @@ body { /** * Remove default outlines. */ -a, button, :focus, a:focus, button:focus, a:active, a:hover { +a, +button, +:focus, +a:focus, +button:focus, +a:active, +a:hover { outline: 0; } /* * @@ -2328,7 +3082,7 @@ a, button, :focus, a:focus, button:focus, a:active, a:hover { */ a { -webkit-user-drag: none; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent; } a[href]:hover { cursor: pointer; } @@ -2339,7 +3093,8 @@ a { /** * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ -b, strong { +b, +strong { font-weight: bold; } /** @@ -2359,7 +3114,10 @@ hr { /** * Correct font family set oddly in Safari 5 and Chrome. */ -code, kbd, pre, samp { +code, +kbd, +pre, +samp { font-size: 1em; font-family: monospace, serif; } @@ -2384,7 +3142,8 @@ small { /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ -sub, sup { +sub, +sup { position: relative; vertical-align: baseline; font-size: 75%; @@ -2422,7 +3181,10 @@ legend { * 5. Make sure webkit font smoothing is being inherited * 6. Remove default gradient in Android Firefox / FirefoxOS */ -button, input, select, textarea { +button, +input, +select, +textarea { margin: 0; /* 3 */ font-size: 100%; @@ -2444,7 +3206,8 @@ button, input, select, textarea { * Address Firefox 4+ setting `line-height` on `input` using `importnt` in * the UA stylesheet. */ -button, input { +button, +input { line-height: normal; } /** @@ -2453,7 +3216,8 @@ button, input { * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. * Correct `select` style inheritance in Firefox 4+ and Opera. */ -button, select { +button, +select { text-transform: none; } /** @@ -2463,7 +3227,10 @@ button, select { * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */ -button, html input[type="button"], input[type="reset"], input[type="submit"] { +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { cursor: pointer; /* 3 */ -webkit-appearance: button; @@ -2472,7 +3239,8 @@ button, html input[type="button"], input[type="reset"], input[type="submit"] { /** * Re-set default cursor for disabled elements. */ -button[disabled], html input[disabled] { +button[disabled], +html input[disabled] { cursor: default; } /** @@ -2492,13 +3260,15 @@ input[type="search"] { * Remove inner padding and search cancel button in Safari 5 and Chrome * on OS X. */ -input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * Remove inner padding and border in Firefox 4+. */ -button::-moz-focus-inner, input::-moz-focus-inner { +button::-moz-focus-inner, +input::-moz-focus-inner { padding: 0; border: 0; } @@ -2529,7 +3299,9 @@ table { * Scaffolding * -------------------------------------------------- */ -*, *:before, *:after { +*, +*:before, +*:after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } @@ -2539,14 +3311,15 @@ html { -ms-touch-action: pan-y; touch-action: pan-y; } -body, .ionic-body { +body, +.ionic-body { -webkit-touch-callout: none; -webkit-font-smoothing: antialiased; font-smoothing: antialiased; -webkit-text-size-adjust: none; -moz-text-size-adjust: none; text-size-adjust: none; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; -moz-user-select: none; @@ -2562,14 +3335,16 @@ body, .ionic-body { color: #000; word-wrap: break-word; font-size: 14px; - font-family: "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; + font-family: -apple-system; + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; line-height: 20px; text-rendering: optimizeLegibility; -webkit-backface-visibility: hidden; -webkit-user-drag: none; -ms-content-zooming: none; } -body.grade-b, body.grade-c { +body.grade-b, +body.grade-c { text-rendering: auto; } .content { @@ -2596,6 +3371,17 @@ body.grade-b, body.grade-c { display: block; overflow: hidden; margin-top: -1px; } + .scroll-view.overflow-scroll { + position: relative; } + .scroll-view.scroll-x { + overflow-x: scroll; + overflow-y: hidden; } + .scroll-view.scroll-y { + overflow-x: hidden; + overflow-y: scroll; } + .scroll-view.scroll-xy { + overflow-x: scroll; + overflow-y: scroll; } /** * Scroll is the scroll view component available for complex and custom @@ -2656,9 +3442,11 @@ body.grade-b, body.grade-c { .platform-android .scroll-bar-indicator { border-radius: 0; } -.grade-b .scroll-bar-indicator, .grade-c .scroll-bar-indicator { +.grade-b .scroll-bar-indicator, +.grade-c .scroll-bar-indicator { background: #aaa; } - .grade-b .scroll-bar-indicator.scroll-bar-fade-out, .grade-c .scroll-bar-indicator.scroll-bar-fade-out { + .grade-b .scroll-bar-indicator.scroll-bar-fade-out, + .grade-c .scroll-bar-indicator.scroll-bar-fade-out { -webkit-transition: none; transition: none; } @@ -2692,22 +3480,29 @@ ion-infinite-scroll { color: #666666; font-size: 30px; color: #666666; } - ion-infinite-scroll:not(.active) .spinner, ion-infinite-scroll:not(.active) .icon:before { + ion-infinite-scroll:not(.active) .spinner, + ion-infinite-scroll:not(.active) .icon:before { display: none; } .overflow-scroll { overflow-x: hidden; overflow-y: scroll; -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; top: 0; right: 0; bottom: 0; left: 0; position: absolute; } + .overflow-scroll.pane { + overflow-x: hidden; + overflow-y: scroll; } .overflow-scroll .scroll { position: static; height: 100%; -webkit-transform: translate3d(0, 0, 0); } + .overflow-scroll.keyboard-up:not(.keyboard-up-confirm) { + overflow: hidden; } /* If you change these, change platform.scss as well */ .has-header { @@ -2731,12 +3526,17 @@ ion-infinite-scroll { .has-subfooter { bottom: 88px; } -.has-tabs, .bar-footer.has-tabs { +.has-tabs, +.bar-footer.has-tabs { bottom: 49px; } - .has-tabs.pane, .bar-footer.has-tabs.pane { + .has-tabs.pane, + .bar-footer.has-tabs.pane { bottom: 49px; height: auto; } +.bar-subfooter.has-tabs { + bottom: 93px; } + .has-footer.has-tabs { bottom: 93px; } @@ -2750,7 +3550,8 @@ ion-infinite-scroll { .view { z-index: 1; } -.pane, .view { +.pane, +.view { position: absolute; top: 0; right: 0; @@ -2789,24 +3590,52 @@ cite { .text-center { text-align: center; } -h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { color: #000; font-weight: 500; - font-family: "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; line-height: 1.2; } - h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small { + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, + .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small { font-weight: normal; line-height: 1; } -h1, .h1, h2, .h2, h3, .h3 { +h1, .h1, +h2, .h2, +h3, .h3 { margin-top: 20px; margin-bottom: 10px; } - h1:first-child, .h1:first-child, h2:first-child, .h2:first-child, h3:first-child, .h3:first-child { + h1:first-child, .h1:first-child, + h2:first-child, .h2:first-child, + h3:first-child, .h3:first-child { margin-top: 0; } - h1 + h1, h1 + .h1, h1 + h2, h1 + .h2, h1 + h3, h1 + .h3, .h1 + h1, .h1 + .h1, .h1 + h2, .h1 + .h2, .h1 + h3, .h1 + .h3, h2 + h1, h2 + .h1, h2 + h2, h2 + .h2, h2 + h3, h2 + .h3, .h2 + h1, .h2 + .h1, .h2 + h2, .h2 + .h2, .h2 + h3, .h2 + .h3, h3 + h1, h3 + .h1, h3 + h2, h3 + .h2, h3 + h3, h3 + .h3, .h3 + h1, .h3 + .h1, .h3 + h2, .h3 + .h2, .h3 + h3, .h3 + .h3 { + h1 + h1, h1 + .h1, + h1 + h2, h1 + .h2, + h1 + h3, h1 + .h3, .h1 + h1, .h1 + .h1, + .h1 + h2, .h1 + .h2, + .h1 + h3, .h1 + .h3, + h2 + h1, + h2 + .h1, + h2 + h2, + h2 + .h2, + h2 + h3, + h2 + .h3, .h2 + h1, .h2 + .h1, + .h2 + h2, .h2 + .h2, + .h2 + h3, .h2 + .h3, + h3 + h1, + h3 + .h1, + h3 + h2, + h3 + .h2, + h3 + h3, + h3 + .h3, .h3 + h1, .h3 + .h1, + .h3 + h2, .h3 + .h2, + .h3 + h3, .h3 + .h3 { margin-top: 10px; } -h4, .h4, h5, .h5, h6, .h6 { +h4, .h4, +h5, .h5, +h6, .h6 { margin-top: 10px; margin-bottom: 10px; } @@ -2834,13 +3663,15 @@ h1 small, .h1 small { h2 small, .h2 small { font-size: 18px; } -h3 small, .h3 small, h4 small, .h4 small { +h3 small, .h3 small, +h4 small, .h4 small { font-size: 14px; } dl { margin-bottom: 20px; } -dt, dd { +dt, +dd { line-height: 1.42857; } dt { @@ -2862,7 +3693,10 @@ blockquote { blockquote small:before { content: '\2014 \00A0'; } -q:before, q:after, blockquote:before, blockquote:after { +q:before, +q:after, +blockquote:before, +blockquote:after { content: ""; } address { @@ -2871,6 +3705,9 @@ address { font-style: normal; line-height: 1.42857; } +a { + color: #387ef5; } + a.subdued { padding-right: 10px; color: #888; @@ -2893,7 +3730,7 @@ a.subdued { z-index: 11; width: 100%; height: 100%; - background-color: rgba(0, 0, 0, 0); } + background-color: transparent; } .action-sheet-backdrop.active { background-color: rgba(0, 0, 0, 0.4); } @@ -2976,9 +3813,11 @@ a.subdued { .platform-android .action-sheet-backdrop.active { background-color: rgba(0, 0, 0, 0.2); } + .platform-android .action-sheet { margin: 0; } - .platform-android .action-sheet .action-sheet-title, .platform-android .action-sheet .button { + .platform-android .action-sheet .action-sheet-title, + .platform-android .action-sheet .button { text-align: left; border-color: transparent; font-size: 16px; @@ -2987,14 +3826,18 @@ a.subdued { font-size: 14px; padding: 16px; color: #666; } - .platform-android .action-sheet .button.active, .platform-android .action-sheet .button.activated { + .platform-android .action-sheet .button.active, + .platform-android .action-sheet .button.activated { background: #e8e8e8; } + .platform-android .action-sheet-group { margin: 0; border-radius: 0; background-color: #fafafa; } + .platform-android .action-sheet-cancel { display: none; } + .platform-android .action-sheet-has-icons .button { padding-left: 56px; } @@ -3091,32 +3934,32 @@ a.subdued { .bar.bar-stable.bar-footer { background-image: linear-gradient(180deg, #b2b2b2, #b2b2b2 50%, transparent 50%); } .bar.bar-positive { - border-color: #0c63ee; + border-color: #0c60ee; background-color: #387ef5; - background-image: linear-gradient(0deg, #0c63ee, #0c63ee 50%, transparent 50%); + background-image: linear-gradient(0deg, #0c60ee, #0c60ee 50%, transparent 50%); color: #fff; } .bar.bar-positive .title { color: #fff; } .bar.bar-positive.bar-footer { - background-image: linear-gradient(180deg, #0c63ee, #0c63ee 50%, transparent 50%); } + background-image: linear-gradient(180deg, #0c60ee, #0c60ee 50%, transparent 50%); } .bar.bar-calm { - border-color: #0a9ec7; + border-color: #0a9dc7; background-color: #11c1f3; - background-image: linear-gradient(0deg, #0a9ec7, #0a9ec7 50%, transparent 50%); + background-image: linear-gradient(0deg, #0a9dc7, #0a9dc7 50%, transparent 50%); color: #fff; } .bar.bar-calm .title { color: #fff; } .bar.bar-calm.bar-footer { - background-image: linear-gradient(180deg, #0a9ec7, #0a9ec7 50%, transparent 50%); } + background-image: linear-gradient(180deg, #0a9dc7, #0a9dc7 50%, transparent 50%); } .bar.bar-assertive { - border-color: #e42012; + border-color: #e42112; background-color: #ef473a; - background-image: linear-gradient(0deg, #e42012, #e42012 50%, transparent 50%); + background-image: linear-gradient(0deg, #e42112, #e42112 50%, transparent 50%); color: #fff; } .bar.bar-assertive .title { color: #fff; } .bar.bar-assertive.bar-footer { - background-image: linear-gradient(180deg, #e42012, #e42012 50%, transparent 50%); } + background-image: linear-gradient(180deg, #e42112, #e42112 50%, transparent 50%); } .bar.bar-balanced { border-color: #28a54c; background-color: #33cd5f; @@ -3125,16 +3968,16 @@ a.subdued { .bar.bar-balanced .title { color: #fff; } .bar.bar-balanced.bar-footer { - background-image: linear-gradient(180deg, #28a54c, #0c63ee 50%, transparent 50%); } + background-image: linear-gradient(180deg, #28a54c, #0c60ee 50%, transparent 50%); } .bar.bar-energized { - border-color: #e6b400; + border-color: #e6b500; background-color: #ffc900; - background-image: linear-gradient(0deg, #e6b400, #e6b400 50%, transparent 50%); + background-image: linear-gradient(0deg, #e6b500, #e6b500 50%, transparent 50%); color: #fff; } .bar.bar-energized .title { color: #fff; } .bar.bar-energized.bar-footer { - background-image: linear-gradient(180deg, #e6b400, #e6b400 50%, transparent 50%); } + background-image: linear-gradient(180deg, #e6b500, #e6b500 50%, transparent 50%); } .bar.bar-royal { border-color: #6b46e5; background-color: #886aea; @@ -3154,6 +3997,7 @@ a.subdued { .bar.bar-dark.bar-footer { background-image: linear-gradient(180deg, #111, #111 50%, transparent 50%); } .bar .title { + display: block; position: absolute; top: 0; right: 0; @@ -3175,7 +4019,7 @@ a.subdued { text-align: right; } .bar .title a { color: inherit; } - .bar .button { + .bar .button, .bar button { z-index: 1; padding: 0 8px; min-width: initial; @@ -3183,39 +4027,45 @@ a.subdued { font-weight: 400; font-size: 13px; line-height: 32px; } - .bar .button.button-icon:before, .bar .button .icon:before, .bar .button.icon:before, .bar .button.icon-left:before, .bar .button.icon-right:before { + .bar .button.button-icon:before, + .bar .button .icon:before, .bar .button.icon:before, .bar .button.icon-left:before, .bar .button.icon-right:before, .bar button.button-icon:before, + .bar button .icon:before, .bar button.icon:before, .bar button.icon-left:before, .bar button.icon-right:before { padding-right: 2px; padding-left: 2px; font-size: 20px; line-height: 32px; } - .bar .button.button-icon { + .bar .button.button-icon, .bar button.button-icon { font-size: 17px; } - .bar .button.button-icon .icon:before, .bar .button.button-icon:before, .bar .button.button-icon.icon-left:before, .bar .button.button-icon.icon-right:before { + .bar .button.button-icon .icon:before, .bar .button.button-icon:before, .bar .button.button-icon.icon-left:before, .bar .button.button-icon.icon-right:before, .bar button.button-icon .icon:before, .bar button.button-icon:before, .bar button.button-icon.icon-left:before, .bar button.button-icon.icon-right:before { vertical-align: top; font-size: 32px; line-height: 32px; } - .bar .button.button-clear { + .bar .button.button-clear, .bar button.button-clear { padding-right: 2px; padding-left: 2px; font-weight: 300; font-size: 17px; } - .bar .button.button-clear .icon:before, .bar .button.button-clear.icon:before, .bar .button.button-clear.icon-left:before, .bar .button.button-clear.icon-right:before { + .bar .button.button-clear .icon:before, .bar .button.button-clear.icon:before, .bar .button.button-clear.icon-left:before, .bar .button.button-clear.icon-right:before, .bar button.button-clear .icon:before, .bar button.button-clear.icon:before, .bar button.button-clear.icon-left:before, .bar button.button-clear.icon-right:before { font-size: 32px; line-height: 32px; } - .bar .button.back-button { + .bar .button.back-button, .bar button.back-button { display: block; margin-right: 5px; padding: 0; white-space: nowrap; font-weight: 400; } - .bar .button.back-button.active, .bar .button.back-button.activated { + .bar .button.back-button.active, .bar .button.back-button.activated, .bar button.back-button.active, .bar button.back-button.activated { opacity: 0.2; } - .bar .button-bar > .button, .bar .buttons > .button { + .bar .button-bar > .button, + .bar .buttons > .button { min-height: 31px; line-height: 32px; } - .bar .button-bar + .button, .bar .button + .button-bar { + .bar .button-bar + .button, + .bar .button + .button-bar { margin-left: 5px; } - .bar .buttons, .bar .buttons.primary-buttons, .bar .buttons.secondary-buttons { + .bar .buttons, + .bar .buttons.primary-buttons, + .bar .buttons.secondary-buttons { display: inherit; } .bar .buttons span { display: inline-block; } @@ -3225,7 +4075,11 @@ a.subdued { .bar .buttons-right span { margin-left: 5px; display: inherit; } - .bar .title + .button:last-child, .bar > .button + .button:last-child, .bar > .button.pull-right, .bar .buttons.pull-right, .bar .title + .buttons { + .bar .title + .button:last-child, + .bar > .button + .button:last-child, + .bar > .button.pull-right, + .bar .buttons.pull-right, + .bar .title + .buttons { position: absolute; top: 5px; right: 5px; @@ -3233,23 +4087,23 @@ a.subdued { .platform-android .nav-bar-has-subheader .bar { background-image: none; } + .platform-android .bar .back-button .icon:before { font-size: 24px; } + .platform-android .bar .title { font-size: 19px; line-height: 44px; } .bar-light .button { - border-color: #ddd; + border-color: transparent; background-color: white; color: #444; } .bar-light .button:hover { color: #444; text-decoration: none; } .bar-light .button.active, .bar-light .button.activated { - border-color: #ccc; - background-color: #fafafa; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #fafafa; } .bar-light .button.button-clear { border-color: transparent; background: none; @@ -3261,16 +4115,14 @@ a.subdued { background: none; } .bar-stable .button { - border-color: #b2b2b2; + border-color: transparent; background-color: #f8f8f8; color: #444; } .bar-stable .button:hover { color: #444; text-decoration: none; } .bar-stable .button.active, .bar-stable .button.activated { - border-color: #a2a2a2; - background-color: #e5e5e5; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #e5e5e5; } .bar-stable .button.button-clear { border-color: transparent; background: none; @@ -3282,16 +4134,14 @@ a.subdued { background: none; } .bar-positive .button { - border-color: #0c63ee; + border-color: transparent; background-color: #387ef5; color: #fff; } .bar-positive .button:hover { color: #fff; text-decoration: none; } .bar-positive .button.active, .bar-positive .button.activated { - border-color: #0c63ee; - background-color: #0c63ee; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #0c60ee; } .bar-positive .button.button-clear { border-color: transparent; background: none; @@ -3303,16 +4153,14 @@ a.subdued { background: none; } .bar-calm .button { - border-color: #0a9ec7; + border-color: transparent; background-color: #11c1f3; color: #fff; } .bar-calm .button:hover { color: #fff; text-decoration: none; } .bar-calm .button.active, .bar-calm .button.activated { - border-color: #0a9ec7; - background-color: #0a9ec7; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #0a9dc7; } .bar-calm .button.button-clear { border-color: transparent; background: none; @@ -3324,16 +4172,14 @@ a.subdued { background: none; } .bar-assertive .button { - border-color: #e42012; + border-color: transparent; background-color: #ef473a; color: #fff; } .bar-assertive .button:hover { color: #fff; text-decoration: none; } .bar-assertive .button.active, .bar-assertive .button.activated { - border-color: #e42012; - background-color: #e42012; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #e42112; } .bar-assertive .button.button-clear { border-color: transparent; background: none; @@ -3345,16 +4191,14 @@ a.subdued { background: none; } .bar-balanced .button { - border-color: #28a54c; + border-color: transparent; background-color: #33cd5f; color: #fff; } .bar-balanced .button:hover { color: #fff; text-decoration: none; } .bar-balanced .button.active, .bar-balanced .button.activated { - border-color: #28a54c; - background-color: #28a54c; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #28a54c; } .bar-balanced .button.button-clear { border-color: transparent; background: none; @@ -3366,16 +4210,14 @@ a.subdued { background: none; } .bar-energized .button { - border-color: #e6b400; + border-color: transparent; background-color: #ffc900; color: #fff; } .bar-energized .button:hover { color: #fff; text-decoration: none; } .bar-energized .button.active, .bar-energized .button.activated { - border-color: #e6b400; - background-color: #e6b400; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #e6b500; } .bar-energized .button.button-clear { border-color: transparent; background: none; @@ -3387,16 +4229,14 @@ a.subdued { background: none; } .bar-royal .button { - border-color: #6b46e5; + border-color: transparent; background-color: #886aea; color: #fff; } .bar-royal .button:hover { color: #fff; text-decoration: none; } .bar-royal .button.active, .bar-royal .button.activated { - border-color: #6b46e5; - background-color: #6b46e5; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #6b46e5; } .bar-royal .button.button-clear { border-color: transparent; background: none; @@ -3408,16 +4248,14 @@ a.subdued { background: none; } .bar-dark .button { - border-color: #111; + border-color: transparent; background-color: #444444; color: #fff; } .bar-dark .button:hover { color: #fff; text-decoration: none; } .bar-dark .button.active, .bar-dark .button.activated { - border-color: #000; - background-color: #262626; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #262626; } .bar-dark .button.button-clear { border-color: transparent; background: none; @@ -3469,7 +4307,8 @@ a.subdued { left: 0; z-index: 9; } -.bar .back-button.hide, .bar .buttons .hide { +.bar .back-button.hide, +.bar .buttons .hide { display: none; } .nav-bar-tabs-top .bar { @@ -3526,84 +4365,102 @@ a.subdued { background-repeat: no-repeat; } } /* Allow parent element of tabs to define color, or just the tab itself */ -.tabs-light > .tabs, .tabs.tabs-light { +.tabs-light > .tabs, +.tabs.tabs-light { border-color: #ddd; background-color: #fff; background-image: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%); color: #444; } - .tabs-light > .tabs .tab-item .badge, .tabs.tabs-light .tab-item .badge { + .tabs-light > .tabs .tab-item .badge, + .tabs.tabs-light .tab-item .badge { background-color: #444; color: #fff; } -.tabs-stable > .tabs, .tabs.tabs-stable { +.tabs-stable > .tabs, +.tabs.tabs-stable { border-color: #b2b2b2; background-color: #f8f8f8; background-image: linear-gradient(0deg, #b2b2b2, #b2b2b2 50%, transparent 50%); color: #444; } - .tabs-stable > .tabs .tab-item .badge, .tabs.tabs-stable .tab-item .badge { + .tabs-stable > .tabs .tab-item .badge, + .tabs.tabs-stable .tab-item .badge { background-color: #444; color: #f8f8f8; } -.tabs-positive > .tabs, .tabs.tabs-positive { - border-color: #0c63ee; +.tabs-positive > .tabs, +.tabs.tabs-positive { + border-color: #0c60ee; background-color: #387ef5; - background-image: linear-gradient(0deg, #0c63ee, #0c63ee 50%, transparent 50%); + background-image: linear-gradient(0deg, #0c60ee, #0c60ee 50%, transparent 50%); color: #fff; } - .tabs-positive > .tabs .tab-item .badge, .tabs.tabs-positive .tab-item .badge { + .tabs-positive > .tabs .tab-item .badge, + .tabs.tabs-positive .tab-item .badge { background-color: #fff; color: #387ef5; } -.tabs-calm > .tabs, .tabs.tabs-calm { - border-color: #0a9ec7; +.tabs-calm > .tabs, +.tabs.tabs-calm { + border-color: #0a9dc7; background-color: #11c1f3; - background-image: linear-gradient(0deg, #0a9ec7, #0a9ec7 50%, transparent 50%); + background-image: linear-gradient(0deg, #0a9dc7, #0a9dc7 50%, transparent 50%); color: #fff; } - .tabs-calm > .tabs .tab-item .badge, .tabs.tabs-calm .tab-item .badge { + .tabs-calm > .tabs .tab-item .badge, + .tabs.tabs-calm .tab-item .badge { background-color: #fff; color: #11c1f3; } -.tabs-assertive > .tabs, .tabs.tabs-assertive { - border-color: #e42012; +.tabs-assertive > .tabs, +.tabs.tabs-assertive { + border-color: #e42112; background-color: #ef473a; - background-image: linear-gradient(0deg, #e42012, #e42012 50%, transparent 50%); + background-image: linear-gradient(0deg, #e42112, #e42112 50%, transparent 50%); color: #fff; } - .tabs-assertive > .tabs .tab-item .badge, .tabs.tabs-assertive .tab-item .badge { + .tabs-assertive > .tabs .tab-item .badge, + .tabs.tabs-assertive .tab-item .badge { background-color: #fff; color: #ef473a; } -.tabs-balanced > .tabs, .tabs.tabs-balanced { +.tabs-balanced > .tabs, +.tabs.tabs-balanced { border-color: #28a54c; background-color: #33cd5f; background-image: linear-gradient(0deg, #28a54c, #28a54c 50%, transparent 50%); color: #fff; } - .tabs-balanced > .tabs .tab-item .badge, .tabs.tabs-balanced .tab-item .badge { + .tabs-balanced > .tabs .tab-item .badge, + .tabs.tabs-balanced .tab-item .badge { background-color: #fff; color: #33cd5f; } -.tabs-energized > .tabs, .tabs.tabs-energized { - border-color: #e6b400; +.tabs-energized > .tabs, +.tabs.tabs-energized { + border-color: #e6b500; background-color: #ffc900; - background-image: linear-gradient(0deg, #e6b400, #e6b400 50%, transparent 50%); + background-image: linear-gradient(0deg, #e6b500, #e6b500 50%, transparent 50%); color: #fff; } - .tabs-energized > .tabs .tab-item .badge, .tabs.tabs-energized .tab-item .badge { + .tabs-energized > .tabs .tab-item .badge, + .tabs.tabs-energized .tab-item .badge { background-color: #fff; color: #ffc900; } -.tabs-royal > .tabs, .tabs.tabs-royal { +.tabs-royal > .tabs, +.tabs.tabs-royal { border-color: #6b46e5; background-color: #886aea; background-image: linear-gradient(0deg, #6b46e5, #6b46e5 50%, transparent 50%); color: #fff; } - .tabs-royal > .tabs .tab-item .badge, .tabs.tabs-royal .tab-item .badge { + .tabs-royal > .tabs .tab-item .badge, + .tabs.tabs-royal .tab-item .badge { background-color: #fff; color: #886aea; } -.tabs-dark > .tabs, .tabs.tabs-dark { +.tabs-dark > .tabs, +.tabs.tabs-dark { border-color: #111; background-color: #444; background-image: linear-gradient(0deg, #111, #111 50%, transparent 50%); color: #fff; } - .tabs-dark > .tabs .tab-item .badge, .tabs.tabs-dark .tab-item .badge { + .tabs-dark > .tabs .tab-item .badge, + .tabs.tabs-dark .tab-item .badge { background-color: #fff; color: #444; } @@ -3613,6 +4470,7 @@ a.subdued { border: none; border-bottom: 1px solid #ddd; padding-top: 2px; } + .tabs-striped .tab-item.tab-item-active, .tabs-striped .tab-item.active, .tabs-striped .tab-item.activated { margin-top: -2px; border-style: solid; @@ -3621,8 +4479,10 @@ a.subdued { .tabs-striped .tab-item.tab-item-active .badge, .tabs-striped .tab-item.active .badge, .tabs-striped .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-light .tabs { background-color: #fff; } + .tabs-striped.tabs-light .tab-item { color: rgba(68, 68, 68, 0.4); opacity: 1; } @@ -3634,10 +4494,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #444; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-stable .tabs { background-color: #f8f8f8; } + .tabs-striped.tabs-stable .tab-item { color: rgba(68, 68, 68, 0.4); opacity: 1; } @@ -3649,10 +4512,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #444; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-positive .tabs { background-color: #387ef5; } + .tabs-striped.tabs-positive .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3664,10 +4530,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #fff; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-calm .tabs { background-color: #11c1f3; } + .tabs-striped.tabs-calm .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3679,10 +4548,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #fff; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-assertive .tabs { background-color: #ef473a; } + .tabs-striped.tabs-assertive .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3694,10 +4566,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #fff; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-balanced .tabs { background-color: #33cd5f; } + .tabs-striped.tabs-balanced .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3709,10 +4584,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #fff; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-energized .tabs { background-color: #ffc900; } + .tabs-striped.tabs-energized .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3724,10 +4602,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #fff; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-royal .tabs { background-color: #886aea; } + .tabs-striped.tabs-royal .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3739,10 +4620,13 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #fff; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-dark .tabs { background-color: #444; } + .tabs-striped.tabs-dark .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3754,35 +4638,46 @@ a.subdued { border-style: solid; border-width: 2px 0 0 0; border-color: #fff; } + .tabs-striped.tabs-top .tab-item.tab-item-active .badge, .tabs-striped.tabs-top .tab-item.active .badge, .tabs-striped.tabs-top .tab-item.activated .badge { top: 4%; } + .tabs-striped.tabs-background-light .tabs { background-color: #fff; background-image: none; } + .tabs-striped.tabs-background-stable .tabs { background-color: #f8f8f8; background-image: none; } + .tabs-striped.tabs-background-positive .tabs { background-color: #387ef5; background-image: none; } + .tabs-striped.tabs-background-calm .tabs { background-color: #11c1f3; background-image: none; } + .tabs-striped.tabs-background-assertive .tabs { background-color: #ef473a; background-image: none; } + .tabs-striped.tabs-background-balanced .tabs { background-color: #33cd5f; background-image: none; } + .tabs-striped.tabs-background-energized .tabs { background-color: #ffc900; background-image: none; } + .tabs-striped.tabs-background-royal .tabs { background-color: #886aea; background-image: none; } + .tabs-striped.tabs-background-dark .tabs { background-color: #444; background-image: none; } + .tabs-striped.tabs-color-light .tab-item { color: rgba(255, 255, 255, 0.4); opacity: 1; } @@ -3796,6 +4691,7 @@ a.subdued { .tabs-striped.tabs-color-light .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-light .tab-item.active .badge, .tabs-striped.tabs-color-light .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-stable .tab-item { color: rgba(248, 248, 248, 0.4); opacity: 1; } @@ -3809,6 +4705,7 @@ a.subdued { .tabs-striped.tabs-color-stable .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-stable .tab-item.active .badge, .tabs-striped.tabs-color-stable .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-positive .tab-item { color: rgba(56, 126, 245, 0.4); opacity: 1; } @@ -3822,6 +4719,7 @@ a.subdued { .tabs-striped.tabs-color-positive .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-positive .tab-item.active .badge, .tabs-striped.tabs-color-positive .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-calm .tab-item { color: rgba(17, 193, 243, 0.4); opacity: 1; } @@ -3835,6 +4733,7 @@ a.subdued { .tabs-striped.tabs-color-calm .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-calm .tab-item.active .badge, .tabs-striped.tabs-color-calm .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-assertive .tab-item { color: rgba(239, 71, 58, 0.4); opacity: 1; } @@ -3848,6 +4747,7 @@ a.subdued { .tabs-striped.tabs-color-assertive .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-assertive .tab-item.active .badge, .tabs-striped.tabs-color-assertive .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-balanced .tab-item { color: rgba(51, 205, 95, 0.4); opacity: 1; } @@ -3861,6 +4761,7 @@ a.subdued { .tabs-striped.tabs-color-balanced .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-balanced .tab-item.active .badge, .tabs-striped.tabs-color-balanced .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-energized .tab-item { color: rgba(255, 201, 0, 0.4); opacity: 1; } @@ -3874,6 +4775,7 @@ a.subdued { .tabs-striped.tabs-color-energized .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-energized .tab-item.active .badge, .tabs-striped.tabs-color-energized .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-royal .tab-item { color: rgba(136, 106, 234, 0.4); opacity: 1; } @@ -3887,6 +4789,7 @@ a.subdued { .tabs-striped.tabs-color-royal .tab-item.tab-item-active .badge, .tabs-striped.tabs-color-royal .tab-item.active .badge, .tabs-striped.tabs-color-royal .tab-item.activated .badge { top: 2px; opacity: 1; } + .tabs-striped.tabs-color-dark .tab-item { color: rgba(68, 68, 68, 0.4); opacity: 1; } @@ -3901,47 +4804,56 @@ a.subdued { top: 2px; opacity: 1; } -.tabs-background-light .tabs, .tabs-background-light > .tabs { +.tabs-background-light .tabs, +.tabs-background-light > .tabs { background-color: #fff; background-image: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%); border-color: #ddd; } -.tabs-background-stable .tabs, .tabs-background-stable > .tabs { +.tabs-background-stable .tabs, +.tabs-background-stable > .tabs { background-color: #f8f8f8; background-image: linear-gradient(0deg, #b2b2b2, #b2b2b2 50%, transparent 50%); border-color: #b2b2b2; } -.tabs-background-positive .tabs, .tabs-background-positive > .tabs { +.tabs-background-positive .tabs, +.tabs-background-positive > .tabs { background-color: #387ef5; - background-image: linear-gradient(0deg, #0c63ee, #0c63ee 50%, transparent 50%); - border-color: #0c63ee; } + background-image: linear-gradient(0deg, #0c60ee, #0c60ee 50%, transparent 50%); + border-color: #0c60ee; } -.tabs-background-calm .tabs, .tabs-background-calm > .tabs { +.tabs-background-calm .tabs, +.tabs-background-calm > .tabs { background-color: #11c1f3; - background-image: linear-gradient(0deg, #0a9ec7, #0a9ec7 50%, transparent 50%); - border-color: #0a9ec7; } + background-image: linear-gradient(0deg, #0a9dc7, #0a9dc7 50%, transparent 50%); + border-color: #0a9dc7; } -.tabs-background-assertive .tabs, .tabs-background-assertive > .tabs { +.tabs-background-assertive .tabs, +.tabs-background-assertive > .tabs { background-color: #ef473a; - background-image: linear-gradient(0deg, #e42012, #e42012 50%, transparent 50%); - border-color: #e42012; } + background-image: linear-gradient(0deg, #e42112, #e42112 50%, transparent 50%); + border-color: #e42112; } -.tabs-background-balanced .tabs, .tabs-background-balanced > .tabs { +.tabs-background-balanced .tabs, +.tabs-background-balanced > .tabs { background-color: #33cd5f; background-image: linear-gradient(0deg, #28a54c, #28a54c 50%, transparent 50%); border-color: #28a54c; } -.tabs-background-energized .tabs, .tabs-background-energized > .tabs { +.tabs-background-energized .tabs, +.tabs-background-energized > .tabs { background-color: #ffc900; - background-image: linear-gradient(0deg, #e6b400, #e6b400 50%, transparent 50%); - border-color: #e6b400; } + background-image: linear-gradient(0deg, #e6b500, #e6b500 50%, transparent 50%); + border-color: #e6b500; } -.tabs-background-royal .tabs, .tabs-background-royal > .tabs { +.tabs-background-royal .tabs, +.tabs-background-royal > .tabs { background-color: #886aea; background-image: linear-gradient(0deg, #6b46e5, #6b46e5 50%, transparent 50%); border-color: #6b46e5; } -.tabs-background-dark .tabs, .tabs-background-dark > .tabs { +.tabs-background-dark .tabs, +.tabs-background-dark > .tabs { background-color: #444; background-image: linear-gradient(0deg, #111, #111 50%, transparent 50%); border-color: #111; } @@ -4049,34 +4961,42 @@ ion-tabs.tabs-color-active-light .tab-item { color: #444; } ion-tabs.tabs-color-active-light .tab-item.tab-item-active, ion-tabs.tabs-color-active-light .tab-item.active, ion-tabs.tabs-color-active-light .tab-item.activated { color: #fff; } + ion-tabs.tabs-color-active-stable .tab-item { color: #444; } ion-tabs.tabs-color-active-stable .tab-item.tab-item-active, ion-tabs.tabs-color-active-stable .tab-item.active, ion-tabs.tabs-color-active-stable .tab-item.activated { color: #f8f8f8; } + ion-tabs.tabs-color-active-positive .tab-item { color: #444; } ion-tabs.tabs-color-active-positive .tab-item.tab-item-active, ion-tabs.tabs-color-active-positive .tab-item.active, ion-tabs.tabs-color-active-positive .tab-item.activated { color: #387ef5; } + ion-tabs.tabs-color-active-calm .tab-item { color: #444; } ion-tabs.tabs-color-active-calm .tab-item.tab-item-active, ion-tabs.tabs-color-active-calm .tab-item.active, ion-tabs.tabs-color-active-calm .tab-item.activated { color: #11c1f3; } + ion-tabs.tabs-color-active-assertive .tab-item { color: #444; } ion-tabs.tabs-color-active-assertive .tab-item.tab-item-active, ion-tabs.tabs-color-active-assertive .tab-item.active, ion-tabs.tabs-color-active-assertive .tab-item.activated { color: #ef473a; } + ion-tabs.tabs-color-active-balanced .tab-item { color: #444; } ion-tabs.tabs-color-active-balanced .tab-item.tab-item-active, ion-tabs.tabs-color-active-balanced .tab-item.active, ion-tabs.tabs-color-active-balanced .tab-item.activated { color: #33cd5f; } + ion-tabs.tabs-color-active-energized .tab-item { color: #444; } ion-tabs.tabs-color-active-energized .tab-item.tab-item-active, ion-tabs.tabs-color-active-energized .tab-item.active, ion-tabs.tabs-color-active-energized .tab-item.activated { color: #ffc900; } + ion-tabs.tabs-color-active-royal .tab-item { color: #444; } ion-tabs.tabs-color-active-royal .tab-item.tab-item-active, ion-tabs.tabs-color-active-royal .tab-item.active, ion-tabs.tabs-color-active-royal .tab-item.activated { color: #886aea; } + ion-tabs.tabs-color-active-dark .tab-item { color: #fff; } ion-tabs.tabs-color-active-dark .tab-item.tab-item-active, ion-tabs.tabs-color-active-dark .tab-item.active, ion-tabs.tabs-color-active-dark .tab-item.activated { @@ -4086,11 +5006,11 @@ ion-tabs.tabs-color-active-dark .tab-item { padding-bottom: 0; } .tabs-top.tabs-striped .tab-item { background: transparent; - -webkit-transition: color 0.1s ease; - -moz-transition: color 0.1s ease; - -ms-transition: color 0.1s ease; - -o-transition: color 0.1s ease; - transition: color 0.1s ease; } + -webkit-transition: color .1s ease; + -moz-transition: color .1s ease; + -ms-transition: color .1s ease; + -o-transition: color .1s ease; + transition: color .1s ease; } .tabs-top.tabs-striped .tab-item.tab-item-active, .tabs-top.tabs-striped .tab-item.active, .tabs-top.tabs-striped .tab-item.activated { margin-top: 1px; border-width: 0px 0px 2px 0px !important; @@ -4098,11 +5018,11 @@ ion-tabs.tabs-color-active-dark .tab-item { .tabs-top.tabs-striped .tab-item.tab-item-active > .badge, .tabs-top.tabs-striped .tab-item.tab-item-active > i, .tabs-top.tabs-striped .tab-item.active > .badge, .tabs-top.tabs-striped .tab-item.active > i, .tabs-top.tabs-striped .tab-item.activated > .badge, .tabs-top.tabs-striped .tab-item.activated > i { margin-top: -1px; } .tabs-top.tabs-striped .tab-item .badge { - -webkit-transition: color 0.2s ease; - -moz-transition: color 0.2s ease; - -ms-transition: color 0.2s ease; - -o-transition: color 0.2s ease; - transition: color 0.2s ease; } + -webkit-transition: color .2s ease; + -moz-transition: color .2s ease; + -ms-transition: color .2s ease; + -o-transition: color .2s ease; + transition: color .2s ease; } .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active .tab-title, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active i, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active .tab-title, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active i, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated .tab-title, .tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated i { display: block; margin-top: -1px; } @@ -4113,13 +5033,17 @@ ion-tabs.tabs-color-active-dark .tab-item { /* Allow parent element to have tabs-top */ /* If you change this, change platform.scss as well */ -.tabs-top > .tabs, .tabs.tabs-top { +.tabs-top > .tabs, +.tabs.tabs-top { top: 44px; padding-top: 0; background-position: bottom; border-top-width: 0; border-bottom-width: 1px; } - .tabs-top > .tabs .tab-item.tab-item-active .badge, .tabs-top > .tabs .tab-item.active .badge, .tabs-top > .tabs .tab-item.activated .badge, .tabs.tabs-top .tab-item.tab-item-active .badge, .tabs.tabs-top .tab-item.active .badge, .tabs.tabs-top .tab-item.activated .badge { + .tabs-top > .tabs .tab-item.tab-item-active .badge, .tabs-top > .tabs .tab-item.active .badge, .tabs-top > .tabs .tab-item.activated .badge, + .tabs.tabs-top .tab-item.tab-item-active .badge, + .tabs.tabs-top .tab-item.active .badge, + .tabs.tabs-top .tab-item.activated .badge { top: 4%; } .tabs-top ~ .bar-header { @@ -4143,17 +5067,21 @@ ion-tabs.tabs-color-active-dark .tab-item { white-space: nowrap; font-weight: 400; font-size: 14px; - font-family: "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; opacity: 0.7; } .tab-item:hover { cursor: pointer; } .tab-item.tab-hidden { display: none; } -.tabs-item-hide > .tabs, .tabs.tabs-item-hide { +.tabs-item-hide > .tabs, +.tabs.tabs-item-hide { display: none; } -.tabs-icon-top > .tabs .tab-item, .tabs-icon-top.tabs .tab-item, .tabs-icon-bottom > .tabs .tab-item, .tabs-icon-bottom.tabs .tab-item { +.tabs-icon-top > .tabs .tab-item, +.tabs-icon-top.tabs .tab-item, +.tabs-icon-bottom > .tabs .tab-item, +.tabs-icon-bottom.tabs .tab-item { font-size: 10px; line-height: 14px; } @@ -4163,23 +5091,41 @@ ion-tabs.tabs-color-active-dark .tab-item { height: 32px; font-size: 32px; } -.tabs-icon-left.tabs .tab-item, .tabs-icon-left > .tabs .tab-item, .tabs-icon-right.tabs .tab-item, .tabs-icon-right > .tabs .tab-item { +.tabs-icon-left.tabs .tab-item, +.tabs-icon-left > .tabs .tab-item, +.tabs-icon-right.tabs .tab-item, +.tabs-icon-right > .tabs .tab-item { font-size: 10px; } - .tabs-icon-left.tabs .tab-item .icon, .tabs-icon-left.tabs .tab-item .tab-title, .tabs-icon-left > .tabs .tab-item .icon, .tabs-icon-left > .tabs .tab-item .tab-title, .tabs-icon-right.tabs .tab-item .icon, .tabs-icon-right.tabs .tab-item .tab-title, .tabs-icon-right > .tabs .tab-item .icon, .tabs-icon-right > .tabs .tab-item .tab-title { + .tabs-icon-left.tabs .tab-item .icon, .tabs-icon-left.tabs .tab-item .tab-title, + .tabs-icon-left > .tabs .tab-item .icon, + .tabs-icon-left > .tabs .tab-item .tab-title, + .tabs-icon-right.tabs .tab-item .icon, + .tabs-icon-right.tabs .tab-item .tab-title, + .tabs-icon-right > .tabs .tab-item .icon, + .tabs-icon-right > .tabs .tab-item .tab-title { display: inline-block; vertical-align: top; - margin-top: -0.1em; } - .tabs-icon-left.tabs .tab-item .icon:before, .tabs-icon-left.tabs .tab-item .tab-title:before, .tabs-icon-left > .tabs .tab-item .icon:before, .tabs-icon-left > .tabs .tab-item .tab-title:before, .tabs-icon-right.tabs .tab-item .icon:before, .tabs-icon-right.tabs .tab-item .tab-title:before, .tabs-icon-right > .tabs .tab-item .icon:before, .tabs-icon-right > .tabs .tab-item .tab-title:before { + margin-top: -.1em; } + .tabs-icon-left.tabs .tab-item .icon:before, .tabs-icon-left.tabs .tab-item .tab-title:before, + .tabs-icon-left > .tabs .tab-item .icon:before, + .tabs-icon-left > .tabs .tab-item .tab-title:before, + .tabs-icon-right.tabs .tab-item .icon:before, + .tabs-icon-right.tabs .tab-item .tab-title:before, + .tabs-icon-right > .tabs .tab-item .icon:before, + .tabs-icon-right > .tabs .tab-item .tab-title:before { font-size: 24px; line-height: 49px; } -.tabs-icon-left > .tabs .tab-item .icon, .tabs-icon-left.tabs .tab-item .icon { +.tabs-icon-left > .tabs .tab-item .icon, +.tabs-icon-left.tabs .tab-item .icon { padding-right: 3px; } -.tabs-icon-right > .tabs .tab-item .icon, .tabs-icon-right.tabs .tab-item .icon { +.tabs-icon-right > .tabs .tab-item .icon, +.tabs-icon-right.tabs .tab-item .icon { padding-left: 3px; } -.tabs-icon-only > .tabs .icon, .tabs-icon-only.tabs .icon { +.tabs-icon-only > .tabs .icon, +.tabs-icon-only.tabs .icon { line-height: inherit; } .tab-item.has-badge { @@ -4197,25 +5143,45 @@ ion-tabs.tabs-color-active-dark .tab-item { /* Navigational tab */ /* Active state for tab */ -.tab-item.tab-item-active, .tab-item.active, .tab-item.activated { +.tab-item.tab-item-active, +.tab-item.active, +.tab-item.activated { opacity: 1; } - .tab-item.tab-item-active.tab-item-light, .tab-item.active.tab-item-light, .tab-item.activated.tab-item-light { + .tab-item.tab-item-active.tab-item-light, + .tab-item.active.tab-item-light, + .tab-item.activated.tab-item-light { color: #fff; } - .tab-item.tab-item-active.tab-item-stable, .tab-item.active.tab-item-stable, .tab-item.activated.tab-item-stable { + .tab-item.tab-item-active.tab-item-stable, + .tab-item.active.tab-item-stable, + .tab-item.activated.tab-item-stable { color: #f8f8f8; } - .tab-item.tab-item-active.tab-item-positive, .tab-item.active.tab-item-positive, .tab-item.activated.tab-item-positive { + .tab-item.tab-item-active.tab-item-positive, + .tab-item.active.tab-item-positive, + .tab-item.activated.tab-item-positive { color: #387ef5; } - .tab-item.tab-item-active.tab-item-calm, .tab-item.active.tab-item-calm, .tab-item.activated.tab-item-calm { + .tab-item.tab-item-active.tab-item-calm, + .tab-item.active.tab-item-calm, + .tab-item.activated.tab-item-calm { color: #11c1f3; } - .tab-item.tab-item-active.tab-item-assertive, .tab-item.active.tab-item-assertive, .tab-item.activated.tab-item-assertive { + .tab-item.tab-item-active.tab-item-assertive, + .tab-item.active.tab-item-assertive, + .tab-item.activated.tab-item-assertive { color: #ef473a; } - .tab-item.tab-item-active.tab-item-balanced, .tab-item.active.tab-item-balanced, .tab-item.activated.tab-item-balanced { + .tab-item.tab-item-active.tab-item-balanced, + .tab-item.active.tab-item-balanced, + .tab-item.activated.tab-item-balanced { color: #33cd5f; } - .tab-item.tab-item-active.tab-item-energized, .tab-item.active.tab-item-energized, .tab-item.activated.tab-item-energized { + .tab-item.tab-item-active.tab-item-energized, + .tab-item.active.tab-item-energized, + .tab-item.activated.tab-item-energized { color: #ffc900; } - .tab-item.tab-item-active.tab-item-royal, .tab-item.active.tab-item-royal, .tab-item.activated.tab-item-royal { + .tab-item.tab-item-active.tab-item-royal, + .tab-item.active.tab-item-royal, + .tab-item.activated.tab-item-royal { color: #886aea; } - .tab-item.tab-item-active.tab-item-dark, .tab-item.active.tab-item-dark, .tab-item.activated.tab-item-dark { + .tab-item.tab-item-active.tab-item-dark, + .tab-item.active.tab-item-dark, + .tab-item.activated.tab-item-dark { color: #444; } .item.tabs { @@ -4229,11 +5195,18 @@ ion-tabs.tabs-color-active-dark .tab-item { .item.tabs .icon:before { position: relative; } -.tab-item.disabled, .tab-item[disabled] { - opacity: 0.4; +.tab-item.disabled, +.tab-item[disabled] { + opacity: .4; cursor: default; pointer-events: none; } +.nav-bar-tabs-top.hide ~ .view-container .tabs-top .tabs { + top: 0; } + +.pane[hide-nav-bar="true"] .has-tabs-top { + top: 49px; } + /** * Menus * -------------------------------------------------- @@ -4259,10 +5232,18 @@ ion-tabs.tabs-color-active-dark .tab-item { transform: none; box-shadow: -1px 0px 2px rgba(0, 0, 0, 0.2), 1px 0px 2px rgba(0, 0, 0, 0.2); } -.menu-open .menu-content .pane, .menu-open .menu-content .scroll-content { +.menu-open .menu-content .pane, +.menu-open .menu-content .scroll-content { + pointer-events: none; } + +.menu-open .menu-content .scroll-content .scroll { pointer-events: none; } -.grade-b .menu-content, .grade-c .menu-content { +.menu-open .menu-content .scroll-content:not(.overflow-scroll) { + overflow: hidden; } + +.grade-b .menu-content, +.grade-c .menu-content { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; @@ -4290,7 +5271,8 @@ ion-tabs.tabs-color-active-dark .tab-item { * -------------------------------------------------- * Modals are independent windows that slide in from off-screen. */ -.modal-backdrop, .modal-backdrop-bg { +.modal-backdrop, +.modal-backdrop-bg { position: fixed; top: 0; left: 0; @@ -4325,9 +5307,11 @@ ion-tabs.tabs-color-active-dark .tab-item { height: 44px; } .platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader) > * { margin-top: 0; } - .platform-ios.platform-cordova .modal-wrapper .modal .tabs-top > .tabs, .platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top { + .platform-ios.platform-cordova .modal-wrapper .modal .tabs-top > .tabs, + .platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top { top: 44px; } - .platform-ios.platform-cordova .modal-wrapper .modal .has-header, .platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader { + .platform-ios.platform-cordova .modal-wrapper .modal .has-header, + .platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader { top: 44px; } .platform-ios.platform-cordova .modal-wrapper .modal .has-subheader { top: 88px; } @@ -4345,9 +5329,11 @@ ion-tabs.tabs-color-active-dark .tab-item { .modal-open { pointer-events: none; } - .modal-open .modal, .modal-open .modal-backdrop { + .modal-open .modal, + .modal-open .modal-backdrop { pointer-events: auto; } - .modal-open.loading-active .modal, .modal-open.loading-active .modal-backdrop { + .modal-open.loading-active .modal, + .modal-open.loading-active .modal-backdrop { pointer-events: none; } /** @@ -4362,7 +5348,7 @@ ion-tabs.tabs-color-active-dark .tab-item { z-index: 10; width: 100%; height: 100%; - background-color: rgba(0, 0, 0, 0); } + background-color: transparent; } .popover-backdrop.active { background-color: rgba(0, 0, 0, 0.1); } @@ -4386,7 +5372,8 @@ ion-tabs.tabs-color-active-dark .tab-item { .popover.popover-bottom { margin-top: -12px; } -.popover, .popover .bar-header { +.popover, +.popover .bar-header { border-radius: 2px; } .popover .scroll-content { @@ -4407,16 +5394,20 @@ ion-tabs.tabs-color-active-dark .tab-item { .platform-ios .popover { box-shadow: 0 0 40px rgba(0, 0, 0, 0.08); border-radius: 10px; } + .platform-ios .popover .bar-header { -webkit-border-top-right-radius: 10px; border-top-right-radius: 10px; -webkit-border-top-left-radius: 10px; border-top-left-radius: 10px; } + .platform-ios .popover .scroll-content { margin: 8px 0; border-radius: 10px; } + .platform-ios .popover .scroll-content.has-header { margin-top: 0; } + .platform-ios .popover-arrow { position: absolute; display: block; @@ -4435,6 +5426,7 @@ ion-tabs.tabs-color-active-dark .tab-item { content: ''; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } + .platform-ios .popover-bottom .popover-arrow { top: auto; bottom: -10px; } @@ -4451,19 +5443,24 @@ ion-tabs.tabs-color-active-dark .tab-item { color: #4d4d4d; } .platform-android .popover.popover-bottom { margin-top: 32px; } -.platform-android .popover-backdrop, .platform-android .popover-backdrop.active { + +.platform-android .popover-backdrop, +.platform-android .popover-backdrop.active { background-color: transparent; } .popover-open { pointer-events: none; } - .popover-open .popover, .popover-open .popover-backdrop { + .popover-open .popover, + .popover-open .popover-backdrop { pointer-events: auto; } - .popover-open.loading-active .popover, .popover-open.loading-active .popover-backdrop { + .popover-open.loading-active .popover, + .popover-open.loading-active .popover-backdrop { pointer-events: none; } @media (min-width: 680px) { .popover { - width: 360px; } } + width: 360px; + margin-left: -180px; } } /** * Popups @@ -4475,7 +5472,7 @@ ion-tabs.tabs-color-active-dark .tab-item { left: 0; bottom: 0; right: 0; - background: rgba(0, 0, 0, 0); + background: transparent; display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -4532,7 +5529,8 @@ ion-tabs.tabs-color-active-dark .tab-item { -moz-flex-direction: column; -ms-flex-direction: column; flex-direction: column; } - .popup-container input, .popup-container textarea { + .popup-container input, + .popup-container textarea { width: 100%; } .popup-head { @@ -4623,7 +5621,8 @@ ion-tabs.tabs-color-active-dark .tab-item { transition: 0.2s opacity linear; visibility: hidden; opacity: 0; } - .loading-container:not(.visible) .icon, .loading-container:not(.visible) .spinner { + .loading-container:not(.visible) .icon, + .loading-container:not(.visible) .spinner { display: none; } .loading-container.visible { visibility: visible; } @@ -4673,7 +5672,13 @@ ion-tabs.tabs-color-active-dark .tab-item { color: #666; font-size: 14px; margin-bottom: 2px; } - .item h1:last-child, .item h2:last-child, .item h3:last-child, .item h4:last-child, .item h5:last-child, .item h6:last-child, .item p:last-child { + .item h1:last-child, + .item h2:last-child, + .item h3:last-child, + .item h4:last-child, + .item h5:last-child, + .item h6:last-child, + .item p:last-child { margin-bottom: 0; } .item .badge { display: -webkit-box; @@ -4700,15 +5705,15 @@ ion-tabs.tabs-color-active-dark .tab-item { background-color: #f8f8f8; color: #444; } .item.item-positive { - border-color: #0c63ee; + border-color: #0c60ee; background-color: #387ef5; color: #fff; } .item.item-calm { - border-color: #0a9ec7; + border-color: #0a9dc7; background-color: #11c1f3; color: #fff; } .item.item-assertive { - border-color: #e42012; + border-color: #e42112; background-color: #ef473a; color: #fff; } .item.item-balanced { @@ -4716,7 +5721,7 @@ ion-tabs.tabs-color-active-dark .tab-item { background-color: #33cd5f; color: #fff; } .item.item-energized { - border-color: #e6b400; + border-color: #e6b500; background-color: #ffc900; color: #fff; } .item.item-royal { @@ -4730,41 +5735,187 @@ ion-tabs.tabs-color-active-dark .tab-item { .item[ng-click]:hover { cursor: pointer; } -.list-borderless .item, .item-borderless { +.list-borderless .item, +.item-borderless { border-width: 0; } -.item.active, .item.activated, .item-complex.active .item-content, .item-complex.activated .item-content, .item .item-content.active, .item .item-content.activated { +.item.active, +.item.activated, +.item-complex.active .item-content, +.item-complex.activated .item-content, +.item .item-content.active, +.item .item-content.activated { border-color: #ccc; background-color: #D9D9D9; } - .item.active.item-light, .item.activated.item-light, .item-complex.active .item-content.item-light, .item-complex.activated .item-content.item-light, .item .item-content.active.item-light, .item .item-content.activated.item-light { + .item.active.item-complex > .item-content, + .item.activated.item-complex > .item-content, + .item-complex.active .item-content.item-complex > .item-content, + .item-complex.activated .item-content.item-complex > .item-content, + .item .item-content.active.item-complex > .item-content, + .item .item-content.activated.item-complex > .item-content { + border-color: #ccc; + background-color: #D9D9D9; } + .item.active.item-light, + .item.activated.item-light, + .item-complex.active .item-content.item-light, + .item-complex.activated .item-content.item-light, + .item .item-content.active.item-light, + .item .item-content.activated.item-light { border-color: #ccc; background-color: #fafafa; } - .item.active.item-stable, .item.activated.item-stable, .item-complex.active .item-content.item-stable, .item-complex.activated .item-content.item-stable, .item .item-content.active.item-stable, .item .item-content.activated.item-stable { + .item.active.item-light.item-complex > .item-content, + .item.activated.item-light.item-complex > .item-content, + .item-complex.active .item-content.item-light.item-complex > .item-content, + .item-complex.activated .item-content.item-light.item-complex > .item-content, + .item .item-content.active.item-light.item-complex > .item-content, + .item .item-content.activated.item-light.item-complex > .item-content { + border-color: #ccc; + background-color: #fafafa; } + .item.active.item-stable, + .item.activated.item-stable, + .item-complex.active .item-content.item-stable, + .item-complex.activated .item-content.item-stable, + .item .item-content.active.item-stable, + .item .item-content.activated.item-stable { border-color: #a2a2a2; background-color: #e5e5e5; } - .item.active.item-positive, .item.activated.item-positive, .item-complex.active .item-content.item-positive, .item-complex.activated .item-content.item-positive, .item .item-content.active.item-positive, .item .item-content.activated.item-positive { - border-color: #0c63ee; - background-color: #0c63ee; } - .item.active.item-calm, .item.activated.item-calm, .item-complex.active .item-content.item-calm, .item-complex.activated .item-content.item-calm, .item .item-content.active.item-calm, .item .item-content.activated.item-calm { - border-color: #0a9ec7; - background-color: #0a9ec7; } - .item.active.item-assertive, .item.activated.item-assertive, .item-complex.active .item-content.item-assertive, .item-complex.activated .item-content.item-assertive, .item .item-content.active.item-assertive, .item .item-content.activated.item-assertive { - border-color: #e42012; - background-color: #e42012; } - .item.active.item-balanced, .item.activated.item-balanced, .item-complex.active .item-content.item-balanced, .item-complex.activated .item-content.item-balanced, .item .item-content.active.item-balanced, .item .item-content.activated.item-balanced { + .item.active.item-stable.item-complex > .item-content, + .item.activated.item-stable.item-complex > .item-content, + .item-complex.active .item-content.item-stable.item-complex > .item-content, + .item-complex.activated .item-content.item-stable.item-complex > .item-content, + .item .item-content.active.item-stable.item-complex > .item-content, + .item .item-content.activated.item-stable.item-complex > .item-content { + border-color: #a2a2a2; + background-color: #e5e5e5; } + .item.active.item-positive, + .item.activated.item-positive, + .item-complex.active .item-content.item-positive, + .item-complex.activated .item-content.item-positive, + .item .item-content.active.item-positive, + .item .item-content.activated.item-positive { + border-color: #0c60ee; + background-color: #0c60ee; } + .item.active.item-positive.item-complex > .item-content, + .item.activated.item-positive.item-complex > .item-content, + .item-complex.active .item-content.item-positive.item-complex > .item-content, + .item-complex.activated .item-content.item-positive.item-complex > .item-content, + .item .item-content.active.item-positive.item-complex > .item-content, + .item .item-content.activated.item-positive.item-complex > .item-content { + border-color: #0c60ee; + background-color: #0c60ee; } + .item.active.item-calm, + .item.activated.item-calm, + .item-complex.active .item-content.item-calm, + .item-complex.activated .item-content.item-calm, + .item .item-content.active.item-calm, + .item .item-content.activated.item-calm { + border-color: #0a9dc7; + background-color: #0a9dc7; } + .item.active.item-calm.item-complex > .item-content, + .item.activated.item-calm.item-complex > .item-content, + .item-complex.active .item-content.item-calm.item-complex > .item-content, + .item-complex.activated .item-content.item-calm.item-complex > .item-content, + .item .item-content.active.item-calm.item-complex > .item-content, + .item .item-content.activated.item-calm.item-complex > .item-content { + border-color: #0a9dc7; + background-color: #0a9dc7; } + .item.active.item-assertive, + .item.activated.item-assertive, + .item-complex.active .item-content.item-assertive, + .item-complex.activated .item-content.item-assertive, + .item .item-content.active.item-assertive, + .item .item-content.activated.item-assertive { + border-color: #e42112; + background-color: #e42112; } + .item.active.item-assertive.item-complex > .item-content, + .item.activated.item-assertive.item-complex > .item-content, + .item-complex.active .item-content.item-assertive.item-complex > .item-content, + .item-complex.activated .item-content.item-assertive.item-complex > .item-content, + .item .item-content.active.item-assertive.item-complex > .item-content, + .item .item-content.activated.item-assertive.item-complex > .item-content { + border-color: #e42112; + background-color: #e42112; } + .item.active.item-balanced, + .item.activated.item-balanced, + .item-complex.active .item-content.item-balanced, + .item-complex.activated .item-content.item-balanced, + .item .item-content.active.item-balanced, + .item .item-content.activated.item-balanced { border-color: #28a54c; background-color: #28a54c; } - .item.active.item-energized, .item.activated.item-energized, .item-complex.active .item-content.item-energized, .item-complex.activated .item-content.item-energized, .item .item-content.active.item-energized, .item .item-content.activated.item-energized { - border-color: #e6b400; - background-color: #e6b400; } - .item.active.item-royal, .item.activated.item-royal, .item-complex.active .item-content.item-royal, .item-complex.activated .item-content.item-royal, .item .item-content.active.item-royal, .item .item-content.activated.item-royal { + .item.active.item-balanced.item-complex > .item-content, + .item.activated.item-balanced.item-complex > .item-content, + .item-complex.active .item-content.item-balanced.item-complex > .item-content, + .item-complex.activated .item-content.item-balanced.item-complex > .item-content, + .item .item-content.active.item-balanced.item-complex > .item-content, + .item .item-content.activated.item-balanced.item-complex > .item-content { + border-color: #28a54c; + background-color: #28a54c; } + .item.active.item-energized, + .item.activated.item-energized, + .item-complex.active .item-content.item-energized, + .item-complex.activated .item-content.item-energized, + .item .item-content.active.item-energized, + .item .item-content.activated.item-energized { + border-color: #e6b500; + background-color: #e6b500; } + .item.active.item-energized.item-complex > .item-content, + .item.activated.item-energized.item-complex > .item-content, + .item-complex.active .item-content.item-energized.item-complex > .item-content, + .item-complex.activated .item-content.item-energized.item-complex > .item-content, + .item .item-content.active.item-energized.item-complex > .item-content, + .item .item-content.activated.item-energized.item-complex > .item-content { + border-color: #e6b500; + background-color: #e6b500; } + .item.active.item-royal, + .item.activated.item-royal, + .item-complex.active .item-content.item-royal, + .item-complex.activated .item-content.item-royal, + .item .item-content.active.item-royal, + .item .item-content.activated.item-royal { border-color: #6b46e5; background-color: #6b46e5; } - .item.active.item-dark, .item.activated.item-dark, .item-complex.active .item-content.item-dark, .item-complex.activated .item-content.item-dark, .item .item-content.active.item-dark, .item .item-content.activated.item-dark { + .item.active.item-royal.item-complex > .item-content, + .item.activated.item-royal.item-complex > .item-content, + .item-complex.active .item-content.item-royal.item-complex > .item-content, + .item-complex.activated .item-content.item-royal.item-complex > .item-content, + .item .item-content.active.item-royal.item-complex > .item-content, + .item .item-content.activated.item-royal.item-complex > .item-content { + border-color: #6b46e5; + background-color: #6b46e5; } + .item.active.item-dark, + .item.activated.item-dark, + .item-complex.active .item-content.item-dark, + .item-complex.activated .item-content.item-dark, + .item .item-content.active.item-dark, + .item .item-content.activated.item-dark { border-color: #000; background-color: #262626; } - -.item, .item h1, .item h2, .item h3, .item h4, .item h5, .item h6, .item p, .item-content, .item-content h1, .item-content h2, .item-content h3, .item-content h4, .item-content h5, .item-content h6, .item-content p { + .item.active.item-dark.item-complex > .item-content, + .item.activated.item-dark.item-complex > .item-content, + .item-complex.active .item-content.item-dark.item-complex > .item-content, + .item-complex.activated .item-content.item-dark.item-complex > .item-content, + .item .item-content.active.item-dark.item-complex > .item-content, + .item .item-content.activated.item-dark.item-complex > .item-content { + border-color: #000; + background-color: #262626; } + +.item, +.item h1, +.item h2, +.item h3, +.item h4, +.item h5, +.item h6, +.item p, +.item-content, +.item-content h1, +.item-content h2, +.item-content h3, +.item-content h4, +.item-content h5, +.item-content h6, +.item-content p { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @@ -4784,10 +5935,13 @@ a.item { * Basically .item-complex removes any default settings which * .item added, so that .item-content looks them as just .item. */ -.item-complex, a.item.item-complex, button.item.item-complex { +.item-complex, +a.item.item-complex, +button.item.item-complex { padding: 0; } -.item-complex .item-content, .item-radio .item-content { +.item-complex .item-content, +.item-radio .item-content { position: relative; z-index: 2; padding: 16px 49px 16px 16px; @@ -4799,11 +5953,35 @@ a.item-content { color: inherit; text-decoration: none; } -.item-text-wrap .item, .item-text-wrap .item-content, .item-text-wrap, .item-text-wrap h1, .item-text-wrap h2, .item-text-wrap h3, .item-text-wrap h4, .item-text-wrap h5, .item-text-wrap h6, .item-text-wrap p, .item-complex.item-text-wrap .item-content, .item-body h1, .item-body h2, .item-body h3, .item-body h4, .item-body h5, .item-body h6, .item-body p { +.item-text-wrap .item, +.item-text-wrap .item-content, +.item-text-wrap, +.item-text-wrap h1, +.item-text-wrap h2, +.item-text-wrap h3, +.item-text-wrap h4, +.item-text-wrap h5, +.item-text-wrap h6, +.item-text-wrap p, +.item-complex.item-text-wrap .item-content, +.item-body h1, +.item-body h2, +.item-body h3, +.item-body h4, +.item-body h5, +.item-body h6, +.item-body p { overflow: visible; white-space: normal; } -.item-complex.item-text-wrap, .item-complex.item-text-wrap h1, .item-complex.item-text-wrap h2, .item-complex.item-text-wrap h3, .item-complex.item-text-wrap h4, .item-complex.item-text-wrap h5, .item-complex.item-text-wrap h6, .item-complex.item-text-wrap p { +.item-complex.item-text-wrap, +.item-complex.item-text-wrap h1, +.item-complex.item-text-wrap h2, +.item-complex.item-text-wrap h3, +.item-complex.item-text-wrap h4, +.item-complex.item-text-wrap h5, +.item-complex.item-text-wrap h6, +.item-complex.item-text-wrap p { overflow: visible; white-space: normal; } @@ -4814,6 +5992,10 @@ a.item-content { .item-complex.item-light > .item-content.active, .item-complex.item-light > .item-content:active { border-color: #ccc; background-color: #fafafa; } + .item-complex.item-light > .item-content.active.item-complex > .item-content, .item-complex.item-light > .item-content:active.item-complex > .item-content { + border-color: #ccc; + background-color: #fafafa; } + .item-complex.item-stable > .item-content { border-color: #b2b2b2; background-color: #f8f8f8; @@ -4821,27 +6003,43 @@ a.item-content { .item-complex.item-stable > .item-content.active, .item-complex.item-stable > .item-content:active { border-color: #a2a2a2; background-color: #e5e5e5; } + .item-complex.item-stable > .item-content.active.item-complex > .item-content, .item-complex.item-stable > .item-content:active.item-complex > .item-content { + border-color: #a2a2a2; + background-color: #e5e5e5; } + .item-complex.item-positive > .item-content { - border-color: #0c63ee; + border-color: #0c60ee; background-color: #387ef5; color: #fff; } .item-complex.item-positive > .item-content.active, .item-complex.item-positive > .item-content:active { - border-color: #0c63ee; - background-color: #0c63ee; } + border-color: #0c60ee; + background-color: #0c60ee; } + .item-complex.item-positive > .item-content.active.item-complex > .item-content, .item-complex.item-positive > .item-content:active.item-complex > .item-content { + border-color: #0c60ee; + background-color: #0c60ee; } + .item-complex.item-calm > .item-content { - border-color: #0a9ec7; + border-color: #0a9dc7; background-color: #11c1f3; color: #fff; } .item-complex.item-calm > .item-content.active, .item-complex.item-calm > .item-content:active { - border-color: #0a9ec7; - background-color: #0a9ec7; } + border-color: #0a9dc7; + background-color: #0a9dc7; } + .item-complex.item-calm > .item-content.active.item-complex > .item-content, .item-complex.item-calm > .item-content:active.item-complex > .item-content { + border-color: #0a9dc7; + background-color: #0a9dc7; } + .item-complex.item-assertive > .item-content { - border-color: #e42012; + border-color: #e42112; background-color: #ef473a; color: #fff; } .item-complex.item-assertive > .item-content.active, .item-complex.item-assertive > .item-content:active { - border-color: #e42012; - background-color: #e42012; } + border-color: #e42112; + background-color: #e42112; } + .item-complex.item-assertive > .item-content.active.item-complex > .item-content, .item-complex.item-assertive > .item-content:active.item-complex > .item-content { + border-color: #e42112; + background-color: #e42112; } + .item-complex.item-balanced > .item-content { border-color: #28a54c; background-color: #33cd5f; @@ -4849,13 +6047,21 @@ a.item-content { .item-complex.item-balanced > .item-content.active, .item-complex.item-balanced > .item-content:active { border-color: #28a54c; background-color: #28a54c; } + .item-complex.item-balanced > .item-content.active.item-complex > .item-content, .item-complex.item-balanced > .item-content:active.item-complex > .item-content { + border-color: #28a54c; + background-color: #28a54c; } + .item-complex.item-energized > .item-content { - border-color: #e6b400; + border-color: #e6b500; background-color: #ffc900; color: #fff; } .item-complex.item-energized > .item-content.active, .item-complex.item-energized > .item-content:active { - border-color: #e6b400; - background-color: #e6b400; } + border-color: #e6b500; + background-color: #e6b500; } + .item-complex.item-energized > .item-content.active.item-complex > .item-content, .item-complex.item-energized > .item-content:active.item-complex > .item-content { + border-color: #e6b500; + background-color: #e6b500; } + .item-complex.item-royal > .item-content { border-color: #6b46e5; background-color: #886aea; @@ -4863,6 +6069,10 @@ a.item-content { .item-complex.item-royal > .item-content.active, .item-complex.item-royal > .item-content:active { border-color: #6b46e5; background-color: #6b46e5; } + .item-complex.item-royal > .item-content.active.item-complex > .item-content, .item-complex.item-royal > .item-content:active.item-complex > .item-content { + border-color: #6b46e5; + background-color: #6b46e5; } + .item-complex.item-dark > .item-content { border-color: #111; background-color: #444; @@ -4870,12 +6080,16 @@ a.item-content { .item-complex.item-dark > .item-content.active, .item-complex.item-dark > .item-content:active { border-color: #000; background-color: #262626; } + .item-complex.item-dark > .item-content.active.item-complex > .item-content, .item-complex.item-dark > .item-content:active.item-complex > .item-content { + border-color: #000; + background-color: #262626; } /** * Item Icons * -------------------------------------------------- */ -.item-icon-left .icon, .item-icon-right .icon { +.item-icon-left .icon, +.item-icon-right .icon { display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -4891,7 +6105,8 @@ a.item-content { top: 0; height: 100%; font-size: 32px; } - .item-icon-left .icon:before, .item-icon-right .icon:before { + .item-icon-left .icon:before, + .item-icon-right .icon:before { display: block; width: 32px; text-align: center; } @@ -4924,10 +6139,12 @@ a.item-content { .item-icon-left.item-icon-right .icon:first-child { right: auto; } -.item-icon-left.item-icon-right .icon:last-child, .item-icon-left .item-delete .icon { +.item-icon-left.item-icon-right .icon:last-child, +.item-icon-left .item-delete .icon { left: auto; } -.item-icon-left .icon-accessory, .item-icon-right .icon-accessory { +.item-icon-left .icon-accessory, +.item-icon-right .icon-accessory { color: #ccc; font-size: 16px; } @@ -4945,7 +6162,8 @@ a.item-content { .item-button-left { padding-left: 72px; } -.item-button-left > .button, .item-button-left .item-content > .button { +.item-button-left > .button, +.item-button-left .item-content > .button { display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -4964,21 +6182,28 @@ a.item-content { min-height: 34px; font-size: 18px; line-height: 32px; } - .item-button-left > .button .icon:before, .item-button-left .item-content > .button .icon:before { + .item-button-left > .button .icon:before, + .item-button-left .item-content > .button .icon:before { position: relative; left: auto; width: auto; line-height: 31px; } - .item-button-left > .button > .button, .item-button-left .item-content > .button > .button { + .item-button-left > .button > .button, + .item-button-left .item-content > .button > .button { margin: 0px 2px; min-height: 34px; font-size: 18px; line-height: 32px; } -.item-button-right, a.item.item-button-right, button.item.item-button-right { +.item-button-right, +a.item.item-button-right, +button.item.item-button-right { padding-right: 80px; } -.item-button-right > .button, .item-button-right .item-content > .button, .item-button-right > .buttons, .item-button-right .item-content > .buttons { +.item-button-right > .button, +.item-button-right .item-content > .button, +.item-button-right > .buttons, +.item-button-right .item-content > .buttons { display: -webkit-box; display: -webkit-flex; display: -moz-box; @@ -4997,22 +6222,38 @@ a.item-content { min-height: 34px; font-size: 18px; line-height: 32px; } - .item-button-right > .button .icon:before, .item-button-right .item-content > .button .icon:before, .item-button-right > .buttons .icon:before, .item-button-right .item-content > .buttons .icon:before { + .item-button-right > .button .icon:before, + .item-button-right .item-content > .button .icon:before, + .item-button-right > .buttons .icon:before, + .item-button-right .item-content > .buttons .icon:before { position: relative; left: auto; width: auto; line-height: 31px; } - .item-button-right > .button > .button, .item-button-right .item-content > .button > .button, .item-button-right > .buttons > .button, .item-button-right .item-content > .buttons > .button { + .item-button-right > .button > .button, + .item-button-right .item-content > .button > .button, + .item-button-right > .buttons > .button, + .item-button-right .item-content > .buttons > .button { margin: 0px 2px; min-width: 34px; min-height: 34px; font-size: 18px; line-height: 32px; } -.item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content { +.item-avatar, +.item-avatar .item-content, +.item-avatar-left, +.item-avatar-left .item-content { padding-left: 72px; min-height: 72px; } - .item-avatar > img:first-child, .item-avatar .item-image, .item-avatar .item-content > img:first-child, .item-avatar .item-content .item-image, .item-avatar-left > img:first-child, .item-avatar-left .item-image, .item-avatar-left .item-content > img:first-child, .item-avatar-left .item-content .item-image { + .item-avatar > img:first-child, + .item-avatar .item-image, + .item-avatar .item-content > img:first-child, + .item-avatar .item-content .item-image, + .item-avatar-left > img:first-child, + .item-avatar-left .item-image, + .item-avatar-left .item-content > img:first-child, + .item-avatar-left .item-content .item-image { position: absolute; top: 16px; left: 16px; @@ -5022,10 +6263,14 @@ a.item-content { height: 100%; border-radius: 50%; } -.item-avatar-right, .item-avatar-right .item-content { +.item-avatar-right, +.item-avatar-right .item-content { padding-right: 72px; min-height: 72px; } - .item-avatar-right > img:first-child, .item-avatar-right .item-image, .item-avatar-right .item-content > img:first-child, .item-avatar-right .item-content .item-image { + .item-avatar-right > img:first-child, + .item-avatar-right .item-image, + .item-avatar-right .item-content > img:first-child, + .item-avatar-right .item-content .item-image { position: absolute; top: 16px; right: 16px; @@ -5035,11 +6280,15 @@ a.item-content { height: 100%; border-radius: 50%; } -.item-thumbnail-left, .item-thumbnail-left .item-content { +.item-thumbnail-left, +.item-thumbnail-left .item-content { padding-top: 8px; padding-left: 106px; min-height: 100px; } - .item-thumbnail-left > img:first-child, .item-thumbnail-left .item-image, .item-thumbnail-left .item-content > img:first-child, .item-thumbnail-left .item-content .item-image { + .item-thumbnail-left > img:first-child, + .item-thumbnail-left .item-image, + .item-thumbnail-left .item-content > img:first-child, + .item-thumbnail-left .item-content .item-image { position: absolute; top: 10px; left: 10px; @@ -5048,15 +6297,21 @@ a.item-content { width: 100%; height: 100%; } -.item-avatar.item-complex, .item-avatar-left.item-complex, .item-thumbnail-left.item-complex { +.item-avatar.item-complex, +.item-avatar-left.item-complex, +.item-thumbnail-left.item-complex { padding-top: 0; padding-left: 0; } -.item-thumbnail-right, .item-thumbnail-right .item-content { +.item-thumbnail-right, +.item-thumbnail-right .item-content { padding-top: 8px; padding-right: 106px; min-height: 100px; } - .item-thumbnail-right > img:first-child, .item-thumbnail-right .item-image, .item-thumbnail-right .item-content > img:first-child, .item-thumbnail-right .item-content .item-image { + .item-thumbnail-right > img:first-child, + .item-thumbnail-right .item-image, + .item-thumbnail-right .item-content > img:first-child, + .item-thumbnail-right .item-content .item-image { position: absolute; top: 10px; right: 10px; @@ -5065,7 +6320,8 @@ a.item-content { width: 100%; height: 100%; } -.item-avatar-right.item-complex, .item-thumbnail-right.item-complex { +.item-avatar-right.item-complex, +.item-thumbnail-right.item-complex { padding-top: 0; padding-right: 0; } @@ -5093,7 +6349,8 @@ a.item-content { color: #222; font-weight: 500; } -.platform-ios .item-divider-platform, .item-divider-ios { +.platform-ios .item-divider-platform, +.item-divider-ios { padding-top: 26px; text-transform: uppercase; font-weight: 300; @@ -5101,7 +6358,8 @@ a.item-content { background-color: #efeff4; color: #555; } -.platform-android .item-divider-platform, .item-divider-android { +.platform-android .item-divider-platform, +.item-divider-android { font-weight: 300; font-size: 13px; } @@ -5110,7 +6368,8 @@ a.item-content { color: #aaa; font-size: 14px; } -.item-left-editable .item-content, .item-right-editable .item-content { +.item-left-editable .item-content, +.item-right-editable .item-content { -webkit-transition-duration: 250ms; transition-duration: 250ms; -webkit-transition-timing-function: ease-in-out; @@ -5119,13 +6378,15 @@ a.item-content { -moz-transition-property: -moz-transform; transition-property: transform; } -.list-left-editing .item-left-editable .item-content, .item-left-editing.item-left-editable .item-content { +.list-left-editing .item-left-editable .item-content, +.item-left-editing.item-left-editable .item-content { -webkit-transform: translate3d(50px, 0, 0); transform: translate3d(50px, 0, 0); } .item-remove-animate.ng-leave { -webkit-transition-duration: 300ms; transition-duration: 300ms; } + .item-remove-animate.ng-leave .item-content, .item-remove-animate.ng-leave:last-of-type { -webkit-transition-duration: 300ms; transition-duration: 300ms; @@ -5133,12 +6394,15 @@ a.item-content { transition-timing-function: ease-in; -webkit-transition-property: all; transition-property: all; } + .item-remove-animate.ng-leave.ng-leave-active .item-content { opacity: 0; -webkit-transform: translate3d(-100%, 0, 0) !important; transform: translate3d(-100%, 0, 0) !important; } + .item-remove-animate.ng-leave.ng-leave-active:last-of-type { opacity: 0; } + .item-remove-animate.ng-leave.ng-leave-active ~ ion-item:not(.ng-leave) { -webkit-transform: translate3d(0, -webkit-calc(-100% + 1px), 0); transform: translate3d(0, calc(-100% + 1px), 0); @@ -5195,7 +6459,7 @@ a.item-content { color: #ef473a; font-size: 24px; } .item-delete .button.icon:hover { - opacity: 0.7; } + opacity: .7; } .item-right-edit { -webkit-transition: all ease-in-out 250ms; @@ -5318,7 +6582,8 @@ a.item-content { * -------------------------------------------------- * A card and list-inset are close to the same thing, except a card as a box shadow. */ -.card, .list-inset { +.card, +.list-inset { overflow: hidden; margin: 20px 10px; border-radius: 2px; @@ -5340,26 +6605,42 @@ a.item-content { margin-left: 0; margin-right: 0; } -.card .item:first-child, .list-inset .item:first-child, .padding > .list .item:first-child { +.card .item:first-child, +.list-inset .item:first-child, +.padding > .list .item:first-child { border-top-left-radius: 2px; border-top-right-radius: 2px; } - .card .item:first-child .item-content, .list-inset .item:first-child .item-content, .padding > .list .item:first-child .item-content { + .card .item:first-child .item-content, + .list-inset .item:first-child .item-content, + .padding > .list .item:first-child .item-content { border-top-left-radius: 2px; border-top-right-radius: 2px; } -.card .item:last-child, .list-inset .item:last-child, .padding > .list .item:last-child { + +.card .item:last-child, +.list-inset .item:last-child, +.padding > .list .item:last-child { border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } - .card .item:last-child .item-content, .list-inset .item:last-child .item-content, .padding > .list .item:last-child .item-content { + .card .item:last-child .item-content, + .list-inset .item:last-child .item-content, + .padding > .list .item:last-child .item-content { border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; } -.card .item:last-child, .list-inset .item:last-child { +.card .item:last-child, +.list-inset .item:last-child { margin-bottom: -1px; } -.card .item, .list-inset .item, .padding > .list .item, .padding-horizontal > .list .item { +.card .item, +.list-inset .item, +.padding > .list .item, +.padding-horizontal > .list .item { margin-right: 0; margin-left: 0; } - .card .item.item-input input, .list-inset .item.item-input input, .padding > .list .item.item-input input, .padding-horizontal > .list .item.item-input input { + .card .item.item-input input, + .list-inset .item.item-input input, + .padding > .list .item.item-input input, + .padding-horizontal > .list .item.item-input input { padding-right: 44px; } .padding-left > .list .item { @@ -5389,31 +6670,48 @@ a.item-content { .badge:empty { display: none; } -.tabs .tab-item .badge.badge-light, .badge.badge-light { +.tabs .tab-item .badge.badge-light, +.badge.badge-light { background-color: #fff; color: #444; } -.tabs .tab-item .badge.badge-stable, .badge.badge-stable { + +.tabs .tab-item .badge.badge-stable, +.badge.badge-stable { background-color: #f8f8f8; color: #444; } -.tabs .tab-item .badge.badge-positive, .badge.badge-positive { + +.tabs .tab-item .badge.badge-positive, +.badge.badge-positive { background-color: #387ef5; color: #fff; } -.tabs .tab-item .badge.badge-calm, .badge.badge-calm { + +.tabs .tab-item .badge.badge-calm, +.badge.badge-calm { background-color: #11c1f3; color: #fff; } -.tabs .tab-item .badge.badge-assertive, .badge.badge-assertive { + +.tabs .tab-item .badge.badge-assertive, +.badge.badge-assertive { background-color: #ef473a; color: #fff; } -.tabs .tab-item .badge.badge-balanced, .badge.badge-balanced { + +.tabs .tab-item .badge.badge-balanced, +.badge.badge-balanced { background-color: #33cd5f; color: #fff; } -.tabs .tab-item .badge.badge-energized, .badge.badge-energized { + +.tabs .tab-item .badge.badge-energized, +.badge.badge-energized { background-color: #ffc900; color: #fff; } -.tabs .tab-item .badge.badge-royal, .badge.badge-royal { + +.tabs .tab-item .badge.badge-royal, +.badge.badge-royal { background-color: #886aea; color: #fff; } -.tabs .tab-item .badge.badge-dark, .badge.badge-dark { + +.tabs .tab-item .badge.badge-dark, +.badge.badge-dark { background-color: #444; color: #fff; } @@ -5464,6 +6762,520 @@ a.item-content { transition: opacity 0.4s ease-in; opacity: 1; } +.slider-slide.ng-enter, .slider-slide.ng-leave, .slider-slide.ng-animate, +.slider-pager-page.ng-enter, +.slider-pager-page.ng-leave, +.slider-pager-page.ng-animate { + -webkit-transition: none !important; + transition: none !important; } + +.slider-slide.ng-animate, +.slider-pager-page.ng-animate { + -webkit-animation: none 0s; + animation: none 0s; } + +/** + * Swiper 3.2.7 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/swiper/ + * + * Copyright 2015, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: December 7, 2015 + */ +.swiper-container { + margin: 0 auto; + position: relative; + overflow: hidden; + /* Fix of Webkit flickering */ + z-index: 1; } + +.swiper-container-no-flexbox .swiper-slide { + float: left; } + +.swiper-container-vertical > .swiper-wrapper { + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; } + +.swiper-wrapper { + position: relative; + width: 100%; + height: 100%; + z-index: 1; + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -webkit-transition-property: -webkit-transform; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; } + +.swiper-container-android .swiper-slide, +.swiper-wrapper { + -webkit-transform: translate3d(0px, 0, 0); + -moz-transform: translate3d(0px, 0, 0); + -o-transform: translate(0px, 0px); + -ms-transform: translate3d(0px, 0, 0); + transform: translate3d(0px, 0, 0); } + +.swiper-container-multirow > .swiper-wrapper { + -webkit-box-lines: multiple; + -moz-box-lines: multiple; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; } + +.swiper-container-free-mode > .swiper-wrapper { + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; + margin: 0 auto; } + +.swiper-slide { + display: block; + -webkit-flex-shrink: 0; + -ms-flex: 0 0 auto; + flex-shrink: 0; + width: 100%; + height: 100%; + position: relative; } + +/* Auto Height */ +.swiper-container-autoheight, +.swiper-container-autoheight .swiper-slide { + height: auto; } + +.swiper-container-autoheight .swiper-wrapper { + -webkit-box-align: start; + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + -webkit-transition-property: -webkit-transform, height; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform, height; } + +/* a11y */ +.swiper-container .swiper-notification { + position: absolute; + left: 0; + top: 0; + pointer-events: none; + opacity: 0; + z-index: -1000; } + +/* IE10 Windows Phone 8 Fixes */ +.swiper-wp8-horizontal { + -ms-touch-action: pan-y; + touch-action: pan-y; } + +.swiper-wp8-vertical { + -ms-touch-action: pan-x; + touch-action: pan-x; } + +/* Arrows */ +.swiper-button-prev, +.swiper-button-next { + position: absolute; + top: 50%; + width: 27px; + height: 44px; + margin-top: -22px; + z-index: 10; + cursor: pointer; + -moz-background-size: 27px 44px; + -webkit-background-size: 27px 44px; + background-size: 27px 44px; + background-position: center; + background-repeat: no-repeat; } + +.swiper-button-prev.swiper-button-disabled, +.swiper-button-next.swiper-button-disabled { + opacity: 0.35; + cursor: auto; + pointer-events: none; } + +.swiper-button-prev, +.swiper-container-rtl .swiper-button-next { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); + left: 10px; + right: auto; } + +.swiper-button-prev.swiper-button-black, +.swiper-container-rtl .swiper-button-next.swiper-button-black { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E"); } + +.swiper-button-prev.swiper-button-white, +.swiper-container-rtl .swiper-button-next.swiper-button-white { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E"); } + +.swiper-button-next, +.swiper-container-rtl .swiper-button-prev { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); + right: 10px; + left: auto; } + +.swiper-button-next.swiper-button-black, +.swiper-container-rtl .swiper-button-prev.swiper-button-black { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E"); } + +.swiper-button-next.swiper-button-white, +.swiper-container-rtl .swiper-button-prev.swiper-button-white { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E"); } + +/* Pagination Styles */ +.swiper-pagination { + position: absolute; + text-align: center; + -webkit-transition: 300ms; + -moz-transition: 300ms; + -o-transition: 300ms; + transition: 300ms; + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + z-index: 10; } + +.swiper-pagination.swiper-pagination-hidden { + opacity: 0; } + +.swiper-pagination-bullet { + width: 8px; + height: 8px; + display: inline-block; + border-radius: 100%; + background: #000; + opacity: 0.2; } + +button.swiper-pagination-bullet { + border: none; + margin: 0; + padding: 0; + box-shadow: none; + -moz-appearance: none; + -ms-appearance: none; + -webkit-appearance: none; + appearance: none; } + +.swiper-pagination-clickable .swiper-pagination-bullet { + cursor: pointer; } + +.swiper-pagination-white .swiper-pagination-bullet { + background: #fff; } + +.swiper-pagination-bullet-active { + opacity: 1; } + +.swiper-pagination-white .swiper-pagination-bullet-active { + background: #fff; } + +.swiper-pagination-black .swiper-pagination-bullet-active { + background: #000; } + +.swiper-container-vertical > .swiper-pagination { + right: 10px; + top: 50%; + -webkit-transform: translate3d(0px, -50%, 0); + -moz-transform: translate3d(0px, -50%, 0); + -o-transform: translate(0px, -50%); + -ms-transform: translate3d(0px, -50%, 0); + transform: translate3d(0px, -50%, 0); } + +.swiper-container-vertical > .swiper-pagination .swiper-pagination-bullet { + margin: 5px 0; + display: block; } + +.swiper-container-horizontal > .swiper-pagination { + bottom: 10px; + left: 0; + width: 100%; } + +.swiper-container-horizontal > .swiper-pagination .swiper-pagination-bullet { + margin: 0 5px; } + +/* 3D Container */ +.swiper-container-3d { + -webkit-perspective: 1200px; + -moz-perspective: 1200px; + -o-perspective: 1200px; + perspective: 1200px; } + +.swiper-container-3d .swiper-wrapper, +.swiper-container-3d .swiper-slide, +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top, +.swiper-container-3d .swiper-slide-shadow-bottom, +.swiper-container-3d .swiper-cube-shadow { + -webkit-transform-style: preserve-3d; + -moz-transform-style: preserve-3d; + -ms-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top, +.swiper-container-3d .swiper-slide-shadow-bottom { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 10; } + +.swiper-container-3d .swiper-slide-shadow-left { + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(right, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +.swiper-container-3d .swiper-slide-shadow-right { + background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +.swiper-container-3d .swiper-slide-shadow-top { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +.swiper-container-3d .swiper-slide-shadow-bottom { + background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.5)), to(transparent)); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.5), transparent); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), transparent); + /* Firefox 16+, IE10, Opera 12.50+ */ } + +/* Coverflow */ +.swiper-container-coverflow .swiper-wrapper { + /* Windows 8 IE 10 fix */ + -ms-perspective: 1200px; } + +/* Fade */ +.swiper-container-fade.swiper-container-free-mode .swiper-slide { + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; } + +.swiper-container-fade .swiper-slide { + pointer-events: none; } + +.swiper-container-fade .swiper-slide .swiper-slide { + pointer-events: none; } + +.swiper-container-fade .swiper-slide-active, +.swiper-container-fade .swiper-slide-active .swiper-slide-active { + pointer-events: auto; } + +/* Cube */ +.swiper-container-cube { + overflow: visible; } + +.swiper-container-cube .swiper-slide { + pointer-events: none; + visibility: hidden; + -webkit-transform-origin: 0 0; + -moz-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; + width: 100%; + height: 100%; + z-index: 1; } + +.swiper-container-cube.swiper-container-rtl .swiper-slide { + -webkit-transform-origin: 100% 0; + -moz-transform-origin: 100% 0; + -ms-transform-origin: 100% 0; + transform-origin: 100% 0; } + +.swiper-container-cube .swiper-slide-active, +.swiper-container-cube .swiper-slide-next, +.swiper-container-cube .swiper-slide-prev, +.swiper-container-cube .swiper-slide-next + .swiper-slide { + pointer-events: auto; + visibility: visible; } + +.swiper-container-cube .swiper-slide-shadow-top, +.swiper-container-cube .swiper-slide-shadow-bottom, +.swiper-container-cube .swiper-slide-shadow-left, +.swiper-container-cube .swiper-slide-shadow-right { + z-index: 0; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; } + +.swiper-container-cube .swiper-cube-shadow { + position: absolute; + left: 0; + bottom: 0px; + width: 100%; + height: 100%; + background: #000; + opacity: 0.6; + -webkit-filter: blur(50px); + filter: blur(50px); + z-index: 0; } + +/* Scrollbar */ +.swiper-scrollbar { + border-radius: 10px; + position: relative; + -ms-touch-action: none; + background: rgba(0, 0, 0, 0.1); } + +.swiper-container-horizontal > .swiper-scrollbar { + position: absolute; + left: 1%; + bottom: 3px; + z-index: 50; + height: 5px; + width: 98%; } + +.swiper-container-vertical > .swiper-scrollbar { + position: absolute; + right: 3px; + top: 1%; + z-index: 50; + width: 5px; + height: 98%; } + +.swiper-scrollbar-drag { + height: 100%; + width: 100%; + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 10px; + left: 0; + top: 0; } + +.swiper-scrollbar-cursor-drag { + cursor: move; } + +/* Preloader */ +.swiper-lazy-preloader { + width: 42px; + height: 42px; + position: absolute; + left: 50%; + top: 50%; + margin-left: -21px; + margin-top: -21px; + z-index: 10; + -webkit-transform-origin: 50%; + -moz-transform-origin: 50%; + transform-origin: 50%; + -webkit-animation: swiper-preloader-spin 1s steps(12, end) infinite; + -moz-animation: swiper-preloader-spin 1s steps(12, end) infinite; + animation: swiper-preloader-spin 1s steps(12, end) infinite; } + +.swiper-lazy-preloader:after { + display: block; + content: ""; + width: 100%; + height: 100%; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + background-position: 50%; + -webkit-background-size: 100%; + background-size: 100%; + background-repeat: no-repeat; } + +.swiper-lazy-preloader-white:after { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); } + +@-webkit-keyframes swiper-preloader-spin { + 100% { + -webkit-transform: rotate(360deg); } } + +@keyframes swiper-preloader-spin { + 100% { + transform: rotate(360deg); } } + +ion-slides { + width: 100%; + height: 100%; + display: block; } + +.slide-zoom { + display: block; + width: 100%; + text-align: center; } + +.swiper-container { + width: 100%; + height: 100%; + padding: 0; + overflow: hidden; } + +.swiper-wrapper { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + padding: 0; } + +.swiper-slide { + width: 100%; + height: 100%; + box-sizing: border-box; + /* Center slide text vertically */ } + .swiper-slide img { + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; } + .scroll-refresher { position: absolute; top: -60px; @@ -5480,12 +7292,14 @@ a.item-content { color: #666666; text-align: center; font-size: 30px; } - .scroll-refresher .ionic-refresher-content .text-refreshing, .scroll-refresher .ionic-refresher-content .text-pulling { + .scroll-refresher .ionic-refresher-content .text-refreshing, + .scroll-refresher .ionic-refresher-content .text-pulling { font-size: 16px; line-height: 16px; } .scroll-refresher .ionic-refresher-content.ionic-refresher-with-text { bottom: 10px; } - .scroll-refresher .icon-refreshing, .scroll-refresher .icon-pulling { + .scroll-refresher .icon-refreshing, + .scroll-refresher .icon-pulling { width: 100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; @@ -5502,7 +7316,8 @@ a.item-content { animation-fill-mode: none; -webkit-transform: translate3d(0, 0, 0) rotate(0deg); transform: translate3d(0, 0, 0) rotate(0deg); } - .scroll-refresher .icon-refreshing, .scroll-refresher .text-refreshing { + .scroll-refresher .icon-refreshing, + .scroll-refresher .text-refreshing { display: none; } .scroll-refresher .icon-refreshing { -webkit-animation-duration: 1.5s; @@ -5519,9 +7334,11 @@ a.item-content { transition: transform 0.2s; -webkit-transform: scale(1, 1); transform: scale(1, 1); } - .scroll-refresher.active.refreshing .icon-pulling, .scroll-refresher.active.refreshing .text-pulling { + .scroll-refresher.active.refreshing .icon-pulling, + .scroll-refresher.active.refreshing .text-pulling { display: none; } - .scroll-refresher.active.refreshing .icon-refreshing, .scroll-refresher.active.refreshing .text-refreshing { + .scroll-refresher.active.refreshing .icon-refreshing, + .scroll-refresher.active.refreshing .text-refreshing { display: block; } .scroll-refresher.active.refreshing.refreshing-tail { -webkit-transform: scale(0, 0); @@ -5531,33 +7348,34 @@ a.item-content { -webkit-overflow-scrolling: touch; width: 100%; } .overflow-scroll > .scroll.overscroll { - position: fixed; } + position: fixed; + right: 0; + left: 0; } + +.overflow-scroll.padding > .scroll.overscroll { + padding: 10px; } @-webkit-keyframes refresh-spin { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(0); } - 100% { -webkit-transform: translate3d(0, 0, 0) rotate(180deg); } } @keyframes refresh-spin { 0% { transform: translate3d(0, 0, 0) rotate(0); } - 100% { transform: translate3d(0, 0, 0) rotate(180deg); } } @-webkit-keyframes refresh-spin-back { 0% { -webkit-transform: translate3d(0, 0, 0) rotate(180deg); } - 100% { -webkit-transform: translate3d(0, 0, 0) rotate(0); } } @keyframes refresh-spin-back { 0% { transform: translate3d(0, 0, 0) rotate(180deg); } - 100% { transform: translate3d(0, 0, 0) rotate(0); } } @@ -5602,30 +7420,41 @@ a.item-content { .spinner-android { stroke: #4b8bf4; } -.spinner-ios, .spinner-ios-small { +.spinner-ios, +.spinner-ios-small { stroke: #69717d; } .spinner-spiral .stop1 { stop-color: #fff; stop-opacity: 0; } + .spinner-spiral.spinner-light .stop1 { stop-color: #444; } + .spinner-spiral.spinner-light .stop2 { stop-color: #fff; } + .spinner-spiral.spinner-stable .stop2 { stop-color: #f8f8f8; } + .spinner-spiral.spinner-positive .stop2 { stop-color: #387ef5; } + .spinner-spiral.spinner-calm .stop2 { stop-color: #11c1f3; } + .spinner-spiral.spinner-balanced .stop2 { stop-color: #33cd5f; } + .spinner-spiral.spinner-assertive .stop2 { stop-color: #ef473a; } + .spinner-spiral.spinner-energized .stop2 { stop-color: #ffc900; } + .spinner-spiral.spinner-royal .stop2 { stop-color: #886aea; } + .spinner-spiral.spinner-dark .stop2 { stop-color: #444; } @@ -5649,13 +7478,20 @@ legend { color: #f8f8f8; font-size: 1.07143; } -label, input, button, select, textarea { +label, +input, +button, +select, +textarea { font-weight: normal; font-size: 14px; line-height: 1.42857; } -input, button, select, textarea { - font-family: "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; } +input, +button, +select, +textarea { + font-family: "-apple-system", "Helvetica Neue", "Roboto", "Segoe UI", sans-serif; } .item-input { display: -webkit-box; @@ -5790,7 +7626,8 @@ input, button, select, textarea { padding: 4px 0 0 0px; vertical-align: middle; } -.item-stacked-label input, .item-stacked-label textarea { +.item-stacked-label input, +.item-stacked-label textarea { -webkit-border-radius: 2px; border-radius: 2px; padding: 4px 8px 3px 0; @@ -5801,6 +7638,14 @@ input, button, select, textarea { overflow: hidden; height: 46px; } +.item-select.item-stacked-label select { + position: relative; + padding: 0px; + max-width: 90%; + direction: ltr; + white-space: pre-wrap; + margin: -3px; } + .item-floating-label { display: block; background-color: transparent; @@ -5818,7 +7663,21 @@ input, button, select, textarea { -webkit-transition: opacity 0.15s ease-in, top 0.2s linear; transition: opacity 0.15s ease-in, top 0.2s linear; } -textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"] { +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"] { display: block; padding-top: 2px; padding-left: 0; @@ -5828,10 +7687,20 @@ textarea, input[type="text"], input[type="password"], input[type="datetime"], in font-size: 14px; line-height: 16px; } -.platform-ios input[type="datetime-local"], .platform-ios input[type="date"], .platform-ios input[type="month"], .platform-ios input[type="time"], .platform-ios input[type="week"], .platform-android input[type="datetime-local"], .platform-android input[type="date"], .platform-android input[type="month"], .platform-android input[type="time"], .platform-android input[type="week"] { +.platform-ios input[type="datetime-local"], +.platform-ios input[type="date"], +.platform-ios input[type="month"], +.platform-ios input[type="time"], +.platform-ios input[type="week"], +.platform-android input[type="datetime-local"], +.platform-android input[type="date"], +.platform-android input[type="month"], +.platform-android input[type="time"], +.platform-android input[type="week"] { padding-top: 8px; } -.item-input input, .item-input textarea { +.item-input input, +.item-input textarea { width: 100%; } textarea { @@ -5847,37 +7716,73 @@ textarea { textarea { height: auto; } -textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"] { +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"] { border: 0; } -input[type="radio"], input[type="checkbox"] { +input[type="radio"], +input[type="checkbox"] { margin: 0; line-height: normal; } -.item-input input[type="file"], .item-input input[type="image"], .item-input input[type="submit"], .item-input input[type="reset"], .item-input input[type="button"], .item-input input[type="radio"], .item-input input[type="checkbox"] { +.item-input input[type="file"], +.item-input input[type="image"], +.item-input input[type="submit"], +.item-input input[type="reset"], +.item-input input[type="button"], +.item-input input[type="radio"], +.item-input input[type="checkbox"] { width: auto; } input[type="file"] { line-height: 34px; } -.previous-input-focus, .cloned-text-input + input, .cloned-text-input + textarea { +.previous-input-focus, +.cloned-text-input + input, +.cloned-text-input + textarea { position: absolute !important; left: -9999px; width: 200px; } -input::-moz-placeholder, textarea::-moz-placeholder { +input::-moz-placeholder, +textarea::-moz-placeholder { color: #aaaaaa; } -input:-ms-input-placeholder, textarea:-ms-input-placeholder { + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { color: #aaaaaa; } -input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { + +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { color: #aaaaaa; text-indent: 0; } -input[disabled], select[disabled], textarea[disabled], input[readonly]:not(.cloned-text-input), textarea[readonly]:not(.cloned-text-input), select[readonly] { +input[disabled], +select[disabled], +textarea[disabled], +input[readonly]:not(.cloned-text-input), +textarea[readonly]:not(.cloned-text-input), +select[readonly] { background-color: #f8f8f8; cursor: not-allowed; } -input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="radio"][readonly], input[type="checkbox"][readonly] { +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"][readonly], +input[type="checkbox"][readonly] { background-color: transparent; } /** @@ -5889,76 +7794,108 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad display: inline-block; padding: 7px 7px; cursor: pointer; } - .checkbox input:before, .checkbox .checkbox-icon:before { + .checkbox input:before, + .checkbox .checkbox-icon:before { border-color: #ddd; } - .checkbox input:checked:before, .checkbox input:checked + .checkbox-icon:before { + .checkbox input:checked:before, + .checkbox input:checked + .checkbox-icon:before { background: #387ef5; border-color: #387ef5; } -.checkbox-light input:before, .checkbox-light .checkbox-icon:before { +.checkbox-light input:before, +.checkbox-light .checkbox-icon:before { border-color: #ddd; } -.checkbox-light input:checked:before, .checkbox-light input:checked + .checkbox-icon:before { + +.checkbox-light input:checked:before, +.checkbox-light input:checked + .checkbox-icon:before { background: #ddd; border-color: #ddd; } -.checkbox-stable input:before, .checkbox-stable .checkbox-icon:before { +.checkbox-stable input:before, +.checkbox-stable .checkbox-icon:before { border-color: #b2b2b2; } -.checkbox-stable input:checked:before, .checkbox-stable input:checked + .checkbox-icon:before { + +.checkbox-stable input:checked:before, +.checkbox-stable input:checked + .checkbox-icon:before { background: #b2b2b2; border-color: #b2b2b2; } -.checkbox-positive input:before, .checkbox-positive .checkbox-icon:before { +.checkbox-positive input:before, +.checkbox-positive .checkbox-icon:before { border-color: #387ef5; } -.checkbox-positive input:checked:before, .checkbox-positive input:checked + .checkbox-icon:before { + +.checkbox-positive input:checked:before, +.checkbox-positive input:checked + .checkbox-icon:before { background: #387ef5; border-color: #387ef5; } -.checkbox-calm input:before, .checkbox-calm .checkbox-icon:before { +.checkbox-calm input:before, +.checkbox-calm .checkbox-icon:before { border-color: #11c1f3; } -.checkbox-calm input:checked:before, .checkbox-calm input:checked + .checkbox-icon:before { + +.checkbox-calm input:checked:before, +.checkbox-calm input:checked + .checkbox-icon:before { background: #11c1f3; border-color: #11c1f3; } -.checkbox-assertive input:before, .checkbox-assertive .checkbox-icon:before { +.checkbox-assertive input:before, +.checkbox-assertive .checkbox-icon:before { border-color: #ef473a; } -.checkbox-assertive input:checked:before, .checkbox-assertive input:checked + .checkbox-icon:before { + +.checkbox-assertive input:checked:before, +.checkbox-assertive input:checked + .checkbox-icon:before { background: #ef473a; border-color: #ef473a; } -.checkbox-balanced input:before, .checkbox-balanced .checkbox-icon:before { +.checkbox-balanced input:before, +.checkbox-balanced .checkbox-icon:before { border-color: #33cd5f; } -.checkbox-balanced input:checked:before, .checkbox-balanced input:checked + .checkbox-icon:before { + +.checkbox-balanced input:checked:before, +.checkbox-balanced input:checked + .checkbox-icon:before { background: #33cd5f; border-color: #33cd5f; } -.checkbox-energized input:before, .checkbox-energized .checkbox-icon:before { +.checkbox-energized input:before, +.checkbox-energized .checkbox-icon:before { border-color: #ffc900; } -.checkbox-energized input:checked:before, .checkbox-energized input:checked + .checkbox-icon:before { + +.checkbox-energized input:checked:before, +.checkbox-energized input:checked + .checkbox-icon:before { background: #ffc900; border-color: #ffc900; } -.checkbox-royal input:before, .checkbox-royal .checkbox-icon:before { +.checkbox-royal input:before, +.checkbox-royal .checkbox-icon:before { border-color: #886aea; } -.checkbox-royal input:checked:before, .checkbox-royal input:checked + .checkbox-icon:before { + +.checkbox-royal input:checked:before, +.checkbox-royal input:checked + .checkbox-icon:before { background: #886aea; border-color: #886aea; } -.checkbox-dark input:before, .checkbox-dark .checkbox-icon:before { +.checkbox-dark input:before, +.checkbox-dark .checkbox-icon:before { border-color: #444; } -.checkbox-dark input:checked:before, .checkbox-dark input:checked + .checkbox-icon:before { + +.checkbox-dark input:checked:before, +.checkbox-dark input:checked + .checkbox-icon:before { background: #444; border-color: #444; } -.checkbox input:disabled:before, .checkbox input:disabled + .checkbox-icon:before { +.checkbox input:disabled:before, +.checkbox input:disabled + .checkbox-icon:before { border-color: #ddd; } -.checkbox input:disabled:checked:before, .checkbox input:disabled:checked + .checkbox-icon:before { +.checkbox input:disabled:checked:before, +.checkbox input:disabled:checked + .checkbox-icon:before { background: #ddd; } .checkbox.checkbox-input-hidden input { display: none !important; } -.checkbox input, .checkbox-icon { +.checkbox input, +.checkbox-icon { position: relative; width: 28px; height: 28px; @@ -5967,7 +7904,8 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad background: transparent; cursor: pointer; -webkit-appearance: none; } - .checkbox input:before, .checkbox-icon:before { + .checkbox input:before, + .checkbox-icon:before { display: table; width: 100%; height: 100%; @@ -5979,10 +7917,12 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad -webkit-transition: background-color 20ms ease-in-out; transition: background-color 20ms ease-in-out; } -.checkbox input:checked:before, input:checked + .checkbox-icon:before { +.checkbox input:checked:before, +input:checked + .checkbox-icon:before { border-width: 2px; } -.checkbox input:after, .checkbox-icon:after { +.checkbox input:after, +.checkbox-icon:after { -webkit-transition: opacity 0.05s ease-in-out; transition: opacity 0.05s ease-in-out; -webkit-transform: rotate(-45deg); @@ -5999,7 +7939,10 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad content: ' '; opacity: 0; } -.platform-android .checkbox-platform input:before, .platform-android .checkbox-platform .checkbox-icon:before, .checkbox-square input:before, .checkbox-square .checkbox-icon:before { +.platform-android .checkbox-platform input:before, +.platform-android .checkbox-platform .checkbox-icon:before, +.checkbox-square input:before, +.checkbox-square .checkbox-icon:before { border-radius: 2px; width: 72%; height: 72%; @@ -6007,14 +7950,21 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad margin-left: 14%; border-width: 2px; } -.platform-android .checkbox-platform input:after, .platform-android .checkbox-platform .checkbox-icon:after, .checkbox-square input:after, .checkbox-square .checkbox-icon:after { +.platform-android .checkbox-platform input:after, +.platform-android .checkbox-platform .checkbox-icon:after, +.checkbox-square input:after, +.checkbox-square .checkbox-icon:after { border-width: 2px; top: 19%; left: 25%; width: 13px; height: 7px; } -.grade-c .checkbox input:after, .grade-c .checkbox-icon:after { +.platform-android .item-checkbox-right .checkbox-square .checkbox-icon::after { + top: 31%; } + +.grade-c .checkbox input:after, +.grade-c .checkbox-icon:after { -webkit-transform: rotate(0); transform: rotate(0); top: 3px; @@ -6025,7 +7975,8 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad font-weight: bold; font-size: 20px; } -.checkbox input:checked:after, input:checked + .checkbox-icon:after { +.checkbox input:checked:after, +input:checked + .checkbox-icon:after { opacity: 1; } .item-checkbox { @@ -6045,7 +7996,8 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad padding-right: 60px; padding-left: 16px; } -.item-checkbox-right .checkbox input, .item-checkbox-right .checkbox-icon { +.item-checkbox-right .checkbox input, +.item-checkbox-right .checkbox-icon { float: right; } /** @@ -6070,27 +8022,35 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad .toggle.toggle-light input:checked + .track { border-color: #ddd; background-color: #ddd; } + .toggle.toggle-stable input:checked + .track { border-color: #b2b2b2; background-color: #b2b2b2; } + .toggle.toggle-positive input:checked + .track { border-color: #387ef5; background-color: #387ef5; } + .toggle.toggle-calm input:checked + .track { border-color: #11c1f3; background-color: #11c1f3; } + .toggle.toggle-assertive input:checked + .track { border-color: #ef473a; background-color: #ef473a; } + .toggle.toggle-balanced input:checked + .track { border-color: #33cd5f; background-color: #33cd5f; } + .toggle.toggle-energized input:checked + .track { border-color: #ffc900; background-color: #ffc900; } + .toggle.toggle-royal input:checked + .track { border-color: #886aea; background-color: #886aea; } + .toggle.toggle-dark input:checked + .track { border-color: #444; background-color: #444; } @@ -6153,7 +8113,8 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad .item-toggle.active { box-shadow: none; } -.item-toggle, .item-toggle.item-complex .item-content { +.item-toggle, +.item-toggle.item-complex .item-content { padding-right: 99px; } .item-toggle.item-complex { @@ -6166,61 +8127,83 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad z-index: 3; } .toggle input:disabled + .track { - opacity: 0.6; } + opacity: .6; } .toggle-small .track { border: 0; width: 34px; height: 15px; background: #9e9e9e; } + .toggle-small input:checked + .track { background: rgba(0, 150, 137, 0.5); } + .toggle-small .handle { top: 2px; left: 4px; width: 21px; height: 21px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25); } + .toggle-small input:checked + .track .handle { -webkit-transform: translate3d(16px, 0, 0); transform: translate3d(16px, 0, 0); background: #009689; } + .toggle-small.item-toggle .toggle { top: 19px; } + .toggle-small .toggle-light input:checked + .track { background-color: rgba(221, 221, 221, 0.5); } + .toggle-small .toggle-light input:checked + .track .handle { background-color: #ddd; } + .toggle-small .toggle-stable input:checked + .track { background-color: rgba(178, 178, 178, 0.5); } + .toggle-small .toggle-stable input:checked + .track .handle { background-color: #b2b2b2; } + .toggle-small .toggle-positive input:checked + .track { background-color: rgba(56, 126, 245, 0.5); } + .toggle-small .toggle-positive input:checked + .track .handle { background-color: #387ef5; } + .toggle-small .toggle-calm input:checked + .track { background-color: rgba(17, 193, 243, 0.5); } + .toggle-small .toggle-calm input:checked + .track .handle { background-color: #11c1f3; } + .toggle-small .toggle-assertive input:checked + .track { background-color: rgba(239, 71, 58, 0.5); } + .toggle-small .toggle-assertive input:checked + .track .handle { background-color: #ef473a; } + .toggle-small .toggle-balanced input:checked + .track { background-color: rgba(51, 205, 95, 0.5); } + .toggle-small .toggle-balanced input:checked + .track .handle { background-color: #33cd5f; } + .toggle-small .toggle-energized input:checked + .track { background-color: rgba(255, 201, 0, 0.5); } + .toggle-small .toggle-energized input:checked + .track .handle { background-color: #ffc900; } + .toggle-small .toggle-royal input:checked + .track { background-color: rgba(136, 106, 234, 0.5); } + .toggle-small .toggle-royal input:checked + .track .handle { background-color: #886aea; } + .toggle-small .toggle-dark input:checked + .track { background-color: rgba(68, 68, 68, 0.5); } + .toggle-small .toggle-dark input:checked + .track .handle { background-color: #444; } @@ -6252,23 +8235,13 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad /* hide any radio button inputs elements (the ugly circles) */ position: absolute; left: -9999px; } - .item-radio input:checked ~ .item-content { + .item-radio input:checked + .radio-content .item-content { /* style the item content when its checked */ background: #f7f7f7; } - .item-radio input:checked ~ .radio-icon { + .item-radio input:checked + .radio-content .radio-icon { /* show the checkmark icon when its checked */ visibility: visible; } -.platform-android.grade-b .item-radio, .platform-android.grade-c .item-radio { - -webkit-animation: androidCheckedbugfix infinite 1s; } - -@-webkit-keyframes androidCheckedbugfix { - from { - padding: 0; } - - to { - padding: 0; } } - /** * Range * -------------------------------------------------- @@ -6288,7 +8261,34 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad background-position: center; background-size: 99% 2px; background-repeat: no-repeat; - -webkit-appearance: none; } + -webkit-appearance: none; + /* + &::-ms-track{ + background: transparent; + border-color: transparent; + border-width: 11px 0 16px; + color:transparent; + margin-top:20px; + } + &::-ms-thumb { + width: $range-slider-width; + height: $range-slider-height; + border-radius: $range-slider-border-radius; + background-color: $toggle-handle-off-bg-color; + border-color:$toggle-handle-off-bg-color; + box-shadow: $range-slider-box-shadow; + margin-left:1px; + margin-right:1px; + outline:none; + } + &::-ms-fill-upper { + height: $range-track-height; + background:$range-default-track-bg; + } + */ } + .range input::-moz-focus-outer { + /* hide the focus outline in Firefox */ + border: 0; } .range input::-webkit-slider-thumb { position: relative; width: 28px; @@ -6315,28 +8315,9 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad left: -15px; padding: 30px; content: ' '; } - .range input::-ms-track { - background: transparent; - border-color: transparent; - border-width: 11px 0 16px; - color: transparent; - margin-top: 20px; } - .range input::-ms-thumb { - width: 28px; - height: 28px; - border-radius: 50%; - background-color: #fff; - border-color: #fff; - box-shadow: 0 0 2px rgba(0, 0, 0, 0.3), 0 3px 5px rgba(0, 0, 0, 0.2); - margin-left: 1px; - margin-right: 1px; - outline: none; } .range input::-ms-fill-lower { height: 2px; background: #444; } - .range input::-ms-fill-upper { - height: 2px; - background: #ccc; } .range { display: -webkit-box; @@ -6445,12 +8426,12 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad top: 0; bottom: 0; right: 0; - padding: 14px 48px 16px 16px; + padding: 0 48px 0 16px; max-width: 65%; border: none; background: #fff; color: #333; - text-indent: 0.01px; + text-indent: .01px; text-overflow: ''; white-space: nowrap; font-size: 14px; @@ -6468,8 +8449,8 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad width: 0; height: 0; border-top: 5px solid; - border-right: 5px solid rgba(0, 0, 0, 0); - border-left: 5px solid rgba(0, 0, 0, 0); + border-right: 5px solid transparent; + border-left: 5px solid transparent; color: #999; content: ""; pointer-events: none; } @@ -6480,7 +8461,7 @@ input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="rad background: #f8f8f8; color: #444; } .item-select.item-stable:after, .item-select.item-stable .input-label { - color: #656565; } + color: #666666; } .item-select.item-positive select { background: #387ef5; color: #fff; } @@ -6534,7 +8515,7 @@ progress { * -------------------------------------------------- */ .button { - border-color: #b2b2b2; + border-color: transparent; background-color: #f8f8f8; color: #444; position: relative; @@ -6545,7 +8526,7 @@ progress { min-height: 47px; border-width: 1px; border-style: solid; - border-radius: 2px; + border-radius: 4px; vertical-align: top; text-align: center; text-overflow: ellipsis; @@ -6556,9 +8537,7 @@ progress { color: #444; text-decoration: none; } .button.active, .button.activated { - border-color: #a2a2a2; - background-color: #e5e5e5; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #e5e5e5; } .button:after { position: absolute; top: -6px; @@ -6578,26 +8557,24 @@ progress { pointer-events: none; } .button.icon-left:before { float: left; - padding-right: 0.2em; + padding-right: .2em; padding-left: 0; } .button.icon-right:before { float: right; padding-right: 0; - padding-left: 0.2em; } + padding-left: .2em; } .button.button-block, .button.button-full { margin-top: 10px; margin-bottom: 10px; } .button.button-light { - border-color: #ddd; + border-color: transparent; background-color: #fff; color: #444; } .button.button-light:hover { color: #444; text-decoration: none; } .button.button-light.active, .button.button-light.activated { - border-color: #ccc; - background-color: #fafafa; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #fafafa; } .button.button-light.button-clear { border-color: transparent; background: none; @@ -6615,16 +8592,14 @@ progress { box-shadow: none; color: #fff; } .button.button-stable { - border-color: #b2b2b2; + border-color: transparent; background-color: #f8f8f8; color: #444; } .button.button-stable:hover { color: #444; text-decoration: none; } .button.button-stable.active, .button.button-stable.activated { - border-color: #a2a2a2; - background-color: #e5e5e5; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #e5e5e5; } .button.button-stable.button-clear { border-color: transparent; background: none; @@ -6642,16 +8617,14 @@ progress { box-shadow: none; color: #fff; } .button.button-positive { - border-color: #0c63ee; + border-color: transparent; background-color: #387ef5; color: #fff; } .button.button-positive:hover { color: #fff; text-decoration: none; } .button.button-positive.active, .button.button-positive.activated { - border-color: #0c63ee; - background-color: #0c63ee; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #0c60ee; } .button.button-positive.button-clear { border-color: transparent; background: none; @@ -6669,16 +8642,14 @@ progress { box-shadow: none; color: #fff; } .button.button-calm { - border-color: #0a9ec7; + border-color: transparent; background-color: #11c1f3; color: #fff; } .button.button-calm:hover { color: #fff; text-decoration: none; } .button.button-calm.active, .button.button-calm.activated { - border-color: #0a9ec7; - background-color: #0a9ec7; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #0a9dc7; } .button.button-calm.button-clear { border-color: transparent; background: none; @@ -6696,16 +8667,14 @@ progress { box-shadow: none; color: #fff; } .button.button-assertive { - border-color: #e42012; + border-color: transparent; background-color: #ef473a; color: #fff; } .button.button-assertive:hover { color: #fff; text-decoration: none; } .button.button-assertive.active, .button.button-assertive.activated { - border-color: #e42012; - background-color: #e42012; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #e42112; } .button.button-assertive.button-clear { border-color: transparent; background: none; @@ -6723,16 +8692,14 @@ progress { box-shadow: none; color: #fff; } .button.button-balanced { - border-color: #28a54c; + border-color: transparent; background-color: #33cd5f; color: #fff; } .button.button-balanced:hover { color: #fff; text-decoration: none; } .button.button-balanced.active, .button.button-balanced.activated { - border-color: #28a54c; - background-color: #28a54c; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #28a54c; } .button.button-balanced.button-clear { border-color: transparent; background: none; @@ -6750,16 +8717,14 @@ progress { box-shadow: none; color: #fff; } .button.button-energized { - border-color: #e6b400; + border-color: transparent; background-color: #ffc900; color: #fff; } .button.button-energized:hover { color: #fff; text-decoration: none; } .button.button-energized.active, .button.button-energized.activated { - border-color: #e6b400; - background-color: #e6b400; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #e6b500; } .button.button-energized.button-clear { border-color: transparent; background: none; @@ -6777,16 +8742,14 @@ progress { box-shadow: none; color: #fff; } .button.button-royal { - border-color: #6b46e5; + border-color: transparent; background-color: #886aea; color: #fff; } .button.button-royal:hover { color: #fff; text-decoration: none; } .button.button-royal.active, .button.button-royal.activated { - border-color: #6b46e5; - background-color: #6b46e5; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #6b46e5; } .button.button-royal.button-clear { border-color: transparent; background: none; @@ -6804,16 +8767,14 @@ progress { box-shadow: none; color: #fff; } .button.button-dark { - border-color: #111; + border-color: transparent; background-color: #444; color: #fff; } .button.button-dark:hover { color: #fff; text-decoration: none; } .button.button-dark.active, .button.button-dark.activated { - border-color: #000; - background-color: #262626; - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.1); } + background-color: #262626; } .button.button-dark.button-clear { border-color: transparent; background: none; @@ -6910,7 +8871,8 @@ progress { .button-block:after { clear: both; } -.button-full, .button-full > .button { +.button-full, +.button-full > .button { display: block; margin-right: 0; margin-left: 0; @@ -6918,7 +8880,10 @@ progress { border-left-width: 0; border-radius: 0; } -button.button-block, button.button-full, .button-full > button.button, input.button.button-block { +button.button-block, +button.button-full, +.button-full > button.button, +input.button.button-block { width: 100%; } a.button { @@ -6926,8 +8891,9 @@ a.button { a.button .icon:before, a.button.icon:before, a.button.icon-left:before, a.button.icon-right:before { margin-top: 2px; } -.button.disabled, .button[disabled] { - opacity: 0.4; +.button.disabled, +.button[disabled] { + opacity: .4; cursor: default !important; pointer-events: none; } @@ -6980,15 +8946,19 @@ a.button { text-align: center; text-overflow: ellipsis; white-space: nowrap; } - .button-bar > .button:before, .button-bar > .button .icon:before { + .button-bar > .button:before, + .button-bar > .button .icon:before { line-height: 44px; } .button-bar > .button:first-child { - border-radius: 2px 0px 0px 2px; } + border-radius: 4px 0px 0px 4px; } .button-bar > .button:last-child { border-right-width: 1px; - border-radius: 0px 2px 2px 0px; } + border-radius: 0px 4px 4px 0px; } + .button-bar > .button:only-child { + border-radius: 4px; } -.button-bar > .button-small:before, .button-bar > .button-small .icon:before { +.button-bar > .button-small:before, +.button-bar > .button-small .icon:before { line-height: 28px; } /** @@ -7160,6 +9130,15 @@ a.button { flex: 0 0 33.3333%; max-width: 33.3333%; } +.col-40 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 40%; + -moz-box-flex: 0; + -moz-flex: 0 0 40%; + -ms-flex: 0 0 40%; + flex: 0 0 40%; + max-width: 40%; } + .col-50 { -webkit-box-flex: 0; -webkit-flex: 0 0 50%; @@ -7169,6 +9148,15 @@ a.button { flex: 0 0 50%; max-width: 50%; } +.col-60 { + -webkit-box-flex: 0; + -webkit-flex: 0 0 60%; + -moz-box-flex: 0; + -moz-flex: 0 0 60%; + -ms-flex: 0 0 60%; + flex: 0 0 60%; + max-width: 60%; } + .col-66, .col-67 { -webkit-box-flex: 0; -webkit-flex: 0 0 66.6666%; @@ -7283,7 +9271,8 @@ a.button { .opacity-hide { opacity: 0; } -.grade-b .opacity-hide, .grade-c .opacity-hide { +.grade-b .opacity-hide, +.grade-c .opacity-hide { opacity: 1; display: none; } @@ -7299,7 +9288,8 @@ a.button { .keyboard-open .hide-on-keyboard-open { display: none; } -.keyboard-open .tabs.hide-on-keyboard-open + .pane .has-tabs, .keyboard-open .bar-footer.hide-on-keyboard-open + .pane .has-footer { +.keyboard-open .tabs.hide-on-keyboard-open + .pane .has-tabs, +.keyboard-open .bar-footer.hide-on-keyboard-open + .pane .has-footer { bottom: 0; } .inline { @@ -7317,7 +9307,7 @@ a.button { -ms-user-select: none; user-select: none; -webkit-touch-callout: none; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent; -webkit-user-drag: none; -ms-touch-action: none; @@ -7371,16 +9361,20 @@ a.button { .padding { padding: 10px; } -.padding-top, .padding-vertical { +.padding-top, +.padding-vertical { padding-top: 10px; } -.padding-right, .padding-horizontal { +.padding-right, +.padding-horizontal { padding-right: 10px; } -.padding-bottom, .padding-vertical { +.padding-bottom, +.padding-vertical { padding-bottom: 10px; } -.padding-left, .padding-horizontal { +.padding-left, +.padding-horizontal { padding-left: 10px; } /** @@ -7434,7 +9428,7 @@ a.button { background-color: #387ef5; } .positive-border { - border-color: #0c63ee; } + border-color: #0c60ee; } .calm, a.calm { color: #11c1f3; } @@ -7443,7 +9437,7 @@ a.button { background-color: #11c1f3; } .calm-border { - border-color: #0a9ec7; } + border-color: #0a9dc7; } .assertive, a.assertive { color: #ef473a; } @@ -7452,7 +9446,7 @@ a.button { background-color: #ef473a; } .assertive-border { - border-color: #e42012; } + border-color: #e42112; } .balanced, a.balanced { color: #33cd5f; } @@ -7470,7 +9464,7 @@ a.button { background-color: #ffc900; } .energized-border { - border-color: #e6b400; } + border-color: #e6b500; } .royal, a.royal { color: #886aea; } @@ -7508,7 +9502,8 @@ a.button { .collection-repeat-after-container.horizontal { display: inline-block; } -[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak, .ng-hide:not(.ng-hide-animate) { +[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, +.x-ng-cloak, .ng-hide:not(.ng-hide-animate) { display: none !important; } /** @@ -7522,26 +9517,38 @@ a.button { margin-top: 19px !important; } .platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) > * { margin-top: 20px; } -.platform-ios.platform-cordova:not(.fullscreen) .tabs-top > .tabs, .platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top { + +.platform-ios.platform-cordova:not(.fullscreen) .tabs-top > .tabs, +.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top { top: 64px; } -.platform-ios.platform-cordova:not(.fullscreen) .has-header, .platform-ios.platform-cordova:not(.fullscreen) .bar-subheader { + +.platform-ios.platform-cordova:not(.fullscreen) .has-header, +.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader { top: 64px; } + .platform-ios.platform-cordova:not(.fullscreen) .has-subheader { top: 108px; } + .platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top { top: 113px; } + .platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top { top: 157px; } + .platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader) { height: 44px; } .platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper { margin-top: -1px; } .platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader) > * { margin-top: 0; } -.platform-ios.platform-cordova .popover .has-header, .platform-ios.platform-cordova .popover .bar-subheader { + +.platform-ios.platform-cordova .popover .has-header, +.platform-ios.platform-cordova .popover .bar-subheader { top: 44px; } + .platform-ios.platform-cordova .popover .has-subheader { top: 88px; } + .platform-ios.platform-cordova.status-bar-hide { margin-bottom: 20px; } @@ -7557,15 +9564,18 @@ a.button { -webkit-transform: translate3d(0, 100%, 0); transform: translate3d(0, 100%, 0); } -.slide-in-up.ng-enter, .slide-in-up > .ng-enter { +.slide-in-up.ng-enter, +.slide-in-up > .ng-enter { -webkit-transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms; transition: all cubic-bezier(0.1, 0.7, 0.1, 1) 400ms; } -.slide-in-up.ng-enter-active, .slide-in-up > .ng-enter-active { +.slide-in-up.ng-enter-active, +.slide-in-up > .ng-enter-active { -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } -.slide-in-up.ng-leave, .slide-in-up > .ng-leave { +.slide-in-up.ng-leave, +.slide-in-up > .ng-leave { -webkit-transition: all ease-in-out 250ms; transition: all ease-in-out 250ms; } @@ -7573,7 +9583,6 @@ a.button { from { -webkit-transform: scale(1); opacity: 1; } - to { -webkit-transform: scale(0.8); opacity: 0; } } @@ -7582,7 +9591,6 @@ a.button { from { transform: scale(1); opacity: 1; } - to { transform: scale(0.8); opacity: 0; } } @@ -7591,7 +9599,6 @@ a.button { from { -webkit-transform: scale(1.2); opacity: 0; } - to { -webkit-transform: scale(1); opacity: 1; } } @@ -7600,82 +9607,112 @@ a.button { from { transform: scale(1.2); opacity: 0; } - to { transform: scale(1); opacity: 1; } } -[nav-view-transition="ios"] [nav-view="entering"], [nav-view-transition="ios"] [nav-view="leaving"] { +[nav-view-transition="ios"] [nav-view="entering"], +[nav-view-transition="ios"] [nav-view="leaving"] { -webkit-transition-duration: 500ms; transition-duration: 500ms; -webkit-transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); -webkit-transition-property: opacity, -webkit-transform, box-shadow; transition-property: opacity, transform, box-shadow; } + [nav-view-transition="ios"][nav-view-direction="forward"], [nav-view-transition="ios"][nav-view-direction="back"] { background-color: #000; } -[nav-view-transition="ios"] [nav-view="active"], [nav-view-transition="ios"][nav-view-direction="forward"] [nav-view="entering"], [nav-view-transition="ios"][nav-view-direction="back"] [nav-view="leaving"] { + +[nav-view-transition="ios"] [nav-view="active"], +[nav-view-transition="ios"][nav-view-direction="forward"] [nav-view="entering"], +[nav-view-transition="ios"][nav-view-direction="back"] [nav-view="leaving"] { z-index: 3; } -[nav-view-transition="ios"][nav-view-direction="back"] [nav-view="entering"], [nav-view-transition="ios"][nav-view-direction="forward"] [nav-view="leaving"] { + +[nav-view-transition="ios"][nav-view-direction="back"] [nav-view="entering"], +[nav-view-transition="ios"][nav-view-direction="forward"] [nav-view="leaving"] { z-index: 2; } -[nav-bar-transition="ios"] .title, [nav-bar-transition="ios"] .buttons, [nav-bar-transition="ios"] .back-text { +[nav-bar-transition="ios"] .title, +[nav-bar-transition="ios"] .buttons, +[nav-bar-transition="ios"] .back-text { -webkit-transition-duration: 500ms; transition-duration: 500ms; -webkit-transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); transition-timing-function: cubic-bezier(0.36, 0.66, 0.04, 1); -webkit-transition-property: opacity, -webkit-transform; transition-property: opacity, transform; } -[nav-bar-transition="ios"] [nav-bar="active"], [nav-bar-transition="ios"] [nav-bar="entering"] { + +[nav-bar-transition="ios"] [nav-bar="active"], +[nav-bar-transition="ios"] [nav-bar="entering"] { z-index: 10; } - [nav-bar-transition="ios"] [nav-bar="active"] .bar, [nav-bar-transition="ios"] [nav-bar="entering"] .bar { + [nav-bar-transition="ios"] [nav-bar="active"] .bar, + [nav-bar-transition="ios"] [nav-bar="entering"] .bar { background: transparent; } + [nav-bar-transition="ios"] [nav-bar="cached"] { display: block; } [nav-bar-transition="ios"] [nav-bar="cached"] .header-item { display: none; } -[nav-view-transition="android"] [nav-view="entering"], [nav-view-transition="android"] [nav-view="leaving"] { +[nav-view-transition="android"] [nav-view="entering"], +[nav-view-transition="android"] [nav-view="leaving"] { -webkit-transition-duration: 200ms; transition-duration: 200ms; -webkit-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); -webkit-transition-property: -webkit-transform; transition-property: transform; } -[nav-view-transition="android"] [nav-view="active"], [nav-view-transition="android"][nav-view-direction="forward"] [nav-view="entering"], [nav-view-transition="android"][nav-view-direction="back"] [nav-view="leaving"] { + +[nav-view-transition="android"] [nav-view="active"], +[nav-view-transition="android"][nav-view-direction="forward"] [nav-view="entering"], +[nav-view-transition="android"][nav-view-direction="back"] [nav-view="leaving"] { z-index: 3; } -[nav-view-transition="android"][nav-view-direction="back"] [nav-view="entering"], [nav-view-transition="android"][nav-view-direction="forward"] [nav-view="leaving"] { + +[nav-view-transition="android"][nav-view-direction="back"] [nav-view="entering"], +[nav-view-transition="android"][nav-view-direction="forward"] [nav-view="leaving"] { z-index: 2; } -[nav-bar-transition="android"] .title, [nav-bar-transition="android"] .buttons { +[nav-bar-transition="android"] .title, +[nav-bar-transition="android"] .buttons { -webkit-transition-duration: 200ms; transition-duration: 200ms; -webkit-transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); transition-timing-function: cubic-bezier(0.4, 0.6, 0.2, 1); -webkit-transition-property: opacity; transition-property: opacity; } -[nav-bar-transition="android"] [nav-bar="active"], [nav-bar-transition="android"] [nav-bar="entering"] { + +[nav-bar-transition="android"] [nav-bar="active"], +[nav-bar-transition="android"] [nav-bar="entering"] { z-index: 10; } - [nav-bar-transition="android"] [nav-bar="active"] .bar, [nav-bar-transition="android"] [nav-bar="entering"] .bar { + [nav-bar-transition="android"] [nav-bar="active"] .bar, + [nav-bar-transition="android"] [nav-bar="entering"] .bar { background: transparent; } + [nav-bar-transition="android"] [nav-bar="cached"] { display: block; } [nav-bar-transition="android"] [nav-bar="cached"] .header-item { display: none; } -[nav-swipe="fast"] [nav-view], [nav-swipe="fast"] .title, [nav-swipe="fast"] .buttons, [nav-swipe="fast"] .back-text { +[nav-swipe="fast"] [nav-view], +[nav-swipe="fast"] .title, +[nav-swipe="fast"] .buttons, +[nav-swipe="fast"] .back-text { -webkit-transition-duration: 50ms; transition-duration: 50ms; -webkit-transition-timing-function: linear; transition-timing-function: linear; } -[nav-swipe="slow"] [nav-view], [nav-swipe="slow"] .title, [nav-swipe="slow"] .buttons, [nav-swipe="slow"] .back-text { +[nav-swipe="slow"] [nav-view], +[nav-swipe="slow"] .title, +[nav-swipe="slow"] .buttons, +[nav-swipe="slow"] .back-text { -webkit-transition-duration: 160ms; transition-duration: 160ms; -webkit-transition-timing-function: linear; transition-timing-function: linear; } -[nav-view="cached"], [nav-bar="cached"] { +[nav-view="cached"], +[nav-bar="cached"] { display: none; } [nav-view="stage"] { @@ -7683,7 +9720,9 @@ a.button { -webkit-transition-duration: 0; transition-duration: 0; } -[nav-bar="stage"] .title, [nav-bar="stage"] .buttons, [nav-bar="stage"] .back-text { +[nav-bar="stage"] .title, +[nav-bar="stage"] .buttons, +[nav-bar="stage"] .back-text { position: absolute; opacity: 0; -webkit-transition-duration: 0s; diff --git a/www/lib/ionic/css/ionic.material.css b/www/lib/ionic/css/ionic.material.css new file mode 100644 index 0000000000000000000000000000000000000000..acfce890ba003753891056d6d8092ad4c4da487a --- /dev/null +++ b/www/lib/ionic/css/ionic.material.css @@ -0,0 +1,2933 @@ +/* Directives : MD Label +==================================*/ +.item-md-label { + display: block; + background: transparent; + box-shadow: none; + margin-left: 12px; + margin-right: 12px; + padding: 30px 0 0; } + +.item-md-label .input-label { + position: absolute; + padding: 5px 0 0; + z-index: 2; + -webkit-transform: translate3d(0, -30px, 0) scale(1); + transform: translate3d(0, -30px, 0) scale(1); + -webkit-transition: all 0.2s ease; + transition: all 0.2s ease; + color: #fff; + opacity: 0.5; + filter: alpha(opacity=50); + -webkit-transform-origin: 0; + -ms-transform-origin: 0; + transform-origin: 0; } + +.item-md-label input { + background-color: rgba(0, 0, 0, 0.6); + bottom: 0; + color: #fff; + letter-spacing: 0.25rem; + padding: 20px 10px; + position: relative; + z-index: 1; } + +.item-md-label .highlight { + position: absolute; + bottom: 0; + height: 2px; + left: 0; + width: 100%; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + -webkit-transition: all 0.15s ease; + transition: all 0.15s ease; + z-index: 1; } + +.item-md-label .highlight-light { + background: #fff; } + +.item-md-label .highlight-stable { + background: #f8f8f8; } + +.item-md-label .highlight-positive { + background: #387ef5; } + +.item-md-label .highlight-calm { + background: #11c1f3; } + +.item-md-label .highlight-balanced { + background: #33cd5f; } + +.item-md-label .highlight-energized { + background: #ffc900; } + +.item-md-label .highlight-assertive { + background: #ef473a; } + +.item-md-label .highlight-royal { + background: #886aea; } + +.item-md-label .highlight-dark { + background: #444; } + +.item-md-label .input-label { + letter-spacing: 0.25rem; + padding: 0 10px; } + +.item-md-label input:focus ~ .input-label, .item-md-label input.used ~ .input-label { + font-weight: bold; + opacity: 0.7; + filter: alpha(opacity=70); + padding: 0; + text-transform: uppercase; + -webkit-transform: translate3d(0, -60px, 0) scale(0.9); + transform: translate3d(0, -60px, 0) scale(0.9); } + +.item-md-label input:focus ~ .highlight { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +/* Bar - Header - Expanded +==================================*/ +.expanded .bar.bar-header, +.bar.bar-header.expanded { + height: 75px; } + +.expanded.bar.bar-header .title, +.bar.bar-header.expanded .title { + bottom: 0; + top: initial; + padding-left: 16px; } + +.expanded .bar.bar-header .title.fab-left, +.bar.bar-header.expanded .title.fab-left { + bottom: 0; + left: 90px; + position: absolute; + right: initial; + top: initial; } + +.expanded .bar.bar-header .title.fab-right, +.bar.bar-header.expanded .title.fab-right { + bottom: 0; + left: 4px; + position: absolute; + top: initial; + right: initial; } + +.expanded .bar.bar-header + .button-fab, +.bar.bar-header.expanded + .button-fab { + top: 50px; } + +.expanded .bar.bar-header.push-down, +.bar.bar-header.expanded.push-down { + height: 44px; + overflow: hidden; } + +.expanded .bar.bar-header, +.bar.bar-header.expanded { + -webkit-transition: height 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: height 1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.expanded .bar.bar-header + .button-fab, +.bar.bar-header.expanded + .button-fab { + -webkit-transition: all 1.1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1.1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0) scale(1); + transform: translate3d(0, 0, 0) scale(1); } + +.expanded .bar.bar-header.push-down + .button-fab, +.bar.bar-header.expanded.push-down + .button-fab { + top: 0; + -webkit-transform: translate3d(-100px, -100px, 0) scale(2.5); + transform: translate3d(-100px, -100px, 0) scale(2.5); } + +.expanded .bar.bar-header.push-down .title, +.bar.bar-header.expanded.push-down .title { + opacity: 0; + filter: alpha(opacity=0); + left: initial; + right: initial; } + +.expanded .bar.bar-header .title, +.bar.bar-header.expanded .title { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transition: all 2s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 2s cubic-bezier(0.55, 0, 0.1, 1); } + +.expanded .bar.bar-header .title, .bar.bar-header.expanded .title { + bottom: 0; + left: 42px !important; + top: initial; } + +.expanded.has-header-fab-left .bar.bar-header .title, .bar.bar-header.expanded.has-header-fab-left .title { + left: 76px !important; } + +/* Bar +==================================*/ +.bar { + z-index: 2; + font-size: 1.3em; + width: 100%; + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); } + +.bar .button { + min-width: 38px; + z-index: 3; } + +.bar .no-text span.back-text { + display: none; } + +.bar .title sup { + opacity: 0.7; } + +.bar.bar-header .button + .title { + text-align: left; + left: 35px; + line-height: 46px; } + +/* Button Bar +==================================*/ +.button-bar { + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15); } + +.button-bar > .button { + box-shadow: none; + /* line-height: initial; */ } + +.button-bar > .button .icon:before, +.button-bar > .button:before { + line-height: initial; } + +.bar-footer .button-fab { + position: absolute; + top: -26px; + bottom: initial; } + +.bar-footer .buttons-left .button-fab { + left: 8px; } + +.bar-footer .buttons-right .button-fab { + right: 8px; } + +.bar .button.button-clear { + box-shadow: none; } + +.left-buttons .button-fab { + left: 8px; + top: 16px; } + +.right-buttons .button-fab { + right: 8px; + top: 16px; } + +.fab-left.title-left, +.fab-left.title.title-left { + left: 68px; } + +/* Button : FAB +==================================*/ +.button.button-fab, +.bar .button.button-fab { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + z-index: 9999; + width: 56px; + height: 56px; + max-height: initial; + max-width: initial; + border-radius: 50%; + border-radius: 50%; + overflow: hidden; + padding: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition: 0.3s fade-in-out; + transition: 0.3s fade-in-out; + -webkit-transition-property: -webkit-transform, box-shadow; + transition-property: transform, box-shadow; } + +.button.button-fab.button-fab-bottom-right, +.bar .button.button-fab.button-fab-bottom-right { + top: auto; + right: 16px; + bottom: 16px; + left: auto; + position: absolute; } + +.button.button-fab.button-fab-bottom-left, +.bar .button.button-fab.button-fab-bottom-left { + top: auto; + right: auto; + bottom: 16px; + left: 16px; + position: absolute; } + +.button.button-fab.button-fab-top-right, +.bar .button.button-fab.button-fab-top-right { + top: 32px; + right: 16px; + bottom: auto; + left: auto; + position: absolute; } + +.button.button-fab.button-fab-top-left, +.bar .button.button-fab.button-fab-top-left { + top: 32px; + right: auto; + bottom: auto; + left: 16px; + position: absolute; } + +.button.button-fab.button-fab-top-left.expanded, +.button.button-fab.button-fab-top-right.expanded, +.bar .button.button-fab.button-fab-top-left.expanded, +.bar .button.button-fab.button-fab-top-right.expanded { + top: 48px; } + +.button.button-fab i, +.bar .button.button-fab i { + font-size: 2.5rem; + margin-top: 0; } + +.button.button-fab.mini, +.bar .button.button-fab.mini { + width: 40px; + height: 40px; } + +.button.button-fab.mini i, +.bar .button.button-fab.mini i { + font-size: 2rem; } + +/* Motion */ +.motion { + -webkit-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; } + +.fade { + opacity: 0; + filter: alpha(opacity=0); + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spin-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) !important; + transform: translateZ(0) rotate(360deg) scale(0) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.menu-open .avatar { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transform: translateZ(0) rotate(0) scale(1) !important; + transform: translateZ(0) rotate(0) scale(1) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.button.button-fab.button-fab-top-left.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(-120px, 60px, 0); + transform: translate3d(-120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.button.button-fab.button-fab-top-right.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(120px, 60px, 0); + transform: translate3d(120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.button.button-fab.button-fab-bottom-left.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(-120px, 60px, 0); + transform: translate3d(-120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.button.button-fab.button-fab-bottom-right.motion { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translate3d(120px, 60px, 0); + transform: translate3d(120px, 60px, 0); + -webkit-transition: all 0.1s ease-out; + transition: all 0.1s ease-out; } + +.spin { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(0) scale(0) !important; + transform: translateZ(0) rotate(0) scale(0) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.spin.on { + -webkit-transform: translateZ(0) rotate(-360deg) scale(1) !important; + transform: translateZ(0) rotate(-360deg) scale(1) !important; } + +.flap { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flap.on { + -webkit-transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) scale(3) !important; + transform: translateZ(0) scale(3) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop.on { + -webkit-transform: translateZ(0) scale(1) !important; + transform: translateZ(0) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateY(0) scale(0) !important; + transform: translateZ(0) rotateY(0) scale(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip.on { + -webkit-transform: translateZ(0) rotateY(-720deg) scale(1) !important; + transform: translateZ(0) rotateY(-720deg) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +/* Button : Floating +==================================*/ +.button.button-floating, .bar .button.button-floating { + display: inline-block; + color: #FFF; + position: relative; + z-index: 1; + width: 37px; + height: 37px; + line-height: 37px; + padding: 0; + border-radius: 50%; + background-clip: padding-box; + -webkit-transition: 0.3s; + transition: 0.3s; + cursor: pointer; } + +.button.button-floating i, .bar .button.button-floating i { + width: inherit; + display: inline-block; + text-align: center; + color: #FFF; + font-size: 1.6rem; + line-height: 37px; } + +.button.button-floating.button-large, .bar .button.button-floating.button-large { + width: 55.5px; + height: 55.5px; } + +.button.button-floating.button-large i, .bar .button.button-floating.button-large i { + line-height: 55.5px; } + +/* Button +==================================*/ +.button, +.button.button-large, +.button.button-flat, +.bar .button, +.bar .button.button-large, +.bar .button.button-flat { + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); + display: inline-block; + height: 36px; + padding: 0 2rem; + border-radius: 2px; + background-clip: padding-box; + text-transform: uppercase; + border: none; + outline: 0; + -webkit-tap-highlight-color: transparent; } + +.button.disabled, +.button.disabled.button-large, +.button.button-floating.disabled, +.button.button-large.disabled, +.button.button:disabled, +.button.button-large:disabled, +.button.button-large:disabled, +.button.button-floating:disabled, +.bar .button.disabled, +.bar .button.disabled.button-large, +.bar .button.button-floating.disabled, +.bar .button.button-large.disabled, +.bar .button.button:disabled, +.bar .button.button-large:disabled, +.bar .button.button-large:disabled, +.bar .button.button-floating:disabled { + background-color: #DFDFDF; + box-shadow: none; + color: #9F9F9F; } + +.button.disabled:hover, +.button.disabled.button-large:hover, +.button.button-floating.disabled:hover, +.button.button-large.disabled:hover, +.button.button:disabled:hover, +.button.button-large:disabled:hover, +.button.button-large:disabled:hover, +.button.button-floating:disabled:hover, +.bar .button.disabled:hover, +.bar .button.disabled.button-large:hover, +.bar .button.button-floating.disabled:hover, +.bar .button.button-large.disabled:hover, +.bar .button.button:disabled:hover, +.bar .button.button-large:disabled:hover, +.bar .button.button-large:disabled:hover, +.bar .button.button-floating:disabled:hover { + background-color: #DFDFDF; + color: #9F9F9F; } + +.button i, +.button.button-large i, +.button.button-floating i, +.button.button-large i, +.button.button-flat i, +.bar .button i, +.bar .button.button-large i, +.bar .button.button-floating i, +.bar .button.button-large i, +.bar .button.button-flat i { + font-size: 1.3rem; } + +.button-bar .button { + border-radius: 0; } + +.button, +.button-large, +.bar .button, +.bar .button-large { + text-decoration: none; + text-align: center; + letter-spacing: 0.5px; + -webkit-transition: 0.2s ease-out; + transition: 0.2s ease-out; + cursor: pointer; } + +.button { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + outline: none; + margin: 0; + /* background: transparent; */ + white-space: nowrap; + text-align: center; + text-transform: uppercase; + font-weight: 500; + font-style: inherit; + font-variant: inherit; + font-size: inherit; + text-decoration: none; + cursor: pointer; + overflow: hidden; + -webkit-transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), -webkit-transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); + transition: box-shadow 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), background-color 0.4s cubic-bezier(0.25, 0.8, 0.25, 1), transform 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); } + +.button:focus { + outline: none; } + +.button.ng-hide { + -webkit-transition: none; + transition: none; } + +.button.cornered { + border-radius: 0; } + +.button.raised { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.button-outline, +.button-outline:hover, +.button-outline:active { + border-style: solid; + border-width: 1px; } + +.button.button-outline.button-assertive, +.button.button-outline.button-balanced, +.button.button-outline.button-calm, +.button.button-outline.button-dark, +.button.button-outline.button-energized, +.button.button-outline.button-light, +.button.button-outline.button-positive, +.button.button-outline.button-royal, +.button.button-outline.button-stable, +.button.button-outline { + border-color: rgba(0, 0, 0, 0.1); } + +.button-flat, +.bar .button-flat { + box-shadow: none; + background-color: transparent; + color: #343434; + cursor: pointer; } + +.button.button-flat.disabled, +.bar .button.button-flat.disabled { + color: #b3b3b3; } + +.button.button-large i, +.bar .button.button-large i { + font-size: 1.6rem; } + +.button-pin-header.button-floating { + position: absolute; + z-index: 1000; } + +.button-pin-header.button-pin-left { + left: 24px; + top: -24px; } + +.button-pin-header.button-pin-right { + right: 24px; + top: -24px; } + +.button:not([disabled]).raised:focus, +.button:not([disabled]).raised:hover, +.button:not([disabled]).floating:focus, +.button:not([disabled]).floating:hover { + -webkit-transform: translate3d(0, -1px, 0); + transform: translate3d(0, -1px, 0); } + +.button.button-flat { + box-shadow: none; + /* background: transparent; */ + color: inherit; } + +.button.button-flat:hover { + color: inherit; } + +.button.button-flat, +.button.button-flat:hover, +.button.button-flat:active { + color: #fff; } + +.button.button-clear, +.button.button-clear:hover, +.button.button-clear:active { + background: transparent; } + +.button-full.ink, +.button-block.ink { + display: block; } + +/* Card +==================================*/ +.card-item.item { + border: none; + padding-bottom: 4px; + padding-top: 4px; } + +.card-item.item:first-child { + padding-top: 16px; } + +.card { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); + display: block; + margin: 8px; + padding: 0; + position: relative; } + +.card .image { + display: block; + margin-top: 10px; + margin-bottom: 5px; } + +.card img { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); + display: block; + max-width: 100%; + max-height: initial; + position: static; } + +.card.card-gallery img { + border: none; + box-shadow: none; + display: block; } + +.card .card-footer { + font-size: 90%; + opacity: 0.8; + filter: alpha(opacity=80); + padding-top: 10px; } + +.card > .item { + border: none; } + +.card.card-gallery > .item { + background: inherit; } + +.card .icon + .icon { + padding-left: 1rem; } + +.card.animate-fade-in { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transform: translate3d(-30px, 1px, 0); + -webkit-transition: all 1s ease-in-out; } + +.card.animate-fade-in.done { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transform: translate3d(0, 0, 0); } + +.card .item.item-avatar { + min-height: 88px; + padding-left: 88px; } + +/* Hero +==================================*/ +.hero { + background-size: cover; + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); + color: #fff; + height: 200px; + position: relative; + text-align: center; + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + width: 100%; } + +.hero > * { + -webkit-transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 1; + filter: alpha(opacity=100); } + +.hero + .mid-bar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + height: initial; + opacity: 1; + filter: alpha(opacity=100); } + +.hero .hero-icon { + box-shadow: 0px 0 2px 0 rgba(0, 0, 0, 0.26); + border-radius: 50%; + display: inline-block; + font-size: 65px; + height: 150px; + padding: 10px 30px; + line-height: 136px; + width: 150px; } + +.hero.no-header { + height: 244px; } + +.hero > .content { + bottom: 0; + position: absolute; + text-align: center; + width: 100%; + z-index: 1; } + +.hero > .content > .avatar { + background-position: center; + background-size: cover; + border: solid 1px rgba(255, 255, 255, 0.8); + border-radius: 50%; + display: inline-block; + height: 88px; + left: auto; + margin-bottom: 10px; + position: relative; + width: 88px; } + +.hero h1 .hero h2, .hero h3, .hero h4, .hero h5, .hero h6 { + color: #fff; + margin: 0; } + +.hero h4 { + color: rgba(255, 255, 255, 0.7); + margin: 3px 0 16px; } + +.hero h1 > a, .hero h2 > a, .hero h3 > a, .hero h4 > a, .hero h5 > a, .hero h6 > a { + text-decoration: none; } + +.hero + .button-bar { + border-radius: 0; + margin-top: 0; } + +.hero + .button-bar > .button:first-child, .hero + .button-bar > .button:last-child { + border-radius: 0; } + +.hero .hero-icon { + color: #fff; + font-size: 96px; } + +.hero .hero-icon + h1 { + color: white; + letter-spacing: 0.15rem; } + +.hero .button, .hero .button.button-large, .hero .button.button-flat { + margin: 0; } + +.hero h1.title { + color: #fff; + font-size: 23px; + margin: 0; + text-align: left; + padding-left: 80px; + line-height: 59px; } + +.hero + .mid-bar { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + height: initial; + opacity: 1; + filter: alpha(opacity=100); } + +.hero > * { + -webkit-transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: opacity 2.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 1; + filter: alpha(opacity=100); } + +/* Item +==================================*/ +.item { + font-size: 14px; + width: 100%; } + +.item-icon-left .icon { + left: 16px; } + +.item-icon-right .icon { + right: 16px; } + +/* +.list .item.item-icon-right { + padding-right: 60px; +} +*/ +.item-thumbnail-left > img:first-child, .item-thumbnail-left .item-image, .item-thumbnail-left .item-content > img:first-child, .item-thumbnail-left .item-content .item-image { + border-radius: 50%; } + +.tab-item.activated { + height: calc(100% + 3px); + /* Stretch */ } + +/* List +==================================*/ +.content + .list { + padding-top: 0; } + +.list .item { + border: none; + /* + padding-left: 16px; + padding-right: 16px; + */ + min-height: 48px; + text-align: left; } + +.list .item.tabs { + padding: initial; } + +.list .item.item-bg-image { + max-height: 150px; + min-height: 150px; } + +.list .item.item-bg-image > img { + height: 100%; + left: 0; + max-width: initial; + opacity: 0.65; + filter: alpha(opacity=65); + position: absolute; + top: 0; + width: 100%; + z-index: 0; } + +.list a.item { + opacity: 1; + filter: alpha(opacity=100); } + +.list .item.item-bg-image h1, .list .item.item-bg-image h2, .list .item.item-bg-image h3, .list .item.item-bg-image h4, .list .item.item-bg-image h5, .list .item.item-bg-image h6 { + color: #fff; + font-weight: bold; + position: relative; + text-shadow: 0 0 3px rgba(0, 0, 0, 0.95); + z-index: 1; } + +.list .item.item-bg-image h2 { + font-size: 24px; } + +.list .item.item-bg-image h2 { + font-size: 24px; } + +.list .item.item-bg-image p { + color: white; + font-size: 17px; + position: relative; + text-shadow: 0 0 4px rgba(0, 0, 0, 0.95); + z-index: 1; } + +.item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content { + min-height: 80px; } + +/* List: Thumbnails +==================================*/ +.item-thumbnail-left, .card > .item.item-thumbnail-left, .item-thumbnail-left .item-content { + padding-left: 106px; } + +.item-thumbnail-right, .card > .item.item-thumbnail-right, .item-thumbnail-right .item-content { + padding-right: 106px; } + +/* List: Avatar +==================================*/ +.item-avatar > img:first-child, .item-avatar .item-image, .item-avatar .item-content > img:first-child, .item-avatar .item-content .item-image, .item-avatar-left > img:first-child, .item-avatar-left .item-image, .item-avatar-left .item-content > img:first-child, .item-avatar-left .item-content .item-image { + border-radius: 50%; + left: 16px; + max-height: 40px; + max-width: 40px; } + +/* +.item-avatar, .list .item-avatar { + padding-left: 100px; +} +*/ +.avatar, .item-avatar .avatar { + background-position: center; + background-size: cover; + border-radius: 50%; + display: inline-block; + height: 56px; + left: 16px; + position: absolute; + width: 56px; } + +/* List: Gallery +==================================*/ +.list.half { + display: inline-block; + float: left; + margin: 0; + padding: 0; + width: 50%; } + +.list.half:first-child { + padding: 16px 8px 16px 16px; } + +.list.half:last-child { + padding: 16px 16px 16px 8px; } + +.list.half:first-child .card.card-gallery { + margin-left: 0; + margin-right: 0; } + +.list.half:last-child .card.card-gallery { + margin-left: 0; + margin-right: 0; } + +.list.condensed-space > .card, .list.condensed-space > .item { + margin: 0px 0px 2px; } + +.list .card.card-gallery { + display: block; + float: left; + margin: 0 0 0 13px; + padding: 0; + width: auto; } + +.list.half .item { + width: 100%; } + +.list.half .item.card { + margin-bottom: 16px; } + +.list .card.card-gallery.item h2 { + padding: 12px; } + +.list .item.item-gallery img { + width: 100%; } + +.item.item-divider { + border-top: solid 1px rgba(0, 0, 0, 0.12); + font-size: 14px; + font-weight: bold; + height: 48px; + line-height: 48px; + color: rgba(0, 0, 0, 0.54); } + .item.item-divider:first-child { + border: none; } + +.item-avatar, .item-avatar .item-content, .item-avatar-left, .item-avatar-left .item-content, .card > .item-avatar { + padding-left: 72px; } + +.item.active, .item.activated, .item-complex.active .item-content, .item-complex.activated .item-content, .item .item-content.active, .item .item-content.activated { + background-color: transparent; } + +.list-inset { + margin: 20px 30px; + border-left: solid 1px #ccc; + border-radius: 0; + background-color: #fff; } + +.list .item.item-floating-label, +.item-floating-label { + border-bottom: solid 1px #ccc; } + +.loader { + position: relative; + margin: 0px auto; + width: 100px; + height: 100px; + zoom: 1.7; } + +.circular { + -webkit-animation: rotate 2s linear infinite; + animation: rotate 2s linear infinite; + height: 100px; + position: relative; + width: 100px; } + +.path { + stroke-dasharray: 1,200; + stroke-dashoffset: 0; + -webkit-animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; + animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite; + stroke-linecap: round; } + +@-webkit-keyframes rotate { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@keyframes rotate { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); } } + +@-webkit-keyframes dash { + 0% { + stroke-dasharray: 1,200; + stroke-dashoffset: 0; } + 50% { + stroke-dasharray: 89,200; + stroke-dashoffset: -35; } + 100% { + stroke-dasharray: 89,200; + stroke-dashoffset: -124; } } + +@keyframes dash { + 0% { + stroke-dasharray: 1,200; + stroke-dashoffset: 0; } + 50% { + stroke-dasharray: 89,200; + stroke-dashoffset: -35; } + 100% { + stroke-dasharray: 89,200; + stroke-dashoffset: -124; } } + +@-webkit-keyframes color { + 100%, 0% { + stroke: #d62d20; } + 40% { + stroke: #0057e7; } + 66% { + stroke: #008744; } + 80%, 90% { + stroke: #ffa700; } } + +@keyframes color { + 100%, 0% { + stroke: #d62d20; } + 40% { + stroke: #0057e7; } + 66% { + stroke: #008744; } + 80%, 90% { + stroke: #ffa700; } } + +/* Layouts: Login +==================================*/ +.login { + background-position: 25% 25%; + background-size: 180% 180%; + height: 100%; + -webkit-transition: all 1.5s ease-in-out; + transition: all 1.5s ease-in-out; } + +.login .item { + margin: 0 12px; + padding-left: 0; + padding-right: 0; + width: initial; } + +.login .button-bar { + bottom: 0; + margin: 28px 12px 0; + width: initial; } + +.login .light-bg { + background-color: #fff; } + +.icon.hero-icon:before { + line-height: 130px; } + +/* Mask +==================================*/ +.hero.has-mask:after, .item.has-mask:after, .card.has-mask:after { + content: ''; + background: -webkit-linear-gradient(top, transparent 0%, rgba(0, 0, 0, 0.6) 100%); + height: 100%; + left: 0; + position: absolute; + top: 0; + z-index: 0; + width: 100%; } + +.hero.has-mask-reverse:after, .item.has-mask-reverse:after, .card.has-mask-reverse:after { + content: ''; + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.6) 0%, transparent 100%); + height: 100%; + left: 0; + position: absolute; + top: 0; + z-index: 0; + width: 100%; } + +/* Menu */ +.menu-bottom { + bottom: 16px; + left: 16px; + right: 16px; + position: absolute; } + +.menu-top { + top: 16px; + left: 16px; + right: 16px; + position: absolute; } + +.menu .avatar { + top: 16px; + left: 16px; + height: 65px; + width: 65px; } + +.menu .bar.bar-header.expanded { + box-shadow: none; + min-height: 150px; + color: #fff; } + +.menu-open .bar.bar-header.expanded { + background-position: 0; + background-size: 100%; } + +.has-expanded-header { + top: 150px !important; } + +.motion { + -webkit-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; } + +.fade { + opacity: 0; + filter: alpha(opacity=0); + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spin-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) !important; + transform: translateZ(0) rotate(360deg) scale(0) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + transform: translateZ(0) rotate(-360deg) scale(0) translate(-120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.spiral-back { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + transform: translateZ(0) rotate(360deg) scale(0) translate(120px) !important; + -webkit-transition: all 0.1s ease-out !important; + transition: all 0.1s ease-out !important; } + +.menu-open .avatar { + opacity: 1; + filter: alpha(opacity=100); + -webkit-transform: translateZ(0) rotate(0) scale(1) !important; + transform: translateZ(0) rotate(0) scale(1) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.spin { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotate(0) scale(0) !important; + transform: translateZ(0) rotate(0) scale(0) !important; + -webkit-transition: all 0.3s ease-out !important; + transition: all 0.3s ease-out !important; } + +.spin.on { + -webkit-transform: translateZ(0) rotate(-360deg) scale(1) !important; + transform: translateZ(0) rotate(-360deg) scale(1) !important; } + +.flap { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + transform: translateZ(0) rotateX(0) scale(0) translate(-120px) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flap.on { + -webkit-transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + transform: translateZ(0) rotateX(-720deg) scale(1) translate(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) scale(3) !important; + transform: translateZ(0) scale(3) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.drop.on { + -webkit-transform: translateZ(0) scale(1) !important; + transform: translateZ(0) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip { + -webkit-backface-visibility: hidden !important; + backface-visibility: hidden !important; + -webkit-transform: translateZ(0) rotateY(0) scale(0) !important; + transform: translateZ(0) rotateY(0) scale(0) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +.flip.on { + -webkit-transform: translateZ(0) rotateY(-720deg) scale(1) !important; + transform: translateZ(0) rotateY(-720deg) scale(1) !important; + -webkit-transition: all 0.5s ease-out !important; + transition: all 0.5s ease-out !important; } + +/* Utilities +==================================*/ +.bold { + font-weight: bold; } + +.static { + position: static; } + +.pull-left { + float: left; } + +.pull-right { + float: right; } + +.double-padding, .ionic-content.double-padding { + padding: 16px; } + +.double-padding-x { + padding-left: 16px; + padding-right: 16px; } + +.double-padding-y { + padding-top: 16px; + padding-bottom: 16px; } + +.outline { + border-style: solid; + border-width: 1px; } + +.border-top { + border-top: solid 1px #ccc; + padding-top: 30px; } + +.no-border { + border: none; } + +.circle { + border-radius: 50%; } + +.no-padding, .list.no-padding, .bar.no-padding, .button-bar.no-padding, .card.no-padding, .button.no-padding, .item.no-padding { + padding: 0; } + +.flat, .flat.tabs, .flat.button, .flat.button.icon, .flat.hero { + box-shadow: none; + -webkit-box-shadow: none; } + +/* Utilities : Padding +==================================*/ +.im-wrapper, .padding { + padding: 16px !important; } + +.padding-bottom { + padding-bottom: 16px !important; } + +.padding-top { + padding-top: 16px !important; } + +.padding-left { + padding-left: 16px !important; } + +.padding-right { + padding-right: 16px !important; } + +.no-padding-bottom { + padding-bottom: 0 !important; } + +.no-padding-top { + padding-top: 0 !important; } + +.no-padding-left { + padding-left: 0 !important; } + +.no-padding-right { + padding-right: 0 !important; } + +/* Utilities : Depth +==================================*/ +.z1 { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); } + +/* Utilities : Color +==================================*/ +.bar.bar-positive.darker { + background-color: #164FAB; } + +/* TODO: Expand to other colors */ +.bar.bar-positive.dark-positive-bg { + background-color: #2C5CAD; } + +/* TODO: Expand to other colors */ +.muted { + color: #C3C3C3; } + +.clear-bg { + background: transparent; } + +/* Motion: Blinds +==================================*/ +.animate-blinds .item, +.animate-blinds .item { + visibility: hidden; } + +.animate-blinds .item, +.animate-blinds .item { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-blinds .item-bg-image > img.background, +.animate-blinds .item-bg-image > img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-blinds .in, +.animate-blinds.done > *, +.animate-blinds .in, +.animate-blinds.done > * { + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.animate-blinds .in, +.animate-blinds.done .item, +.animate-blinds .in, +.animate-blinds.done .item { + visibility: visible; } + +.animate-blinds .item, +.animate-blinds .item { + visibility: hidden; } + +.animate-blinds .item, +.animate-blinds .item { + opacity: 0; + filter: alpha(opacity=0); } + +.animate-blinds .in, +.animate-blinds.done, +.animate-blinds .in, +.animate-blinds.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + opacity: 1; + filter: alpha(opacity=100); } + +.animate-blinds .in, +.animate-blinds.done, +.animate-blinds .in, +.animate-blinds.done { + visibility: visible; } + +.animate-blinds.done .in, +.animate-blinds.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-blinds .has-mask-reverse:after, +.animate-blinds .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-blinds.done .has-mask-reverse:after, +.animate-blinds.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-blinds .out, +.animate-blinds .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Pan In Left +==================================*/ +.animate-pan-in-left, +.animate-pan-in-left { + background-position: 0% 0%; } + +/* Motion: Ripple +==================================*/ +.animate-ripple .done, +.animate-ripple .done { + visibility: hidden; } + +.animate-ripple .done, +.animate-ripple .done { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-ripple .item-bg-image img.background, +.animate-ripple .item-bg-image img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-ripple .in, .animate-ripple.done, +.animate-ripple .in, .animate-ripple.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-ripple .in, .animate-ripple.done, +.animate-ripple .in, .animate-ripple.done { + visibility: visible; } + +.animate-ripple .item { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); + opacity: 0; + filter: alpha(opacity=0); } + +.animate-ripple .item.in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-ripple .done { + visibility: hidden; } + +.animate-ripple .done, +.animate-ripple .done { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +/* Uncomment if you want images to fade in after the card + + .animate-ripple .in .item-bg-image img:last-child, + .animate-ripple .in .item-bg-image img:last-child { + opacity: 0; + } + + .animate-ripple.done .item-bg-image img:last-child, + .animate-ripple.done .item-bg-image img:last-child { + opacity: 1; + -moz-transition: all 1s ease-in-out; + -o-transition: all 1s ease-in-out; + -webkit-transition: all 1s ease-in-out; + transition: all 1s ease-in-out; + } + + .animate-ripple .item-bg-image img:last-child, + .animate-ripple .item-bg-image img:last-child { + box-shadow: none; + -moz-transform: scale3d(1, 1, 1); + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + .animate-ripple .in .item-bg-image img:last-child, + .animate-ripple .in .item-bg-image img:last-child { + opacity: 0; + } + +.animate-ripple.done .item-bg-image img:last-child, +.animate-ripple.done .item-bg-image img:last-child { + opacity: 1; + -moz-transition: all 0.3s ease-in-out; + -o-transition: all 0.3s ease-in-out; + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; +} + +.animate-ripple .in, +.animate-ripple .in { + opacity: 0.6; +} +*/ +.animate-ripple .in, .animate-ripple.done, .animate-ripple .in, .animate-ripple.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-ripple .in, .animate-ripple.done, .animate-ripple .in, .animate-ripple.done { + visibility: visible; } + +.animate-ripple.done .in, .animate-ripple.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-ripple .has-mask-reverse:after, .animate-ripple .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-ripple.done .has-mask-reverse:after, .animate-ripple.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-ripple .out, .animate-ripple .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Slide / Fade In +==================================*/ +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + visibility: hidden; } + +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-fade-slide-in .item-bg-image img.background, +.animate-fade-slide-in .item-bg-image img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item { + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done .item { + visibility: visible; } + +.list .item.item-bg-image, +.list .item.item-bg-image { + max-height: 150px; } + +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + visibility: hidden; } + +.animate-fade-slide-in .item, +.animate-fade-slide-in .item { + -ms-transform: translate3d(-250px, 250px, 0); + -webkit-transform: translate3d(-250px, 250px, 0); + transform: translate3d(-250px, 250px, 0); + -webkit-transition: -webkit-transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 0; + filter: alpha(opacity=0); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.5s ease-in-out; + transition: all 0.5s ease-in-out; + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in .in, +.animate-fade-slide-in.done, +.animate-fade-slide-in .in, +.animate-fade-slide-in.done { + visibility: visible; } + +.animate-fade-slide-in.done .in, +.animate-fade-slide-in.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in .has-mask-reverse:after, +.animate-fade-slide-in .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-fade-slide-in.done .has-mask-reverse:after, +.animate-fade-slide-in.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in .out, +.animate-fade-slide-in .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Slide In Right +==================================*/ +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + visibility: hidden; } + +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + -ms-transform: scale3d(0.8, 0, 1); + -webkit-transform: scale3d(0.8, 0, 1); + transform: scale3d(0.8, 0, 1); + -webkit-transition: -webkit-transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.3s cubic-bezier(0.55, 0, 0.1, 1); } + +.animate-fade-slide-in-right .item-bg-image > img.background, +.animate-fade-slide-in-right .item-bg-image > img.background { + box-shadow: none; + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done > *, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done > * { + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done .item, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done .item { + visibility: visible; } + +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + visibility: hidden; } + +.animate-fade-slide-in-right .item, +.animate-fade-slide-in-right .item { + -ms-transform: translate3d(250px, 250px, 0); + -webkit-transform: translate3d(250px, 250px, 0); + transform: translate3d(250px, 250px, 0); + -webkit-transition: -webkit-transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + transition: transform 0.5s cubic-bezier(0.55, 0, 0.1, 1); + opacity: 0; + filter: alpha(opacity=0); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done { + -ms-transform: scale3d(1, 1, 1); + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done, +.animate-fade-slide-in-right .in, +.animate-fade-slide-in-right.done { + visibility: visible; } + +.animate-fade-slide-in-right.done .in, +.animate-fade-slide-in-right.done .in { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in-right .has-mask-reverse:after, +.animate-fade-slide-in-right .has-mask-reverse:after { + opacity: 0; + filter: alpha(opacity=0); + -webkit-transition: all 0.3s ease-in-out; + transition: all 0.3s ease-in-out; } + +.animate-fade-slide-in-right.done .has-mask-reverse:after, +.animate-fade-slide-in-right.done .has-mask-reverse:after { + opacity: 1; + filter: alpha(opacity=100); } + +.animate-fade-slide-in-right .out, +.animate-fade-slide-in-right .out { + -ms-transform: scale3d(0, 0, 1); + -webkit-transform: scale3d(0, 0, 1); + transform: scale3d(0, 0, 1); } + +/* Motion: Slide Up +==================================*/ +.slide-up, +.slide-up, +.hero.slide-up { + height: 100%; + overflow: hidden; + text-align: center; } + +.slide-up { + -webkit-transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + transition: all 1s cubic-bezier(0.55, 0, 0.1, 1); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.slide-up *, +.slide-up *, +.hero.slide-up * { + opacity: 0; + filter: alpha(opacity=0); } + +.hero.slide-up + .mid-bar, +.slide-up + .mid-bar, +.slide-up + .mid-bar { + height: 100%; + opacity: 0.7; + filter: alpha(opacity=70); + -webkit-transform: translate3d(100%, -240px, 0); + transform: translate3d(100%, -240px, 0); } + +/*! + * Waves v0.5.4 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Forked by Zach Fitzgerald and other contributors for Ionic Material + * + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + * + */ +.ink, .button-fab, .button-flat, .button-raised, .button-clear, .popup .button { + position: relative; + cursor: pointer; + /*display: inline-block;*/ + overflow: hidden; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent; + -webkit-transition: all 0.3s ease-out; + -moz-transition: all 0.3s ease-out; + -o-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; } + +.ink-ripple { + position: absolute; + border-radius: 50%; + width: 100px; + height: 100px; + margin-top: -50px; + margin-left: -50px; + opacity: 0; + background-color: rgba(255, 255, 255, 0.4); + -webkit-transition: all 0.5s ease-out; + -moz-transition: all 0.5s ease-out; + -o-transition: all 0.5s ease-out; + transition: all 0.5s ease-out; + -webkit-transition-property: -webkit-transform, opacity; + -moz-transition-property: -moz-transform, opacity; + -o-transition-property: -o-transform, opacity; + transition-property: transform, opacity; + -webkit-transform: scale(0); + -moz-transform: scale(0); + -ms-transform: scale(0); + -o-transform: scale(0); + transform: scale(0); + pointer-events: none; } + +.ink-notransition { + -webkit-transition: none !important; + -moz-transition: none !important; + -o-transition: none !important; + transition: none !important; } + +.button-fab, +.button-flat, +.button-clear, +.button-raised, +.ink-button, +.ink-circle { + -webkit-transform: translateZ(0); + -moz-transform: translateZ(0); + -ms-transform: translateZ(0); + -o-transform: translateZ(0); + transform: translateZ(0); } + +.button-fab.activated, +.button-flat.activated, +.button-raised.activated, +.button-clear.activated, +.ink-button.activated, +.ink.activated, +.ink-circle.activated, +.popup .button.activated, +.button-fab:active, +.button-flat:active, +.button-raised:active, +.button-clear:active, +.ink-button:active, +.ink:active, +.ink-circle:active, +.popup .button:active { + -webkit-mask-image: -webkit-radial-gradient(circle, #ffffff 100%, #000000 100%); } + +.ink-button, +.ink-button:visited, +.ink-button:link, +.button-fab, +.button-fab:visited, +.button-fab:link, +.button-flat, +.button-flat:visited, +.button-flat:link, +.button-raised, +.button-raised:visited, +.button-raised:link, +.button-clear, +.button-clear:visited, +.button-clear:link, +.ink-button-input { + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + border: none; + outline: none; + /* color: inherit; */ + /* background-color: rgba(0, 0, 0, 0); */ + font-size: 14px; + text-align: center; + text-decoration: none; + z-index: 1; } + +.ink-button { + padding: 10px 15px; + border-radius: 2px; } + +.ink-button-input { + margin: 0; + padding: 10px 15px; } + +.ink-input-wrapper { + border-radius: 2px; + vertical-align: bottom; } + +.ink-input-wrapper.ink-button { + padding: 0; } + +.ink-input-wrapper .ink-button-input { + position: relative; + top: 0; + left: 0; + z-index: 1; } + +.ink-circle { + text-align: center; + width: 2.5em; + height: 2.5em; + line-height: 2.5em; + border-radius: 50%; } + +.ink-float { + -webkit-mask-image: none; + -webkit-box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); + box-shadow: 0px 1px 1.5px 1px rgba(0, 0, 0, 0.12); } + +.ink-float:active { + -webkit-box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); + box-shadow: 0px 8px 20px 1px rgba(0, 0, 0, 0.3); } + +.ink-block { + display: block; } + +.ink-ripple { + z-index: 0; + /* Firefox Bug: link not triggered unless -1 z-index */ } + +/* Handled elsewhere +.button-fab,.button-raised,.button-flat,.ink-circle,.list a.item { + -webkit-mask-image: none; +} +*/ +.button-clear .ink-ripple, +*[class$="-clear"] > .ink-ripple, +*[class$="-light"] > .ink-ripple, +*[class$="-stable"] > .ink-ripple, +*[class$="-100"] > .ink-ripple, +.list .ink-ripple, +.ink-dark .ink-ripple { + background-color: rgba(0, 0, 0, 0.2); } + +.tab-item { + position: relative; + /* for Ink */ } + +/* Ionic Overrides +==================================*/ +* { + font-family: "RobotoDraft","Roboto","Helvetica Neue", "Segoe UI", sans-serif; } + +.rounded { + border-radius: 4px; } + +a { + cursor: pointer; } + +.has-header.expanded { + /* Expanded modifier */ + top: 76px; } + +/* Bar Overrides +==================================*/ +.bar { + border-bottom: none; + padding: 0; } + +.bar .button { + min-height: 44px; + min-width: 44px; + max-width: 48px; + margin-bottom: 0; + max-height: 44px; + width: 48px; } + +.bar .title + .buttons.buttons-right { + right: 0; + top: 0; } + +/* Title Overrides +==================================*/ +.title-left, +.title.title-left { + left: 48px; } + +.title-right, +.title.title-right { + left: 48px; } + +/* Background Colors +==================================*/ +.positive-bg, +.button-positive, +.bar .button-positive, +.header-positive, +.button-bar-positive, +.bar-positive, +.positive-border, +.positive-bg:hover, +.bar .button-positive:hover, +.button-positive:hover, +.header-positive:hover, +.button-bar-positive:hover, +.bar-positive:hover, +.positive-border:hover, +.positive-bg:active, +.bar .button-positive:active, +.button-positive:active, +.header-positive:active, +.button-bar-positive:active, +.bar-positive:active, +.positive-border:active, +.positive-bg.activated, +.bar .button-positive.activated, +.button-positive.activated, +.header-positive.activated, +.button-bar-positive.activated, +.bar-positive.activated, +.positive-border.activated { + background-color: #3F51B5; + color: #fff; } + +.positive-900-bg, +.button-positive-900, +.bar .button-positive-900, +.header-positive-900, +.button-bar-positive-900, +.bar-positive-900, +.positive-900-border, +.positive-900-bg:hover, +.button-positive-900:hover, +.bar .button-positive-900:hover, +.header-positive-900:hover, +.button-bar-positive-900:hover, +.bar-positive-900:hover, +.positive-900-border:hover, +.positive-900-bg:active, +.bar .button-positive-900:active, +.button-positive-900:active, +.header-positive-900:active, +.button-bar-positive-900:active, +.bar-positive-900:active, +.positive-900-border:active, +.positive-900-bg.activated, +.button-positive-900.activated, +.bar .button-positive-900.activated, +.header-positive-900.activated, +.button-bar-positive-900.activated, +.bar-positive-900.activated, +.positive-900-border.activated { + background-color: #1A237E; + color: #fff; } + +.positive-100-bg, +.button-positive-100, +.bar .button-positive-100, +.header-positive-100, +.button-bar-positive-100, +.bar-positive-100, +.positive-100-border, +.positive-100-bg:hover, +.button-positive-100:hover, +.bar .button-positive-100:hover, +.header-positive-100:hover, +.button-bar-positive-100:hover, +.bar-positive-100:hover, +.positive-100-border:hover, +.positive-100-bg:active, +.button-positive-100:active, +.bar .button-positive-100:active, +.header-positive-100:active, +.button-bar-positive-100:active, +.bar-positive-100:active, +.positive-100-border:active, +.positive-100-bg.activated, +.button-positive-100.activated, +.bar .button-positive-100.activated, +.header-positive-100.activated, +.button-bar-positive-100.activated, +.bar-positive-100.activated, +.positive-100-border.activated { + background-color: #C5CAE9; + color: #fff; } + +.calm-bg, +.button-calm, +.bar .button-calm, +.header-calm, +.button-bar-calm, +.bar-calm, +.calm-border, +.calm-bg:hover, +.button-calm:hover, +.bar .button-calm:hover, +.header-calm:hover, +.button-bar-calm:hover, +.bar-calm:hover, +.calm-border:hover, +.calm-bg:active, +.button-calm:active, +.bar .button-calm:active, +.header-calm:active, +.button-bar-calm:active, +.bar-calm:active, +.calm-border:active, +.calm-bg.activated, +.button-calm.activated, +.bar .button-calm.activated, +.header-calm.activated, +.button-bar-calm.activated, +.bar-calm.activated, +.calm-border.activated { + background-color: #2196F3; + color: #fff; } + +.calm-900-bg, +.button-calm-900, +.bar .button-calm-900, +.header-calm-900, +.button-bar-calm-900, +.bar-calm-900, +.calm-900-border, +.calm-900-bg:hover, +.button-calm-900:hover, +.bar .button-calm-900:hover, +.header-calm-900:hover, +.button-bar-calm-900:hover, +.bar-calm-900:hover, +.calm-900-border:hover, +.calm-900-bg:active, +.button-calm-900:active, +.bar .button-calm-900:active, +.header-calm-900:active, +.button-bar-calm-900:active, +.bar-calm-900:active, +.calm-900-border:active, +.calm-900-bg.activated, +.button-calm-900.activated, +.bar .button-calm-900.activated, +.header-calm-900.activated, +.button-bar-calm-900.activated, +.bar-calm-900.activated, +.calm-900-border.activated { + background-color: #0D47A1; + color: #fff; } + +.calm-100-bg, +.button-calm-100, +.bar .button-calm-100, +.header-calm-100, +.button-bar-calm-100, +.bar-calm-100, +.calm-100-border, +.calm-100-bg:hover, +.button-calm-100:hover, +.bar .button-calm-100:hover, +.header-calm-100:hover, +.button-bar-calm-100:hover, +.bar-calm-100:hover, +.calm-100-border:hover, +.calm-100-bg:active, +.button-calm-100:active, +.bar .button-calm-100:active, +.header-calm-100:active, +.button-bar-calm-100:active, +.bar-calm-100:active, +.calm-100-border:active, +.calm-100-bg.activated, +.button-calm-100.activated, +.bar .button-calm-100.activated, +.header-calm-100.activated, +.button-bar-calm-100.activated, +.bar-calm-100.activated, +.calm-100-border.activated { + background-color: #BBDEFB; + color: #fff; } + +.royal-bg, +.button-royal, +.bar .button-royal, +.header-royal, +.button-bar-royal, +.bar-royal, +.royal-border, +.royal-bg:hover, +.button-royal:hover, +.bar .button-royal:hover, +.header-royal:hover, +.button-bar-royal:hover, +.bar-royal:hover, +.royal-border:hover, +.royal-bg:active, +.button-royal:active, +.bar .button-royal:active, +.header-royal:active, +.button-bar-royal:active, +.bar-royal:active, +.royal-border:active, +.royal-bg.activated, +.button-royal.activated, +.bar .button-royal.activated, +.header-royal.activated, +.button-bar-royal.activated, +.bar-royal.activated, +.royal-border.activated { + background-color: #673AB7; + color: #fff; } + +.royal-900-bg, +.button-royal-900, +.bar .button-royal-900, +.header-royal-900, +.button-bar-royal-900, +.bar-royal-900, +.royal-900-border, +.royal-900-bg:hover, +.button-royal-900:hover, +.bar .button-royal-900:hover, +.header-royal-900:hover, +.button-bar-royal-900:hover, +.bar-royal-900:hover, +.royal-900-border:hover, +.royal-900-bg:active, +.button-royal-900:active, +.bar .button-royal-900:active, +.header-royal-900:active, +.button-bar-royal-900:active, +.bar-royal-900:active, +.royal-900-border:active, +.royal-900-bg.activated, +.button-royal-900.activated, +.bar .button-royal-900.activated, +.header-royal-900.activated, +.button-bar-royal-900.activated, +.bar-royal-900.activated, +.royal-900-border.activated { + background-color: #311B92; + color: #fff; } + +.royal-100-bg, +.button-royal-100, +.bar .button-royal-100, +.header-royal-100, +.button-bar-royal-100, +.bar-royal-100, +.royal-100-border, +.royal-100-bg:hover, +.button-royal-100:hover, +.bar .button-royal-100:hover, +.header-royal-100:hover, +.button-bar-royal-100:hover, +.bar-royal-100:hover, +.royal-100-border:hover, +.royal-100-bg:active, +.button-royal-100:active, +.bar .button-royal-100:active, +.header-royal-100:active, +.button-bar-royal-100:active, +.bar-royal-100:active, +.royal-100-border:active, +.royal-100-bg.activated, +.button-royal-100.activated, +.bar .button-royal-100.activated, +.header-royal-100.activated, +.button-bar-royal-100.activated, +.bar-royal-100.activated, +.royal-100-border.activated { + background-color: #D1C4E9; + color: #fff; } + +.balanced-bg, +.button-balanced, +.bar .button-balanced, +.header-balanced, +.button-bar-balanced, +.bar-balanced, +.balanced-border, +.balanced-bg:hover, +.button-balanced:hover, +.bar .button-balanced:hover, +.header-balanced:hover, +.button-bar-balanced:hover, +.bar-balanced:hover, +.balanced-border:hover, +.balanced-bg:active, +.button-balanced:active, +.bar .button-balanced:active, +.header-balanced:active, +.button-bar-balanced:active, +.bar-balanced:active, +.balanced-border:active, +.balanced-bg.activated, +.button-balanced.activated, +.bar .button-balanced.activated, +.header-balanced.activated, +.button-bar-balanced.activated, +.bar-balanced.activated, +.balanced-border.activated { + background-color: #4CAF50; + color: #fff; } + +.balanced-900-bg, +.button-balanced-900, +.bar .button-balanced-900, +.header-balanced-900, +.button-bar-balanced-900, +.bar-balanced-900, +.balanced-900-border, +.balanced-900-bg:hover, +.button-balanced-900:hover, +.bar .button-balanced-900:hover, +.header-balanced-900:hover, +.button-bar-balanced-900:hover, +.bar-balanced-900:hover, +.balanced-900-border:hover, +.balanced-900-bg:active, +.button-balanced-900:active, +.bar .button-balanced-900:active, +.header-balanced-900:active, +.button-bar-balanced-900:active, +.bar-balanced-900:active, +.balanced-900-border:active, +.balanced-900-bg.activated, +.button-balanced-900.activated, +.bar .button-balanced-900.activated, +.header-balanced-900.activated, +.button-bar-balanced-900.activated, +.bar-balanced-900.activated, +.balanced-900-border.activated { + background-color: #1B5E20; + color: #fff; } + +.balanced-100-bg, +.button-balanced-100, +.bar .button-balanced-100, +.header-balanced-100, +.button-bar-balanced-100, +.bar-balanced-100, +.balanced-100-border, +.balanced-100-bg:hover, +.button-balanced-100:hover, +.bar .balanced-100-bg:hover, +.header-balanced-100:hover, +.button-bar-balanced-100:hover, +.bar-balanced-100:hover, +.balanced-100-border:hover, +.balanced-100-bg:active, +.button-balanced-100:active, +.bar .button-balanced-100:active, +.header-balanced-100:active, +.button-bar-balanced-100:active, +.bar-balanced-100:active, +.balanced-100-border:active, +.balanced-100-bg.activated, +.button-balanced-100.activated, +.bar .button-balanced-100.activated, +.header-balanced-100.activated, +.button-bar-balanced-100.activated, +.bar-balanced-100.activated, +.balanced-100-border.activated { + background-color: #C8E6C9; + color: #fff; } + +.energized-bg, +.button-energized, +.bar .button-energized, +.header-energized, +.button-bar-energized, +.bar-energized, +.energized-border, +.energized-bg:hover, +.button-energized:hover, +.bar .button-energized:hover, +.header-energized:hover, +.button-bar-energized:hover, +.bar-energized:hover, +.energized-border:hover, +.energized-bg:active, +.button-energized:active, +.bar .button-energized:active, +.header-energized:active, +.button-bar-energized:active, +.bar-energized:active, +.energized-border:active, +.energized-bg.activated, +.button-energized.activated, +.bar .button-energized.activated, +.header-energized.activated, +.button-bar-energized.activated, +.bar-energized.activated, +.energized-border.activated { + background-color: #FF9800; + color: #fff; } + +.energized-900-bg, +.button-energized-900, +.bar .button-energized-900, +.header-energized-900, +.button-bar-energized-900, +.bar-energized-900, +.energized-900-border, +.energized-900-bg:hover, +.button-energized-900:hover, +.bar .button-energized-900:hover, +.header-energized-900:hover, +.button-bar-energized-900:hover, +.bar-energized-900:hover, +.energized-900-border:hover, +.energized-900-bg:active, +.button-energized-900:active, +.bar .button-energized-900:active, +.header-energized-900:active, +.button-bar-energized-900:active, +.bar-energized-900:active, +.energized-900-border:active, +.energized-900-bg.activated, +.button-energized-900.activated, +.bar .button-energized-900.activated, +.header-energized-900.activated, +.button-bar-energized-900.activated, +.bar-energized-900.activated, +.energized-900-border.activated { + background-color: #E65100; + color: #fff; } + +.energized-100-bg, +.button-energized-100, +.bar .button-energized-100, +.header-energized-100, +.button-bar-energized-100, +.bar-energized-100, +.energized-100-border, +.energized-100-bg:hover, +.button-energized-100:hover, +.bar .button-energized-100:hover, +.header-energized-100:hover, +.button-bar-energized-100:hover, +.bar-energized-100:hover, +.energized-100-border:hover, +.energized-100-bg:active, +.button-energized-100:active, +.bar .button-energized-100:active, +.header-energized-100:active, +.button-bar-energized-100:active, +.bar-energized-100:active, +.energized-100-border:active, +.energized-100-bg.activated, +.button-energized-100.activated, +.bar .button-energized-100.activated, +.header-energized-100.activated, +.button-bar-energized-100.activated, +.bar-energized-100.activated, +.energized-100-border.activated { + background-color: #FFE0B2; } + +.assertive-bg, +.button-assertive, +.bar .button-assertive, +.header-assertive, +.button-bar-assertive, +.bar-assertive, +.assertive-border, +.assertive-bg:hover, +.button-assertive:hover, +.bar .button-assertive:hover, +.header-assertive:hover, +.button-bar-assertive:hover, +.bar-assertive:hover, +.assertive-border:hover, +.assertive-bg:active, +.button-assertive:active, +.bar .button-assertive:active, +.header-assertive:active, +.button-bar-assertive:active, +.bar-assertive:active, +.assertive-border:active, +.assertive-bg.activated, +.button-assertive.activated, +.bar .button-assertive.activated, +.header-assertive.activated, +.button-bar-assertive.activated, +.bar-assertive.activated, +.assertive-border.activated { + background-color: #F44336; + color: #fff; } + +.assertive-900-bg, +.button-assertive-900, +.bar .button-assertive-900, +.header-assertive-900, +.button-bar-assertive-900, +.bar-assertive-900, +.assertive-900-border, +.assertive-900-bg:hover, +.button-assertive-900:hover, +.bar .button-assertive-900:hover, +.header-assertive-900:hover, +.button-bar-assertive-900:hover, +.bar-assertive-900:hover, +.assertive-900-border:hover, +.assertive-900-bg:active, +.button-assertive-900:active, +.bar .button-assertive-900:active, +.header-assertive-900:active, +.button-bar-assertive-900:active, +.bar-assertive-900:active, +.assertive-900-border:active, +.assertive-900-bg.activated, +.button-assertive-900.activated, +.bar .button-assertive-900.activated, +.header-assertive-900.activated, +.button-bar-assertive-900.activated, +.bar-assertive-900.activated, +.assertive-900-border.activated { + background-color: #B71C1C; + color: #fff; } + +.assertive-100-bg, +.button-assertive-100, +.bar .button-assertive-100, +.header-assertive-100, +.button-bar-assertive-100, +.bar-assertive-100, +.assertive-100-border, +.assertive-100-bg:hover, +.button-assertive-100:hover, +.bar .button-assertive-100:hover, +.header-assertive-100:hover, +.button-bar-assertive-100:hover, +.bar-assertive-100:hover, +.assertive-100-border:hover, +.assertive-100-bg:active, +.button-assertive-100:active, +.bar .button-assertive-100:active, +.header-assertive-100:active, +.button-bar-assertive-100:active, +.bar-assertive-100:active, +.assertive-100-border:active, +.assertive-100-bg.activated, +.bar .button-assertive-100.activated, +.button-assertive-100.activated, +.header-assertive-100.activated, +.button-bar-assertive-100.activated, +.bar-assertive-100.activated, +.assertive-100-border.activated { + background-color: #FFCDD2; + color: #fff; } + +.stable-bg, +.button-stable, +.bar .button-stable, +.header-stable, +.button-bar-stable, +.bar-stable, +.stable-border, +.stable-bg:hover, +.button-stable:hover, +.bar .button-stable:hover, +.header-stable:hover, +.button-bar-stable:hover, +.bar-stable:hover, +.stable-border:hover, +.stable-bg:active, +.button-stable:active, +.bar .button-stable:active, +.header-stable:active, +.button-bar-stable:active, +.bar-stable:active, +.stable-border:active, +.stable-bg.activated, +.button-stable.activated, +.bar .button-stable.activated, +.header-stable.activated, +.button-bar-stable.activated, +.bar-stable.activated, +.stable-border.activated { + background-color: #E0E0E0; + color: #fff; } + +/* Text Colors +==================================*/ +.positive, +.positive *, +*.positive, +.positive:hover, +.positive:hover *, +*.positive:hover, +.positive:active, +.positive:active *, +*.positive:active { + color: #3F51B5; } + +.positive-900, +.positive-900 *, +*.positive-900, +.positive-900:hover, +.positive-900:hover *, +*.positive-900:hover, +.positive-900:active, +.positive-900:active *, +*.positive-900:active { + color: #3F51B5; } + +.positive-100, +.positive-100 *, +*.positive-100, +.positive-100:hover, +.positive-100:hover *, +*.positive-100:hover, +.positive-100:active, +.positive-100:active *, +*.positive-100:active { + color: #C5CAE9; } + +.calm-100, +.calm-100 *, +*.calm-100, +.calm-100:hover, +.calm-100:hover *, +*.calm-100:hover, +.calm-100:active, +.calm-100:active *, +*.calm-100:active { + color: #2196F3; } + +.calm-900, +.calm-900 *, +*.calm-900, +.calm-900:hover, +.calm-900:hover *, +*.calm-900:hover, +.calm-900:active, +.calm-900:active *, +*.calm-900:active { + color: #0D47A1; } + +.calm-100, +.calm-100 *, +*.calm-100, +.calm-100:hover, +.calm-100:hover *, +*.calm-100:hover, +.calm-100:active, +.calm-100:active *, +*.calm-100:active { + color: #BBDEFB; } + +.royal, +.royal *, +*.royal, +.royal:hover, +.royal:hover *, +*.royal:hover, +.royal:active, +.royal:active *, +*.royal:active { + color: #673AB7; } + +.royal-900, +.royal-900 *, +*.royal-900, +.royal-900:hover, +.royal-900:hover *, +*.royal-900:hover, +.royal-900:active, +.royal-900:active *, +*.royal-900:active { + color: #311B92; } + +.royal-100, +.royal-100 *, +*.royal-100, +.royal-100:hover, +.royal-100:hover *, +*.royal-100:hover, +.royal-100:active, +.royal-100:active *, +*.royal-100:active { + color: #D1C4E9; } + +.balanced, +.balanced *, +*.balanced, +.balanced:hover, +.balanced:hover *, +*.balanced:hover, +.balanced:active, +.balanced:active *, +*.balanced:active { + color: #4CAF50; } + +.balanced-900, +.balanced-900 *, +*.balanced-900, +.balanced-900:hover, +.balanced-900:hover *, +*.balanced-900:hover, +.balanced-900:active, +.balanced-900:active *, +*.balanced-900:active { + color: #1B5E20; } + +.balanced-100, +.balanced-100 *, +*.balanced-100, +.balanced-100:hover, +.balanced-100:hover *, +*.balanced-100:hover, +.balanced-100:active, +.balanced-100:active *, +*.balanced-100:active { + color: #C8E6C9; } + +.energized, +.energized *, +*.energized, +.energized:hover, +.energized:hover *, +*.energized:hover, +.energized:active, +.energized:active *, +*.energized:active { + color: #FF9800; } + +.energized-900, +.energized-900 *, +*.energized-900, +.energized-900:hover, +.energized-900:hover *, +*.energized-900:hover, +.energized-900:active, +.energized-900:active *, +*.energized-900:active { + color: #E65100; } + +.energized-100, +.energized-100 *, +*.energized-100, +.energized-100:hover, +.energized-100:hover *, +*.energized-100:hover, +.energized-100:active, +.energized-100:active *, +*.energized-100:active { + color: #FFE0B2; } + +.assertive, +.assertive *, +*.assertive, +.assertive:hover, +.assertive:hover *, +*.assertive:hover, +.assertive:active, +.assertive:active *, +*.assertive:active { + color: #F44336; } + +.assertive-900, +.assertive-900 *, +*.assertive-900, +.assertive-900:hover, +.assertive-900:hover *, +*.assertive-900:hover, +.assertive-900:active, +.assertive-900:active *, +*.assertive-900:active { + color: #B71C1C; } + +.assertive-100, +.assertive-100 *, +*.assertive-100, +.assertive-100:hover, +.assertive-100:hover *, +*.assertive-100:hover, +.assertive-100:active, +.assertive-100:active *, +*.assertive-100:active { + color: #FFCDD2; } + +.stable, +.stable *, +*.stable, +.stable:hover, +.stable:hover *, +*.stable:hover, +.stable:active, +.stable:active *, +*.stable:active { + color: #E0E0E0; } + +.light, +.light *, +*.light, +.light:hover, +.light:hover *, +*.light:hover, +.light:active, +.light:active *, +*.light:active { + color: #fff; } + +.dark, +.dark *, +*.dark, +.dark:hover, +.dark:hover *, +*.dark:hover, +.dark:active, +.dark:active *, +*.dark:active { + color: #444; } + +.light-border { + border-color: #ddd; } + +.navbar-default .navbar-nav > li > a { + margin: 0; + padding-right: 26px; + padding-left: 26px; + border-top: 3px solid transparent; + color: #BFD5C9; + opacity: 1; } + +/* Mid-Bar +==================================*/ +.mid-bar { + padding: 16px; } + +.mid-bar h1, +.mid-bar h2, +.mid-bar h3, +.mid-bar h4, +.mid-bar h5, +.mid-bar h6 { + color: #fff; + margin-bottom: 5px; } + +.mid-bar p { + color: rgba(255, 255, 255, 0.5); + margin-bottom: 0; } + +/* Item +==================================*/ +.item-avatar, +.item-avatar .item-content, +.item-avatar-left, +.item-avatar-left .item-content, +.card > .item-avatar { + padding-left: 95px; } + +.item, +.item-complex .item-content, +.item-radio .item-content { + background-color: transparent; } + +.dark-bg h2, +.item.dark-bg h2 { + color: #fff; } + +.tabs-striped .tabs { + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.26); } + +.bar .button.button-clear { + color: #fff; } + +.bar .button.button-icon .icon:before, +.bar .button.button-icon.icon-left:before, +.bar .button.button-icon.icon-right:before, +.bar .button.button-icon:before { + vertical-align: top; + font-size: 24px; } + +.menu { + background-color: transparent; } + +.button-icon.button.active, +.button-icon.button.activated { + opacity: initial; } + +/* Popover +==================================*/ +.popover { + opacity: 0; + position: absolute; + right: 8px; + transform: translate(50%, -50%) scale(0, 0); + transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; + top: 8px; } + +.popover.ng-enter { + opacity: 1; + transform: translate(0, -14px) scale(1, 1); + transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; } + +.popover.ng-leave { + opacity: 0; + transform: translate(50%, -50%) scale(0, 0); + transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; } + +/* Button +==================================*/ +.button { + overflow: hidden !important; } diff --git a/www/lib/ionic/css/ionic.material.min.css b/www/lib/ionic/css/ionic.material.min.css new file mode 100644 index 0000000000000000000000000000000000000000..7b6eb5cb98a0b521f2bf4971c3f88e64f707e441 --- /dev/null +++ b/www/lib/ionic/css/ionic.material.min.css @@ -0,0 +1,12 @@ +.item-md-label{display:block;background:0 0;box-shadow:none;margin-left:12px;margin-right:12px;padding:30px 0 0}.item-md-label .input-label{position:absolute;z-index:2;-webkit-transform:translate3d(0,-30px,0) scale(1);transform:translate3d(0,-30px,0) scale(1);-webkit-transition:all .2s ease;transition:all .2s ease;color:#fff;opacity:.5;filter:alpha(opacity=50);-webkit-transform-origin:0;-ms-transform-origin:0;transform-origin:0}.item-md-label input{background-color:rgba(0,0,0,.6);bottom:0;color:#fff;letter-spacing:.25rem;padding:20px 10px;position:relative;z-index:1}.item-md-label .highlight{position:absolute;bottom:0;height:2px;left:0;width:100%;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);-webkit-transition:all .15s ease;transition:all .15s ease;z-index:1}.item-md-label .highlight-light{background:#fff}.item-md-label .highlight-stable{background:#f8f8f8}.item-md-label .highlight-positive{background:#387ef5}.item-md-label .highlight-calm{background:#11c1f3}.item-md-label .highlight-balanced{background:#33cd5f}.item-md-label .highlight-energized{background:#ffc900}.item-md-label .highlight-assertive{background:#ef473a}.item-md-label .highlight-royal{background:#886aea}.item-md-label .highlight-dark{background:#444}.item-md-label .input-label{letter-spacing:.25rem;padding:0 10px}.item-md-label input.used~.input-label,.item-md-label input:focus~.input-label{font-weight:700;opacity:.7;filter:alpha(opacity=70);padding:0;text-transform:uppercase;-webkit-transform:translate3d(0,-60px,0) scale(.9);transform:translate3d(0,-60px,0) scale(.9)}.item-md-label input:focus~.highlight{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded,.expanded .bar.bar-header{height:75px}.bar.bar-header.expanded .title,.expanded.bar.bar-header .title{bottom:0;top:initial;padding-left:16px}.bar.bar-header.expanded .title.fab-left,.expanded .bar.bar-header .title.fab-left{bottom:0;left:90px;position:absolute;right:initial;top:initial}.bar.bar-header.expanded .title.fab-right,.expanded .bar.bar-header .title.fab-right{bottom:0;left:4px;position:absolute;top:initial;right:initial}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{top:50px}.bar.bar-header.expanded.push-down,.expanded .bar.bar-header.push-down{height:44px;overflow:hidden}.bar.bar-header.expanded,.expanded .bar.bar-header{-webkit-transition:height 1s cubic-bezier(.55,0,.1,1);transition:height 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bar.bar-header.expanded+.button-fab,.expanded .bar.bar-header+.button-fab{-webkit-transition:all 1.1s cubic-bezier(.55,0,.1,1);transition:all 1.1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0) scale(1);transform:translate3d(0,0,0) scale(1)}.bar.bar-header.expanded.push-down+.button-fab,.expanded .bar.bar-header.push-down+.button-fab{top:0;-webkit-transform:translate3d(-100px,-100px,0) scale(2.5);transform:translate3d(-100px,-100px,0) scale(2.5)}.bar.bar-header.expanded.push-down .title,.expanded .bar.bar-header.push-down .title{opacity:0;filter:alpha(opacity=0);left:initial;right:initial}.bar.bar-header.expanded .title,.expanded .bar.bar-header .title{opacity:1;filter:alpha(opacity=100);-webkit-transition:all 2s cubic-bezier(.55,0,.1,1);transition:all 2s cubic-bezier(.55,0,.1,1);bottom:0;left:42px!important;top:initial}.bar.bar-header.expanded.has-header-fab-left .title,.expanded.has-header-fab-left .bar.bar-header .title{left:76px!important}.bar{z-index:2;font-size:1.3em;width:100%;box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button{z-index:3}.bar .no-text span.back-text{display:none}.bar .title sup{opacity:.7}.bar.bar-header .button+.title{text-align:left;left:35px;line-height:46px}.button-bar{box-shadow:0 1px 3px rgba(0,0,0,.15)}.button-bar>.button{box-shadow:none}.button-bar>.button .icon:before,.button-bar>.button:before{line-height:initial}.bar-footer .button-fab{position:absolute;top:-26px;bottom:initial}.bar-footer .buttons-left .button-fab{left:8px}.bar-footer .buttons-right .button-fab{right:8px}.bar .button.button-clear{box-shadow:none}.left-buttons .button-fab{left:8px;top:16px}.right-buttons .button-fab{right:8px;top:16px}.fab-left.title-left,.fab-left.title.title-left{left:68px}.bar .button.button-fab,.button.button-fab{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);z-index:9999;width:56px;height:56px;max-height:initial;max-width:initial;border-radius:50%;border-radius:50%;overflow:hidden;padding:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:.3s fade-in-out;transition:.3s fade-in-out;-webkit-transition-property:-webkit-transform,box-shadow;transition-property:transform,box-shadow}.bar .button.button-fab.button-fab-bottom-right,.button.button-fab.button-fab-bottom-right{top:auto;right:16px;bottom:16px;left:auto;position:absolute}.bar .button.button-fab.button-fab-bottom-left,.button.button-fab.button-fab-bottom-left{top:auto;right:auto;bottom:16px;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-right,.button.button-fab.button-fab-top-right{top:32px;right:16px;bottom:auto;left:auto;position:absolute}.bar .button.button-fab.button-fab-top-left,.button.button-fab.button-fab-top-left{top:32px;right:auto;bottom:auto;left:16px;position:absolute}.bar .button.button-fab.button-fab-top-left.expanded,.bar .button.button-fab.button-fab-top-right.expanded,.button.button-fab.button-fab-top-left.expanded,.button.button-fab.button-fab-top-right.expanded{top:48px}.bar .button.button-fab i,.button.button-fab i{font-size:2.5rem;margin-top:0}.bar .button.button-fab.mini,.button.button-fab.mini{width:40px;height:40px}.bar .button.button-fab.mini i,.button.button-fab.mini i{font-size:2rem}.button.button-fab.button-fab-top-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-top-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-left.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(-120px,60px,0);transform:translate3d(-120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.button.button-fab.button-fab-bottom-right.motion{-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform:translate3d(120px,60px,0);transform:translate3d(120px,60px,0);-webkit-transition:all .1s ease-out;transition:all .1s ease-out}.bar .button.button-floating,.button.button-floating{display:inline-block;color:#FFF;position:relative;z-index:1;width:37px;height:37px;line-height:37px;padding:0;border-radius:50%;background-clip:padding-box;-webkit-transition:.3s;transition:.3s;cursor:pointer}.bar .button.button-floating i,.button.button-floating i{width:inherit;display:inline-block;text-align:center;color:#FFF;line-height:37px}.bar .button.button-floating.button-large,.button.button-floating.button-large{width:55.5px;height:55.5px}.bar .button.button-floating.button-large i,.button.button-floating.button-large i{line-height:55.5px}.bar .button,.bar .button.button-flat,.bar .button.button-large,.button,.button.button-flat,.button.button-large{box-shadow:0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);display:inline-block;height:36px;padding:0 2rem;border-radius:2px;background-clip:padding-box;text-transform:uppercase;border:none;outline:0;-webkit-tap-highlight-color:transparent}.bar .button.button-floating.disabled,.bar .button.button-floating:disabled,.bar .button.button-large.disabled,.bar .button.button-large:disabled,.bar .button.button:disabled,.bar .button.disabled,.bar .button.disabled.button-large,.button.button-floating.disabled,.button.button-floating:disabled,.button.button-large.disabled,.button.button-large:disabled,.button.button:disabled,.button.disabled,.button.disabled.button-large{background-color:#DFDFDF;box-shadow:none;color:#9F9F9F}.bar .button.button-floating.disabled:hover,.bar .button.button-floating:disabled:hover,.bar .button.button-large.disabled:hover,.bar .button.button-large:disabled:hover,.bar .button.button:disabled:hover,.bar .button.disabled.button-large:hover,.bar .button.disabled:hover,.button.button-floating.disabled:hover,.button.button-floating:disabled:hover,.button.button-large.disabled:hover,.button.button-large:disabled:hover,.button.button:disabled:hover,.button.disabled.button-large:hover,.button.disabled:hover{background-color:#DFDFDF;color:#9F9F9F}.bar .button i,.bar .button.button-flat i,.bar .button.button-floating i,.bar .button.button-large i,.button i,.button.button-flat i,.button.button-floating i,.button.button-large i{font-size:1.3rem}.button-bar .button{border-radius:0}.bar .button,.bar .button-large,.button,.button-large{text-decoration:none;text-align:center;letter-spacing:.5px;-webkit-transition:.2s ease-out;transition:.2s ease-out;cursor:pointer}.button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;outline:0;margin:0;white-space:nowrap;text-align:center;text-transform:uppercase;font-weight:500;font-style:inherit;font-variant:inherit;font-size:inherit;text-decoration:none;cursor:pointer;-webkit-transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),-webkit-transform .4s cubic-bezier(.25,.8,.25,1);transition:box-shadow .4s cubic-bezier(.25,.8,.25,1),background-color .4s cubic-bezier(.25,.8,.25,1),transform .4s cubic-bezier(.25,.8,.25,1)}.button:focus{outline:0}.button.ng-hide{-webkit-transition:none;transition:none}.button.cornered{border-radius:0}.button.raised{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.button-outline,.button-outline:active,.button-outline:hover{border-style:solid;border-width:1px}.button.button-outline,.button.button-outline.button-assertive,.button.button-outline.button-balanced,.button.button-outline.button-calm,.button.button-outline.button-dark,.button.button-outline.button-energized,.button.button-outline.button-light,.button.button-outline.button-positive,.button.button-outline.button-royal,.button.button-outline.button-stable{border-color:rgba(0,0,0,.1)}.bar .button-flat,.button-flat{box-shadow:none;background-color:transparent;color:#343434;cursor:pointer}.bar .button.button-flat.disabled,.button.button-flat.disabled{color:#b3b3b3}.bar .button.button-large i,.button.button-large i{font-size:1.6rem}.button-pin-header.button-floating{position:absolute;z-index:1000}.button-pin-header.button-pin-left{left:24px;top:-24px}.button-pin-header.button-pin-right{right:24px;top:-24px}.button:not([disabled]).floating:focus,.button:not([disabled]).floating:hover,.button:not([disabled]).raised:focus,.button:not([disabled]).raised:hover{-webkit-transform:translate3d(0,-1px,0);transform:translate3d(0,-1px,0)}.button.button-flat{box-shadow:none}.button.button-flat,.button.button-flat:active,.button.button-flat:hover{color:#fff}.button.button-clear,.button.button-clear:active,.button.button-clear:hover{background:0 0}.button-block.ink,.button-full.ink{display:block}.card-item.item{border:none;padding-bottom:4px;padding-top:4px}.card-item.item:first-child{padding-top:16px}.card{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;margin:8px;padding:0;position:relative}.card .image{display:block;margin-top:10px;margin-bottom:5px}.card img{box-shadow:0 2px 5px 0 rgba(0,0,0,.26);display:block;max-width:100%;max-height:initial;position:static}.card.card-gallery img{border:none;box-shadow:none;display:block}.card .card-footer{font-size:90%;opacity:.8;filter:alpha(opacity=80);padding-top:10px}.card>.item{border:none}.card.card-gallery>.item{background:inherit}.card .icon+.icon{padding-left:1rem}.card.animate-fade-in{opacity:0;filter:alpha(opacity=0);-webkit-transform:translate3d(-30px,1px,0);-webkit-transition:all 1s ease-in-out}.card.animate-fade-in.done{opacity:1;filter:alpha(opacity=100);-webkit-transform:translate3d(0,0,0)}.card .item.item-avatar{min-height:88px;padding-left:88px}.hero{background-size:cover;box-shadow:0 2px 5px 0 rgba(0,0,0,.26);color:#fff;height:200px;position:relative;text-align:center;-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);width:100%}.hero .hero-icon{box-shadow:0 0 2px 0 rgba(0,0,0,.26);border-radius:50%;display:inline-block;height:150px;padding:10px 30px;line-height:136px;width:150px}.hero.no-header{height:244px}.hero>.content{bottom:0;position:absolute;text-align:center;width:100%;z-index:1}.hero>.content>.avatar{background-position:center;background-size:cover;border:solid 1px rgba(255,255,255,.8);border-radius:50%;display:inline-block;height:88px;left:auto;margin-bottom:10px;position:relative;width:88px}.hero h1 .hero h2,.hero h3,.hero h4,.hero h5,.hero h6{color:#fff;margin:0}.hero h4{color:rgba(255,255,255,.7);margin:3px 0 16px}.hero h1>a,.hero h2>a,.hero h3>a,.hero h4>a,.hero h5>a,.hero h6>a{text-decoration:none}.hero+.button-bar{border-radius:0;margin-top:0}.hero+.button-bar>.button:first-child,.hero+.button-bar>.button:last-child{border-radius:0}.hero .hero-icon{color:#fff;font-size:96px}.hero .hero-icon+h1{color:#fff;letter-spacing:.15rem}.hero .button,.hero .button.button-flat,.hero .button.button-large{margin:0}.hero h1.title{color:#fff;font-size:23px;margin:0;text-align:left;padding-left:80px;line-height:59px}.hero+.mid-bar{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);height:initial;opacity:1;filter:alpha(opacity=100)}.hero>*{-webkit-transition:opacity 2.5s cubic-bezier(.55,0,.1,1);transition:opacity 2.5s cubic-bezier(.55,0,.1,1);opacity:1;filter:alpha(opacity=100)}.item{font-size:14px;width:100%}.item-icon-left .icon{left:16px}.item-icon-right .icon{right:16px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{border-radius:50%}.tab-item.activated{height:calc(100% + 3px)}.content+.list{padding-top:0}.list .item{border:none;min-height:48px;text-align:left}.list .item.tabs{padding:initial}.list .item.item-bg-image{min-height:150px}.list .item.item-bg-image>img{height:100%;left:0;max-width:initial;opacity:.65;filter:alpha(opacity=65);position:absolute;top:0;width:100%;z-index:0}.list a.item{opacity:1;filter:alpha(opacity=100)}.list .item.item-bg-image h1,.list .item.item-bg-image h2,.list .item.item-bg-image h3,.list .item.item-bg-image h4,.list .item.item-bg-image h5,.list .item.item-bg-image h6{color:#fff;font-weight:700;position:relative;text-shadow:0 0 3px rgba(0,0,0,.95);z-index:1}.list .item.item-bg-image h2{font-size:24px}.list .item.item-bg-image p{color:#fff;font-size:17px;position:relative;text-shadow:0 0 4px rgba(0,0,0,.95);z-index:1}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{min-height:80px}.card>.item.item-thumbnail-left,.item-thumbnail-left,.item-thumbnail-left .item-content{padding-left:106px}.card>.item.item-thumbnail-right,.item-thumbnail-right,.item-thumbnail-right .item-content{padding-right:106px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{border-radius:50%;left:16px;max-height:40px;max-width:40px}.avatar,.item-avatar .avatar{background-position:center;background-size:cover;border-radius:50%;display:inline-block;height:56px;left:16px;position:absolute;width:56px}.list.half{display:inline-block;float:left;margin:0;padding:0;width:50%}.list.half:first-child{padding:16px 8px 16px 16px}.list.half:last-child{padding:16px 16px 16px 8px}.list.half:first-child .card.card-gallery,.list.half:last-child .card.card-gallery{margin-left:0;margin-right:0}.list.condensed-space>.card,.list.condensed-space>.item{margin:0 0 2px}.list .card.card-gallery{display:block;float:left;margin:0 0 0 13px;padding:0;width:auto}.list.half .item{width:100%}.list.half .item.card{margin-bottom:16px}.list .card.card-gallery.item h2{padding:12px}.list .item.item-gallery img{width:100%}.item.item-divider{border-top:solid 1px rgba(0,0,0,.12);font-size:14px;font-weight:700;height:48px;line-height:48px;color:rgba(0,0,0,.54)}.item.item-divider:first-child{border:none}.item .item-content.activated,.item .item-content.active,.item-complex.activated .item-content,.item-complex.active .item-content,.item.activated,.item.active{background-color:transparent}.list-inset{margin:20px 30px;border-left:solid 1px #ccc;border-radius:0;background-color:#fff}.item-floating-label,.list .item.item-floating-label{border-bottom:solid 1px #ccc}.loader{position:relative;margin:0 auto;width:100px;height:100px;zoom:1.7}.circular{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;height:100px;position:relative;width:100px}.path{stroke-dasharray:1,200;stroke-dashoffset:0;-webkit-animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite,color 6s ease-in-out infinite;stroke-linecap:round}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35}100%{stroke-dasharray:89,200;stroke-dashoffset:-124}}@-webkit-keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}@keyframes color{0%,100%{stroke:#d62d20}40%{stroke:#0057e7}66%{stroke:#008744}80%,90%{stroke:#ffa700}}.login{background-position:25% 25%;background-size:180% 180%;height:100%;-webkit-transition:all 1.5s ease-in-out;transition:all 1.5s ease-in-out}.login .item{margin:0 12px;padding-left:0;padding-right:0;width:initial}.login .button-bar{bottom:0;margin:28px 12px 0;width:initial}.login .light-bg{background-color:#fff}.icon.hero-icon:before{line-height:130px}.card.has-mask:after,.hero.has-mask:after,.item.has-mask:after{content:'';background:-webkit-linear-gradient(top,transparent 0,rgba(0,0,0,.6) 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.card.has-mask-reverse:after,.hero.has-mask-reverse:after,.item.has-mask-reverse:after{content:'';background:-webkit-linear-gradient(top,rgba(0,0,0,.6) 0,transparent 100%);height:100%;left:0;position:absolute;top:0;z-index:0;width:100%}.menu-bottom{bottom:16px;left:16px;right:16px;position:absolute}.menu-top{top:16px;left:16px;right:16px;position:absolute}.menu .avatar{top:16px;left:16px;height:65px;width:65px}.menu .bar.bar-header.expanded{box-shadow:none;min-height:150px;color:#fff}.menu-open .bar.bar-header.expanded{background-position:0;background-size:100%}.has-expanded-header{top:150px!important}.motion{-webkit-transition:all .5s ease-out;transition:all .5s ease-out}.fade{opacity:0;filter:alpha(opacity=0);-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spin-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0)!important;transform:translateZ(0) rotate(360deg) scale(0)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;transform:translateZ(0) rotate(-360deg) scale(0) translate(-120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.spiral-back{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;transform:translateZ(0) rotate(360deg) scale(0) translate(120px)!important;-webkit-transition:all .1s ease-out!important;transition:all .1s ease-out!important}.menu-open .avatar{opacity:1;filter:alpha(opacity=100);-webkit-transform:translateZ(0) rotate(0) scale(1)!important;transform:translateZ(0) rotate(0) scale(1)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotate(0) scale(0)!important;transform:translateZ(0) rotate(0) scale(0)!important;-webkit-transition:all .3s ease-out!important;transition:all .3s ease-out!important}.spin.on{-webkit-transform:translateZ(0) rotate(-360deg) scale(1)!important;transform:translateZ(0) rotate(-360deg) scale(1)!important}.flap{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;transform:translateZ(0) rotateX(0) scale(0) translate(-120px)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flap.on{-webkit-transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;transform:translateZ(0) rotateX(-720deg) scale(1) translate(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) scale(3)!important;transform:translateZ(0) scale(3)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.drop.on{-webkit-transform:translateZ(0) scale(1)!important;transform:translateZ(0) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip{-webkit-backface-visibility:hidden!important;backface-visibility:hidden!important;-webkit-transform:translateZ(0) rotateY(0) scale(0)!important;transform:translateZ(0) rotateY(0) scale(0)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.flip.on{-webkit-transform:translateZ(0) rotateY(-720deg) scale(1)!important;transform:translateZ(0) rotateY(-720deg) scale(1)!important;-webkit-transition:all .5s ease-out!important;transition:all .5s ease-out!important}.bold{font-weight:700}.static{position:static}.pull-left{float:left}.pull-right{float:right}.double-padding,.ionic-content.double-padding{padding:16px}.double-padding-x{padding-left:16px;padding-right:16px}.double-padding-y{padding-top:16px;padding-bottom:16px}.outline{border-style:solid;border-width:1px}.border-top{border-top:solid 1px #ccc;padding-top:30px}.no-border{border:none}.circle{border-radius:50%}.bar.no-padding,.button-bar.no-padding,.button.no-padding,.card.no-padding,.item.no-padding,.list.no-padding,.no-padding{padding:0}.flat,.flat.button,.flat.button.icon,.flat.hero,.flat.tabs{box-shadow:none;-webkit-box-shadow:none}.im-wrapper,.padding{padding:16px!important}.padding-bottom{padding-bottom:16px!important}.padding-top{padding-top:16px!important}.padding-left{padding-left:16px!important}.padding-right{padding-right:16px!important}.no-padding-bottom{padding-bottom:0!important}.no-padding-top{padding-top:0!important}.no-padding-left{padding-left:0!important}.no-padding-right{padding-right:0!important}.z1{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar.bar-positive.darker{background-color:#164FAB}.bar.bar-positive.dark-positive-bg{background-color:#2C5CAD}.muted{color:#C3C3C3}.clear-bg{background:0 0}.animate-blinds .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-blinds .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-blinds .in,.animate-blinds.done>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-blinds .in,.animate-blinds.done .item{visibility:visible}.animate-blinds .item{visibility:hidden;opacity:0;filter:alpha(opacity=0)}.animate-blinds .in,.animate-blinds.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1;filter:alpha(opacity=100);visibility:visible}.animate-blinds.done .in{opacity:1;filter:alpha(opacity=100)}.animate-blinds .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-blinds.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-blinds .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-pan-in-left{background-position:0 0}.animate-ripple .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-ripple .item{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1);opacity:0;filter:alpha(opacity=0)}.animate-ripple .item.in{opacity:1;filter:alpha(opacity=100)}.animate-ripple .done{visibility:hidden;-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1);-webkit-transition:-webkit-transform .3s cubic-bezier(.55,0,.1,1);transition:transform .3s cubic-bezier(.55,0,.1,1)}.animate-ripple .in,.animate-ripple.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;visibility:visible}.animate-ripple.done .in{opacity:1;filter:alpha(opacity=100)}.animate-ripple .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-ripple.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-ripple .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1)}.animate-fade-slide-in .item-bg-image img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in .in,.animate-fade-slide-in.done .item{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);visibility:visible}.list .item.item-bg-image{max-height:150px}.animate-fade-slide-in .item{visibility:hidden;-ms-transform:translate3d(-250px,250px,0);-webkit-transform:translate3d(-250px,250px,0);transform:translate3d(-250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0;filter:alpha(opacity=0)}.animate-fade-slide-in .in,.animate-fade-slide-in.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .5s ease-in-out;transition:all .5s ease-in-out;opacity:1;filter:alpha(opacity=100);visibility:visible}.animate-fade-slide-in.done .in{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.animate-fade-slide-in-right .item{-ms-transform:scale3d(.8,0,1);-webkit-transform:scale3d(.8,0,1);transform:scale3d(.8,0,1)}.animate-fade-slide-in-right .item-bg-image>img.background{box-shadow:none;-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done>*{-ms-transform:translate3d(0,0,0);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done .item{visibility:visible}.animate-fade-slide-in-right .item{visibility:hidden;-ms-transform:translate3d(250px,250px,0);-webkit-transform:translate3d(250px,250px,0);transform:translate3d(250px,250px,0);-webkit-transition:-webkit-transform .5s cubic-bezier(.55,0,.1,1);transition:transform .5s cubic-bezier(.55,0,.1,1);opacity:0;filter:alpha(opacity=0)}.animate-fade-slide-in-right .in,.animate-fade-slide-in-right.done{-ms-transform:scale3d(1,1,1);-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;opacity:1;filter:alpha(opacity=100);visibility:visible}.animate-fade-slide-in-right.done .in{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in-right .has-mask-reverse:after{opacity:0;filter:alpha(opacity=0);-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.animate-fade-slide-in-right.done .has-mask-reverse:after{opacity:1;filter:alpha(opacity=100)}.animate-fade-slide-in-right .out{-ms-transform:scale3d(0,0,1);-webkit-transform:scale3d(0,0,1);transform:scale3d(0,0,1)}.hero.slide-up,.slide-up{height:100%;overflow:hidden;text-align:center}.slide-up{-webkit-transition:all 1s cubic-bezier(.55,0,.1,1);transition:all 1s cubic-bezier(.55,0,.1,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.hero.slide-up *,.slide-up *{opacity:0;filter:alpha(opacity=0)}.hero.slide-up+.mid-bar,.slide-up+.mid-bar{height:100%;opacity:.7;filter:alpha(opacity=70);-webkit-transform:translate3d(100%,-240px,0);transform:translate3d(100%,-240px,0)}/*! + * Waves v0.5.4 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * Forked by Zach Fitzgerald and other contributors for Ionic Material + * + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + * + */.button-clear,.button-fab,.button-flat,.button-raised,.ink,.popup .button{position:relative;cursor:pointer;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.ink-ripple{position:absolute;border-radius:50%;width:100px;height:100px;margin-top:-50px;margin-left:-50px;opacity:0;background-color:rgba(255,255,255,.4);-webkit-transition:all .5s ease-out;-moz-transition:all .5s ease-out;-o-transition:all .5s ease-out;transition:all .5s ease-out;-webkit-transition-property:-webkit-transform,opacity;-moz-transition-property:-moz-transform,opacity;-o-transition-property:-o-transform,opacity;transition-property:transform,opacity;-webkit-transform:scale(0);-moz-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);pointer-events:none}.ink-notransition{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.button-clear,.button-fab,.button-flat,.button-raised,.ink-button,.ink-circle{-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.button-clear.activated,.button-clear:active,.button-fab.activated,.button-fab:active,.button-flat.activated,.button-flat:active,.button-raised.activated,.button-raised:active,.ink-button.activated,.ink-button:active,.ink-circle.activated,.ink-circle:active,.ink.activated,.ink:active,.popup .button.activated,.popup .button:active{-webkit-mask-image:-webkit-radial-gradient(circle,#fff 100%,#000 100%)}.button-clear,.button-clear:link,.button-clear:visited,.button-fab,.button-fab:link,.button-fab:visited,.button-flat,.button-flat:link,.button-flat:visited,.button-raised,.button-raised:link,.button-raised:visited,.ink-button,.ink-button-input,.ink-button:link,.ink-button:visited{white-space:nowrap;vertical-align:middle;cursor:pointer;border:none;outline:0;font-size:14px;text-align:center;text-decoration:none;z-index:1}.ink-button{padding:10px 15px;border-radius:2px}.ink-button-input{margin:0;padding:10px 15px}.ink-input-wrapper{border-radius:2px;vertical-align:bottom}.ink-input-wrapper.ink-button{padding:0}.ink-input-wrapper .ink-button-input{position:relative;top:0;left:0;z-index:1}.ink-circle{text-align:center;width:2.5em;height:2.5em;line-height:2.5em;border-radius:50%}.ink-float{-webkit-mask-image:none;-webkit-box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12);box-shadow:0 1px 1.5px 1px rgba(0,0,0,.12)}.ink-float:active{-webkit-box-shadow:0 8px 20px 1px rgba(0,0,0,.3);box-shadow:0 8px 20px 1px rgba(0,0,0,.3)}.ink-block{display:block}.ink-ripple{z-index:0}.button-clear .ink-ripple,.ink-dark .ink-ripple,.list .ink-ripple,[class$="-clear"]>.ink-ripple,[class$="-light"]>.ink-ripple,[class$="-stable"]>.ink-ripple,[class$="-100"]>.ink-ripple{background-color:rgba(0,0,0,.2)}.tab-item{position:relative}*{font-family:RobotoDraft,Roboto,"Helvetica Neue","Segoe UI",sans-serif}.rounded{border-radius:4px}a{cursor:pointer}.has-header.expanded{top:76px}.bar{border-bottom:none;padding:0}.bar .button{min-height:44px;min-width:44px;max-width:48px;margin-bottom:0;max-height:44px;width:48px}.bar .title+.buttons.buttons-right{right:0;top:0}.title-left,.title-right,.title.title-left,.title.title-right{left:48px}.bar .button-positive,.bar .button-positive.activated,.bar .button-positive:active,.bar .button-positive:hover,.bar-positive,.bar-positive.activated,.bar-positive:active,.bar-positive:hover,.button-bar-positive,.button-bar-positive.activated,.button-bar-positive:active,.button-bar-positive:hover,.button-positive,.button-positive.activated,.button-positive:active,.button-positive:hover,.header-positive,.header-positive.activated,.header-positive:active,.header-positive:hover,.positive-bg,.positive-bg.activated,.positive-bg:active,.positive-bg:hover,.positive-border,.positive-border.activated,.positive-border:active,.positive-border:hover{background-color:#3F51B5;color:#fff}.bar .button-positive-900,.bar .button-positive-900.activated,.bar .button-positive-900:active,.bar .button-positive-900:hover,.bar-positive-900,.bar-positive-900.activated,.bar-positive-900:active,.bar-positive-900:hover,.button-bar-positive-900,.button-bar-positive-900.activated,.button-bar-positive-900:active,.button-bar-positive-900:hover,.button-positive-900,.button-positive-900.activated,.button-positive-900:active,.button-positive-900:hover,.header-positive-900,.header-positive-900.activated,.header-positive-900:active,.header-positive-900:hover,.positive-900-bg,.positive-900-bg.activated,.positive-900-bg:active,.positive-900-bg:hover,.positive-900-border,.positive-900-border.activated,.positive-900-border:active,.positive-900-border:hover{background-color:#1A237E;color:#fff}.bar .button-positive-100,.bar .button-positive-100.activated,.bar .button-positive-100:active,.bar .button-positive-100:hover,.bar-positive-100,.bar-positive-100.activated,.bar-positive-100:active,.bar-positive-100:hover,.button-bar-positive-100,.button-bar-positive-100.activated,.button-bar-positive-100:active,.button-bar-positive-100:hover,.button-positive-100,.button-positive-100.activated,.button-positive-100:active,.button-positive-100:hover,.header-positive-100,.header-positive-100.activated,.header-positive-100:active,.header-positive-100:hover,.positive-100-bg,.positive-100-bg.activated,.positive-100-bg:active,.positive-100-bg:hover,.positive-100-border,.positive-100-border.activated,.positive-100-border:active,.positive-100-border:hover{background-color:#C5CAE9;color:#fff}.bar .button-calm,.bar .button-calm.activated,.bar .button-calm:active,.bar .button-calm:hover,.bar-calm,.bar-calm.activated,.bar-calm:active,.bar-calm:hover,.button-bar-calm,.button-bar-calm.activated,.button-bar-calm:active,.button-bar-calm:hover,.button-calm,.button-calm.activated,.button-calm:active,.button-calm:hover,.calm-bg,.calm-bg.activated,.calm-bg:active,.calm-bg:hover,.calm-border,.calm-border.activated,.calm-border:active,.calm-border:hover,.header-calm,.header-calm.activated,.header-calm:active,.header-calm:hover{background-color:#2196F3;color:#fff}.bar .button-calm-900,.bar .button-calm-900.activated,.bar .button-calm-900:active,.bar .button-calm-900:hover,.bar-calm-900,.bar-calm-900.activated,.bar-calm-900:active,.bar-calm-900:hover,.button-bar-calm-900,.button-bar-calm-900.activated,.button-bar-calm-900:active,.button-bar-calm-900:hover,.button-calm-900,.button-calm-900.activated,.button-calm-900:active,.button-calm-900:hover,.calm-900-bg,.calm-900-bg.activated,.calm-900-bg:active,.calm-900-bg:hover,.calm-900-border,.calm-900-border.activated,.calm-900-border:active,.calm-900-border:hover,.header-calm-900,.header-calm-900.activated,.header-calm-900:active,.header-calm-900:hover{background-color:#0D47A1;color:#fff}.bar .button-calm-100,.bar .button-calm-100.activated,.bar .button-calm-100:active,.bar .button-calm-100:hover,.bar-calm-100,.bar-calm-100.activated,.bar-calm-100:active,.bar-calm-100:hover,.button-bar-calm-100,.button-bar-calm-100.activated,.button-bar-calm-100:active,.button-bar-calm-100:hover,.button-calm-100,.button-calm-100.activated,.button-calm-100:active,.button-calm-100:hover,.calm-100-bg,.calm-100-bg.activated,.calm-100-bg:active,.calm-100-bg:hover,.calm-100-border,.calm-100-border.activated,.calm-100-border:active,.calm-100-border:hover,.header-calm-100,.header-calm-100.activated,.header-calm-100:active,.header-calm-100:hover{background-color:#BBDEFB;color:#fff}.bar .button-royal,.bar .button-royal.activated,.bar .button-royal:active,.bar .button-royal:hover,.bar-royal,.bar-royal.activated,.bar-royal:active,.bar-royal:hover,.button-bar-royal,.button-bar-royal.activated,.button-bar-royal:active,.button-bar-royal:hover,.button-royal,.button-royal.activated,.button-royal:active,.button-royal:hover,.header-royal,.header-royal.activated,.header-royal:active,.header-royal:hover,.royal-bg,.royal-bg.activated,.royal-bg:active,.royal-bg:hover,.royal-border,.royal-border.activated,.royal-border:active,.royal-border:hover{background-color:#673AB7;color:#fff}.bar .button-royal-900,.bar .button-royal-900.activated,.bar .button-royal-900:active,.bar .button-royal-900:hover,.bar-royal-900,.bar-royal-900.activated,.bar-royal-900:active,.bar-royal-900:hover,.button-bar-royal-900,.button-bar-royal-900.activated,.button-bar-royal-900:active,.button-bar-royal-900:hover,.button-royal-900,.button-royal-900.activated,.button-royal-900:active,.button-royal-900:hover,.header-royal-900,.header-royal-900.activated,.header-royal-900:active,.header-royal-900:hover,.royal-900-bg,.royal-900-bg.activated,.royal-900-bg:active,.royal-900-bg:hover,.royal-900-border,.royal-900-border.activated,.royal-900-border:active,.royal-900-border:hover{background-color:#311B92;color:#fff}.bar .button-royal-100,.bar .button-royal-100.activated,.bar .button-royal-100:active,.bar .button-royal-100:hover,.bar-royal-100,.bar-royal-100.activated,.bar-royal-100:active,.bar-royal-100:hover,.button-bar-royal-100,.button-bar-royal-100.activated,.button-bar-royal-100:active,.button-bar-royal-100:hover,.button-royal-100,.button-royal-100.activated,.button-royal-100:active,.button-royal-100:hover,.header-royal-100,.header-royal-100.activated,.header-royal-100:active,.header-royal-100:hover,.royal-100-bg,.royal-100-bg.activated,.royal-100-bg:active,.royal-100-bg:hover,.royal-100-border,.royal-100-border.activated,.royal-100-border:active,.royal-100-border:hover{background-color:#D1C4E9;color:#fff}.balanced-bg,.balanced-bg.activated,.balanced-bg:active,.balanced-bg:hover,.balanced-border,.balanced-border.activated,.balanced-border:active,.balanced-border:hover,.bar .button-balanced,.bar .button-balanced.activated,.bar .button-balanced:active,.bar .button-balanced:hover,.bar-balanced,.bar-balanced.activated,.bar-balanced:active,.bar-balanced:hover,.button-balanced,.button-balanced.activated,.button-balanced:active,.button-balanced:hover,.button-bar-balanced,.button-bar-balanced.activated,.button-bar-balanced:active,.button-bar-balanced:hover,.header-balanced,.header-balanced.activated,.header-balanced:active,.header-balanced:hover{background-color:#4CAF50;color:#fff}.balanced-900-bg,.balanced-900-bg.activated,.balanced-900-bg:active,.balanced-900-bg:hover,.balanced-900-border,.balanced-900-border.activated,.balanced-900-border:active,.balanced-900-border:hover,.bar .button-balanced-900,.bar .button-balanced-900.activated,.bar .button-balanced-900:active,.bar .button-balanced-900:hover,.bar-balanced-900,.bar-balanced-900.activated,.bar-balanced-900:active,.bar-balanced-900:hover,.button-balanced-900,.button-balanced-900.activated,.button-balanced-900:active,.button-balanced-900:hover,.button-bar-balanced-900,.button-bar-balanced-900.activated,.button-bar-balanced-900:active,.button-bar-balanced-900:hover,.header-balanced-900,.header-balanced-900.activated,.header-balanced-900:active,.header-balanced-900:hover{background-color:#1B5E20;color:#fff}.balanced-100-bg,.balanced-100-bg.activated,.balanced-100-bg:active,.balanced-100-bg:hover,.balanced-100-border,.balanced-100-border.activated,.balanced-100-border:active,.balanced-100-border:hover,.bar .balanced-100-bg:hover,.bar .button-balanced-100,.bar .button-balanced-100.activated,.bar .button-balanced-100:active,.bar-balanced-100,.bar-balanced-100.activated,.bar-balanced-100:active,.bar-balanced-100:hover,.button-balanced-100,.button-balanced-100.activated,.button-balanced-100:active,.button-balanced-100:hover,.button-bar-balanced-100,.button-bar-balanced-100.activated,.button-bar-balanced-100:active,.button-bar-balanced-100:hover,.header-balanced-100,.header-balanced-100.activated,.header-balanced-100:active,.header-balanced-100:hover{background-color:#C8E6C9;color:#fff}.bar .button-energized,.bar .button-energized.activated,.bar .button-energized:active,.bar .button-energized:hover,.bar-energized,.bar-energized.activated,.bar-energized:active,.bar-energized:hover,.button-bar-energized,.button-bar-energized.activated,.button-bar-energized:active,.button-bar-energized:hover,.button-energized,.button-energized.activated,.button-energized:active,.button-energized:hover,.energized-bg,.energized-bg.activated,.energized-bg:active,.energized-bg:hover,.energized-border,.energized-border.activated,.energized-border:active,.energized-border:hover,.header-energized,.header-energized.activated,.header-energized:active,.header-energized:hover{background-color:#FF9800;color:#fff}.bar .button-energized-900,.bar .button-energized-900.activated,.bar .button-energized-900:active,.bar .button-energized-900:hover,.bar-energized-900,.bar-energized-900.activated,.bar-energized-900:active,.bar-energized-900:hover,.button-bar-energized-900,.button-bar-energized-900.activated,.button-bar-energized-900:active,.button-bar-energized-900:hover,.button-energized-900,.button-energized-900.activated,.button-energized-900:active,.button-energized-900:hover,.energized-900-bg,.energized-900-bg.activated,.energized-900-bg:active,.energized-900-bg:hover,.energized-900-border,.energized-900-border.activated,.energized-900-border:active,.energized-900-border:hover,.header-energized-900,.header-energized-900.activated,.header-energized-900:active,.header-energized-900:hover{background-color:#E65100;color:#fff}.bar .button-energized-100,.bar .button-energized-100.activated,.bar .button-energized-100:active,.bar .button-energized-100:hover,.bar-energized-100,.bar-energized-100.activated,.bar-energized-100:active,.bar-energized-100:hover,.button-bar-energized-100,.button-bar-energized-100.activated,.button-bar-energized-100:active,.button-bar-energized-100:hover,.button-energized-100,.button-energized-100.activated,.button-energized-100:active,.button-energized-100:hover,.energized-100-bg,.energized-100-bg.activated,.energized-100-bg:active,.energized-100-bg:hover,.energized-100-border,.energized-100-border.activated,.energized-100-border:active,.energized-100-border:hover,.header-energized-100,.header-energized-100.activated,.header-energized-100:active,.header-energized-100:hover{background-color:#FFE0B2}.assertive-bg,.assertive-bg.activated,.assertive-bg:active,.assertive-bg:hover,.assertive-border,.assertive-border.activated,.assertive-border:active,.assertive-border:hover,.bar .button-assertive,.bar .button-assertive.activated,.bar .button-assertive:active,.bar .button-assertive:hover,.bar-assertive,.bar-assertive.activated,.bar-assertive:active,.bar-assertive:hover,.button-assertive,.button-assertive.activated,.button-assertive:active,.button-assertive:hover,.button-bar-assertive,.button-bar-assertive.activated,.button-bar-assertive:active,.button-bar-assertive:hover,.header-assertive,.header-assertive.activated,.header-assertive:active,.header-assertive:hover{background-color:#F44336;color:#fff}.assertive-900-bg,.assertive-900-bg.activated,.assertive-900-bg:active,.assertive-900-bg:hover,.assertive-900-border,.assertive-900-border.activated,.assertive-900-border:active,.assertive-900-border:hover,.bar .button-assertive-900,.bar .button-assertive-900.activated,.bar .button-assertive-900:active,.bar .button-assertive-900:hover,.bar-assertive-900,.bar-assertive-900.activated,.bar-assertive-900:active,.bar-assertive-900:hover,.button-assertive-900,.button-assertive-900.activated,.button-assertive-900:active,.button-assertive-900:hover,.button-bar-assertive-900,.button-bar-assertive-900.activated,.button-bar-assertive-900:active,.button-bar-assertive-900:hover,.header-assertive-900,.header-assertive-900.activated,.header-assertive-900:active,.header-assertive-900:hover{background-color:#B71C1C;color:#fff}.assertive-100-bg,.assertive-100-bg.activated,.assertive-100-bg:active,.assertive-100-bg:hover,.assertive-100-border,.assertive-100-border.activated,.assertive-100-border:active,.assertive-100-border:hover,.bar .button-assertive-100,.bar .button-assertive-100.activated,.bar .button-assertive-100:active,.bar .button-assertive-100:hover,.bar-assertive-100,.bar-assertive-100.activated,.bar-assertive-100:active,.bar-assertive-100:hover,.button-assertive-100,.button-assertive-100.activated,.button-assertive-100:active,.button-assertive-100:hover,.button-bar-assertive-100,.button-bar-assertive-100.activated,.button-bar-assertive-100:active,.button-bar-assertive-100:hover,.header-assertive-100,.header-assertive-100.activated,.header-assertive-100:active,.header-assertive-100:hover{background-color:#FFCDD2;color:#fff}.bar .button-stable,.bar .button-stable.activated,.bar .button-stable:active,.bar .button-stable:hover,.bar-stable,.bar-stable.activated,.bar-stable:active,.bar-stable:hover,.button-bar-stable,.button-bar-stable.activated,.button-bar-stable:active,.button-bar-stable:hover,.button-stable,.button-stable.activated,.button-stable:active,.button-stable:hover,.header-stable,.header-stable.activated,.header-stable:active,.header-stable:hover,.stable-bg,.stable-bg.activated,.stable-bg:active,.stable-bg:hover,.stable-border,.stable-border.activated,.stable-border:active,.stable-border:hover{background-color:#E0E0E0;color:#fff}.positive,.positive *,.positive-900,.positive-900 *,.positive-900:active,.positive-900:active *,.positive-900:hover,.positive-900:hover *,.positive:active,.positive:active *,.positive:hover,.positive:hover *{color:#3F51B5}.positive-100,.positive-100 *,.positive-100:active,.positive-100:active *,.positive-100:hover,.positive-100:hover *{color:#C5CAE9}.calm-900,.calm-900 *,.calm-900:active,.calm-900:active *,.calm-900:hover,.calm-900:hover *{color:#0D47A1}.calm-100,.calm-100 *,.calm-100:active,.calm-100:active *,.calm-100:hover,.calm-100:hover *{color:#BBDEFB}.royal,.royal *,.royal:active,.royal:active *,.royal:hover,.royal:hover *{color:#673AB7}.royal-900,.royal-900 *,.royal-900:active,.royal-900:active *,.royal-900:hover,.royal-900:hover *{color:#311B92}.royal-100,.royal-100 *,.royal-100:active,.royal-100:active *,.royal-100:hover,.royal-100:hover *{color:#D1C4E9}.balanced,.balanced *,.balanced:active,.balanced:active *,.balanced:hover,.balanced:hover *{color:#4CAF50}.balanced-900,.balanced-900 *,.balanced-900:active,.balanced-900:active *,.balanced-900:hover,.balanced-900:hover *{color:#1B5E20}.balanced-100,.balanced-100 *,.balanced-100:active,.balanced-100:active *,.balanced-100:hover,.balanced-100:hover *{color:#C8E6C9}.energized,.energized *,.energized:active,.energized:active *,.energized:hover,.energized:hover *{color:#FF9800}.energized-900,.energized-900 *,.energized-900:active,.energized-900:active *,.energized-900:hover,.energized-900:hover *{color:#E65100}.energized-100,.energized-100 *,.energized-100:active,.energized-100:active *,.energized-100:hover,.energized-100:hover *{color:#FFE0B2}.assertive,.assertive *,.assertive:active,.assertive:active *,.assertive:hover,.assertive:hover *{color:#F44336}.assertive-900,.assertive-900 *,.assertive-900:active,.assertive-900:active *,.assertive-900:hover,.assertive-900:hover *{color:#B71C1C}.assertive-100,.assertive-100 *,.assertive-100:active,.assertive-100:active *,.assertive-100:hover,.assertive-100:hover *{color:#FFCDD2}.stable,.stable *,.stable:active,.stable:active *,.stable:hover,.stable:hover *{color:#E0E0E0}.light,.light *,.light:active,.light:active *,.light:hover,.light:hover *{color:#fff}.dark,.dark *,.dark:active,.dark:active *,.dark:hover,.dark:hover *{color:#444}.light-border{border-color:#ddd}.navbar-default .navbar-nav>li>a{margin:0;padding-right:26px;padding-left:26px;border-top:3px solid transparent;color:#BFD5C9;opacity:1}.mid-bar{padding:16px}.mid-bar h1,.mid-bar h2,.mid-bar h3,.mid-bar h4,.mid-bar h5,.mid-bar h6{color:#fff;margin-bottom:5px}.mid-bar p{color:rgba(255,255,255,.5);margin-bottom:0}.card>.item-avatar,.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:95px}.item,.item-complex .item-content,.item-radio .item-content{background-color:transparent}.dark-bg h2,.item.dark-bg h2{color:#fff}.tabs-striped .tabs{box-shadow:0 2px 5px 0 rgba(0,0,0,.26)}.bar .button.button-clear{color:#fff}.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before{vertical-align:top;font-size:24px}.menu{background-color:transparent}.button-icon.button.activated,.button-icon.button.active{opacity:initial}.popover{opacity:0;position:absolute;right:8px;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out;top:8px}.popover.ng-enter{opacity:1;transform:translate(0,-14px) scale(1,1);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.popover.ng-leave{opacity:0;transform:translate(50%,-50%) scale(0,0);transition:transform .3s ease-in-out,opacity .3s ease-in-out}.button{overflow:hidden!important} +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImRpcmVjdGl2ZXMvbWQtbGFiZWwuc2NzcyIsImVsZW1lbnRzL2Jhci1oZWFkZXItZXhwYW5kZWQuc2NzcyIsImVsZW1lbnRzL2Jhci5zY3NzIiwiZWxlbWVudHMvYnV0dG9uLWJhci5zY3NzIiwiZWxlbWVudHMvYnV0dG9uLWZhYi5zY3NzIiwiZWxlbWVudHMvYnV0dG9uLWZsb2F0aW5nLnNjc3MiLCJlbGVtZW50cy9idXR0b24uc2NzcyIsImVsZW1lbnRzL2NhcmQuc2NzcyIsImVsZW1lbnRzL2hlcm8uc2NzcyIsImVsZW1lbnRzL2l0ZW0uc2NzcyIsImVsZW1lbnRzL2xpc3Quc2NzcyIsImVsZW1lbnRzL2xvYWRpbmcuc2NzcyIsImVsZW1lbnRzL2xvZ2luLnNjc3MiLCJlbGVtZW50cy9tYXNrLnNjc3MiLCJlbGVtZW50cy9tZW51LnNjc3MiLCJlbGVtZW50cy9tb3Rpb24tZWxlbWVudHMuc2NzcyIsImhlbHBlcnMvdXRpbGl0aWVzLnNjc3MiLCJtb3Rpb24vYmxpbmRzLnNjc3MiLCJtb3Rpb24vcGFuLWluLWxlZnQuc2NzcyIsIm1vdGlvbi9yaXBwbGUuc2NzcyIsIm1vdGlvbi9zbGlkZS1mYWRlLWluLnNjc3MiLCJtb3Rpb24vc2xpZGUtaW4tcmlnaHQuc2NzcyIsIm1vdGlvbi9zbGlkZS11cC5zY3NzIiwib3ZlcnJpZGVzL2luay5zY3NzIiwib3ZlcnJpZGVzL2lvbmljLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsZUFDSSxjQUNBLGVBQ0EsZ0JBQ0EsaUJBQ0Esa0JBQ0EsaUJBRVcsNEJBQ1gsa0JBRUEsVUFDQSxrREFDQSwwQ0FDQSxnQ0FDQSx3QkFDQSxXQUNBLFdBQ0EseUJBQ0EsMkJBQ0EsdUJBQ0EsbUJBRVcscUJBQ1gsZ0NBQ0EsU0FDQSxXQUNBLHNCQUNBLGtCQUNBLGtCQUNBLFVBRVcsMEJBQ1gsa0JBQ0EsU0FDQSxXQUNBLE9BQ0EsV0FDQSx5Q0FDQSxpQ0FDQSxpQ0FDQSx5QkFDQSxVQUVXLGdDQUNYLGdCQUVXLGlDQUNYLG1CQUVXLG1DQUNYLG1CQUVXLCtCQUNYLG1CQUVXLG1DQUNYLG1CQUVXLG9DQUNYLG1CQUVXLG9DQUNYLG1CQUVXLGdDQUNYLG1CQUVXLCtCQUNYLGdCQUVXLDRCQUNYLHNCQUNBLGVBRThHLHVDQUEzQyx3Q0FDbkUsZ0JBQ0EsV0FDQSx5QkFDQSxVQUNBLHlCQUNBLG1EQUNBLDJDQUV5QixzQ0FDekIscUNBQ0EsNkJDcEZKLHlCQURlLDBCQUNYLFlBS0osZ0NBRHlCLGdDQUNyQixTQUNBLFlBQ0Esa0JBS0oseUNBRCtCLDBDQUMzQixTQUNBLFVBQ0Esa0JBQ0EsY0FDQSxZQUlKLDBDQUQrQiwyQ0FDM0IsU0FDQSxTQUNBLGtCQUNBLFlBQ0EsY0FJSixxQ0FEMkIsc0NBQ3ZCLFNBSUosbUNBRHdCLG9DQUNwQixZQUNBLGdCQUlKLHlCQURlLDBCQUNYLHNEQUNBLDhDQUNBLHFDQUNBLDZCQUlKLHFDQUQyQixzQ0FDdkIscURBQ0EsNkNBQ0EsOENBQ0Esc0NBSUosK0NBRHFDLGdEQUNqQyxNQUNBLDBEQUNBLGtEQUlKLDBDQURtQywyQ0FDL0IsVUFDQSx3QkFDQSxhQUNBLGNBSUosZ0NBRHlCLGlDQUNyQixVQUNBLDBCQUNBLG1EQUNBLDJDQUlBLFNBQ0Esb0JBQ0EsWUFFcUosb0RBQXRELHFEQUMvRixvQkMzRUosS0FDSSxVQUNBLGdCQUNBLFdBQ0EsdUNBR0MsYUFFRCxVQUdjLDZCQUNkLGFBR1EsZ0JBQ1IsV0FHc0IsK0JBQ3RCLGdCQUNBLFVBQ0EsaUJDM0JKLFlBQ0kscUNBR1Usb0JBQ1YsZ0JBS2UsaUNBQ25CLDJCQUFJLG9CQUdRLHdCQUNSLGtCQUNBLFVBQ0EsZUFHc0Isc0NBQ3RCLFNBR3VCLHVDQUN2QixVQUdRLDBCQUNSLGdCQUdVLDBCQUNWLFNBQ0EsU0FHVywyQkFDWCxVQUNBLFNBSVcscUJBQ2YsMkJBQUksVUMxQ0osd0JBRFksbUJBQ1Isb0VBQ0EsYUFDQSxXQUNBLFlBQ0EsbUJBQ0Esa0JBQ0Esa0JBQ0Esa0JBQ0EsZ0JBQ0EsVUFDQSxxQ0FDQSw2QkFDQSxtQ0FDQSwyQkFDQSx5REFDQSx5Q0FLSixnREFEdUIsMkNBQ25CLFNBQ0EsV0FDQSxZQUNBLFVBQ0Esa0JBS0osK0NBRHVCLDBDQUNuQixTQUNBLFdBQ0EsWUFDQSxVQUNBLGtCQUtKLDZDQUR1Qix3Q0FDbkIsU0FDQSxXQUNBLFlBQ0EsVUFDQSxrQkFLSiw0Q0FEdUIsdUNBQ25CLFNBQ0EsV0FDQSxZQUNBLFVBQ0Esa0JBT0oscURBQ0Esc0RBSDRDLGdEQUM1QyxpREFBSSxTQUtKLDBCQUR3QixxQkFDcEIsaUJBQ0EsYUFLSiw2QkFEdUIsd0JBQ25CLFdBQ0EsWUFLSiwrQkFENkIsMEJBQ3pCLGVBeURrQyw4Q0FDbEMsbUNBQ0EsMkJBQ0EsNkNBQ0EscUNBQ0Esb0NBQ0EsNEJBRW1DLCtDQUNuQyxtQ0FDQSwyQkFDQSw0Q0FDQSxvQ0FDQSxvQ0FDQSw0QkFFcUMsaURBQ3JDLG1DQUNBLDJCQUNBLDZDQUNBLHFDQUNBLG9DQUNBLDRCQUVzQyxrREFDdEMsbUNBQ0EsMkJBQ0EsNENBQ0Esb0NBQ0Esb0NBQ0EsNEJDbEswRCw2QkFBekIsd0JBQ2pDLHFCQUNBLFdBQ0Esa0JBQ0EsVUFDQSxXQUNBLFlBQ0EsaUJBQ0EsVUFDQSxrQkFDQSw0QkFDQSx1QkFDQSxlQUNBLGVBRStFLCtCQUEzQiwwQkFDcEQsY0FDQSxxQkFDQSxrQkFDQSxXQUVBLGlCQUVvRywwQ0FBdEMscUNBQzlELGFBQ0EsY0FFc0gsNENBQXhDLHVDQUM5RSxtQkNyQkosYUFFQSx5QkFEQSwwQkFKWSxRQUVaLG9CQURBLHFCQUFJLG9FQUNBLHFCQUNBLFlBQ0EsZUFDQSxrQkFDQSw0QkFDQSx5QkFDQSxZQUNBLFVBQ0Esd0NBNEJKLHNDQUtBLHNDQUpBLG1DQUVBLG1DQURBLDZCQUpBLHNCQUNBLG1DQVBBLGlDQUtBLGlDQUpBLDhCQUVBLDhCQURBLHdCQUo0QixpQkFDNUIsOEJBQUkseUJBQ0EsZ0JBQ0EsY0E0QkosNENBS0EsNENBSkEseUNBRUEseUNBREEsbUNBSEEseUNBREEsNEJBTkEsdUNBS0EsdUNBSkEsb0NBRUEsb0NBREEsOEJBSEEsb0NBRHFDLHVCQUNqQyx5QkFDQSxjQWlCSixlQUlBLDJCQUZBLCtCQURBLDRCQU55QixVQUl6QixzQkFGQSwwQkFEQSx1QkFBSSxpQkFHUSxvQkFDUixnQkFRSixhQUNBLG1CQUhLLFFBQ0wsY0FBSSxxQkFDQSxrQkFDQSxvQkFDQSxnQ0FDQSx3QkFDQSxlQUdKLFFBQ0kseUJBQ0Esc0JBQ0EscUJBQ0EsaUJBQ0Esa0JBQ0EsVUFDQSxTQUVBLG1CQUNBLGtCQUNBLHlCQUNBLGdCQUNBLG1CQUNBLHFCQUNBLGtCQUNBLHFCQUNBLGVBRUEsOEpBQ0EsOElBR0csY0FDSCxVQUdHLGdCQUNILHdCQUNBLGdCQUdHLGlCQUNILGdCQUdHLGVBQ0gscUNBQ0EsNkJBS1csZ0JBRWYsdUJBREEsc0JBQUksbUJBQ0EsaUJBcUJKLHVCQVRPLHdDQUNQLHVDQUNBLG1DQUNBLG1DQUNBLHdDQUNBLG9DQUNBLHVDQUNBLG9DQUNBLHFDQVBJLDRCQUtKLGtCQURLLGFBQ0QsZ0JBQ0EsNkJBQ0EsY0FDQSxlQUtKLGtDQUR3Qiw2QkFDcEIsY0FLSiw0QkFEMEIsdUJBQ3RCLGlCQUdjLG1DQUNkLGtCQUNBLGFBR2MsbUNBQ2QsVUFDQSxVQUdjLG9DQUNkLFdBQ0EsVUFRSix1Q0FDQSx1Q0FIZ0MscUNBQ2hDLHFDQUFJLHdDQUNBLGdDQUdHLG9CQUNILGdCQVllLG9CQUVuQiwyQkFEQSwwQkFBSSxXQUtnQixxQkFFcEIsNEJBREEsMkJBQUksZUFNSixrQkFEYSxpQkFDVCxjQ3ZOTSxnQkFDTixZQUNBLG1CQUNBLGdCQUdXLDRCQUNYLGlCQUdKLE1BQ0ksdUNBQ0EsY0FDQSxXQUNBLFVBQ0Esa0JBRUUsYUFDRixjQUNBLGdCQUNBLGtCQUVFLFVBQ0YsdUNBQ0EsY0FDQSxlQUNBLG1CQUNBLGdCQUVlLHVCQUNmLFlBQ0EsZ0JBQ0EsY0FFRSxtQkFDRixjQUNBLFdBQ0EseUJBQ0EsaUJBRUksWUFDSixZQUVpQix5QkFDakIsbUJBRVUsa0JBQ1Ysa0JBRUMsc0JBQ0QsVUFDQSx3QkFDQSwyQ0FDQSxzQ0FFaUIsMkJBQ2pCLFVBQ0EsMEJBQ0EscUNBRU8sd0JBQ1AsZ0JBQ0Esa0JDOURKLE1BQ0ksc0JBQ0EsdUNBQ0EsV0FDQSxhQUNBLGtCQUNBLGtCQUNBLG1EQUNBLDJDQUNBLHFDQUNBLDZCQUNBLFdBb0JFLGlCQUNGLHFDQUNBLGtCQUNBLHFCQUVBLGFBQ0Esa0JBQ0Esa0JBQ0EsWUFFQyxnQkFDRCxhQUVJLGVBQ0osU0FDQSxrQkFDQSxrQkFDQSxXQUNBLFVBRWUsdUJBQ2YsMkJBQ0Esc0JBQ0Esc0NBQ0Esa0JBQ0EscUJBQ0EsWUFDQSxVQUNBLG1CQUNBLGtCQUNBLFdBRW1ELGtCQUFtQixTQUFVLFNBQVUsU0FBVSxTQUNwRyxXQUNBLFNBRUUsU0FDRiwyQkFDQSxrQkFFNkUsV0FBYyxXQUFjLFdBQWMsV0FBYyxXQUFjLFdBQ25KLHFCQUVJLGtCQUNKLGdCQUNBLGFBRW9FLHNDQUEyQyxxQ0FDL0csZ0JBRUUsaUJBQ0YsV0FDQSxlQUVlLG9CQUNmLFdBQ0Esc0JBRW9ELGNBQTJDLDBCQUE1QiwyQkFDbkUsU0FFSSxlQUNKLFdBQ0EsZUFDQSxTQUNBLGdCQUNBLGtCQUNBLGlCQUVJLGVBQ0oscUNBQ0EsNkJBQ0EsbURBQ0EsMkNBQ0EsZUFDQSxVQUNBLDBCQUVJLFFBQ0oseURBQ0EsaURBQ0EsVUFDQSwwQkNqSEosTUFDSSxlQUNBLFdBRVksc0JBQ1osVUFFYSx1QkFDYixXQVMrUiwrQ0FBdEQsbURBQWxDLGlDQUF4QyxxQ0FDbEssa0JBR1Esb0JBQ1Isd0JDbkJVLGVBQ1AsY0FFRSxZQUNGLFlBS0EsZ0JBRUEsZ0JBRU8saUJBQ1AsZ0JBRU8sMEJBRVAsaUJBRXdCLDhCQUN4QixZQUNBLE9BQ0Esa0JBQ0EsWUFDQSx5QkFDQSxrQkFDQSxNQUNBLFdBQ0EsVUFFRyxhQUNILFVBQ0EsMEJBRTRLLDZCQUE4Qiw2QkFBOEIsNkJBQThCLDZCQUE4Qiw2QkFBOEIsNkJBQ2xVLFdBQ0EsZ0JBQ0Esa0JBQ0Esb0NBQ0EsVUFLc0IsNkJBQ3RCLGVBRXNCLDRCQUN0QixXQUNBLGVBQ0Esa0JBQ0Esb0NBQ0EsVUFFMkUsYUFBYywyQkFBNEIsa0JBQW1CLGdDQUN4SSxnQkFNZ0csZ0NBQXRCLHFCQUF5RCxtQ0FDbkksbUJBRW9HLGlDQUF2QixzQkFBMkQsb0NBQ3hJLG9CQU8yWSx1Q0FBOUMsMkNBQTFCLHlCQUF1Tyw0Q0FBbkQsZ0RBQS9CLDhCQUFyQyxrQ0FBaEosNkJBQ25TLGtCQUNBLFVBQ0EsZ0JBQ0EsZUFPa0IsUUFBUyxxQkFDM0IsMkJBQ0Esc0JBQ0Esa0JBQ0EscUJBQ0EsWUFDQSxVQUNBLGtCQUNBLFdBT0MsV0FDRCxxQkFDQSxXQUNBLFNBQ0EsVUFDQSxVQUVNLHVCQUNOLDJCQUVNLHNCQUNOLDJCQUd3QiwwQ0FJRCx5Q0FIdkIsY0FDQSxlQU1tRCw0QkFBK0IsNEJBQ2xGLGVBRU8seUJBQ1AsY0FDQSxXQUNBLGtCQUNBLFVBQ0EsV0FFTyxpQkFDUCxXQUVZLHNCQUNaLG1CQUUwQixpQ0FDMUIsYUFFaUQsNkJBQ3JCLFdBSTNCLG1CQUlELHFDQUNBLGVBQ0EsZ0JBQ0EsWUFDQSxpQkFDQSxzQkFSQywrQkFDRyxZQWtCdVIsOEJBQTVCLDJCQUF2QyxzQ0FBcEMsbUNBQWpCLGdCQUFkLGFBQ3JKLDZCQUdKLFlBQ0ksaUJBQ0EsMkJBQ0EsZ0JBQ0Esc0JBS0oscUJBREEsZ0NBQ0ksNkJDekxKLFFBQ0ksa0JBQ0EsY0FDQSxZQUNBLGFBQ0EsU0FHSixVQUNJLDRDQUNBLG9DQUNBLGFBQ0Esa0JBQ0EsWUFHSixNQUNJLHVCQUNBLG9CQUNBLCtFQUNBLHVFQUNBLHFCQUdKLDBCQUNJLEtBQ0ksaUNBQ0EsMEJBSVIsa0JBQ0ksS0FDSSxpQ0FDQSwwQkFHUix3QkFDSSxHQUNJLHVCQUNBLG9CQUVKLElBQ0ksd0JBQ0Esc0JBRUosS0FDSSx3QkFDQSx3QkFHUixnQkFDSSxHQUNJLHVCQUNBLG9CQUVKLElBQ0ksd0JBQ0Esc0JBRUosS0FDSSx3QkFDQSx3QkFHUix5QkFDVSxHQUFOLEtBQ0ksZUFFSixJQUNJLGVBRUosSUFDSSxlQUVKLElBQUssSUFDRCxnQkFHUixpQkFDVSxHQUFOLEtBQ0ksZUFFSixJQUNJLGVBRUosSUFDSSxlQUVKLElBQUssSUFDRCxnQkN0RlIsT0FDSSw0QkFDQSwwQkFDQSxZQUNBLHdDQUNBLGdDQUVHLGFBQ0gsY0FDQSxlQUNBLGdCQUNBLGNBRUcsbUJBQ0gsU0FDQSxtQkFDQSxjQUVHLGlCQUNILHNCQUVXLHVCQUNYLGtCQ3RCa0cscUJBQTVDLHFCQUFzQixxQkFDNUUsV0FDQSwwRUFDQSxZQUNBLE9BQ0Esa0JBQ0EsTUFDQSxVQUNBLFdBRTBJLDZCQUE1RCw2QkFBOEIsNkJBQzVHLFdBQ0EsMEVBQ0EsWUFDQSxPQUNBLGtCQUNBLE1BQ0EsVUFDQSxXQ3BCSixhQUNJLFlBQ0EsVUFDQSxXQUNBLGtCQUdKLFVBQ0ksU0FDQSxVQUNBLFdBQ0Esa0JBR0UsY0FDRixTQUNBLFVBQ0EsWUFDQSxXQUdpQiwrQkFDakIsZ0JBQ0EsaUJBQ0EsV0FHc0Isb0NBQ3RCLHNCQUNBLHFCQUdKLHFCQUNJLG9CQ25DSixRQUNJLG9DQUNBLDRCQUVKLE1BQ0ksVUFDQSx3QkFDQSw2Q0FDQSxxQ0FDQSw4Q0FDQSxzQ0FFSixXQUNJLDZDQUNBLHFDQUNBLGtFQUNBLDBEQUNBLDhDQUNBLHNDQUVKLFFBQ0ksNkNBQ0EscUNBQ0EscUZBQ0EsNkVBQ0EsOENBQ0Esc0NBRUosYUFDSSw2Q0FDQSxxQ0FDQSxtRkFDQSwyRUFDQSw4Q0FDQSxzQ0FFTyxtQkFDUCxVQUNBLDBCQUNBLDZEQUNBLHFEQUNBLDhDQUNBLHNDQUVKLE1BQ0ksNkNBQ0EscUNBQ0EsNkRBQ0EscURBQ0EsOENBQ0Esc0NBRUMsU0FDRCxtRUFDQSwyREFFSixNQUNJLDZDQUNBLHFDQUNBLGdGQUNBLHdFQUNBLDhDQUNBLHNDQUVDLFNBQ0QsaUZBQ0EseUVBQ0EsOENBQ0Esc0NBRUosTUFDSSw2Q0FDQSxxQ0FDQSxtREFDQSwyQ0FDQSw4Q0FDQSxzQ0FFQyxTQUNELG1EQUNBLDJDQUNBLDhDQUNBLHNDQUVKLE1BQ0ksNkNBQ0EscUNBQ0EsOERBQ0Esc0RBQ0EsOENBQ0Esc0NBRUMsU0FDRCxvRUFDQSw0REFDQSw4Q0FDQSxzQ0M1RkosTUFDSSxnQkFFSixRQUNJLGdCQUVKLFdBQ0ksV0FFSixZQUNJLFlBRTJCLGdCQUFpQiw4QkFDNUMsYUFFSixrQkFDSSxrQkFDQSxtQkFFSixrQkFDSSxpQkFDQSxvQkFFSixTQUNJLG1CQUNBLGlCQUVKLFlBQ0ksMEJBQ0EsaUJBRUosV0FDSSxZQUVKLFFBQ0ksa0JBRThJLGdCQUFpQix1QkFBMEMsbUJBQWxCLGlCQUFzQyxpQkFBakcsaUJBQWIsWUFDL0csVUFFcUQsTUFBbUIsYUFBYyxrQkFBbUIsV0FBN0MsV0FDNUQsZ0JBQ0Esd0JBT1MsWUFBYSxTQUN0Qix1QkFHSixnQkFDSSw4QkFHSixhQUNJLDJCQUdKLGNBQ0ksNEJBR0osZUFDSSw2QkFHSixtQkFDSSwyQkFHSixnQkFDSSx3QkFHSixpQkFDSSx5QkFHSixrQkFDSSwwQkFPSixJQUNJLHVDQU9hLHlCQUNiLHlCQUdhLG1DQUNiLHlCQUdKLE9BQ0ksY0FFSixVQUNJLGVDeEdZLHNCQUNaLDhCQUNBLGtDQUNBLDBCQUNBLGtFQUNBLGtEQUdnQyw4Q0FDaEMsZ0JBQ0EsNkJBQ0EsaUNBQ0EseUJBS21CLG9CQUN2Qix1QkFBSSxpQ0FDQSxxQ0FDQSw2QkFLaUIsb0JBQ3JCLDJCQUFJLG1CQUdZLHNCQUNaLGtCQUlBLFVBQ0Esd0JBS1csb0JBQ2YscUJBQUksNkJBQ0EsaUNBQ0EseUJBQ0EsdUNBQ0EsK0JBQ0EsVUFDQSwwQkFNQSxtQkFHaUIseUJBQ2pCLFVBQ0EsMEJBRzZCLHdDQUM3QixVQUNBLHdCQUNBLHVDQUNBLCtCQUdrQyw2Q0FDbEMsVUFDQSwwQkFHWSxxQkFDWiw2QkFDQSxpQ0FDQSx5QkMvRUoscUJBQ0ksd0JDUzhCLDhDQUM5QixnQkFDQSw2QkFDQSxpQ0FDQSx5QkFZWSxzQkFDWiw2QkFDQSxpQ0FDQSx5QkFDQSxVQUNBLHdCQUVpQix5QkFDakIsVUFDQSwwQkFFWSxzQkFDWixrQkFJQSw4QkFDQSxrQ0FDQSwwQkFDQSxrRUFDQSxrREE4QzJFLG9CQUFxQixxQkFDaEcsNkJBQ0EsaUNBQ0EseUJBQ0EsdUNBQ0EsK0JBR0EsbUJBRTJDLHlCQUMzQyxVQUNBLDBCQUVzRSx3Q0FDdEUsVUFDQSx3QkFDQSx1Q0FDQSwrQkFFZ0YsNkNBQ2hGLFVBQ0EsMEJBRWtDLHFCQUNsQyw2QkFDQSxpQ0FDQSx5QkNwSG1CLDZCQUNuQiw4QkFDQSxrQ0FDQSwwQkFLcUMscURBQ3JDLGdCQUNBLDZCQUNBLGlDQUNBLHlCQUt3QiwyQkFDNUIsa0NBQUksaUNBQ0EscUNBQ0EsNkJBTUEsbUJBR08sMEJBQ1AsaUJBR21CLDZCQUNuQixrQkFJQSwwQ0FDQSw4Q0FDQSxzQ0FDQSxrRUFDQSxrREFDQSxVQUNBLHdCQUtrQiwyQkFDdEIsNEJBQUksNkJBQ0EsaUNBQ0EseUJBQ0EsdUNBQ0EsK0JBQ0EsVUFDQSwwQkFNQSxtQkFHd0IsZ0NBQ3hCLFVBQ0EsMEJBR29DLCtDQUNwQyxVQUNBLHdCQUNBLHVDQUNBLCtCQUd5QyxvREFDekMsVUFDQSwwQkFHbUIsNEJBQ25CLDZCQUNBLGlDQUNBLHlCQ3JGeUIsbUNBQ3pCLDhCQUNBLGtDQUNBLDBCQUs2QywyREFDN0MsZ0JBQ0EsNkJBQ0EsaUNBQ0EseUJBS2dDLGlDQUNwQyxvQ0FBSSxpQ0FDQSxxQ0FDQSw2QkFLOEIsaUNBQ2xDLHdDQUFJLG1CQUd5QixtQ0FDekIsa0JBSUEseUNBQ0EsNkNBQ0EscUNBQ0Esa0VBQ0Esa0RBQ0EsVUFDQSx3QkFLd0IsaUNBQzVCLGtDQUFJLDZCQUNBLGlDQUNBLHlCQUNBLHVDQUNBLCtCQUNBLFVBQ0EsMEJBTUEsbUJBRzhCLHNDQUM5QixVQUNBLDBCQUcwQyxxREFDMUMsVUFDQSx3QkFDQSx1Q0FDQSwrQkFHK0MsMERBQy9DLFVBQ0EsMEJBR3lCLGtDQUN6Qiw2QkFDQSxpQ0FDQSx5QkNsRkosZUFGSyxVQUNELFlBQ0EsZ0JBQ0Esa0JBSUosVUFDSSxtREFDQSwyQ0FDQSxxQ0FDQSw2QkFPSixpQkFGZSxZQUNYLFVBQ0Esd0JBSVEsd0JBQ1osbUJBQUksWUFDQSxXQUNBLHlCQUNBLDZDQUNBOzs7Ozs7Ozs7O0FDdEJvSCxjQUEzQyxZQUFhLGFBQWMsZUFBakMsS0FBZ0UsZUFDckksa0JBQ0EsZUFFQSxnQkFDQSx5QkFDQSxzQkFDQSxxQkFDQSxpQkFDQSx3Q0FDQSxvQ0FDQSxpQ0FDQSwrQkFDQSw0QkFFRixZQUNFLGtCQUNBLGtCQUNBLFlBQ0EsYUFDQSxpQkFDQSxrQkFDQSxVQUNBLHNDQUNBLG9DQUNBLGlDQUNBLCtCQUNBLDRCQUNBLHNEQUNBLGdEQUNBLDRDQUNBLHNDQUNBLDJCQUNBLHdCQUNBLHVCQUNBLHNCQUNBLG1CQUNBLG9CQUVGLGtCQUNFLGtDQUNBLCtCQUNBLDZCQUNBLDBCQVNGLGNBRkEsWUFDQSxhQUVBLGVBQ0EsWUFDQSxZQUpFLGdDQUNBLDZCQUNBLDRCQUNBLDJCQUNBLHdCQXNCRix3QkFRQSxxQkFYYyxzQkFRZCxtQkFQQSx1QkFRQSxvQkFQQSx5QkFRQSxzQkFOQSxzQkFRQSxtQkFOQSxzQkFRQSxtQkFUQSxlQVFBLFlBTkEseUJBUUEsc0JBZEUsdUVBOEJGLGNBRUEsbUJBREEsc0JBVkEsWUFFQSxpQkFEQSxvQkFFQSxhQUVBLGtCQURBLHFCQUVBLGVBRUEsb0JBREEsdUJBVkEsWUFlQSxrQkFiQSxpQkFEQSxvQkFBRSxtQkFDQSxzQkFDQSxlQUNBLFlBQ0EsVUFHQSxlQUNBLGtCQUNBLHFCQUNBLFVBRUYsWUFDRSxrQkFDQSxrQkFFRixrQkFDRSxTQUNBLGtCQUVGLG1CQUNFLGtCQUNBLHNCQUVnQiw4QkFDaEIsVUFFaUIscUNBQ2pCLGtCQUNBLE1BQ0EsT0FDQSxVQUVGLFlBQ0Usa0JBQ0EsWUFDQSxhQUNBLGtCQUNBLGtCQUVGLFdBQ0Usd0JBQ0EsbURBQ0EsMkNBRVEsa0JBQ1IsaURBQ0EseUNBRUYsV0FDRSxjQUVGLFlBQ0UsVUFnQlEsMEJBTVYsc0JBREEsa0JBSkEsOEJBQ0EsOEJBQ0EsK0JBQ0EsNEJBSEUsZ0NBR0YsVUFDRSxrQkNqTEYsRUFDSSxzRUFHSixTQUNJLGtCQUdKLEVBQUksZUFFTyxxQkFDVCxTQU1GLEtBQ0ksbUJBQ0EsVUFFQyxhQUNILGdCQUNBLGVBQ0EsZUFDQSxnQkFDQSxnQkFDQSxXQUVvQixtQ0FDbEIsUUFDQSxNQU9FLFlBS0EsYUFKTixrQkFLQSxtQkFMRSxVQXdDRixzQkFvQkEsZ0NBUEEsNkJBUEEsNEJBSEEsY0FxQkEsd0JBUEEscUJBUEEsb0JBUkEscUJBcUJBLCtCQVBBLDRCQVBBLDJCQVZBLGlCQXNCQSwyQkFQQSx3QkFQQSx1QkFOQSxpQkFxQkEsMkJBUEEsd0JBUEEsdUJBVmdCLGFBcUJoQix1QkFQQSxvQkFQQSxtQkFEQSxpQkFxQkEsMkJBUEEsd0JBUEEsdUJBWkkseUJBQ0EsV0ErQkosMEJBcUJBLG9DQVJBLGlDQU5BLGdDQUpBLGtCQXFCQSw0QkFQQSx5QkFQQSx3QkFSQSx5QkFxQkEsbUNBUEEsZ0NBUEEsK0JBVkEscUJBcUJBLCtCQU5BLDRCQVJBLDJCQUxBLHFCQXFCQSwrQkFQQSw0QkFQQSwyQkFWb0IsaUJBcUJwQiwyQkFQQSx3QkFQQSx1QkFEQSxxQkFxQkEsK0JBUEEsNEJBUEEsMkJBWkkseUJBQ0EsV0ErQkosMEJBcUJBLG9DQVBBLGlDQVBBLGdDQUpBLGtCQXFCQSw0QkFQQSx5QkFQQSx3QkFSQSx5QkFxQkEsbUNBUEEsZ0NBUEEsK0JBVkEscUJBcUJBLCtCQVBBLDRCQVBBLDJCQUxBLHFCQXFCQSwrQkFQQSw0QkFQQSwyQkFWb0IsaUJBcUJwQiwyQkFQQSx3QkFQQSx1QkFEQSxxQkFxQkEsK0JBUEEsNEJBUEEsMkJBWkkseUJBQ0EsV0ErQkosa0JBcUJBLDRCQVBBLHlCQVBBLHdCQUpBLFVBcUJBLG9CQVBBLGlCQVBBLGdCQVJBLGlCQXFCQSwyQkFQQSx3QkFQQSx1QkFWQSxhQXFCQSx1QkFQQSxvQkFQQSxtQkFSWSxTQXFCWixtQkFQQSxnQkFQQSxlQURBLGFBcUJBLHVCQVBBLG9CQVBBLG1CQVZBLGFBcUJBLHVCQVBBLG9CQVBBLG1CQVRJLHlCQUNBLFdBK0JKLHNCQXFCQSxnQ0FQQSw2QkFQQSw0QkFKQSxjQXFCQSx3QkFQQSxxQkFQQSxvQkFSQSxxQkFxQkEsK0JBUEEsNEJBUEEsMkJBVkEsaUJBcUJBLDJCQVBBLHdCQVBBLHVCQVJnQixhQXFCaEIsdUJBUEEsb0JBUEEsbUJBREEsaUJBcUJBLDJCQVBBLHdCQVBBLHVCQVZBLGlCQXFCQSwyQkFQQSx3QkFQQSx1QkFUSSx5QkFDQSxXQStCSixzQkFxQkEsZ0NBUEEsNkJBUEEsNEJBSkEsY0FxQkEsd0JBUEEscUJBUEEsb0JBUkEscUJBcUJBLCtCQVBBLDRCQVBBLDJCQVZBLGlCQXFCQSwyQkFQQSx3QkFQQSx1QkFSZ0IsYUFxQmhCLHVCQVBBLG9CQVBBLG1CQURBLGlCQXFCQSwyQkFQQSx3QkFQQSx1QkFWQSxpQkFxQkEsMkJBUEEsd0JBUEEsdUJBVEkseUJBQ0EsV0ErQkosbUJBcUJBLDZCQVBBLDBCQVBBLHlCQUpBLFdBcUJBLHFCQVBBLGtCQVBBLGlCQVJBLGtCQXFCQSw0QkFQQSx5QkFQQSx3QkFWQSxjQXFCQSx3QkFQQSxxQkFQQSxvQkFMQSxjQXFCQSx3QkFQQSxxQkFQQSxvQkFWYSxVQXFCYixvQkFQQSxpQkFQQSxnQkFEQSxjQXFCQSx3QkFQQSxxQkFQQSxvQkFaSSx5QkFDQSxXQStCSix1QkFxQkEsaUNBUEEsOEJBUEEsNkJBSkEsZUFxQkEseUJBUEEsc0JBUEEscUJBUkEsc0JBcUJBLGdDQVBBLDZCQVBBLDRCQVZBLGtCQXFCQSw0QkFQQSx5QkFQQSx3QkFMQSxrQkFxQkEsNEJBUEEseUJBUEEsd0JBVmlCLGNBcUJqQix3QkFQQSxxQkFQQSxvQkFEQSxrQkFxQkEsNEJBUEEseUJBUEEsd0JBWkkseUJBQ0EsV0ErQkosdUJBcUJBLGlDQVBBLDhCQVBBLDZCQUpBLGVBcUJBLHlCQVBBLHNCQVBBLHFCQVJBLHNCQXFCQSxnQ0FQQSw2QkFQQSw0QkFWQSxrQkFxQkEsNEJBUEEseUJBUEEsd0JBTEEsa0JBcUJBLDRCQVBBLHlCQVBBLHdCQVZpQixjQXFCakIsd0JBUEEscUJBUEEsb0JBREEsa0JBcUJBLDRCQVBBLHlCQVBBLHdCQVpJLHlCQUNBLFdBNkJZLGFBcUJoQix1QkFQQSxvQkFQQSxtQkFEQSxpQkFxQkEsMkJBUEEsd0JBUEEsdUJBWEEsc0JBcUJBLGdDQVBBLDZCQVBBLDRCQUpBLGNBcUJBLHdCQVBBLHFCQVBBLG9CQVhBLGlCQXFCQSwyQkFQQSx3QkFQQSx1QkFKQSxxQkFxQkEsK0JBUEEsNEJBUEEsMkJBUkEsaUJBcUJBLDJCQVBBLHdCQVBBLHVCQVRJLHlCQUNBLFdBNkJnQixpQkFxQnBCLDJCQVBBLHdCQVBBLHVCQURBLHFCQXFCQSwrQkFQQSw0QkFQQSwyQkFYQSwwQkFxQkEsb0NBUEEsaUNBUEEsZ0NBSkEsa0JBcUJBLDRCQVBBLHlCQVBBLHdCQVhBLHFCQXFCQSwrQkFQQSw0QkFQQSwyQkFKQSx5QkFxQkEsbUNBUEEsZ0NBUEEsK0JBUkEscUJBcUJBLCtCQVBBLDRCQVBBLDJCQVRJLHlCQUNBLFdBNkJnQixpQkFxQnBCLDJCQVBBLHdCQVBBLHVCQURBLHFCQXFCQSwrQkFQQSw0QkFQQSwyQkFKQSw0QkFQQSwwQkFxQkEsb0NBUEEsaUNBWEEsa0JBcUJBLDRCQVBBLHlCQVBBLHdCQVhBLHFCQXFCQSwrQkFQQSw0QkFQQSwyQkFKQSx5QkFxQkEsbUNBUEEsZ0NBUEEsK0JBUkEscUJBcUJBLCtCQVBBLDRCQVBBLDJCQVRJLHlCQUNBLFdBK0JKLHVCQXFCQSxpQ0FQQSw4QkFQQSw2QkFKQSxlQXFCQSx5QkFQQSxzQkFQQSxxQkFSQSxzQkFxQkEsZ0NBUEEsNkJBUEEsNEJBVkEsa0JBcUJBLDRCQVBBLHlCQVBBLHdCQVJpQixjQXFCakIsd0JBUEEscUJBUEEsb0JBREEsa0JBcUJBLDRCQVBBLHlCQVBBLHdCQVZBLGtCQXFCQSw0QkFQQSx5QkFQQSx3QkFUSSx5QkFDQSxXQStCSiwyQkFxQkEscUNBUEEsa0NBUEEsaUNBSkEsbUJBcUJBLDZCQVBBLDBCQVBBLHlCQVJBLDBCQXFCQSxvQ0FQQSxpQ0FQQSxnQ0FWQSxzQkFxQkEsZ0NBUEEsNkJBUEEsNEJBUnFCLGtCQXFCckIsNEJBUEEseUJBUEEsd0JBREEsc0JBcUJBLGdDQVBBLDZCQVBBLDRCQVZBLHNCQXFCQSxnQ0FQQSw2QkFQQSw0QkFUSSx5QkFDQSxXQStCSiwyQkFxQkEscUNBUEEsa0NBUEEsaUNBSkEsbUJBcUJBLDZCQVBBLDBCQVBBLHlCQVJBLDBCQXFCQSxvQ0FQQSxpQ0FQQSxnQ0FWQSxzQkFxQkEsZ0NBUEEsNkJBUEEsNEJBUnFCLGtCQXFCckIsNEJBUEEseUJBUEEsd0JBREEsc0JBcUJBLGdDQVBBLDZCQVBBLDRCQVZBLHNCQXFCQSxnQ0FQQSw2QkFQQSw0QkFUSSx5QkE2QmEsY0FxQmpCLHdCQVBBLHFCQVBBLG9CQURBLGtCQXFCQSw0QkFQQSx5QkFQQSx3QkFYQSx1QkFxQkEsaUNBUEEsOEJBUEEsNkJBSkEsZUFxQkEseUJBUEEsc0JBUEEscUJBWEEsa0JBcUJBLDRCQVBBLHlCQVBBLHdCQUpBLHNCQXFCQSxnQ0FQQSw2QkFQQSw0QkFSQSxrQkFxQkEsNEJBUEEseUJBUEEsd0JBVEkseUJBQ0EsV0E2QmlCLGtCQXFCckIsNEJBUEEseUJBUEEsd0JBREEsc0JBcUJBLGdDQVBBLDZCQVBBLDRCQVhBLDJCQXFCQSxxQ0FQQSxrQ0FQQSxpQ0FKQSxtQkFxQkEsNkJBUEEsMEJBUEEseUJBWEEsc0JBcUJBLGdDQVBBLDZCQVBBLDRCQUpBLDBCQXFCQSxvQ0FQQSxpQ0FQQSxnQ0FSQSxzQkFxQkEsZ0NBUEEsNkJBUEEsNEJBVEkseUJBQ0EsV0E2QmlCLGtCQXFCckIsNEJBUEEseUJBUEEsd0JBREEsc0JBcUJBLGdDQVBBLDZCQVBBLDRCQVhBLDJCQW9CQSxxQ0FOQSxrQ0FQQSxpQ0FKQSxtQkFxQkEsNkJBUEEsMEJBUEEseUJBWEEsc0JBc0JBLGdDQVJBLDZCQVBBLDRCQUpBLDBCQXFCQSxvQ0FQQSxpQ0FQQSxnQ0FSQSxzQkFxQkEsZ0NBUEEsNkJBUEEsNEJBVEkseUJBQ0EsV0ErQkosb0JBcUJBLDhCQVBBLDJCQVBBLDBCQUpBLFlBcUJBLHNCQVBBLG1CQVBBLGtCQVJBLG1CQXFCQSw2QkFQQSwwQkFQQSx5QkFWQSxlQXFCQSx5QkFQQSxzQkFQQSxxQkFMQSxlQXFCQSx5QkFQQSxzQkFQQSxxQkFWYyxXQXFCZCxxQkFQQSxrQkFQQSxpQkFEQSxlQXFCQSx5QkFQQSxzQkFQQSxxQkFaSSx5QkFDQSxXQWFNLFVBQ1YsWUFVYyxjQUNkLGdCQUtBLHFCQUNBLHVCQUpBLG9CQUNBLHNCQVRBLGlCQUNBLG1CQUpBLGdCQUNBLGtCQUhJLGNBcUJVLGNBQ2QsZ0JBS0EscUJBQ0EsdUJBSkEsb0JBQ0Esc0JBSEksY0FxQk0sVUFDVixZQUtBLGlCQUNBLG1CQUpBLGdCQUNBLGtCQUhJLGNBVU0sVUFDVixZQUtBLGlCQUNBLG1CQUpBLGdCQUNBLGtCQUhJLGNBVUcsT0FDUCxTQUtBLGNBQ0EsZ0JBSkEsYUFDQSxlQUhJLGNBVU8sV0FDWCxhQUtBLGtCQUNBLG9CQUpBLGlCQUNBLG1CQUhJLGNBVU8sV0FDWCxhQUtBLGtCQUNBLG9CQUpBLGlCQUNBLG1CQUhJLGNBVU0sVUFDVixZQUtBLGlCQUNBLG1CQUpBLGdCQUNBLGtCQUhJLGNBVVUsY0FDZCxnQkFLQSxxQkFDQSx1QkFKQSxvQkFDQSxzQkFISSxjQVVVLGNBQ2QsZ0JBS0EscUJBQ0EsdUJBSkEsb0JBQ0Esc0JBSEksY0FVTyxXQUNYLGFBS0Esa0JBQ0Esb0JBSkEsaUJBQ0EsbUJBSEksY0FVVyxlQUNmLGlCQUtBLHNCQUNBLHdCQUpBLHFCQUNBLHVCQUhJLGNBVVcsZUFDZixpQkFLQSxzQkFDQSx3QkFKQSxxQkFDQSx1QkFISSxjQVVPLFdBQ1gsYUFLQSxrQkFDQSxvQkFKQSxpQkFDQSxtQkFISSxjQVVXLGVBQ2YsaUJBS0Esc0JBQ0Esd0JBSkEscUJBQ0EsdUJBSEksY0FVVyxlQUNmLGlCQUtBLHNCQUNBLHdCQUpBLHFCQUNBLHVCQUhJLGNBVUksUUFDUixVQUtBLGVBQ0EsaUJBSkEsY0FDQSxnQkFISSxjQVVHLE9BQ1AsU0FLQSxjQUNBLGdCQUpBLGFBQ0EsZUFISSxXQVVFLE1BQ04sUUFLQSxhQUNBLGVBSkEsWUFDQSxjQUhJLFdBU0osY0FDSSxrQkFHK0IsaUNBQy9CLFNBQ0EsbUJBQ0Esa0JBQ0EsaUNBQ0EsY0FDQSxVQU9KLFNBQ0ksYUFRSyxZQUNULFlBQ0EsWUFDQSxZQUNBLFlBQ0EsWUFKSSxXQUNBLGtCQUdLLFdBQ0wsMkJBQ0EsZ0JBY0osbUJBSlEsYUFDUiwyQkFDQSxrQkFDQSxnQ0FGSSxrQkFLUSxNQUNaLDRCQUNBLDBCQURJLDZCQUlVLFlBQ2QsaUJBQUksV0FHVSxvQkFDVix1Q0FHUSwwQkFDUixXQU1vQixzQ0FDeEIsMENBQ0EsMkNBQ0EsZ0NBRkksbUJBQ0EsZUFHSixNQUNJLDZCQUtKLDhCQURtQiwyQkFDZixnQkFNSixTQUNJLFVBQ0Esa0JBQ0EsVUFDQSx5Q0FDQSw2REFDQSxRQUVJLGtCQUNKLFVBQ0Esd0NBQ0EsNkRBR0ksa0JBQ0osVUFDQSx5Q0FDQSw2REFNSixRQUNJIiwiZmlsZSI6ImlvbmljLm1hdGVyaWFsLm1pbi5jc3MiLCJzb3VyY2VzQ29udGVudCI6W10sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 */ \ No newline at end of file diff --git a/www/lib/ionic/css/ionic.min.css b/www/lib/ionic/css/ionic.min.css index 52c30b07b2fe8e8415b5aa2f16e19a1fbce59e55..d72dfc1cd8ce62f37bee8a4d90d8f799194feaf0 100644 --- a/www/lib/ionic/css/ionic.min.css +++ b/www/lib/ionic/css/ionic.min.css @@ -1,8 +1,8 @@ -/*! - * Copyright 2014 Drifty Co. +@charset "UTF-8";/*! + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -20,4 +20,4 @@ Material Design Icons: https://github.com/google/material-design-icons used under CC BY http://creativecommons.org/licenses/by/4.0/ Modified icons to fit ionicon’s grid from original. -*/@font-face{font-family:Ionicons;src:url(../fonts/ionicons.eot?v=2.0.1);src:url(../fonts/ionicons.eot?v=2.0.1#iefix) format("embedded-opentype"),url(../fonts/ionicons.ttf?v=2.0.1) format("truetype"),url(../fonts/ionicons.woff?v=2.0.1) format("woff"),url(../fonts/ionicons.woff) format("woff"),url(../fonts/ionicons.svg?v=2.0.1#Ionicons) format("svg");font-weight:400;font-style:normal}.ion,.ion-alert-circled:before,.ion-alert:before,.ion-android-add-circle:before,.ion-android-add:before,.ion-android-alarm-clock:before,.ion-android-alert:before,.ion-android-apps:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down:before,.ion-android-arrow-dropdown-circle:before,.ion-android-arrow-dropdown:before,.ion-android-arrow-dropleft-circle:before,.ion-android-arrow-dropleft:before,.ion-android-arrow-dropright-circle:before,.ion-android-arrow-dropright:before,.ion-android-arrow-dropup-circle:before,.ion-android-arrow-dropup:before,.ion-android-arrow-forward:before,.ion-android-arrow-up:before,.ion-android-attach:before,.ion-android-bar:before,.ion-android-bicycle:before,.ion-android-boat:before,.ion-android-bookmark:before,.ion-android-bulb:before,.ion-android-bus:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-cancel:before,.ion-android-car:before,.ion-android-cart:before,.ion-android-chat:before,.ion-android-checkbox-blank:before,.ion-android-checkbox-outline-blank:before,.ion-android-checkbox-outline:before,.ion-android-checkbox:before,.ion-android-checkmark-circle:before,.ion-android-clipboard:before,.ion-android-close:before,.ion-android-cloud-circle:before,.ion-android-cloud-done:before,.ion-android-cloud-outline:before,.ion-android-cloud:before,.ion-android-color-palette:before,.ion-android-compass:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-contract:before,.ion-android-create:before,.ion-android-delete:before,.ion-android-desktop:before,.ion-android-document:before,.ion-android-done-all:before,.ion-android-done:before,.ion-android-download:before,.ion-android-drafts:before,.ion-android-exit:before,.ion-android-expand:before,.ion-android-favorite-outline:before,.ion-android-favorite:before,.ion-android-film:before,.ion-android-folder-open:before,.ion-android-folder:before,.ion-android-funnel:before,.ion-android-globe:before,.ion-android-hand:before,.ion-android-hangout:before,.ion-android-happy:before,.ion-android-home:before,.ion-android-image:before,.ion-android-laptop:before,.ion-android-list:before,.ion-android-locate:before,.ion-android-lock:before,.ion-android-mail:before,.ion-android-map:before,.ion-android-menu:before,.ion-android-microphone-off:before,.ion-android-microphone:before,.ion-android-more-horizontal:before,.ion-android-more-vertical:before,.ion-android-navigate:before,.ion-android-notifications-none:before,.ion-android-notifications-off:before,.ion-android-notifications:before,.ion-android-open:before,.ion-android-options:before,.ion-android-people:before,.ion-android-person-add:before,.ion-android-person:before,.ion-android-phone-landscape:before,.ion-android-phone-portrait:before,.ion-android-pin:before,.ion-android-plane:before,.ion-android-playstore:before,.ion-android-print:before,.ion-android-radio-button-off:before,.ion-android-radio-button-on:before,.ion-android-refresh:before,.ion-android-remove-circle:before,.ion-android-remove:before,.ion-android-restaurant:before,.ion-android-sad:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share-alt:before,.ion-android-share:before,.ion-android-star-half:before,.ion-android-star-outline:before,.ion-android-star:before,.ion-android-stopwatch:before,.ion-android-subway:before,.ion-android-sunny:before,.ion-android-sync:before,.ion-android-textsms:before,.ion-android-time:before,.ion-android-train:before,.ion-android-unlock:before,.ion-android-upload:before,.ion-android-volume-down:before,.ion-android-volume-mute:before,.ion-android-volume-off:before,.ion-android-volume-up:before,.ion-android-walk:before,.ion-android-warning:before,.ion-android-watch:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-backspace-outline:before,.ion-backspace:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-bowtie:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox-working:before,.ion-chatbox:before,.ion-chatboxes:before,.ion-chatbubble-working:before,.ion-chatbubble:before,.ion-chatbubbles:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-checkmark:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close-circled:before,.ion-close-round:before,.ion-close:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code-download:before,.ion-code-working:before,.ion-code:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-crop:before,.ion-cube:before,.ion-disc:before,.ion-document-text:before,.ion-document:before,.ion-drag:before,.ion-earth:before,.ion-easel:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email-unread:before,.ion-email:before,.ion-erlenmeyer-flask-bubbles:before,.ion-erlenmeyer-flask:before,.ion-eye-disabled:before,.ion-eye:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash-off:before,.ion-flash:before,.ion-folder:before,.ion-fork-repo:before,.ion-fork:before,.ion-forward:before,.ion-funnel:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy-outline:before,.ion-happy:before,.ion-headphone:before,.ion-heart-broken:before,.ion-heart:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-help:before,.ion-home:before,.ion-icecream:before,.ion-image:before,.ion-images:before,.ion-information-circled:before,.ion-information:before,.ion-ionic:before,.ion-ios-alarm-outline:before,.ion-ios-alarm:before,.ion-ios-albums-outline:before,.ion-ios-albums:before,.ion-ios-americanfootball-outline:before,.ion-ios-americanfootball:before,.ion-ios-analytics-outline:before,.ion-ios-analytics:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-left:before,.ion-ios-arrow-right:before,.ion-ios-arrow-thin-down:before,.ion-ios-arrow-thin-left:before,.ion-ios-arrow-thin-right:before,.ion-ios-arrow-thin-up:before,.ion-ios-arrow-up:before,.ion-ios-at-outline:before,.ion-ios-at:before,.ion-ios-barcode-outline:before,.ion-ios-barcode:before,.ion-ios-baseball-outline:before,.ion-ios-baseball:before,.ion-ios-basketball-outline:before,.ion-ios-basketball:before,.ion-ios-bell-outline:before,.ion-ios-bell:before,.ion-ios-body-outline:before,.ion-ios-body:before,.ion-ios-bolt-outline:before,.ion-ios-bolt:before,.ion-ios-book-outline:before,.ion-ios-book:before,.ion-ios-bookmarks-outline:before,.ion-ios-bookmarks:before,.ion-ios-box-outline:before,.ion-ios-box:before,.ion-ios-briefcase-outline:before,.ion-ios-briefcase:before,.ion-ios-browsers-outline:before,.ion-ios-browsers:before,.ion-ios-calculator-outline:before,.ion-ios-calculator:before,.ion-ios-calendar-outline:before,.ion-ios-calendar:before,.ion-ios-camera-outline:before,.ion-ios-camera:before,.ion-ios-cart-outline:before,.ion-ios-cart:before,.ion-ios-chatboxes-outline:before,.ion-ios-chatboxes:before,.ion-ios-chatbubble-outline:before,.ion-ios-chatbubble:before,.ion-ios-checkmark-empty:before,.ion-ios-checkmark-outline:before,.ion-ios-checkmark:before,.ion-ios-circle-filled:before,.ion-ios-circle-outline:before,.ion-ios-clock-outline:before,.ion-ios-clock:before,.ion-ios-close-empty:before,.ion-ios-close-outline:before,.ion-ios-close:before,.ion-ios-cloud-download-outline:before,.ion-ios-cloud-download:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloud:before,.ion-ios-cloudy-night-outline:before,.ion-ios-cloudy-night:before,.ion-ios-cloudy-outline:before,.ion-ios-cloudy:before,.ion-ios-cog-outline:before,.ion-ios-cog:before,.ion-ios-color-filter-outline:before,.ion-ios-color-filter:before,.ion-ios-color-wand-outline:before,.ion-ios-color-wand:before,.ion-ios-compose-outline:before,.ion-ios-compose:before,.ion-ios-contact-outline:before,.ion-ios-contact:before,.ion-ios-copy-outline:before,.ion-ios-copy:before,.ion-ios-crop-strong:before,.ion-ios-crop:before,.ion-ios-download-outline:before,.ion-ios-download:before,.ion-ios-drag:before,.ion-ios-email-outline:before,.ion-ios-email:before,.ion-ios-eye-outline:before,.ion-ios-eye:before,.ion-ios-fastforward-outline:before,.ion-ios-fastforward:before,.ion-ios-filing-outline:before,.ion-ios-filing:before,.ion-ios-film-outline:before,.ion-ios-film:before,.ion-ios-flag-outline:before,.ion-ios-flag:before,.ion-ios-flame-outline:before,.ion-ios-flame:before,.ion-ios-flask-outline:before,.ion-ios-flask:before,.ion-ios-flower-outline:before,.ion-ios-flower:before,.ion-ios-folder-outline:before,.ion-ios-folder:before,.ion-ios-football-outline:before,.ion-ios-football:before,.ion-ios-game-controller-a-outline:before,.ion-ios-game-controller-a:before,.ion-ios-game-controller-b-outline:before,.ion-ios-game-controller-b:before,.ion-ios-gear-outline:before,.ion-ios-gear:before,.ion-ios-glasses-outline:before,.ion-ios-glasses:before,.ion-ios-grid-view-outline:before,.ion-ios-grid-view:before,.ion-ios-heart-outline:before,.ion-ios-heart:before,.ion-ios-help-empty:before,.ion-ios-help-outline:before,.ion-ios-help:before,.ion-ios-home-outline:before,.ion-ios-home:before,.ion-ios-infinite-outline:before,.ion-ios-infinite:before,.ion-ios-information-empty:before,.ion-ios-information-outline:before,.ion-ios-information:before,.ion-ios-ionic-outline:before,.ion-ios-keypad-outline:before,.ion-ios-keypad:before,.ion-ios-lightbulb-outline:before,.ion-ios-lightbulb:before,.ion-ios-list-outline:before,.ion-ios-list:before,.ion-ios-location-outline:before,.ion-ios-location:before,.ion-ios-locked-outline:before,.ion-ios-locked:before,.ion-ios-loop-strong:before,.ion-ios-loop:before,.ion-ios-medical-outline:before,.ion-ios-medical:before,.ion-ios-medkit-outline:before,.ion-ios-medkit:before,.ion-ios-mic-off:before,.ion-ios-mic-outline:before,.ion-ios-mic:before,.ion-ios-minus-empty:before,.ion-ios-minus-outline:before,.ion-ios-minus:before,.ion-ios-monitor-outline:before,.ion-ios-monitor:before,.ion-ios-moon-outline:before,.ion-ios-moon:before,.ion-ios-more-outline:before,.ion-ios-more:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate-outline:before,.ion-ios-navigate:before,.ion-ios-nutrition-outline:before,.ion-ios-nutrition:before,.ion-ios-paper-outline:before,.ion-ios-paper:before,.ion-ios-paperplane-outline:before,.ion-ios-paperplane:before,.ion-ios-partlysunny-outline:before,.ion-ios-partlysunny:before,.ion-ios-pause-outline:before,.ion-ios-pause:before,.ion-ios-paw-outline:before,.ion-ios-paw:before,.ion-ios-people-outline:before,.ion-ios-people:before,.ion-ios-person-outline:before,.ion-ios-person:before,.ion-ios-personadd-outline:before,.ion-ios-personadd:before,.ion-ios-photos-outline:before,.ion-ios-photos:before,.ion-ios-pie-outline:before,.ion-ios-pie:before,.ion-ios-pint-outline:before,.ion-ios-pint:before,.ion-ios-play-outline:before,.ion-ios-play:before,.ion-ios-plus-empty:before,.ion-ios-plus-outline:before,.ion-ios-plus:before,.ion-ios-pricetag-outline:before,.ion-ios-pricetag:before,.ion-ios-pricetags-outline:before,.ion-ios-pricetags:before,.ion-ios-printer-outline:before,.ion-ios-printer:before,.ion-ios-pulse-strong:before,.ion-ios-pulse:before,.ion-ios-rainy-outline:before,.ion-ios-rainy:before,.ion-ios-recording-outline:before,.ion-ios-recording:before,.ion-ios-redo-outline:before,.ion-ios-redo:before,.ion-ios-refresh-empty:before,.ion-ios-refresh-outline:before,.ion-ios-refresh:before,.ion-ios-reload:before,.ion-ios-reverse-camera-outline:before,.ion-ios-reverse-camera:before,.ion-ios-rewind-outline:before,.ion-ios-rewind:before,.ion-ios-rose-outline:before,.ion-ios-rose:before,.ion-ios-search-strong:before,.ion-ios-search:before,.ion-ios-settings-strong:before,.ion-ios-settings:before,.ion-ios-shuffle-strong:before,.ion-ios-shuffle:before,.ion-ios-skipbackward-outline:before,.ion-ios-skipbackward:before,.ion-ios-skipforward-outline:before,.ion-ios-skipforward:before,.ion-ios-snowy:before,.ion-ios-speedometer-outline:before,.ion-ios-speedometer:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-star:before,.ion-ios-stopwatch-outline:before,.ion-ios-stopwatch:before,.ion-ios-sunny-outline:before,.ion-ios-sunny:before,.ion-ios-telephone-outline:before,.ion-ios-telephone:before,.ion-ios-tennisball-outline:before,.ion-ios-tennisball:before,.ion-ios-thunderstorm-outline:before,.ion-ios-thunderstorm:before,.ion-ios-time-outline:before,.ion-ios-time:before,.ion-ios-timer-outline:before,.ion-ios-timer:before,.ion-ios-toggle-outline:before,.ion-ios-toggle:before,.ion-ios-trash-outline:before,.ion-ios-trash:before,.ion-ios-undo-outline:before,.ion-ios-undo:before,.ion-ios-unlocked-outline:before,.ion-ios-unlocked:before,.ion-ios-upload-outline:before,.ion-ios-upload:before,.ion-ios-videocam-outline:before,.ion-ios-videocam:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-wineglass-outline:before,.ion-ios-wineglass:before,.ion-ios-world-outline:before,.ion-ios-world:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-lock-combination:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-minus:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon-round:before,.ion-navicon:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paintbrush:before,.ion-paintbucket:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person-add:before,.ion-person-stalker:before,.ion-person:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-plus:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply-all:before,.ion-reply:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad-outline:before,.ion-sad:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android-outline:before,.ion-social-android:before,.ion-social-angular-outline:before,.ion-social-angular:before,.ion-social-apple-outline:before,.ion-social-apple:before,.ion-social-bitcoin-outline:before,.ion-social-bitcoin:before,.ion-social-buffer-outline:before,.ion-social-buffer:before,.ion-social-chrome-outline:before,.ion-social-chrome:before,.ion-social-codepen-outline:before,.ion-social-codepen:before,.ion-social-css3-outline:before,.ion-social-css3:before,.ion-social-designernews-outline:before,.ion-social-designernews:before,.ion-social-dribbble-outline:before,.ion-social-dribbble:before,.ion-social-dropbox-outline:before,.ion-social-dropbox:before,.ion-social-euro-outline:before,.ion-social-euro:before,.ion-social-facebook-outline:before,.ion-social-facebook:before,.ion-social-foursquare-outline:before,.ion-social-foursquare:before,.ion-social-freebsd-devil:before,.ion-social-github-outline:before,.ion-social-github:before,.ion-social-google-outline:before,.ion-social-google:before,.ion-social-googleplus-outline:before,.ion-social-googleplus:before,.ion-social-hackernews-outline:before,.ion-social-hackernews:before,.ion-social-html5-outline:before,.ion-social-html5:before,.ion-social-instagram-outline:before,.ion-social-instagram:before,.ion-social-javascript-outline:before,.ion-social-javascript:before,.ion-social-linkedin-outline:before,.ion-social-linkedin:before,.ion-social-markdown:before,.ion-social-nodejs:before,.ion-social-octocat:before,.ion-social-pinterest-outline:before,.ion-social-pinterest:before,.ion-social-python:before,.ion-social-reddit-outline:before,.ion-social-reddit:before,.ion-social-rss-outline:before,.ion-social-rss:before,.ion-social-sass:before,.ion-social-skype-outline:before,.ion-social-skype:before,.ion-social-snapchat-outline:before,.ion-social-snapchat:before,.ion-social-tumblr-outline:before,.ion-social-tumblr:before,.ion-social-tux:before,.ion-social-twitch-outline:before,.ion-social-twitch:before,.ion-social-twitter-outline:before,.ion-social-twitter:before,.ion-social-usd-outline:before,.ion-social-usd:before,.ion-social-vimeo-outline:before,.ion-social-vimeo:before,.ion-social-whatsapp-outline:before,.ion-social-whatsapp:before,.ion-social-windows-outline:before,.ion-social-windows:before,.ion-social-wordpress-outline:before,.ion-social-wordpress:before,.ion-social-yahoo-outline:before,.ion-social-yahoo:before,.ion-social-yen-outline:before,.ion-social-yen:before,.ion-social-youtube-outline:before,.ion-social-youtube:before,.ion-soup-can-outline:before,.ion-soup-can:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle-filled:before,.ion-toggle:before,.ion-transgender:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-tshirt-outline:before,.ion-tshirt:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before,.ionicons{display:inline-block;font-family:Ionicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-alert:before{content:"\f101"}.ion-alert-circled:before{content:"\f100"}.ion-android-add:before{content:"\f2c7"}.ion-android-add-circle:before{content:"\f359"}.ion-android-alarm-clock:before{content:"\f35a"}.ion-android-alert:before{content:"\f35b"}.ion-android-apps:before{content:"\f35c"}.ion-android-archive:before{content:"\f2c9"}.ion-android-arrow-back:before{content:"\f2ca"}.ion-android-arrow-down:before{content:"\f35d"}.ion-android-arrow-dropdown:before{content:"\f35f"}.ion-android-arrow-dropdown-circle:before{content:"\f35e"}.ion-android-arrow-dropleft:before{content:"\f361"}.ion-android-arrow-dropleft-circle:before{content:"\f360"}.ion-android-arrow-dropright:before{content:"\f363"}.ion-android-arrow-dropright-circle:before{content:"\f362"}.ion-android-arrow-dropup:before{content:"\f365"}.ion-android-arrow-dropup-circle:before{content:"\f364"}.ion-android-arrow-forward:before{content:"\f30f"}.ion-android-arrow-up:before{content:"\f366"}.ion-android-attach:before{content:"\f367"}.ion-android-bar:before{content:"\f368"}.ion-android-bicycle:before{content:"\f369"}.ion-android-boat:before{content:"\f36a"}.ion-android-bookmark:before{content:"\f36b"}.ion-android-bulb:before{content:"\f36c"}.ion-android-bus:before{content:"\f36d"}.ion-android-calendar:before{content:"\f2d1"}.ion-android-call:before{content:"\f2d2"}.ion-android-camera:before{content:"\f2d3"}.ion-android-cancel:before{content:"\f36e"}.ion-android-car:before{content:"\f36f"}.ion-android-cart:before{content:"\f370"}.ion-android-chat:before{content:"\f2d4"}.ion-android-checkbox:before{content:"\f374"}.ion-android-checkbox-blank:before{content:"\f371"}.ion-android-checkbox-outline:before{content:"\f373"}.ion-android-checkbox-outline-blank:before{content:"\f372"}.ion-android-checkmark-circle:before{content:"\f375"}.ion-android-clipboard:before{content:"\f376"}.ion-android-close:before{content:"\f2d7"}.ion-android-cloud:before{content:"\f37a"}.ion-android-cloud-circle:before{content:"\f377"}.ion-android-cloud-done:before{content:"\f378"}.ion-android-cloud-outline:before{content:"\f379"}.ion-android-color-palette:before{content:"\f37b"}.ion-android-compass:before{content:"\f37c"}.ion-android-contact:before{content:"\f2d8"}.ion-android-contacts:before{content:"\f2d9"}.ion-android-contract:before{content:"\f37d"}.ion-android-create:before{content:"\f37e"}.ion-android-delete:before{content:"\f37f"}.ion-android-desktop:before{content:"\f380"}.ion-android-document:before{content:"\f381"}.ion-android-done:before{content:"\f383"}.ion-android-done-all:before{content:"\f382"}.ion-android-download:before{content:"\f2dd"}.ion-android-drafts:before{content:"\f384"}.ion-android-exit:before{content:"\f385"}.ion-android-expand:before{content:"\f386"}.ion-android-favorite:before{content:"\f388"}.ion-android-favorite-outline:before{content:"\f387"}.ion-android-film:before{content:"\f389"}.ion-android-folder:before{content:"\f2e0"}.ion-android-folder-open:before{content:"\f38a"}.ion-android-funnel:before{content:"\f38b"}.ion-android-globe:before{content:"\f38c"}.ion-android-hand:before{content:"\f2e3"}.ion-android-hangout:before{content:"\f38d"}.ion-android-happy:before{content:"\f38e"}.ion-android-home:before{content:"\f38f"}.ion-android-image:before{content:"\f2e4"}.ion-android-laptop:before{content:"\f390"}.ion-android-list:before{content:"\f391"}.ion-android-locate:before{content:"\f2e9"}.ion-android-lock:before{content:"\f392"}.ion-android-mail:before{content:"\f2eb"}.ion-android-map:before{content:"\f393"}.ion-android-menu:before{content:"\f394"}.ion-android-microphone:before{content:"\f2ec"}.ion-android-microphone-off:before{content:"\f395"}.ion-android-more-horizontal:before{content:"\f396"}.ion-android-more-vertical:before{content:"\f397"}.ion-android-navigate:before{content:"\f398"}.ion-android-notifications:before{content:"\f39b"}.ion-android-notifications-none:before{content:"\f399"}.ion-android-notifications-off:before{content:"\f39a"}.ion-android-open:before{content:"\f39c"}.ion-android-options:before{content:"\f39d"}.ion-android-people:before{content:"\f39e"}.ion-android-person:before{content:"\f3a0"}.ion-android-person-add:before{content:"\f39f"}.ion-android-phone-landscape:before{content:"\f3a1"}.ion-android-phone-portrait:before{content:"\f3a2"}.ion-android-pin:before{content:"\f3a3"}.ion-android-plane:before{content:"\f3a4"}.ion-android-playstore:before{content:"\f2f0"}.ion-android-print:before{content:"\f3a5"}.ion-android-radio-button-off:before{content:"\f3a6"}.ion-android-radio-button-on:before{content:"\f3a7"}.ion-android-refresh:before{content:"\f3a8"}.ion-android-remove:before{content:"\f2f4"}.ion-android-remove-circle:before{content:"\f3a9"}.ion-android-restaurant:before{content:"\f3aa"}.ion-android-sad:before{content:"\f3ab"}.ion-android-search:before{content:"\f2f5"}.ion-android-send:before{content:"\f2f6"}.ion-android-settings:before{content:"\f2f7"}.ion-android-share:before{content:"\f2f8"}.ion-android-share-alt:before{content:"\f3ac"}.ion-android-star:before{content:"\f2fc"}.ion-android-star-half:before{content:"\f3ad"}.ion-android-star-outline:before{content:"\f3ae"}.ion-android-stopwatch:before{content:"\f2fd"}.ion-android-subway:before{content:"\f3af"}.ion-android-sunny:before{content:"\f3b0"}.ion-android-sync:before{content:"\f3b1"}.ion-android-textsms:before{content:"\f3b2"}.ion-android-time:before{content:"\f3b3"}.ion-android-train:before{content:"\f3b4"}.ion-android-unlock:before{content:"\f3b5"}.ion-android-upload:before{content:"\f3b6"}.ion-android-volume-down:before{content:"\f3b7"}.ion-android-volume-mute:before{content:"\f3b8"}.ion-android-volume-off:before{content:"\f3b9"}.ion-android-volume-up:before{content:"\f3ba"}.ion-android-walk:before{content:"\f3bb"}.ion-android-warning:before{content:"\f3bc"}.ion-android-watch:before{content:"\f3bd"}.ion-android-wifi:before{content:"\f305"}.ion-aperture:before{content:"\f313"}.ion-archive:before{content:"\f102"}.ion-arrow-down-a:before{content:"\f103"}.ion-arrow-down-b:before{content:"\f104"}.ion-arrow-down-c:before{content:"\f105"}.ion-arrow-expand:before{content:"\f25e"}.ion-arrow-graph-down-left:before{content:"\f25f"}.ion-arrow-graph-down-right:before{content:"\f260"}.ion-arrow-graph-up-left:before{content:"\f261"}.ion-arrow-graph-up-right:before{content:"\f262"}.ion-arrow-left-a:before{content:"\f106"}.ion-arrow-left-b:before{content:"\f107"}.ion-arrow-left-c:before{content:"\f108"}.ion-arrow-move:before{content:"\f263"}.ion-arrow-resize:before{content:"\f264"}.ion-arrow-return-left:before{content:"\f265"}.ion-arrow-return-right:before{content:"\f266"}.ion-arrow-right-a:before{content:"\f109"}.ion-arrow-right-b:before{content:"\f10a"}.ion-arrow-right-c:before{content:"\f10b"}.ion-arrow-shrink:before{content:"\f267"}.ion-arrow-swap:before{content:"\f268"}.ion-arrow-up-a:before{content:"\f10c"}.ion-arrow-up-b:before{content:"\f10d"}.ion-arrow-up-c:before{content:"\f10e"}.ion-asterisk:before{content:"\f314"}.ion-at:before{content:"\f10f"}.ion-backspace:before{content:"\f3bf"}.ion-backspace-outline:before{content:"\f3be"}.ion-bag:before{content:"\f110"}.ion-battery-charging:before{content:"\f111"}.ion-battery-empty:before{content:"\f112"}.ion-battery-full:before{content:"\f113"}.ion-battery-half:before{content:"\f114"}.ion-battery-low:before{content:"\f115"}.ion-beaker:before{content:"\f269"}.ion-beer:before{content:"\f26a"}.ion-bluetooth:before{content:"\f116"}.ion-bonfire:before{content:"\f315"}.ion-bookmark:before{content:"\f26b"}.ion-bowtie:before{content:"\f3c0"}.ion-briefcase:before{content:"\f26c"}.ion-bug:before{content:"\f2be"}.ion-calculator:before{content:"\f26d"}.ion-calendar:before{content:"\f117"}.ion-camera:before{content:"\f118"}.ion-card:before{content:"\f119"}.ion-cash:before{content:"\f316"}.ion-chatbox:before{content:"\f11b"}.ion-chatbox-working:before{content:"\f11a"}.ion-chatboxes:before{content:"\f11c"}.ion-chatbubble:before{content:"\f11e"}.ion-chatbubble-working:before{content:"\f11d"}.ion-chatbubbles:before{content:"\f11f"}.ion-checkmark:before{content:"\f122"}.ion-checkmark-circled:before{content:"\f120"}.ion-checkmark-round:before{content:"\f121"}.ion-chevron-down:before{content:"\f123"}.ion-chevron-left:before{content:"\f124"}.ion-chevron-right:before{content:"\f125"}.ion-chevron-up:before{content:"\f126"}.ion-clipboard:before{content:"\f127"}.ion-clock:before{content:"\f26e"}.ion-close:before{content:"\f12a"}.ion-close-circled:before{content:"\f128"}.ion-close-round:before{content:"\f129"}.ion-closed-captioning:before{content:"\f317"}.ion-cloud:before{content:"\f12b"}.ion-code:before{content:"\f271"}.ion-code-download:before{content:"\f26f"}.ion-code-working:before{content:"\f270"}.ion-coffee:before{content:"\f272"}.ion-compass:before{content:"\f273"}.ion-compose:before{content:"\f12c"}.ion-connection-bars:before{content:"\f274"}.ion-contrast:before{content:"\f275"}.ion-crop:before{content:"\f3c1"}.ion-cube:before{content:"\f318"}.ion-disc:before{content:"\f12d"}.ion-document:before{content:"\f12f"}.ion-document-text:before{content:"\f12e"}.ion-drag:before{content:"\f130"}.ion-earth:before{content:"\f276"}.ion-easel:before{content:"\f3c2"}.ion-edit:before{content:"\f2bf"}.ion-egg:before{content:"\f277"}.ion-eject:before{content:"\f131"}.ion-email:before{content:"\f132"}.ion-email-unread:before{content:"\f3c3"}.ion-erlenmeyer-flask:before{content:"\f3c5"}.ion-erlenmeyer-flask-bubbles:before{content:"\f3c4"}.ion-eye:before{content:"\f133"}.ion-eye-disabled:before{content:"\f306"}.ion-female:before{content:"\f278"}.ion-filing:before{content:"\f134"}.ion-film-marker:before{content:"\f135"}.ion-fireball:before{content:"\f319"}.ion-flag:before{content:"\f279"}.ion-flame:before{content:"\f31a"}.ion-flash:before{content:"\f137"}.ion-flash-off:before{content:"\f136"}.ion-folder:before{content:"\f139"}.ion-fork:before{content:"\f27a"}.ion-fork-repo:before{content:"\f2c0"}.ion-forward:before{content:"\f13a"}.ion-funnel:before{content:"\f31b"}.ion-gear-a:before{content:"\f13d"}.ion-gear-b:before{content:"\f13e"}.ion-grid:before{content:"\f13f"}.ion-hammer:before{content:"\f27b"}.ion-happy:before{content:"\f31c"}.ion-happy-outline:before{content:"\f3c6"}.ion-headphone:before{content:"\f140"}.ion-heart:before{content:"\f141"}.ion-heart-broken:before{content:"\f31d"}.ion-help:before{content:"\f143"}.ion-help-buoy:before{content:"\f27c"}.ion-help-circled:before{content:"\f142"}.ion-home:before{content:"\f144"}.ion-icecream:before{content:"\f27d"}.ion-image:before{content:"\f147"}.ion-images:before{content:"\f148"}.ion-information:before{content:"\f14a"}.ion-information-circled:before{content:"\f149"}.ion-ionic:before{content:"\f14b"}.ion-ios-alarm:before{content:"\f3c8"}.ion-ios-alarm-outline:before{content:"\f3c7"}.ion-ios-albums:before{content:"\f3ca"}.ion-ios-albums-outline:before{content:"\f3c9"}.ion-ios-americanfootball:before{content:"\f3cc"}.ion-ios-americanfootball-outline:before{content:"\f3cb"}.ion-ios-analytics:before{content:"\f3ce"}.ion-ios-analytics-outline:before{content:"\f3cd"}.ion-ios-arrow-back:before{content:"\f3cf"}.ion-ios-arrow-down:before{content:"\f3d0"}.ion-ios-arrow-forward:before{content:"\f3d1"}.ion-ios-arrow-left:before{content:"\f3d2"}.ion-ios-arrow-right:before{content:"\f3d3"}.ion-ios-arrow-thin-down:before{content:"\f3d4"}.ion-ios-arrow-thin-left:before{content:"\f3d5"}.ion-ios-arrow-thin-right:before{content:"\f3d6"}.ion-ios-arrow-thin-up:before{content:"\f3d7"}.ion-ios-arrow-up:before{content:"\f3d8"}.ion-ios-at:before{content:"\f3da"}.ion-ios-at-outline:before{content:"\f3d9"}.ion-ios-barcode:before{content:"\f3dc"}.ion-ios-barcode-outline:before{content:"\f3db"}.ion-ios-baseball:before{content:"\f3de"}.ion-ios-baseball-outline:before{content:"\f3dd"}.ion-ios-basketball:before{content:"\f3e0"}.ion-ios-basketball-outline:before{content:"\f3df"}.ion-ios-bell:before{content:"\f3e2"}.ion-ios-bell-outline:before{content:"\f3e1"}.ion-ios-body:before{content:"\f3e4"}.ion-ios-body-outline:before{content:"\f3e3"}.ion-ios-bolt:before{content:"\f3e6"}.ion-ios-bolt-outline:before{content:"\f3e5"}.ion-ios-book:before{content:"\f3e8"}.ion-ios-book-outline:before{content:"\f3e7"}.ion-ios-bookmarks:before{content:"\f3ea"}.ion-ios-bookmarks-outline:before{content:"\f3e9"}.ion-ios-box:before{content:"\f3ec"}.ion-ios-box-outline:before{content:"\f3eb"}.ion-ios-briefcase:before{content:"\f3ee"}.ion-ios-briefcase-outline:before{content:"\f3ed"}.ion-ios-browsers:before{content:"\f3f0"}.ion-ios-browsers-outline:before{content:"\f3ef"}.ion-ios-calculator:before{content:"\f3f2"}.ion-ios-calculator-outline:before{content:"\f3f1"}.ion-ios-calendar:before{content:"\f3f4"}.ion-ios-calendar-outline:before{content:"\f3f3"}.ion-ios-camera:before{content:"\f3f6"}.ion-ios-camera-outline:before{content:"\f3f5"}.ion-ios-cart:before{content:"\f3f8"}.ion-ios-cart-outline:before{content:"\f3f7"}.ion-ios-chatboxes:before{content:"\f3fa"}.ion-ios-chatboxes-outline:before{content:"\f3f9"}.ion-ios-chatbubble:before{content:"\f3fc"}.ion-ios-chatbubble-outline:before{content:"\f3fb"}.ion-ios-checkmark:before{content:"\f3ff"}.ion-ios-checkmark-empty:before{content:"\f3fd"}.ion-ios-checkmark-outline:before{content:"\f3fe"}.ion-ios-circle-filled:before{content:"\f400"}.ion-ios-circle-outline:before{content:"\f401"}.ion-ios-clock:before{content:"\f403"}.ion-ios-clock-outline:before{content:"\f402"}.ion-ios-close:before{content:"\f406"}.ion-ios-close-empty:before{content:"\f404"}.ion-ios-close-outline:before{content:"\f405"}.ion-ios-cloud:before{content:"\f40c"}.ion-ios-cloud-download:before{content:"\f408"}.ion-ios-cloud-download-outline:before{content:"\f407"}.ion-ios-cloud-outline:before{content:"\f409"}.ion-ios-cloud-upload:before{content:"\f40b"}.ion-ios-cloud-upload-outline:before{content:"\f40a"}.ion-ios-cloudy:before{content:"\f410"}.ion-ios-cloudy-night:before{content:"\f40e"}.ion-ios-cloudy-night-outline:before{content:"\f40d"}.ion-ios-cloudy-outline:before{content:"\f40f"}.ion-ios-cog:before{content:"\f412"}.ion-ios-cog-outline:before{content:"\f411"}.ion-ios-color-filter:before{content:"\f414"}.ion-ios-color-filter-outline:before{content:"\f413"}.ion-ios-color-wand:before{content:"\f416"}.ion-ios-color-wand-outline:before{content:"\f415"}.ion-ios-compose:before{content:"\f418"}.ion-ios-compose-outline:before{content:"\f417"}.ion-ios-contact:before{content:"\f41a"}.ion-ios-contact-outline:before{content:"\f419"}.ion-ios-copy:before{content:"\f41c"}.ion-ios-copy-outline:before{content:"\f41b"}.ion-ios-crop:before{content:"\f41e"}.ion-ios-crop-strong:before{content:"\f41d"}.ion-ios-download:before{content:"\f420"}.ion-ios-download-outline:before{content:"\f41f"}.ion-ios-drag:before{content:"\f421"}.ion-ios-email:before{content:"\f423"}.ion-ios-email-outline:before{content:"\f422"}.ion-ios-eye:before{content:"\f425"}.ion-ios-eye-outline:before{content:"\f424"}.ion-ios-fastforward:before{content:"\f427"}.ion-ios-fastforward-outline:before{content:"\f426"}.ion-ios-filing:before{content:"\f429"}.ion-ios-filing-outline:before{content:"\f428"}.ion-ios-film:before{content:"\f42b"}.ion-ios-film-outline:before{content:"\f42a"}.ion-ios-flag:before{content:"\f42d"}.ion-ios-flag-outline:before{content:"\f42c"}.ion-ios-flame:before{content:"\f42f"}.ion-ios-flame-outline:before{content:"\f42e"}.ion-ios-flask:before{content:"\f431"}.ion-ios-flask-outline:before{content:"\f430"}.ion-ios-flower:before{content:"\f433"}.ion-ios-flower-outline:before{content:"\f432"}.ion-ios-folder:before{content:"\f435"}.ion-ios-folder-outline:before{content:"\f434"}.ion-ios-football:before{content:"\f437"}.ion-ios-football-outline:before{content:"\f436"}.ion-ios-game-controller-a:before{content:"\f439"}.ion-ios-game-controller-a-outline:before{content:"\f438"}.ion-ios-game-controller-b:before{content:"\f43b"}.ion-ios-game-controller-b-outline:before{content:"\f43a"}.ion-ios-gear:before{content:"\f43d"}.ion-ios-gear-outline:before{content:"\f43c"}.ion-ios-glasses:before{content:"\f43f"}.ion-ios-glasses-outline:before{content:"\f43e"}.ion-ios-grid-view:before{content:"\f441"}.ion-ios-grid-view-outline:before{content:"\f440"}.ion-ios-heart:before{content:"\f443"}.ion-ios-heart-outline:before{content:"\f442"}.ion-ios-help:before{content:"\f446"}.ion-ios-help-empty:before{content:"\f444"}.ion-ios-help-outline:before{content:"\f445"}.ion-ios-home:before{content:"\f448"}.ion-ios-home-outline:before{content:"\f447"}.ion-ios-infinite:before{content:"\f44a"}.ion-ios-infinite-outline:before{content:"\f449"}.ion-ios-information:before{content:"\f44d"}.ion-ios-information-empty:before{content:"\f44b"}.ion-ios-information-outline:before{content:"\f44c"}.ion-ios-ionic-outline:before{content:"\f44e"}.ion-ios-keypad:before{content:"\f450"}.ion-ios-keypad-outline:before{content:"\f44f"}.ion-ios-lightbulb:before{content:"\f452"}.ion-ios-lightbulb-outline:before{content:"\f451"}.ion-ios-list:before{content:"\f454"}.ion-ios-list-outline:before{content:"\f453"}.ion-ios-location:before{content:"\f456"}.ion-ios-location-outline:before{content:"\f455"}.ion-ios-locked:before{content:"\f458"}.ion-ios-locked-outline:before{content:"\f457"}.ion-ios-loop:before{content:"\f45a"}.ion-ios-loop-strong:before{content:"\f459"}.ion-ios-medical:before{content:"\f45c"}.ion-ios-medical-outline:before{content:"\f45b"}.ion-ios-medkit:before{content:"\f45e"}.ion-ios-medkit-outline:before{content:"\f45d"}.ion-ios-mic:before{content:"\f461"}.ion-ios-mic-off:before{content:"\f45f"}.ion-ios-mic-outline:before{content:"\f460"}.ion-ios-minus:before{content:"\f464"}.ion-ios-minus-empty:before{content:"\f462"}.ion-ios-minus-outline:before{content:"\f463"}.ion-ios-monitor:before{content:"\f466"}.ion-ios-monitor-outline:before{content:"\f465"}.ion-ios-moon:before{content:"\f468"}.ion-ios-moon-outline:before{content:"\f467"}.ion-ios-more:before{content:"\f46a"}.ion-ios-more-outline:before{content:"\f469"}.ion-ios-musical-note:before{content:"\f46b"}.ion-ios-musical-notes:before{content:"\f46c"}.ion-ios-navigate:before{content:"\f46e"}.ion-ios-navigate-outline:before{content:"\f46d"}.ion-ios-nutrition:before{content:"\f470"}.ion-ios-nutrition-outline:before{content:"\f46f"}.ion-ios-paper:before{content:"\f472"}.ion-ios-paper-outline:before{content:"\f471"}.ion-ios-paperplane:before{content:"\f474"}.ion-ios-paperplane-outline:before{content:"\f473"}.ion-ios-partlysunny:before{content:"\f476"}.ion-ios-partlysunny-outline:before{content:"\f475"}.ion-ios-pause:before{content:"\f478"}.ion-ios-pause-outline:before{content:"\f477"}.ion-ios-paw:before{content:"\f47a"}.ion-ios-paw-outline:before{content:"\f479"}.ion-ios-people:before{content:"\f47c"}.ion-ios-people-outline:before{content:"\f47b"}.ion-ios-person:before{content:"\f47e"}.ion-ios-person-outline:before{content:"\f47d"}.ion-ios-personadd:before{content:"\f480"}.ion-ios-personadd-outline:before{content:"\f47f"}.ion-ios-photos:before{content:"\f482"}.ion-ios-photos-outline:before{content:"\f481"}.ion-ios-pie:before{content:"\f484"}.ion-ios-pie-outline:before{content:"\f483"}.ion-ios-pint:before{content:"\f486"}.ion-ios-pint-outline:before{content:"\f485"}.ion-ios-play:before{content:"\f488"}.ion-ios-play-outline:before{content:"\f487"}.ion-ios-plus:before{content:"\f48b"}.ion-ios-plus-empty:before{content:"\f489"}.ion-ios-plus-outline:before{content:"\f48a"}.ion-ios-pricetag:before{content:"\f48d"}.ion-ios-pricetag-outline:before{content:"\f48c"}.ion-ios-pricetags:before{content:"\f48f"}.ion-ios-pricetags-outline:before{content:"\f48e"}.ion-ios-printer:before{content:"\f491"}.ion-ios-printer-outline:before{content:"\f490"}.ion-ios-pulse:before{content:"\f493"}.ion-ios-pulse-strong:before{content:"\f492"}.ion-ios-rainy:before{content:"\f495"}.ion-ios-rainy-outline:before{content:"\f494"}.ion-ios-recording:before{content:"\f497"}.ion-ios-recording-outline:before{content:"\f496"}.ion-ios-redo:before{content:"\f499"}.ion-ios-redo-outline:before{content:"\f498"}.ion-ios-refresh:before{content:"\f49c"}.ion-ios-refresh-empty:before{content:"\f49a"}.ion-ios-refresh-outline:before{content:"\f49b"}.ion-ios-reload:before{content:"\f49d"}.ion-ios-reverse-camera:before{content:"\f49f"}.ion-ios-reverse-camera-outline:before{content:"\f49e"}.ion-ios-rewind:before{content:"\f4a1"}.ion-ios-rewind-outline:before{content:"\f4a0"}.ion-ios-rose:before{content:"\f4a3"}.ion-ios-rose-outline:before{content:"\f4a2"}.ion-ios-search:before{content:"\f4a5"}.ion-ios-search-strong:before{content:"\f4a4"}.ion-ios-settings:before{content:"\f4a7"}.ion-ios-settings-strong:before{content:"\f4a6"}.ion-ios-shuffle:before{content:"\f4a9"}.ion-ios-shuffle-strong:before{content:"\f4a8"}.ion-ios-skipbackward:before{content:"\f4ab"}.ion-ios-skipbackward-outline:before{content:"\f4aa"}.ion-ios-skipforward:before{content:"\f4ad"}.ion-ios-skipforward-outline:before{content:"\f4ac"}.ion-ios-snowy:before{content:"\f4ae"}.ion-ios-speedometer:before{content:"\f4b0"}.ion-ios-speedometer-outline:before{content:"\f4af"}.ion-ios-star:before{content:"\f4b3"}.ion-ios-star-half:before{content:"\f4b1"}.ion-ios-star-outline:before{content:"\f4b2"}.ion-ios-stopwatch:before{content:"\f4b5"}.ion-ios-stopwatch-outline:before{content:"\f4b4"}.ion-ios-sunny:before{content:"\f4b7"}.ion-ios-sunny-outline:before{content:"\f4b6"}.ion-ios-telephone:before{content:"\f4b9"}.ion-ios-telephone-outline:before{content:"\f4b8"}.ion-ios-tennisball:before{content:"\f4bb"}.ion-ios-tennisball-outline:before{content:"\f4ba"}.ion-ios-thunderstorm:before{content:"\f4bd"}.ion-ios-thunderstorm-outline:before{content:"\f4bc"}.ion-ios-time:before{content:"\f4bf"}.ion-ios-time-outline:before{content:"\f4be"}.ion-ios-timer:before{content:"\f4c1"}.ion-ios-timer-outline:before{content:"\f4c0"}.ion-ios-toggle:before{content:"\f4c3"}.ion-ios-toggle-outline:before{content:"\f4c2"}.ion-ios-trash:before{content:"\f4c5"}.ion-ios-trash-outline:before{content:"\f4c4"}.ion-ios-undo:before{content:"\f4c7"}.ion-ios-undo-outline:before{content:"\f4c6"}.ion-ios-unlocked:before{content:"\f4c9"}.ion-ios-unlocked-outline:before{content:"\f4c8"}.ion-ios-upload:before{content:"\f4cb"}.ion-ios-upload-outline:before{content:"\f4ca"}.ion-ios-videocam:before{content:"\f4cd"}.ion-ios-videocam-outline:before{content:"\f4cc"}.ion-ios-volume-high:before{content:"\f4ce"}.ion-ios-volume-low:before{content:"\f4cf"}.ion-ios-wineglass:before{content:"\f4d1"}.ion-ios-wineglass-outline:before{content:"\f4d0"}.ion-ios-world:before{content:"\f4d3"}.ion-ios-world-outline:before{content:"\f4d2"}.ion-ipad:before{content:"\f1f9"}.ion-iphone:before{content:"\f1fa"}.ion-ipod:before{content:"\f1fb"}.ion-jet:before{content:"\f295"}.ion-key:before{content:"\f296"}.ion-knife:before{content:"\f297"}.ion-laptop:before{content:"\f1fc"}.ion-leaf:before{content:"\f1fd"}.ion-levels:before{content:"\f298"}.ion-lightbulb:before{content:"\f299"}.ion-link:before{content:"\f1fe"}.ion-load-a:before{content:"\f29a"}.ion-load-b:before{content:"\f29b"}.ion-load-c:before{content:"\f29c"}.ion-load-d:before{content:"\f29d"}.ion-location:before{content:"\f1ff"}.ion-lock-combination:before{content:"\f4d4"}.ion-locked:before{content:"\f200"}.ion-log-in:before{content:"\f29e"}.ion-log-out:before{content:"\f29f"}.ion-loop:before{content:"\f201"}.ion-magnet:before{content:"\f2a0"}.ion-male:before{content:"\f2a1"}.ion-man:before{content:"\f202"}.ion-map:before{content:"\f203"}.ion-medkit:before{content:"\f2a2"}.ion-merge:before{content:"\f33f"}.ion-mic-a:before{content:"\f204"}.ion-mic-b:before{content:"\f205"}.ion-mic-c:before{content:"\f206"}.ion-minus:before{content:"\f209"}.ion-minus-circled:before{content:"\f207"}.ion-minus-round:before{content:"\f208"}.ion-model-s:before{content:"\f2c1"}.ion-monitor:before{content:"\f20a"}.ion-more:before{content:"\f20b"}.ion-mouse:before{content:"\f340"}.ion-music-note:before{content:"\f20c"}.ion-navicon:before{content:"\f20e"}.ion-navicon-round:before{content:"\f20d"}.ion-navigate:before{content:"\f2a3"}.ion-network:before{content:"\f341"}.ion-no-smoking:before{content:"\f2c2"}.ion-nuclear:before{content:"\f2a4"}.ion-outlet:before{content:"\f342"}.ion-paintbrush:before{content:"\f4d5"}.ion-paintbucket:before{content:"\f4d6"}.ion-paper-airplane:before{content:"\f2c3"}.ion-paperclip:before{content:"\f20f"}.ion-pause:before{content:"\f210"}.ion-person:before{content:"\f213"}.ion-person-add:before{content:"\f211"}.ion-person-stalker:before{content:"\f212"}.ion-pie-graph:before{content:"\f2a5"}.ion-pin:before{content:"\f2a6"}.ion-pinpoint:before{content:"\f2a7"}.ion-pizza:before{content:"\f2a8"}.ion-plane:before{content:"\f214"}.ion-planet:before{content:"\f343"}.ion-play:before{content:"\f215"}.ion-playstation:before{content:"\f30a"}.ion-plus:before{content:"\f218"}.ion-plus-circled:before{content:"\f216"}.ion-plus-round:before{content:"\f217"}.ion-podium:before{content:"\f344"}.ion-pound:before{content:"\f219"}.ion-power:before{content:"\f2a9"}.ion-pricetag:before{content:"\f2aa"}.ion-pricetags:before{content:"\f2ab"}.ion-printer:before{content:"\f21a"}.ion-pull-request:before{content:"\f345"}.ion-qr-scanner:before{content:"\f346"}.ion-quote:before{content:"\f347"}.ion-radio-waves:before{content:"\f2ac"}.ion-record:before{content:"\f21b"}.ion-refresh:before{content:"\f21c"}.ion-reply:before{content:"\f21e"}.ion-reply-all:before{content:"\f21d"}.ion-ribbon-a:before{content:"\f348"}.ion-ribbon-b:before{content:"\f349"}.ion-sad:before{content:"\f34a"}.ion-sad-outline:before{content:"\f4d7"}.ion-scissors:before{content:"\f34b"}.ion-search:before{content:"\f21f"}.ion-settings:before{content:"\f2ad"}.ion-share:before{content:"\f220"}.ion-shuffle:before{content:"\f221"}.ion-skip-backward:before{content:"\f222"}.ion-skip-forward:before{content:"\f223"}.ion-social-android:before{content:"\f225"}.ion-social-android-outline:before{content:"\f224"}.ion-social-angular:before{content:"\f4d9"}.ion-social-angular-outline:before{content:"\f4d8"}.ion-social-apple:before{content:"\f227"}.ion-social-apple-outline:before{content:"\f226"}.ion-social-bitcoin:before{content:"\f2af"}.ion-social-bitcoin-outline:before{content:"\f2ae"}.ion-social-buffer:before{content:"\f229"}.ion-social-buffer-outline:before{content:"\f228"}.ion-social-chrome:before{content:"\f4db"}.ion-social-chrome-outline:before{content:"\f4da"}.ion-social-codepen:before{content:"\f4dd"}.ion-social-codepen-outline:before{content:"\f4dc"}.ion-social-css3:before{content:"\f4df"}.ion-social-css3-outline:before{content:"\f4de"}.ion-social-designernews:before{content:"\f22b"}.ion-social-designernews-outline:before{content:"\f22a"}.ion-social-dribbble:before{content:"\f22d"}.ion-social-dribbble-outline:before{content:"\f22c"}.ion-social-dropbox:before{content:"\f22f"}.ion-social-dropbox-outline:before{content:"\f22e"}.ion-social-euro:before{content:"\f4e1"}.ion-social-euro-outline:before{content:"\f4e0"}.ion-social-facebook:before{content:"\f231"}.ion-social-facebook-outline:before{content:"\f230"}.ion-social-foursquare:before{content:"\f34d"}.ion-social-foursquare-outline:before{content:"\f34c"}.ion-social-freebsd-devil:before{content:"\f2c4"}.ion-social-github:before{content:"\f233"}.ion-social-github-outline:before{content:"\f232"}.ion-social-google:before{content:"\f34f"}.ion-social-google-outline:before{content:"\f34e"}.ion-social-googleplus:before{content:"\f235"}.ion-social-googleplus-outline:before{content:"\f234"}.ion-social-hackernews:before{content:"\f237"}.ion-social-hackernews-outline:before{content:"\f236"}.ion-social-html5:before{content:"\f4e3"}.ion-social-html5-outline:before{content:"\f4e2"}.ion-social-instagram:before{content:"\f351"}.ion-social-instagram-outline:before{content:"\f350"}.ion-social-javascript:before{content:"\f4e5"}.ion-social-javascript-outline:before{content:"\f4e4"}.ion-social-linkedin:before{content:"\f239"}.ion-social-linkedin-outline:before{content:"\f238"}.ion-social-markdown:before{content:"\f4e6"}.ion-social-nodejs:before{content:"\f4e7"}.ion-social-octocat:before{content:"\f4e8"}.ion-social-pinterest:before{content:"\f2b1"}.ion-social-pinterest-outline:before{content:"\f2b0"}.ion-social-python:before{content:"\f4e9"}.ion-social-reddit:before{content:"\f23b"}.ion-social-reddit-outline:before{content:"\f23a"}.ion-social-rss:before{content:"\f23d"}.ion-social-rss-outline:before{content:"\f23c"}.ion-social-sass:before{content:"\f4ea"}.ion-social-skype:before{content:"\f23f"}.ion-social-skype-outline:before{content:"\f23e"}.ion-social-snapchat:before{content:"\f4ec"}.ion-social-snapchat-outline:before{content:"\f4eb"}.ion-social-tumblr:before{content:"\f241"}.ion-social-tumblr-outline:before{content:"\f240"}.ion-social-tux:before{content:"\f2c5"}.ion-social-twitch:before{content:"\f4ee"}.ion-social-twitch-outline:before{content:"\f4ed"}.ion-social-twitter:before{content:"\f243"}.ion-social-twitter-outline:before{content:"\f242"}.ion-social-usd:before{content:"\f353"}.ion-social-usd-outline:before{content:"\f352"}.ion-social-vimeo:before{content:"\f245"}.ion-social-vimeo-outline:before{content:"\f244"}.ion-social-whatsapp:before{content:"\f4f0"}.ion-social-whatsapp-outline:before{content:"\f4ef"}.ion-social-windows:before{content:"\f247"}.ion-social-windows-outline:before{content:"\f246"}.ion-social-wordpress:before{content:"\f249"}.ion-social-wordpress-outline:before{content:"\f248"}.ion-social-yahoo:before{content:"\f24b"}.ion-social-yahoo-outline:before{content:"\f24a"}.ion-social-yen:before{content:"\f4f2"}.ion-social-yen-outline:before{content:"\f4f1"}.ion-social-youtube:before{content:"\f24d"}.ion-social-youtube-outline:before{content:"\f24c"}.ion-soup-can:before{content:"\f4f4"}.ion-soup-can-outline:before{content:"\f4f3"}.ion-speakerphone:before{content:"\f2b2"}.ion-speedometer:before{content:"\f2b3"}.ion-spoon:before{content:"\f2b4"}.ion-star:before{content:"\f24e"}.ion-stats-bars:before{content:"\f2b5"}.ion-steam:before{content:"\f30b"}.ion-stop:before{content:"\f24f"}.ion-thermometer:before{content:"\f2b6"}.ion-thumbsdown:before{content:"\f250"}.ion-thumbsup:before{content:"\f251"}.ion-toggle:before{content:"\f355"}.ion-toggle-filled:before{content:"\f354"}.ion-transgender:before{content:"\f4f5"}.ion-trash-a:before{content:"\f252"}.ion-trash-b:before{content:"\f253"}.ion-trophy:before{content:"\f356"}.ion-tshirt:before{content:"\f4f7"}.ion-tshirt-outline:before{content:"\f4f6"}.ion-umbrella:before{content:"\f2b7"}.ion-university:before{content:"\f357"}.ion-unlocked:before{content:"\f254"}.ion-upload:before{content:"\f255"}.ion-usb:before{content:"\f2b8"}.ion-videocamera:before{content:"\f256"}.ion-volume-high:before{content:"\f257"}.ion-volume-low:before{content:"\f258"}.ion-volume-medium:before{content:"\f259"}.ion-volume-mute:before{content:"\f25a"}.ion-wand:before{content:"\f358"}.ion-waterdrop:before{content:"\f25b"}.ion-wifi:before{content:"\f25c"}.ion-wineglass:before{content:"\f2b9"}.ion-woman:before{content:"\f25d"}.ion-wrench:before{content:"\f2ba"}.ion-xbox:before{content:"\f30c"}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;vertical-align:baseline;font:inherit;font-size:100%}ol,ul{list-style:none}blockquote,q{quotes:none}audio:not([controls]){display:none;height:0}[hidden],template{display:none}script{display:none!important}html{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}:focus,a,a:active,a:focus,a:hover,button,button:focus{outline:0}a{-webkit-user-drag:none;-webkit-tap-highlight-color:transparent}a[href]:hover{cursor:pointer}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}code,kbd,pre,samp{font-size:1em;font-family:monospace,serif}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{position:relative;vertical-align:baseline;font-size:75%;line-height:0}sup{top:-.5em}sub{bottom:-.25em}fieldset{margin:0 2px;padding:.35em .625em .75em;border:1px solid silver}button,input,select,textarea{margin:0;outline-offset:0;outline-style:none;outline-width:0;-webkit-font-smoothing:inherit;background-image:none}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto}img{-webkit-user-drag:none}table{border-spacing:0;border-collapse:collapse}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{overflow:hidden;-ms-touch-action:pan-y;touch-action:pan-y}.ionic-body,body{-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;top:0;right:0;bottom:0;left:0;overflow:hidden;margin:0;padding:0;color:#000;word-wrap:break-word;font-size:14px;font-family:"Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:20px;text-rendering:optimizeLegibility;-webkit-backface-visibility:hidden;-webkit-user-drag:none;-ms-content-zooming:none}body.grade-b,body.grade-c{text-rendering:auto}.content{position:relative}.scroll-content{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;margin-top:-1px;padding-top:1px;margin-bottom:-1px;width:auto;height:auto}.menu .scroll-content.scroll-content-false{z-index:11}.scroll-view{position:relative;display:block;overflow:hidden;margin-top:-1px}.scroll{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-transform-origin:left top;transform-origin:left top}@-ms-viewport{width:device-width}.scroll-bar{position:absolute;z-index:9999}.ng-animate .scroll-bar{visibility:hidden}.scroll-bar-h{right:2px;bottom:3px;left:2px;height:3px}.scroll-bar-h .scroll-bar-indicator{height:100%}.scroll-bar-v{top:2px;right:3px;bottom:2px;width:3px}.scroll-bar-v .scroll-bar-indicator{width:100%}.scroll-bar-indicator{position:absolute;border-radius:4px;background:rgba(0,0,0,.3);opacity:1;-webkit-transition:opacity .3s linear;transition:opacity .3s linear}.scroll-bar-indicator.scroll-bar-fade-out{opacity:0}.platform-android .scroll-bar-indicator{border-radius:0}.grade-b .scroll-bar-indicator,.grade-c .scroll-bar-indicator{background:#aaa}.grade-b .scroll-bar-indicator.scroll-bar-fade-out,.grade-c .scroll-bar-indicator.scroll-bar-fade-out{-webkit-transition:none;transition:none}ion-infinite-scroll{height:60px;width:100%;display:block;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}ion-infinite-scroll .icon{font-size:30px;color:#666}ion-infinite-scroll:not(.active) .icon:before,ion-infinite-scroll:not(.active) .spinner{display:none}.overflow-scroll{overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;top:0;right:0;bottom:0;left:0;position:absolute}.overflow-scroll .scroll{position:static;height:100%;-webkit-transform:translate3d(0,0,0)}.has-header{top:44px}.no-header{top:0}.has-subheader{top:88px}.has-tabs-top{top:93px}.has-header.has-subheader.has-tabs-top{top:137px}.has-footer{bottom:44px}.has-subfooter{bottom:88px}.bar-footer.has-tabs,.has-tabs{bottom:49px}.bar-footer.has-tabs.pane,.has-tabs.pane{bottom:49px;height:auto}.has-footer.has-tabs{bottom:93px}.pane{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:0;transition-duration:0;z-index:1}.view{z-index:1}.pane,.view{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:#fff;overflow:hidden}.view-container{position:absolute;display:block;width:100%;height:100%}p{margin:0 0 10px}small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{color:#000;font-weight:500;font-family:"Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:1.2}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1:first-child,.h2:first-child,.h3:first-child,h1:first-child,h2:first-child,h3:first-child{margin-top:0}.h1+.h1,.h1+.h2,.h1+.h3,.h1+h1,.h1+h2,.h1+h3,.h2+.h1,.h2+.h2,.h2+.h3,.h2+h1,.h2+h2,.h2+h3,.h3+.h1,.h3+.h2,.h3+.h3,.h3+h1,.h3+h2,.h3+h3,h1+.h1,h1+.h2,h1+.h3,h1+h1,h1+h2,h1+h3,h2+.h1,h2+.h2,h2+.h3,h2+h1,h2+h2,h2+h3,h3+.h1,h3+.h2,h3+.h3,h3+h1,h3+h2,h3+h3{margin-top:10px}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}.h1 small,h1 small{font-size:24px}.h2 small,h2 small{font-size:18px}.h3 small,.h4 small,h3 small,h4 small{font-size:14px}dl{margin-bottom:20px}dd,dt{line-height:1.42857}dt{font-weight:700}blockquote{margin:0 0 20px;padding:10px 20px;border-left:5px solid gray}blockquote p{font-weight:300;font-size:17.5px;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.42857}blockquote small:before{content:'\2014 \00A0'}blockquote:after,blockquote:before,q:after,q:before{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.42857}a.subdued{padding-right:10px;color:#888;text-decoration:none}a.subdued:hover{text-decoration:none}a.subdued:last-child{padding-right:0}.action-sheet-backdrop{-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:transparent}.action-sheet-backdrop.active{background-color:rgba(0,0,0,.4)}.action-sheet-wrapper{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition:all cubic-bezier(.36,.66,.04,1) 500ms;transition:all cubic-bezier(.36,.66,.04,1) 500ms;position:absolute;bottom:0;left:0;right:0;width:100%;max-width:500px;margin:auto}.action-sheet-up{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.action-sheet{margin-left:8px;margin-right:8px;width:auto;z-index:11;overflow:hidden}.action-sheet .button{display:block;padding:1px;width:100%;border-radius:0;border-color:#d1d3d6;background-color:transparent;color:#007aff;font-size:21px}.action-sheet .button:hover{color:#007aff}.action-sheet .button.destructive,.action-sheet .button.destructive:hover{color:#ff3b30}.action-sheet .button.activated,.action-sheet .button.active{box-shadow:none;border-color:#d1d3d6;color:#007aff;background:#e4e5e7}.action-sheet-has-icons .icon{position:absolute;left:16px}.action-sheet-title{padding:16px;color:#8f8f8f;text-align:center;font-size:13px}.action-sheet-group{margin-bottom:8px;border-radius:4px;background-color:#fff;overflow:hidden}.action-sheet-group .button{border-width:1px 0 0}.action-sheet-group .button:first-child:last-child{border-width:0}.action-sheet-options{background:#f1f2f3}.action-sheet-cancel .button{font-weight:500}.action-sheet-open,.action-sheet-open.modal-open .modal{pointer-events:none}.action-sheet-open .action-sheet-backdrop{pointer-events:auto}.platform-android .action-sheet-backdrop.active{background-color:rgba(0,0,0,.2)}.platform-android .action-sheet{margin:0}.platform-android .action-sheet .action-sheet-title,.platform-android .action-sheet .button{text-align:left;border-color:transparent;font-size:16px;color:inherit}.platform-android .action-sheet .action-sheet-title{font-size:14px;padding:16px;color:#666}.platform-android .action-sheet .button.activated,.platform-android .action-sheet .button.active{background:#e8e8e8}.platform-android .action-sheet-group{margin:0;border-radius:0;background-color:#fafafa}.platform-android .action-sheet-cancel{display:none}.platform-android .action-sheet-has-icons .button{padding-left:56px}.backdrop{position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:rgba(0,0,0,.4);visibility:hidden;opacity:0;-webkit-transition:.1s opacity linear;transition:.1s opacity linear}.backdrop.visible{visibility:visible}.backdrop.active{opacity:1}.bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:absolute;right:0;left:0;z-index:9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:5px;width:100%;height:44px;border-width:0;border-style:solid;border-top:1px solid transparent;border-bottom:1px solid #ddd;background-color:#fff;background-size:0}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.bar{border:none;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);background-position:bottom;background-size:100% 1px;background-repeat:no-repeat}}.bar.bar-clear{border:none;background:0 0;color:#fff}.bar.bar-clear .button,.bar.bar-clear .title{color:#fff}.bar.item-input-inset .item-input-wrapper{margin-top:-1px}.bar.item-input-inset .item-input-wrapper input{padding-left:8px;width:94%;height:28px;background:0 0}.bar.bar-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.bar.bar-light .title{color:#444}.bar.bar-light.bar-footer{background-image:linear-gradient(180deg,#ddd,#ddd 50%,transparent 50%)}.bar.bar-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.bar.bar-stable .title{color:#444}.bar.bar-stable.bar-footer{background-image:linear-gradient(180deg,#b2b2b2,#b2b2b2 50%,transparent 50%)}.bar.bar-positive{border-color:#0c63ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c63ee,#0c63ee 50%,transparent 50%);color:#fff}.bar.bar-positive .title{color:#fff}.bar.bar-positive.bar-footer{background-image:linear-gradient(180deg,#0c63ee,#0c63ee 50%,transparent 50%)}.bar.bar-calm{border-color:#0a9ec7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9ec7,#0a9ec7 50%,transparent 50%);color:#fff}.bar.bar-calm .title{color:#fff}.bar.bar-calm.bar-footer{background-image:linear-gradient(180deg,#0a9ec7,#0a9ec7 50%,transparent 50%)}.bar.bar-assertive{border-color:#e42012;background-color:#ef473a;background-image:linear-gradient(0deg,#e42012,#e42012 50%,transparent 50%);color:#fff}.bar.bar-assertive .title{color:#fff}.bar.bar-assertive.bar-footer{background-image:linear-gradient(180deg,#e42012,#e42012 50%,transparent 50%)}.bar.bar-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.bar.bar-balanced .title{color:#fff}.bar.bar-balanced.bar-footer{background-image:linear-gradient(180deg,#28a54c,#0c63ee 50%,transparent 50%)}.bar.bar-energized{border-color:#e6b400;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b400,#e6b400 50%,transparent 50%);color:#fff}.bar.bar-energized .title{color:#fff}.bar.bar-energized.bar-footer{background-image:linear-gradient(180deg,#e6b400,#e6b400 50%,transparent 50%)}.bar.bar-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.bar.bar-royal .title{color:#fff}.bar.bar-royal.bar-footer{background-image:linear-gradient(180deg,#6b46e5,#6b46e5 50%,transparent 50%)}.bar.bar-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.bar.bar-dark .title{color:#fff}.bar.bar-dark.bar-footer{background-image:linear-gradient(180deg,#111,#111 50%,transparent 50%)}.bar .title{position:absolute;top:0;right:0;left:0;z-index:0;overflow:hidden;margin:0 10px;min-width:30px;height:43px;text-align:center;text-overflow:ellipsis;white-space:nowrap;font-size:17px;font-weight:500;line-height:44px}.bar .title.title-left{text-align:left}.bar .title.title-right{text-align:right}.bar .title a{color:inherit}.bar .button{z-index:1;padding:0 8px;min-width:initial;min-height:31px;font-weight:400;font-size:13px;line-height:32px}.bar .button .icon:before,.bar .button.button-icon:before,.bar .button.icon-left:before,.bar .button.icon-right:before,.bar .button.icon:before{padding-right:2px;padding-left:2px;font-size:20px;line-height:32px}.bar .button.button-icon{font-size:17px}.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before{vertical-align:top;font-size:32px;line-height:32px}.bar .button.button-clear{padding-right:2px;padding-left:2px;font-weight:300;font-size:17px}.bar .button.button-clear .icon:before,.bar .button.button-clear.icon-left:before,.bar .button.button-clear.icon-right:before,.bar .button.button-clear.icon:before{font-size:32px;line-height:32px}.bar .button.back-button{display:block;margin-right:5px;padding:0;white-space:nowrap;font-weight:400}.bar .button.back-button.activated,.bar .button.back-button.active{opacity:.2}.bar .button-bar>.button,.bar .buttons>.button{min-height:31px;line-height:32px}.bar .button+.button-bar,.bar .button-bar+.button{margin-left:5px}.bar .buttons,.bar .buttons.primary-buttons,.bar .buttons.secondary-buttons{display:inherit}.bar .buttons span{display:inline-block}.bar .buttons-left span{margin-right:5px;display:inherit}.bar .buttons-right span{margin-left:5px;display:inherit}.bar .buttons.pull-right,.bar .title+.button:last-child,.bar .title+.buttons,.bar>.button+.button:last-child,.bar>.button.pull-right{position:absolute;top:5px;right:5px;bottom:5px}.platform-android .nav-bar-has-subheader .bar{background-image:none}.platform-android .bar .back-button .icon:before{font-size:24px}.platform-android .bar .title{font-size:19px;line-height:44px}.bar-light .button{border-color:#ddd;background-color:#fff;color:#444}.bar-light .button:hover{color:#444;text-decoration:none}.bar-light .button.activated,.bar-light .button.active{border-color:#ccc;background-color:#fafafa;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-light .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-light .button.button-icon{border-color:transparent;background:0 0}.bar-stable .button{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.bar-stable .button:hover{color:#444;text-decoration:none}.bar-stable .button.activated,.bar-stable .button.active{border-color:#a2a2a2;background-color:#e5e5e5;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-stable .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-stable .button.button-icon{border-color:transparent;background:0 0}.bar-positive .button{border-color:#0c63ee;background-color:#387ef5;color:#fff}.bar-positive .button:hover{color:#fff;text-decoration:none}.bar-positive .button.activated,.bar-positive .button.active{border-color:#0c63ee;background-color:#0c63ee;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-positive .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-positive .button.button-icon{border-color:transparent;background:0 0}.bar-calm .button{border-color:#0a9ec7;background-color:#11c1f3;color:#fff}.bar-calm .button:hover{color:#fff;text-decoration:none}.bar-calm .button.activated,.bar-calm .button.active{border-color:#0a9ec7;background-color:#0a9ec7;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-calm .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-calm .button.button-icon{border-color:transparent;background:0 0}.bar-assertive .button{border-color:#e42012;background-color:#ef473a;color:#fff}.bar-assertive .button:hover{color:#fff;text-decoration:none}.bar-assertive .button.activated,.bar-assertive .button.active{border-color:#e42012;background-color:#e42012;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-assertive .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-assertive .button.button-icon{border-color:transparent;background:0 0}.bar-balanced .button{border-color:#28a54c;background-color:#33cd5f;color:#fff}.bar-balanced .button:hover{color:#fff;text-decoration:none}.bar-balanced .button.activated,.bar-balanced .button.active{border-color:#28a54c;background-color:#28a54c;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-balanced .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-balanced .button.button-icon{border-color:transparent;background:0 0}.bar-energized .button{border-color:#e6b400;background-color:#ffc900;color:#fff}.bar-energized .button:hover{color:#fff;text-decoration:none}.bar-energized .button.activated,.bar-energized .button.active{border-color:#e6b400;background-color:#e6b400;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-energized .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-energized .button.button-icon{border-color:transparent;background:0 0}.bar-royal .button{border-color:#6b46e5;background-color:#886aea;color:#fff}.bar-royal .button:hover{color:#fff;text-decoration:none}.bar-royal .button.activated,.bar-royal .button.active{border-color:#6b46e5;background-color:#6b46e5;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-royal .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-royal .button.button-icon{border-color:transparent;background:0 0}.bar-dark .button{border-color:#111;background-color:#444;color:#fff}.bar-dark .button:hover{color:#fff;text-decoration:none}.bar-dark .button.activated,.bar-dark .button.active{border-color:#000;background-color:#262626;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.bar-dark .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-dark .button.button-icon{border-color:transparent;background:0 0}.bar-header{top:0;border-top-width:0;border-bottom-width:1px}.bar-header.has-tabs-top,.tabs-top .bar-header{border-bottom-width:0;background-image:none}.bar-footer{bottom:0;border-top-width:1px;border-bottom-width:0;background-position:top;height:44px}.bar-footer.item-input-inset{position:absolute}.bar-tabs{padding:0}.bar-subheader{top:44px;display:block;height:44px}.bar-subfooter{bottom:44px;display:block;height:44px}.nav-bar-block{position:absolute;top:0;right:0;left:0;z-index:9}.bar .back-button.hide,.bar .buttons .hide{display:none}.nav-bar-tabs-top .bar{background-image:none}.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:horizontal;-moz-flex-direction:horizontal;-ms-flex-direction:horizontal;flex-direction:horizontal;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444;position:absolute;bottom:0;z-index:5;width:100%;height:49px;border-style:solid;border-top-width:1px;background-size:0;line-height:49px}.tabs .tab-item .badge{background-color:#444;color:#f8f8f8}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.tabs{padding-top:2px;border-top:none!important;border-bottom:none;background-position:top;background-size:100% 1px;background-repeat:no-repeat}}.tabs-light>.tabs,.tabs.tabs-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.tabs-light>.tabs .tab-item .badge,.tabs.tabs-light .tab-item .badge{background-color:#444;color:#fff}.tabs-stable>.tabs,.tabs.tabs-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.tabs-stable>.tabs .tab-item .badge,.tabs.tabs-stable .tab-item .badge{background-color:#444;color:#f8f8f8}.tabs-positive>.tabs,.tabs.tabs-positive{border-color:#0c63ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c63ee,#0c63ee 50%,transparent 50%);color:#fff}.tabs-positive>.tabs .tab-item .badge,.tabs.tabs-positive .tab-item .badge{background-color:#fff;color:#387ef5}.tabs-calm>.tabs,.tabs.tabs-calm{border-color:#0a9ec7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9ec7,#0a9ec7 50%,transparent 50%);color:#fff}.tabs-calm>.tabs .tab-item .badge,.tabs.tabs-calm .tab-item .badge{background-color:#fff;color:#11c1f3}.tabs-assertive>.tabs,.tabs.tabs-assertive{border-color:#e42012;background-color:#ef473a;background-image:linear-gradient(0deg,#e42012,#e42012 50%,transparent 50%);color:#fff}.tabs-assertive>.tabs .tab-item .badge,.tabs.tabs-assertive .tab-item .badge{background-color:#fff;color:#ef473a}.tabs-balanced>.tabs,.tabs.tabs-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.tabs-balanced>.tabs .tab-item .badge,.tabs.tabs-balanced .tab-item .badge{background-color:#fff;color:#33cd5f}.tabs-energized>.tabs,.tabs.tabs-energized{border-color:#e6b400;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b400,#e6b400 50%,transparent 50%);color:#fff}.tabs-energized>.tabs .tab-item .badge,.tabs.tabs-energized .tab-item .badge{background-color:#fff;color:#ffc900}.tabs-royal>.tabs,.tabs.tabs-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.tabs-royal>.tabs .tab-item .badge,.tabs.tabs-royal .tab-item .badge{background-color:#fff;color:#886aea}.tabs-dark>.tabs,.tabs.tabs-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.tabs-dark>.tabs .tab-item .badge,.tabs.tabs-dark .tab-item .badge{background-color:#fff;color:#444}.tabs-striped .tabs{background-color:#fff;background-image:none;border:none;border-bottom:1px solid #ddd;padding-top:2px}.tabs-striped .tab-item.activated,.tabs-striped .tab-item.active,.tabs-striped .tab-item.tab-item-active{margin-top:-2px;border-style:solid;border-width:2px 0 0;border-color:#444}.tabs-striped .tab-item.activated .badge,.tabs-striped .tab-item.active .badge,.tabs-striped .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-light .tabs{background-color:#fff}.tabs-striped.tabs-light .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-light .tab-item.activated,.tabs-striped.tabs-light .tab-item.active,.tabs-striped.tabs-light .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0;border-color:#444}.tabs-striped.tabs-stable .tabs{background-color:#f8f8f8}.tabs-striped.tabs-stable .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-stable .tab-item.activated,.tabs-striped.tabs-stable .tab-item.active,.tabs-striped.tabs-stable .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0;border-color:#444}.tabs-striped.tabs-positive .tabs{background-color:#387ef5}.tabs-striped.tabs-positive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-positive .tab-item.activated,.tabs-striped.tabs-positive .tab-item.active,.tabs-striped.tabs-positive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-calm .tabs{background-color:#11c1f3}.tabs-striped.tabs-calm .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-calm .tab-item.activated,.tabs-striped.tabs-calm .tab-item.active,.tabs-striped.tabs-calm .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-assertive .tabs{background-color:#ef473a}.tabs-striped.tabs-assertive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-assertive .tab-item.activated,.tabs-striped.tabs-assertive .tab-item.active,.tabs-striped.tabs-assertive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-balanced .tabs{background-color:#33cd5f}.tabs-striped.tabs-balanced .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-balanced .tab-item.activated,.tabs-striped.tabs-balanced .tab-item.active,.tabs-striped.tabs-balanced .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-energized .tabs{background-color:#ffc900}.tabs-striped.tabs-energized .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-energized .tab-item.activated,.tabs-striped.tabs-energized .tab-item.active,.tabs-striped.tabs-energized .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-royal .tabs{background-color:#886aea}.tabs-striped.tabs-royal .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-royal .tab-item.activated,.tabs-striped.tabs-royal .tab-item.active,.tabs-striped.tabs-royal .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-dark .tabs{background-color:#444}.tabs-striped.tabs-dark .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-dark .tab-item.activated,.tabs-striped.tabs-dark .tab-item.active,.tabs-striped.tabs-dark .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-background-light .tabs{background-color:#fff;background-image:none}.tabs-striped.tabs-background-stable .tabs{background-color:#f8f8f8;background-image:none}.tabs-striped.tabs-background-positive .tabs{background-color:#387ef5;background-image:none}.tabs-striped.tabs-background-calm .tabs{background-color:#11c1f3;background-image:none}.tabs-striped.tabs-background-assertive .tabs{background-color:#ef473a;background-image:none}.tabs-striped.tabs-background-balanced .tabs{background-color:#33cd5f;background-image:none}.tabs-striped.tabs-background-energized .tabs{background-color:#ffc900;background-image:none}.tabs-striped.tabs-background-royal .tabs{background-color:#886aea;background-image:none}.tabs-striped.tabs-background-dark .tabs{background-color:#444;background-image:none}.tabs-striped.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-color-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-light .tab-item.activated,.tabs-striped.tabs-color-light .tab-item.active,.tabs-striped.tabs-color-light .tab-item.tab-item-active{margin-top:-2px;color:#fff;border:0 solid #fff;border-top-width:2px}.tabs-striped.tabs-color-light .tab-item.activated .badge,.tabs-striped.tabs-color-light .tab-item.active .badge,.tabs-striped.tabs-color-light .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-striped.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-stable .tab-item.activated,.tabs-striped.tabs-color-stable .tab-item.active,.tabs-striped.tabs-color-stable .tab-item.tab-item-active{margin-top:-2px;color:#f8f8f8;border:0 solid #f8f8f8;border-top-width:2px}.tabs-striped.tabs-color-stable .tab-item.activated .badge,.tabs-striped.tabs-color-stable .tab-item.active .badge,.tabs-striped.tabs-color-stable .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-striped.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-positive .tab-item.activated,.tabs-striped.tabs-color-positive .tab-item.active,.tabs-striped.tabs-color-positive .tab-item.tab-item-active{margin-top:-2px;color:#387ef5;border:0 solid #387ef5;border-top-width:2px}.tabs-striped.tabs-color-positive .tab-item.activated .badge,.tabs-striped.tabs-color-positive .tab-item.active .badge,.tabs-striped.tabs-color-positive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-striped.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-calm .tab-item.activated,.tabs-striped.tabs-color-calm .tab-item.active,.tabs-striped.tabs-color-calm .tab-item.tab-item-active{margin-top:-2px;color:#11c1f3;border:0 solid #11c1f3;border-top-width:2px}.tabs-striped.tabs-color-calm .tab-item.activated .badge,.tabs-striped.tabs-color-calm .tab-item.active .badge,.tabs-striped.tabs-color-calm .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-striped.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-assertive .tab-item.activated,.tabs-striped.tabs-color-assertive .tab-item.active,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active{margin-top:-2px;color:#ef473a;border:0 solid #ef473a;border-top-width:2px}.tabs-striped.tabs-color-assertive .tab-item.activated .badge,.tabs-striped.tabs-color-assertive .tab-item.active .badge,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-striped.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-balanced .tab-item.activated,.tabs-striped.tabs-color-balanced .tab-item.active,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active{margin-top:-2px;color:#33cd5f;border:0 solid #33cd5f;border-top-width:2px}.tabs-striped.tabs-color-balanced .tab-item.activated .badge,.tabs-striped.tabs-color-balanced .tab-item.active .badge,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-striped.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-energized .tab-item.activated,.tabs-striped.tabs-color-energized .tab-item.active,.tabs-striped.tabs-color-energized .tab-item.tab-item-active{margin-top:-2px;color:#ffc900;border:0 solid #ffc900;border-top-width:2px}.tabs-striped.tabs-color-energized .tab-item.activated .badge,.tabs-striped.tabs-color-energized .tab-item.active .badge,.tabs-striped.tabs-color-energized .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-striped.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-royal .tab-item.activated,.tabs-striped.tabs-color-royal .tab-item.active,.tabs-striped.tabs-color-royal .tab-item.tab-item-active{margin-top:-2px;color:#886aea;border:0 solid #886aea;border-top-width:2px}.tabs-striped.tabs-color-royal .tab-item.activated .badge,.tabs-striped.tabs-color-royal .tab-item.active .badge,.tabs-striped.tabs-color-royal .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-dark .tab-item.activated,.tabs-striped.tabs-color-dark .tab-item.active,.tabs-striped.tabs-color-dark .tab-item.tab-item-active{margin-top:-2px;color:#444;border:0 solid #444;border-top-width:2px}.tabs-striped.tabs-color-dark .tab-item.activated .badge,.tabs-striped.tabs-color-dark .tab-item.active .badge,.tabs-striped.tabs-color-dark .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-background-light .tabs,.tabs-background-light>.tabs{background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);border-color:#ddd}.tabs-background-stable .tabs,.tabs-background-stable>.tabs{background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);border-color:#b2b2b2}.tabs-background-positive .tabs,.tabs-background-positive>.tabs{background-color:#387ef5;background-image:linear-gradient(0deg,#0c63ee,#0c63ee 50%,transparent 50%);border-color:#0c63ee}.tabs-background-calm .tabs,.tabs-background-calm>.tabs{background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9ec7,#0a9ec7 50%,transparent 50%);border-color:#0a9ec7}.tabs-background-assertive .tabs,.tabs-background-assertive>.tabs{background-color:#ef473a;background-image:linear-gradient(0deg,#e42012,#e42012 50%,transparent 50%);border-color:#e42012}.tabs-background-balanced .tabs,.tabs-background-balanced>.tabs{background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);border-color:#28a54c}.tabs-background-energized .tabs,.tabs-background-energized>.tabs{background-color:#ffc900;background-image:linear-gradient(0deg,#e6b400,#e6b400 50%,transparent 50%);border-color:#e6b400}.tabs-background-royal .tabs,.tabs-background-royal>.tabs{background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);border-color:#6b46e5}.tabs-background-dark .tabs,.tabs-background-dark>.tabs{background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);border-color:#111}.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-color-light .tab-item .badge{opacity:.4}.tabs-color-light .tab-item.activated,.tabs-color-light .tab-item.active,.tabs-color-light .tab-item.tab-item-active{color:#fff;border:0 solid #fff}.tabs-color-light .tab-item.activated .badge,.tabs-color-light .tab-item.active .badge,.tabs-color-light .tab-item.tab-item-active .badge{opacity:1}.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-color-stable .tab-item.activated,.tabs-color-stable .tab-item.active,.tabs-color-stable .tab-item.tab-item-active{color:#f8f8f8;border:0 solid #f8f8f8}.tabs-color-stable .tab-item.activated .badge,.tabs-color-stable .tab-item.active .badge,.tabs-color-stable .tab-item.tab-item-active .badge{opacity:1}.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-color-positive .tab-item.activated,.tabs-color-positive .tab-item.active,.tabs-color-positive .tab-item.tab-item-active{color:#387ef5;border:0 solid #387ef5}.tabs-color-positive .tab-item.activated .badge,.tabs-color-positive .tab-item.active .badge,.tabs-color-positive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-color-calm .tab-item.activated,.tabs-color-calm .tab-item.active,.tabs-color-calm .tab-item.tab-item-active{color:#11c1f3;border:0 solid #11c1f3}.tabs-color-calm .tab-item.activated .badge,.tabs-color-calm .tab-item.active .badge,.tabs-color-calm .tab-item.tab-item-active .badge{opacity:1}.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-color-assertive .tab-item.activated,.tabs-color-assertive .tab-item.active,.tabs-color-assertive .tab-item.tab-item-active{color:#ef473a;border:0 solid #ef473a}.tabs-color-assertive .tab-item.activated .badge,.tabs-color-assertive .tab-item.active .badge,.tabs-color-assertive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-color-balanced .tab-item.activated,.tabs-color-balanced .tab-item.active,.tabs-color-balanced .tab-item.tab-item-active{color:#33cd5f;border:0 solid #33cd5f}.tabs-color-balanced .tab-item.activated .badge,.tabs-color-balanced .tab-item.active .badge,.tabs-color-balanced .tab-item.tab-item-active .badge{opacity:1}.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-color-energized .tab-item.activated,.tabs-color-energized .tab-item.active,.tabs-color-energized .tab-item.tab-item-active{color:#ffc900;border:0 solid #ffc900}.tabs-color-energized .tab-item.activated .badge,.tabs-color-energized .tab-item.active .badge,.tabs-color-energized .tab-item.tab-item-active .badge{opacity:1}.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-color-royal .tab-item.activated,.tabs-color-royal .tab-item.active,.tabs-color-royal .tab-item.tab-item-active{color:#886aea;border:0 solid #886aea}.tabs-color-royal .tab-item.activated .badge,.tabs-color-royal .tab-item.active .badge,.tabs-color-royal .tab-item.tab-item-active .badge{opacity:1}.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-color-dark .tab-item.activated,.tabs-color-dark .tab-item.active,.tabs-color-dark .tab-item.tab-item-active{color:#444;border:0 solid #444}.tabs-color-dark .tab-item.activated .badge,.tabs-color-dark .tab-item.active .badge,.tabs-color-dark .tab-item.tab-item-active .badge{opacity:1}ion-tabs.tabs-color-active-light .tab-item{color:#444}ion-tabs.tabs-color-active-light .tab-item.activated,ion-tabs.tabs-color-active-light .tab-item.active,ion-tabs.tabs-color-active-light .tab-item.tab-item-active{color:#fff}ion-tabs.tabs-color-active-stable .tab-item{color:#444}ion-tabs.tabs-color-active-stable .tab-item.activated,ion-tabs.tabs-color-active-stable .tab-item.active,ion-tabs.tabs-color-active-stable .tab-item.tab-item-active{color:#f8f8f8}ion-tabs.tabs-color-active-positive .tab-item{color:#444}ion-tabs.tabs-color-active-positive .tab-item.activated,ion-tabs.tabs-color-active-positive .tab-item.active,ion-tabs.tabs-color-active-positive .tab-item.tab-item-active{color:#387ef5}ion-tabs.tabs-color-active-calm .tab-item{color:#444}ion-tabs.tabs-color-active-calm .tab-item.activated,ion-tabs.tabs-color-active-calm .tab-item.active,ion-tabs.tabs-color-active-calm .tab-item.tab-item-active{color:#11c1f3}ion-tabs.tabs-color-active-assertive .tab-item{color:#444}ion-tabs.tabs-color-active-assertive .tab-item.activated,ion-tabs.tabs-color-active-assertive .tab-item.active,ion-tabs.tabs-color-active-assertive .tab-item.tab-item-active{color:#ef473a}ion-tabs.tabs-color-active-balanced .tab-item{color:#444}ion-tabs.tabs-color-active-balanced .tab-item.activated,ion-tabs.tabs-color-active-balanced .tab-item.active,ion-tabs.tabs-color-active-balanced .tab-item.tab-item-active{color:#33cd5f}ion-tabs.tabs-color-active-energized .tab-item{color:#444}ion-tabs.tabs-color-active-energized .tab-item.activated,ion-tabs.tabs-color-active-energized .tab-item.active,ion-tabs.tabs-color-active-energized .tab-item.tab-item-active{color:#ffc900}ion-tabs.tabs-color-active-royal .tab-item{color:#444}ion-tabs.tabs-color-active-royal .tab-item.activated,ion-tabs.tabs-color-active-royal .tab-item.active,ion-tabs.tabs-color-active-royal .tab-item.tab-item-active{color:#886aea}ion-tabs.tabs-color-active-dark .tab-item{color:#fff}ion-tabs.tabs-color-active-dark .tab-item.activated,ion-tabs.tabs-color-active-dark .tab-item.active,ion-tabs.tabs-color-active-dark .tab-item.tab-item-active{color:#444}.tabs-top.tabs-striped{padding-bottom:0}.tabs-top.tabs-striped .tab-item{background:0 0;-webkit-transition:color .1s ease;-moz-transition:color .1s ease;-ms-transition:color .1s ease;-o-transition:color .1s ease;transition:color .1s ease}.tabs-top.tabs-striped .tab-item.activated,.tabs-top.tabs-striped .tab-item.active,.tabs-top.tabs-striped .tab-item.tab-item-active{margin-top:1px;border-width:0 0 2px!important;border-style:solid}.tabs-top.tabs-striped .tab-item.activated>.badge,.tabs-top.tabs-striped .tab-item.activated>i,.tabs-top.tabs-striped .tab-item.active>.badge,.tabs-top.tabs-striped .tab-item.active>i,.tabs-top.tabs-striped .tab-item.tab-item-active>.badge,.tabs-top.tabs-striped .tab-item.tab-item-active>i{margin-top:-1px}.tabs-top.tabs-striped .tab-item .badge{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease}.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active i{display:block;margin-top:-1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item{margin-top:1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active i{margin-top:-.1em}.tabs-top>.tabs,.tabs.tabs-top{top:44px;padding-top:0;background-position:bottom;border-top-width:0;border-bottom-width:1px}.tabs-top>.tabs .tab-item.activated .badge,.tabs-top>.tabs .tab-item.active .badge,.tabs-top>.tabs .tab-item.tab-item-active .badge,.tabs.tabs-top .tab-item.activated .badge,.tabs.tabs-top .tab-item.active .badge,.tabs.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-top~.bar-header{border-bottom-width:0}.tab-item{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;max-width:150px;height:100%;color:inherit;text-align:center;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;font-weight:400;font-size:14px;font-family:"Helvetica Neue",Roboto,"Segoe UI",sans-serif;opacity:.7}.tab-item:hover{cursor:pointer}.tab-item.tab-hidden,.tabs-item-hide>.tabs,.tabs.tabs-item-hide{display:none}.tabs-icon-bottom.tabs .tab-item,.tabs-icon-bottom>.tabs .tab-item,.tabs-icon-top.tabs .tab-item,.tabs-icon-top>.tabs .tab-item{font-size:10px;line-height:14px}.tab-item .icon{display:block;margin:0 auto;height:32px;font-size:32px}.tabs-icon-left.tabs .tab-item,.tabs-icon-left>.tabs .tab-item,.tabs-icon-right.tabs .tab-item,.tabs-icon-right>.tabs .tab-item{font-size:10px}.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left.tabs .tab-item .tab-title,.tabs-icon-left>.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .tab-title,.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right.tabs .tab-item .tab-title,.tabs-icon-right>.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .tab-title{display:inline-block;vertical-align:top;margin-top:-.1em}.tabs-icon-left.tabs .tab-item .icon:before,.tabs-icon-left.tabs .tab-item .tab-title:before,.tabs-icon-left>.tabs .tab-item .icon:before,.tabs-icon-left>.tabs .tab-item .tab-title:before,.tabs-icon-right.tabs .tab-item .icon:before,.tabs-icon-right.tabs .tab-item .tab-title:before,.tabs-icon-right>.tabs .tab-item .icon:before,.tabs-icon-right>.tabs .tab-item .tab-title:before{font-size:24px;line-height:49px}.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .icon{padding-right:3px}.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .icon{padding-left:3px}.tabs-icon-only.tabs .icon,.tabs-icon-only>.tabs .icon{line-height:inherit}.tab-item.has-badge{position:relative}.tab-item .badge{position:absolute;top:4%;right:33%;right:calc(50% - 26px);padding:1px 6px;height:auto;font-size:12px;line-height:16px}.tab-item.activated,.tab-item.active,.tab-item.tab-item-active{opacity:1}.tab-item.activated.tab-item-light,.tab-item.active.tab-item-light,.tab-item.tab-item-active.tab-item-light{color:#fff}.tab-item.activated.tab-item-stable,.tab-item.active.tab-item-stable,.tab-item.tab-item-active.tab-item-stable{color:#f8f8f8}.tab-item.activated.tab-item-positive,.tab-item.active.tab-item-positive,.tab-item.tab-item-active.tab-item-positive{color:#387ef5}.tab-item.activated.tab-item-calm,.tab-item.active.tab-item-calm,.tab-item.tab-item-active.tab-item-calm{color:#11c1f3}.tab-item.activated.tab-item-assertive,.tab-item.active.tab-item-assertive,.tab-item.tab-item-active.tab-item-assertive{color:#ef473a}.tab-item.activated.tab-item-balanced,.tab-item.active.tab-item-balanced,.tab-item.tab-item-active.tab-item-balanced{color:#33cd5f}.tab-item.activated.tab-item-energized,.tab-item.active.tab-item-energized,.tab-item.tab-item-active.tab-item-energized{color:#ffc900}.tab-item.activated.tab-item-royal,.tab-item.active.tab-item-royal,.tab-item.tab-item-active.tab-item-royal{color:#886aea}.tab-item.activated.tab-item-dark,.tab-item.active.tab-item-dark,.tab-item.tab-item-active.tab-item-dark{color:#444}.item.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:0}.item.tabs .icon:before{position:relative}.tab-item.disabled,.tab-item[disabled]{opacity:.4;cursor:default;pointer-events:none}.menu{position:absolute;top:0;bottom:0;z-index:0;overflow:hidden;min-height:100%;max-height:100%;width:275px;background-color:#fff}.menu .scroll-content{z-index:10}.menu .bar-header{z-index:11}.menu-content{-webkit-transform:none;transform:none;box-shadow:-1px 0 2px rgba(0,0,0,.2),1px 0 2px rgba(0,0,0,.2)}.menu-open .menu-content .pane,.menu-open .menu-content .scroll-content{pointer-events:none}.grade-b .menu-content,.grade-c .menu-content{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;right:-1px;left:-1px;border-right:1px solid #ccc;border-left:1px solid #ccc;box-shadow:none}.menu-left{left:0}.menu-right{right:0}.aside-open.aside-resizing .menu-right{display:none}.menu-animated{-webkit-transition:-webkit-transform 200ms ease;transition:transform 200ms ease}.modal-backdrop,.modal-backdrop-bg{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%}.modal-backdrop-bg{pointer-events:none}.modal{display:block;position:absolute;top:0;z-index:10;overflow:hidden;min-height:100%;width:100%;background-color:#fff}@media (min-width:680px){.modal{top:20%;right:20%;bottom:20%;left:20%;min-height:240px;width:60%}.modal.ng-leave-active{bottom:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader,.platform-ios.platform-cordova .modal-wrapper .modal .has-header,.platform-ios.platform-cordova .modal-wrapper .modal .tabs-top>.tabs,.platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top{top:44px}.platform-ios.platform-cordova .modal-wrapper .modal .has-subheader{top:88px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-tabs-top{top:93px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-subheader.has-tabs-top{top:137px}.modal-backdrop-bg{-webkit-transition:opacity 300ms ease-in-out;transition:opacity 300ms ease-in-out;background-color:#000;opacity:0}.active .modal-backdrop-bg{opacity:.5}}.modal-open{pointer-events:none}.modal-open .modal,.modal-open .modal-backdrop{pointer-events:auto}.modal-open.loading-active .modal,.modal-open.loading-active .modal-backdrop{pointer-events:none}.popover-backdrop{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%;background-color:transparent}.popover-backdrop.active{background-color:rgba(0,0,0,.1)}.popover{position:absolute;top:25%;left:50%;z-index:10;display:block;margin-top:12px;margin-left:-110px;height:280px;width:220px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4);opacity:0}.popover .item:first-child{border-top:0}.popover .item:last-child{border-bottom:0}.popover.popover-bottom{margin-top:-12px}.popover,.popover .bar-header{border-radius:2px}.popover .scroll-content{z-index:1;margin:2px 0}.popover .bar-header{border-bottom-right-radius:0;border-bottom-left-radius:0}.popover .has-header{border-top-right-radius:0;border-top-left-radius:0}.popover-arrow{display:none}.platform-ios .popover{box-shadow:0 0 40px rgba(0,0,0,.08);border-radius:10px}.platform-ios .popover .bar-header{-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-webkit-border-top-left-radius:10px;border-top-left-radius:10px}.platform-ios .popover .scroll-content{margin:8px 0;border-radius:10px}.platform-ios .popover .scroll-content.has-header{margin-top:0}.platform-ios .popover-arrow{position:absolute;display:block;top:-17px;width:30px;height:19px;overflow:hidden}.platform-ios .popover-arrow:after{position:absolute;top:12px;left:5px;width:20px;height:20px;background-color:#fff;border-radius:3px;content:'';-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.platform-ios .popover-bottom .popover-arrow{top:auto;bottom:-10px}.platform-ios .popover-bottom .popover-arrow:after{top:-6px}.platform-android .popover{margin-top:-32px;background-color:#fafafa;box-shadow:0 2px 6px rgba(0,0,0,.35)}.platform-android .popover .item{border-color:#fafafa;background-color:#fafafa;color:#4d4d4d}.platform-android .popover.popover-bottom{margin-top:32px}.platform-android .popover-backdrop,.platform-android .popover-backdrop.active{background-color:transparent}.popover-open{pointer-events:none}.popover-open .popover,.popover-open .popover-backdrop{pointer-events:auto}.popover-open.loading-active .popover,.popover-open.loading-active .popover-backdrop{pointer-events:none}@media (min-width:680px){.popover{width:360px}}.popup-container{position:absolute;top:0;left:0;bottom:0;right:0;background:0 0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;z-index:12;visibility:hidden}.popup-container.popup-showing{visibility:visible}.popup-container.popup-hidden .popup{-webkit-animation-name:scaleOut;animation-name:scaleOut;-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container.active .popup{-webkit-animation-name:superScaleIn;animation-name:superScaleIn;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container .popup{width:250px;max-width:100%;max-height:90%;border-radius:0;background-color:rgba(255,255,255,.9);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.popup-container input,.popup-container textarea{width:100%}.popup-head{padding:15px 10px;border-bottom:1px solid #eee;text-align:center}.popup-title{margin:0;padding:0;font-size:15px}.popup-sub-title{margin:5px 0 0;padding:0;font-weight:400;font-size:11px}.popup-body{padding:10px;overflow:auto}.popup-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding:10px;min-height:65px}.popup-buttons .button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;min-height:45px;border-radius:2px;line-height:20px;margin-right:5px}.popup-buttons .button:last-child{margin-right:0}.popup-open,.popup-open.modal-open .modal{pointer-events:none}.popup-open .popup,.popup-open .popup-backdrop{pointer-events:auto}.loading-container{position:absolute;left:0;top:0;right:0;bottom:0;z-index:13;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-transition:.2s opacity linear;transition:.2s opacity linear;visibility:hidden;opacity:0}.loading-container:not(.visible) .icon,.loading-container:not(.visible) .spinner{display:none}.loading-container.visible{visibility:visible}.loading-container.active{opacity:1}.loading-container .loading{padding:20px;border-radius:5px;background-color:rgba(0,0,0,.7);color:#fff;text-align:center;text-overflow:ellipsis;font-size:15px}.loading-container .loading h1,.loading-container .loading h2,.loading-container .loading h3,.loading-container .loading h4,.loading-container .loading h5,.loading-container .loading h6{color:#fff}.item{border-color:#ddd;background-color:#fff;color:#444;position:relative;z-index:2;display:block;margin:-1px;padding:16px;border-width:1px;border-style:solid;font-size:16px}.item h2{margin:0 0 2px;font-size:16px;font-weight:400}.item h3{margin:0 0 4px;font-size:14px}.item h4{margin:0 0 4px;font-size:12px}.item h5,.item h6{margin:0 0 3px;font-size:10px}.item p{color:#666;font-size:14px;margin-bottom:2px}.item h1:last-child,.item h2:last-child,.item h3:last-child,.item h4:last-child,.item h5:last-child,.item h6:last-child,.item p:last-child{margin-bottom:0}.item .badge{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;position:absolute;top:16px;right:32px}.item.item-button-right .badge{right:67px}.item.item-divider .badge{top:8px}.item .badge+.badge{margin-right:5px}.item.item-light{border-color:#ddd;background-color:#fff;color:#444}.item.item-stable{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item.item-positive{border-color:#0c63ee;background-color:#387ef5;color:#fff}.item.item-calm{border-color:#0a9ec7;background-color:#11c1f3;color:#fff}.item.item-assertive{border-color:#e42012;background-color:#ef473a;color:#fff}.item.item-balanced{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item.item-energized{border-color:#e6b400;background-color:#ffc900;color:#fff}.item.item-royal{border-color:#6b46e5;background-color:#886aea;color:#fff}.item.item-dark{border-color:#111;background-color:#444;color:#fff}.item[ng-click]:hover{cursor:pointer}.item-borderless,.list-borderless .item{border-width:0}.item .item-content.activated,.item .item-content.active,.item-complex.activated .item-content,.item-complex.active .item-content,.item.activated,.item.active{border-color:#ccc;background-color:#D9D9D9}.item .item-content.activated.item-light,.item .item-content.active.item-light,.item-complex.activated .item-content.item-light,.item-complex.active .item-content.item-light,.item.activated.item-light,.item.active.item-light{border-color:#ccc;background-color:#fafafa}.item .item-content.activated.item-stable,.item .item-content.active.item-stable,.item-complex.activated .item-content.item-stable,.item-complex.active .item-content.item-stable,.item.activated.item-stable,.item.active.item-stable{border-color:#a2a2a2;background-color:#e5e5e5}.item .item-content.activated.item-positive,.item .item-content.active.item-positive,.item-complex.activated .item-content.item-positive,.item-complex.active .item-content.item-positive,.item.activated.item-positive,.item.active.item-positive{border-color:#0c63ee;background-color:#0c63ee}.item .item-content.activated.item-calm,.item .item-content.active.item-calm,.item-complex.activated .item-content.item-calm,.item-complex.active .item-content.item-calm,.item.activated.item-calm,.item.active.item-calm{border-color:#0a9ec7;background-color:#0a9ec7}.item .item-content.activated.item-assertive,.item .item-content.active.item-assertive,.item-complex.activated .item-content.item-assertive,.item-complex.active .item-content.item-assertive,.item.activated.item-assertive,.item.active.item-assertive{border-color:#e42012;background-color:#e42012}.item .item-content.activated.item-balanced,.item .item-content.active.item-balanced,.item-complex.activated .item-content.item-balanced,.item-complex.active .item-content.item-balanced,.item.activated.item-balanced,.item.active.item-balanced{border-color:#28a54c;background-color:#28a54c}.item .item-content.activated.item-energized,.item .item-content.active.item-energized,.item-complex.activated .item-content.item-energized,.item-complex.active .item-content.item-energized,.item.activated.item-energized,.item.active.item-energized{border-color:#e6b400;background-color:#e6b400}.item .item-content.activated.item-royal,.item .item-content.active.item-royal,.item-complex.activated .item-content.item-royal,.item-complex.active .item-content.item-royal,.item.activated.item-royal,.item.active.item-royal{border-color:#6b46e5;background-color:#6b46e5}.item .item-content.activated.item-dark,.item .item-content.active.item-dark,.item-complex.activated .item-content.item-dark,.item-complex.active .item-content.item-dark,.item.activated.item-dark,.item.active.item-dark{border-color:#000;background-color:#262626}.item,.item h1,.item h2,.item h3,.item h4,.item h5,.item h6,.item p,.item-content,.item-content h1,.item-content h2,.item-content h3,.item-content h4,.item-content h5,.item-content h6,.item-content p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a.item{color:inherit;text-decoration:none}a.item:focus,a.item:hover{text-decoration:none}.item-complex,a.item.item-complex,button.item.item-complex{padding:0}.item-complex .item-content,.item-radio .item-content{position:relative;z-index:2;padding:16px 49px 16px 16px;border:none;background-color:#fff}a.item-content{display:block;color:inherit;text-decoration:none}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p,.item-complex.item-text-wrap,.item-complex.item-text-wrap .item-content,.item-complex.item-text-wrap h1,.item-complex.item-text-wrap h2,.item-complex.item-text-wrap h3,.item-complex.item-text-wrap h4,.item-complex.item-text-wrap h5,.item-complex.item-text-wrap h6,.item-complex.item-text-wrap p,.item-text-wrap,.item-text-wrap .item,.item-text-wrap .item-content,.item-text-wrap h1,.item-text-wrap h2,.item-text-wrap h3,.item-text-wrap h4,.item-text-wrap h5,.item-text-wrap h6,.item-text-wrap p{overflow:visible;white-space:normal}.item-complex.item-light>.item-content{border-color:#ddd;background-color:#fff;color:#444}.item-complex.item-light>.item-content.active,.item-complex.item-light>.item-content:active{border-color:#ccc;background-color:#fafafa}.item-complex.item-stable>.item-content{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item-complex.item-stable>.item-content.active,.item-complex.item-stable>.item-content:active{border-color:#a2a2a2;background-color:#e5e5e5}.item-complex.item-positive>.item-content{border-color:#0c63ee;background-color:#387ef5;color:#fff}.item-complex.item-positive>.item-content.active,.item-complex.item-positive>.item-content:active{border-color:#0c63ee;background-color:#0c63ee}.item-complex.item-calm>.item-content{border-color:#0a9ec7;background-color:#11c1f3;color:#fff}.item-complex.item-calm>.item-content.active,.item-complex.item-calm>.item-content:active{border-color:#0a9ec7;background-color:#0a9ec7}.item-complex.item-assertive>.item-content{border-color:#e42012;background-color:#ef473a;color:#fff}.item-complex.item-assertive>.item-content.active,.item-complex.item-assertive>.item-content:active{border-color:#e42012;background-color:#e42012}.item-complex.item-balanced>.item-content{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item-complex.item-balanced>.item-content.active,.item-complex.item-balanced>.item-content:active{border-color:#28a54c;background-color:#28a54c}.item-complex.item-energized>.item-content{border-color:#e6b400;background-color:#ffc900;color:#fff}.item-complex.item-energized>.item-content.active,.item-complex.item-energized>.item-content:active{border-color:#e6b400;background-color:#e6b400}.item-complex.item-royal>.item-content{border-color:#6b46e5;background-color:#886aea;color:#fff}.item-complex.item-royal>.item-content.active,.item-complex.item-royal>.item-content:active{border-color:#6b46e5;background-color:#6b46e5}.item-complex.item-dark>.item-content{border-color:#111;background-color:#444;color:#fff}.item-complex.item-dark>.item-content.active,.item-complex.item-dark>.item-content:active{border-color:#000;background-color:#262626}.item-icon-left .icon,.item-icon-right .icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-icon-left .icon:before,.item-icon-right .icon:before{display:block;width:32px;text-align:center}.item .fill-icon{min-width:30px;min-height:30px;font-size:28px}.item-icon-left{padding-left:54px}.item-icon-left .icon{left:11px}.item-complex.item-icon-left{padding-left:0}.item-complex.item-icon-left .item-content{padding-left:54px}.item-icon-right{padding-right:54px}.item-icon-right .icon{right:11px}.item-complex.item-icon-right{padding-right:0}.item-complex.item-icon-right .item-content{padding-right:54px}.item-icon-left.item-icon-right .icon:first-child{right:auto}.item-icon-left .item-delete .icon,.item-icon-left.item-icon-right .icon:last-child{left:auto}.item-icon-left .icon-accessory,.item-icon-right .icon-accessory{color:#ccc;font-size:16px}.item-icon-left .icon-accessory{left:3px}.item-icon-right .icon-accessory{right:3px}.item-button-left{padding-left:72px}.item-button-left .item-content>.button,.item-button-left>.button{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;left:11px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-left .item-content>.button .icon:before,.item-button-left>.button .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-left .item-content>.button>.button,.item-button-left>.button>.button{margin:0 2px;min-height:34px;font-size:18px;line-height:32px}.item-button-right,a.item.item-button-right,button.item.item-button-right{padding-right:80px}.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.button,.item-button-right>.buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;right:16px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-right .item-content>.button .icon:before,.item-button-right .item-content>.buttons .icon:before,.item-button-right>.button .icon:before,.item-button-right>.buttons .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-right .item-content>.button>.button,.item-button-right .item-content>.buttons>.button,.item-button-right>.button>.button,.item-button-right>.buttons>.button{margin:0 2px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:72px;min-height:72px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{position:absolute;top:16px;left:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-avatar-right,.item-avatar-right .item-content{padding-right:72px;min-height:72px}.item-avatar-right .item-content .item-image,.item-avatar-right .item-content>img:first-child,.item-avatar-right .item-image,.item-avatar-right>img:first-child{position:absolute;top:16px;right:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-thumbnail-left,.item-thumbnail-left .item-content{padding-top:8px;padding-left:106px;min-height:100px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{position:absolute;top:10px;left:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-left.item-complex,.item-avatar.item-complex,.item-thumbnail-left.item-complex{padding-top:0;padding-left:0}.item-thumbnail-right,.item-thumbnail-right .item-content{padding-top:8px;padding-right:106px;min-height:100px}.item-thumbnail-right .item-content .item-image,.item-thumbnail-right .item-content>img:first-child,.item-thumbnail-right .item-image,.item-thumbnail-right>img:first-child{position:absolute;top:10px;right:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-right.item-complex,.item-thumbnail-right.item-complex{padding-top:0;padding-right:0}.item-image{padding:0;text-align:center}.item-image .list-img,.item-image img:first-child{width:100%;vertical-align:middle}.item-body{overflow:auto;padding:16px;text-overflow:inherit;white-space:normal}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p{margin-top:16px;margin-bottom:16px}.item-divider{padding-top:8px;padding-bottom:8px;min-height:30px;background-color:#f5f5f5;color:#222;font-weight:500}.item-divider-ios,.platform-ios .item-divider-platform{padding-top:26px;text-transform:uppercase;font-weight:300;font-size:13px;background-color:#efeff4;color:#555}.item-divider-android,.platform-android .item-divider-platform{font-weight:300;font-size:13px}.item-note{float:right;color:#aaa;font-size:14px}.item-left-editable .item-content,.item-right-editable .item-content{-webkit-transition-duration:250ms;transition-duration:250ms;-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform}.item-left-editing.item-left-editable .item-content,.list-left-editing .item-left-editable .item-content{-webkit-transform:translate3d(50px,0,0);transform:translate3d(50px,0,0)}.item-remove-animate.ng-leave{-webkit-transition-duration:300ms;transition-duration:300ms}.item-remove-animate.ng-leave .item-content,.item-remove-animate.ng-leave:last-of-type{-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;-webkit-transition-property:all;transition-property:all}.item-remove-animate.ng-leave.ng-leave-active .item-content{opacity:0;-webkit-transform:translate3d(-100%,0,0)!important;transform:translate3d(-100%,0,0)!important}.item-remove-animate.ng-leave.ng-leave-active:last-of-type{opacity:0}.item-remove-animate.ng-leave.ng-leave-active~ion-item:not(.ng-leave){-webkit-transform:translate3d(0,-webkit-calc(-100% + 1px),0);transform:translate3d(0,calc(-100% + 1px),0);-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transition-timing-function:cubic-bezier(.25,.81,.24,1);transition-timing-function:cubic-bezier(.25,.81,.24,1);-webkit-transition-property:all;transition-property:all}.item-left-edit{-webkit-transition:all ease-in-out 125ms;transition:all ease-in-out 125ms;position:absolute;top:0;left:0;z-index:0;width:50px;height:100%;line-height:100%;display:none;opacity:0;-webkit-transform:translate3d(-21px,0,0);transform:translate3d(-21px,0,0)}.item-left-edit .button{height:100%}.item-left-edit .button.icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%}.item-left-edit.visible{display:block}.item-left-edit.visible.active{opacity:1;-webkit-transform:translate3d(8px,0,0);transform:translate3d(8px,0,0)}.list-left-editing .item-left-edit{-webkit-transition-delay:125ms;transition-delay:125ms}.item-delete .button.icon{color:#ef473a;font-size:24px}.item-delete .button.icon:hover{opacity:.7}.item-right-edit{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms;position:absolute;top:0;right:0;z-index:3;width:75px;height:100%;background:inherit;padding-left:20px;display:block;opacity:0;-webkit-transform:translate3d(75px,0,0);transform:translate3d(75px,0,0)}.item-right-edit .button{min-width:50px;height:100%}.item-right-edit .button.icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-right-edit.visible{display:block}.item-right-edit.visible.active{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.item-reorder .button.icon{color:#444;font-size:32px}.item-reordering{position:absolute;left:0;top:0;z-index:9;width:100%;box-shadow:0 0 10px 0 #aaa}.item-reordering .item-reorder{z-index:9}.item-placeholder{opacity:.7}.item-options{position:absolute;top:0;right:0;z-index:1;height:100%}.item-options .button{height:100%;border:none;border-radius:0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.item-options .button:before{margin:0 auto}.list{position:relative;padding-top:1px;padding-bottom:1px;padding-left:0;margin-bottom:20px}.list:last-child{margin-bottom:0}.list:last-child.card{margin-bottom:40px}.list-header{margin-top:20px;padding:5px 15px;background-color:transparent;color:#222;font-weight:700}.card.list .list-item{padding-right:1px;padding-left:1px}.card,.list-inset{overflow:hidden;margin:20px 10px;border-radius:2px;background-color:#fff}.card{padding-top:1px;padding-bottom:1px;box-shadow:0 1px 3px rgba(0,0,0,.3)}.card .item{border-left:0;border-right:0}.card .item:first-child{border-top:0}.card .item:last-child{border-bottom:0}.padding .card,.padding .list-inset{margin-left:0;margin-right:0}.card .item:first-child,.card .item:first-child .item-content,.list-inset .item:first-child,.list-inset .item:first-child .item-content,.padding>.list .item:first-child,.padding>.list .item:first-child .item-content{border-top-left-radius:2px;border-top-right-radius:2px}.card .item:last-child,.card .item:last-child .item-content,.list-inset .item:last-child,.list-inset .item:last-child .item-content,.padding>.list .item:last-child,.padding>.list .item:last-child .item-content{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.card .item:last-child,.list-inset .item:last-child{margin-bottom:-1px}.card .item,.list-inset .item,.padding-horizontal>.list .item,.padding>.list .item{margin-right:0;margin-left:0}.card .item.item-input input,.list-inset .item.item-input input,.padding-horizontal>.list .item.item-input input,.padding>.list .item.item-input input{padding-right:44px}.padding-left>.list .item{margin-left:0}.padding-right>.list .item{margin-right:0}.badge{background-color:transparent;color:#AAA;z-index:1;display:inline-block;padding:3px 8px;min-width:10px;border-radius:10px;vertical-align:baseline;text-align:center;white-space:nowrap;font-weight:700;font-size:14px;line-height:16px}.badge:empty{display:none}.badge.badge-light,.tabs .tab-item .badge.badge-light{background-color:#fff;color:#444}.badge.badge-stable,.tabs .tab-item .badge.badge-stable{background-color:#f8f8f8;color:#444}.badge.badge-positive,.tabs .tab-item .badge.badge-positive{background-color:#387ef5;color:#fff}.badge.badge-calm,.tabs .tab-item .badge.badge-calm{background-color:#11c1f3;color:#fff}.badge.badge-assertive,.tabs .tab-item .badge.badge-assertive{background-color:#ef473a;color:#fff}.badge.badge-balanced,.tabs .tab-item .badge.badge-balanced{background-color:#33cd5f;color:#fff}.badge.badge-energized,.tabs .tab-item .badge.badge-energized{background-color:#ffc900;color:#fff}.badge.badge-royal,.tabs .tab-item .badge.badge-royal{background-color:#886aea;color:#fff}.badge.badge-dark,.tabs .tab-item .badge.badge-dark{background-color:#444;color:#fff}.button .badge{position:relative;top:-1px}.slider{position:relative;visibility:hidden;overflow:hidden}.slider-slides{position:relative;height:100%}.slider-slide{position:relative;display:block;float:left;width:100%;height:100%;vertical-align:top}.slider-slide-image>img{width:100%}.slider-pager{position:absolute;bottom:20px;z-index:1;width:100%;height:15px;text-align:center}.slider-pager .slider-pager-page{display:inline-block;margin:0 3px;width:15px;color:#000;text-decoration:none;opacity:.3}.slider-pager .slider-pager-page.active{-webkit-transition:opacity .4s ease-in;transition:opacity .4s ease-in;opacity:1}.scroll-refresher{position:absolute;top:-60px;right:0;left:0;overflow:hidden;margin:auto;height:60px}.scroll-refresher .ionic-refresher-content{position:absolute;bottom:15px;left:0;width:100%;color:#666;text-align:center;font-size:30px}.scroll-refresher .ionic-refresher-content .text-pulling,.scroll-refresher .ionic-refresher-content .text-refreshing{font-size:16px;line-height:16px}.scroll-refresher .ionic-refresher-content.ionic-refresher-with-text{bottom:10px}.scroll-refresher .icon-pulling,.scroll-refresher .icon-refreshing{width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.scroll-refresher .icon-pulling{-webkit-animation-name:refresh-spin-back;animation-name:refresh-spin-back;-webkit-animation-duration:200ms;animation-duration:200ms;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-transform:translate3d(0,0,0) rotate(0deg);transform:translate3d(0,0,0) rotate(0deg)}.scroll-refresher .icon-refreshing,.scroll-refresher .text-refreshing{display:none}.scroll-refresher .icon-refreshing{-webkit-animation-duration:1.5s;animation-duration:1.5s}.scroll-refresher.active .icon-pulling:not(.pulling-rotation-disabled){-webkit-animation-name:refresh-spin;animation-name:refresh-spin;-webkit-transform:translate3d(0,0,0) rotate(-180deg);transform:translate3d(0,0,0) rotate(-180deg)}.scroll-refresher.active.refreshing{-webkit-transition:transform .2s;transition:transform .2s;-webkit-transform:scale(1,1);transform:scale(1,1)}.scroll-refresher.active.refreshing .icon-pulling,.scroll-refresher.active.refreshing .text-pulling{display:none}.scroll-refresher.active.refreshing .icon-refreshing,.scroll-refresher.active.refreshing .text-refreshing{display:block}.scroll-refresher.active.refreshing.refreshing-tail{-webkit-transform:scale(0,0);transform:scale(0,0)}.overflow-scroll>.scroll{-webkit-overflow-scrolling:touch;width:100%}.overflow-scroll>.scroll.overscroll{position:fixed}@-webkit-keyframes refresh-spin{0%{-webkit-transform:translate3d(0,0,0) rotate(0)}100%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}}@keyframes refresh-spin{0%{transform:translate3d(0,0,0) rotate(0)}100%{transform:translate3d(0,0,0) rotate(180deg)}}@-webkit-keyframes refresh-spin-back{0%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}100%{-webkit-transform:translate3d(0,0,0) rotate(0)}}@keyframes refresh-spin-back{0%{transform:translate3d(0,0,0) rotate(180deg)}100%{transform:translate3d(0,0,0) rotate(0)}}.spinner{stroke:#444;fill:#444}.spinner svg{width:28px;height:28px}.spinner.spinner-light{stroke:#fff;fill:#fff}.spinner.spinner-stable{stroke:#f8f8f8;fill:#f8f8f8}.spinner.spinner-positive{stroke:#387ef5;fill:#387ef5}.spinner.spinner-calm{stroke:#11c1f3;fill:#11c1f3}.spinner.spinner-balanced{stroke:#33cd5f;fill:#33cd5f}.spinner.spinner-assertive{stroke:#ef473a;fill:#ef473a}.spinner.spinner-energized{stroke:#ffc900;fill:#ffc900}.spinner.spinner-royal{stroke:#886aea;fill:#886aea}.spinner.spinner-dark{stroke:#444;fill:#444}.spinner-android{stroke:#4b8bf4}.spinner-ios,.spinner-ios-small{stroke:#69717d}.spinner-spiral .stop1{stop-color:#fff;stop-opacity:0}.spinner-spiral.spinner-light .stop1{stop-color:#444}.spinner-spiral.spinner-light .stop2{stop-color:#fff}.spinner-spiral.spinner-stable .stop2{stop-color:#f8f8f8}.spinner-spiral.spinner-positive .stop2{stop-color:#387ef5}.spinner-spiral.spinner-calm .stop2{stop-color:#11c1f3}.spinner-spiral.spinner-balanced .stop2{stop-color:#33cd5f}.spinner-spiral.spinner-assertive .stop2{stop-color:#ef473a}.spinner-spiral.spinner-energized .stop2{stop-color:#ffc900}.spinner-spiral.spinner-royal .stop2{stop-color:#886aea}.spinner-spiral.spinner-dark .stop2{stop-color:#444}form{margin:0 0 1.42857}legend{display:block;margin-bottom:1.42857;padding:0;width:100%;border:1px solid #ddd;color:#444;font-size:21px;line-height:2.85714}legend small{color:#f8f8f8;font-size:1.07143}button,input,label,select,textarea{font-weight:400;font-size:14px;line-height:1.42857}button,input,select,textarea{font-family:"Helvetica Neue",Roboto,"Segoe UI",sans-serif}.item-input{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:6px 0 5px 16px}.item-input input{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 220px;-moz-box-flex:1;-moz-flex:1 220px;-ms-flex:1 220px;flex:1 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;padding-right:24px;background-color:transparent}.item-input .button .icon{-webkit-box-flex:0;-webkit-flex:0 0 24px;-moz-box-flex:0;-moz-flex:0 0 24px;-ms-flex:0 0 24px;flex:0 0 24px;position:static;display:inline-block;height:auto;text-align:center;font-size:16px}.item-input .button-bar{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 0 220px;-moz-box-flex:1;-moz-flex:1 0 220px;-ms-flex:1 0 220px;flex:1 0 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.item-input .icon{min-width:14px}.platform-windowsphone .item-input input{flex-shrink:1}.item-input-inset{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:10.67px}.item-input-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-moz-flex:1 0;-ms-flex:1 0;flex:1 0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-border-radius:4px;border-radius:4px;padding-right:8px;padding-left:8px;background:#eee}.item-input-inset .item-input-wrapper input{padding-left:4px;height:29px;background:0 0;line-height:18px}.item-input-wrapper~.button{margin-left:10.67px}.input-label{display:table;padding:7px 10px 7px 0;max-width:200px;width:35%;color:#444;font-size:16px}.placeholder-icon{color:#aaa}.placeholder-icon:first-child{padding-right:6px}.placeholder-icon:last-child{padding-left:6px}.item-stacked-label{display:block;background-color:transparent;box-shadow:none}.item-stacked-label .icon,.item-stacked-label .input-label{display:inline-block;padding:4px 0 0;vertical-align:middle}.item-stacked-label input,.item-stacked-label textarea{-webkit-border-radius:2px;border-radius:2px;padding:4px 8px 3px 0;border:none;background-color:#fff}.item-stacked-label input{overflow:hidden;height:46px}.item-floating-label{display:block;background-color:transparent;box-shadow:none}.item-floating-label .input-label{position:relative;padding:5px 0 0;opacity:0;top:10px;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}.item-floating-label .input-label.has-input{opacity:1;top:0;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}input[type=search],input[type=text],input[type=password],input[type=datetime],input[type=datetime-local],input[type=date],input[type=month],input[type=time],input[type=week],input[type=number],input[type=email],input[type=url],input[type=tel],input[type=color],textarea{display:block;padding-top:2px;padding-left:0;height:34px;color:#111;vertical-align:middle;font-size:14px;line-height:16px}.platform-android input[type=datetime-local],.platform-android input[type=date],.platform-android input[type=month],.platform-android input[type=time],.platform-android input[type=week],.platform-ios input[type=datetime-local],.platform-ios input[type=date],.platform-ios input[type=month],.platform-ios input[type=time],.platform-ios input[type=week]{padding-top:8px}.item-input input,.item-input textarea{width:100%}textarea{padding-left:0}textarea::-moz-placeholder{color:#aaa}textarea:-ms-input-placeholder{color:#aaa}textarea::-webkit-input-placeholder{color:#aaa;text-indent:-3px}textarea{height:auto}input[type=search],input[type=text],input[type=password],input[type=datetime],input[type=datetime-local],input[type=date],input[type=month],input[type=time],input[type=week],input[type=number],input[type=email],input[type=url],input[type=tel],input[type=color],textarea{border:0}input[type=radio],input[type=checkbox]{margin:0;line-height:normal}.item-input input[type=button],.item-input input[type=reset],.item-input input[type=submit],.item-input input[type=radio],.item-input input[type=checkbox],.item-input input[type=file],.item-input input[type=image]{width:auto}input[type=file]{line-height:34px}.cloned-text-input+input,.cloned-text-input+textarea,.previous-input-focus{position:absolute!important;left:-9999px;width:200px}input::-moz-placeholder,textarea::-moz-placeholder{color:#aaa}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#aaa}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#aaa;text-indent:0}input[disabled],input[readonly]:not(.cloned-text-input),select[disabled],select[readonly],textarea[disabled],textarea[readonly]:not(.cloned-text-input){background-color:#f8f8f8;cursor:not-allowed}input[type=radio][disabled],input[type=radio][readonly],input[type=checkbox][disabled],input[type=checkbox][readonly]{background-color:transparent}.checkbox{position:relative;display:inline-block;padding:7px;cursor:pointer}.checkbox .checkbox-icon:before,.checkbox input:before{border-color:#ddd}.checkbox input:checked+.checkbox-icon:before,.checkbox input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-light .checkbox-icon:before,.checkbox-light input:before{border-color:#ddd}.checkbox-light input:checked+.checkbox-icon:before,.checkbox-light input:checked:before{background:#ddd;border-color:#ddd}.checkbox-stable .checkbox-icon:before,.checkbox-stable input:before{border-color:#b2b2b2}.checkbox-stable input:checked+.checkbox-icon:before,.checkbox-stable input:checked:before{background:#b2b2b2;border-color:#b2b2b2}.checkbox-positive .checkbox-icon:before,.checkbox-positive input:before{border-color:#387ef5}.checkbox-positive input:checked+.checkbox-icon:before,.checkbox-positive input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-calm .checkbox-icon:before,.checkbox-calm input:before{border-color:#11c1f3}.checkbox-calm input:checked+.checkbox-icon:before,.checkbox-calm input:checked:before{background:#11c1f3;border-color:#11c1f3}.checkbox-assertive .checkbox-icon:before,.checkbox-assertive input:before{border-color:#ef473a}.checkbox-assertive input:checked+.checkbox-icon:before,.checkbox-assertive input:checked:before{background:#ef473a;border-color:#ef473a}.checkbox-balanced .checkbox-icon:before,.checkbox-balanced input:before{border-color:#33cd5f}.checkbox-balanced input:checked+.checkbox-icon:before,.checkbox-balanced input:checked:before{background:#33cd5f;border-color:#33cd5f}.checkbox-energized .checkbox-icon:before,.checkbox-energized input:before{border-color:#ffc900}.checkbox-energized input:checked+.checkbox-icon:before,.checkbox-energized input:checked:before{background:#ffc900;border-color:#ffc900}.checkbox-royal .checkbox-icon:before,.checkbox-royal input:before{border-color:#886aea}.checkbox-royal input:checked+.checkbox-icon:before,.checkbox-royal input:checked:before{background:#886aea;border-color:#886aea}.checkbox-dark .checkbox-icon:before,.checkbox-dark input:before{border-color:#444}.checkbox-dark input:checked+.checkbox-icon:before,.checkbox-dark input:checked:before{background:#444;border-color:#444}.checkbox input:disabled+.checkbox-icon:before,.checkbox input:disabled:before{border-color:#ddd}.checkbox input:disabled:checked+.checkbox-icon:before,.checkbox input:disabled:checked:before{background:#ddd}.checkbox.checkbox-input-hidden input{display:none!important}.checkbox input,.checkbox-icon{position:relative;width:28px;height:28px;display:block;border:0;background:0 0;cursor:pointer;-webkit-appearance:none}.checkbox input:before,.checkbox-icon:before{display:table;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:28px;background:#fff;content:' ';-webkit-transition:background-color 20ms ease-in-out;transition:background-color 20ms ease-in-out}.checkbox input:checked:before,input:checked+.checkbox-icon:before{border-width:2px}.checkbox input:after,.checkbox-icon:after{-webkit-transition:opacity .05s ease-in-out;transition:opacity .05s ease-in-out;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);position:absolute;top:33%;left:25%;display:table;width:14px;height:6px;border:1px solid #fff;border-top:0;border-right:0;content:' ';opacity:0}.checkbox-square .checkbox-icon:before,.checkbox-square input:before,.platform-android .checkbox-platform .checkbox-icon:before,.platform-android .checkbox-platform input:before{border-radius:2px;width:72%;height:72%;margin-top:14%;margin-left:14%;border-width:2px}.checkbox-square .checkbox-icon:after,.checkbox-square input:after,.platform-android .checkbox-platform .checkbox-icon:after,.platform-android .checkbox-platform input:after{border-width:2px;top:19%;left:25%;width:13px;height:7px}.grade-c .checkbox input:after,.grade-c .checkbox-icon:after{-webkit-transform:rotate(0);transform:rotate(0);top:3px;left:4px;border:none;color:#fff;content:'\2713';font-weight:700;font-size:20px}.checkbox input:checked:after,input:checked+.checkbox-icon:after{opacity:1}.item-checkbox{padding-left:60px}.item-checkbox.active{box-shadow:none}.item-checkbox .checkbox{position:absolute;top:50%;right:8px;left:8px;z-index:3;margin-top:-21px}.item-checkbox.item-checkbox-right{padding-right:60px;padding-left:16px}.item-checkbox-right .checkbox input,.item-checkbox-right .checkbox-icon{float:right}.item-toggle{pointer-events:none}.toggle{position:relative;display:inline-block;pointer-events:auto;margin:-5px;padding:5px}.toggle input:checked+.track{border-color:#4cd964;background-color:#4cd964}.toggle.dragging .handle{background-color:#f2f2f2!important}.toggle.toggle-light input:checked+.track{border-color:#ddd;background-color:#ddd}.toggle.toggle-stable input:checked+.track{border-color:#b2b2b2;background-color:#b2b2b2}.toggle.toggle-positive input:checked+.track{border-color:#387ef5;background-color:#387ef5}.toggle.toggle-calm input:checked+.track{border-color:#11c1f3;background-color:#11c1f3}.toggle.toggle-assertive input:checked+.track{border-color:#ef473a;background-color:#ef473a}.toggle.toggle-balanced input:checked+.track{border-color:#33cd5f;background-color:#33cd5f}.toggle.toggle-energized input:checked+.track{border-color:#ffc900;background-color:#ffc900}.toggle.toggle-royal input:checked+.track{border-color:#886aea;background-color:#886aea}.toggle.toggle-dark input:checked+.track{border-color:#444;background-color:#444}.toggle input{display:none}.toggle .track{-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:background-color,border;transition-property:background-color,border;display:inline-block;box-sizing:border-box;width:51px;height:31px;border:2px solid #e6e6e6;border-radius:20px;background-color:#fff;content:' ';cursor:pointer;pointer-events:none}.platform-android4_2 .toggle .track{-webkit-background-clip:padding-box}.toggle .handle{-webkit-transition:.3s cubic-bezier(0,1.1,1,1.1);transition:.3s cubic-bezier(0,1.1,1,1.1);-webkit-transition-property:background-color,transform;transition-property:background-color,transform;position:absolute;display:block;width:27px;height:27px;border-radius:27px;background-color:#fff;top:7px;left:7px;box-shadow:0 2px 7px rgba(0,0,0,.35),0 1px 1px rgba(0,0,0,.15)}.toggle .handle:before{position:absolute;top:-4px;left:-21.5px;padding:18.5px 34px;content:" "}.toggle input:checked+.track .handle{-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0);background-color:#fff}.item-toggle.active{box-shadow:none}.item-toggle,.item-toggle.item-complex .item-content{padding-right:99px}.item-toggle.item-complex{padding-right:0}.item-toggle .toggle{position:absolute;top:10px;right:16px;z-index:3}.toggle input:disabled+.track{opacity:.6}.toggle-small .track{border:0;width:34px;height:15px;background:#9e9e9e}.toggle-small input:checked+.track{background:rgba(0,150,137,.5)}.toggle-small .handle{top:2px;left:4px;width:21px;height:21px;box-shadow:0 2px 5px rgba(0,0,0,.25)}.toggle-small input:checked+.track .handle{-webkit-transform:translate3d(16px,0,0);transform:translate3d(16px,0,0);background:#009689}.toggle-small.item-toggle .toggle{top:19px}.toggle-small .toggle-light input:checked+.track{background-color:rgba(221,221,221,.5)}.toggle-small .toggle-light input:checked+.track .handle{background-color:#ddd}.toggle-small .toggle-stable input:checked+.track{background-color:rgba(178,178,178,.5)}.toggle-small .toggle-stable input:checked+.track .handle{background-color:#b2b2b2}.toggle-small .toggle-positive input:checked+.track{background-color:rgba(56,126,245,.5)}.toggle-small .toggle-positive input:checked+.track .handle{background-color:#387ef5}.toggle-small .toggle-calm input:checked+.track{background-color:rgba(17,193,243,.5)}.toggle-small .toggle-calm input:checked+.track .handle{background-color:#11c1f3}.toggle-small .toggle-assertive input:checked+.track{background-color:rgba(239,71,58,.5)}.toggle-small .toggle-assertive input:checked+.track .handle{background-color:#ef473a}.toggle-small .toggle-balanced input:checked+.track{background-color:rgba(51,205,95,.5)}.toggle-small .toggle-balanced input:checked+.track .handle{background-color:#33cd5f}.toggle-small .toggle-energized input:checked+.track{background-color:rgba(255,201,0,.5)}.toggle-small .toggle-energized input:checked+.track .handle{background-color:#ffc900}.toggle-small .toggle-royal input:checked+.track{background-color:rgba(136,106,234,.5)}.toggle-small .toggle-royal input:checked+.track .handle{background-color:#886aea}.toggle-small .toggle-dark input:checked+.track{background-color:rgba(68,68,68,.5)}.toggle-small .toggle-dark input:checked+.track .handle{background-color:#444}.item-radio{padding:0}.item-radio:hover{cursor:pointer}.item-radio .item-content{padding-right:64px}.item-radio .radio-icon{position:absolute;top:0;right:0;z-index:3;visibility:hidden;padding:14px;height:100%;font-size:24px}.item-radio input{position:absolute;left:-9999px}.item-radio input:checked~.item-content{background:#f7f7f7}.item-radio input:checked~.radio-icon{visibility:visible}.platform-android.grade-b .item-radio,.platform-android.grade-c .item-radio{-webkit-animation:androidCheckedbugfix infinite 1s}@-webkit-keyframes androidCheckedbugfix{from,to{padding:0}}.range input{overflow:hidden;margin-top:5px;margin-bottom:5px;padding-right:2px;padding-left:1px;width:auto;height:43px;outline:0;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(0,#ccc),color-stop(100%,#ccc)) center no-repeat;background:linear-gradient(to right,#ccc 0,#ccc 100%) center no-repeat;background-size:99% 2px;-webkit-appearance:none}.range input::-webkit-slider-thumb{position:relative;width:28px;height:28px;border-radius:50%;background-color:#fff;box-shadow:0 0 2px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2);cursor:pointer;-webkit-appearance:none;border:0}.range input::-webkit-slider-thumb:before{position:absolute;top:13px;left:-2001px;width:2000px;height:2px;background:#444;content:' '}.range input::-webkit-slider-thumb:after{position:absolute;top:-15px;left:-15px;padding:30px;content:' '}.range input::-ms-track{background:0 0;border-color:transparent;border-width:11px 0 16px;color:transparent;margin-top:20px}.range input::-ms-thumb{width:28px;height:28px;border-radius:50%;background-color:#fff;border-color:#fff;box-shadow:0 0 2px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2);margin-left:1px;margin-right:1px;outline:0}.range input::-ms-fill-lower{height:2px;background:#444}.range input::-ms-fill-upper{height:2px;background:#ccc}.range{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;padding:2px 11px}.range.range-light input::-webkit-slider-thumb:before{background:#ddd}.range.range-light input::-ms-fill-lower{background:#ddd}.range.range-stable input::-webkit-slider-thumb:before{background:#b2b2b2}.range.range-stable input::-ms-fill-lower{background:#b2b2b2}.range.range-positive input::-webkit-slider-thumb:before{background:#387ef5}.range.range-positive input::-ms-fill-lower{background:#387ef5}.range.range-calm input::-webkit-slider-thumb:before{background:#11c1f3}.range.range-calm input::-ms-fill-lower{background:#11c1f3}.range.range-balanced input::-webkit-slider-thumb:before{background:#33cd5f}.range.range-balanced input::-ms-fill-lower{background:#33cd5f}.range.range-assertive input::-webkit-slider-thumb:before{background:#ef473a}.range.range-assertive input::-ms-fill-lower{background:#ef473a}.range.range-energized input::-webkit-slider-thumb:before{background:#ffc900}.range.range-energized input::-ms-fill-lower{background:#ffc900}.range.range-royal input::-webkit-slider-thumb:before{background:#886aea}.range.range-royal input::-ms-fill-lower{background:#886aea}.range.range-dark input::-webkit-slider-thumb:before{background:#444}.range.range-dark input::-ms-fill-lower{background:#444}.range .icon{-webkit-box-flex:0;-webkit-flex:0;-moz-box-flex:0;-moz-flex:0;-ms-flex:0;flex:0;display:block;min-width:24px;text-align:center;font-size:24px}.range input{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;margin-right:10px;margin-left:10px}.range-label{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-moz-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;display:block;white-space:nowrap}.range-label:first-child{padding-left:5px}.range input+.range-label{padding-right:5px;padding-left:0}.platform-windowsphone .range input{height:auto}.item-select{position:relative}.item-select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:absolute;top:0;bottom:0;right:0;padding:14px 48px 16px 16px;max-width:65%;border:none;background:#fff;color:#333;text-indent:.01px;text-overflow:'';white-space:nowrap;font-size:14px;cursor:pointer;direction:rtl}.item-select select::-ms-expand{display:none}.item-select option{direction:ltr}.item-select:after{position:absolute;top:50%;right:16px;margin-top:-3px;width:0;height:0;border-top:5px solid;border-right:5px solid transparent;border-left:5px solid transparent;color:#999;content:"";pointer-events:none}.item-select.item-light select{background:#fff;color:#444}.item-select.item-stable select{background:#f8f8f8;color:#444}.item-select.item-stable .input-label,.item-select.item-stable:after{color:#656565}.item-select.item-positive select{background:#387ef5;color:#fff}.item-select.item-positive .input-label,.item-select.item-positive:after{color:#fff}.item-select.item-calm select{background:#11c1f3;color:#fff}.item-select.item-calm .input-label,.item-select.item-calm:after{color:#fff}.item-select.item-assertive select{background:#ef473a;color:#fff}.item-select.item-assertive .input-label,.item-select.item-assertive:after{color:#fff}.item-select.item-balanced select{background:#33cd5f;color:#fff}.item-select.item-balanced .input-label,.item-select.item-balanced:after{color:#fff}.item-select.item-energized select{background:#ffc900;color:#fff}.item-select.item-energized .input-label,.item-select.item-energized:after{color:#fff}.item-select.item-royal select{background:#886aea;color:#fff}.item-select.item-royal .input-label,.item-select.item-royal:after{color:#fff}.item-select.item-dark select{background:#444;color:#fff}.item-select.item-dark .input-label,.item-select.item-dark:after{color:#fff}select[multiple],select[size]{height:auto}progress{display:block;margin:15px auto;width:100%}.button{border-color:#b2b2b2;background-color:#f8f8f8;color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-width:52px;min-height:47px;border-width:1px;border-style:solid;border-radius:2px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer}.button:hover{color:#444;text-decoration:none}.button.activated,.button.active{border-color:#a2a2a2;background-color:#e5e5e5;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button:after{position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px;content:' '}.button .icon{vertical-align:top;pointer-events:none}.button .icon:before,.button.icon-left:before,.button.icon-right:before,.button.icon:before{display:inline-block;padding:0 0 1px;vertical-align:inherit;font-size:24px;line-height:41px;pointer-events:none}.button.icon-left:before{float:left;padding-right:.2em;padding-left:0}.button.icon-right:before{float:right;padding-right:0;padding-left:.2em}.button.button-block,.button.button-full{margin-top:10px;margin-bottom:10px}.button.button-light{border-color:#ddd;background-color:#fff;color:#444}.button.button-light:hover{color:#444;text-decoration:none}.button.button-light.activated,.button.button-light.active{border-color:#ccc;background-color:#fafafa;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-light.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ddd}.button.button-light.button-icon{border-color:transparent;background:0 0}.button.button-light.button-outline{border-color:#ddd;background:0 0;color:#ddd}.button.button-light.button-outline.activated,.button.button-light.button-outline.active{background-color:#ddd;box-shadow:none;color:#fff}.button.button-stable{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.button.button-stable:hover{color:#444;text-decoration:none}.button.button-stable.activated,.button.button-stable.active{border-color:#a2a2a2;background-color:#e5e5e5;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-stable.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button.button-stable.button-icon{border-color:transparent;background:0 0}.button.button-stable.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button.button-stable.button-outline.activated,.button.button-stable.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.button.button-positive{border-color:#0c63ee;background-color:#387ef5;color:#fff}.button.button-positive:hover{color:#fff;text-decoration:none}.button.button-positive.activated,.button.button-positive.active{border-color:#0c63ee;background-color:#0c63ee;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-positive.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#387ef5}.button.button-positive.button-icon{border-color:transparent;background:0 0}.button.button-positive.button-outline{border-color:#387ef5;background:0 0;color:#387ef5}.button.button-positive.button-outline.activated,.button.button-positive.button-outline.active{background-color:#387ef5;box-shadow:none;color:#fff}.button.button-calm{border-color:#0a9ec7;background-color:#11c1f3;color:#fff}.button.button-calm:hover{color:#fff;text-decoration:none}.button.button-calm.activated,.button.button-calm.active{border-color:#0a9ec7;background-color:#0a9ec7;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-calm.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#11c1f3}.button.button-calm.button-icon{border-color:transparent;background:0 0}.button.button-calm.button-outline{border-color:#11c1f3;background:0 0;color:#11c1f3}.button.button-calm.button-outline.activated,.button.button-calm.button-outline.active{background-color:#11c1f3;box-shadow:none;color:#fff}.button.button-assertive{border-color:#e42012;background-color:#ef473a;color:#fff}.button.button-assertive:hover{color:#fff;text-decoration:none}.button.button-assertive.activated,.button.button-assertive.active{border-color:#e42012;background-color:#e42012;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-assertive.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ef473a}.button.button-assertive.button-icon{border-color:transparent;background:0 0}.button.button-assertive.button-outline{border-color:#ef473a;background:0 0;color:#ef473a}.button.button-assertive.button-outline.activated,.button.button-assertive.button-outline.active{background-color:#ef473a;box-shadow:none;color:#fff}.button.button-balanced{border-color:#28a54c;background-color:#33cd5f;color:#fff}.button.button-balanced:hover{color:#fff;text-decoration:none}.button.button-balanced.activated,.button.button-balanced.active{border-color:#28a54c;background-color:#28a54c;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-balanced.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#33cd5f}.button.button-balanced.button-icon{border-color:transparent;background:0 0}.button.button-balanced.button-outline{border-color:#33cd5f;background:0 0;color:#33cd5f}.button.button-balanced.button-outline.activated,.button.button-balanced.button-outline.active{background-color:#33cd5f;box-shadow:none;color:#fff}.button.button-energized{border-color:#e6b400;background-color:#ffc900;color:#fff}.button.button-energized:hover{color:#fff;text-decoration:none}.button.button-energized.activated,.button.button-energized.active{border-color:#e6b400;background-color:#e6b400;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-energized.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ffc900}.button.button-energized.button-icon{border-color:transparent;background:0 0}.button.button-energized.button-outline{border-color:#ffc900;background:0 0;color:#ffc900}.button.button-energized.button-outline.activated,.button.button-energized.button-outline.active{background-color:#ffc900;box-shadow:none;color:#fff}.button.button-royal{border-color:#6b46e5;background-color:#886aea;color:#fff}.button.button-royal:hover{color:#fff;text-decoration:none}.button.button-royal.activated,.button.button-royal.active{border-color:#6b46e5;background-color:#6b46e5;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-royal.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#886aea}.button.button-royal.button-icon{border-color:transparent;background:0 0}.button.button-royal.button-outline{border-color:#886aea;background:0 0;color:#886aea}.button.button-royal.button-outline.activated,.button.button-royal.button-outline.active{background-color:#886aea;box-shadow:none;color:#fff}.button.button-dark{border-color:#111;background-color:#444;color:#fff}.button.button-dark:hover{color:#fff;text-decoration:none}.button.button-dark.activated,.button.button-dark.active{border-color:#000;background-color:#262626;box-shadow:inset 0 1px 4px rgba(0,0,0,.1)}.button.button-dark.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444}.button.button-dark.button-icon{border-color:transparent;background:0 0}.button.button-dark.button-outline{border-color:#444;background:0 0;color:#444}.button.button-dark.button-outline.activated,.button.button-dark.button-outline.active{background-color:#444;box-shadow:none;color:#fff}.button-small{padding:2px 4px 1px;min-width:28px;min-height:30px;font-size:12px;line-height:26px}.button-small .icon:before,.button-small.icon-left:before,.button-small.icon-right:before,.button-small.icon:before{font-size:16px;line-height:19px;margin-top:3px}.button-large{padding:0 16px;min-width:68px;min-height:59px;font-size:20px;line-height:53px}.button-large .icon:before,.button-large.icon-left:before,.button-large.icon-right:before,.button-large.icon:before{padding-bottom:2px;font-size:32px;line-height:51px}.button-icon{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;min-width:initial;border-color:transparent;background:0 0}.button-icon.button.activated,.button-icon.button.active{border-color:transparent;background:0 0;box-shadow:none;opacity:.3}.button-icon .icon:before,.button-icon.icon:before{font-size:32px}.button-clear{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;max-height:42px;border-color:transparent;background:0 0;box-shadow:none}.button-clear.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button-clear.button-icon{border-color:transparent;background:0 0}.button-clear.activated,.button-clear.active{opacity:.3}.button-outline{-webkit-transition:opacity .1s;transition:opacity .1s;background:0 0;box-shadow:none}.button-outline.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button-outline.button-outline.activated,.button-outline.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.padding>.button.button-block:first-child{margin-top:0}.button-block{display:block;clear:both}.button-block:after{clear:both}.button-full,.button-full>.button{display:block;margin-right:0;margin-left:0;border-right-width:0;border-left-width:0;border-radius:0}.button-full>button.button,button.button-block,button.button-full,input.button.button-block{width:100%}a.button{text-decoration:none}a.button .icon:before,a.button.icon-left:before,a.button.icon-right:before,a.button.icon:before{margin-top:2px}.button.disabled,.button[disabled]{opacity:.4;cursor:default!important;pointer-events:none}.button-bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;width:100%}.button-bar.button-bar-inline{display:block;width:auto}.button-bar.button-bar-inline:after,.button-bar.button-bar-inline:before{display:table;content:"";line-height:0}.button-bar.button-bar-inline:after{clear:both}.button-bar.button-bar-inline>.button{width:auto;display:inline-block;float:left}.button-bar>.button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;padding:0 16px;width:0;border-width:1px 0 1px 1px;border-radius:0;text-align:center;text-overflow:ellipsis;white-space:nowrap}.button-bar>.button .icon:before,.button-bar>.button:before{line-height:44px}.button-bar>.button:first-child{border-radius:2px 0 0 2px}.button-bar>.button:last-child{border-right-width:1px;border-radius:0 2px 2px 0}.button-bar>.button-small .icon:before,.button-bar>.button-small:before{line-height:28px}.row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:5px;width:100%}.row-wrap{-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.row-no-padding,.row-no-padding>.col{padding:0}.row+.row{margin-top:-5px;padding-top:0}.col{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;padding:5px;width:100%}.row-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;-moz-align-items:flex-start;align-items:flex-start}.row-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;-moz-align-items:flex-end;align-items:flex-end}.row-center{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.row-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;-moz-align-items:stretch;align-items:stretch}.row-baseline{-webkit-box-align:baseline;-ms-flex-align:baseline;-webkit-align-items:baseline;-moz-align-items:baseline;align-items:baseline}.col-top{-webkit-align-self:flex-start;-moz-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.col-bottom{-webkit-align-self:flex-end;-moz-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.col-center{-webkit-align-self:center;-moz-align-self:center;-ms-flex-item-align:center;align-self:center}.col-offset-10{margin-left:10%}.col-offset-20{margin-left:20%}.col-offset-25{margin-left:25%}.col-offset-33,.col-offset-34{margin-left:33.3333%}.col-offset-50{margin-left:50%}.col-offset-66,.col-offset-67{margin-left:66.6666%}.col-offset-75{margin-left:75%}.col-offset-80{margin-left:80%}.col-offset-90{margin-left:90%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 10%;-moz-box-flex:0;-moz-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%;max-width:10%}.col-20{-webkit-box-flex:0;-webkit-flex:0 0 20%;-moz-box-flex:0;-moz-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.col-25{-webkit-box-flex:0;-webkit-flex:0 0 25%;-moz-box-flex:0;-moz-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-33,.col-34{-webkit-box-flex:0;-webkit-flex:0 0 33.3333%;-moz-box-flex:0;-moz-flex:0 0 33.3333%;-ms-flex:0 0 33.3333%;flex:0 0 33.3333%;max-width:33.3333%}.col-50{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-moz-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-66,.col-67{-webkit-box-flex:0;-webkit-flex:0 0 66.6666%;-moz-box-flex:0;-moz-flex:0 0 66.6666%;-ms-flex:0 0 66.6666%;flex:0 0 66.6666%;max-width:66.6666%}.col-75{-webkit-box-flex:0;-webkit-flex:0 0 75%;-moz-box-flex:0;-moz-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-80{-webkit-box-flex:0;-webkit-flex:0 0 80%;-moz-box-flex:0;-moz-flex:0 0 80%;-ms-flex:0 0 80%;flex:0 0 80%;max-width:80%}.col-90{-webkit-box-flex:0;-webkit-flex:0 0 90%;-moz-box-flex:0;-moz-flex:0 0 90%;-ms-flex:0 0 90%;flex:0 0 90%;max-width:90%}@media (max-width:567px){.responsive-sm{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-sm .col,.responsive-sm .col-10,.responsive-sm .col-20,.responsive-sm .col-25,.responsive-sm .col-33,.responsive-sm .col-34,.responsive-sm .col-50,.responsive-sm .col-66,.responsive-sm .col-67,.responsive-sm .col-75,.responsive-sm .col-80,.responsive-sm .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:767px){.responsive-md{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-md .col,.responsive-md .col-10,.responsive-md .col-20,.responsive-md .col-25,.responsive-md .col-33,.responsive-md .col-34,.responsive-md .col-50,.responsive-md .col-66,.responsive-md .col-67,.responsive-md .col-75,.responsive-md .col-80,.responsive-md .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:1023px){.responsive-lg{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-lg .col,.responsive-lg .col-10,.responsive-lg .col-20,.responsive-lg .col-25,.responsive-lg .col-33,.responsive-lg .col-34,.responsive-lg .col-50,.responsive-lg .col-66,.responsive-lg .col-67,.responsive-lg .col-75,.responsive-lg .col-80,.responsive-lg .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}.hide{display:none}.opacity-hide{opacity:0}.grade-b .opacity-hide,.grade-c .opacity-hide{opacity:1;display:none}.show{display:block}.opacity-show{opacity:1}.invisible{visibility:hidden}.keyboard-open .hide-on-keyboard-open{display:none}.keyboard-open .bar-footer.hide-on-keyboard-open+.pane .has-footer,.keyboard-open .tabs.hide-on-keyboard-open+.pane .has-tabs{bottom:0}.inline{display:inline-block}.disable-pointer-events{pointer-events:none}.enable-pointer-events{pointer-events:auto}.disable-user-behavior{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-ms-touch-action:none;-ms-content-zooming:none}.click-block{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;z-index:99999;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);overflow:hidden}.click-block-hide{-webkit-transform:translate3d(-9999px,0,0);transform:translate3d(-9999px,0,0)}.no-resize{resize:none}.block{display:block;clear:both}.block:after{display:block;visibility:hidden;clear:both;height:0;content:"."}.full-image{width:100%}.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}.padding{padding:10px}.padding-top,.padding-vertical{padding-top:10px}.padding-horizontal,.padding-right{padding-right:10px}.padding-bottom,.padding-vertical{padding-bottom:10px}.padding-horizontal,.padding-left{padding-left:10px}.iframe-wrapper{position:fixed;-webkit-overflow-scrolling:touch;overflow:scroll}.iframe-wrapper iframe{height:100%;width:100%}.rounded{border-radius:4px}.light,a.light{color:#fff}.light-bg{background-color:#fff}.light-border{border-color:#ddd}.stable,a.stable{color:#f8f8f8}.stable-bg{background-color:#f8f8f8}.stable-border{border-color:#b2b2b2}.positive,a.positive{color:#387ef5}.positive-bg{background-color:#387ef5}.positive-border{border-color:#0c63ee}.calm,a.calm{color:#11c1f3}.calm-bg{background-color:#11c1f3}.calm-border{border-color:#0a9ec7}.assertive,a.assertive{color:#ef473a}.assertive-bg{background-color:#ef473a}.assertive-border{border-color:#e42012}.balanced,a.balanced{color:#33cd5f}.balanced-bg{background-color:#33cd5f}.balanced-border{border-color:#28a54c}.energized,a.energized{color:#ffc900}.energized-bg{background-color:#ffc900}.energized-border{border-color:#e6b400}.royal,a.royal{color:#886aea}.royal-bg{background-color:#886aea}.royal-border{border-color:#6b46e5}.dark,a.dark{color:#444}.dark-bg{background-color:#444}.dark-border{border-color:#111}[collection-repeat]{left:0!important;top:0!important;position:absolute!important;z-index:1}.collection-repeat-container{position:relative;z-index:1}.collection-repeat-after-container{z-index:0;display:block}.collection-repeat-after-container.horizontal{display:inline-block}.ng-cloak,.ng-hide:not(.ng-hide-animate),.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader){height:64px}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:19px!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader)>*{margin-top:20px}.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader,.platform-ios.platform-cordova:not(.fullscreen) .has-header,.platform-ios.platform-cordova:not(.fullscreen) .tabs-top>.tabs,.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top{top:64px}.platform-ios.platform-cordova:not(.fullscreen) .has-subheader{top:108px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top{top:113px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top{top:157px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:-1px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .popover .bar-subheader,.platform-ios.platform-cordova .popover .has-header{top:44px}.platform-ios.platform-cordova .popover .has-subheader{top:88px}.platform-ios.platform-cordova.status-bar-hide{margin-bottom:20px}@media (orientation:landscape){.platform-ios.platform-browser.platform-ipad{position:fixed}}.platform-c:not(.enable-transitions) *{-webkit-transition:none!important;transition:none!important}.slide-in-up{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.slide-in-up.ng-enter,.slide-in-up>.ng-enter{-webkit-transition:all cubic-bezier(.1,.7,.1,1) 400ms;transition:all cubic-bezier(.1,.7,.1,1) 400ms}.slide-in-up.ng-enter-active,.slide-in-up>.ng-enter-active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slide-in-up.ng-leave,.slide-in-up>.ng-leave{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms}@-webkit-keyframes scaleOut{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@keyframes scaleOut{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}@-webkit-keyframes superScaleIn{from{-webkit-transform:scale(1.2);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@keyframes superScaleIn{from{transform:scale(1.2);opacity:0}to{transform:scale(1);opacity:1}}[nav-view-transition=ios] [nav-view=entering],[nav-view-transition=ios] [nav-view=leaving]{-webkit-transition-duration:500ms;transition-duration:500ms;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform,box-shadow;transition-property:opacity,transform,box-shadow}[nav-view-transition=ios][nav-view-direction=forward],[nav-view-transition=ios][nav-view-direction=back]{background-color:#000}[nav-view-transition=ios] [nav-view=active],[nav-view-transition=ios][nav-view-direction=forward] [nav-view=entering],[nav-view-transition=ios][nav-view-direction=back] [nav-view=leaving]{z-index:3}[nav-view-transition=ios][nav-view-direction=forward] [nav-view=leaving],[nav-view-transition=ios][nav-view-direction=back] [nav-view=entering]{z-index:2}[nav-bar-transition=ios] .back-text,[nav-bar-transition=ios] .buttons,[nav-bar-transition=ios] .title{-webkit-transition-duration:500ms;transition-duration:500ms;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,transform}[nav-bar-transition=ios] [nav-bar=entering],[nav-bar-transition=ios] [nav-bar=active]{z-index:10}[nav-bar-transition=ios] [nav-bar=entering] .bar,[nav-bar-transition=ios] [nav-bar=active] .bar{background:0 0}[nav-bar-transition=ios] [nav-bar=cached]{display:block}[nav-bar-transition=ios] [nav-bar=cached] .header-item{display:none}[nav-view-transition=android] [nav-view=entering],[nav-view-transition=android] [nav-view=leaving]{-webkit-transition-duration:200ms;transition-duration:200ms;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:-webkit-transform;transition-property:transform}[nav-view-transition=android] [nav-view=active],[nav-view-transition=android][nav-view-direction=forward] [nav-view=entering],[nav-view-transition=android][nav-view-direction=back] [nav-view=leaving]{z-index:3}[nav-view-transition=android][nav-view-direction=forward] [nav-view=leaving],[nav-view-transition=android][nav-view-direction=back] [nav-view=entering]{z-index:2}[nav-bar-transition=android] .buttons,[nav-bar-transition=android] .title{-webkit-transition-duration:200ms;transition-duration:200ms;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:opacity;transition-property:opacity}[nav-bar-transition=android] [nav-bar=entering],[nav-bar-transition=android] [nav-bar=active]{z-index:10}[nav-bar-transition=android] [nav-bar=entering] .bar,[nav-bar-transition=android] [nav-bar=active] .bar{background:0 0}[nav-bar-transition=android] [nav-bar=cached]{display:block}[nav-bar-transition=android] [nav-bar=cached] .header-item{display:none}[nav-swipe=fast] .back-text,[nav-swipe=fast] .buttons,[nav-swipe=fast] .title,[nav-swipe=fast] [nav-view]{-webkit-transition-duration:50ms;transition-duration:50ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-swipe=slow] .back-text,[nav-swipe=slow] .buttons,[nav-swipe=slow] .title,[nav-swipe=slow] [nav-view]{-webkit-transition-duration:160ms;transition-duration:160ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-bar=cached],[nav-view=cached]{display:none}[nav-view=stage]{opacity:0;-webkit-transition-duration:0;transition-duration:0}[nav-bar=stage] .back-text,[nav-bar=stage] .buttons,[nav-bar=stage] .title{position:absolute;opacity:0;-webkit-transition-duration:0s;transition-duration:0s} \ No newline at end of file +*/@font-face{font-family:Ionicons;src:url(../fonts/ionicons.eot?v=2.0.1);src:url(../fonts/ionicons.eot?v=2.0.1#iefix) format("embedded-opentype"),url(../fonts/ionicons.ttf?v=2.0.1) format("truetype"),url(../fonts/ionicons.woff?v=2.0.1) format("woff"),url(../fonts/ionicons.woff) format("woff"),url(../fonts/ionicons.svg?v=2.0.1#Ionicons) format("svg");font-weight:400;font-style:normal}.ion,.ion-alert-circled:before,.ion-alert:before,.ion-android-add-circle:before,.ion-android-add:before,.ion-android-alarm-clock:before,.ion-android-alert:before,.ion-android-apps:before,.ion-android-archive:before,.ion-android-arrow-back:before,.ion-android-arrow-down:before,.ion-android-arrow-dropdown-circle:before,.ion-android-arrow-dropdown:before,.ion-android-arrow-dropleft-circle:before,.ion-android-arrow-dropleft:before,.ion-android-arrow-dropright-circle:before,.ion-android-arrow-dropright:before,.ion-android-arrow-dropup-circle:before,.ion-android-arrow-dropup:before,.ion-android-arrow-forward:before,.ion-android-arrow-up:before,.ion-android-attach:before,.ion-android-bar:before,.ion-android-bicycle:before,.ion-android-boat:before,.ion-android-bookmark:before,.ion-android-bulb:before,.ion-android-bus:before,.ion-android-calendar:before,.ion-android-call:before,.ion-android-camera:before,.ion-android-cancel:before,.ion-android-car:before,.ion-android-cart:before,.ion-android-chat:before,.ion-android-checkbox-blank:before,.ion-android-checkbox-outline-blank:before,.ion-android-checkbox-outline:before,.ion-android-checkbox:before,.ion-android-checkmark-circle:before,.ion-android-clipboard:before,.ion-android-close:before,.ion-android-cloud-circle:before,.ion-android-cloud-done:before,.ion-android-cloud-outline:before,.ion-android-cloud:before,.ion-android-color-palette:before,.ion-android-compass:before,.ion-android-contact:before,.ion-android-contacts:before,.ion-android-contract:before,.ion-android-create:before,.ion-android-delete:before,.ion-android-desktop:before,.ion-android-document:before,.ion-android-done-all:before,.ion-android-done:before,.ion-android-download:before,.ion-android-drafts:before,.ion-android-exit:before,.ion-android-expand:before,.ion-android-favorite-outline:before,.ion-android-favorite:before,.ion-android-film:before,.ion-android-folder-open:before,.ion-android-folder:before,.ion-android-funnel:before,.ion-android-globe:before,.ion-android-hand:before,.ion-android-hangout:before,.ion-android-happy:before,.ion-android-home:before,.ion-android-image:before,.ion-android-laptop:before,.ion-android-list:before,.ion-android-locate:before,.ion-android-lock:before,.ion-android-mail:before,.ion-android-map:before,.ion-android-menu:before,.ion-android-microphone-off:before,.ion-android-microphone:before,.ion-android-more-horizontal:before,.ion-android-more-vertical:before,.ion-android-navigate:before,.ion-android-notifications-none:before,.ion-android-notifications-off:before,.ion-android-notifications:before,.ion-android-open:before,.ion-android-options:before,.ion-android-people:before,.ion-android-person-add:before,.ion-android-person:before,.ion-android-phone-landscape:before,.ion-android-phone-portrait:before,.ion-android-pin:before,.ion-android-plane:before,.ion-android-playstore:before,.ion-android-print:before,.ion-android-radio-button-off:before,.ion-android-radio-button-on:before,.ion-android-refresh:before,.ion-android-remove-circle:before,.ion-android-remove:before,.ion-android-restaurant:before,.ion-android-sad:before,.ion-android-search:before,.ion-android-send:before,.ion-android-settings:before,.ion-android-share-alt:before,.ion-android-share:before,.ion-android-star-half:before,.ion-android-star-outline:before,.ion-android-star:before,.ion-android-stopwatch:before,.ion-android-subway:before,.ion-android-sunny:before,.ion-android-sync:before,.ion-android-textsms:before,.ion-android-time:before,.ion-android-train:before,.ion-android-unlock:before,.ion-android-upload:before,.ion-android-volume-down:before,.ion-android-volume-mute:before,.ion-android-volume-off:before,.ion-android-volume-up:before,.ion-android-walk:before,.ion-android-warning:before,.ion-android-watch:before,.ion-android-wifi:before,.ion-aperture:before,.ion-archive:before,.ion-arrow-down-a:before,.ion-arrow-down-b:before,.ion-arrow-down-c:before,.ion-arrow-expand:before,.ion-arrow-graph-down-left:before,.ion-arrow-graph-down-right:before,.ion-arrow-graph-up-left:before,.ion-arrow-graph-up-right:before,.ion-arrow-left-a:before,.ion-arrow-left-b:before,.ion-arrow-left-c:before,.ion-arrow-move:before,.ion-arrow-resize:before,.ion-arrow-return-left:before,.ion-arrow-return-right:before,.ion-arrow-right-a:before,.ion-arrow-right-b:before,.ion-arrow-right-c:before,.ion-arrow-shrink:before,.ion-arrow-swap:before,.ion-arrow-up-a:before,.ion-arrow-up-b:before,.ion-arrow-up-c:before,.ion-asterisk:before,.ion-at:before,.ion-backspace-outline:before,.ion-backspace:before,.ion-bag:before,.ion-battery-charging:before,.ion-battery-empty:before,.ion-battery-full:before,.ion-battery-half:before,.ion-battery-low:before,.ion-beaker:before,.ion-beer:before,.ion-bluetooth:before,.ion-bonfire:before,.ion-bookmark:before,.ion-bowtie:before,.ion-briefcase:before,.ion-bug:before,.ion-calculator:before,.ion-calendar:before,.ion-camera:before,.ion-card:before,.ion-cash:before,.ion-chatbox-working:before,.ion-chatbox:before,.ion-chatboxes:before,.ion-chatbubble-working:before,.ion-chatbubble:before,.ion-chatbubbles:before,.ion-checkmark-circled:before,.ion-checkmark-round:before,.ion-checkmark:before,.ion-chevron-down:before,.ion-chevron-left:before,.ion-chevron-right:before,.ion-chevron-up:before,.ion-clipboard:before,.ion-clock:before,.ion-close-circled:before,.ion-close-round:before,.ion-close:before,.ion-closed-captioning:before,.ion-cloud:before,.ion-code-download:before,.ion-code-working:before,.ion-code:before,.ion-coffee:before,.ion-compass:before,.ion-compose:before,.ion-connection-bars:before,.ion-contrast:before,.ion-crop:before,.ion-cube:before,.ion-disc:before,.ion-document-text:before,.ion-document:before,.ion-drag:before,.ion-earth:before,.ion-easel:before,.ion-edit:before,.ion-egg:before,.ion-eject:before,.ion-email-unread:before,.ion-email:before,.ion-erlenmeyer-flask-bubbles:before,.ion-erlenmeyer-flask:before,.ion-eye-disabled:before,.ion-eye:before,.ion-female:before,.ion-filing:before,.ion-film-marker:before,.ion-fireball:before,.ion-flag:before,.ion-flame:before,.ion-flash-off:before,.ion-flash:before,.ion-folder:before,.ion-fork-repo:before,.ion-fork:before,.ion-forward:before,.ion-funnel:before,.ion-gear-a:before,.ion-gear-b:before,.ion-grid:before,.ion-hammer:before,.ion-happy-outline:before,.ion-happy:before,.ion-headphone:before,.ion-heart-broken:before,.ion-heart:before,.ion-help-buoy:before,.ion-help-circled:before,.ion-help:before,.ion-home:before,.ion-icecream:before,.ion-image:before,.ion-images:before,.ion-information-circled:before,.ion-information:before,.ion-ionic:before,.ion-ios-alarm-outline:before,.ion-ios-alarm:before,.ion-ios-albums-outline:before,.ion-ios-albums:before,.ion-ios-americanfootball-outline:before,.ion-ios-americanfootball:before,.ion-ios-analytics-outline:before,.ion-ios-analytics:before,.ion-ios-arrow-back:before,.ion-ios-arrow-down:before,.ion-ios-arrow-forward:before,.ion-ios-arrow-left:before,.ion-ios-arrow-right:before,.ion-ios-arrow-thin-down:before,.ion-ios-arrow-thin-left:before,.ion-ios-arrow-thin-right:before,.ion-ios-arrow-thin-up:before,.ion-ios-arrow-up:before,.ion-ios-at-outline:before,.ion-ios-at:before,.ion-ios-barcode-outline:before,.ion-ios-barcode:before,.ion-ios-baseball-outline:before,.ion-ios-baseball:before,.ion-ios-basketball-outline:before,.ion-ios-basketball:before,.ion-ios-bell-outline:before,.ion-ios-bell:before,.ion-ios-body-outline:before,.ion-ios-body:before,.ion-ios-bolt-outline:before,.ion-ios-bolt:before,.ion-ios-book-outline:before,.ion-ios-book:before,.ion-ios-bookmarks-outline:before,.ion-ios-bookmarks:before,.ion-ios-box-outline:before,.ion-ios-box:before,.ion-ios-briefcase-outline:before,.ion-ios-briefcase:before,.ion-ios-browsers-outline:before,.ion-ios-browsers:before,.ion-ios-calculator-outline:before,.ion-ios-calculator:before,.ion-ios-calendar-outline:before,.ion-ios-calendar:before,.ion-ios-camera-outline:before,.ion-ios-camera:before,.ion-ios-cart-outline:before,.ion-ios-cart:before,.ion-ios-chatboxes-outline:before,.ion-ios-chatboxes:before,.ion-ios-chatbubble-outline:before,.ion-ios-chatbubble:before,.ion-ios-checkmark-empty:before,.ion-ios-checkmark-outline:before,.ion-ios-checkmark:before,.ion-ios-circle-filled:before,.ion-ios-circle-outline:before,.ion-ios-clock-outline:before,.ion-ios-clock:before,.ion-ios-close-empty:before,.ion-ios-close-outline:before,.ion-ios-close:before,.ion-ios-cloud-download-outline:before,.ion-ios-cloud-download:before,.ion-ios-cloud-outline:before,.ion-ios-cloud-upload-outline:before,.ion-ios-cloud-upload:before,.ion-ios-cloud:before,.ion-ios-cloudy-night-outline:before,.ion-ios-cloudy-night:before,.ion-ios-cloudy-outline:before,.ion-ios-cloudy:before,.ion-ios-cog-outline:before,.ion-ios-cog:before,.ion-ios-color-filter-outline:before,.ion-ios-color-filter:before,.ion-ios-color-wand-outline:before,.ion-ios-color-wand:before,.ion-ios-compose-outline:before,.ion-ios-compose:before,.ion-ios-contact-outline:before,.ion-ios-contact:before,.ion-ios-copy-outline:before,.ion-ios-copy:before,.ion-ios-crop-strong:before,.ion-ios-crop:before,.ion-ios-download-outline:before,.ion-ios-download:before,.ion-ios-drag:before,.ion-ios-email-outline:before,.ion-ios-email:before,.ion-ios-eye-outline:before,.ion-ios-eye:before,.ion-ios-fastforward-outline:before,.ion-ios-fastforward:before,.ion-ios-filing-outline:before,.ion-ios-filing:before,.ion-ios-film-outline:before,.ion-ios-film:before,.ion-ios-flag-outline:before,.ion-ios-flag:before,.ion-ios-flame-outline:before,.ion-ios-flame:before,.ion-ios-flask-outline:before,.ion-ios-flask:before,.ion-ios-flower-outline:before,.ion-ios-flower:before,.ion-ios-folder-outline:before,.ion-ios-folder:before,.ion-ios-football-outline:before,.ion-ios-football:before,.ion-ios-game-controller-a-outline:before,.ion-ios-game-controller-a:before,.ion-ios-game-controller-b-outline:before,.ion-ios-game-controller-b:before,.ion-ios-gear-outline:before,.ion-ios-gear:before,.ion-ios-glasses-outline:before,.ion-ios-glasses:before,.ion-ios-grid-view-outline:before,.ion-ios-grid-view:before,.ion-ios-heart-outline:before,.ion-ios-heart:before,.ion-ios-help-empty:before,.ion-ios-help-outline:before,.ion-ios-help:before,.ion-ios-home-outline:before,.ion-ios-home:before,.ion-ios-infinite-outline:before,.ion-ios-infinite:before,.ion-ios-information-empty:before,.ion-ios-information-outline:before,.ion-ios-information:before,.ion-ios-ionic-outline:before,.ion-ios-keypad-outline:before,.ion-ios-keypad:before,.ion-ios-lightbulb-outline:before,.ion-ios-lightbulb:before,.ion-ios-list-outline:before,.ion-ios-list:before,.ion-ios-location-outline:before,.ion-ios-location:before,.ion-ios-locked-outline:before,.ion-ios-locked:before,.ion-ios-loop-strong:before,.ion-ios-loop:before,.ion-ios-medical-outline:before,.ion-ios-medical:before,.ion-ios-medkit-outline:before,.ion-ios-medkit:before,.ion-ios-mic-off:before,.ion-ios-mic-outline:before,.ion-ios-mic:before,.ion-ios-minus-empty:before,.ion-ios-minus-outline:before,.ion-ios-minus:before,.ion-ios-monitor-outline:before,.ion-ios-monitor:before,.ion-ios-moon-outline:before,.ion-ios-moon:before,.ion-ios-more-outline:before,.ion-ios-more:before,.ion-ios-musical-note:before,.ion-ios-musical-notes:before,.ion-ios-navigate-outline:before,.ion-ios-navigate:before,.ion-ios-nutrition-outline:before,.ion-ios-nutrition:before,.ion-ios-paper-outline:before,.ion-ios-paper:before,.ion-ios-paperplane-outline:before,.ion-ios-paperplane:before,.ion-ios-partlysunny-outline:before,.ion-ios-partlysunny:before,.ion-ios-pause-outline:before,.ion-ios-pause:before,.ion-ios-paw-outline:before,.ion-ios-paw:before,.ion-ios-people-outline:before,.ion-ios-people:before,.ion-ios-person-outline:before,.ion-ios-person:before,.ion-ios-personadd-outline:before,.ion-ios-personadd:before,.ion-ios-photos-outline:before,.ion-ios-photos:before,.ion-ios-pie-outline:before,.ion-ios-pie:before,.ion-ios-pint-outline:before,.ion-ios-pint:before,.ion-ios-play-outline:before,.ion-ios-play:before,.ion-ios-plus-empty:before,.ion-ios-plus-outline:before,.ion-ios-plus:before,.ion-ios-pricetag-outline:before,.ion-ios-pricetag:before,.ion-ios-pricetags-outline:before,.ion-ios-pricetags:before,.ion-ios-printer-outline:before,.ion-ios-printer:before,.ion-ios-pulse-strong:before,.ion-ios-pulse:before,.ion-ios-rainy-outline:before,.ion-ios-rainy:before,.ion-ios-recording-outline:before,.ion-ios-recording:before,.ion-ios-redo-outline:before,.ion-ios-redo:before,.ion-ios-refresh-empty:before,.ion-ios-refresh-outline:before,.ion-ios-refresh:before,.ion-ios-reload:before,.ion-ios-reverse-camera-outline:before,.ion-ios-reverse-camera:before,.ion-ios-rewind-outline:before,.ion-ios-rewind:before,.ion-ios-rose-outline:before,.ion-ios-rose:before,.ion-ios-search-strong:before,.ion-ios-search:before,.ion-ios-settings-strong:before,.ion-ios-settings:before,.ion-ios-shuffle-strong:before,.ion-ios-shuffle:before,.ion-ios-skipbackward-outline:before,.ion-ios-skipbackward:before,.ion-ios-skipforward-outline:before,.ion-ios-skipforward:before,.ion-ios-snowy:before,.ion-ios-speedometer-outline:before,.ion-ios-speedometer:before,.ion-ios-star-half:before,.ion-ios-star-outline:before,.ion-ios-star:before,.ion-ios-stopwatch-outline:before,.ion-ios-stopwatch:before,.ion-ios-sunny-outline:before,.ion-ios-sunny:before,.ion-ios-telephone-outline:before,.ion-ios-telephone:before,.ion-ios-tennisball-outline:before,.ion-ios-tennisball:before,.ion-ios-thunderstorm-outline:before,.ion-ios-thunderstorm:before,.ion-ios-time-outline:before,.ion-ios-time:before,.ion-ios-timer-outline:before,.ion-ios-timer:before,.ion-ios-toggle-outline:before,.ion-ios-toggle:before,.ion-ios-trash-outline:before,.ion-ios-trash:before,.ion-ios-undo-outline:before,.ion-ios-undo:before,.ion-ios-unlocked-outline:before,.ion-ios-unlocked:before,.ion-ios-upload-outline:before,.ion-ios-upload:before,.ion-ios-videocam-outline:before,.ion-ios-videocam:before,.ion-ios-volume-high:before,.ion-ios-volume-low:before,.ion-ios-wineglass-outline:before,.ion-ios-wineglass:before,.ion-ios-world-outline:before,.ion-ios-world:before,.ion-ipad:before,.ion-iphone:before,.ion-ipod:before,.ion-jet:before,.ion-key:before,.ion-knife:before,.ion-laptop:before,.ion-leaf:before,.ion-levels:before,.ion-lightbulb:before,.ion-link:before,.ion-load-a:before,.ion-load-b:before,.ion-load-c:before,.ion-load-d:before,.ion-location:before,.ion-lock-combination:before,.ion-locked:before,.ion-log-in:before,.ion-log-out:before,.ion-loop:before,.ion-magnet:before,.ion-male:before,.ion-man:before,.ion-map:before,.ion-medkit:before,.ion-merge:before,.ion-mic-a:before,.ion-mic-b:before,.ion-mic-c:before,.ion-minus-circled:before,.ion-minus-round:before,.ion-minus:before,.ion-model-s:before,.ion-monitor:before,.ion-more:before,.ion-mouse:before,.ion-music-note:before,.ion-navicon-round:before,.ion-navicon:before,.ion-navigate:before,.ion-network:before,.ion-no-smoking:before,.ion-nuclear:before,.ion-outlet:before,.ion-paintbrush:before,.ion-paintbucket:before,.ion-paper-airplane:before,.ion-paperclip:before,.ion-pause:before,.ion-person-add:before,.ion-person-stalker:before,.ion-person:before,.ion-pie-graph:before,.ion-pin:before,.ion-pinpoint:before,.ion-pizza:before,.ion-plane:before,.ion-planet:before,.ion-play:before,.ion-playstation:before,.ion-plus-circled:before,.ion-plus-round:before,.ion-plus:before,.ion-podium:before,.ion-pound:before,.ion-power:before,.ion-pricetag:before,.ion-pricetags:before,.ion-printer:before,.ion-pull-request:before,.ion-qr-scanner:before,.ion-quote:before,.ion-radio-waves:before,.ion-record:before,.ion-refresh:before,.ion-reply-all:before,.ion-reply:before,.ion-ribbon-a:before,.ion-ribbon-b:before,.ion-sad-outline:before,.ion-sad:before,.ion-scissors:before,.ion-search:before,.ion-settings:before,.ion-share:before,.ion-shuffle:before,.ion-skip-backward:before,.ion-skip-forward:before,.ion-social-android-outline:before,.ion-social-android:before,.ion-social-angular-outline:before,.ion-social-angular:before,.ion-social-apple-outline:before,.ion-social-apple:before,.ion-social-bitcoin-outline:before,.ion-social-bitcoin:before,.ion-social-buffer-outline:before,.ion-social-buffer:before,.ion-social-chrome-outline:before,.ion-social-chrome:before,.ion-social-codepen-outline:before,.ion-social-codepen:before,.ion-social-css3-outline:before,.ion-social-css3:before,.ion-social-designernews-outline:before,.ion-social-designernews:before,.ion-social-dribbble-outline:before,.ion-social-dribbble:before,.ion-social-dropbox-outline:before,.ion-social-dropbox:before,.ion-social-euro-outline:before,.ion-social-euro:before,.ion-social-facebook-outline:before,.ion-social-facebook:before,.ion-social-foursquare-outline:before,.ion-social-foursquare:before,.ion-social-freebsd-devil:before,.ion-social-github-outline:before,.ion-social-github:before,.ion-social-google-outline:before,.ion-social-google:before,.ion-social-googleplus-outline:before,.ion-social-googleplus:before,.ion-social-hackernews-outline:before,.ion-social-hackernews:before,.ion-social-html5-outline:before,.ion-social-html5:before,.ion-social-instagram-outline:before,.ion-social-instagram:before,.ion-social-javascript-outline:before,.ion-social-javascript:before,.ion-social-linkedin-outline:before,.ion-social-linkedin:before,.ion-social-markdown:before,.ion-social-nodejs:before,.ion-social-octocat:before,.ion-social-pinterest-outline:before,.ion-social-pinterest:before,.ion-social-python:before,.ion-social-reddit-outline:before,.ion-social-reddit:before,.ion-social-rss-outline:before,.ion-social-rss:before,.ion-social-sass:before,.ion-social-skype-outline:before,.ion-social-skype:before,.ion-social-snapchat-outline:before,.ion-social-snapchat:before,.ion-social-tumblr-outline:before,.ion-social-tumblr:before,.ion-social-tux:before,.ion-social-twitch-outline:before,.ion-social-twitch:before,.ion-social-twitter-outline:before,.ion-social-twitter:before,.ion-social-usd-outline:before,.ion-social-usd:before,.ion-social-vimeo-outline:before,.ion-social-vimeo:before,.ion-social-whatsapp-outline:before,.ion-social-whatsapp:before,.ion-social-windows-outline:before,.ion-social-windows:before,.ion-social-wordpress-outline:before,.ion-social-wordpress:before,.ion-social-yahoo-outline:before,.ion-social-yahoo:before,.ion-social-yen-outline:before,.ion-social-yen:before,.ion-social-youtube-outline:before,.ion-social-youtube:before,.ion-soup-can-outline:before,.ion-soup-can:before,.ion-speakerphone:before,.ion-speedometer:before,.ion-spoon:before,.ion-star:before,.ion-stats-bars:before,.ion-steam:before,.ion-stop:before,.ion-thermometer:before,.ion-thumbsdown:before,.ion-thumbsup:before,.ion-toggle-filled:before,.ion-toggle:before,.ion-transgender:before,.ion-trash-a:before,.ion-trash-b:before,.ion-trophy:before,.ion-tshirt-outline:before,.ion-tshirt:before,.ion-umbrella:before,.ion-university:before,.ion-unlocked:before,.ion-upload:before,.ion-usb:before,.ion-videocamera:before,.ion-volume-high:before,.ion-volume-low:before,.ion-volume-medium:before,.ion-volume-mute:before,.ion-wand:before,.ion-waterdrop:before,.ion-wifi:before,.ion-wineglass:before,.ion-woman:before,.ion-wrench:before,.ion-xbox:before,.ionicons{display:inline-block;font-family:Ionicons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ion-alert:before{content:"ï„"}.ion-alert-circled:before{content:"ï„€"}.ion-android-add:before{content:""}.ion-android-add-circle:before{content:"ï™"}.ion-android-alarm-clock:before{content:"ïš"}.ion-android-alert:before{content:"ï›"}.ion-android-apps:before{content:"ïœ"}.ion-android-archive:before{content:""}.ion-android-arrow-back:before{content:""}.ion-android-arrow-down:before{content:"ï"}.ion-android-arrow-dropdown:before{content:"ïŸ"}.ion-android-arrow-dropdown-circle:before{content:"ïž"}.ion-android-arrow-dropleft:before{content:"ï¡"}.ion-android-arrow-dropleft-circle:before{content:"ï "}.ion-android-arrow-dropright:before{content:"ï£"}.ion-android-arrow-dropright-circle:before{content:"ï¢"}.ion-android-arrow-dropup:before{content:"ï¥"}.ion-android-arrow-dropup-circle:before{content:"ï¤"}.ion-android-arrow-forward:before{content:"ïŒ"}.ion-android-arrow-up:before{content:"ï¦"}.ion-android-attach:before{content:"ï§"}.ion-android-bar:before{content:"ï¨"}.ion-android-bicycle:before{content:"ï©"}.ion-android-boat:before{content:"ïª"}.ion-android-bookmark:before{content:"ï«"}.ion-android-bulb:before{content:"ï¬"}.ion-android-bus:before{content:"ï"}.ion-android-calendar:before{content:"ï‹‘"}.ion-android-call:before{content:"ï‹’"}.ion-android-camera:before{content:"ï‹“"}.ion-android-cancel:before{content:"ï®"}.ion-android-car:before{content:"ï¯"}.ion-android-cart:before{content:"ï°"}.ion-android-chat:before{content:"ï‹”"}.ion-android-checkbox:before{content:"ï´"}.ion-android-checkbox-blank:before{content:"ï±"}.ion-android-checkbox-outline:before{content:"ï³"}.ion-android-checkbox-outline-blank:before{content:"ï²"}.ion-android-checkmark-circle:before{content:"ïµ"}.ion-android-clipboard:before{content:"ï¶"}.ion-android-close:before{content:"ï‹—"}.ion-android-cloud:before{content:"ïº"}.ion-android-cloud-circle:before{content:"ï·"}.ion-android-cloud-done:before{content:"ï¸"}.ion-android-cloud-outline:before{content:"ï¹"}.ion-android-color-palette:before{content:"ï»"}.ion-android-compass:before{content:"ï¼"}.ion-android-contact:before{content:""}.ion-android-contacts:before{content:"ï‹™"}.ion-android-contract:before{content:"ï½"}.ion-android-create:before{content:"ï¾"}.ion-android-delete:before{content:"ï¿"}.ion-android-desktop:before{content:""}.ion-android-document:before{content:"ïŽ"}.ion-android-done:before{content:""}.ion-android-done-all:before{content:""}.ion-android-download:before{content:"ï‹"}.ion-android-drafts:before{content:""}.ion-android-exit:before{content:""}.ion-android-expand:before{content:""}.ion-android-favorite:before{content:""}.ion-android-favorite-outline:before{content:""}.ion-android-film:before{content:""}.ion-android-folder:before{content:"ï‹ "}.ion-android-folder-open:before{content:""}.ion-android-funnel:before{content:""}.ion-android-globe:before{content:""}.ion-android-hand:before{content:"ï‹£"}.ion-android-hangout:before{content:"ïŽ"}.ion-android-happy:before{content:""}.ion-android-home:before{content:"ïŽ"}.ion-android-image:before{content:""}.ion-android-laptop:before{content:"ïŽ"}.ion-android-list:before{content:""}.ion-android-locate:before{content:"ï‹©"}.ion-android-lock:before{content:""}.ion-android-mail:before{content:"ï‹«"}.ion-android-map:before{content:""}.ion-android-menu:before{content:""}.ion-android-microphone:before{content:""}.ion-android-microphone-off:before{content:""}.ion-android-more-horizontal:before{content:""}.ion-android-more-vertical:before{content:""}.ion-android-navigate:before{content:""}.ion-android-notifications:before{content:""}.ion-android-notifications-none:before{content:""}.ion-android-notifications-off:before{content:""}.ion-android-open:before{content:""}.ion-android-options:before{content:"ïŽ"}.ion-android-people:before{content:""}.ion-android-person:before{content:"ïŽ "}.ion-android-person-add:before{content:""}.ion-android-phone-landscape:before{content:""}.ion-android-phone-portrait:before{content:""}.ion-android-pin:before{content:""}.ion-android-plane:before{content:""}.ion-android-playstore:before{content:"ï‹°"}.ion-android-print:before{content:""}.ion-android-radio-button-off:before{content:""}.ion-android-radio-button-on:before{content:""}.ion-android-refresh:before{content:""}.ion-android-remove:before{content:"ï‹´"}.ion-android-remove-circle:before{content:""}.ion-android-restaurant:before{content:""}.ion-android-sad:before{content:""}.ion-android-search:before{content:""}.ion-android-send:before{content:"ï‹¶"}.ion-android-settings:before{content:"ï‹·"}.ion-android-share:before{content:""}.ion-android-share-alt:before{content:""}.ion-android-star:before{content:""}.ion-android-star-half:before{content:"ïŽ"}.ion-android-star-outline:before{content:""}.ion-android-stopwatch:before{content:""}.ion-android-subway:before{content:""}.ion-android-sunny:before{content:""}.ion-android-sync:before{content:""}.ion-android-textsms:before{content:""}.ion-android-time:before{content:""}.ion-android-train:before{content:""}.ion-android-unlock:before{content:""}.ion-android-upload:before{content:""}.ion-android-volume-down:before{content:""}.ion-android-volume-mute:before{content:""}.ion-android-volume-off:before{content:""}.ion-android-volume-up:before{content:""}.ion-android-walk:before{content:""}.ion-android-warning:before{content:""}.ion-android-watch:before{content:""}.ion-android-wifi:before{content:""}.ion-aperture:before{content:""}.ion-archive:before{content:"ï„‚"}.ion-arrow-down-a:before{content:""}.ion-arrow-down-b:before{content:"ï„„"}.ion-arrow-down-c:before{content:"ï„…"}.ion-arrow-expand:before{content:""}.ion-arrow-graph-down-left:before{content:""}.ion-arrow-graph-down-right:before{content:"ï‰ "}.ion-arrow-graph-up-left:before{content:""}.ion-arrow-graph-up-right:before{content:""}.ion-arrow-left-a:before{content:""}.ion-arrow-left-b:before{content:""}.ion-arrow-left-c:before{content:""}.ion-arrow-move:before{content:""}.ion-arrow-resize:before{content:""}.ion-arrow-return-left:before{content:""}.ion-arrow-return-right:before{content:""}.ion-arrow-right-a:before{content:""}.ion-arrow-right-b:before{content:""}.ion-arrow-right-c:before{content:"ï„‹"}.ion-arrow-shrink:before{content:""}.ion-arrow-swap:before{content:""}.ion-arrow-up-a:before{content:""}.ion-arrow-up-b:before{content:"ï„"}.ion-arrow-up-c:before{content:""}.ion-asterisk:before{content:""}.ion-at:before{content:"ï„"}.ion-backspace:before{content:""}.ion-backspace-outline:before{content:""}.ion-bag:before{content:"ï„"}.ion-battery-charging:before{content:"ï„‘"}.ion-battery-empty:before{content:"ï„’"}.ion-battery-full:before{content:"ï„“"}.ion-battery-half:before{content:"ï„”"}.ion-battery-low:before{content:"ï„•"}.ion-beaker:before{content:""}.ion-beer:before{content:""}.ion-bluetooth:before{content:"ï„–"}.ion-bonfire:before{content:""}.ion-bookmark:before{content:""}.ion-bowtie:before{content:"ï€"}.ion-briefcase:before{content:""}.ion-bug:before{content:""}.ion-calculator:before{content:"ï‰"}.ion-calendar:before{content:"ï„—"}.ion-camera:before{content:""}.ion-card:before{content:"ï„™"}.ion-cash:before{content:""}.ion-chatbox:before{content:"ï„›"}.ion-chatbox-working:before{content:""}.ion-chatboxes:before{content:""}.ion-chatbubble:before{content:""}.ion-chatbubble-working:before{content:"ï„"}.ion-chatbubbles:before{content:""}.ion-checkmark:before{content:"ï„¢"}.ion-checkmark-circled:before{content:"ï„ "}.ion-checkmark-round:before{content:"ï„¡"}.ion-chevron-down:before{content:"ï„£"}.ion-chevron-left:before{content:""}.ion-chevron-right:before{content:"ï„¥"}.ion-chevron-up:before{content:""}.ion-clipboard:before{content:"ï„§"}.ion-clock:before{content:""}.ion-close:before{content:""}.ion-close-circled:before{content:""}.ion-close-round:before{content:"ï„©"}.ion-closed-captioning:before{content:""}.ion-cloud:before{content:"ï„«"}.ion-code:before{content:""}.ion-code-download:before{content:""}.ion-code-working:before{content:""}.ion-coffee:before{content:""}.ion-compass:before{content:""}.ion-compose:before{content:""}.ion-connection-bars:before{content:""}.ion-contrast:before{content:""}.ion-crop:before{content:"ï"}.ion-cube:before{content:""}.ion-disc:before{content:"ï„"}.ion-document:before{content:""}.ion-document-text:before{content:"ï„®"}.ion-drag:before{content:"ï„°"}.ion-earth:before{content:""}.ion-easel:before{content:"ï‚"}.ion-edit:before{content:""}.ion-egg:before{content:""}.ion-eject:before{content:""}.ion-email:before{content:""}.ion-email-unread:before{content:"ïƒ"}.ion-erlenmeyer-flask:before{content:"ï…"}.ion-erlenmeyer-flask-bubbles:before{content:"ï„"}.ion-eye:before{content:""}.ion-eye-disabled:before{content:""}.ion-female:before{content:""}.ion-filing:before{content:"ï„´"}.ion-film-marker:before{content:""}.ion-fireball:before{content:""}.ion-flag:before{content:""}.ion-flame:before{content:""}.ion-flash:before{content:"ï„·"}.ion-flash-off:before{content:"ï„¶"}.ion-folder:before{content:""}.ion-fork:before{content:""}.ion-fork-repo:before{content:"ï‹€"}.ion-forward:before{content:""}.ion-funnel:before{content:""}.ion-gear-a:before{content:""}.ion-gear-b:before{content:""}.ion-grid:before{content:"ï„¿"}.ion-hammer:before{content:""}.ion-happy:before{content:""}.ion-happy-outline:before{content:"ï†"}.ion-headphone:before{content:"ï…€"}.ion-heart:before{content:"ï…"}.ion-heart-broken:before{content:"ïŒ"}.ion-help:before{content:"ï…ƒ"}.ion-help-buoy:before{content:""}.ion-help-circled:before{content:"ï…‚"}.ion-home:before{content:"ï…„"}.ion-icecream:before{content:""}.ion-image:before{content:"ï…‡"}.ion-images:before{content:"ï…ˆ"}.ion-information:before{content:"ï…Š"}.ion-information-circled:before{content:"ï…‰"}.ion-ionic:before{content:"ï…‹"}.ion-ios-alarm:before{content:"ïˆ"}.ion-ios-alarm-outline:before{content:"ï‡"}.ion-ios-albums:before{content:"ïŠ"}.ion-ios-albums-outline:before{content:"ï‰"}.ion-ios-americanfootball:before{content:"ïŒ"}.ion-ios-americanfootball-outline:before{content:"ï‹"}.ion-ios-analytics:before{content:"ïŽ"}.ion-ios-analytics-outline:before{content:"ï"}.ion-ios-arrow-back:before{content:"ï"}.ion-ios-arrow-down:before{content:"ï"}.ion-ios-arrow-forward:before{content:"ï‘"}.ion-ios-arrow-left:before{content:"ï’"}.ion-ios-arrow-right:before{content:"ï“"}.ion-ios-arrow-thin-down:before{content:"ï”"}.ion-ios-arrow-thin-left:before{content:"ï•"}.ion-ios-arrow-thin-right:before{content:"ï–"}.ion-ios-arrow-thin-up:before{content:"ï—"}.ion-ios-arrow-up:before{content:"ï˜"}.ion-ios-at:before{content:"ïš"}.ion-ios-at-outline:before{content:"ï™"}.ion-ios-barcode:before{content:"ïœ"}.ion-ios-barcode-outline:before{content:"ï›"}.ion-ios-baseball:before{content:"ïž"}.ion-ios-baseball-outline:before{content:"ï"}.ion-ios-basketball:before{content:"ï "}.ion-ios-basketball-outline:before{content:"ïŸ"}.ion-ios-bell:before{content:"ï¢"}.ion-ios-bell-outline:before{content:"ï¡"}.ion-ios-body:before{content:"ï¤"}.ion-ios-body-outline:before{content:"ï£"}.ion-ios-bolt:before{content:"ï¦"}.ion-ios-bolt-outline:before{content:"ï¥"}.ion-ios-book:before{content:"ï¨"}.ion-ios-book-outline:before{content:"ï§"}.ion-ios-bookmarks:before{content:"ïª"}.ion-ios-bookmarks-outline:before{content:"ï©"}.ion-ios-box:before{content:"ï¬"}.ion-ios-box-outline:before{content:"ï«"}.ion-ios-briefcase:before{content:"ï®"}.ion-ios-briefcase-outline:before{content:"ï"}.ion-ios-browsers:before{content:"ï°"}.ion-ios-browsers-outline:before{content:"ï¯"}.ion-ios-calculator:before{content:"ï²"}.ion-ios-calculator-outline:before{content:"ï±"}.ion-ios-calendar:before{content:"ï´"}.ion-ios-calendar-outline:before{content:"ï³"}.ion-ios-camera:before{content:"ï¶"}.ion-ios-camera-outline:before{content:"ïµ"}.ion-ios-cart:before{content:"ï¸"}.ion-ios-cart-outline:before{content:"ï·"}.ion-ios-chatboxes:before{content:"ïº"}.ion-ios-chatboxes-outline:before{content:"ï¹"}.ion-ios-chatbubble:before{content:"ï¼"}.ion-ios-chatbubble-outline:before{content:"ï»"}.ion-ios-checkmark:before{content:"ï¿"}.ion-ios-checkmark-empty:before{content:"ï½"}.ion-ios-checkmark-outline:before{content:"ï¾"}.ion-ios-circle-filled:before{content:"ï€"}.ion-ios-circle-outline:before{content:"ï"}.ion-ios-clock:before{content:"ïƒ"}.ion-ios-clock-outline:before{content:"ï‚"}.ion-ios-close:before{content:"ï†"}.ion-ios-close-empty:before{content:"ï„"}.ion-ios-close-outline:before{content:"ï…"}.ion-ios-cloud:before{content:"ïŒ"}.ion-ios-cloud-download:before{content:"ïˆ"}.ion-ios-cloud-download-outline:before{content:"ï‡"}.ion-ios-cloud-outline:before{content:"ï‰"}.ion-ios-cloud-upload:before{content:"ï‹"}.ion-ios-cloud-upload-outline:before{content:"ïŠ"}.ion-ios-cloudy:before{content:"ï"}.ion-ios-cloudy-night:before{content:"ïŽ"}.ion-ios-cloudy-night-outline:before{content:"ï"}.ion-ios-cloudy-outline:before{content:"ï"}.ion-ios-cog:before{content:"ï’"}.ion-ios-cog-outline:before{content:"ï‘"}.ion-ios-color-filter:before{content:"ï”"}.ion-ios-color-filter-outline:before{content:"ï“"}.ion-ios-color-wand:before{content:"ï–"}.ion-ios-color-wand-outline:before{content:"ï•"}.ion-ios-compose:before{content:"ï˜"}.ion-ios-compose-outline:before{content:"ï—"}.ion-ios-contact:before{content:"ïš"}.ion-ios-contact-outline:before{content:"ï™"}.ion-ios-copy:before{content:"ïœ"}.ion-ios-copy-outline:before{content:"ï›"}.ion-ios-crop:before{content:"ïž"}.ion-ios-crop-strong:before{content:"ï"}.ion-ios-download:before{content:"ï "}.ion-ios-download-outline:before{content:"ïŸ"}.ion-ios-drag:before{content:"ï¡"}.ion-ios-email:before{content:"ï£"}.ion-ios-email-outline:before{content:"ï¢"}.ion-ios-eye:before{content:"ï¥"}.ion-ios-eye-outline:before{content:"ï¤"}.ion-ios-fastforward:before{content:"ï§"}.ion-ios-fastforward-outline:before{content:"ï¦"}.ion-ios-filing:before{content:"ï©"}.ion-ios-filing-outline:before{content:"ï¨"}.ion-ios-film:before{content:"ï«"}.ion-ios-film-outline:before{content:"ïª"}.ion-ios-flag:before{content:"ï"}.ion-ios-flag-outline:before{content:"ï¬"}.ion-ios-flame:before{content:"ï¯"}.ion-ios-flame-outline:before{content:"ï®"}.ion-ios-flask:before{content:"ï±"}.ion-ios-flask-outline:before{content:"ï°"}.ion-ios-flower:before{content:"ï³"}.ion-ios-flower-outline:before{content:"ï²"}.ion-ios-folder:before{content:"ïµ"}.ion-ios-folder-outline:before{content:"ï´"}.ion-ios-football:before{content:"ï·"}.ion-ios-football-outline:before{content:"ï¶"}.ion-ios-game-controller-a:before{content:"ï¹"}.ion-ios-game-controller-a-outline:before{content:"ï¸"}.ion-ios-game-controller-b:before{content:"ï»"}.ion-ios-game-controller-b-outline:before{content:"ïº"}.ion-ios-gear:before{content:"ï½"}.ion-ios-gear-outline:before{content:"ï¼"}.ion-ios-glasses:before{content:"ï¿"}.ion-ios-glasses-outline:before{content:"ï¾"}.ion-ios-grid-view:before{content:"ï‘"}.ion-ios-grid-view-outline:before{content:"ï‘€"}.ion-ios-heart:before{content:""}.ion-ios-heart-outline:before{content:"ï‘‚"}.ion-ios-help:before{content:""}.ion-ios-help-empty:before{content:"ï‘„"}.ion-ios-help-outline:before{content:"ï‘…"}.ion-ios-home:before{content:""}.ion-ios-home-outline:before{content:""}.ion-ios-infinite:before{content:""}.ion-ios-infinite-outline:before{content:""}.ion-ios-information:before{content:"ï‘"}.ion-ios-information-empty:before{content:"ï‘‹"}.ion-ios-information-outline:before{content:""}.ion-ios-ionic-outline:before{content:""}.ion-ios-keypad:before{content:"ï‘"}.ion-ios-keypad-outline:before{content:"ï‘"}.ion-ios-lightbulb:before{content:"ï‘’"}.ion-ios-lightbulb-outline:before{content:"ï‘‘"}.ion-ios-list:before{content:"ï‘”"}.ion-ios-list-outline:before{content:"ï‘“"}.ion-ios-location:before{content:"ï‘–"}.ion-ios-location-outline:before{content:"ï‘•"}.ion-ios-locked:before{content:""}.ion-ios-locked-outline:before{content:"ï‘—"}.ion-ios-loop:before{content:""}.ion-ios-loop-strong:before{content:"ï‘™"}.ion-ios-medical:before{content:""}.ion-ios-medical-outline:before{content:"ï‘›"}.ion-ios-medkit:before{content:""}.ion-ios-medkit-outline:before{content:"ï‘"}.ion-ios-mic:before{content:"ï‘¡"}.ion-ios-mic-off:before{content:""}.ion-ios-mic-outline:before{content:"ï‘ "}.ion-ios-minus:before{content:""}.ion-ios-minus-empty:before{content:"ï‘¢"}.ion-ios-minus-outline:before{content:"ï‘£"}.ion-ios-monitor:before{content:""}.ion-ios-monitor-outline:before{content:"ï‘¥"}.ion-ios-moon:before{content:""}.ion-ios-moon-outline:before{content:"ï‘§"}.ion-ios-more:before{content:""}.ion-ios-more-outline:before{content:"ï‘©"}.ion-ios-musical-note:before{content:"ï‘«"}.ion-ios-musical-notes:before{content:""}.ion-ios-navigate:before{content:"ï‘®"}.ion-ios-navigate-outline:before{content:"ï‘"}.ion-ios-nutrition:before{content:"ï‘°"}.ion-ios-nutrition-outline:before{content:""}.ion-ios-paper:before{content:""}.ion-ios-paper-outline:before{content:""}.ion-ios-paperplane:before{content:"ï‘´"}.ion-ios-paperplane-outline:before{content:""}.ion-ios-partlysunny:before{content:"ï‘¶"}.ion-ios-partlysunny-outline:before{content:""}.ion-ios-pause:before{content:""}.ion-ios-pause-outline:before{content:"ï‘·"}.ion-ios-paw:before{content:""}.ion-ios-paw-outline:before{content:""}.ion-ios-people:before{content:""}.ion-ios-people-outline:before{content:"ï‘»"}.ion-ios-person:before{content:""}.ion-ios-person-outline:before{content:""}.ion-ios-personadd:before{content:"ï’€"}.ion-ios-personadd-outline:before{content:"ï‘¿"}.ion-ios-photos:before{content:"ï’‚"}.ion-ios-photos-outline:before{content:"ï’"}.ion-ios-pie:before{content:"ï’„"}.ion-ios-pie-outline:before{content:"ï’ƒ"}.ion-ios-pint:before{content:"ï’†"}.ion-ios-pint-outline:before{content:"ï’…"}.ion-ios-play:before{content:"ï’ˆ"}.ion-ios-play-outline:before{content:"ï’‡"}.ion-ios-plus:before{content:"ï’‹"}.ion-ios-plus-empty:before{content:"ï’‰"}.ion-ios-plus-outline:before{content:"ï’Š"}.ion-ios-pricetag:before{content:"ï’"}.ion-ios-pricetag-outline:before{content:"ï’Œ"}.ion-ios-pricetags:before{content:"ï’"}.ion-ios-pricetags-outline:before{content:"ï’Ž"}.ion-ios-printer:before{content:"ï’‘"}.ion-ios-printer-outline:before{content:"ï’"}.ion-ios-pulse:before{content:"ï’“"}.ion-ios-pulse-strong:before{content:"ï’’"}.ion-ios-rainy:before{content:"ï’•"}.ion-ios-rainy-outline:before{content:"ï’”"}.ion-ios-recording:before{content:"ï’—"}.ion-ios-recording-outline:before{content:"ï’–"}.ion-ios-redo:before{content:"ï’™"}.ion-ios-redo-outline:before{content:"ï’˜"}.ion-ios-refresh:before{content:"ï’œ"}.ion-ios-refresh-empty:before{content:"ï’š"}.ion-ios-refresh-outline:before{content:"ï’›"}.ion-ios-reload:before{content:"ï’"}.ion-ios-reverse-camera:before{content:"ï’Ÿ"}.ion-ios-reverse-camera-outline:before{content:"ï’ž"}.ion-ios-rewind:before{content:"ï’¡"}.ion-ios-rewind-outline:before{content:"ï’ "}.ion-ios-rose:before{content:"ï’£"}.ion-ios-rose-outline:before{content:"ï’¢"}.ion-ios-search:before{content:"ï’¥"}.ion-ios-search-strong:before{content:"ï’¤"}.ion-ios-settings:before{content:"ï’§"}.ion-ios-settings-strong:before{content:"ï’¦"}.ion-ios-shuffle:before{content:"ï’©"}.ion-ios-shuffle-strong:before{content:"ï’¨"}.ion-ios-skipbackward:before{content:"ï’«"}.ion-ios-skipbackward-outline:before{content:"ï’ª"}.ion-ios-skipforward:before{content:"ï’"}.ion-ios-skipforward-outline:before{content:"ï’¬"}.ion-ios-snowy:before{content:"ï’®"}.ion-ios-speedometer:before{content:"ï’°"}.ion-ios-speedometer-outline:before{content:"ï’¯"}.ion-ios-star:before{content:"ï’³"}.ion-ios-star-half:before{content:"ï’±"}.ion-ios-star-outline:before{content:"ï’²"}.ion-ios-stopwatch:before{content:"ï’µ"}.ion-ios-stopwatch-outline:before{content:"ï’´"}.ion-ios-sunny:before{content:"ï’·"}.ion-ios-sunny-outline:before{content:"ï’¶"}.ion-ios-telephone:before{content:"ï’¹"}.ion-ios-telephone-outline:before{content:"ï’¸"}.ion-ios-tennisball:before{content:"ï’»"}.ion-ios-tennisball-outline:before{content:"ï’º"}.ion-ios-thunderstorm:before{content:"ï’½"}.ion-ios-thunderstorm-outline:before{content:"ï’¼"}.ion-ios-time:before{content:"ï’¿"}.ion-ios-time-outline:before{content:"ï’¾"}.ion-ios-timer:before{content:"ï“"}.ion-ios-timer-outline:before{content:"ï“€"}.ion-ios-toggle:before{content:""}.ion-ios-toggle-outline:before{content:"ï“‚"}.ion-ios-trash:before{content:"ï“…"}.ion-ios-trash-outline:before{content:"ï“„"}.ion-ios-undo:before{content:""}.ion-ios-undo-outline:before{content:""}.ion-ios-unlocked:before{content:""}.ion-ios-unlocked-outline:before{content:""}.ion-ios-upload:before{content:"ï“‹"}.ion-ios-upload-outline:before{content:""}.ion-ios-videocam:before{content:"ï“"}.ion-ios-videocam-outline:before{content:""}.ion-ios-volume-high:before{content:""}.ion-ios-volume-low:before{content:"ï“"}.ion-ios-wineglass:before{content:"ï“‘"}.ion-ios-wineglass-outline:before{content:"ï“"}.ion-ios-world:before{content:"ï““"}.ion-ios-world-outline:before{content:"ï“’"}.ion-ipad:before{content:""}.ion-iphone:before{content:""}.ion-ipod:before{content:""}.ion-jet:before{content:""}.ion-key:before{content:""}.ion-knife:before{content:""}.ion-laptop:before{content:""}.ion-leaf:before{content:""}.ion-levels:before{content:""}.ion-lightbulb:before{content:""}.ion-link:before{content:""}.ion-load-a:before{content:""}.ion-load-b:before{content:""}.ion-load-c:before{content:""}.ion-load-d:before{content:"ïŠ"}.ion-location:before{content:""}.ion-lock-combination:before{content:"ï“”"}.ion-locked:before{content:""}.ion-log-in:before{content:""}.ion-log-out:before{content:""}.ion-loop:before{content:"ïˆ"}.ion-magnet:before{content:"ïŠ "}.ion-male:before{content:""}.ion-man:before{content:""}.ion-map:before{content:""}.ion-medkit:before{content:""}.ion-merge:before{content:""}.ion-mic-a:before{content:""}.ion-mic-b:before{content:""}.ion-mic-c:before{content:""}.ion-minus:before{content:""}.ion-minus-circled:before{content:""}.ion-minus-round:before{content:""}.ion-model-s:before{content:"ï‹"}.ion-monitor:before{content:""}.ion-more:before{content:""}.ion-mouse:before{content:"ï€"}.ion-music-note:before{content:""}.ion-navicon:before{content:""}.ion-navicon-round:before{content:"ïˆ"}.ion-navigate:before{content:""}.ion-network:before{content:"ï"}.ion-no-smoking:before{content:"ï‹‚"}.ion-nuclear:before{content:""}.ion-outlet:before{content:"ï‚"}.ion-paintbrush:before{content:"ï“•"}.ion-paintbucket:before{content:"ï“–"}.ion-paper-airplane:before{content:""}.ion-paperclip:before{content:"ïˆ"}.ion-pause:before{content:"ïˆ"}.ion-person:before{content:""}.ion-person-add:before{content:""}.ion-person-stalker:before{content:""}.ion-pie-graph:before{content:""}.ion-pin:before{content:""}.ion-pinpoint:before{content:""}.ion-pizza:before{content:""}.ion-plane:before{content:""}.ion-planet:before{content:"ïƒ"}.ion-play:before{content:""}.ion-playstation:before{content:""}.ion-plus:before{content:""}.ion-plus-circled:before{content:""}.ion-plus-round:before{content:""}.ion-podium:before{content:"ï„"}.ion-pound:before{content:""}.ion-power:before{content:""}.ion-pricetag:before{content:""}.ion-pricetags:before{content:""}.ion-printer:before{content:""}.ion-pull-request:before{content:"ï…"}.ion-qr-scanner:before{content:"ï†"}.ion-quote:before{content:"ï‡"}.ion-radio-waves:before{content:""}.ion-record:before{content:""}.ion-refresh:before{content:""}.ion-reply:before{content:""}.ion-reply-all:before{content:"ïˆ"}.ion-ribbon-a:before{content:"ïˆ"}.ion-ribbon-b:before{content:"ï‰"}.ion-sad:before{content:"ïŠ"}.ion-sad-outline:before{content:"ï“—"}.ion-scissors:before{content:"ï‹"}.ion-search:before{content:""}.ion-settings:before{content:"ïŠ"}.ion-share:before{content:"ïˆ "}.ion-shuffle:before{content:""}.ion-skip-backward:before{content:""}.ion-skip-forward:before{content:""}.ion-social-android:before{content:""}.ion-social-android-outline:before{content:""}.ion-social-angular:before{content:"ï“™"}.ion-social-angular-outline:before{content:""}.ion-social-apple:before{content:""}.ion-social-apple-outline:before{content:""}.ion-social-bitcoin:before{content:""}.ion-social-bitcoin-outline:before{content:""}.ion-social-buffer:before{content:""}.ion-social-buffer-outline:before{content:""}.ion-social-chrome:before{content:"ï“›"}.ion-social-chrome-outline:before{content:""}.ion-social-codepen:before{content:"ï“"}.ion-social-codepen-outline:before{content:""}.ion-social-css3:before{content:""}.ion-social-css3-outline:before{content:""}.ion-social-designernews:before{content:""}.ion-social-designernews-outline:before{content:""}.ion-social-dribbble:before{content:"ïˆ"}.ion-social-dribbble-outline:before{content:""}.ion-social-dropbox:before{content:""}.ion-social-dropbox-outline:before{content:""}.ion-social-euro:before{content:"ï“¡"}.ion-social-euro-outline:before{content:"ï“ "}.ion-social-facebook:before{content:""}.ion-social-facebook-outline:before{content:""}.ion-social-foursquare:before{content:"ï"}.ion-social-foursquare-outline:before{content:"ïŒ"}.ion-social-freebsd-devil:before{content:"ï‹„"}.ion-social-github:before{content:""}.ion-social-github-outline:before{content:""}.ion-social-google:before{content:"ï"}.ion-social-google-outline:before{content:"ïŽ"}.ion-social-googleplus:before{content:""}.ion-social-googleplus-outline:before{content:""}.ion-social-hackernews:before{content:""}.ion-social-hackernews-outline:before{content:""}.ion-social-html5:before{content:"ï“£"}.ion-social-html5-outline:before{content:"ï“¢"}.ion-social-instagram:before{content:"ï‘"}.ion-social-instagram-outline:before{content:"ï"}.ion-social-javascript:before{content:"ï“¥"}.ion-social-javascript-outline:before{content:""}.ion-social-linkedin:before{content:""}.ion-social-linkedin-outline:before{content:""}.ion-social-markdown:before{content:""}.ion-social-nodejs:before{content:"ï“§"}.ion-social-octocat:before{content:""}.ion-social-pinterest:before{content:""}.ion-social-pinterest-outline:before{content:""}.ion-social-python:before{content:"ï“©"}.ion-social-reddit:before{content:""}.ion-social-reddit-outline:before{content:""}.ion-social-rss:before{content:""}.ion-social-rss-outline:before{content:""}.ion-social-sass:before{content:""}.ion-social-skype:before{content:""}.ion-social-skype-outline:before{content:""}.ion-social-snapchat:before{content:""}.ion-social-snapchat-outline:before{content:"ï“«"}.ion-social-tumblr:before{content:"ï‰"}.ion-social-tumblr-outline:before{content:""}.ion-social-tux:before{content:"ï‹…"}.ion-social-twitch:before{content:"ï“®"}.ion-social-twitch-outline:before{content:"ï“"}.ion-social-twitter:before{content:""}.ion-social-twitter-outline:before{content:""}.ion-social-usd:before{content:"ï“"}.ion-social-usd-outline:before{content:"ï’"}.ion-social-vimeo:before{content:""}.ion-social-vimeo-outline:before{content:""}.ion-social-whatsapp:before{content:"ï“°"}.ion-social-whatsapp-outline:before{content:""}.ion-social-windows:before{content:""}.ion-social-windows-outline:before{content:""}.ion-social-wordpress:before{content:""}.ion-social-wordpress-outline:before{content:""}.ion-social-yahoo:before{content:""}.ion-social-yahoo-outline:before{content:""}.ion-social-yen:before{content:""}.ion-social-yen-outline:before{content:""}.ion-social-youtube:before{content:"ï‰"}.ion-social-youtube-outline:before{content:""}.ion-soup-can:before{content:"ï“´"}.ion-soup-can-outline:before{content:""}.ion-speakerphone:before{content:""}.ion-speedometer:before{content:""}.ion-spoon:before{content:""}.ion-star:before{content:""}.ion-stats-bars:before{content:""}.ion-steam:before{content:""}.ion-stop:before{content:"ï‰"}.ion-thermometer:before{content:""}.ion-thumbsdown:before{content:"ï‰"}.ion-thumbsup:before{content:""}.ion-toggle:before{content:"ï•"}.ion-toggle-filled:before{content:"ï”"}.ion-transgender:before{content:""}.ion-trash-a:before{content:""}.ion-trash-b:before{content:""}.ion-trophy:before{content:"ï–"}.ion-tshirt:before{content:"ï“·"}.ion-tshirt-outline:before{content:"ï“¶"}.ion-umbrella:before{content:""}.ion-university:before{content:"ï—"}.ion-unlocked:before{content:""}.ion-upload:before{content:""}.ion-usb:before{content:""}.ion-videocamera:before{content:""}.ion-volume-high:before{content:""}.ion-volume-low:before{content:""}.ion-volume-medium:before{content:""}.ion-volume-mute:before{content:""}.ion-wand:before{content:"ï˜"}.ion-waterdrop:before{content:""}.ion-wifi:before{content:""}.ion-wineglass:before{content:""}.ion-woman:before{content:"ï‰"}.ion-wrench:before{content:""}.ion-xbox:before{content:""}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;vertical-align:baseline;font:inherit;font-size:100%}ol,ul{list-style:none}blockquote,q{quotes:none}audio:not([controls]){display:none;height:0}[hidden],template{display:none}script{display:none!important}html{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}:focus,a,a:active,a:focus,a:hover,button,button:focus{outline:0}a{-webkit-user-drag:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent}a[href]:hover{cursor:pointer}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}code,kbd,pre,samp{font-size:1em;font-family:monospace,serif}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{position:relative;vertical-align:baseline;font-size:75%;line-height:0}sup{top:-.5em}sub{bottom:-.25em}fieldset{margin:0 2px;padding:.35em .625em .75em;border:1px solid silver}button,input,select,textarea{margin:0;outline-offset:0;outline-style:none;outline-width:0;-webkit-font-smoothing:inherit;background-image:none}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto}img{-webkit-user-drag:none}table{border-spacing:0;border-collapse:collapse}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{overflow:hidden;-ms-touch-action:pan-y;touch-action:pan-y}.ionic-body,body{-webkit-touch-callout:none;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;top:0;right:0;bottom:0;left:0;overflow:hidden;margin:0;padding:0;color:#000;word-wrap:break-word;font-size:14px;font-family:-apple-system;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:20px;text-rendering:optimizeLegibility;-webkit-backface-visibility:hidden;-webkit-user-drag:none;-ms-content-zooming:none}body.grade-b,body.grade-c{text-rendering:auto}.content{position:relative}.scroll-content{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;margin-top:-1px;padding-top:1px;margin-bottom:-1px;width:auto;height:auto}.menu .scroll-content.scroll-content-false{z-index:11}.scroll-view{position:relative;display:block;overflow:hidden;margin-top:-1px}.scroll-view.overflow-scroll{position:relative}.scroll-view.scroll-x{overflow-x:scroll;overflow-y:hidden}.scroll-view.scroll-y{overflow-x:hidden;overflow-y:scroll}.scroll-view.scroll-xy{overflow-x:scroll;overflow-y:scroll}.scroll{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;-webkit-transform-origin:left top;transform-origin:left top}@-ms-viewport{width:device-width}.scroll-bar{position:absolute;z-index:9999}.ng-animate .scroll-bar{visibility:hidden}.scroll-bar-h{right:2px;bottom:3px;left:2px;height:3px}.scroll-bar-h .scroll-bar-indicator{height:100%}.scroll-bar-v{top:2px;right:3px;bottom:2px;width:3px}.scroll-bar-v .scroll-bar-indicator{width:100%}.scroll-bar-indicator{position:absolute;border-radius:4px;background:rgba(0,0,0,.3);opacity:1;-webkit-transition:opacity .3s linear;transition:opacity .3s linear}.scroll-bar-indicator.scroll-bar-fade-out{opacity:0}.platform-android .scroll-bar-indicator{border-radius:0}.grade-b .scroll-bar-indicator,.grade-c .scroll-bar-indicator{background:#aaa}.grade-b .scroll-bar-indicator.scroll-bar-fade-out,.grade-c .scroll-bar-indicator.scroll-bar-fade-out{-webkit-transition:none;transition:none}ion-infinite-scroll{height:60px;width:100%;display:block;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}ion-infinite-scroll .icon{font-size:30px;color:#666}ion-infinite-scroll:not(.active) .icon:before,ion-infinite-scroll:not(.active) .spinner{display:none}.overflow-scroll{overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar;top:0;right:0;bottom:0;left:0;position:absolute}.overflow-scroll.pane{overflow-x:hidden;overflow-y:scroll}.overflow-scroll .scroll{position:static;height:100%;-webkit-transform:translate3d(0,0,0)}.overflow-scroll.keyboard-up:not(.keyboard-up-confirm){overflow:hidden}.has-header{top:44px}.no-header{top:0}.has-subheader{top:88px}.has-tabs-top{top:93px}.has-header.has-subheader.has-tabs-top{top:137px}.has-footer{bottom:44px}.has-subfooter{bottom:88px}.bar-footer.has-tabs,.has-tabs{bottom:49px}.bar-footer.has-tabs.pane,.has-tabs.pane{bottom:49px;height:auto}.bar-subfooter.has-tabs,.has-footer.has-tabs{bottom:93px}.pane{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-duration:0;transition-duration:0;z-index:1}.view{z-index:1}.pane,.view{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;background-color:#fff;overflow:hidden}.view-container{position:absolute;display:block;width:100%;height:100%}p{margin:0 0 10px}small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{color:#000;font-weight:500;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;line-height:1.2}.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1:first-child,.h2:first-child,.h3:first-child,h1:first-child,h2:first-child,h3:first-child{margin-top:0}.h1+.h1,.h1+.h2,.h1+.h3,.h1+h1,.h1+h2,.h1+h3,.h2+.h1,.h2+.h2,.h2+.h3,.h2+h1,.h2+h2,.h2+h3,.h3+.h1,.h3+.h2,.h3+.h3,.h3+h1,.h3+h2,.h3+h3,h1+.h1,h1+.h2,h1+.h3,h1+h1,h1+h2,h1+h3,h2+.h1,h2+.h2,h2+.h3,h2+h1,h2+h2,h2+h3,h3+.h1,h3+.h2,h3+.h3,h3+h1,h3+h2,h3+h3{margin-top:10px}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}.h1 small,h1 small{font-size:24px}.h2 small,h2 small{font-size:18px}.h3 small,.h4 small,h3 small,h4 small{font-size:14px}dl{margin-bottom:20px}dd,dt{line-height:1.42857}dt{font-weight:700}blockquote{margin:0 0 20px;padding:10px 20px;border-left:5px solid gray}blockquote p{font-weight:300;font-size:17.5px;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.42857}blockquote small:before{content:'\2014 \00A0'}blockquote:after,blockquote:before,q:after,q:before{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.42857}a{color:#387ef5}a.subdued{padding-right:10px;color:#888;text-decoration:none}a.subdued:hover{text-decoration:none}a.subdued:last-child{padding-right:0}.action-sheet-backdrop{-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:transparent}.action-sheet-backdrop.active{background-color:rgba(0,0,0,.4)}.action-sheet-wrapper{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);-webkit-transition:all cubic-bezier(.36,.66,.04,1) 500ms;transition:all cubic-bezier(.36,.66,.04,1) 500ms;position:absolute;bottom:0;left:0;right:0;width:100%;max-width:500px;margin:auto}.action-sheet-up{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.action-sheet{margin-left:8px;margin-right:8px;width:auto;z-index:11;overflow:hidden}.action-sheet .button{display:block;padding:1px;width:100%;border-radius:0;border-color:#d1d3d6;background-color:transparent;color:#007aff;font-size:21px}.action-sheet .button:hover{color:#007aff}.action-sheet .button.destructive,.action-sheet .button.destructive:hover{color:#ff3b30}.action-sheet .button.activated,.action-sheet .button.active{box-shadow:none;border-color:#d1d3d6;color:#007aff;background:#e4e5e7}.action-sheet-has-icons .icon{position:absolute;left:16px}.action-sheet-title{padding:16px;color:#8f8f8f;text-align:center;font-size:13px}.action-sheet-group{margin-bottom:8px;border-radius:4px;background-color:#fff;overflow:hidden}.action-sheet-group .button{border-width:1px 0 0 0}.action-sheet-group .button:first-child:last-child{border-width:0}.action-sheet-options{background:#f1f2f3}.action-sheet-cancel .button{font-weight:500}.action-sheet-open,.action-sheet-open.modal-open .modal{pointer-events:none}.action-sheet-open .action-sheet-backdrop{pointer-events:auto}.platform-android .action-sheet-backdrop.active{background-color:rgba(0,0,0,.2)}.platform-android .action-sheet{margin:0}.platform-android .action-sheet .action-sheet-title,.platform-android .action-sheet .button{text-align:left;border-color:transparent;font-size:16px;color:inherit}.platform-android .action-sheet .action-sheet-title{font-size:14px;padding:16px;color:#666}.platform-android .action-sheet .button.activated,.platform-android .action-sheet .button.active{background:#e8e8e8}.platform-android .action-sheet-group{margin:0;border-radius:0;background-color:#fafafa}.platform-android .action-sheet-cancel{display:none}.platform-android .action-sheet-has-icons .button{padding-left:56px}.backdrop{position:fixed;top:0;left:0;z-index:11;width:100%;height:100%;background-color:rgba(0,0,0,.4);visibility:hidden;opacity:0;-webkit-transition:.1s opacity linear;transition:.1s opacity linear}.backdrop.visible{visibility:visible}.backdrop.active{opacity:1}.bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:absolute;right:0;left:0;z-index:9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:5px;width:100%;height:44px;border-width:0;border-style:solid;border-top:1px solid transparent;border-bottom:1px solid #ddd;background-color:#fff;background-size:0}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.bar{border:none;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);background-position:bottom;background-size:100% 1px;background-repeat:no-repeat}}.bar.bar-clear{border:none;background:0 0;color:#fff}.bar.bar-clear .button,.bar.bar-clear .title{color:#fff}.bar.item-input-inset .item-input-wrapper{margin-top:-1px}.bar.item-input-inset .item-input-wrapper input{padding-left:8px;width:94%;height:28px;background:0 0}.bar.bar-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.bar.bar-light .title{color:#444}.bar.bar-light.bar-footer{background-image:linear-gradient(180deg,#ddd,#ddd 50%,transparent 50%)}.bar.bar-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.bar.bar-stable .title{color:#444}.bar.bar-stable.bar-footer{background-image:linear-gradient(180deg,#b2b2b2,#b2b2b2 50%,transparent 50%)}.bar.bar-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.bar.bar-positive .title{color:#fff}.bar.bar-positive.bar-footer{background-image:linear-gradient(180deg,#0c60ee,#0c60ee 50%,transparent 50%)}.bar.bar-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.bar.bar-calm .title{color:#fff}.bar.bar-calm.bar-footer{background-image:linear-gradient(180deg,#0a9dc7,#0a9dc7 50%,transparent 50%)}.bar.bar-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.bar.bar-assertive .title{color:#fff}.bar.bar-assertive.bar-footer{background-image:linear-gradient(180deg,#e42112,#e42112 50%,transparent 50%)}.bar.bar-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.bar.bar-balanced .title{color:#fff}.bar.bar-balanced.bar-footer{background-image:linear-gradient(180deg,#28a54c,#0c60ee 50%,transparent 50%)}.bar.bar-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.bar.bar-energized .title{color:#fff}.bar.bar-energized.bar-footer{background-image:linear-gradient(180deg,#e6b500,#e6b500 50%,transparent 50%)}.bar.bar-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.bar.bar-royal .title{color:#fff}.bar.bar-royal.bar-footer{background-image:linear-gradient(180deg,#6b46e5,#6b46e5 50%,transparent 50%)}.bar.bar-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.bar.bar-dark .title{color:#fff}.bar.bar-dark.bar-footer{background-image:linear-gradient(180deg,#111,#111 50%,transparent 50%)}.bar .title{display:block;position:absolute;top:0;right:0;left:0;z-index:0;overflow:hidden;margin:0 10px;min-width:30px;height:43px;text-align:center;text-overflow:ellipsis;white-space:nowrap;font-size:17px;font-weight:500;line-height:44px}.bar .title.title-left{text-align:left}.bar .title.title-right{text-align:right}.bar .title a{color:inherit}.bar .button,.bar button{z-index:1;padding:0 8px;min-width:initial;min-height:31px;font-weight:400;font-size:13px;line-height:32px}.bar .button .icon:before,.bar .button.button-icon:before,.bar .button.icon-left:before,.bar .button.icon-right:before,.bar .button.icon:before,.bar button .icon:before,.bar button.button-icon:before,.bar button.icon-left:before,.bar button.icon-right:before,.bar button.icon:before{padding-right:2px;padding-left:2px;font-size:20px;line-height:32px}.bar .button.button-icon,.bar button.button-icon{font-size:17px}.bar .button.button-icon .icon:before,.bar .button.button-icon.icon-left:before,.bar .button.button-icon.icon-right:before,.bar .button.button-icon:before,.bar button.button-icon .icon:before,.bar button.button-icon.icon-left:before,.bar button.button-icon.icon-right:before,.bar button.button-icon:before{vertical-align:top;font-size:32px;line-height:32px}.bar .button.button-clear,.bar button.button-clear{padding-right:2px;padding-left:2px;font-weight:300;font-size:17px}.bar .button.button-clear .icon:before,.bar .button.button-clear.icon-left:before,.bar .button.button-clear.icon-right:before,.bar .button.button-clear.icon:before,.bar button.button-clear .icon:before,.bar button.button-clear.icon-left:before,.bar button.button-clear.icon-right:before,.bar button.button-clear.icon:before{font-size:32px;line-height:32px}.bar .button.back-button,.bar button.back-button{display:block;margin-right:5px;padding:0;white-space:nowrap;font-weight:400}.bar .button.back-button.activated,.bar .button.back-button.active,.bar button.back-button.activated,.bar button.back-button.active{opacity:.2}.bar .button-bar>.button,.bar .buttons>.button{min-height:31px;line-height:32px}.bar .button+.button-bar,.bar .button-bar+.button{margin-left:5px}.bar .buttons,.bar .buttons.primary-buttons,.bar .buttons.secondary-buttons{display:inherit}.bar .buttons span{display:inline-block}.bar .buttons-left span{margin-right:5px;display:inherit}.bar .buttons-right span{margin-left:5px;display:inherit}.bar .buttons.pull-right,.bar .title+.button:last-child,.bar .title+.buttons,.bar>.button+.button:last-child,.bar>.button.pull-right{position:absolute;top:5px;right:5px;bottom:5px}.platform-android .nav-bar-has-subheader .bar{background-image:none}.platform-android .bar .back-button .icon:before{font-size:24px}.platform-android .bar .title{font-size:19px;line-height:44px}.bar-light .button{border-color:transparent;background-color:#fff;color:#444}.bar-light .button:hover{color:#444;text-decoration:none}.bar-light .button.activated,.bar-light .button.active{background-color:#fafafa}.bar-light .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-light .button.button-icon{border-color:transparent;background:0 0}.bar-stable .button{border-color:transparent;background-color:#f8f8f8;color:#444}.bar-stable .button:hover{color:#444;text-decoration:none}.bar-stable .button.activated,.bar-stable .button.active{background-color:#e5e5e5}.bar-stable .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444;font-size:17px}.bar-stable .button.button-icon{border-color:transparent;background:0 0}.bar-positive .button{border-color:transparent;background-color:#387ef5;color:#fff}.bar-positive .button:hover{color:#fff;text-decoration:none}.bar-positive .button.activated,.bar-positive .button.active{background-color:#0c60ee}.bar-positive .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-positive .button.button-icon{border-color:transparent;background:0 0}.bar-calm .button{border-color:transparent;background-color:#11c1f3;color:#fff}.bar-calm .button:hover{color:#fff;text-decoration:none}.bar-calm .button.activated,.bar-calm .button.active{background-color:#0a9dc7}.bar-calm .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-calm .button.button-icon{border-color:transparent;background:0 0}.bar-assertive .button{border-color:transparent;background-color:#ef473a;color:#fff}.bar-assertive .button:hover{color:#fff;text-decoration:none}.bar-assertive .button.activated,.bar-assertive .button.active{background-color:#e42112}.bar-assertive .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-assertive .button.button-icon{border-color:transparent;background:0 0}.bar-balanced .button{border-color:transparent;background-color:#33cd5f;color:#fff}.bar-balanced .button:hover{color:#fff;text-decoration:none}.bar-balanced .button.activated,.bar-balanced .button.active{background-color:#28a54c}.bar-balanced .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-balanced .button.button-icon{border-color:transparent;background:0 0}.bar-energized .button{border-color:transparent;background-color:#ffc900;color:#fff}.bar-energized .button:hover{color:#fff;text-decoration:none}.bar-energized .button.activated,.bar-energized .button.active{background-color:#e6b500}.bar-energized .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-energized .button.button-icon{border-color:transparent;background:0 0}.bar-royal .button{border-color:transparent;background-color:#886aea;color:#fff}.bar-royal .button:hover{color:#fff;text-decoration:none}.bar-royal .button.activated,.bar-royal .button.active{background-color:#6b46e5}.bar-royal .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-royal .button.button-icon{border-color:transparent;background:0 0}.bar-dark .button{border-color:transparent;background-color:#444;color:#fff}.bar-dark .button:hover{color:#fff;text-decoration:none}.bar-dark .button.activated,.bar-dark .button.active{background-color:#262626}.bar-dark .button.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#fff;font-size:17px}.bar-dark .button.button-icon{border-color:transparent;background:0 0}.bar-header{top:0;border-top-width:0;border-bottom-width:1px}.bar-header.has-tabs-top,.tabs-top .bar-header{border-bottom-width:0;background-image:none}.bar-footer{bottom:0;border-top-width:1px;border-bottom-width:0;background-position:top;height:44px}.bar-footer.item-input-inset{position:absolute}.bar-tabs{padding:0}.bar-subheader{top:44px;display:block;height:44px}.bar-subfooter{bottom:44px;display:block;height:44px}.nav-bar-block{position:absolute;top:0;right:0;left:0;z-index:9}.bar .back-button.hide,.bar .buttons .hide{display:none}.nav-bar-tabs-top .bar{background-image:none}.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:horizontal;-moz-flex-direction:horizontal;-ms-flex-direction:horizontal;flex-direction:horizontal;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444;position:absolute;bottom:0;z-index:5;width:100%;height:49px;border-style:solid;border-top-width:1px;background-size:0;line-height:49px}.tabs .tab-item .badge{background-color:#444;color:#f8f8f8}@media (min--moz-device-pixel-ratio:1.5),(-webkit-min-device-pixel-ratio:1.5),(min-device-pixel-ratio:1.5),(min-resolution:144dpi),(min-resolution:1.5dppx){.tabs{padding-top:2px;border-top:none!important;border-bottom:none;background-position:top;background-size:100% 1px;background-repeat:no-repeat}}.tabs-light>.tabs,.tabs.tabs-light{border-color:#ddd;background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);color:#444}.tabs-light>.tabs .tab-item .badge,.tabs.tabs-light .tab-item .badge{background-color:#444;color:#fff}.tabs-stable>.tabs,.tabs.tabs-stable{border-color:#b2b2b2;background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);color:#444}.tabs-stable>.tabs .tab-item .badge,.tabs.tabs-stable .tab-item .badge{background-color:#444;color:#f8f8f8}.tabs-positive>.tabs,.tabs.tabs-positive{border-color:#0c60ee;background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);color:#fff}.tabs-positive>.tabs .tab-item .badge,.tabs.tabs-positive .tab-item .badge{background-color:#fff;color:#387ef5}.tabs-calm>.tabs,.tabs.tabs-calm{border-color:#0a9dc7;background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);color:#fff}.tabs-calm>.tabs .tab-item .badge,.tabs.tabs-calm .tab-item .badge{background-color:#fff;color:#11c1f3}.tabs-assertive>.tabs,.tabs.tabs-assertive{border-color:#e42112;background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);color:#fff}.tabs-assertive>.tabs .tab-item .badge,.tabs.tabs-assertive .tab-item .badge{background-color:#fff;color:#ef473a}.tabs-balanced>.tabs,.tabs.tabs-balanced{border-color:#28a54c;background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);color:#fff}.tabs-balanced>.tabs .tab-item .badge,.tabs.tabs-balanced .tab-item .badge{background-color:#fff;color:#33cd5f}.tabs-energized>.tabs,.tabs.tabs-energized{border-color:#e6b500;background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);color:#fff}.tabs-energized>.tabs .tab-item .badge,.tabs.tabs-energized .tab-item .badge{background-color:#fff;color:#ffc900}.tabs-royal>.tabs,.tabs.tabs-royal{border-color:#6b46e5;background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);color:#fff}.tabs-royal>.tabs .tab-item .badge,.tabs.tabs-royal .tab-item .badge{background-color:#fff;color:#886aea}.tabs-dark>.tabs,.tabs.tabs-dark{border-color:#111;background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);color:#fff}.tabs-dark>.tabs .tab-item .badge,.tabs.tabs-dark .tab-item .badge{background-color:#fff;color:#444}.tabs-striped .tabs{background-color:#fff;background-image:none;border:none;border-bottom:1px solid #ddd;padding-top:2px}.tabs-striped .tab-item.activated,.tabs-striped .tab-item.active,.tabs-striped .tab-item.tab-item-active{margin-top:-2px;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped .tab-item.activated .badge,.tabs-striped .tab-item.active .badge,.tabs-striped .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-light .tabs{background-color:#fff}.tabs-striped.tabs-light .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-light .tab-item.activated,.tabs-striped.tabs-light .tab-item.active,.tabs-striped.tabs-light .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped.tabs-stable .tabs{background-color:#f8f8f8}.tabs-striped.tabs-stable .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-stable .tab-item.activated,.tabs-striped.tabs-stable .tab-item.active,.tabs-striped.tabs-stable .tab-item.tab-item-active{margin-top:-2px;color:#444;border-style:solid;border-width:2px 0 0 0;border-color:#444}.tabs-striped.tabs-positive .tabs{background-color:#387ef5}.tabs-striped.tabs-positive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-positive .tab-item.activated,.tabs-striped.tabs-positive .tab-item.active,.tabs-striped.tabs-positive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-calm .tabs{background-color:#11c1f3}.tabs-striped.tabs-calm .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-calm .tab-item.activated,.tabs-striped.tabs-calm .tab-item.active,.tabs-striped.tabs-calm .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-assertive .tabs{background-color:#ef473a}.tabs-striped.tabs-assertive .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-assertive .tab-item.activated,.tabs-striped.tabs-assertive .tab-item.active,.tabs-striped.tabs-assertive .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-balanced .tabs{background-color:#33cd5f}.tabs-striped.tabs-balanced .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-balanced .tab-item.activated,.tabs-striped.tabs-balanced .tab-item.active,.tabs-striped.tabs-balanced .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-energized .tabs{background-color:#ffc900}.tabs-striped.tabs-energized .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-energized .tab-item.activated,.tabs-striped.tabs-energized .tab-item.active,.tabs-striped.tabs-energized .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-royal .tabs{background-color:#886aea}.tabs-striped.tabs-royal .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-royal .tab-item.activated,.tabs-striped.tabs-royal .tab-item.active,.tabs-striped.tabs-royal .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-dark .tabs{background-color:#444}.tabs-striped.tabs-dark .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-dark .tab-item.activated,.tabs-striped.tabs-dark .tab-item.active,.tabs-striped.tabs-dark .tab-item.tab-item-active{margin-top:-2px;color:#fff;border-style:solid;border-width:2px 0 0 0;border-color:#fff}.tabs-striped.tabs-top .tab-item.activated .badge,.tabs-striped.tabs-top .tab-item.active .badge,.tabs-striped.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-striped.tabs-background-light .tabs{background-color:#fff;background-image:none}.tabs-striped.tabs-background-stable .tabs{background-color:#f8f8f8;background-image:none}.tabs-striped.tabs-background-positive .tabs{background-color:#387ef5;background-image:none}.tabs-striped.tabs-background-calm .tabs{background-color:#11c1f3;background-image:none}.tabs-striped.tabs-background-assertive .tabs{background-color:#ef473a;background-image:none}.tabs-striped.tabs-background-balanced .tabs{background-color:#33cd5f;background-image:none}.tabs-striped.tabs-background-energized .tabs{background-color:#ffc900;background-image:none}.tabs-striped.tabs-background-royal .tabs{background-color:#886aea;background-image:none}.tabs-striped.tabs-background-dark .tabs{background-color:#444;background-image:none}.tabs-striped.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-striped.tabs-color-light .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-light .tab-item.activated,.tabs-striped.tabs-color-light .tab-item.active,.tabs-striped.tabs-color-light .tab-item.tab-item-active{margin-top:-2px;color:#fff;border:0 solid #fff;border-top-width:2px}.tabs-striped.tabs-color-light .tab-item.activated .badge,.tabs-striped.tabs-color-light .tab-item.active .badge,.tabs-striped.tabs-color-light .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-striped.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-stable .tab-item.activated,.tabs-striped.tabs-color-stable .tab-item.active,.tabs-striped.tabs-color-stable .tab-item.tab-item-active{margin-top:-2px;color:#f8f8f8;border:0 solid #f8f8f8;border-top-width:2px}.tabs-striped.tabs-color-stable .tab-item.activated .badge,.tabs-striped.tabs-color-stable .tab-item.active .badge,.tabs-striped.tabs-color-stable .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-striped.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-positive .tab-item.activated,.tabs-striped.tabs-color-positive .tab-item.active,.tabs-striped.tabs-color-positive .tab-item.tab-item-active{margin-top:-2px;color:#387ef5;border:0 solid #387ef5;border-top-width:2px}.tabs-striped.tabs-color-positive .tab-item.activated .badge,.tabs-striped.tabs-color-positive .tab-item.active .badge,.tabs-striped.tabs-color-positive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-striped.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-calm .tab-item.activated,.tabs-striped.tabs-color-calm .tab-item.active,.tabs-striped.tabs-color-calm .tab-item.tab-item-active{margin-top:-2px;color:#11c1f3;border:0 solid #11c1f3;border-top-width:2px}.tabs-striped.tabs-color-calm .tab-item.activated .badge,.tabs-striped.tabs-color-calm .tab-item.active .badge,.tabs-striped.tabs-color-calm .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-striped.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-assertive .tab-item.activated,.tabs-striped.tabs-color-assertive .tab-item.active,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active{margin-top:-2px;color:#ef473a;border:0 solid #ef473a;border-top-width:2px}.tabs-striped.tabs-color-assertive .tab-item.activated .badge,.tabs-striped.tabs-color-assertive .tab-item.active .badge,.tabs-striped.tabs-color-assertive .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-striped.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-balanced .tab-item.activated,.tabs-striped.tabs-color-balanced .tab-item.active,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active{margin-top:-2px;color:#33cd5f;border:0 solid #33cd5f;border-top-width:2px}.tabs-striped.tabs-color-balanced .tab-item.activated .badge,.tabs-striped.tabs-color-balanced .tab-item.active .badge,.tabs-striped.tabs-color-balanced .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-striped.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-energized .tab-item.activated,.tabs-striped.tabs-color-energized .tab-item.active,.tabs-striped.tabs-color-energized .tab-item.tab-item-active{margin-top:-2px;color:#ffc900;border:0 solid #ffc900;border-top-width:2px}.tabs-striped.tabs-color-energized .tab-item.activated .badge,.tabs-striped.tabs-color-energized .tab-item.active .badge,.tabs-striped.tabs-color-energized .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-striped.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-royal .tab-item.activated,.tabs-striped.tabs-color-royal .tab-item.active,.tabs-striped.tabs-color-royal .tab-item.tab-item-active{margin-top:-2px;color:#886aea;border:0 solid #886aea;border-top-width:2px}.tabs-striped.tabs-color-royal .tab-item.activated .badge,.tabs-striped.tabs-color-royal .tab-item.active .badge,.tabs-striped.tabs-color-royal .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-striped.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-striped.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-striped.tabs-color-dark .tab-item.activated,.tabs-striped.tabs-color-dark .tab-item.active,.tabs-striped.tabs-color-dark .tab-item.tab-item-active{margin-top:-2px;color:#444;border:0 solid #444;border-top-width:2px}.tabs-striped.tabs-color-dark .tab-item.activated .badge,.tabs-striped.tabs-color-dark .tab-item.active .badge,.tabs-striped.tabs-color-dark .tab-item.tab-item-active .badge{top:2px;opacity:1}.tabs-background-light .tabs,.tabs-background-light>.tabs{background-color:#fff;background-image:linear-gradient(0deg,#ddd,#ddd 50%,transparent 50%);border-color:#ddd}.tabs-background-stable .tabs,.tabs-background-stable>.tabs{background-color:#f8f8f8;background-image:linear-gradient(0deg,#b2b2b2,#b2b2b2 50%,transparent 50%);border-color:#b2b2b2}.tabs-background-positive .tabs,.tabs-background-positive>.tabs{background-color:#387ef5;background-image:linear-gradient(0deg,#0c60ee,#0c60ee 50%,transparent 50%);border-color:#0c60ee}.tabs-background-calm .tabs,.tabs-background-calm>.tabs{background-color:#11c1f3;background-image:linear-gradient(0deg,#0a9dc7,#0a9dc7 50%,transparent 50%);border-color:#0a9dc7}.tabs-background-assertive .tabs,.tabs-background-assertive>.tabs{background-color:#ef473a;background-image:linear-gradient(0deg,#e42112,#e42112 50%,transparent 50%);border-color:#e42112}.tabs-background-balanced .tabs,.tabs-background-balanced>.tabs{background-color:#33cd5f;background-image:linear-gradient(0deg,#28a54c,#28a54c 50%,transparent 50%);border-color:#28a54c}.tabs-background-energized .tabs,.tabs-background-energized>.tabs{background-color:#ffc900;background-image:linear-gradient(0deg,#e6b500,#e6b500 50%,transparent 50%);border-color:#e6b500}.tabs-background-royal .tabs,.tabs-background-royal>.tabs{background-color:#886aea;background-image:linear-gradient(0deg,#6b46e5,#6b46e5 50%,transparent 50%);border-color:#6b46e5}.tabs-background-dark .tabs,.tabs-background-dark>.tabs{background-color:#444;background-image:linear-gradient(0deg,#111,#111 50%,transparent 50%);border-color:#111}.tabs-color-light .tab-item{color:rgba(255,255,255,.4);opacity:1}.tabs-color-light .tab-item .badge{opacity:.4}.tabs-color-light .tab-item.activated,.tabs-color-light .tab-item.active,.tabs-color-light .tab-item.tab-item-active{color:#fff;border:0 solid #fff}.tabs-color-light .tab-item.activated .badge,.tabs-color-light .tab-item.active .badge,.tabs-color-light .tab-item.tab-item-active .badge{opacity:1}.tabs-color-stable .tab-item{color:rgba(248,248,248,.4);opacity:1}.tabs-color-stable .tab-item .badge{opacity:.4}.tabs-color-stable .tab-item.activated,.tabs-color-stable .tab-item.active,.tabs-color-stable .tab-item.tab-item-active{color:#f8f8f8;border:0 solid #f8f8f8}.tabs-color-stable .tab-item.activated .badge,.tabs-color-stable .tab-item.active .badge,.tabs-color-stable .tab-item.tab-item-active .badge{opacity:1}.tabs-color-positive .tab-item{color:rgba(56,126,245,.4);opacity:1}.tabs-color-positive .tab-item .badge{opacity:.4}.tabs-color-positive .tab-item.activated,.tabs-color-positive .tab-item.active,.tabs-color-positive .tab-item.tab-item-active{color:#387ef5;border:0 solid #387ef5}.tabs-color-positive .tab-item.activated .badge,.tabs-color-positive .tab-item.active .badge,.tabs-color-positive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-calm .tab-item{color:rgba(17,193,243,.4);opacity:1}.tabs-color-calm .tab-item .badge{opacity:.4}.tabs-color-calm .tab-item.activated,.tabs-color-calm .tab-item.active,.tabs-color-calm .tab-item.tab-item-active{color:#11c1f3;border:0 solid #11c1f3}.tabs-color-calm .tab-item.activated .badge,.tabs-color-calm .tab-item.active .badge,.tabs-color-calm .tab-item.tab-item-active .badge{opacity:1}.tabs-color-assertive .tab-item{color:rgba(239,71,58,.4);opacity:1}.tabs-color-assertive .tab-item .badge{opacity:.4}.tabs-color-assertive .tab-item.activated,.tabs-color-assertive .tab-item.active,.tabs-color-assertive .tab-item.tab-item-active{color:#ef473a;border:0 solid #ef473a}.tabs-color-assertive .tab-item.activated .badge,.tabs-color-assertive .tab-item.active .badge,.tabs-color-assertive .tab-item.tab-item-active .badge{opacity:1}.tabs-color-balanced .tab-item{color:rgba(51,205,95,.4);opacity:1}.tabs-color-balanced .tab-item .badge{opacity:.4}.tabs-color-balanced .tab-item.activated,.tabs-color-balanced .tab-item.active,.tabs-color-balanced .tab-item.tab-item-active{color:#33cd5f;border:0 solid #33cd5f}.tabs-color-balanced .tab-item.activated .badge,.tabs-color-balanced .tab-item.active .badge,.tabs-color-balanced .tab-item.tab-item-active .badge{opacity:1}.tabs-color-energized .tab-item{color:rgba(255,201,0,.4);opacity:1}.tabs-color-energized .tab-item .badge{opacity:.4}.tabs-color-energized .tab-item.activated,.tabs-color-energized .tab-item.active,.tabs-color-energized .tab-item.tab-item-active{color:#ffc900;border:0 solid #ffc900}.tabs-color-energized .tab-item.activated .badge,.tabs-color-energized .tab-item.active .badge,.tabs-color-energized .tab-item.tab-item-active .badge{opacity:1}.tabs-color-royal .tab-item{color:rgba(136,106,234,.4);opacity:1}.tabs-color-royal .tab-item .badge{opacity:.4}.tabs-color-royal .tab-item.activated,.tabs-color-royal .tab-item.active,.tabs-color-royal .tab-item.tab-item-active{color:#886aea;border:0 solid #886aea}.tabs-color-royal .tab-item.activated .badge,.tabs-color-royal .tab-item.active .badge,.tabs-color-royal .tab-item.tab-item-active .badge{opacity:1}.tabs-color-dark .tab-item{color:rgba(68,68,68,.4);opacity:1}.tabs-color-dark .tab-item .badge{opacity:.4}.tabs-color-dark .tab-item.activated,.tabs-color-dark .tab-item.active,.tabs-color-dark .tab-item.tab-item-active{color:#444;border:0 solid #444}.tabs-color-dark .tab-item.activated .badge,.tabs-color-dark .tab-item.active .badge,.tabs-color-dark .tab-item.tab-item-active .badge{opacity:1}ion-tabs.tabs-color-active-light .tab-item{color:#444}ion-tabs.tabs-color-active-light .tab-item.activated,ion-tabs.tabs-color-active-light .tab-item.active,ion-tabs.tabs-color-active-light .tab-item.tab-item-active{color:#fff}ion-tabs.tabs-color-active-stable .tab-item{color:#444}ion-tabs.tabs-color-active-stable .tab-item.activated,ion-tabs.tabs-color-active-stable .tab-item.active,ion-tabs.tabs-color-active-stable .tab-item.tab-item-active{color:#f8f8f8}ion-tabs.tabs-color-active-positive .tab-item{color:#444}ion-tabs.tabs-color-active-positive .tab-item.activated,ion-tabs.tabs-color-active-positive .tab-item.active,ion-tabs.tabs-color-active-positive .tab-item.tab-item-active{color:#387ef5}ion-tabs.tabs-color-active-calm .tab-item{color:#444}ion-tabs.tabs-color-active-calm .tab-item.activated,ion-tabs.tabs-color-active-calm .tab-item.active,ion-tabs.tabs-color-active-calm .tab-item.tab-item-active{color:#11c1f3}ion-tabs.tabs-color-active-assertive .tab-item{color:#444}ion-tabs.tabs-color-active-assertive .tab-item.activated,ion-tabs.tabs-color-active-assertive .tab-item.active,ion-tabs.tabs-color-active-assertive .tab-item.tab-item-active{color:#ef473a}ion-tabs.tabs-color-active-balanced .tab-item{color:#444}ion-tabs.tabs-color-active-balanced .tab-item.activated,ion-tabs.tabs-color-active-balanced .tab-item.active,ion-tabs.tabs-color-active-balanced .tab-item.tab-item-active{color:#33cd5f}ion-tabs.tabs-color-active-energized .tab-item{color:#444}ion-tabs.tabs-color-active-energized .tab-item.activated,ion-tabs.tabs-color-active-energized .tab-item.active,ion-tabs.tabs-color-active-energized .tab-item.tab-item-active{color:#ffc900}ion-tabs.tabs-color-active-royal .tab-item{color:#444}ion-tabs.tabs-color-active-royal .tab-item.activated,ion-tabs.tabs-color-active-royal .tab-item.active,ion-tabs.tabs-color-active-royal .tab-item.tab-item-active{color:#886aea}ion-tabs.tabs-color-active-dark .tab-item{color:#fff}ion-tabs.tabs-color-active-dark .tab-item.activated,ion-tabs.tabs-color-active-dark .tab-item.active,ion-tabs.tabs-color-active-dark .tab-item.tab-item-active{color:#444}.tabs-top.tabs-striped{padding-bottom:0}.tabs-top.tabs-striped .tab-item{background:0 0;-webkit-transition:color .1s ease;-moz-transition:color .1s ease;-ms-transition:color .1s ease;-o-transition:color .1s ease;transition:color .1s ease}.tabs-top.tabs-striped .tab-item.activated,.tabs-top.tabs-striped .tab-item.active,.tabs-top.tabs-striped .tab-item.tab-item-active{margin-top:1px;border-width:0 0 2px 0!important;border-style:solid}.tabs-top.tabs-striped .tab-item.activated>.badge,.tabs-top.tabs-striped .tab-item.activated>i,.tabs-top.tabs-striped .tab-item.active>.badge,.tabs-top.tabs-striped .tab-item.active>i,.tabs-top.tabs-striped .tab-item.tab-item-active>.badge,.tabs-top.tabs-striped .tab-item.tab-item-active>i{margin-top:-1px}.tabs-top.tabs-striped .tab-item .badge{-webkit-transition:color .2s ease;-moz-transition:color .2s ease;-ms-transition:color .2s ease;-o-transition:color .2s ease;transition:color .2s ease}.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.activated i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.active i,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped:not(.tabs-icon-left):not(.tabs-icon-top) .tab-item.tab-item-active i{display:block;margin-top:-1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item{margin-top:1px}.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.activated i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.active i,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active .tab-title,.tabs-top.tabs-striped.tabs-icon-left .tab-item.tab-item-active i{margin-top:-.1em}.tabs-top>.tabs,.tabs.tabs-top{top:44px;padding-top:0;background-position:bottom;border-top-width:0;border-bottom-width:1px}.tabs-top>.tabs .tab-item.activated .badge,.tabs-top>.tabs .tab-item.active .badge,.tabs-top>.tabs .tab-item.tab-item-active .badge,.tabs.tabs-top .tab-item.activated .badge,.tabs.tabs-top .tab-item.active .badge,.tabs.tabs-top .tab-item.tab-item-active .badge{top:4%}.tabs-top~.bar-header{border-bottom-width:0}.tab-item{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;max-width:150px;height:100%;color:inherit;text-align:center;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;font-weight:400;font-size:14px;font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif;opacity:.7}.tab-item:hover{cursor:pointer}.tab-item.tab-hidden,.tabs-item-hide>.tabs,.tabs.tabs-item-hide{display:none}.tabs-icon-bottom.tabs .tab-item,.tabs-icon-bottom>.tabs .tab-item,.tabs-icon-top.tabs .tab-item,.tabs-icon-top>.tabs .tab-item{font-size:10px;line-height:14px}.tab-item .icon{display:block;margin:0 auto;height:32px;font-size:32px}.tabs-icon-left.tabs .tab-item,.tabs-icon-left>.tabs .tab-item,.tabs-icon-right.tabs .tab-item,.tabs-icon-right>.tabs .tab-item{font-size:10px}.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left.tabs .tab-item .tab-title,.tabs-icon-left>.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .tab-title,.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right.tabs .tab-item .tab-title,.tabs-icon-right>.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .tab-title{display:inline-block;vertical-align:top;margin-top:-.1em}.tabs-icon-left.tabs .tab-item .icon:before,.tabs-icon-left.tabs .tab-item .tab-title:before,.tabs-icon-left>.tabs .tab-item .icon:before,.tabs-icon-left>.tabs .tab-item .tab-title:before,.tabs-icon-right.tabs .tab-item .icon:before,.tabs-icon-right.tabs .tab-item .tab-title:before,.tabs-icon-right>.tabs .tab-item .icon:before,.tabs-icon-right>.tabs .tab-item .tab-title:before{font-size:24px;line-height:49px}.tabs-icon-left.tabs .tab-item .icon,.tabs-icon-left>.tabs .tab-item .icon{padding-right:3px}.tabs-icon-right.tabs .tab-item .icon,.tabs-icon-right>.tabs .tab-item .icon{padding-left:3px}.tabs-icon-only.tabs .icon,.tabs-icon-only>.tabs .icon{line-height:inherit}.tab-item.has-badge{position:relative}.tab-item .badge{position:absolute;top:4%;right:33%;right:calc(50% - 26px);padding:1px 6px;height:auto;font-size:12px;line-height:16px}.tab-item.activated,.tab-item.active,.tab-item.tab-item-active{opacity:1}.tab-item.activated.tab-item-light,.tab-item.active.tab-item-light,.tab-item.tab-item-active.tab-item-light{color:#fff}.tab-item.activated.tab-item-stable,.tab-item.active.tab-item-stable,.tab-item.tab-item-active.tab-item-stable{color:#f8f8f8}.tab-item.activated.tab-item-positive,.tab-item.active.tab-item-positive,.tab-item.tab-item-active.tab-item-positive{color:#387ef5}.tab-item.activated.tab-item-calm,.tab-item.active.tab-item-calm,.tab-item.tab-item-active.tab-item-calm{color:#11c1f3}.tab-item.activated.tab-item-assertive,.tab-item.active.tab-item-assertive,.tab-item.tab-item-active.tab-item-assertive{color:#ef473a}.tab-item.activated.tab-item-balanced,.tab-item.active.tab-item-balanced,.tab-item.tab-item-active.tab-item-balanced{color:#33cd5f}.tab-item.activated.tab-item-energized,.tab-item.active.tab-item-energized,.tab-item.tab-item-active.tab-item-energized{color:#ffc900}.tab-item.activated.tab-item-royal,.tab-item.active.tab-item-royal,.tab-item.tab-item-active.tab-item-royal{color:#886aea}.tab-item.activated.tab-item-dark,.tab-item.active.tab-item-dark,.tab-item.tab-item-active.tab-item-dark{color:#444}.item.tabs{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:0}.item.tabs .icon:before{position:relative}.tab-item.disabled,.tab-item[disabled]{opacity:.4;cursor:default;pointer-events:none}.nav-bar-tabs-top.hide~.view-container .tabs-top .tabs{top:0}.pane[hide-nav-bar=true] .has-tabs-top{top:49px}.menu{position:absolute;top:0;bottom:0;z-index:0;overflow:hidden;min-height:100%;max-height:100%;width:275px;background-color:#fff}.menu .scroll-content{z-index:10}.menu .bar-header{z-index:11}.menu-content{-webkit-transform:none;transform:none;box-shadow:-1px 0 2px rgba(0,0,0,.2),1px 0 2px rgba(0,0,0,.2)}.menu-open .menu-content .pane,.menu-open .menu-content .scroll-content,.menu-open .menu-content .scroll-content .scroll{pointer-events:none}.menu-open .menu-content .scroll-content:not(.overflow-scroll){overflow:hidden}.grade-b .menu-content,.grade-c .menu-content{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;right:-1px;left:-1px;border-right:1px solid #ccc;border-left:1px solid #ccc;box-shadow:none}.menu-left{left:0}.menu-right{right:0}.aside-open.aside-resizing .menu-right{display:none}.menu-animated{-webkit-transition:-webkit-transform 200ms ease;transition:transform 200ms ease}.modal-backdrop,.modal-backdrop-bg{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%}.modal-backdrop-bg{pointer-events:none}.modal{display:block;position:absolute;top:0;z-index:10;overflow:hidden;min-height:100%;width:100%;background-color:#fff}@media (min-width:680px){.modal{top:20%;right:20%;bottom:20%;left:20%;min-height:240px;width:60%}.modal.ng-leave-active{bottom:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .modal-wrapper .modal .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .modal-wrapper .modal .bar-subheader,.platform-ios.platform-cordova .modal-wrapper .modal .has-header,.platform-ios.platform-cordova .modal-wrapper .modal .tabs-top>.tabs,.platform-ios.platform-cordova .modal-wrapper .modal .tabs.tabs-top{top:44px}.platform-ios.platform-cordova .modal-wrapper .modal .has-subheader{top:88px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-tabs-top{top:93px}.platform-ios.platform-cordova .modal-wrapper .modal .has-header.has-subheader.has-tabs-top{top:137px}.modal-backdrop-bg{-webkit-transition:opacity 300ms ease-in-out;transition:opacity 300ms ease-in-out;background-color:#000;opacity:0}.active .modal-backdrop-bg{opacity:.5}}.modal-open{pointer-events:none}.modal-open .modal,.modal-open .modal-backdrop{pointer-events:auto}.modal-open.loading-active .modal,.modal-open.loading-active .modal-backdrop{pointer-events:none}.popover-backdrop{position:fixed;top:0;left:0;z-index:10;width:100%;height:100%;background-color:transparent}.popover-backdrop.active{background-color:rgba(0,0,0,.1)}.popover{position:absolute;top:25%;left:50%;z-index:10;display:block;margin-top:12px;margin-left:-110px;height:280px;width:220px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.4);opacity:0}.popover .item:first-child{border-top:0}.popover .item:last-child{border-bottom:0}.popover.popover-bottom{margin-top:-12px}.popover,.popover .bar-header{border-radius:2px}.popover .scroll-content{z-index:1;margin:2px 0}.popover .bar-header{border-bottom-right-radius:0;border-bottom-left-radius:0}.popover .has-header{border-top-right-radius:0;border-top-left-radius:0}.popover-arrow{display:none}.platform-ios .popover{box-shadow:0 0 40px rgba(0,0,0,.08);border-radius:10px}.platform-ios .popover .bar-header{-webkit-border-top-right-radius:10px;border-top-right-radius:10px;-webkit-border-top-left-radius:10px;border-top-left-radius:10px}.platform-ios .popover .scroll-content{margin:8px 0;border-radius:10px}.platform-ios .popover .scroll-content.has-header{margin-top:0}.platform-ios .popover-arrow{position:absolute;display:block;top:-17px;width:30px;height:19px;overflow:hidden}.platform-ios .popover-arrow:after{position:absolute;top:12px;left:5px;width:20px;height:20px;background-color:#fff;border-radius:3px;content:'';-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.platform-ios .popover-bottom .popover-arrow{top:auto;bottom:-10px}.platform-ios .popover-bottom .popover-arrow:after{top:-6px}.platform-android .popover{margin-top:-32px;background-color:#fafafa;box-shadow:0 2px 6px rgba(0,0,0,.35)}.platform-android .popover .item{border-color:#fafafa;background-color:#fafafa;color:#4d4d4d}.platform-android .popover.popover-bottom{margin-top:32px}.platform-android .popover-backdrop,.platform-android .popover-backdrop.active{background-color:transparent}.popover-open{pointer-events:none}.popover-open .popover,.popover-open .popover-backdrop{pointer-events:auto}.popover-open.loading-active .popover,.popover-open.loading-active .popover-backdrop{pointer-events:none}@media (min-width:680px){.popover{width:360px;margin-left:-180px}}.popup-container{position:absolute;top:0;left:0;bottom:0;right:0;background:0 0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;z-index:12;visibility:hidden}.popup-container.popup-showing{visibility:visible}.popup-container.popup-hidden .popup{-webkit-animation-name:scaleOut;animation-name:scaleOut;-webkit-animation-duration:.1s;animation-duration:.1s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container.active .popup{-webkit-animation-name:superScaleIn;animation-name:superScaleIn;-webkit-animation-duration:.2s;animation-duration:.2s;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}.popup-container .popup{width:250px;max-width:100%;max-height:90%;border-radius:0;background-color:rgba(255,255,255,.9);display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.popup-container input,.popup-container textarea{width:100%}.popup-head{padding:15px 10px;border-bottom:1px solid #eee;text-align:center}.popup-title{margin:0;padding:0;font-size:15px}.popup-sub-title{margin:5px 0 0 0;padding:0;font-weight:400;font-size:11px}.popup-body{padding:10px;overflow:auto}.popup-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-webkit-box-orient:horizontal;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding:10px;min-height:65px}.popup-buttons .button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;min-height:45px;border-radius:2px;line-height:20px;margin-right:5px}.popup-buttons .button:last-child{margin-right:0}.popup-open,.popup-open.modal-open .modal{pointer-events:none}.popup-open .popup,.popup-open .popup-backdrop{pointer-events:auto}.loading-container{position:absolute;left:0;top:0;right:0;bottom:0;z-index:13;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-transition:.2s opacity linear;transition:.2s opacity linear;visibility:hidden;opacity:0}.loading-container:not(.visible) .icon,.loading-container:not(.visible) .spinner{display:none}.loading-container.visible{visibility:visible}.loading-container.active{opacity:1}.loading-container .loading{padding:20px;border-radius:5px;background-color:rgba(0,0,0,.7);color:#fff;text-align:center;text-overflow:ellipsis;font-size:15px}.loading-container .loading h1,.loading-container .loading h2,.loading-container .loading h3,.loading-container .loading h4,.loading-container .loading h5,.loading-container .loading h6{color:#fff}.item{border-color:#ddd;background-color:#fff;color:#444;position:relative;z-index:2;display:block;margin:-1px;padding:16px;border-width:1px;border-style:solid;font-size:16px}.item h2{margin:0 0 2px 0;font-size:16px;font-weight:400}.item h3{margin:0 0 4px 0;font-size:14px}.item h4{margin:0 0 4px 0;font-size:12px}.item h5,.item h6{margin:0 0 3px 0;font-size:10px}.item p{color:#666;font-size:14px;margin-bottom:2px}.item h1:last-child,.item h2:last-child,.item h3:last-child,.item h4:last-child,.item h5:last-child,.item h6:last-child,.item p:last-child{margin-bottom:0}.item .badge{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;position:absolute;top:16px;right:32px}.item.item-button-right .badge{right:67px}.item.item-divider .badge{top:8px}.item .badge+.badge{margin-right:5px}.item.item-light{border-color:#ddd;background-color:#fff;color:#444}.item.item-stable{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item.item-positive{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item.item-calm{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item.item-assertive{border-color:#e42112;background-color:#ef473a;color:#fff}.item.item-balanced{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item.item-energized{border-color:#e6b500;background-color:#ffc900;color:#fff}.item.item-royal{border-color:#6b46e5;background-color:#886aea;color:#fff}.item.item-dark{border-color:#111;background-color:#444;color:#fff}.item[ng-click]:hover{cursor:pointer}.item-borderless,.list-borderless .item{border-width:0}.item .item-content.activated,.item .item-content.activated.item-complex>.item-content,.item .item-content.active,.item .item-content.active.item-complex>.item-content,.item-complex.activated .item-content,.item-complex.activated .item-content.item-complex>.item-content,.item-complex.active .item-content,.item-complex.active .item-content.item-complex>.item-content,.item.activated,.item.activated.item-complex>.item-content,.item.active,.item.active.item-complex>.item-content{border-color:#ccc;background-color:#D9D9D9}.item .item-content.activated.item-light,.item .item-content.activated.item-light.item-complex>.item-content,.item .item-content.active.item-light,.item .item-content.active.item-light.item-complex>.item-content,.item-complex.activated .item-content.item-light,.item-complex.activated .item-content.item-light.item-complex>.item-content,.item-complex.active .item-content.item-light,.item-complex.active .item-content.item-light.item-complex>.item-content,.item.activated.item-light,.item.activated.item-light.item-complex>.item-content,.item.active.item-light,.item.active.item-light.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item .item-content.activated.item-stable,.item .item-content.activated.item-stable.item-complex>.item-content,.item .item-content.active.item-stable,.item .item-content.active.item-stable.item-complex>.item-content,.item-complex.activated .item-content.item-stable,.item-complex.activated .item-content.item-stable.item-complex>.item-content,.item-complex.active .item-content.item-stable,.item-complex.active .item-content.item-stable.item-complex>.item-content,.item.activated.item-stable,.item.activated.item-stable.item-complex>.item-content,.item.active.item-stable,.item.active.item-stable.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item .item-content.activated.item-positive,.item .item-content.activated.item-positive.item-complex>.item-content,.item .item-content.active.item-positive,.item .item-content.active.item-positive.item-complex>.item-content,.item-complex.activated .item-content.item-positive,.item-complex.activated .item-content.item-positive.item-complex>.item-content,.item-complex.active .item-content.item-positive,.item-complex.active .item-content.item-positive.item-complex>.item-content,.item.activated.item-positive,.item.activated.item-positive.item-complex>.item-content,.item.active.item-positive,.item.active.item-positive.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item .item-content.activated.item-calm,.item .item-content.activated.item-calm.item-complex>.item-content,.item .item-content.active.item-calm,.item .item-content.active.item-calm.item-complex>.item-content,.item-complex.activated .item-content.item-calm,.item-complex.activated .item-content.item-calm.item-complex>.item-content,.item-complex.active .item-content.item-calm,.item-complex.active .item-content.item-calm.item-complex>.item-content,.item.activated.item-calm,.item.activated.item-calm.item-complex>.item-content,.item.active.item-calm,.item.active.item-calm.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item .item-content.activated.item-assertive,.item .item-content.activated.item-assertive.item-complex>.item-content,.item .item-content.active.item-assertive,.item .item-content.active.item-assertive.item-complex>.item-content,.item-complex.activated .item-content.item-assertive,.item-complex.activated .item-content.item-assertive.item-complex>.item-content,.item-complex.active .item-content.item-assertive,.item-complex.active .item-content.item-assertive.item-complex>.item-content,.item.activated.item-assertive,.item.activated.item-assertive.item-complex>.item-content,.item.active.item-assertive,.item.active.item-assertive.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item .item-content.activated.item-balanced,.item .item-content.activated.item-balanced.item-complex>.item-content,.item .item-content.active.item-balanced,.item .item-content.active.item-balanced.item-complex>.item-content,.item-complex.activated .item-content.item-balanced,.item-complex.activated .item-content.item-balanced.item-complex>.item-content,.item-complex.active .item-content.item-balanced,.item-complex.active .item-content.item-balanced.item-complex>.item-content,.item.activated.item-balanced,.item.activated.item-balanced.item-complex>.item-content,.item.active.item-balanced,.item.active.item-balanced.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item .item-content.activated.item-energized,.item .item-content.activated.item-energized.item-complex>.item-content,.item .item-content.active.item-energized,.item .item-content.active.item-energized.item-complex>.item-content,.item-complex.activated .item-content.item-energized,.item-complex.activated .item-content.item-energized.item-complex>.item-content,.item-complex.active .item-content.item-energized,.item-complex.active .item-content.item-energized.item-complex>.item-content,.item.activated.item-energized,.item.activated.item-energized.item-complex>.item-content,.item.active.item-energized,.item.active.item-energized.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item .item-content.activated.item-royal,.item .item-content.activated.item-royal.item-complex>.item-content,.item .item-content.active.item-royal,.item .item-content.active.item-royal.item-complex>.item-content,.item-complex.activated .item-content.item-royal,.item-complex.activated .item-content.item-royal.item-complex>.item-content,.item-complex.active .item-content.item-royal,.item-complex.active .item-content.item-royal.item-complex>.item-content,.item.activated.item-royal,.item.activated.item-royal.item-complex>.item-content,.item.active.item-royal,.item.active.item-royal.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item .item-content.activated.item-dark,.item .item-content.activated.item-dark.item-complex>.item-content,.item .item-content.active.item-dark,.item .item-content.active.item-dark.item-complex>.item-content,.item-complex.activated .item-content.item-dark,.item-complex.activated .item-content.item-dark.item-complex>.item-content,.item-complex.active .item-content.item-dark,.item-complex.active .item-content.item-dark.item-complex>.item-content,.item.activated.item-dark,.item.activated.item-dark.item-complex>.item-content,.item.active.item-dark,.item.active.item-dark.item-complex>.item-content{border-color:#000;background-color:#262626}.item,.item h1,.item h2,.item h3,.item h4,.item h5,.item h6,.item p,.item-content,.item-content h1,.item-content h2,.item-content h3,.item-content h4,.item-content h5,.item-content h6,.item-content p{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}a.item{color:inherit;text-decoration:none}a.item:focus,a.item:hover{text-decoration:none}.item-complex,a.item.item-complex,button.item.item-complex{padding:0}.item-complex .item-content,.item-radio .item-content{position:relative;z-index:2;padding:16px 49px 16px 16px;border:none;background-color:#fff}a.item-content{display:block;color:inherit;text-decoration:none}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p,.item-complex.item-text-wrap,.item-complex.item-text-wrap .item-content,.item-complex.item-text-wrap h1,.item-complex.item-text-wrap h2,.item-complex.item-text-wrap h3,.item-complex.item-text-wrap h4,.item-complex.item-text-wrap h5,.item-complex.item-text-wrap h6,.item-complex.item-text-wrap p,.item-text-wrap,.item-text-wrap .item,.item-text-wrap .item-content,.item-text-wrap h1,.item-text-wrap h2,.item-text-wrap h3,.item-text-wrap h4,.item-text-wrap h5,.item-text-wrap h6,.item-text-wrap p{overflow:visible;white-space:normal}.item-complex.item-light>.item-content{border-color:#ddd;background-color:#fff;color:#444}.item-complex.item-light>.item-content.active,.item-complex.item-light>.item-content.active.item-complex>.item-content,.item-complex.item-light>.item-content:active,.item-complex.item-light>.item-content:active.item-complex>.item-content{border-color:#ccc;background-color:#fafafa}.item-complex.item-stable>.item-content{border-color:#b2b2b2;background-color:#f8f8f8;color:#444}.item-complex.item-stable>.item-content.active,.item-complex.item-stable>.item-content.active.item-complex>.item-content,.item-complex.item-stable>.item-content:active,.item-complex.item-stable>.item-content:active.item-complex>.item-content{border-color:#a2a2a2;background-color:#e5e5e5}.item-complex.item-positive>.item-content{border-color:#0c60ee;background-color:#387ef5;color:#fff}.item-complex.item-positive>.item-content.active,.item-complex.item-positive>.item-content.active.item-complex>.item-content,.item-complex.item-positive>.item-content:active,.item-complex.item-positive>.item-content:active.item-complex>.item-content{border-color:#0c60ee;background-color:#0c60ee}.item-complex.item-calm>.item-content{border-color:#0a9dc7;background-color:#11c1f3;color:#fff}.item-complex.item-calm>.item-content.active,.item-complex.item-calm>.item-content.active.item-complex>.item-content,.item-complex.item-calm>.item-content:active,.item-complex.item-calm>.item-content:active.item-complex>.item-content{border-color:#0a9dc7;background-color:#0a9dc7}.item-complex.item-assertive>.item-content{border-color:#e42112;background-color:#ef473a;color:#fff}.item-complex.item-assertive>.item-content.active,.item-complex.item-assertive>.item-content.active.item-complex>.item-content,.item-complex.item-assertive>.item-content:active,.item-complex.item-assertive>.item-content:active.item-complex>.item-content{border-color:#e42112;background-color:#e42112}.item-complex.item-balanced>.item-content{border-color:#28a54c;background-color:#33cd5f;color:#fff}.item-complex.item-balanced>.item-content.active,.item-complex.item-balanced>.item-content.active.item-complex>.item-content,.item-complex.item-balanced>.item-content:active,.item-complex.item-balanced>.item-content:active.item-complex>.item-content{border-color:#28a54c;background-color:#28a54c}.item-complex.item-energized>.item-content{border-color:#e6b500;background-color:#ffc900;color:#fff}.item-complex.item-energized>.item-content.active,.item-complex.item-energized>.item-content.active.item-complex>.item-content,.item-complex.item-energized>.item-content:active,.item-complex.item-energized>.item-content:active.item-complex>.item-content{border-color:#e6b500;background-color:#e6b500}.item-complex.item-royal>.item-content{border-color:#6b46e5;background-color:#886aea;color:#fff}.item-complex.item-royal>.item-content.active,.item-complex.item-royal>.item-content.active.item-complex>.item-content,.item-complex.item-royal>.item-content:active,.item-complex.item-royal>.item-content:active.item-complex>.item-content{border-color:#6b46e5;background-color:#6b46e5}.item-complex.item-dark>.item-content{border-color:#111;background-color:#444;color:#fff}.item-complex.item-dark>.item-content.active,.item-complex.item-dark>.item-content.active.item-complex>.item-content,.item-complex.item-dark>.item-content:active,.item-complex.item-dark>.item-content:active.item-complex>.item-content{border-color:#000;background-color:#262626}.item-icon-left .icon,.item-icon-right .icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-icon-left .icon:before,.item-icon-right .icon:before{display:block;width:32px;text-align:center}.item .fill-icon{min-width:30px;min-height:30px;font-size:28px}.item-icon-left{padding-left:54px}.item-icon-left .icon{left:11px}.item-complex.item-icon-left{padding-left:0}.item-complex.item-icon-left .item-content{padding-left:54px}.item-icon-right{padding-right:54px}.item-icon-right .icon{right:11px}.item-complex.item-icon-right{padding-right:0}.item-complex.item-icon-right .item-content{padding-right:54px}.item-icon-left.item-icon-right .icon:first-child{right:auto}.item-icon-left .item-delete .icon,.item-icon-left.item-icon-right .icon:last-child{left:auto}.item-icon-left .icon-accessory,.item-icon-right .icon-accessory{color:#ccc;font-size:16px}.item-icon-left .icon-accessory{left:3px}.item-icon-right .icon-accessory{right:3px}.item-button-left{padding-left:72px}.item-button-left .item-content>.button,.item-button-left>.button{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;left:11px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-left .item-content>.button .icon:before,.item-button-left>.button .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-left .item-content>.button>.button,.item-button-left>.button>.button{margin:0 2px;min-height:34px;font-size:18px;line-height:32px}.item-button-right,a.item.item-button-right,button.item.item-button-right{padding-right:80px}.item-button-right .item-content>.button,.item-button-right .item-content>.buttons,.item-button-right>.button,.item-button-right>.buttons{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:8px;right:16px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-button-right .item-content>.button .icon:before,.item-button-right .item-content>.buttons .icon:before,.item-button-right>.button .icon:before,.item-button-right>.buttons .icon:before{position:relative;left:auto;width:auto;line-height:31px}.item-button-right .item-content>.button>.button,.item-button-right .item-content>.buttons>.button,.item-button-right>.button>.button,.item-button-right>.buttons>.button{margin:0 2px;min-width:34px;min-height:34px;font-size:18px;line-height:32px}.item-avatar,.item-avatar .item-content,.item-avatar-left,.item-avatar-left .item-content{padding-left:72px;min-height:72px}.item-avatar .item-content .item-image,.item-avatar .item-content>img:first-child,.item-avatar .item-image,.item-avatar-left .item-content .item-image,.item-avatar-left .item-content>img:first-child,.item-avatar-left .item-image,.item-avatar-left>img:first-child,.item-avatar>img:first-child{position:absolute;top:16px;left:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-avatar-right,.item-avatar-right .item-content{padding-right:72px;min-height:72px}.item-avatar-right .item-content .item-image,.item-avatar-right .item-content>img:first-child,.item-avatar-right .item-image,.item-avatar-right>img:first-child{position:absolute;top:16px;right:16px;max-width:40px;max-height:40px;width:100%;height:100%;border-radius:50%}.item-thumbnail-left,.item-thumbnail-left .item-content{padding-top:8px;padding-left:106px;min-height:100px}.item-thumbnail-left .item-content .item-image,.item-thumbnail-left .item-content>img:first-child,.item-thumbnail-left .item-image,.item-thumbnail-left>img:first-child{position:absolute;top:10px;left:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-left.item-complex,.item-avatar.item-complex,.item-thumbnail-left.item-complex{padding-top:0;padding-left:0}.item-thumbnail-right,.item-thumbnail-right .item-content{padding-top:8px;padding-right:106px;min-height:100px}.item-thumbnail-right .item-content .item-image,.item-thumbnail-right .item-content>img:first-child,.item-thumbnail-right .item-image,.item-thumbnail-right>img:first-child{position:absolute;top:10px;right:10px;max-width:80px;max-height:80px;width:100%;height:100%}.item-avatar-right.item-complex,.item-thumbnail-right.item-complex{padding-top:0;padding-right:0}.item-image{padding:0;text-align:center}.item-image .list-img,.item-image img:first-child{width:100%;vertical-align:middle}.item-body{overflow:auto;padding:16px;text-overflow:inherit;white-space:normal}.item-body h1,.item-body h2,.item-body h3,.item-body h4,.item-body h5,.item-body h6,.item-body p{margin-top:16px;margin-bottom:16px}.item-divider{padding-top:8px;padding-bottom:8px;min-height:30px;background-color:#f5f5f5;color:#222;font-weight:500}.item-divider-ios,.platform-ios .item-divider-platform{padding-top:26px;text-transform:uppercase;font-weight:300;font-size:13px;background-color:#efeff4;color:#555}.item-divider-android,.platform-android .item-divider-platform{font-weight:300;font-size:13px}.item-note{float:right;color:#aaa;font-size:14px}.item-left-editable .item-content,.item-right-editable .item-content{-webkit-transition-duration:250ms;transition-duration:250ms;-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;transition-property:transform}.item-left-editing.item-left-editable .item-content,.list-left-editing .item-left-editable .item-content{-webkit-transform:translate3d(50px,0,0);transform:translate3d(50px,0,0)}.item-remove-animate.ng-leave{-webkit-transition-duration:300ms;transition-duration:300ms}.item-remove-animate.ng-leave .item-content,.item-remove-animate.ng-leave:last-of-type{-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;-webkit-transition-property:all;transition-property:all}.item-remove-animate.ng-leave.ng-leave-active .item-content{opacity:0;-webkit-transform:translate3d(-100%,0,0)!important;transform:translate3d(-100%,0,0)!important}.item-remove-animate.ng-leave.ng-leave-active:last-of-type{opacity:0}.item-remove-animate.ng-leave.ng-leave-active~ion-item:not(.ng-leave){-webkit-transform:translate3d(0,-webkit-calc(-100% + 1px),0);transform:translate3d(0,calc(-100% + 1px),0);-webkit-transition-duration:300ms;transition-duration:300ms;-webkit-transition-timing-function:cubic-bezier(.25,.81,.24,1);transition-timing-function:cubic-bezier(.25,.81,.24,1);-webkit-transition-property:all;transition-property:all}.item-left-edit{-webkit-transition:all ease-in-out 125ms;transition:all ease-in-out 125ms;position:absolute;top:0;left:0;z-index:0;width:50px;height:100%;line-height:100%;display:none;opacity:0;-webkit-transform:translate3d(-21px,0,0);transform:translate3d(-21px,0,0)}.item-left-edit .button{height:100%}.item-left-edit .button.icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%}.item-left-edit.visible{display:block}.item-left-edit.visible.active{opacity:1;-webkit-transform:translate3d(8px,0,0);transform:translate3d(8px,0,0)}.list-left-editing .item-left-edit{-webkit-transition-delay:125ms;transition-delay:125ms}.item-delete .button.icon{color:#ef473a;font-size:24px}.item-delete .button.icon:hover{opacity:.7}.item-right-edit{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms;position:absolute;top:0;right:0;z-index:3;width:75px;height:100%;background:inherit;padding-left:20px;display:block;opacity:0;-webkit-transform:translate3d(75px,0,0);transform:translate3d(75px,0,0)}.item-right-edit .button{min-width:50px;height:100%}.item-right-edit .button.icon{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:absolute;top:0;height:100%;font-size:32px}.item-right-edit.visible{display:block}.item-right-edit.visible.active{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.item-reorder .button.icon{color:#444;font-size:32px}.item-reordering{position:absolute;left:0;top:0;z-index:9;width:100%;box-shadow:0 0 10px 0 #aaa}.item-reordering .item-reorder{z-index:9}.item-placeholder{opacity:.7}.item-options{position:absolute;top:0;right:0;z-index:1;height:100%}.item-options .button{height:100%;border:none;border-radius:0;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.item-options .button:before{margin:0 auto}.list{position:relative;padding-top:1px;padding-bottom:1px;padding-left:0;margin-bottom:20px}.list:last-child{margin-bottom:0}.list:last-child.card{margin-bottom:40px}.list-header{margin-top:20px;padding:5px 15px;background-color:transparent;color:#222;font-weight:700}.card.list .list-item{padding-right:1px;padding-left:1px}.card,.list-inset{overflow:hidden;margin:20px 10px;border-radius:2px;background-color:#fff}.card{padding-top:1px;padding-bottom:1px;box-shadow:0 1px 3px rgba(0,0,0,.3)}.card .item{border-left:0;border-right:0}.card .item:first-child{border-top:0}.card .item:last-child{border-bottom:0}.padding .card,.padding .list-inset{margin-left:0;margin-right:0}.card .item:first-child,.card .item:first-child .item-content,.list-inset .item:first-child,.list-inset .item:first-child .item-content,.padding>.list .item:first-child,.padding>.list .item:first-child .item-content{border-top-left-radius:2px;border-top-right-radius:2px}.card .item:last-child,.card .item:last-child .item-content,.list-inset .item:last-child,.list-inset .item:last-child .item-content,.padding>.list .item:last-child,.padding>.list .item:last-child .item-content{border-bottom-right-radius:2px;border-bottom-left-radius:2px}.card .item:last-child,.list-inset .item:last-child{margin-bottom:-1px}.card .item,.list-inset .item,.padding-horizontal>.list .item,.padding>.list .item{margin-right:0;margin-left:0}.card .item.item-input input,.list-inset .item.item-input input,.padding-horizontal>.list .item.item-input input,.padding>.list .item.item-input input{padding-right:44px}.padding-left>.list .item{margin-left:0}.padding-right>.list .item{margin-right:0}.badge{background-color:transparent;color:#AAA;z-index:1;display:inline-block;padding:3px 8px;min-width:10px;border-radius:10px;vertical-align:baseline;text-align:center;white-space:nowrap;font-weight:700;font-size:14px;line-height:16px}.badge:empty{display:none}.badge.badge-light,.tabs .tab-item .badge.badge-light{background-color:#fff;color:#444}.badge.badge-stable,.tabs .tab-item .badge.badge-stable{background-color:#f8f8f8;color:#444}.badge.badge-positive,.tabs .tab-item .badge.badge-positive{background-color:#387ef5;color:#fff}.badge.badge-calm,.tabs .tab-item .badge.badge-calm{background-color:#11c1f3;color:#fff}.badge.badge-assertive,.tabs .tab-item .badge.badge-assertive{background-color:#ef473a;color:#fff}.badge.badge-balanced,.tabs .tab-item .badge.badge-balanced{background-color:#33cd5f;color:#fff}.badge.badge-energized,.tabs .tab-item .badge.badge-energized{background-color:#ffc900;color:#fff}.badge.badge-royal,.tabs .tab-item .badge.badge-royal{background-color:#886aea;color:#fff}.badge.badge-dark,.tabs .tab-item .badge.badge-dark{background-color:#444;color:#fff}.button .badge{position:relative;top:-1px}.slider{position:relative;visibility:hidden;overflow:hidden}.slider-slides{position:relative;height:100%}.slider-slide{position:relative;display:block;float:left;width:100%;height:100%;vertical-align:top}.slider-slide-image>img{width:100%}.slider-pager{position:absolute;bottom:20px;z-index:1;width:100%;height:15px;text-align:center}.slider-pager .slider-pager-page{display:inline-block;margin:0 3px;width:15px;color:#000;text-decoration:none;opacity:.3}.slider-pager .slider-pager-page.active{-webkit-transition:opacity .4s ease-in;transition:opacity .4s ease-in;opacity:1}.slider-pager-page.ng-animate,.slider-pager-page.ng-enter,.slider-pager-page.ng-leave,.slider-slide.ng-animate,.slider-slide.ng-enter,.slider-slide.ng-leave{-webkit-transition:none!important;transition:none!important}.slider-pager-page.ng-animate,.slider-slide.ng-animate{-webkit-animation:none 0s;animation:none 0s}.swiper-container{margin:0 auto;position:relative;z-index:1}.swiper-container-no-flexbox .swiper-slide{float:left}.swiper-container-vertical>.swiper-wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.swiper-wrapper{z-index:1;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate(0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.swiper-container-multirow>.swiper-wrapper{-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{display:block;-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;position:relative}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform,height}.swiper-container .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-wp8-horizontal{-ms-touch-action:pan-y;touch-action:pan-y}.swiper-wp8-vertical{-ms-touch-action:pan-x;touch-action:pan-x}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:27px;height:44px;margin-top:-22px;z-index:10;cursor:pointer;-moz-background-size:27px 44px;-webkit-background-size:27px 44px;background-size:27px 44px;background-position:center;background-repeat:no-repeat}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-prev,.swiper-container-rtl .swiper-button-next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");left:10px;right:auto}.swiper-button-prev.swiper-button-black,.swiper-container-rtl .swiper-button-next.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-prev.swiper-button-white,.swiper-container-rtl .swiper-button-next.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next,.swiper-container-rtl .swiper-button-prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");right:10px;left:auto}.swiper-button-next.swiper-button-black,.swiper-container-rtl .swiper-button-prev.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next.swiper-button-white,.swiper-container-rtl .swiper-button-prev.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-pagination{position:absolute;text-align:center;-webkit-transition:300ms;-moz-transition:300ms;-o-transition:300ms;transition:300ms;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2}button.swiper-pagination-bullet{border:none;margin:0;padding:0;box-shadow:none;-moz-appearance:none;-ms-appearance:none;-webkit-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-white .swiper-pagination-bullet{background:#fff}.swiper-pagination-bullet-active{opacity:1}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);-moz-transform:translate3d(0,-50%,0);-o-transform:translate(0,-50%);-ms-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination{bottom:10px;left:0;width:100%}.swiper-container-horizontal>.swiper-pagination .swiper-pagination-bullet{margin:0 5px}.swiper-container-3d{-webkit-perspective:1200px;-moz-perspective:1200px;-o-perspective:1200px;perspective:1200px}.swiper-container-3d .swiper-cube-shadow,.swiper-container-3d .swiper-slide,.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top,.swiper-container-3d .swiper-wrapper{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d}.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-container-3d .swiper-slide-shadow-left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(right,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to left,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-right{background-image:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(left,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to right,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-top{background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(bottom,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to top,rgba(0,0,0,.5),transparent)}.swiper-container-3d .swiper-slide-shadow-bottom{background-image:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.5)),to(transparent));background-image:-webkit-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:-moz-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:-o-linear-gradient(top,rgba(0,0,0,.5),transparent);background-image:linear-gradient(to bottom,rgba(0,0,0,.5),transparent)}.swiper-container-coverflow .swiper-wrapper{-ms-perspective:1200px}.swiper-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide,.swiper-container-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide-active,.swiper-container-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube{overflow:visible}.swiper-container-cube .swiper-slide{pointer-events:none;visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;width:100%;height:100%;z-index:1}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-next,.swiper-container-cube .swiper-slide-next+.swiper-slide,.swiper-container-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-container-cube .swiper-slide-shadow-bottom,.swiper-container-cube .swiper-slide-shadow-left,.swiper-container-cube .swiper-slide-shadow-right,.swiper-container-cube .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0;width:100%;height:100%;background:#000;opacity:.6;-webkit-filter:blur(50px);filter:blur(50px);z-index:0}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-container-horizontal>.swiper-scrollbar{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-container-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;-webkit-transform-origin:50%;-moz-transform-origin:50%;transform-origin:50%;-webkit-animation:swiper-preloader-spin 1s steps(12,end) infinite;-moz-animation:swiper-preloader-spin 1s steps(12,end) infinite;animation:swiper-preloader-spin 1s steps(12,end) infinite}.swiper-lazy-preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");background-position:50%;-webkit-background-size:100%;background-size:100%;background-repeat:no-repeat}.swiper-lazy-preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}@-webkit-keyframes swiper-preloader-spin{100%{-webkit-transform:rotate(360deg)}}@keyframes swiper-preloader-spin{100%{transform:rotate(360deg)}}ion-slides{width:100%;height:100%;display:block}.slide-zoom{display:block;width:100%;text-align:center}.swiper-container{width:100%;height:100%;padding:0;overflow:hidden}.swiper-wrapper{position:absolute;left:0;top:0;width:100%;height:100%;padding:0}.swiper-slide{width:100%;height:100%;box-sizing:border-box}.swiper-slide img{width:auto;height:auto;max-width:100%;max-height:100%}.scroll-refresher{position:absolute;top:-60px;right:0;left:0;overflow:hidden;margin:auto;height:60px}.scroll-refresher .ionic-refresher-content{position:absolute;bottom:15px;left:0;width:100%;color:#666;text-align:center;font-size:30px}.scroll-refresher .ionic-refresher-content .text-pulling,.scroll-refresher .ionic-refresher-content .text-refreshing{font-size:16px;line-height:16px}.scroll-refresher .ionic-refresher-content.ionic-refresher-with-text{bottom:10px}.scroll-refresher .icon-pulling,.scroll-refresher .icon-refreshing{width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.scroll-refresher .icon-pulling{-webkit-animation-name:refresh-spin-back;animation-name:refresh-spin-back;-webkit-animation-duration:200ms;animation-duration:200ms;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:none;animation-fill-mode:none;-webkit-transform:translate3d(0,0,0) rotate(0deg);transform:translate3d(0,0,0) rotate(0deg)}.scroll-refresher .icon-refreshing,.scroll-refresher .text-refreshing{display:none}.scroll-refresher .icon-refreshing{-webkit-animation-duration:1.5s;animation-duration:1.5s}.scroll-refresher.active .icon-pulling:not(.pulling-rotation-disabled){-webkit-animation-name:refresh-spin;animation-name:refresh-spin;-webkit-transform:translate3d(0,0,0) rotate(-180deg);transform:translate3d(0,0,0) rotate(-180deg)}.scroll-refresher.active.refreshing{-webkit-transition:transform .2s;transition:transform .2s;-webkit-transform:scale(1,1);transform:scale(1,1)}.scroll-refresher.active.refreshing .icon-pulling,.scroll-refresher.active.refreshing .text-pulling{display:none}.scroll-refresher.active.refreshing .icon-refreshing,.scroll-refresher.active.refreshing .text-refreshing{display:block}.scroll-refresher.active.refreshing.refreshing-tail{-webkit-transform:scale(0,0);transform:scale(0,0)}.overflow-scroll>.scroll{-webkit-overflow-scrolling:touch;width:100%}.overflow-scroll>.scroll.overscroll{position:fixed;right:0;left:0}.overflow-scroll.padding>.scroll.overscroll{padding:10px}@-webkit-keyframes refresh-spin{0%{-webkit-transform:translate3d(0,0,0) rotate(0)}100%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}}@keyframes refresh-spin{0%{transform:translate3d(0,0,0) rotate(0)}100%{transform:translate3d(0,0,0) rotate(180deg)}}@-webkit-keyframes refresh-spin-back{0%{-webkit-transform:translate3d(0,0,0) rotate(180deg)}100%{-webkit-transform:translate3d(0,0,0) rotate(0)}}@keyframes refresh-spin-back{0%{transform:translate3d(0,0,0) rotate(180deg)}100%{transform:translate3d(0,0,0) rotate(0)}}.spinner{stroke:#444;fill:#444}.spinner svg{width:28px;height:28px}.spinner.spinner-light{stroke:#fff;fill:#fff}.spinner.spinner-stable{stroke:#f8f8f8;fill:#f8f8f8}.spinner.spinner-positive{stroke:#387ef5;fill:#387ef5}.spinner.spinner-calm{stroke:#11c1f3;fill:#11c1f3}.spinner.spinner-balanced{stroke:#33cd5f;fill:#33cd5f}.spinner.spinner-assertive{stroke:#ef473a;fill:#ef473a}.spinner.spinner-energized{stroke:#ffc900;fill:#ffc900}.spinner.spinner-royal{stroke:#886aea;fill:#886aea}.spinner.spinner-dark{stroke:#444;fill:#444}.spinner-android{stroke:#4b8bf4}.spinner-ios,.spinner-ios-small{stroke:#69717d}.spinner-spiral .stop1{stop-color:#fff;stop-opacity:0}.spinner-spiral.spinner-light .stop1{stop-color:#444}.spinner-spiral.spinner-light .stop2{stop-color:#fff}.spinner-spiral.spinner-stable .stop2{stop-color:#f8f8f8}.spinner-spiral.spinner-positive .stop2{stop-color:#387ef5}.spinner-spiral.spinner-calm .stop2{stop-color:#11c1f3}.spinner-spiral.spinner-balanced .stop2{stop-color:#33cd5f}.spinner-spiral.spinner-assertive .stop2{stop-color:#ef473a}.spinner-spiral.spinner-energized .stop2{stop-color:#ffc900}.spinner-spiral.spinner-royal .stop2{stop-color:#886aea}.spinner-spiral.spinner-dark .stop2{stop-color:#444}form{margin:0 0 1.42857}legend{display:block;margin-bottom:1.42857;padding:0;width:100%;border:1px solid #ddd;color:#444;font-size:21px;line-height:2.85714}legend small{color:#f8f8f8;font-size:1.07143}button,input,label,select,textarea{font-weight:400;font-size:14px;line-height:1.42857}button,input,select,textarea{font-family:"-apple-system","Helvetica Neue",Roboto,"Segoe UI",sans-serif}.item-input{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:6px 0 5px 16px}.item-input input{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 220px;-moz-box-flex:1;-moz-flex:1 220px;-ms-flex:1 220px;flex:1 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:0;padding-right:24px;background-color:transparent}.item-input .button .icon{-webkit-box-flex:0;-webkit-flex:0 0 24px;-moz-box-flex:0;-moz-flex:0 0 24px;-ms-flex:0 0 24px;flex:0 0 24px;position:static;display:inline-block;height:auto;text-align:center;font-size:16px}.item-input .button-bar{-webkit-border-radius:0;border-radius:0;-webkit-box-flex:1;-webkit-flex:1 0 220px;-moz-box-flex:1;-moz-flex:1 0 220px;-ms-flex:1 0 220px;flex:1 0 220px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.item-input .icon{min-width:14px}.platform-windowsphone .item-input input{flex-shrink:1}.item-input-inset{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;position:relative;overflow:hidden;padding:10.67px}.item-input-wrapper{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1 0;-moz-box-flex:1;-moz-flex:1 0;-ms-flex:1 0;flex:1 0;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;-webkit-border-radius:4px;border-radius:4px;padding-right:8px;padding-left:8px;background:#eee}.item-input-inset .item-input-wrapper input{padding-left:4px;height:29px;background:0 0;line-height:18px}.item-input-wrapper~.button{margin-left:10.67px}.input-label{display:table;padding:7px 10px 7px 0;max-width:200px;width:35%;color:#444;font-size:16px}.placeholder-icon{color:#aaa}.placeholder-icon:first-child{padding-right:6px}.placeholder-icon:last-child{padding-left:6px}.item-stacked-label{display:block;background-color:transparent;box-shadow:none}.item-stacked-label .icon,.item-stacked-label .input-label{display:inline-block;padding:4px 0 0 0;vertical-align:middle}.item-stacked-label input,.item-stacked-label textarea{-webkit-border-radius:2px;border-radius:2px;padding:4px 8px 3px 0;border:none;background-color:#fff}.item-stacked-label input{overflow:hidden;height:46px}.item-select.item-stacked-label select{position:relative;padding:0;max-width:90%;direction:ltr;white-space:pre-wrap;margin:-3px}.item-floating-label{display:block;background-color:transparent;box-shadow:none}.item-floating-label .input-label{position:relative;padding:5px 0 0 0;opacity:0;top:10px;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}.item-floating-label .input-label.has-input{opacity:1;top:0;-webkit-transition:opacity .15s ease-in,top .2s linear;transition:opacity .15s ease-in,top .2s linear}input[type=search],input[type=text],input[type=password],input[type=datetime],input[type=datetime-local],input[type=date],input[type=month],input[type=time],input[type=week],input[type=number],input[type=email],input[type=url],input[type=tel],input[type=color],textarea{display:block;padding-top:2px;padding-left:0;height:34px;color:#111;vertical-align:middle;font-size:14px;line-height:16px}.platform-android input[type=datetime-local],.platform-android input[type=date],.platform-android input[type=month],.platform-android input[type=time],.platform-android input[type=week],.platform-ios input[type=datetime-local],.platform-ios input[type=date],.platform-ios input[type=month],.platform-ios input[type=time],.platform-ios input[type=week]{padding-top:8px}.item-input input,.item-input textarea{width:100%}textarea{padding-left:0}textarea::-moz-placeholder{color:#aaa}textarea:-ms-input-placeholder{color:#aaa}textarea::-webkit-input-placeholder{color:#aaa;text-indent:-3px}textarea{height:auto}input[type=search],input[type=text],input[type=password],input[type=datetime],input[type=datetime-local],input[type=date],input[type=month],input[type=time],input[type=week],input[type=number],input[type=email],input[type=url],input[type=tel],input[type=color],textarea{border:0}input[type=radio],input[type=checkbox]{margin:0;line-height:normal}.item-input input[type=button],.item-input input[type=reset],.item-input input[type=submit],.item-input input[type=radio],.item-input input[type=checkbox],.item-input input[type=file],.item-input input[type=image]{width:auto}input[type=file]{line-height:34px}.cloned-text-input+input,.cloned-text-input+textarea,.previous-input-focus{position:absolute!important;left:-9999px;width:200px}input::-moz-placeholder,textarea::-moz-placeholder{color:#aaa}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#aaa}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#aaa;text-indent:0}input[disabled],input[readonly]:not(.cloned-text-input),select[disabled],select[readonly],textarea[disabled],textarea[readonly]:not(.cloned-text-input){background-color:#f8f8f8;cursor:not-allowed}input[type=radio][disabled],input[type=radio][readonly],input[type=checkbox][disabled],input[type=checkbox][readonly]{background-color:transparent}.checkbox{position:relative;display:inline-block;padding:7px 7px;cursor:pointer}.checkbox .checkbox-icon:before,.checkbox input:before{border-color:#ddd}.checkbox input:checked+.checkbox-icon:before,.checkbox input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-light .checkbox-icon:before,.checkbox-light input:before{border-color:#ddd}.checkbox-light input:checked+.checkbox-icon:before,.checkbox-light input:checked:before{background:#ddd;border-color:#ddd}.checkbox-stable .checkbox-icon:before,.checkbox-stable input:before{border-color:#b2b2b2}.checkbox-stable input:checked+.checkbox-icon:before,.checkbox-stable input:checked:before{background:#b2b2b2;border-color:#b2b2b2}.checkbox-positive .checkbox-icon:before,.checkbox-positive input:before{border-color:#387ef5}.checkbox-positive input:checked+.checkbox-icon:before,.checkbox-positive input:checked:before{background:#387ef5;border-color:#387ef5}.checkbox-calm .checkbox-icon:before,.checkbox-calm input:before{border-color:#11c1f3}.checkbox-calm input:checked+.checkbox-icon:before,.checkbox-calm input:checked:before{background:#11c1f3;border-color:#11c1f3}.checkbox-assertive .checkbox-icon:before,.checkbox-assertive input:before{border-color:#ef473a}.checkbox-assertive input:checked+.checkbox-icon:before,.checkbox-assertive input:checked:before{background:#ef473a;border-color:#ef473a}.checkbox-balanced .checkbox-icon:before,.checkbox-balanced input:before{border-color:#33cd5f}.checkbox-balanced input:checked+.checkbox-icon:before,.checkbox-balanced input:checked:before{background:#33cd5f;border-color:#33cd5f}.checkbox-energized .checkbox-icon:before,.checkbox-energized input:before{border-color:#ffc900}.checkbox-energized input:checked+.checkbox-icon:before,.checkbox-energized input:checked:before{background:#ffc900;border-color:#ffc900}.checkbox-royal .checkbox-icon:before,.checkbox-royal input:before{border-color:#886aea}.checkbox-royal input:checked+.checkbox-icon:before,.checkbox-royal input:checked:before{background:#886aea;border-color:#886aea}.checkbox-dark .checkbox-icon:before,.checkbox-dark input:before{border-color:#444}.checkbox-dark input:checked+.checkbox-icon:before,.checkbox-dark input:checked:before{background:#444;border-color:#444}.checkbox input:disabled+.checkbox-icon:before,.checkbox input:disabled:before{border-color:#ddd}.checkbox input:disabled:checked+.checkbox-icon:before,.checkbox input:disabled:checked:before{background:#ddd}.checkbox.checkbox-input-hidden input{display:none!important}.checkbox input,.checkbox-icon{position:relative;width:28px;height:28px;display:block;border:0;background:0 0;cursor:pointer;-webkit-appearance:none}.checkbox input:before,.checkbox-icon:before{display:table;width:100%;height:100%;border-width:1px;border-style:solid;border-radius:28px;background:#fff;content:' ';-webkit-transition:background-color 20ms ease-in-out;transition:background-color 20ms ease-in-out}.checkbox input:checked:before,input:checked+.checkbox-icon:before{border-width:2px}.checkbox input:after,.checkbox-icon:after{-webkit-transition:opacity .05s ease-in-out;transition:opacity .05s ease-in-out;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);position:absolute;top:33%;left:25%;display:table;width:14px;height:6px;border:1px solid #fff;border-top:0;border-right:0;content:' ';opacity:0}.checkbox-square .checkbox-icon:before,.checkbox-square input:before,.platform-android .checkbox-platform .checkbox-icon:before,.platform-android .checkbox-platform input:before{border-radius:2px;width:72%;height:72%;margin-top:14%;margin-left:14%;border-width:2px}.checkbox-square .checkbox-icon:after,.checkbox-square input:after,.platform-android .checkbox-platform .checkbox-icon:after,.platform-android .checkbox-platform input:after{border-width:2px;top:19%;left:25%;width:13px;height:7px}.platform-android .item-checkbox-right .checkbox-square .checkbox-icon::after{top:31%}.grade-c .checkbox input:after,.grade-c .checkbox-icon:after{-webkit-transform:rotate(0);transform:rotate(0);top:3px;left:4px;border:none;color:#fff;content:'\2713';font-weight:700;font-size:20px}.checkbox input:checked:after,input:checked+.checkbox-icon:after{opacity:1}.item-checkbox{padding-left:60px}.item-checkbox.active{box-shadow:none}.item-checkbox .checkbox{position:absolute;top:50%;right:8px;left:8px;z-index:3;margin-top:-21px}.item-checkbox.item-checkbox-right{padding-right:60px;padding-left:16px}.item-checkbox-right .checkbox input,.item-checkbox-right .checkbox-icon{float:right}.item-toggle{pointer-events:none}.toggle{position:relative;display:inline-block;pointer-events:auto;margin:-5px;padding:5px}.toggle input:checked+.track{border-color:#4cd964;background-color:#4cd964}.toggle.dragging .handle{background-color:#f2f2f2!important}.toggle.toggle-light input:checked+.track{border-color:#ddd;background-color:#ddd}.toggle.toggle-stable input:checked+.track{border-color:#b2b2b2;background-color:#b2b2b2}.toggle.toggle-positive input:checked+.track{border-color:#387ef5;background-color:#387ef5}.toggle.toggle-calm input:checked+.track{border-color:#11c1f3;background-color:#11c1f3}.toggle.toggle-assertive input:checked+.track{border-color:#ef473a;background-color:#ef473a}.toggle.toggle-balanced input:checked+.track{border-color:#33cd5f;background-color:#33cd5f}.toggle.toggle-energized input:checked+.track{border-color:#ffc900;background-color:#ffc900}.toggle.toggle-royal input:checked+.track{border-color:#886aea;background-color:#886aea}.toggle.toggle-dark input:checked+.track{border-color:#444;background-color:#444}.toggle input{display:none}.toggle .track{-webkit-transition-timing-function:ease-in-out;transition-timing-function:ease-in-out;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:background-color,border;transition-property:background-color,border;display:inline-block;box-sizing:border-box;width:51px;height:31px;border:solid 2px #e6e6e6;border-radius:20px;background-color:#fff;content:' ';cursor:pointer;pointer-events:none}.platform-android4_2 .toggle .track{-webkit-background-clip:padding-box}.toggle .handle{-webkit-transition:.3s cubic-bezier(0,1.1,1,1.1);transition:.3s cubic-bezier(0,1.1,1,1.1);-webkit-transition-property:background-color,transform;transition-property:background-color,transform;position:absolute;display:block;width:27px;height:27px;border-radius:27px;background-color:#fff;top:7px;left:7px;box-shadow:0 2px 7px rgba(0,0,0,.35),0 1px 1px rgba(0,0,0,.15)}.toggle .handle:before{position:absolute;top:-4px;left:-21.5px;padding:18.5px 34px;content:" "}.toggle input:checked+.track .handle{-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0);background-color:#fff}.item-toggle.active{box-shadow:none}.item-toggle,.item-toggle.item-complex .item-content{padding-right:99px}.item-toggle.item-complex{padding-right:0}.item-toggle .toggle{position:absolute;top:10px;right:16px;z-index:3}.toggle input:disabled+.track{opacity:.6}.toggle-small .track{border:0;width:34px;height:15px;background:#9e9e9e}.toggle-small input:checked+.track{background:rgba(0,150,137,.5)}.toggle-small .handle{top:2px;left:4px;width:21px;height:21px;box-shadow:0 2px 5px rgba(0,0,0,.25)}.toggle-small input:checked+.track .handle{-webkit-transform:translate3d(16px,0,0);transform:translate3d(16px,0,0);background:#009689}.toggle-small.item-toggle .toggle{top:19px}.toggle-small .toggle-light input:checked+.track{background-color:rgba(221,221,221,.5)}.toggle-small .toggle-light input:checked+.track .handle{background-color:#ddd}.toggle-small .toggle-stable input:checked+.track{background-color:rgba(178,178,178,.5)}.toggle-small .toggle-stable input:checked+.track .handle{background-color:#b2b2b2}.toggle-small .toggle-positive input:checked+.track{background-color:rgba(56,126,245,.5)}.toggle-small .toggle-positive input:checked+.track .handle{background-color:#387ef5}.toggle-small .toggle-calm input:checked+.track{background-color:rgba(17,193,243,.5)}.toggle-small .toggle-calm input:checked+.track .handle{background-color:#11c1f3}.toggle-small .toggle-assertive input:checked+.track{background-color:rgba(239,71,58,.5)}.toggle-small .toggle-assertive input:checked+.track .handle{background-color:#ef473a}.toggle-small .toggle-balanced input:checked+.track{background-color:rgba(51,205,95,.5)}.toggle-small .toggle-balanced input:checked+.track .handle{background-color:#33cd5f}.toggle-small .toggle-energized input:checked+.track{background-color:rgba(255,201,0,.5)}.toggle-small .toggle-energized input:checked+.track .handle{background-color:#ffc900}.toggle-small .toggle-royal input:checked+.track{background-color:rgba(136,106,234,.5)}.toggle-small .toggle-royal input:checked+.track .handle{background-color:#886aea}.toggle-small .toggle-dark input:checked+.track{background-color:rgba(68,68,68,.5)}.toggle-small .toggle-dark input:checked+.track .handle{background-color:#444}.item-radio{padding:0}.item-radio:hover{cursor:pointer}.item-radio .item-content{padding-right:64px}.item-radio .radio-icon{position:absolute;top:0;right:0;z-index:3;visibility:hidden;padding:14px;height:100%;font-size:24px}.item-radio input{position:absolute;left:-9999px}.item-radio input:checked+.radio-content .item-content{background:#f7f7f7}.item-radio input:checked+.radio-content .radio-icon{visibility:visible}.range input{overflow:hidden;margin-top:5px;margin-bottom:5px;padding-right:2px;padding-left:1px;width:auto;height:43px;outline:0;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(0,#ccc),color-stop(100%,#ccc));background:linear-gradient(to right,#ccc 0,#ccc 100%);background-position:center;background-size:99% 2px;background-repeat:no-repeat;-webkit-appearance:none}.range input::-moz-focus-outer{border:0}.range input::-webkit-slider-thumb{position:relative;width:28px;height:28px;border-radius:50%;background-color:#fff;box-shadow:0 0 2px rgba(0,0,0,.3),0 3px 5px rgba(0,0,0,.2);cursor:pointer;-webkit-appearance:none;border:0}.range input::-webkit-slider-thumb:before{position:absolute;top:13px;left:-2001px;width:2000px;height:2px;background:#444;content:' '}.range input::-webkit-slider-thumb:after{position:absolute;top:-15px;left:-15px;padding:30px;content:' '}.range input::-ms-fill-lower{height:2px;background:#444}.range{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center;padding:2px 11px}.range.range-light input::-webkit-slider-thumb:before{background:#ddd}.range.range-light input::-ms-fill-lower{background:#ddd}.range.range-stable input::-webkit-slider-thumb:before{background:#b2b2b2}.range.range-stable input::-ms-fill-lower{background:#b2b2b2}.range.range-positive input::-webkit-slider-thumb:before{background:#387ef5}.range.range-positive input::-ms-fill-lower{background:#387ef5}.range.range-calm input::-webkit-slider-thumb:before{background:#11c1f3}.range.range-calm input::-ms-fill-lower{background:#11c1f3}.range.range-balanced input::-webkit-slider-thumb:before{background:#33cd5f}.range.range-balanced input::-ms-fill-lower{background:#33cd5f}.range.range-assertive input::-webkit-slider-thumb:before{background:#ef473a}.range.range-assertive input::-ms-fill-lower{background:#ef473a}.range.range-energized input::-webkit-slider-thumb:before{background:#ffc900}.range.range-energized input::-ms-fill-lower{background:#ffc900}.range.range-royal input::-webkit-slider-thumb:before{background:#886aea}.range.range-royal input::-ms-fill-lower{background:#886aea}.range.range-dark input::-webkit-slider-thumb:before{background:#444}.range.range-dark input::-ms-fill-lower{background:#444}.range .icon{-webkit-box-flex:0;-webkit-flex:0;-moz-box-flex:0;-moz-flex:0;-ms-flex:0;flex:0;display:block;min-width:24px;text-align:center;font-size:24px}.range input{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;margin-right:10px;margin-left:10px}.range-label{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-box-flex:0;-moz-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;display:block;white-space:nowrap}.range-label:first-child{padding-left:5px}.range input+.range-label{padding-right:5px;padding-left:0}.platform-windowsphone .range input{height:auto}.item-select{position:relative}.item-select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;position:absolute;top:0;bottom:0;right:0;padding:0 48px 0 16px;max-width:65%;border:none;background:#fff;color:#333;text-indent:.01px;text-overflow:'';white-space:nowrap;font-size:14px;cursor:pointer;direction:rtl}.item-select select::-ms-expand{display:none}.item-select option{direction:ltr}.item-select:after{position:absolute;top:50%;right:16px;margin-top:-3px;width:0;height:0;border-top:5px solid;border-right:5px solid transparent;border-left:5px solid transparent;color:#999;content:"";pointer-events:none}.item-select.item-light select{background:#fff;color:#444}.item-select.item-stable select{background:#f8f8f8;color:#444}.item-select.item-stable .input-label,.item-select.item-stable:after{color:#666}.item-select.item-positive select{background:#387ef5;color:#fff}.item-select.item-positive .input-label,.item-select.item-positive:after{color:#fff}.item-select.item-calm select{background:#11c1f3;color:#fff}.item-select.item-calm .input-label,.item-select.item-calm:after{color:#fff}.item-select.item-assertive select{background:#ef473a;color:#fff}.item-select.item-assertive .input-label,.item-select.item-assertive:after{color:#fff}.item-select.item-balanced select{background:#33cd5f;color:#fff}.item-select.item-balanced .input-label,.item-select.item-balanced:after{color:#fff}.item-select.item-energized select{background:#ffc900;color:#fff}.item-select.item-energized .input-label,.item-select.item-energized:after{color:#fff}.item-select.item-royal select{background:#886aea;color:#fff}.item-select.item-royal .input-label,.item-select.item-royal:after{color:#fff}.item-select.item-dark select{background:#444;color:#fff}.item-select.item-dark .input-label,.item-select.item-dark:after{color:#fff}select[multiple],select[size]{height:auto}progress{display:block;margin:15px auto;width:100%}.button{border-color:transparent;background-color:#f8f8f8;color:#444;position:relative;display:inline-block;margin:0;padding:0 12px;min-width:52px;min-height:47px;border-width:1px;border-style:solid;border-radius:4px;vertical-align:top;text-align:center;text-overflow:ellipsis;font-size:16px;line-height:42px;cursor:pointer}.button:hover{color:#444;text-decoration:none}.button.activated,.button.active{background-color:#e5e5e5}.button:after{position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px;content:' '}.button .icon{vertical-align:top;pointer-events:none}.button .icon:before,.button.icon-left:before,.button.icon-right:before,.button.icon:before{display:inline-block;padding:0 0 1px 0;vertical-align:inherit;font-size:24px;line-height:41px;pointer-events:none}.button.icon-left:before{float:left;padding-right:.2em;padding-left:0}.button.icon-right:before{float:right;padding-right:0;padding-left:.2em}.button.button-block,.button.button-full{margin-top:10px;margin-bottom:10px}.button.button-light{border-color:transparent;background-color:#fff;color:#444}.button.button-light:hover{color:#444;text-decoration:none}.button.button-light.activated,.button.button-light.active{background-color:#fafafa}.button.button-light.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ddd}.button.button-light.button-icon{border-color:transparent;background:0 0}.button.button-light.button-outline{border-color:#ddd;background:0 0;color:#ddd}.button.button-light.button-outline.activated,.button.button-light.button-outline.active{background-color:#ddd;box-shadow:none;color:#fff}.button.button-stable{border-color:transparent;background-color:#f8f8f8;color:#444}.button.button-stable:hover{color:#444;text-decoration:none}.button.button-stable.activated,.button.button-stable.active{background-color:#e5e5e5}.button.button-stable.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button.button-stable.button-icon{border-color:transparent;background:0 0}.button.button-stable.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button.button-stable.button-outline.activated,.button.button-stable.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.button.button-positive{border-color:transparent;background-color:#387ef5;color:#fff}.button.button-positive:hover{color:#fff;text-decoration:none}.button.button-positive.activated,.button.button-positive.active{background-color:#0c60ee}.button.button-positive.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#387ef5}.button.button-positive.button-icon{border-color:transparent;background:0 0}.button.button-positive.button-outline{border-color:#387ef5;background:0 0;color:#387ef5}.button.button-positive.button-outline.activated,.button.button-positive.button-outline.active{background-color:#387ef5;box-shadow:none;color:#fff}.button.button-calm{border-color:transparent;background-color:#11c1f3;color:#fff}.button.button-calm:hover{color:#fff;text-decoration:none}.button.button-calm.activated,.button.button-calm.active{background-color:#0a9dc7}.button.button-calm.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#11c1f3}.button.button-calm.button-icon{border-color:transparent;background:0 0}.button.button-calm.button-outline{border-color:#11c1f3;background:0 0;color:#11c1f3}.button.button-calm.button-outline.activated,.button.button-calm.button-outline.active{background-color:#11c1f3;box-shadow:none;color:#fff}.button.button-assertive{border-color:transparent;background-color:#ef473a;color:#fff}.button.button-assertive:hover{color:#fff;text-decoration:none}.button.button-assertive.activated,.button.button-assertive.active{background-color:#e42112}.button.button-assertive.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ef473a}.button.button-assertive.button-icon{border-color:transparent;background:0 0}.button.button-assertive.button-outline{border-color:#ef473a;background:0 0;color:#ef473a}.button.button-assertive.button-outline.activated,.button.button-assertive.button-outline.active{background-color:#ef473a;box-shadow:none;color:#fff}.button.button-balanced{border-color:transparent;background-color:#33cd5f;color:#fff}.button.button-balanced:hover{color:#fff;text-decoration:none}.button.button-balanced.activated,.button.button-balanced.active{background-color:#28a54c}.button.button-balanced.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#33cd5f}.button.button-balanced.button-icon{border-color:transparent;background:0 0}.button.button-balanced.button-outline{border-color:#33cd5f;background:0 0;color:#33cd5f}.button.button-balanced.button-outline.activated,.button.button-balanced.button-outline.active{background-color:#33cd5f;box-shadow:none;color:#fff}.button.button-energized{border-color:transparent;background-color:#ffc900;color:#fff}.button.button-energized:hover{color:#fff;text-decoration:none}.button.button-energized.activated,.button.button-energized.active{background-color:#e6b500}.button.button-energized.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#ffc900}.button.button-energized.button-icon{border-color:transparent;background:0 0}.button.button-energized.button-outline{border-color:#ffc900;background:0 0;color:#ffc900}.button.button-energized.button-outline.activated,.button.button-energized.button-outline.active{background-color:#ffc900;box-shadow:none;color:#fff}.button.button-royal{border-color:transparent;background-color:#886aea;color:#fff}.button.button-royal:hover{color:#fff;text-decoration:none}.button.button-royal.activated,.button.button-royal.active{background-color:#6b46e5}.button.button-royal.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#886aea}.button.button-royal.button-icon{border-color:transparent;background:0 0}.button.button-royal.button-outline{border-color:#886aea;background:0 0;color:#886aea}.button.button-royal.button-outline.activated,.button.button-royal.button-outline.active{background-color:#886aea;box-shadow:none;color:#fff}.button.button-dark{border-color:transparent;background-color:#444;color:#fff}.button.button-dark:hover{color:#fff;text-decoration:none}.button.button-dark.activated,.button.button-dark.active{background-color:#262626}.button.button-dark.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#444}.button.button-dark.button-icon{border-color:transparent;background:0 0}.button.button-dark.button-outline{border-color:#444;background:0 0;color:#444}.button.button-dark.button-outline.activated,.button.button-dark.button-outline.active{background-color:#444;box-shadow:none;color:#fff}.button-small{padding:2px 4px 1px;min-width:28px;min-height:30px;font-size:12px;line-height:26px}.button-small .icon:before,.button-small.icon-left:before,.button-small.icon-right:before,.button-small.icon:before{font-size:16px;line-height:19px;margin-top:3px}.button-large{padding:0 16px;min-width:68px;min-height:59px;font-size:20px;line-height:53px}.button-large .icon:before,.button-large.icon-left:before,.button-large.icon-right:before,.button-large.icon:before{padding-bottom:2px;font-size:32px;line-height:51px}.button-icon{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;min-width:initial;border-color:transparent;background:0 0}.button-icon.button.activated,.button-icon.button.active{border-color:transparent;background:0 0;box-shadow:none;opacity:.3}.button-icon .icon:before,.button-icon.icon:before{font-size:32px}.button-clear{-webkit-transition:opacity .1s;transition:opacity .1s;padding:0 6px;max-height:42px;border-color:transparent;background:0 0;box-shadow:none}.button-clear.button-clear{border-color:transparent;background:0 0;box-shadow:none;color:#b2b2b2}.button-clear.button-icon{border-color:transparent;background:0 0}.button-clear.activated,.button-clear.active{opacity:.3}.button-outline{-webkit-transition:opacity .1s;transition:opacity .1s;background:0 0;box-shadow:none}.button-outline.button-outline{border-color:#b2b2b2;background:0 0;color:#b2b2b2}.button-outline.button-outline.activated,.button-outline.button-outline.active{background-color:#b2b2b2;box-shadow:none;color:#fff}.padding>.button.button-block:first-child{margin-top:0}.button-block{display:block;clear:both}.button-block:after{clear:both}.button-full,.button-full>.button{display:block;margin-right:0;margin-left:0;border-right-width:0;border-left-width:0;border-radius:0}.button-full>button.button,button.button-block,button.button-full,input.button.button-block{width:100%}a.button{text-decoration:none}a.button .icon:before,a.button.icon-left:before,a.button.icon-right:before,a.button.icon:before{margin-top:2px}.button.disabled,.button[disabled]{opacity:.4;cursor:default!important;pointer-events:none}.button-bar{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;width:100%}.button-bar.button-bar-inline{display:block;width:auto}.button-bar.button-bar-inline:after,.button-bar.button-bar-inline:before{display:table;content:"";line-height:0}.button-bar.button-bar-inline:after{clear:both}.button-bar.button-bar-inline>.button{width:auto;display:inline-block;float:left}.button-bar>.button{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;overflow:hidden;padding:0 16px;width:0;border-width:1px 0 1px 1px;border-radius:0;text-align:center;text-overflow:ellipsis;white-space:nowrap}.button-bar>.button .icon:before,.button-bar>.button:before{line-height:44px}.button-bar>.button:first-child{border-radius:4px 0 0 4px}.button-bar>.button:last-child{border-right-width:1px;border-radius:0 4px 4px 0}.button-bar>.button:only-child{border-radius:4px}.button-bar>.button-small .icon:before,.button-bar>.button-small:before{line-height:28px}.row{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-moz-flex;display:-ms-flexbox;display:flex;padding:5px;width:100%}.row-wrap{-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap}.row-no-padding,.row-no-padding>.col{padding:0}.row+.row{margin-top:-5px;padding-top:0}.col{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;display:block;padding:5px;width:100%}.row-top{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;-moz-align-items:flex-start;align-items:flex-start}.row-bottom{-webkit-box-align:end;-ms-flex-align:end;-webkit-align-items:flex-end;-moz-align-items:flex-end;align-items:flex-end}.row-center{-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;-moz-align-items:center;align-items:center}.row-stretch{-webkit-box-align:stretch;-ms-flex-align:stretch;-webkit-align-items:stretch;-moz-align-items:stretch;align-items:stretch}.row-baseline{-webkit-box-align:baseline;-ms-flex-align:baseline;-webkit-align-items:baseline;-moz-align-items:baseline;align-items:baseline}.col-top{-webkit-align-self:flex-start;-moz-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.col-bottom{-webkit-align-self:flex-end;-moz-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end}.col-center{-webkit-align-self:center;-moz-align-self:center;-ms-flex-item-align:center;align-self:center}.col-offset-10{margin-left:10%}.col-offset-20{margin-left:20%}.col-offset-25{margin-left:25%}.col-offset-33,.col-offset-34{margin-left:33.3333%}.col-offset-50{margin-left:50%}.col-offset-66,.col-offset-67{margin-left:66.6666%}.col-offset-75{margin-left:75%}.col-offset-80{margin-left:80%}.col-offset-90{margin-left:90%}.col-10{-webkit-box-flex:0;-webkit-flex:0 0 10%;-moz-box-flex:0;-moz-flex:0 0 10%;-ms-flex:0 0 10%;flex:0 0 10%;max-width:10%}.col-20{-webkit-box-flex:0;-webkit-flex:0 0 20%;-moz-box-flex:0;-moz-flex:0 0 20%;-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.col-25{-webkit-box-flex:0;-webkit-flex:0 0 25%;-moz-box-flex:0;-moz-flex:0 0 25%;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-33,.col-34{-webkit-box-flex:0;-webkit-flex:0 0 33.3333%;-moz-box-flex:0;-moz-flex:0 0 33.3333%;-ms-flex:0 0 33.3333%;flex:0 0 33.3333%;max-width:33.3333%}.col-40{-webkit-box-flex:0;-webkit-flex:0 0 40%;-moz-box-flex:0;-moz-flex:0 0 40%;-ms-flex:0 0 40%;flex:0 0 40%;max-width:40%}.col-50{-webkit-box-flex:0;-webkit-flex:0 0 50%;-moz-box-flex:0;-moz-flex:0 0 50%;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-60{-webkit-box-flex:0;-webkit-flex:0 0 60%;-moz-box-flex:0;-moz-flex:0 0 60%;-ms-flex:0 0 60%;flex:0 0 60%;max-width:60%}.col-66,.col-67{-webkit-box-flex:0;-webkit-flex:0 0 66.6666%;-moz-box-flex:0;-moz-flex:0 0 66.6666%;-ms-flex:0 0 66.6666%;flex:0 0 66.6666%;max-width:66.6666%}.col-75{-webkit-box-flex:0;-webkit-flex:0 0 75%;-moz-box-flex:0;-moz-flex:0 0 75%;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-80{-webkit-box-flex:0;-webkit-flex:0 0 80%;-moz-box-flex:0;-moz-flex:0 0 80%;-ms-flex:0 0 80%;flex:0 0 80%;max-width:80%}.col-90{-webkit-box-flex:0;-webkit-flex:0 0 90%;-moz-box-flex:0;-moz-flex:0 0 90%;-ms-flex:0 0 90%;flex:0 0 90%;max-width:90%}@media (max-width:567px){.responsive-sm{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-sm .col,.responsive-sm .col-10,.responsive-sm .col-20,.responsive-sm .col-25,.responsive-sm .col-33,.responsive-sm .col-34,.responsive-sm .col-50,.responsive-sm .col-66,.responsive-sm .col-67,.responsive-sm .col-75,.responsive-sm .col-80,.responsive-sm .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:767px){.responsive-md{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-md .col,.responsive-md .col-10,.responsive-md .col-20,.responsive-md .col-25,.responsive-md .col-33,.responsive-md .col-34,.responsive-md .col-50,.responsive-md .col-66,.responsive-md .col-67,.responsive-md .col-75,.responsive-md .col-80,.responsive-md .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}@media (max-width:1023px){.responsive-lg{-webkit-box-direction:normal;-moz-box-direction:normal;-webkit-box-orient:vertical;-moz-box-orient:vertical;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.responsive-lg .col,.responsive-lg .col-10,.responsive-lg .col-20,.responsive-lg .col-25,.responsive-lg .col-33,.responsive-lg .col-34,.responsive-lg .col-50,.responsive-lg .col-66,.responsive-lg .col-67,.responsive-lg .col-75,.responsive-lg .col-80,.responsive-lg .col-90{-webkit-box-flex:1;-webkit-flex:1;-moz-box-flex:1;-moz-flex:1;-ms-flex:1;flex:1;margin-bottom:15px;margin-left:0;max-width:100%;width:100%}}.hide{display:none}.opacity-hide{opacity:0}.grade-b .opacity-hide,.grade-c .opacity-hide{opacity:1;display:none}.show{display:block}.opacity-show{opacity:1}.invisible{visibility:hidden}.keyboard-open .hide-on-keyboard-open{display:none}.keyboard-open .bar-footer.hide-on-keyboard-open+.pane .has-footer,.keyboard-open .tabs.hide-on-keyboard-open+.pane .has-tabs{bottom:0}.inline{display:inline-block}.disable-pointer-events{pointer-events:none}.enable-pointer-events{pointer-events:auto}.disable-user-behavior{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;-webkit-user-drag:none;-ms-touch-action:none;-ms-content-zooming:none}.click-block{position:absolute;top:0;right:0;bottom:0;left:0;opacity:0;z-index:99999;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);overflow:hidden}.click-block-hide{-webkit-transform:translate3d(-9999px,0,0);transform:translate3d(-9999px,0,0)}.no-resize{resize:none}.block{display:block;clear:both}.block:after{display:block;visibility:hidden;clear:both;height:0;content:"."}.full-image{width:100%}.clearfix:after,.clearfix:before{display:table;content:"";line-height:0}.clearfix:after{clear:both}.padding{padding:10px}.padding-top,.padding-vertical{padding-top:10px}.padding-horizontal,.padding-right{padding-right:10px}.padding-bottom,.padding-vertical{padding-bottom:10px}.padding-horizontal,.padding-left{padding-left:10px}.iframe-wrapper{position:fixed;-webkit-overflow-scrolling:touch;overflow:scroll}.iframe-wrapper iframe{height:100%;width:100%}.rounded{border-radius:4px}.light,a.light{color:#fff}.light-bg{background-color:#fff}.light-border{border-color:#ddd}.stable,a.stable{color:#f8f8f8}.stable-bg{background-color:#f8f8f8}.stable-border{border-color:#b2b2b2}.positive,a.positive{color:#387ef5}.positive-bg{background-color:#387ef5}.positive-border{border-color:#0c60ee}.calm,a.calm{color:#11c1f3}.calm-bg{background-color:#11c1f3}.calm-border{border-color:#0a9dc7}.assertive,a.assertive{color:#ef473a}.assertive-bg{background-color:#ef473a}.assertive-border{border-color:#e42112}.balanced,a.balanced{color:#33cd5f}.balanced-bg{background-color:#33cd5f}.balanced-border{border-color:#28a54c}.energized,a.energized{color:#ffc900}.energized-bg{background-color:#ffc900}.energized-border{border-color:#e6b500}.royal,a.royal{color:#886aea}.royal-bg{background-color:#886aea}.royal-border{border-color:#6b46e5}.dark,a.dark{color:#444}.dark-bg{background-color:#444}.dark-border{border-color:#111}[collection-repeat]{left:0!important;top:0!important;position:absolute!important;z-index:1}.collection-repeat-container{position:relative;z-index:1}.collection-repeat-after-container{z-index:0;display:block}.collection-repeat-after-container.horizontal{display:inline-block}.ng-cloak,.ng-hide:not(.ng-hide-animate),.x-ng-cloak,[data-ng-cloak],[ng-cloak],[ng\:cloak],[x-ng-cloak]{display:none!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader){height:64px}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:19px!important}.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader)>*{margin-top:20px}.platform-ios.platform-cordova:not(.fullscreen) .bar-subheader,.platform-ios.platform-cordova:not(.fullscreen) .has-header,.platform-ios.platform-cordova:not(.fullscreen) .tabs-top>.tabs,.platform-ios.platform-cordova:not(.fullscreen) .tabs.tabs-top{top:64px}.platform-ios.platform-cordova:not(.fullscreen) .has-subheader{top:108px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-tabs-top{top:113px}.platform-ios.platform-cordova:not(.fullscreen) .has-header.has-subheader.has-tabs-top{top:157px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader){height:44px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader).item-input-inset .item-input-wrapper{margin-top:-1px}.platform-ios.platform-cordova .popover .bar-header:not(.bar-subheader)>*{margin-top:0}.platform-ios.platform-cordova .popover .bar-subheader,.platform-ios.platform-cordova .popover .has-header{top:44px}.platform-ios.platform-cordova .popover .has-subheader{top:88px}.platform-ios.platform-cordova.status-bar-hide{margin-bottom:20px}@media (orientation:landscape){.platform-ios.platform-browser.platform-ipad{position:fixed}}.platform-c:not(.enable-transitions) *{-webkit-transition:none!important;transition:none!important}.slide-in-up{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}.slide-in-up.ng-enter,.slide-in-up>.ng-enter{-webkit-transition:all cubic-bezier(.1,.7,.1,1) 400ms;transition:all cubic-bezier(.1,.7,.1,1) 400ms}.slide-in-up.ng-enter-active,.slide-in-up>.ng-enter-active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.slide-in-up.ng-leave,.slide-in-up>.ng-leave{-webkit-transition:all ease-in-out 250ms;transition:all ease-in-out 250ms}@-webkit-keyframes scaleOut{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@keyframes scaleOut{from{transform:scale(1);opacity:1}to{transform:scale(.8);opacity:0}}@-webkit-keyframes superScaleIn{from{-webkit-transform:scale(1.2);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@keyframes superScaleIn{from{transform:scale(1.2);opacity:0}to{transform:scale(1);opacity:1}}[nav-view-transition=ios] [nav-view=entering],[nav-view-transition=ios] [nav-view=leaving]{-webkit-transition-duration:500ms;transition-duration:500ms;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform,box-shadow;transition-property:opacity,transform,box-shadow}[nav-view-transition=ios][nav-view-direction=forward],[nav-view-transition=ios][nav-view-direction=back]{background-color:#000}[nav-view-transition=ios] [nav-view=active],[nav-view-transition=ios][nav-view-direction=forward] [nav-view=entering],[nav-view-transition=ios][nav-view-direction=back] [nav-view=leaving]{z-index:3}[nav-view-transition=ios][nav-view-direction=forward] [nav-view=leaving],[nav-view-transition=ios][nav-view-direction=back] [nav-view=entering]{z-index:2}[nav-bar-transition=ios] .back-text,[nav-bar-transition=ios] .buttons,[nav-bar-transition=ios] .title{-webkit-transition-duration:500ms;transition-duration:500ms;-webkit-transition-timing-function:cubic-bezier(.36,.66,.04,1);transition-timing-function:cubic-bezier(.36,.66,.04,1);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,transform}[nav-bar-transition=ios] [nav-bar=entering],[nav-bar-transition=ios] [nav-bar=active]{z-index:10}[nav-bar-transition=ios] [nav-bar=entering] .bar,[nav-bar-transition=ios] [nav-bar=active] .bar{background:0 0}[nav-bar-transition=ios] [nav-bar=cached]{display:block}[nav-bar-transition=ios] [nav-bar=cached] .header-item{display:none}[nav-view-transition=android] [nav-view=entering],[nav-view-transition=android] [nav-view=leaving]{-webkit-transition-duration:200ms;transition-duration:200ms;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:-webkit-transform;transition-property:transform}[nav-view-transition=android] [nav-view=active],[nav-view-transition=android][nav-view-direction=forward] [nav-view=entering],[nav-view-transition=android][nav-view-direction=back] [nav-view=leaving]{z-index:3}[nav-view-transition=android][nav-view-direction=forward] [nav-view=leaving],[nav-view-transition=android][nav-view-direction=back] [nav-view=entering]{z-index:2}[nav-bar-transition=android] .buttons,[nav-bar-transition=android] .title{-webkit-transition-duration:200ms;transition-duration:200ms;-webkit-transition-timing-function:cubic-bezier(.4,.6,.2,1);transition-timing-function:cubic-bezier(.4,.6,.2,1);-webkit-transition-property:opacity;transition-property:opacity}[nav-bar-transition=android] [nav-bar=entering],[nav-bar-transition=android] [nav-bar=active]{z-index:10}[nav-bar-transition=android] [nav-bar=entering] .bar,[nav-bar-transition=android] [nav-bar=active] .bar{background:0 0}[nav-bar-transition=android] [nav-bar=cached]{display:block}[nav-bar-transition=android] [nav-bar=cached] .header-item{display:none}[nav-swipe=fast] .back-text,[nav-swipe=fast] .buttons,[nav-swipe=fast] .title,[nav-swipe=fast] [nav-view]{-webkit-transition-duration:50ms;transition-duration:50ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-swipe=slow] .back-text,[nav-swipe=slow] .buttons,[nav-swipe=slow] .title,[nav-swipe=slow] [nav-view]{-webkit-transition-duration:160ms;transition-duration:160ms;-webkit-transition-timing-function:linear;transition-timing-function:linear}[nav-bar=cached],[nav-view=cached]{display:none}[nav-view=stage]{opacity:0;-webkit-transition-duration:0;transition-duration:0}[nav-bar=stage] .back-text,[nav-bar=stage] .buttons,[nav-bar=stage] .title{position:absolute;opacity:0;-webkit-transition-duration:0s;transition-duration:0s} \ No newline at end of file diff --git a/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.eot b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.eot new file mode 100644 index 0000000000000000000000000000000000000000..90f63af09a1d0f347150eee2b882d70f0af9d9fd Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.svg b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.svg new file mode 100644 index 0000000000000000000000000000000000000000..ee86b03db2109227cd1a6568e7086ac6a71af8d8 --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.svg @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-Black" horiz-adv-x="1186"> +<font-face underline-position="-100" font-weight="900" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-125 -472 1920 1932" x-height="1082" underline-thickness="100" font-family="RobotoDraft Black" ascent="1536" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1302" unicode="fi" d="M173 0v848h-157v234h157v36q3 216 142 331q132 108 369 108q149 0 352 -58l-46 -266l-56 15q-109 29 -230 29q-193 0 -193 -176v-19h212v-234h-212v-848h-338zM1191 0h-339v1082h339v-1082z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1298" unicode="fl" d="M848 1290q-86 7 -145 7q-196 0 -196 -153v-62h211v-234h-211v-848h-338v848h-157v234h157v70q1 194 125.5 299.5t356.5 105.5q165 0 536 -21v-1536h-339v1290z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="uni0000" horiz-adv-x="0"/> +<glyph glyph-name="glyph2" horiz-adv-x="0"/> +<glyph glyph-name="uni000D" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="565" unicode="!" d="M429 461h-273l-43 995h359zM103 151q0 74 53.5 121.5t133.5 47.5t133.5 -47.5t53.5 -121.5t-53.5 -121.5t-133.5 -47.5t-133.5 47.5t-53.5 121.5z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="649" unicode='"' d="M255 1398l-43 -429h-187v568h230v-139zM606 1398l-43 -429h-185v568h228v-139z"/> +<glyph glyph-name="numbersign" horiz-adv-x="1190" unicode="#" d="M612 410h-161l-67 -410h-199l67 410h-222v183h252l44 264h-221v183h251l69 416h198l-68 -416h161l69 416h199l-69 -416h231v-183h-261l-44 -264h229v-183h-259l-67 -410h-199zM481 593h161l44 264h-161z"/> +<glyph glyph-name="dollar" d="M760 386q0 79 -39 124t-137 85t-181 81t-143 95t-92 125t-32 172q0 169 114 278.5t304 127.5v211h159v-215q183 -27 287.5 -150.5t104.5 -313.5h-338q0 104 -40 160t-114 56q-66 0 -102.5 -41.5t-36.5 -114.5q0 -74 42 -117.5t135 -83t175.5 -82t142.5 -96.5t94 -126 t34 -173q0 -171 -108.5 -279t-295.5 -126v-201h-159v202q-218 23 -334.5 149.5t-116.5 333.5h337q0 -114 50.5 -173.5t143.5 -59.5q68 0 107 40.5t39 111.5z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1520" unicode="%" d="M90 1176q0 135 88 218t236 83q150 0 237 -82.5t87 -223.5v-72q0 -135 -87 -217t-235 -82q-147 0 -236.5 81.5t-89.5 223.5v71zM307 1099q0 -52 29 -84.5t80 -32.5q105 0 105 134v60q0 52 -28 85.5t-79 33.5q-49 0 -78 -32.5t-29 -88.5v-75zM782 357q0 136 88.5 218 t235.5 82q149 0 237 -81t88 -226v-70q0 -136 -87 -218t-236 -82q-147 0 -236.5 81.5t-89.5 223.5v72zM998 280q0 -47 32 -82.5t78 -35.5q97 0 105 92l1 103q0 53 -29 85.5t-79 32.5q-48 0 -77 -30.5t-31 -82.5v-82zM480 109l-157 79l711 1138l157 -79z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1380" unicode="&" d="M311 767q-59 84 -92.5 160t-33.5 157q0 176 114 284.5t298 108.5q165 0 273 -100.5t108 -249.5q0 -186 -205 -330l-76 -53l224 -257q55 110 55 241h283q0 -295 -136 -473l222 -255h-376l-68 77q-84 -50 -171.5 -74t-197.5 -24q-216 0 -346 113.5t-130 298.5 q0 101 51.5 183t200.5 191zM554 239q88 0 168 41l-262 298l-9 -6q-57 -70 -57 -158q0 -73 46 -124t114 -51zM476 1088q0 -70 76 -170l67 42q46 30 67 62t21 81q0 46 -32 80t-79 34q-56 0 -88 -35.5t-32 -93.5z"/> +<glyph glyph-name="quotesingle" horiz-adv-x="316" unicode="'" d="M283 1374l-33 -413h-207v575h240v-162z"/> +<glyph glyph-name="parenleft" horiz-adv-x="723" unicode="(" d="M120 592q0 244 65 454t179.5 356t254.5 204l64 -166q-140 -103 -216.5 -321.5t-77.5 -512.5v-44q0 -301 76.5 -522t217.5 -324l-64 -166q-138 56 -254.5 204.5t-179.5 354.5t-65 438v45z"/> +<glyph glyph-name="parenright" horiz-adv-x="721" unicode=")" d="M626 564q0 -235 -69 -446t-190.5 -362.5t-262.5 -205.5l-64 166q139 104 215 320t79 497v61q0 301 -76.5 522t-217.5 324l64 166q140 -55 260.5 -203.5t190 -357t71.5 -437.5v-44z"/> +<glyph glyph-name="asterisk" horiz-adv-x="952" unicode="*" d="M352 956l-326 90l65 189l319 -131l-25 352h214l-26 -359l310 128l65 -191l-330 -90l219 -265l-173 -118l-183 294l-184 -284l-173 113z"/> +<glyph glyph-name="plus" horiz-adv-x="1094" unicode="+" d="M702 826h341v-289h-341v-391h-315v391h-342v289h342v380h315v-380z"/> +<glyph glyph-name="comma" horiz-adv-x="552" unicode="," d="M213 -392l-170 80l34 68q70 130 73 248v250h270l-1 -217q-1 -115 -59 -234t-147 -195z"/> +<glyph glyph-name="hyphen" horiz-adv-x="921" unicode="-" d="M753 497h-601v261h601v-261z"/> +<glyph glyph-name="period" horiz-adv-x="619" unicode="." d="M303 327q80 0 133 -47.5t53 -121.5t-53 -121.5t-133 -47.5q-81 0 -133.5 48t-52.5 121t52.5 121t133.5 48z"/> +<glyph glyph-name="slash" horiz-adv-x="719" unicode="/" d="M210 -125h-239l497 1581h240z"/> +<glyph glyph-name="zero" d="M1100 595q0 -295 -132.5 -455t-373.5 -160q-243 0 -376 161t-133 454v266q0 295 132.5 455t374.5 160t375 -161t133 -455v-265zM763 904q0 157 -41 234.5t-130 77.5q-87 0 -126.5 -72t-42.5 -218v-372q0 -163 41 -238.5t130 -75.5q86 0 127 73.5t42 230.5v360z" unicode="0"/> +<glyph glyph-name="one" d="M836 0h-338v1076l-332 -97v256l639 221h31v-1456z" unicode="1"/> +<glyph glyph-name="two" d="M1105 0h-1016v220l468 492q173 197 173 313q0 94 -41 143t-119 49q-77 0 -125 -65.5t-48 -163.5h-338q0 134 67 247.5t186 177.5t266 64q236 0 363.5 -109t127.5 -313q0 -86 -32 -167.5t-99.5 -171t-217.5 -239.5l-188 -217h573v-260z" unicode="2"/> +<glyph glyph-name="three" d="M397 869h159q189 0 189 185q0 72 -45 117.5t-127 45.5q-67 0 -116.5 -39t-49.5 -97h-337q0 115 64 205t177.5 140.5t249.5 50.5q243 0 382 -111t139 -305q0 -94 -57.5 -177.5t-167.5 -135.5q116 -42 182 -127.5t66 -211.5q0 -195 -150 -312t-394 -117q-143 0 -265.5 54.5 t-185.5 151t-63 219.5h339q0 -67 54 -116t133 -49q89 0 142 49.5t53 126.5q0 110 -55 156t-152 46h-164v251z" unicode="3"/> +<glyph glyph-name="four" d="M979 569h148v-260h-148v-309h-337v309h-563l-20 206l583 938v3h337v-887zM380 569h262v448l-21 -34z" unicode="4"/> +<glyph glyph-name="five" d="M109 712l89 744h851v-262h-577l-33 -289q36 21 94.5 37t114.5 16q217 0 333.5 -128.5t116.5 -360.5q0 -140 -62.5 -253.5t-175.5 -174.5t-267 -61q-137 0 -257 56.5t-188 155t-67 222.5h338q5 -80 51 -127t121 -47q170 0 170 252q0 233 -208 233q-118 0 -176 -76z" unicode="5"/> +<glyph glyph-name="six" d="M903 1477v-265h-15q-189 0 -310.5 -90.5t-149.5 -251.5q114 112 288 112q189 0 301 -138t112 -362q0 -139 -65.5 -255t-183 -181.5t-260.5 -65.5q-155 0 -277 70.5t-190 201.5t-70 302v135q0 225 96.5 404.5t275.5 281.5t397 102h51zM599 724q-67 0 -112 -31t-67 -76 v-101q0 -276 191 -276q77 0 128.5 69t51.5 173q0 107 -52.5 174.5t-139.5 67.5z" unicode="6"/> +<glyph glyph-name="seven" d="M1101 1276l-544 -1276h-356l545 1196h-694v260h1049v-180z" unicode="7"/> +<glyph glyph-name="eight" d="M1071 1067q0 -106 -52.5 -187t-144.5 -130q104 -51 165 -139.5t61 -209.5q0 -195 -134.5 -308t-370.5 -113q-237 0 -374 113.5t-137 307.5q0 117 60 207t170 142q-93 49 -146 130t-53 187q0 190 129 300t348 110q221 0 350 -110t129 -300zM762 428q0 90 -46.5 138.5 t-122.5 48.5t-123 -48.5t-47 -138.5q0 -87 47.5 -137.5t124.5 -50.5q75 0 121 50t46 138zM592 1217q-68 0 -103.5 -44.5t-35.5 -123.5q0 -78 36 -126t106 -48q69 0 103.5 48t34.5 126t-35.5 123t-105.5 45z" unicode="8"/> +<glyph glyph-name="nine" d="M753 563q-109 -98 -244 -98q-198 0 -314 134t-116 358q0 140 65 260t182.5 190t259.5 70q144 0 260.5 -72.5t181.5 -205t67 -305.5v-129q0 -241 -94.5 -418t-269.5 -272t-408 -95h-21v270l64 1q348 17 387 312zM600 708q110 0 158 95v140q0 140 -47 207t-127 67 q-71 0 -119 -76t-48 -184q0 -114 49 -181.5t134 -67.5z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="615" unicode=":" d="M304 327q80 0 133 -47.5t53 -121.5t-53 -121.5t-133 -47.5q-81 0 -133.5 48t-52.5 121t52.5 121t133.5 48zM304 1125q80 0 133 -47.5t53 -121.5t-53 -121.5t-133 -47.5q-81 0 -133.5 48t-52.5 121t52.5 121t133.5 48z"/> +<glyph glyph-name="semicolon" horiz-adv-x="590" unicode=";" d="M294 1125q80 0 133 -47.5t53 -121.5t-53 -121.5t-133 -47.5q-81 0 -133.5 48t-52.5 121t52.5 121t133.5 48zM238 -392l-170 80l34 68q70 130 73 248v250h270l-1 -217q-1 -115 -59 -234t-147 -195z"/> +<glyph glyph-name="less" horiz-adv-x="1044" unicode="<" d="M383 609l547 -184v-307l-884 360v266l884 360v-306z"/> +<glyph glyph-name="equal" horiz-adv-x="1199" unicode="=" d="M1054 722h-926v260h926v-260zM1054 283h-926v260h926v-260z"/> +<glyph glyph-name="greater" horiz-adv-x="1050" unicode=">" d="M655 612l-544 185v306l879 -360v-266l-879 -360v306z"/> +<glyph glyph-name="question" horiz-adv-x="1043" unicode="?" d="M344 461q0 146 33 230.5t107 146.5t112.5 113.5t38.5 113.5q0 151 -130 151q-60 0 -97 -44t-39 -119h-338q2 200 126 311.5t348 111.5q223 0 345.5 -103t122.5 -293q0 -83 -33 -151t-106 -139l-115 -107q-49 -47 -68 -96.5t-21 -125.5h-286zM303 157q0 74 53.5 121.5 t133.5 47.5t133.5 -47.5t53.5 -121.5t-53.5 -121.5t-133.5 -47.5t-133.5 47.5t-53.5 121.5z"/> +<glyph glyph-name="at" horiz-adv-x="1834" unicode="@" d="M1756 550q-10 -261 -130 -416t-320 -155q-82 0 -145 35.5t-98 100.5q-98 -132 -263 -132q-96 0 -168 56.5t-105.5 160.5t-20.5 236q30 250 161 402t321 152q147 0 253 -68l63 -42l-51 -587q-17 -139 96 -139q85 0 142.5 108.5t63.5 277.5q17 334 -138.5 516t-455.5 182 q-191 0 -339.5 -97.5t-235 -276t-97.5 -406.5q-16 -350 140 -535.5t468 -185.5q84 0 178 19.5t153 45.5l37 -166q-61 -40 -164.5 -64.5t-207.5 -24.5q-273 0 -461.5 104.5t-280.5 309.5t-82 497q12 276 127.5 494.5t316 338t452.5 119.5t435 -104.5t275 -300.5t81 -455z M756 436q-11 -130 20.5 -196.5t101.5 -66.5q47 0 86.5 42t65.5 120l40 456q-30 8 -62 8q-112 0 -172.5 -87.5t-79.5 -275.5z"/> +<glyph glyph-name="A" horiz-adv-x="1395" unicode="A" d="M937 272h-481l-84 -272h-375l534 1456h330l538 -1456h-377zM540 543h313l-157 505z"/> +<glyph glyph-name="B" horiz-adv-x="1321" unicode="B" d="M110 0v1456h523q281 0 427.5 -103t146.5 -299q0 -113 -52 -193t-153 -118q114 -30 175 -112t61 -200q0 -214 -135.5 -321.5t-401.5 -109.5h-591zM461 619v-349h230q95 0 146 43.5t51 122.5q0 182 -181 183h-246zM461 849h183q115 1 164 42t49 121q0 92 -53 132.5 t-171 40.5h-172v-336z"/> +<glyph glyph-name="C" horiz-adv-x="1344" unicode="C" d="M1288 493q-7 -152 -82 -268.5t-210.5 -180.5t-309.5 -64q-287 0 -452 187t-165 528v72q0 214 74.5 374.5t214.5 248t324 87.5q265 0 426 -139.5t183 -384.5h-350q-4 133 -67 191t-192 58q-131 0 -192 -98t-64 -313v-103q0 -233 58.5 -333t201.5 -100q121 0 185 57t68 181 h349z"/> +<glyph glyph-name="D" horiz-adv-x="1324" unicode="D" d="M110 0v1456h469q193 0 347 -87.5t240.5 -247t87.5 -357.5v-67q0 -200 -84.5 -358.5t-238 -248t-342.5 -90.5h-479zM461 1185v-915h122q151 0 232 107.5t81 319.5v63q0 211 -81 318t-236 107h-118z"/> +<glyph glyph-name="E" horiz-adv-x="1146" unicode="E" d="M1013 617h-552v-347h652v-270h-1003v1456h1005v-271h-654v-307h552v-261z"/> +<glyph glyph-name="F" horiz-adv-x="1120" unicode="F" d="M1027 580h-566v-580h-351v1456h974v-271h-623v-335h566v-270z"/> +<glyph glyph-name="G" horiz-adv-x="1396" unicode="G" d="M1302 180q-81 -90 -237 -145t-342 -55q-286 0 -457 175t-183 487l-1 126q0 215 76 375.5t217.5 247t327.5 86.5q272 0 422.5 -124.5t175.5 -371.5h-338q-18 122 -78 174t-170 52q-132 0 -204 -112t-73 -320v-88q0 -218 74.5 -327.5t234.5 -109.5q137 0 204 61v226h-244 v241h595v-598z"/> +<glyph glyph-name="H" horiz-adv-x="1439" unicode="H" d="M1327 0h-349v608h-517v-608h-351v1456h351v-578h517v578h349v-1456z"/> +<glyph glyph-name="I" horiz-adv-x="618" unicode="I" d="M484 0h-350v1456h350v-1456z"/> +<glyph glyph-name="J" horiz-adv-x="1151" unicode="J" d="M690 1456h350v-999q0 -139 -64.5 -248t-180 -169t-257.5 -60q-238 0 -370 120t-132 340h352q0 -100 34.5 -145t115.5 -45q73 0 112.5 54.5t39.5 152.5v999z"/> +<glyph glyph-name="K" horiz-adv-x="1310" unicode="K" d="M605 542l-144 -158v-384h-351v1456h351v-642l122 185l314 457h434l-492 -644l492 -812h-416z"/> +<glyph glyph-name="L" horiz-adv-x="1110" unicode="L" d="M461 270h611v-270h-962v1456h351v-1186z"/> +<glyph glyph-name="M" horiz-adv-x="1795" unicode="M" d="M571 1456l325 -1013l324 1013h462v-1456h-352v340l34 696l-352 -1036h-232l-353 1037l34 -697v-340h-351v1456h461z"/> +<glyph glyph-name="N" horiz-adv-x="1438" unicode="N" d="M1326 0h-349l-516 906v-906h-351v1456h351l515 -906v906h350v-1456z"/> +<glyph glyph-name="O" horiz-adv-x="1414" unicode="O" d="M1343 698q0 -213 -79 -377t-224.5 -252.5t-331.5 -88.5t-330 85.5t-224.5 244.5t-84.5 365v82q0 214 78.5 377.5t225 252.5t333.5 89q185 0 330 -88t225.5 -250.5t81.5 -372.5v-67zM986 759q0 217 -72.5 329.5t-207.5 112.5q-264 0 -279 -396l-1 -107q0 -214 71 -329 t211 -115q133 0 205 113t73 325v67z"/> +<glyph glyph-name="P" horiz-adv-x="1333" unicode="P" d="M461 494v-494h-351v1456h581q167 0 295.5 -61.5t199 -175t70.5 -257.5q0 -213 -152.5 -340.5t-418.5 -127.5h-224zM461 765h230q102 0 155.5 51t53.5 144q0 102 -55 163t-150 62h-234v-420z"/> +<glyph glyph-name="Q" horiz-adv-x="1414" unicode="Q" d="M1345 698q0 -202 -67 -352.5t-185 -241.5l235 -186l-217 -184l-313 252q-44 -6 -88 -6q-186 0 -330 86t-224.5 246t-83.5 368v77q0 215 78.5 378t224 252t333.5 89q185 0 330 -88t225.5 -250.5t81.5 -372.5v-67zM988 759q0 217 -72.5 329.5t-207.5 112.5 q-139 0 -209 -111t-71 -325v-67q0 -215 71 -329.5t211 -114.5q134 0 205.5 113t72.5 325v67z"/> +<glyph glyph-name="R" horiz-adv-x="1336" unicode="R" d="M651 514h-190v-514h-351v1456h573q259 0 405 -115t146 -325q0 -152 -61.5 -252t-192.5 -162l304 -587v-15h-376zM461 785h222q100 0 150.5 52.5t50.5 146.5t-51 147.5t-150 53.5h-222v-400z"/> +<glyph glyph-name="S" horiz-adv-x="1282" unicode="S" d="M861 387q0 77 -54.5 120t-191.5 89t-224 89q-283 139 -283 382q0 121 70.5 213.5t199.5 144t290 51.5q157 0 281.5 -56t193.5 -159.5t69 -236.5h-350q0 89 -54.5 138t-147.5 49q-94 0 -148.5 -41.5t-54.5 -105.5q0 -56 60 -101.5t211 -94t248 -104.5q236 -136 236 -375 q0 -191 -144 -300t-395 -109q-177 0 -320.5 63.5t-216 174t-72.5 254.5h352q0 -117 60.5 -172.5t196.5 -55.5q87 0 137.5 37.5t50.5 105.5z"/> +<glyph glyph-name="T" horiz-adv-x="1291" unicode="T" d="M1253 1185h-437v-1185h-351v1185h-429v271h1217v-271z"/> +<glyph glyph-name="U" horiz-adv-x="1361" unicode="U" d="M1252 1456v-953q0 -162 -69 -280.5t-198 -180.5t-305 -62q-266 0 -419 138t-156 378v960h353v-967q6 -239 222 -239q109 0 165 60t56 195v951h351z"/> +<glyph glyph-name="V" horiz-adv-x="1353" unicode="V" d="M675 396l290 1060h392l-490 -1456h-384l-486 1456h389z"/> +<glyph glyph-name="W" horiz-adv-x="1780" unicode="W" d="M1238 543l167 913h348l-309 -1456h-364l-195 830l-191 -830h-363l-310 1456h349l167 -913l200 913h298z"/> +<glyph glyph-name="X" horiz-adv-x="1307" unicode="X" d="M653 972l238 484h401l-407 -722l418 -734h-405l-245 493l-245 -493h-404l417 734l-406 722h400z"/> +<glyph glyph-name="Y" horiz-adv-x="1286" unicode="Y" d="M643 824l268 632h379l-469 -933v-523h-356v523l-468 933h377z"/> +<glyph glyph-name="Z" horiz-adv-x="1249" unicode="Z" d="M504 270h696v-270h-1134v185l694 1000h-698v271h1131v-180z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="577" unicode="[" d="M564 1460h-118v-1564h118v-245h-456v2055h456v-246z"/> +<glyph glyph-name="backslash" horiz-adv-x="873" unicode="\" d="M-20 1456h351l608 -1581h-353z"/> +<glyph glyph-name="bracketright" horiz-adv-x="577" unicode="]" d="M14 1706h456v-2055h-456v245h119v1564h-119v246z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="916" unicode="^" d="M460 1182l-171 -453h-253l299 727h249l300 -727h-254z"/> +<glyph glyph-name="underscore" horiz-adv-x="904" unicode="_" d="M903 -251h-903v251h903v-251z"/> +<glyph glyph-name="grave" horiz-adv-x="695" unicode="`" d="M610 1222h-274l-282 314h356z"/> +<glyph glyph-name="a" horiz-adv-x="1087" unicode="a" d="M704 0q-18 33 -32 97q-93 -117 -260 -117q-153 0 -260 92.5t-107 232.5q0 176 130 266t378 90h104v57q0 149 -129 149q-120 0 -120 -118h-337q0 157 133.5 255t340.5 98t327 -101t123 -277v-479q2 -149 46 -228v-17h-337zM493 220q63 0 104.5 27t59.5 61v173h-98 q-176 0 -176 -158q0 -46 31 -74.5t79 -28.5z"/> +<glyph glyph-name="b" horiz-adv-x="1153" unicode="b" d="M1099 532q0 -266 -110 -409t-310 -143q-165 0 -266 131l-14 -111h-302v1536h337v-541q94 107 243 107q202 0 312 -145t110 -408v-17zM761 553q0 156 -41.5 222.5t-127.5 66.5q-114 0 -158 -87v-430q43 -86 160 -86q119 0 151 116q16 57 16 198z"/> +<glyph glyph-name="c" horiz-adv-x="1064" unicode="c" d="M552 240q71 0 110 38.5t38 107.5h316q0 -178 -127.5 -292t-328.5 -114q-236 0 -372 148t-136 410v14q0 164 60.5 289.5t174.5 193t270 67.5q211 0 335 -117t124 -317h-316q0 84 -41 129t-110 45q-131 0 -153 -167q-7 -53 -7 -146q0 -163 39 -226t124 -63z"/> +<glyph glyph-name="d" horiz-adv-x="1152" unicode="d" d="M52 549q0 257 111 405t310 148q145 0 244 -114v548h338v-1536h-303l-17 116q-104 -136 -264 -136q-193 0 -306 148t-113 421zM389 528q0 -288 168 -288q112 0 160 94v412q-46 96 -158 96q-156 0 -169 -252z"/> +<glyph glyph-name="e" horiz-adv-x="1115" unicode="e" d="M618 -20q-249 0 -403 148.5t-154 386.5v28q0 166 61.5 293t179.5 196.5t280 69.5q228 0 360 -141.5t132 -394.5v-131h-670q18 -91 79 -143t158 -52q160 0 250 112l154 -182q-63 -87 -178.5 -138.5t-248.5 -51.5zM580 842q-148 0 -176 -196h340v26q2 81 -41 125.5 t-123 44.5z"/> +<glyph glyph-name="f" horiz-adv-x="742" unicode="f" d="M169 0v848h-157v234h157v86q0 185 109 287t306 102q72 0 158 -21l1 -248q-31 9 -83 9q-153 0 -153 -132v-83h211v-234h-211v-848h-338z"/> +<glyph glyph-name="g" horiz-adv-x="1178" unicode="g" d="M55 549q0 164 54 290t155 194.5t235 68.5q169 0 264 -114l12 94h306v-1041q0 -143 -66.5 -248.5t-192.5 -162t-292 -56.5q-119 0 -230.5 45t-170.5 117l141 198q94 -111 248 -111q224 0 224 230v34q-97 -107 -245 -107q-198 0 -320 151.5t-122 405.5v12zM393 528 q0 -133 50 -210.5t140 -77.5q109 0 159 73v455q-49 74 -157 74q-90 0 -141 -80.5t-51 -233.5z"/> +<glyph glyph-name="h" horiz-adv-x="1156" unicode="h" d="M424 966q108 136 276 136q179 0 270 -106t93 -313v-683h-338v675q0 86 -35 126.5t-119 40.5q-104 0 -147 -66v-776h-337v1536h337v-570z"/> +<glyph glyph-name="i" horiz-adv-x="563" unicode="i" d="M450 0h-338v1082h338v-1082zM92 1361q0 72 52 118t135 46t135 -46t52 -118t-52 -118t-135 -46t-135 46t-52 118z"/> +<glyph glyph-name="j" horiz-adv-x="553" unicode="j" d="M457 1082v-1119q-1 -192 -110 -296t-304 -104q-84 0 -159 17v255q58 -9 95 -9q140 0 140 139v1117h338zM94 1361q0 72 52 118t135 46t135 -46t52 -118t-52 -118t-135 -46t-135 46t-52 118z"/> +<glyph glyph-name="k" horiz-adv-x="1120" unicode="k" d="M529 403l-95 -95v-308h-337v1537h337v-816l34 45l254 316h404l-379 -445l404 -637h-386z"/> +<glyph glyph-name="l" horiz-adv-x="563" unicode="l" d="M450 0h-338v1536h338v-1536z"/> +<glyph glyph-name="m" horiz-adv-x="1764" unicode="m" d="M413 1082l11 -127q115 147 309 147q205 0 277 -163q110 163 318 163q329 0 338 -398v-704h-338v683q0 83 -28 121t-102 38q-100 0 -149 -89l1 -14v-739h-338v681q0 85 -27 123t-103 38q-97 0 -148 -89v-753h-337v1082h316z"/> +<glyph glyph-name="n" horiz-adv-x="1155" unicode="n" d="M404 1082l11 -127q112 147 309 147q169 0 252.5 -101t86.5 -304v-697h-338v683q0 82 -33 120.5t-120 38.5q-99 0 -147 -78v-764h-337v1082h316z"/> +<glyph glyph-name="o" horiz-adv-x="1150" unicode="o" d="M52 551q0 162 63 288.5t181 194.5t277 68q243 0 383 -150.5t140 -409.5v-12q0 -253 -140.5 -401.5t-380.5 -148.5q-231 0 -371 138.5t-151 375.5zM389 530q0 -150 47 -220t139 -70q180 0 184 277v34q0 291 -186 291q-169 0 -183 -251z"/> +<glyph glyph-name="p" horiz-adv-x="1153" unicode="p" d="M1099 533q0 -252 -113.5 -402.5t-306.5 -150.5q-149 0 -245 109v-505h-337v1498h315l10 -100q97 120 255 120q200 0 311 -147.5t111 -405.5v-16zM762 554q0 288 -168 288q-120 0 -160 -86v-426q44 -90 162 -90q161 0 166 278v36z"/> +<glyph glyph-name="q" horiz-adv-x="1151" unicode="q" d="M52 552q0 258 112 404t309 146q166 0 266 -136l24 116h292v-1498h-338v506q-97 -110 -246 -110q-192 0 -305.5 148.5t-113.5 423.5zM389 531q0 -291 168 -291q116 0 160 88v428q-42 86 -158 86q-157 0 -169 -251z"/> +<glyph glyph-name="r" horiz-adv-x="776" unicode="r" d="M749 777l-111 8q-159 0 -204 -100v-685h-337v1082h316l11 -139q85 159 237 159q54 0 94 -12z"/> +<glyph glyph-name="s" horiz-adv-x="1049" unicode="s" d="M661 304q0 43 -45 69t-171 54t-208 73.5t-125 110.5t-43 149q0 149 123 245.5t322 96.5q214 0 344 -97t130 -255h-338q0 130 -137 130q-53 0 -89 -29.5t-36 -73.5q0 -45 44 -73t140.5 -46t169.5 -43q244 -84 244 -301q0 -148 -131.5 -241t-340.5 -93q-139 0 -248 50 t-170 136t-61 181h315q2 -75 50 -109.5t123 -34.5q69 0 103.5 28t34.5 73z"/> +<glyph glyph-name="t" horiz-adv-x="703" unicode="t" d="M487 1351v-269h178v-234h-178v-495q0 -61 22 -85t87 -24q50 0 84 6v-241q-91 -29 -190 -29q-174 0 -257 82t-83 249v537h-138v234h138v269h337z"/> +<glyph glyph-name="u" horiz-adv-x="1155" unicode="u" d="M739 117q-107 -137 -289 -137q-178 0 -269.5 103.5t-91.5 297.5v701h337v-703q0 -139 135 -139q116 0 165 83v759h339v-1082h-316z"/> +<glyph glyph-name="v" horiz-adv-x="1058" unicode="v" d="M526 401l171 681h355l-353 -1082h-344l-353 1082h356z"/> +<glyph glyph-name="w" horiz-adv-x="1487" unicode="w" d="M1029 444l109 638h323l-255 -1082h-285l-179 642l-180 -642h-285l-255 1082h323l107 -653l172 653h235z"/> +<glyph glyph-name="x" horiz-adv-x="1054" unicode="x" d="M533 784l157 298h350l-285 -527l299 -555h-352l-170 320l-167 -320h-354l300 555l-284 527h354z"/> +<glyph glyph-name="y" horiz-adv-x="1061" unicode="y" d="M527 472l180 610h361l-441 -1263l-19 -46q-94 -210 -332 -210q-66 0 -139 20v241h44q71 0 108.5 20.5t55.5 73.5l27 72l-376 1092h360z"/> +<glyph glyph-name="z" horiz-adv-x="1054" unicode="z" d="M492 260h493v-260h-919v188l480 634h-459v260h887v-182z"/> +<glyph glyph-name="braceleft" horiz-adv-x="665" unicode="{" d="M562 -360q-360 101 -360 465v198q0 202 -162 202v227q162 0 162 203v210q3 180 93.5 291t266.5 161l63 -176q-126 -48 -131 -269v-217q0 -224 -185 -316q185 -92 185 -317v-216q5 -221 131 -269z"/> +<glyph glyph-name="bar" horiz-adv-x="523" unicode="|" d="M356 -270h-184v1726h184v-1726z"/> +<glyph glyph-name="braceright" horiz-adv-x="665" unicode="}" d="M41 -183q126 48 131 269v217q0 225 186 316q-186 91 -186 316v217q-5 221 -131 269l63 176q179 -50 269 -163.5t91 -297.5v-201q0 -203 162 -203v-227q-162 0 -162 -201v-213q-7 -352 -360 -451z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1295" unicode="~" d="M1197 799q0 -196 -91.5 -314t-242.5 -118q-75 0 -135.5 29t-137 104.5t-141.5 75.5q-50 0 -83.5 -49t-33.5 -122l-238 4q0 196 89.5 311.5t242.5 115.5q76 0 139 -29.5t137.5 -104t137.5 -74.5q51 0 83.5 49.5t32.5 122.5z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="615" unicode="¡" d="M171 623h273l43 -995h-359zM497 933q0 -74 -53.5 -121.5t-133.5 -47.5t-133.5 47.5t-53.5 121.5t53.5 121.5t133.5 47.5t133.5 -47.5t53.5 -121.5z"/> +<glyph glyph-name="cent" horiz-adv-x="1209" unicode="¢" d="M598 240q71 0 110 38.5t38 107.5h316q0 -156 -97 -262.5t-255 -134.5v-234h-200v232q-193 28 -302.5 171.5t-109.5 375.5v18q0 224 109 369.5t303 173.5v223h200v-225q165 -29 258.5 -141.5t93.5 -283.5h-316q0 84 -41 129t-110 45q-131 0 -153 -167q-7 -53 -7 -146 q0 -163 39 -226t124 -63z"/> +<glyph glyph-name="sterling" horiz-adv-x="1229" unicode="£" d="M621 561l5 -112q0 -114 -59 -179h608v-270h-1069v270h103q57 15 60 103l1 53l-5 135h-162v261h154l-6 217q0 205 122.5 320.5t331.5 115.5q224 0 349.5 -115t125.5 -312h-330q0 157 -136 157q-51 0 -82 -40.5t-31 -125.5l9 -217h307v-261h-296z"/> +<glyph glyph-name="currency" horiz-adv-x="1397" unicode="¤" d="M1061 107q-159 -127 -361 -127q-203 0 -361 126l-129 -132l-141 144l135 137q-100 156 -100 353q0 204 109 365l-144 147l141 144l142 -145q155 115 348 115q194 0 349 -117l144 148l142 -145l-148 -151q107 -159 107 -361q0 -193 -98 -349l139 -141l-142 -145zM290 608 q0 -118 54 -218.5t149 -158.5t207 -58q111 0 206 58t149 158.5t54 218.5q0 119 -54.5 219.5t-149 157.5t-205.5 57q-112 0 -206.5 -57t-149 -157.5t-54.5 -219.5z"/> +<glyph glyph-name="yen" horiz-adv-x="1259" unicode="Â¥" d="M633 880l236 576h379l-361 -714h203v-190h-287v-100h287v-189h-287v-263h-349v263h-319v189h319v100h-319v190h243l-362 714h380z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="524" unicode="¦" d="M119 -270v795h292v-795h-292zM411 698h-292v758h292v-758z"/> +<glyph glyph-name="section" horiz-adv-x="1301" unicode="§" d="M1196 500q0 -177 -155 -268q138 -103 138 -293q0 -177 -141.5 -276.5t-389.5 -99.5q-268 0 -411 107t-143 305h338q0 -75 50.5 -113t165.5 -38q193 0 193 114q0 58 -57.5 94t-236.5 86t-270 104.5t-137 129t-46 176.5q0 176 157 270q-141 106 -141 292q0 174 145 280 t389 106q250 0 391 -112t141 -313h-337q0 75 -51.5 120t-143.5 45q-95 0 -145 -33t-50 -91q0 -66 56 -100t202 -71.5t232 -74.5t142.5 -86t85.5 -112.5t29 -147.5zM597 652q-62 16 -117 36q-49 -40 -49 -120q0 -68 44.5 -103.5t214.5 -88.5l118 -34q56 44 56 120 q0 62 -55 101.5t-212 88.5z"/> +<glyph glyph-name="dieresis" horiz-adv-x="1013" unicode="¨" d="M244 1498q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM763 1498q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="copyright" horiz-adv-x="1608" unicode="©" d="M1116 596q0 -152 -87.5 -233t-247.5 -81t-254.5 106.5t-94.5 286.5v113q0 174 95.5 280.5t253.5 106.5q163 0 249.5 -82.5t86.5 -231.5h-156q0 96 -46 137.5t-134 41.5q-92 0 -142.5 -67.5t-51.5 -180.5v-123q0 -117 51 -184.5t143 -67.5q89 0 134 40.5t45 138.5h156z M207 729q0 -165 74.5 -308t211.5 -229.5t302 -86.5q164 0 300.5 86t211.5 229t75 309t-75 308.5t-212 228t-300 85.5q-159 0 -295.5 -82t-214.5 -226t-78 -314zM85 729q0 202 93.5 375t259 272.5t357.5 99.5t357.5 -99.5t259 -272.5t93.5 -375q0 -204 -95 -377.5 t-259.5 -272.5t-355.5 -99q-193 0 -357.5 100t-258.5 273t-94 376z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="904" unicode="ª" d="M600 705q-10 27 -17 68q-77 -82 -201 -82q-118 0 -183.5 61.5t-65.5 166.5q0 110 84 170.5t257 60.5h102v51q0 127 -116 127q-65 0 -101.5 -25.5t-36.5 -73.5l-173 14q0 104 87.5 168.5t223.5 64.5q135 0 213 -72t78 -205v-316q0 -97 26 -178h-177zM425 835q40 0 82 18.5 t69 43.5v136h-106q-76 -1 -119 -31t-43 -79q0 -88 117 -88z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="1054" unicode="«" d="M311 515l232 -399h-206l-272 390v19l272 390h206zM724 515l232 -399h-206l-272 390v19l272 390h206z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1124" unicode="¬" d="M960 374h-200v260h-635v171h835v-431z"/> +<glyph glyph-name="registered" horiz-adv-x="1608" unicode="®" d="M85 729q0 202 93.5 375t259 272.5t357.5 99.5t357.5 -99.5t259 -272.5t93.5 -375q0 -204 -95 -377.5t-259.5 -272.5t-355.5 -99q-193 0 -357.5 100t-258.5 273t-94 376zM207 729q0 -165 74.5 -308t211.5 -229.5t302 -86.5q164 0 300.5 86t211.5 229t75 309t-75 308.5 t-212 228t-300 85.5q-159 0 -295.5 -82t-214.5 -226t-78 -314zM651 653v-337h-151v850h281q154 0 239.5 -70t85.5 -194q0 -110 -107 -170q58 -32 81 -88t23 -138.5t3.5 -116.5t13.5 -57v-16h-155q-13 34 -13 194q0 76 -33 109.5t-110 33.5h-158zM651 787h128 q76 0 126.5 31.5t50.5 84.5q0 70 -35.5 99.5t-128.5 30.5h-141v-246z"/> +<glyph glyph-name="macron" horiz-adv-x="1065" unicode="¯" d="M895 1285h-734v173h734v-173z"/> +<glyph glyph-name="degree" horiz-adv-x="813" unicode="°" d="M125 1195q0 117 83.5 199t197.5 82q112 0 193.5 -82t81.5 -199q0 -116 -80.5 -196.5t-194.5 -80.5q-116 0 -198.5 80.5t-82.5 196.5zM406 1071q53 0 87 36t34 88t-34 90t-87 38t-89.5 -37.5t-36.5 -90.5t37.5 -88.5t88.5 -35.5z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1102" unicode="±" d="M688 974h312v-271h-312v-348h-294v348h-310v271h310v319h294v-319zM979 1h-878v264h878v-264z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="768" unicode="²" d="M697 667h-628v147l286 253q50 44 74.5 86.5t24.5 62.5q0 76 -85 76q-43 0 -68 -30t-25 -73h-225q0 118 85.5 198.5t221.5 80.5q154 0 237 -65t83 -187q0 -75 -42.5 -137.5t-187.5 -168.5l-81 -68h330v-175z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="768" unicode="³" d="M277 1140h88q101 0 101 82q0 32 -25.5 50.5t-70.5 18.5q-35 0 -62 -13t-27 -38h-224q0 102 85 164.5t221 62.5q154 0 240.5 -61.5t86.5 -165.5q0 -120 -138 -169q154 -41 154 -183q0 -104 -94 -168.5t-249 -64.5q-145 0 -233.5 69t-88.5 183h227q0 -29 29.5 -52.5 t81.5 -23.5q56 0 78.5 25t22.5 56q0 85 -109 86h-94v142z"/> +<glyph glyph-name="acute" horiz-adv-x="691" unicode="´" d="M287 1536h356l-278 -314h-275z"/> +<glyph glyph-name="uni00B5" horiz-adv-x="1313" unicode="µ" d="M470 1082v-632q1 -107 36.5 -157t126.5 -50q128 0 181 91v748h337v-1082h-317l-5 53q-89 -74 -210 -74q-85 0 -149 34v-429h-338v1498h338z"/> +<glyph glyph-name="paragraph" horiz-adv-x="1001" unicode="¶" d="M657 0v520h-80q-230 0 -362.5 127t-132.5 341q0 213 133 340.5t363 127.5h308v-1456h-229z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="657" unicode="·" d="M324 854q81 0 133.5 -48t52.5 -121t-52.5 -121t-133.5 -48q-80 0 -133 47.5t-53 121.5t53 121.5t133 47.5z"/> +<glyph glyph-name="cedilla" horiz-adv-x="569" unicode="¸" d="M373 10l-10 -61q150 -28 150 -173q0 -116 -99 -182t-275 -66l-7 186q88 0 88 77q0 38 -31.5 53t-102.5 20l31 146h256z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="768" unicode="¹" d="M542 667h-223v533l-176 -36v167l380 122h19v-786z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="938" unicode="º" d="M117 1121q0 160 95.5 257.5t250.5 97.5t251 -97t96 -263v-72q0 -159 -94 -256.5t-251 -97.5q-158 0 -253 98t-95 261v72zM292 1044q0 -98 46.5 -153t126.5 -55q78 0 123.5 54t46.5 151v80q0 97 -46.5 152t-125.5 55q-78 0 -124.5 -54.5t-46.5 -156.5v-73z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="1054" unicode="»" d="M284 914l272 -390v-19l-272 -390h-207l232 399l-232 400h207zM697 914l272 -390v-19l-272 -390h-207l232 399l-232 400h207z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1452" unicode="¼" d="M512 664h-223v533l-176 -36v167l380 122h19v-786zM462 117l-157 79l711 1138l157 -79zM1288 335h79v-178h-79v-157h-225v157h-333l-15 145l348 487h225v-454zM925 335h138v191l-16 -23z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1537" unicode="½" d="M422 117l-157 79l711 1138l157 -79zM488 672h-223v533l-176 -36v167l380 122h19v-786zM1470 0h-628v147l286 253q50 44 74.5 86.5t24.5 62.5q0 76 -85 76q-43 0 -68 -30t-25 -73h-225q0 118 85.5 198.5t221.5 80.5q154 0 237 -65t83 -187q0 -75 -42.5 -137.5 t-187.5 -168.5l-81 -68h330v-175z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1689" unicode="¾" d="M644 117l-157 79l711 1138l157 -79zM1486 335h79v-178h-79v-157h-225v157h-333l-15 145l348 487h225v-454zM1123 335h138v191l-16 -23zM321 1141h88q101 0 101 82q0 32 -25.5 50.5t-70.5 18.5q-35 0 -62 -13t-27 -38h-224q0 102 85 164.5t221 62.5q154 0 240.5 -61.5 t86.5 -165.5q0 -120 -138 -169q154 -41 154 -183q0 -104 -94 -168.5t-249 -64.5q-145 0 -233.5 69t-88.5 183h227q0 -29 29.5 -52.5t81.5 -23.5q56 0 78.5 25t22.5 56q0 85 -109 86h-94v142z"/> +<glyph glyph-name="questiondown" horiz-adv-x="1043" unicode="¿" d="M703 630q0 -150 -30.5 -230.5t-102.5 -141.5l-66 -61q-93 -90 -93 -186q0 -71 33.5 -103.5t86.5 -32.5q67 0 104.5 42.5t39.5 120.5h339q-4 -201 -127.5 -312t-347.5 -111q-223 0 -344.5 103.5t-121.5 292.5q0 83 38 156.5t130 159.5l85 78q77 66 86 153l5 72h286z M569 765q-80 0 -133.5 47.5t-53.5 121.5t53.5 121.5t133.5 47.5q82 0 134.5 -48.5t52.5 -120.5t-52.5 -120.5t-134.5 -48.5z"/> +<glyph glyph-name="AE" horiz-adv-x="1926" unicode="Æ" d="M1851 0h-897l-14 329h-382l-152 -329h-390l735 1456h1039v-264h-549l13 -316h455v-264h-444l15 -348h571v-264zM683 599h246l-21 486z"/> +<glyph glyph-name="multiply" horiz-adv-x="1083" unicode="×" d="M53 381l299 305l-299 306l193 183l293 -299l293 299l193 -183l-300 -306l300 -305l-193 -183l-293 298l-293 -298z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1409" unicode="Ø" d="M1354 698q0 -213 -79 -377t-224.5 -252.5t-331.5 -88.5q-162 0 -292 65l-81 -140h-207l141 245q-199 199 -199 556v51q0 215 78.5 378t224 252t333.5 89q157 0 287 -64l61 106h208l-121 -211q202 -200 202 -558v-51zM997 759q0 133 -29 229l-396 -689q60 -45 147 -45 q134 0 205.5 113t72.5 325v67zM437 698q0 -133 27 -227l394 687q-60 43 -141 43q-139 0 -209 -111t-71 -325v-67z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1266" unicode="Þ" d="M455 1456v-258h205q171 -1 296.5 -58t191.5 -161t66 -241q0 -209 -148.5 -333.5t-405.5 -126.5h-205v-278h-339v1456h339zM455 938v-400h198q103 0 162.5 52t59.5 146q0 95 -59 148.5t-161 53.5h-200z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1330" unicode="ß" d="M472 0h-338v1099q0 221 133.5 341.5t380.5 120.5q196 0 319 -104t123 -276q0 -107 -47.5 -183t-47.5 -163q0 -31 24.5 -64t108.5 -115q143 -139 143 -288q0 -187 -124.5 -287.5t-352.5 -100.5q-75 0 -150.5 13.5t-117.5 37.5l59 253q85 -44 211 -44q60 0 99.5 32.5 t39.5 92.5q0 41 -25 77t-105 105t-113.5 132.5t-33.5 137.5q0 103 47 187t47 163q0 59 -40 97t-101 38q-74 0 -106.5 -52t-32.5 -156v-1094z"/> +<glyph glyph-name="ae" horiz-adv-x="1730" unicode="æ" d="M1238 -20q-240 0 -380 134q-66 -66 -164 -100t-210 -34q-199 0 -311 91.5t-112 252.5q0 158 129.5 244t384.5 87h142v46q0 66 -34 103.5t-99 37.5q-72 0 -110 -29.5t-38 -72.5l-337 19q0 151 134 247t355 96q202 0 319 -91q126 93 320 91q212 0 335 -133t123 -360v-174 h-639q14 -98 75 -146.5t163 -48.5q126 0 223 40l62 27l81 -206q-67 -52 -181.5 -86.5t-230.5 -34.5zM548 212q89 0 169 63v176h-139q-78 -1 -129 -37t-51 -94q0 -108 150 -108zM1227 842q-82 0 -125.5 -48.5t-54.5 -147.5h309v26q0 81 -33 125.5t-96 44.5z"/> +<glyph glyph-name="eth" horiz-adv-x="1165" unicode="ð" d="M862 1308q261 -259 261 -658v-57q0 -177 -70.5 -318.5t-194.5 -218t-277 -76.5q-148 0 -267 63.5t-184.5 176t-65.5 248.5q0 233 120 363t334 130q127 0 228 -62q-49 139 -156 241l-178 -110l-78 118l136 84q-108 66 -244 103l108 244q236 -48 415 -176l163 101l77 -118z M585 240q94 0 147 82.5t53 234.5v97q-66 66 -194 66q-98 0 -143.5 -67.5t-45.5 -184.5q0 -102 50 -165t133 -63z"/> +<glyph glyph-name="divide" horiz-adv-x="1166" unicode="÷" d="M1103 563h-1044v244h1044v-244zM394 1086q0 71 51 117.5t135 46.5t135 -46.5t51 -117.5t-51 -117.5t-135 -46.5t-135 46.5t-51 117.5zM394 277q0 71 51 117.5t135 46.5t135 -46.5t51 -117.5t-51 -117.5t-135 -46.5t-135 46.5t-51 117.5z"/> +<glyph glyph-name="oslash" horiz-adv-x="1151" unicode="ø" d="M52 551q0 162 63 288.5t181 194.5t277 68q94 0 177 -25l69 142h177l-103 -212q203 -148 203 -477q0 -253 -140.5 -401.5t-380.5 -148.5q-93 0 -171 22l-71 -147h-177l104 215q-208 147 -208 481zM389 530q0 -96 18 -157l224 460q-26 9 -58 9q-169 0 -183 -251zM759 551 q0 85 -17 147l-219 -452q22 -6 52 -6q180 0 184 277v34z"/> +<glyph glyph-name="thorn" horiz-adv-x="1148" unicode="þ" d="M1096 533q0 -251 -112.5 -402t-306.5 -151q-150 0 -244 107v-503h-338v1952h338v-539q94 105 242 105q197 0 309 -145.5t112 -406.5v-17zM759 554q0 288 -168 288q-116 0 -158 -84v-431q43 -87 160 -87q161 0 166 276v38z"/> +<glyph glyph-name="dotlessi" horiz-adv-x="584" unicode="ı" d="M462 0h-339v1082h339v-1082z"/> +<glyph glyph-name="OE" horiz-adv-x="1994" unicode="Å’" d="M1918 0h-908q-167 -20 -288 -20q-183 0 -327 75t-223.5 211.5t-79.5 308.5v305q0 173 79 310t223 211.5t326 74.5q123 0 290 -20h910v-271h-654v-307h552v-261h-552v-347h652v-270zM722 240q101 0 193 12v951q-102 13 -195 13q-135 0 -212.5 -83t-77.5 -251v-306 q0 -168 78.5 -252t213.5 -84z"/> +<glyph glyph-name="oe" horiz-adv-x="1845" unicode="Å“" d="M75 551q0 164 63.5 289.5t181.5 193.5t277 68q218 0 357 -124q132 126 340 124q220 0 345 -131.5t125 -363.5v-172h-626q18 -93 77.5 -144t149.5 -51q127 0 222 36l76 31l80 -206q-71 -53 -185.5 -87t-238.5 -34q-216 0 -359 128q-138 -128 -361 -128q-231 0 -371.5 138 t-151.5 376zM412 530q0 -290 187 -290q180 0 185 275v36q0 291 -187 291q-170 0 -184 -251zM1294 842q-134 0 -157 -196h298v26q0 170 -141 170z"/> +<glyph glyph-name="circumflex" horiz-adv-x="1033" unicode="ˆ" d="M941 1255v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="ring" horiz-adv-x="674" unicode="Ëš" d="M118 1294q0 86 65.5 144.5t159.5 58.5q93 0 158.5 -58.5t65.5 -144.5q0 -85 -64.5 -142t-159.5 -57q-96 0 -160.5 57t-64.5 142zM343 1190q48 0 75.5 30t27.5 74t-27.5 75t-75.5 31q-49 0 -76.5 -31t-27.5 -75t27.5 -74t76.5 -30z"/> +<glyph glyph-name="tilde" horiz-adv-x="987" unicode="Ëœ" d="M885 1532q0 -114 -66.5 -193.5t-164.5 -79.5q-66 0 -147 42t-131 42q-32 0 -54.5 -22t-22.5 -68l-187 10q0 111 66.5 192t163.5 81q50 0 131 -36.5t102.5 -41.5t45.5 -5q32 0 55 22t23 68z"/> +<glyph glyph-name="endash" horiz-adv-x="1266" unicode="–" d="M1201.81 578h-1054.81v264h1054.81v-264z"/> +<glyph glyph-name="emdash" horiz-adv-x="1541" unicode="—" d="M1493.38 578h-1406.38v264h1406.38v-264z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="511" unicode="‘" d="M291 1576l148 -80q-82 -148 -85 -277v-177h-246v165q1 91 54 195.5t129 173.5z"/> +<glyph glyph-name="quoteright" horiz-adv-x="497" unicode="’" d="M214 1000l-148 80q83 144 85 282v174h246v-163q0 -93 -53.5 -198.5t-129.5 -174.5z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="556" unicode="‚" d="M231 -310l-148 80q72 125 74 280v199h258l-1 -190q-1 -91 -54 -195.5t-129 -173.5z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="875" unicode="“" d="M298 1576l148 -80q-82 -148 -85 -277v-177h-246v165q1 91 54 195.5t129 173.5zM649 1576l148 -80q-82 -148 -85 -277v-177h-246v165q1 91 54 195.5t129 173.5z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="881" unicode="â€" d="M228 1000l-148 80q83 144 85 282v174h246v-163q0 -93 -53.5 -198.5t-129.5 -174.5zM590 1000l-148 80q83 144 85 282v174h246v-163q0 -93 -53.5 -198.5t-129.5 -174.5z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="876" unicode="„" d="M242 -330l-159 80q72 134 74 299v220h258l-1 -207q0 -97 -48 -207.5t-124 -184.5zM593 -330l-160 80q82 153 85 297v222h259l-1 -213q-2 -96 -54 -204t-129 -182z"/> +<glyph glyph-name="bullet" horiz-adv-x="757" unicode="•" d="M134 763q0 107 70 174t182 67q115 0 184 -65t71 -171v-42q0 -107 -69 -172.5t-184 -65.5q-113 0 -182.5 64.5t-71.5 168.5v42z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="650" unicode="‹" d="M354 515l232 -399h-206l-272 390v19l272 390h206z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="620" unicode="›" d="M283 914l272 -390v-19l-272 -390h-207l232 399l-232 400h207z"/> +<glyph glyph-name="fraction" horiz-adv-x="902" unicode="â„" d="M172 109l-157 79l711 1138l157 -79z"/> +<glyph glyph-name="uni2074" horiz-adv-x="768" unicode="â´" d="M627 1002h79v-178h-79v-157h-225v157h-333l-15 145l348 487h225v-454zM264 1002h138v191l-16 -23z"/> +<glyph glyph-name="Euro" d="M914 508h-312q5 -132 71.5 -195t219.5 -63q99 0 176 30l43 -269q-133 -30 -263 -30q-270 0 -430.5 140t-168.5 387h-165v160h165v122h-165v159h168q19 248 186 387t441 139q106 0 232 -31l-43 -270q-78 31 -167 31q-138 0 -211 -62.5t-86 -193.5h309v-159h-312v-122h312 v-160z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1120" unicode="−" d="M1014 578h-879v264h879v-264z"/> +<glyph glyph-name="glyph162" d="M627 335h79v-178h-79v-157h-225v157h-333l-15 145l348 487h225v-454zM264 335h138v191l-16 -23z" horiz-adv-x="767"/> +<glyph glyph-name="glyph163" d="M277 474h88q101 0 101 82q0 32 -25.5 50.5t-70.5 18.5q-35 0 -62 -13t-27 -38h-224q0 102 85 164.5t221 62.5q154 0 240.5 -61.5t86.5 -165.5q0 -120 -138 -169q154 -41 154 -183q0 -104 -94 -168.5t-249 -64.5q-145 0 -233.5 69t-88.5 183h227q0 -29 29.5 -52.5 t81.5 -23.5q56 0 78.5 25t22.5 56q0 85 -109 86h-94v142z" horiz-adv-x="767"/> +<glyph glyph-name="glyph164" d="M697 0h-628v147l286 253q50 44 74.5 86.5t24.5 62.5q0 76 -85 76q-43 0 -68 -30t-25 -73h-225q0 118 85.5 198.5t221.5 80.5q154 0 237 -65t83 -187q0 -75 -42.5 -137.5t-187.5 -168.5l-81 -68h330v-175z" horiz-adv-x="767"/> +<glyph glyph-name="glyph165" d="M542 0h-223v533l-176 -36v167l380 122h19v-786z" horiz-adv-x="767"/> +<glyph glyph-name="uni00A0" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="921" unicode="Â" d="M753 497h-601v261h601v-261z"/> +<glyph glyph-name="Eth" horiz-adv-x="1354" unicode="Ã" d="M140 0v635h-170v191h170v630h469q193 0 347 -87.5t240.5 -247t87.5 -357.5v-67q0 -200 -84.5 -358.5t-238 -248t-342.5 -90.5h-479zM700 635h-209v-365h122q151 0 232 107.5t81 319.5v63q0 211 -81 318t-236 107h-118v-359h209v-191z"/> +<glyph glyph-name="Agrave" horiz-adv-x="1395" unicode="À" d="M937 272h-481l-84 -272h-375l534 1456h330l538 -1456h-377zM540 543h313l-157 505zM860 1532h-274l-282 314h356z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1395" unicode="Ã" d="M937 272h-481l-84 -272h-375l534 1456h330l538 -1456h-377zM540 543h313l-157 505zM742 1846h356l-278 -314h-275z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1395" unicode="Â" d="M937 272h-481l-84 -272h-375l534 1456h330l538 -1456h-377zM540 543h313l-157 505zM1124 1565v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1395" unicode="Ã" d="M937 272h-481l-84 -272h-375l534 1456h330l538 -1456h-377zM540 543h313l-157 505zM1085 1837q0 -114 -66.5 -193.5t-164.5 -79.5q-66 0 -147 42t-131 42q-32 0 -54.5 -22t-22.5 -68l-187 10q0 111 66.5 192t163.5 81q50 0 131 -36.5t102.5 -41.5t45.5 -5q32 0 55 22 t23 68z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1395" unicode="Ä" d="M937 272h-481l-84 -272h-375l534 1456h330l538 -1456h-377zM540 543h313l-157 505zM436 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM955 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39 t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="Aring" horiz-adv-x="1395" unicode="Ã…" d="M937 272h-481l-84 -272h-375l534 1456h330l538 -1456h-377zM540 543h313l-157 505zM477 1729q0 86 65.5 144.5t159.5 58.5q93 0 158.5 -58.5t65.5 -144.5q0 -85 -64.5 -142t-159.5 -57q-96 0 -160.5 57t-64.5 142zM702 1625q48 0 75.5 30t27.5 74t-27.5 75t-75.5 31 q-49 0 -76.5 -31t-27.5 -75t27.5 -74t76.5 -30z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1344" unicode="Ç" d="M1288 493q-7 -152 -82 -268.5t-210.5 -180.5t-309.5 -64q-287 0 -452 187t-165 528v72q0 214 74.5 374.5t214.5 248t324 87.5q265 0 426 -139.5t183 -384.5h-350q-4 133 -67 191t-192 58q-131 0 -192 -98t-64 -313v-103q0 -233 58.5 -333t201.5 -100q121 0 185 57t68 181 h349zM818 10l-10 -61q150 -28 150 -173q0 -116 -99 -182t-275 -66l-7 186q88 0 88 77q0 38 -31.5 53t-102.5 20l31 146h256z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1146" unicode="È" d="M1013 617h-552v-347h652v-270h-1003v1456h1005v-271h-654v-307h552v-261zM804 1532h-274l-282 314h356z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1146" unicode="É" d="M1013 617h-552v-347h652v-270h-1003v1456h1005v-271h-654v-307h552v-261zM686 1846h356l-278 -314h-275z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1146" unicode="Ê" d="M1013 617h-552v-347h652v-270h-1003v1456h1005v-271h-654v-307h552v-261zM1068 1565v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1146" unicode="Ë" d="M1013 617h-552v-347h652v-270h-1003v1456h1005v-271h-654v-307h552v-261zM380 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM899 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94 t43.5 94t107.5 39z"/> +<glyph glyph-name="Igrave" horiz-adv-x="618" unicode="ÃŒ" d="M484 0h-350v1456h350v-1456zM470 1532h-274l-282 314h356z"/> +<glyph glyph-name="Iacute" horiz-adv-x="618" unicode="Ã" d="M484 0h-350v1456h350v-1456zM351 1846h356l-278 -314h-275z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="618" unicode="ÃŽ" d="M484 0h-350v1456h350v-1456zM734 1565v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="618" unicode="Ã" d="M484 0h-350v1456h350v-1456zM46 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM565 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1438" unicode="Ñ" d="M1326 0h-349l-516 906v-906h-351v1456h351l515 -906v906h350v-1456zM1112 1837q0 -114 -66.5 -193.5t-164.5 -79.5q-66 0 -147 42t-131 42q-32 0 -54.5 -22t-22.5 -68l-187 10q0 111 66.5 192t163.5 81q50 0 131 -36.5t102.5 -41.5t45.5 -5q32 0 55 22t23 68z"/> +<glyph glyph-name="Ograve" horiz-adv-x="1414" unicode="Ã’" d="M1343 698q0 -213 -79 -377t-224.5 -252.5t-331.5 -88.5t-330 85.5t-224.5 244.5t-84.5 365v82q0 214 78.5 377.5t225 252.5t333.5 89q185 0 330 -88t225.5 -250.5t81.5 -372.5v-67zM986 759q0 217 -72.5 329.5t-207.5 112.5q-264 0 -279 -396l-1 -107q0 -214 71 -329 t211 -115q133 0 205 113t73 325v67zM865 1532h-274l-282 314h356z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1414" unicode="Ó" d="M1343 698q0 -213 -79 -377t-224.5 -252.5t-331.5 -88.5t-330 85.5t-224.5 244.5t-84.5 365v82q0 214 78.5 377.5t225 252.5t333.5 89q185 0 330 -88t225.5 -250.5t81.5 -372.5v-67zM986 759q0 217 -72.5 329.5t-207.5 112.5q-264 0 -279 -396l-1 -107q0 -214 71 -329 t211 -115q133 0 205 113t73 325v67zM747 1846h356l-278 -314h-275z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1414" unicode="Ô" d="M1343 698q0 -213 -79 -377t-224.5 -252.5t-331.5 -88.5t-330 85.5t-224.5 244.5t-84.5 365v82q0 214 78.5 377.5t225 252.5t333.5 89q185 0 330 -88t225.5 -250.5t81.5 -372.5v-67zM986 759q0 217 -72.5 329.5t-207.5 112.5q-264 0 -279 -396l-1 -107q0 -214 71 -329 t211 -115q133 0 205 113t73 325v67zM1129 1565v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1414" unicode="Õ" d="M1343 698q0 -213 -79 -377t-224.5 -252.5t-331.5 -88.5t-330 85.5t-224.5 244.5t-84.5 365v82q0 214 78.5 377.5t225 252.5t333.5 89q185 0 330 -88t225.5 -250.5t81.5 -372.5v-67zM986 759q0 217 -72.5 329.5t-207.5 112.5q-264 0 -279 -396l-1 -107q0 -214 71 -329 t211 -115q133 0 205 113t73 325v67zM1090 1837q0 -114 -66.5 -193.5t-164.5 -79.5q-66 0 -147 42t-131 42q-32 0 -54.5 -22t-22.5 -68l-187 10q0 111 66.5 192t163.5 81q50 0 131 -36.5t102.5 -41.5t45.5 -5q32 0 55 22t23 68z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1414" unicode="Ö" d="M1343 698q0 -213 -79 -377t-224.5 -252.5t-331.5 -88.5t-330 85.5t-224.5 244.5t-84.5 365v82q0 214 78.5 377.5t225 252.5t333.5 89q185 0 330 -88t225.5 -250.5t81.5 -372.5v-67zM986 759q0 217 -72.5 329.5t-207.5 112.5q-264 0 -279 -396l-1 -107q0 -214 71 -329 t211 -115q133 0 205 113t73 325v67zM441 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM960 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1361" unicode="Ù" d="M1252 1456v-953q0 -162 -69 -280.5t-198 -180.5t-305 -62q-266 0 -419 138t-156 378v960h353v-967q6 -239 222 -239q109 0 165 60t56 195v951h351zM835 1532h-274l-282 314h356z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1361" unicode="Ú" d="M1252 1456v-953q0 -162 -69 -280.5t-198 -180.5t-305 -62q-266 0 -419 138t-156 378v960h353v-967q6 -239 222 -239q109 0 165 60t56 195v951h351zM717 1846h356l-278 -314h-275z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1361" unicode="Û" d="M1252 1456v-953q0 -162 -69 -280.5t-198 -180.5t-305 -62q-266 0 -419 138t-156 378v960h353v-967q6 -239 222 -239q109 0 165 60t56 195v951h351zM1099 1565v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="Udieresis" horiz-adv-x="1361" unicode="Ü" d="M1252 1456v-953q0 -162 -69 -280.5t-198 -180.5t-305 -62q-266 0 -419 138t-156 378v960h353v-967q6 -239 222 -239q109 0 165 60t56 195v951h351zM411 1808q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM930 1808 q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1286" unicode="Ã" d="M643 824l268 632h379l-469 -933v-523h-356v523l-468 933h377zM686 1846h356l-278 -314h-275z"/> +<glyph glyph-name="agrave" horiz-adv-x="1087" unicode="à " d="M704 0q-18 33 -32 97q-93 -117 -260 -117q-153 0 -260 92.5t-107 232.5q0 176 130 266t378 90h104v57q0 149 -129 149q-120 0 -120 -118h-337q0 157 133.5 255t340.5 98t327 -101t123 -277v-479q2 -149 46 -228v-17h-337zM493 220q63 0 104.5 27t59.5 61v173h-98 q-176 0 -176 -158q0 -46 31 -74.5t79 -28.5zM695 1222h-274l-282 314h356z"/> +<glyph glyph-name="aacute" horiz-adv-x="1087" unicode="á" d="M704 0q-18 33 -32 97q-93 -117 -260 -117q-153 0 -260 92.5t-107 232.5q0 176 130 266t378 90h104v57q0 149 -129 149q-120 0 -120 -118h-337q0 157 133.5 255t340.5 98t327 -101t123 -277v-479q2 -149 46 -228v-17h-337zM493 220q63 0 104.5 27t59.5 61v173h-98 q-176 0 -176 -158q0 -46 31 -74.5t79 -28.5zM577 1536h356l-278 -314h-275z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1087" unicode="â" d="M704 0q-18 33 -32 97q-93 -117 -260 -117q-153 0 -260 92.5t-107 232.5q0 176 130 266t378 90h104v57q0 149 -129 149q-120 0 -120 -118h-337q0 157 133.5 255t340.5 98t327 -101t123 -277v-479q2 -149 46 -228v-17h-337zM493 220q63 0 104.5 27t59.5 61v173h-98 q-176 0 -176 -158q0 -46 31 -74.5t79 -28.5zM959 1255v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="atilde" horiz-adv-x="1087" unicode="ã" d="M704 0q-18 33 -32 97q-93 -117 -260 -117q-153 0 -260 92.5t-107 232.5q0 176 130 266t378 90h104v57q0 149 -129 149q-120 0 -120 -118h-337q0 157 133.5 255t340.5 98t327 -101t123 -277v-479q2 -149 46 -228v-17h-337zM493 220q63 0 104.5 27t59.5 61v173h-98 q-176 0 -176 -158q0 -46 31 -74.5t79 -28.5zM920 1528q0 -114 -66.5 -193.5t-164.5 -79.5q-66 0 -147 42t-131 42q-32 0 -54.5 -22t-22.5 -68l-187 10q0 111 66.5 192t163.5 81q50 0 131 -36.5t102.5 -41.5t45.5 -5q32 0 55 22t23 68z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1087" unicode="ä" d="M704 0q-18 33 -32 97q-93 -117 -260 -117q-153 0 -260 92.5t-107 232.5q0 176 130 266t378 90h104v57q0 149 -129 149q-120 0 -120 -118h-337q0 157 133.5 255t340.5 98t327 -101t123 -277v-479q2 -149 46 -228v-17h-337zM493 220q63 0 104.5 27t59.5 61v173h-98 q-176 0 -176 -158q0 -46 31 -74.5t79 -28.5zM271 1498q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM790 1498q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="aring" horiz-adv-x="1087" unicode="Ã¥" d="M704 0q-18 33 -32 97q-93 -117 -260 -117q-153 0 -260 92.5t-107 232.5q0 176 130 266t378 90h104v57q0 149 -129 149q-120 0 -120 -118h-337q0 157 133.5 255t340.5 98t327 -101t123 -277v-479q2 -149 46 -228v-17h-337zM493 220q63 0 104.5 27t59.5 61v173h-98 q-176 0 -176 -158q0 -46 31 -74.5t79 -28.5zM312 1419q0 86 65.5 144.5t159.5 58.5q93 0 158.5 -58.5t65.5 -144.5q0 -85 -64.5 -142t-159.5 -57q-96 0 -160.5 57t-64.5 142zM537 1315q48 0 75.5 30t27.5 74t-27.5 75t-75.5 31q-49 0 -76.5 -31t-27.5 -75t27.5 -74t76.5 -30 z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1064" unicode="ç" d="M552 240q71 0 110 38.5t38 107.5h316q0 -178 -127.5 -292t-328.5 -114q-236 0 -372 148t-136 410v14q0 164 60.5 289.5t174.5 193t270 67.5q211 0 335 -117t124 -317h-316q0 84 -41 129t-110 45q-131 0 -153 -167q-7 -53 -7 -146q0 -163 39 -226t124 -63zM698 10l-10 -61 q150 -28 150 -173q0 -116 -99 -182t-275 -66l-7 186q88 0 88 77q0 38 -31.5 53t-102.5 20l31 146h256z"/> +<glyph glyph-name="egrave" horiz-adv-x="1115" unicode="è" d="M618 -20q-249 0 -403 148.5t-154 386.5v28q0 166 61.5 293t179.5 196.5t280 69.5q228 0 360 -141.5t132 -394.5v-131h-670q18 -91 79 -143t158 -52q160 0 250 112l154 -182q-63 -87 -178.5 -138.5t-248.5 -51.5zM580 842q-148 0 -176 -196h340v26q2 81 -41 125.5 t-123 44.5zM694 1223h-274l-282 314h356z"/> +<glyph glyph-name="eacute" horiz-adv-x="1115" unicode="é" d="M618 -20q-249 0 -403 148.5t-154 386.5v28q0 166 61.5 293t179.5 196.5t280 69.5q228 0 360 -141.5t132 -394.5v-131h-670q18 -91 79 -143t158 -52q160 0 250 112l154 -182q-63 -87 -178.5 -138.5t-248.5 -51.5zM580 842q-148 0 -176 -196h340v26q2 81 -41 125.5 t-123 44.5zM576 1537h356l-278 -314h-275z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1115" unicode="ê" d="M618 -20q-249 0 -403 148.5t-154 386.5v28q0 166 61.5 293t179.5 196.5t280 69.5q228 0 360 -141.5t132 -394.5v-131h-670q18 -91 79 -143t158 -52q160 0 250 112l154 -182q-63 -87 -178.5 -138.5t-248.5 -51.5zM580 842q-148 0 -176 -196h340v26q2 81 -41 125.5 t-123 44.5zM958 1256v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1115" unicode="ë" d="M618 -20q-249 0 -403 148.5t-154 386.5v28q0 166 61.5 293t179.5 196.5t280 69.5q228 0 360 -141.5t132 -394.5v-131h-670q18 -91 79 -143t158 -52q160 0 250 112l154 -182q-63 -87 -178.5 -138.5t-248.5 -51.5zM580 842q-148 0 -176 -196h340v26q2 81 -41 125.5 t-123 44.5zM270 1499q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM789 1499q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="igrave" horiz-adv-x="584" unicode="ì" d="M462 0h-339v1082h339v-1082zM455 1202h-274l-282 314h356z"/> +<glyph glyph-name="iacute" horiz-adv-x="584" unicode="Ã" d="M462 0h-339v1082h339v-1082zM336 1516h356l-278 -314h-275z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="584" unicode="î" d="M462 0h-339v1082h339v-1082zM719 1235v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="idieresis" horiz-adv-x="584" unicode="ï" d="M462 0h-339v1082h339v-1082zM31 1478q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM550 1478q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="ntilde" horiz-adv-x="1155" unicode="ñ" d="M404 1082l11 -127q112 147 309 147q169 0 252.5 -101t86.5 -304v-697h-338v683q0 82 -33 120.5t-120 38.5q-99 0 -147 -78v-764h-337v1082h316zM963 1528q0 -114 -66.5 -193.5t-164.5 -79.5q-66 0 -147 42t-131 42q-32 0 -54.5 -22t-22.5 -68l-187 10q0 111 66.5 192 t163.5 81q50 0 131 -36.5t102.5 -41.5t45.5 -5q32 0 55 22t23 68z"/> +<glyph glyph-name="ograve" horiz-adv-x="1150" unicode="ò" d="M52 551q0 162 63 288.5t181 194.5t277 68q243 0 383 -150.5t140 -409.5v-12q0 -253 -140.5 -401.5t-380.5 -148.5q-231 0 -371 138.5t-151 375.5zM389 530q0 -150 47 -220t139 -70q180 0 184 277v34q0 291 -186 291q-169 0 -183 -251zM737 1222h-274l-282 314h356z"/> +<glyph glyph-name="oacute" horiz-adv-x="1150" unicode="ó" d="M52 551q0 162 63 288.5t181 194.5t277 68q243 0 383 -150.5t140 -409.5v-12q0 -253 -140.5 -401.5t-380.5 -148.5q-231 0 -371 138.5t-151 375.5zM389 530q0 -150 47 -220t139 -70q180 0 184 277v34q0 291 -186 291q-169 0 -183 -251zM619 1536h356l-278 -314h-275z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1150" unicode="ô" d="M52 551q0 162 63 288.5t181 194.5t277 68q243 0 383 -150.5t140 -409.5v-12q0 -253 -140.5 -401.5t-380.5 -148.5q-231 0 -371 138.5t-151 375.5zM389 530q0 -150 47 -220t139 -70q180 0 184 277v34q0 291 -186 291q-169 0 -183 -251zM1001 1255v-13h-266l-159 136 l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="otilde" horiz-adv-x="1150" unicode="õ" d="M52 551q0 162 63 288.5t181 194.5t277 68q243 0 383 -150.5t140 -409.5v-12q0 -253 -140.5 -401.5t-380.5 -148.5q-231 0 -371 138.5t-151 375.5zM389 530q0 -150 47 -220t139 -70q180 0 184 277v34q0 291 -186 291q-169 0 -183 -251zM962 1528q0 -114 -66.5 -193.5 t-164.5 -79.5q-66 0 -147 42t-131 42q-32 0 -54.5 -22t-22.5 -68l-187 10q0 111 66.5 192t163.5 81q50 0 131 -36.5t102.5 -41.5t45.5 -5q32 0 55 22t23 68z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1150" unicode="ö" d="M52 551q0 162 63 288.5t181 194.5t277 68q243 0 383 -150.5t140 -409.5v-12q0 -253 -140.5 -401.5t-380.5 -148.5q-231 0 -371 138.5t-151 375.5zM389 530q0 -150 47 -220t139 -70q180 0 184 277v34q0 291 -186 291q-169 0 -183 -251zM313 1498q63 0 106.5 -39t43.5 -94 t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM832 1498q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="ugrave" horiz-adv-x="1155" unicode="ù" d="M739 117q-107 -137 -289 -137q-178 0 -269.5 103.5t-91.5 297.5v701h337v-703q0 -139 135 -139q116 0 165 83v759h339v-1082h-316zM737 1222h-274l-282 314h356z"/> +<glyph glyph-name="uacute" horiz-adv-x="1155" unicode="ú" d="M739 117q-107 -137 -289 -137q-178 0 -269.5 103.5t-91.5 297.5v701h337v-703q0 -139 135 -139q116 0 165 83v759h339v-1082h-316zM619 1536h356l-278 -314h-275z"/> +<glyph glyph-name="ucircumflex" horiz-adv-x="1155" unicode="û" d="M739 117q-107 -137 -289 -137q-178 0 -269.5 103.5t-91.5 297.5v701h337v-703q0 -139 135 -139q116 0 165 83v759h339v-1082h-316zM1001 1255v-13h-266l-159 136l-159 -136h-260v17l323 277h193z"/> +<glyph glyph-name="udieresis" horiz-adv-x="1155" unicode="ü" d="M739 117q-107 -137 -289 -137q-178 0 -269.5 103.5t-91.5 297.5v701h337v-703q0 -139 135 -139q116 0 165 83v759h339v-1082h-316zM313 1498q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM832 1498q63 0 106.5 -39 t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +<glyph glyph-name="yacute" horiz-adv-x="1061" unicode="ý" d="M527 472l180 610h361l-441 -1263l-19 -46q-94 -210 -332 -210q-66 0 -139 20v241h44q71 0 108.5 20.5t55.5 73.5l27 72l-376 1092h360zM571 1536h356l-278 -314h-275z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="1061" unicode="ÿ" d="M527 472l180 610h361l-441 -1263l-19 -46q-94 -210 -332 -210q-66 0 -139 20v241h44q71 0 108.5 20.5t55.5 73.5l27 72l-376 1092h360zM265 1498q63 0 106.5 -39t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39zM784 1498q63 0 106.5 -39 t43.5 -94t-43.5 -94t-106.5 -39q-64 0 -107.5 39t-43.5 94t43.5 94t107.5 39z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.ttf b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bd7cde8592987b916f17a1eac3908f25ac33cfcf Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff new file mode 100644 index 0000000000000000000000000000000000000000..aca865b3d02c1e00c711fda40f9ee9a74d8eda7b Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff2 b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..9c7d849071ae0f6faa38edf990f410b392d82a04 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Black/RobotoDraft-Black.woff2 differ diff --git a/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.eot b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.eot new file mode 100644 index 0000000000000000000000000000000000000000..4b5fe00406bdbb1970d66a73fc3d25b6e2d8ee53 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.svg b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.svg new file mode 100644 index 0000000000000000000000000000000000000000..8e75916cfa47fb2c7b5ee1c771628389f46cf4c0 --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.svg @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-Bold" horiz-adv-x="1175"> +<font-face underline-position="-100" font-weight="700" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-102 -463 1876 1935" x-height="1082" underline-thickness="100" font-family="RobotoDraft" ascent="1536" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1246" unicode="fi" d="M181 0v870h-161v212h161v50q2 204 125.5 314.5t348.5 110.5q135 0 328 -59l-42 -239q-98 29 -152 37.5t-116 8.5q-202 0 -202 -179v-44h213v-212h-213v-870h-290zM1118 0h-290v1082h290v-1082z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1255" unicode="fl" d="M836 1312q-86 10 -160 10q-196 0 -196 -167v-73h215v-212h-215v-870h-290v870h-161v212h161v84q2 188 118 289.5t328 101.5q151 0 490 -32v-1525h-290v1312z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="uni0000" horiz-adv-x="0"/> +<glyph glyph-name="glyph2" horiz-adv-x="0"/> +<glyph glyph-name="uni000D" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="557" unicode="!" d="M405 447h-240l-34 1009h308zM285 289q73 0 117.5 -43t44.5 -110q0 -66 -44.5 -109t-117.5 -43q-72 0 -116.5 43t-44.5 109t44.5 109.5t116.5 43.5z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="657" unicode='"' d="M266 1398l-40 -411h-162v549h202v-138zM591 1398l-39 -411h-162v549h201v-138z"/> +<glyph glyph-name="numbersign" horiz-adv-x="1220" unicode="#" d="M667 410h-193l-72 -410h-183l72 410h-227v172h257l50 284h-232v174h263l73 416h182l-73 -416h194l73 416h183l-73 -416h219v-174h-250l-50 -284h224v-172h-254l-72 -410h-183zM504 582h193l50 284h-194z"/> +<glyph glyph-name="dollar" d="M790 383q0 82 -45.5 130.5t-154.5 89.5t-188 81.5t-135.5 93t-88 123.5t-31.5 169q0 169 108 277t287 126v214h160v-217q177 -25 277 -147.5t100 -317.5h-289q0 120 -49.5 179.5t-132.5 59.5q-82 0 -127 -46.5t-45 -128.5q0 -76 44 -122t163.5 -94t196.5 -90.5t130 -96 t81 -122t28 -159.5q0 -170 -106 -276t-292 -125v-199h-159v198q-205 22 -317.5 145.5t-112.5 328.5h289q0 -119 56.5 -182.5t162.5 -63.5q88 0 139 46.5t51 125.5z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1512" unicode="%" d="M95 1176q0 134 87 217.5t228 83.5q143 0 230 -82.5t87 -223.5v-72q0 -135 -87 -217t-228 -82q-142 0 -229.5 82.5t-87.5 222.5v71zM287 1099q0 -60 34.5 -96.5t90.5 -36.5t89 37t33 99v74q0 60 -33 97t-91 37q-55 0 -89 -36.5t-34 -101.5v-73zM791 357q0 135 88 217.5 t228 82.5q142 0 229.5 -81.5t87.5 -224.5v-72q0 -134 -86 -216.5t-229 -82.5q-144 0 -231 83t-87 220v74zM983 279q0 -55 36 -94t90 -39q122 0 122 135v76q0 60 -34 96.5t-90 36.5t-90 -36.5t-34 -99.5v-75zM469 109l-141 76l711 1138l141 -76z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1344" unicode="&" d="M71 392q0 101 56.5 187t207.5 191q-65 87 -102 163.5t-37 159.5q0 170 107.5 276.5t289.5 106.5q163 0 267.5 -97t104.5 -242q0 -174 -176 -307l-112 -81l251 -292q59 116 59 256h246q0 -284 -131 -460l218 -253h-328l-75 86q-161 -106 -370 -106q-216 0 -346 113.5 t-130 298.5zM561 212q104 0 197 58l-287 332l-21 -15q-89 -76 -89 -179q0 -87 55.5 -141.5t144.5 -54.5zM455 1097q0 -75 88 -189l77 51q59 38 81.5 74t22.5 86t-37 87t-95 37q-62 0 -99.5 -40t-37.5 -106z"/> +<glyph glyph-name="quotesingle" horiz-adv-x="331" unicode="'" d="M275 1389l-29 -404h-183v551h212v-147z"/> +<glyph glyph-name="parenleft" horiz-adv-x="719" unicode="(" d="M124 592q0 229 61 436t180 366.5t258 221.5l56 -156q-146 -108 -228 -334t-82 -528v-31q0 -303 81 -530t229 -339l-56 -153q-136 61 -253.5 215.5t-179.5 356.5t-66 422v53z"/> +<glyph glyph-name="parenright" horiz-adv-x="722" unicode=")" d="M609 569q0 -226 -65 -435t-187 -369t-261 -220l-56 153q142 107 224 330t85 513v53q0 299 -81.5 527t-227.5 342l56 153q136 -59 256.5 -214t187 -361t69.5 -427v-45z"/> +<glyph glyph-name="asterisk" horiz-adv-x="928" unicode="*" d="M341 962l-314 89l59 181l311 -125l-20 349h196l-20 -356l303 123l59 -183l-320 -89l210 -266l-159 -113l-182 292l-180 -282l-159 108z"/> +<glyph glyph-name="plus" horiz-adv-x="1118" unicode="+" d="M694 815h361v-261h-361v-408h-275v408h-362v261h362v391h275v-391z"/> +<glyph glyph-name="comma" horiz-adv-x="500" unicode="," d="M186 -365l-151 79l36 65q67 122 69 243v224h244l-1 -200q-1 -111 -56 -224t-141 -187z"/> +<glyph glyph-name="hyphen" horiz-adv-x="794" unicode="-" d="M673 507h-563v233h563v-233z"/> +<glyph glyph-name="period" horiz-adv-x="595" unicode="." d="M126 142q0 69 46.5 112t116.5 43q71 0 117.5 -43t46.5 -112q0 -68 -46 -110.5t-118 -42.5q-71 0 -117 42.5t-46 110.5z"/> +<glyph glyph-name="slash" horiz-adv-x="765" unicode="/" d="M202 -125h-215l536 1581h215z"/> +<glyph glyph-name="zero" d="M1079 602q0 -302 -125 -462t-366 -160q-238 0 -364 157t-129 450v268q0 305 126.5 463t364.5 158t364 -156.5t129 -449.5v-268zM790 896q0 181 -49.5 263.5t-154.5 82.5q-102 0 -150.5 -78.5t-51.5 -245.5v-354q0 -178 48.5 -264.5t155.5 -86.5q106 0 153 83t49 254v346z " unicode="0"/> +<glyph glyph-name="one" d="M801 0h-289v1114l-345 -107v235l603 216h31v-1458z" unicode="1"/> +<glyph glyph-name="two" d="M1097 0h-998v198l471 502q97 106 143.5 185t46.5 150q0 97 -49 152.5t-140 55.5q-98 0 -154.5 -67.5t-56.5 -177.5h-290q0 133 63.5 243t179.5 172.5t263 62.5q225 0 349.5 -108t124.5 -305q0 -108 -56 -220t-192 -261l-331 -349h626v-233z" unicode="2"/> +<glyph glyph-name="three" d="M393 856h154q110 0 163 55t53 146q0 88 -52.5 137t-144.5 49q-83 0 -139 -45.5t-56 -118.5h-289q0 114 61.5 204.5t172 141.5t243.5 51q231 0 362 -110.5t131 -304.5q0 -100 -61 -184t-160 -129q123 -44 183.5 -132t60.5 -208q0 -194 -141.5 -311t-374.5 -117 q-218 0 -356.5 115t-138.5 304h289q0 -82 61.5 -134t151.5 -52q103 0 161.5 54.5t58.5 144.5q0 218 -240 218h-153v226z" unicode="3"/> +<glyph glyph-name="four" d="M954 548h165v-233h-165v-315h-289v315h-597l-13 182l607 959h292v-908zM343 548h322v514l-19 -33z" unicode="4"/> +<glyph glyph-name="five" d="M142 716l84 740h816v-241h-579l-36 -313q103 55 219 55q208 0 326 -129t118 -361q0 -141 -59.5 -252.5t-170.5 -173t-262 -61.5q-132 0 -245 53.5t-178.5 150.5t-69.5 221h286q9 -91 63.5 -141.5t142.5 -50.5q98 0 151 70.5t53 199.5q0 124 -61 190t-173 66 q-103 0 -167 -54l-28 -26z" unicode="5"/> +<glyph glyph-name="six" d="M883 1471v-238h-28q-196 -3 -315.5 -102t-143.5 -275q116 118 293 118q190 0 302 -136t112 -358q0 -142 -61.5 -257t-174 -179t-254.5 -64q-230 0 -371.5 160t-141.5 427v104q0 237 89.5 418.5t257 281t388.5 100.5h48zM601 742q-70 0 -127 -36.5t-84 -96.5v-88 q0 -145 57 -226.5t160 -81.5q93 0 150.5 73.5t57.5 190.5q0 119 -58 192t-156 73z" unicode="6"/> +<glyph glyph-name="seven" d="M1089 1294l-563 -1294h-305l564 1222h-724v234h1028v-162z" unicode="7"/> +<glyph glyph-name="eight" d="M1048 1069q0 -106 -53 -188t-146 -131q106 -51 168 -140.5t62 -210.5q0 -194 -132 -306.5t-359 -112.5t-360 113t-133 306q0 121 62 211t167 140q-93 49 -145.5 131t-52.5 188q0 186 124 296.5t337 110.5q212 0 336.5 -109.5t124.5 -297.5zM789 420q0 95 -55 152t-148 57 q-92 0 -147 -56.5t-55 -152.5q0 -93 54 -150t150 -57q94 0 147.5 55t53.5 152zM759 1055q0 85 -45 136.5t-127 51.5q-81 0 -126 -50t-45 -138q0 -87 45 -140t127 -53t126.5 53t44.5 140z" unicode="8"/> +<glyph glyph-name="nine" d="M775 582q-113 -111 -264 -111q-193 0 -309 132.5t-116 357.5q0 143 62.5 262.5t174.5 186t252 66.5q144 0 256 -72t174 -207t63 -309v-107q0 -364 -181 -572t-513 -222l-71 -1v241l64 1q377 17 408 354zM582 692q70 0 120.5 36t76.5 87v119q0 147 -56 228t-150 81 q-87 0 -143 -79.5t-56 -199.5q0 -119 54.5 -195.5t153.5 -76.5z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="578" unicode=":" d="M125 142q0 69 46.5 112t116.5 43q71 0 117.5 -43t46.5 -112q0 -68 -46 -110.5t-118 -42.5q-71 0 -117 42.5t-46 110.5zM125 961q0 69 46.5 112t116.5 43q71 0 117.5 -43t46.5 -112q0 -68 -46 -110.5t-118 -42.5q-71 0 -117 42.5t-46 110.5z"/> +<glyph glyph-name="semicolon" horiz-adv-x="537" unicode=";" d="M108 961q0 69 46.5 112t116.5 43q71 0 117.5 -43t46.5 -112q0 -68 -46 -110.5t-118 -42.5q-71 0 -117 42.5t-46 110.5zM208 -365l-151 79l36 65q67 122 69 243v224h244l-1 -200q-1 -111 -56 -224t-141 -187z"/> +<glyph glyph-name="less" horiz-adv-x="1042" unicode="<" d="M345 618l570 -201v-280l-861 365v236l861 365v-280z"/> +<glyph glyph-name="equal" horiz-adv-x="1172" unicode="=" d="M1030 746h-894v236h894v-236zM1030 313h-894v236h894v-236z"/> +<glyph glyph-name="greater" horiz-adv-x="1058" unicode=">" d="M701 621l-581 203v278l871 -365v-235l-871 -366v279z"/> +<glyph glyph-name="question" horiz-adv-x="1019" unicode="?" d="M347 447q0 140 34 223t124.5 163.5t120.5 131t30 106.5q0 169 -156 169q-74 0 -118.5 -45.5t-46.5 -125.5h-290q2 191 123.5 299t331.5 108q212 0 329 -102.5t117 -289.5q0 -85 -38 -160.5t-133 -167.5l-81 -77q-76 -73 -87 -171l-4 -61h-256zM318 140q0 67 45.5 110.5 t116.5 43.5t116.5 -43.5t45.5 -110.5q0 -66 -44.5 -109t-117.5 -43t-117.5 43t-44.5 109z"/> +<glyph glyph-name="at" horiz-adv-x="1833" unicode="@" d="M1749 536q-11 -256 -126.5 -406.5t-310.5 -150.5q-86 0 -148.5 37t-94.5 106q-100 -140 -261 -140q-146 0 -226 123t-60 325q18 165 83.5 293.5t165.5 197.5t216 69q143 0 244 -66l63 -43l-51 -578q-10 -79 17.5 -121t87.5 -42q92 0 154 107.5t68 281.5 q17 349 -140.5 536.5t-466.5 187.5q-193 0 -344 -98t-238 -278.5t-98 -413.5q-16 -354 142 -547.5t473 -193.5q83 0 174 18.5t157 49.5l38 -154q-61 -40 -164.5 -64.5t-208.5 -24.5q-264 0 -450 106.5t-277.5 314t-79.5 495.5q12 276 126 495t310.5 338.5t443.5 119.5 q251 0 432 -107.5t271 -307.5t79 -465zM744 430q-11 -132 23 -200.5t110 -68.5q49 0 93 43t73 124l42 473q-39 13 -80 13q-115 0 -178.5 -98t-82.5 -286z"/> +<glyph glyph-name="A" horiz-adv-x="1378" unicode="A" d="M952 300h-526l-100 -300h-319l542 1456h278l545 -1456h-319zM507 543h364l-183 545z"/> +<glyph glyph-name="B" horiz-adv-x="1307" unicode="B" d="M130 0v1456h510q265 0 402 -101.5t137 -297.5q0 -107 -55 -188.5t-153 -119.5q112 -28 176.5 -113t64.5 -208q0 -210 -134 -318t-382 -110h-566zM430 634v-393h257q106 0 165.5 50.5t59.5 139.5q0 200 -207 203h-275zM430 846h222q227 4 227 181q0 99 -57.5 142.5 t-181.5 43.5h-210v-367z"/> +<glyph glyph-name="C" horiz-adv-x="1340" unicode="C" d="M1273 485q-17 -235 -173.5 -370t-412.5 -135q-280 0 -440.5 188.5t-160.5 517.5v89q0 210 74 370t211.5 245.5t319.5 85.5q252 0 406 -135t178 -379h-300q-11 141 -78.5 204.5t-205.5 63.5q-150 0 -224.5 -107.5t-76.5 -333.5v-110q0 -236 71.5 -345t225.5 -109 q139 0 207.5 63.5t78.5 196.5h300z"/> +<glyph glyph-name="D" horiz-adv-x="1331" unicode="D" d="M130 0v1456h448q192 0 343.5 -86.5t236.5 -246t85 -362.5v-67q0 -203 -83.5 -361t-235.5 -245t-343 -88h-451zM430 1213v-972h145q176 0 269 115t95 329v77q0 222 -92 336.5t-269 114.5h-148z"/> +<glyph glyph-name="E" horiz-adv-x="1152" unicode="E" d="M1006 631h-576v-390h676v-241h-976v1456h974v-243h-674v-347h576v-235z"/> +<glyph glyph-name="F" horiz-adv-x="1122" unicode="F" d="M1006 595h-576v-595h-300v1456h948v-243h-648v-376h576v-242z"/> +<glyph glyph-name="G" horiz-adv-x="1395" unicode="G" d="M1282 184q-81 -97 -229 -150.5t-328 -53.5q-189 0 -331.5 82.5t-220 239.5t-79.5 369v99q0 218 73.5 377.5t212 244t324.5 84.5q259 0 405 -123.5t173 -359.5h-292q-20 125 -88.5 183t-188.5 58q-153 0 -233 -115t-81 -342v-93q0 -229 87 -346t255 -117q169 0 241 72v251 h-273v221h573v-581z"/> +<glyph glyph-name="H" horiz-adv-x="1447" unicode="H" d="M1315 0h-300v624h-585v-624h-300v1456h300v-590h585v590h300v-1456z"/> +<glyph glyph-name="I" horiz-adv-x="597" unicode="I" d="M449 0h-300v1456h300v-1456z"/> +<glyph glyph-name="J" horiz-adv-x="1144" unicode="J" d="M717 1456h300v-1008q0 -139 -61.5 -245.5t-173.5 -164.5t-253 -58q-231 0 -360 117.5t-129 332.5h302q0 -107 45 -158t142 -51q86 0 137 59t51 168v1008z"/> +<glyph glyph-name="K" horiz-adv-x="1300" unicode="K" d="M586 584l-156 -168v-416h-300v1456h300v-660l132 181l371 479h369l-517 -647l532 -809h-357z"/> +<glyph glyph-name="L" horiz-adv-x="1109" unicode="L" d="M430 241h637v-241h-937v1456h300v-1215z"/> +<glyph glyph-name="M" horiz-adv-x="1794" unicode="M" d="M522 1456l374 -1056l372 1056h394v-1456h-301v398l30 687l-393 -1085h-206l-392 1084l30 -686v-398h-300v1456h392z"/> +<glyph glyph-name="N" horiz-adv-x="1446" unicode="N" d="M1314 0h-300l-584 958v-958h-300v1456h300l585 -960v960h299v-1456z"/> +<glyph glyph-name="O" horiz-adv-x="1414" unicode="O" d="M1326 695q0 -215 -76 -377t-217.5 -250t-324.5 -88q-181 0 -323 87t-220 248.5t-79 371.5v72q0 215 77.5 378.5t219 251t323.5 87.5t323.5 -87.5t219 -251t77.5 -377.5v-65zM1022 761q0 229 -82 348t-234 119q-151 0 -233 -117.5t-83 -344.5v-71q0 -223 82 -346t236 -123 q151 0 232 118.5t82 345.5v71z"/> +<glyph glyph-name="P" horiz-adv-x="1321" unicode="P" d="M430 513v-513h-300v1456h568q164 0 288.5 -60t191.5 -170.5t67 -251.5q0 -214 -146.5 -337.5t-405.5 -123.5h-263zM430 756h268q119 0 181.5 56t62.5 160q0 107 -63 173t-174 68h-275v-457z"/> +<glyph glyph-name="Q" horiz-adv-x="1414" unicode="Q" d="M1324 695q0 -204 -66 -354.5t-183 -241.5l242 -190l-191 -169l-310 249q-53 -9 -110 -9q-181 0 -323 87t-220 248.5t-79 371.5v72q0 215 77.5 378.5t219 251t323.5 87.5t323.5 -87.5t219 -251t77.5 -377.5v-65zM1020 761q0 229 -82 348t-234 119q-151 0 -233 -117.5 t-83 -344.5v-71q0 -223 82 -346t236 -123q151 0 232 118.5t82 345.5v71z"/> +<glyph glyph-name="R" horiz-adv-x="1307" unicode="R" d="M669 533h-239v-533h-300v1456h541q258 0 398 -115t140 -325q0 -149 -64.5 -248.5t-195.5 -158.5l315 -595v-14h-322zM430 776h242q113 0 175 57.5t62 158.5q0 103 -58.5 162t-179.5 59h-241v-437z"/> +<glyph glyph-name="S" horiz-adv-x="1259" unicode="S" d="M885 382q0 85 -60 130.5t-216 96t-247 99.5q-248 134 -248 361q0 118 66.5 210.5t191 144.5t279.5 52q156 0 278 -56.5t189.5 -159.5t67.5 -234h-300q0 100 -63 155.5t-177 55.5q-110 0 -171 -46.5t-61 -122.5q0 -71 71.5 -119t210.5 -90q256 -77 373 -191t117 -284 q0 -189 -143 -296.5t-385 -107.5q-168 0 -306 61.5t-210.5 168.5t-72.5 248h301q0 -241 288 -241q107 0 167 43.5t60 121.5z"/> +<glyph glyph-name="T" horiz-adv-x="1267" unicode="T" d="M1226 1213h-446v-1213h-300v1213h-440v243h1186v-243z"/> +<glyph glyph-name="U" horiz-adv-x="1348" unicode="U" d="M1232 1456v-959q0 -239 -149.5 -378t-408.5 -139q-255 0 -405 135t-153 371v970h300v-961q0 -143 68.5 -208.5t189.5 -65.5q253 0 257 266v969h301z"/> +<glyph glyph-name="V" horiz-adv-x="1339" unicode="V" d="M668 361l330 1095h334l-507 -1456h-313l-505 1456h333z"/> +<glyph glyph-name="W" horiz-adv-x="1791" unicode="W" d="M1264 420l196 1036h299l-323 -1456h-302l-237 974l-237 -974h-302l-323 1456h299l197 -1034l240 1034h254z"/> +<glyph glyph-name="X" horiz-adv-x="1301" unicode="X" d="M651 954l273 502h345l-424 -722l435 -734h-349l-280 510l-280 -510h-349l435 734l-424 722h345z"/> +<glyph glyph-name="Y" horiz-adv-x="1266" unicode="Y" d="M632 800l303 656h328l-478 -928v-528h-305v528l-478 928h329z"/> +<glyph glyph-name="Z" horiz-adv-x="1241" unicode="Z" d="M448 241h734v-241h-1109v176l720 1037h-719v243h1092v-172z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="569" unicode="[" d="M552 1471h-142v-1587h142v-223h-432v2033h432v-223z"/> +<glyph glyph-name="backslash" horiz-adv-x="864" unicode="\" d="M0 1456h295l608 -1581h-296z"/> +<glyph glyph-name="bracketright" horiz-adv-x="569" unicode="]" d="M13 1694h432v-2033h-432v223h143v1587h-143v223z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="895" unicode="^" d="M448 1186l-174 -457h-230l299 727h210l299 -727h-229z"/> +<glyph glyph-name="underscore" horiz-adv-x="914" unicode="_" d="M912 -226h-911v226h911v-226z"/> +<glyph glyph-name="grave" horiz-adv-x="677" unicode="`" d="M565 1226h-237l-276 310h315z"/> +<glyph glyph-name="a" horiz-adv-x="1098" unicode="a" d="M738 0q-20 39 -29 97q-105 -117 -273 -117q-159 0 -263.5 92t-104.5 232q0 172 127.5 264t368.5 93h133v62q0 75 -38.5 120t-121.5 45q-73 0 -114.5 -35t-41.5 -96h-289q0 94 58 174t164 125.5t238 45.5q200 0 317.5 -100.5t117.5 -282.5v-469q1 -154 43 -233v-17h-292z M499 201q64 0 118 28.5t80 76.5v186h-108q-217 0 -231 -150l-1 -17q0 -54 38 -89t104 -35z"/> +<glyph glyph-name="b" horiz-adv-x="1153" unicode="b" d="M1086 531q0 -260 -111 -405.5t-310 -145.5q-176 0 -281 135l-13 -115h-260v1536h289v-551q100 117 263 117q198 0 310.5 -145.5t112.5 -409.5v-16zM797 552q0 164 -52 239.5t-155 75.5q-138 0 -190 -113v-427q53 -114 192 -114q140 0 184 138q21 66 21 201z"/> +<glyph glyph-name="c" horiz-adv-x="1068" unicode="c" d="M561 213q80 0 130 44t52 117h271q-1 -110 -60 -201.5t-161.5 -142t-226.5 -50.5q-232 0 -366 147.5t-134 407.5v19q0 250 133 399t365 149q203 0 325.5 -115.5t124.5 -307.5h-271q-2 84 -52 136.5t-132 52.5q-101 0 -152.5 -73.5t-51.5 -238.5v-30q0 -167 51 -240 t155 -73z"/> +<glyph glyph-name="d" horiz-adv-x="1154" unicode="d" d="M66 549q0 253 113.5 403t310.5 150q158 0 261 -118v552h290v-1536h-261l-14 115q-108 -135 -278 -135q-191 0 -306.5 150.5t-115.5 418.5zM355 528q0 -152 53 -233t154 -81q134 0 189 113v427q-54 113 -187 113q-209 0 -209 -339z"/> +<glyph glyph-name="e" horiz-adv-x="1107" unicode="e" d="M609 -20q-238 0 -387.5 146t-149.5 389v28q0 163 63 291.5t178.5 198t263.5 69.5q222 0 349.5 -140t127.5 -397v-118h-689q14 -106 84.5 -170t178.5 -64q167 0 261 121l142 -159q-65 -92 -176 -143.5t-246 -51.5zM576 868q-86 0 -139.5 -58t-68.5 -166h402v23 q-2 96 -52 148.5t-142 52.5z"/> +<glyph glyph-name="f" horiz-adv-x="734" unicode="f" d="M190 0v870h-161v212h161v92q0 182 104.5 282.5t292.5 100.5q60 0 147 -20l-3 -224q-36 9 -88 9q-163 0 -163 -153v-87h215v-212h-215v-870h-290z"/> +<glyph glyph-name="g" horiz-adv-x="1169" unicode="g" d="M69 549q0 249 118.5 401t319.5 152q178 0 277 -122l12 102h262v-1046q0 -142 -64.5 -247t-181.5 -160t-274 -55q-119 0 -232 47.5t-171 122.5l128 176q108 -121 262 -121q115 0 179 61.5t64 174.5v58q-100 -113 -263 -113q-195 0 -315.5 152.5t-120.5 404.5v12zM358 528 q0 -147 59 -230.5t162 -83.5q132 0 189 99v455q-58 99 -187 99q-104 0 -163.5 -85t-59.5 -254z"/> +<glyph glyph-name="h" horiz-adv-x="1146" unicode="h" d="M393 964q115 138 289 138q352 0 357 -409v-693h-289v685q0 93 -40 137.5t-133 44.5q-127 0 -184 -98v-769h-289v1536h289v-572z"/> +<glyph glyph-name="i" horiz-adv-x="543" unicode="i" d="M416 0h-290v1082h290v-1082zM109 1362q0 65 43.5 107t118.5 42q74 0 118 -42t44 -107q0 -66 -44.5 -108t-117.5 -42t-117.5 42t-44.5 108z"/> +<glyph glyph-name="j" horiz-adv-x="532" unicode="j" d="M417 1082v-1141q0 -179 -95 -278.5t-274 -99.5q-75 0 -143 17v229q52 -9 91 -9q131 0 131 139v1143h290zM104 1362q0 65 43.5 107t118.5 42t118.5 -42t43.5 -107q0 -66 -44.5 -108t-117.5 -42t-117.5 42t-44.5 108z"/> +<glyph glyph-name="k" horiz-adv-x="1094" unicode="k" d="M504 434l-104 -104v-330h-289v1536h289v-851l56 72l277 325h347l-391 -451l425 -631h-332z"/> +<glyph glyph-name="l" horiz-adv-x="543" unicode="l" d="M416 0h-290v1536h290v-1536z"/> +<glyph glyph-name="m" horiz-adv-x="1773" unicode="m" d="M382 1082l9 -121q115 141 311 141q209 0 287 -165q114 165 325 165q176 0 262 -102.5t86 -308.5v-691h-290v690q0 92 -36 134.5t-127 42.5q-130 0 -180 -124l1 -743h-289v689q0 94 -37 136t-126 42q-123 0 -178 -102v-765h-289v1082h271z"/> +<glyph glyph-name="n" horiz-adv-x="1147" unicode="n" d="M377 1082l9 -125q116 145 311 145q172 0 256 -101t86 -302v-699h-289v692q0 92 -40 133.5t-133 41.5q-122 0 -183 -104v-763h-289v1082h272z"/> +<glyph glyph-name="o" horiz-adv-x="1158" unicode="o" d="M66 551q0 161 62 287t178.5 195t270.5 69q219 0 357.5 -134t154.5 -364l2 -74q0 -249 -139 -399.5t-373 -150.5t-373.5 150t-139.5 408v13zM355 530q0 -154 58 -235.5t166 -81.5q105 0 164 80.5t59 257.5q0 151 -59 234t-166 83q-106 0 -164 -82.5t-58 -255.5z"/> +<glyph glyph-name="p" horiz-adv-x="1153" unicode="p" d="M1085 531q0 -250 -113.5 -400.5t-306.5 -150.5q-164 0 -265 114v-510h-289v1498h268l10 -106q105 126 274 126q200 0 311 -148t111 -408v-15zM796 552q0 151 -53.5 233t-155.5 82q-136 0 -187 -104v-443q53 -107 189 -107q207 0 207 339z"/> +<glyph glyph-name="q" horiz-adv-x="1157" unicode="q" d="M66 551q0 255 113.5 403t311.5 148q174 0 277 -133l19 113h254v-1498h-290v509q-100 -113 -262 -113q-193 0 -308 150t-115 421zM355 530q0 -155 54.5 -236t153.5 -81q133 0 188 106v447q-54 102 -186 102q-100 0 -155 -81t-55 -257z"/> +<glyph glyph-name="r" horiz-adv-x="747" unicode="r" d="M719 811q-59 8 -104 8q-164 0 -215 -111v-708h-289v1082h273l8 -129q87 149 241 149q48 0 90 -13z"/> +<glyph glyph-name="s" horiz-adv-x="1053" unicode="s" d="M697 299q0 53 -52.5 83.5t-168.5 54.5q-386 81 -386 328q0 144 119.5 240.5t312.5 96.5q206 0 329.5 -97t123.5 -252h-289q0 62 -40 102.5t-125 40.5q-73 0 -113 -33t-40 -84q0 -48 45.5 -77.5t153.5 -51t182 -48.5q229 -84 229 -291q0 -148 -127 -239.5t-328 -91.5 q-136 0 -241.5 48.5t-165.5 133t-60 182.5h274q4 -77 57 -118t142 -41q83 0 125.5 31.5t42.5 82.5z"/> +<glyph glyph-name="t" horiz-adv-x="692" unicode="t" d="M457 1348v-266h185v-212h-185v-540q0 -60 23 -86t88 -26q48 0 85 7v-219q-85 -26 -175 -26q-304 0 -310 307v583h-158v212h158v266h289z"/> +<glyph glyph-name="u" horiz-adv-x="1146" unicode="u" d="M759 110q-107 -130 -296 -130q-174 0 -265.5 100t-93.5 293v709h289v-699q0 -169 154 -169q147 0 202 102v766h290v-1082h-272z"/> +<glyph glyph-name="v" horiz-adv-x="1035" unicode="v" d="M516 353l201 729h302l-365 -1082h-276l-365 1082h302z"/> +<glyph glyph-name="w" horiz-adv-x="1505" unicode="w" d="M1052 393l142 689h279l-276 -1082h-242l-205 681l-205 -681h-241l-276 1082h279l141 -688l198 688h209z"/> +<glyph glyph-name="x" horiz-adv-x="1042" unicode="x" d="M523 759l182 323h309l-308 -530l321 -552h-310l-193 340l-192 -340h-311l321 552l-307 530h310z"/> +<glyph glyph-name="y" horiz-adv-x="1028" unicode="y" d="M515 409l200 673h310l-435 -1250l-24 -57q-97 -212 -320 -212q-63 0 -128 19v219l44 -1q82 0 122.5 25t63.5 83l34 89l-379 1085h311z"/> +<glyph glyph-name="z" horiz-adv-x="1042" unicode="z" d="M443 233h529v-233h-898v176l509 672h-494v234h867v-171z"/> +<glyph glyph-name="braceleft" horiz-adv-x="676" unicode="{" d="M586 -360q-360 101 -360 465v199q0 211 -178 211v207q174 0 178 199v212q0 185 90 299t270 165l56 -161q-76 -28 -115 -97.5t-41 -192.5v-210q0 -226 -179 -317q179 -92 179 -319v-212q5 -234 156 -286z"/> +<glyph glyph-name="bar" horiz-adv-x="518" unicode="|" d="M348 -270h-175v1726h175v-1726z"/> +<glyph glyph-name="braceright" horiz-adv-x="676" unicode="}" d="M34 -198q152 54 156 290v212q0 226 183 314q-183 88 -183 319v209q-4 233 -156 290l56 161q179 -50 269 -163.5t91 -297.5v-215q4 -199 178 -199v-207q-178 0 -178 -209v-217q-8 -350 -360 -449z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1328" unicode="~" d="M1221 793q0 -186 -93 -302t-240 -116q-74 0 -137.5 28.5t-146.5 108t-153 79.5q-58 0 -94 -50t-36 -128l-215 2q0 186 90.5 299t240.5 113q78 0 142 -30t145.5 -107.5t148.5 -77.5q59 0 96.5 53t37.5 129z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="578" unicode="¡" d="M170 639h241l33 -1008h-307zM452 948q0 -67 -46 -110t-116 -43t-116 43t-46 110t44.5 110t117.5 43t117.5 -43t44.5 -110z"/> +<glyph glyph-name="cent" horiz-adv-x="1178" unicode="¢" d="M594 213q80 0 130 44t52 117h272q-2 -145 -98.5 -250.5t-251.5 -134.5v-234h-200v233q-187 30 -293 174t-106 370v22q0 218 105 363t294 177v224h200v-225q163 -29 255.5 -140t94.5 -274h-272q-2 86 -52 137.5t-131 51.5q-102 0 -153 -74.5t-52 -234.5v-33 q0 -168 51.5 -240.5t154.5 -72.5z"/> +<glyph glyph-name="sterling" horiz-adv-x="1217" unicode="£" d="M564 576l6 -139q0 -123 -62 -196h653v-241h-1059v241h92q72 18 72 179l-5 156h-162v236h154l-7 227q0 202 123.5 319t330.5 117q212 0 333 -112.5t121 -304.5h-287q0 85 -43.5 130t-124.5 45q-66 0 -109.5 -49t-43.5 -145l9 -227h309v-236h-300z"/> +<glyph glyph-name="currency" horiz-adv-x="1418" unicode="¤" d="M1073 107q-159 -127 -361 -127q-203 0 -361 126l-129 -132l-141 144l135 137q-100 156 -100 353q0 204 109 365l-144 147l141 144l142 -145q155 115 348 115q194 0 349 -117l144 148l142 -145l-148 -151q107 -159 107 -361q0 -193 -98 -349l139 -141l-142 -145zM302 608 q0 -118 54 -219.5t149.5 -160t206.5 -58.5q110 0 205.5 58.5t149.5 160t54 219.5q0 119 -54 219.5t-149 158.5t-206 58q-112 0 -207 -58t-149 -158.5t-54 -219.5z"/> +<glyph glyph-name="yen" horiz-adv-x="1254" unicode="Â¥" d="M626 850l277 606h329l-375 -714h234v-175h-319v-115h319v-174h-319v-278h-300v278h-336v174h336v115h-336v175h260l-376 714h330z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="516" unicode="¦" d="M128 -270v795h260v-795h-260zM388 698h-260v758h260v-758z"/> +<glyph glyph-name="section" horiz-adv-x="1287" unicode="§" d="M1180 481q0 -182 -162 -271q135 -102 135 -288q0 -175 -137.5 -274.5t-379.5 -99.5q-257 0 -400.5 107t-143.5 310l289 1q0 -89 64 -136.5t191 -47.5q112 0 170 37.5t58 100.5q0 65 -64.5 106t-247 91.5t-275 105.5t-138 130t-45.5 181q0 180 162 273q-136 103 -136 288 q0 171 140.5 276t379.5 105q247 0 383 -113t136 -314h-289q0 87 -61.5 140.5t-168.5 53.5q-110 0 -170 -39t-60 -107q0 -73 55.5 -110t240.5 -86t282.5 -104t144.5 -131.5t47 -184.5zM458 704q-75 -42 -75 -141q0 -69 41.5 -106.5t165.5 -77.5l222 -67q82 47 82 140 q0 62 -45.5 101.5t-163.5 79.5z"/> +<glyph glyph-name="dieresis" horiz-adv-x="956" unicode="¨" d="M93 1365q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM580 1365q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="copyright" horiz-adv-x="1606" unicode="©" d="M1117 596q0 -152 -87.5 -233t-247.5 -81t-254.5 106.5t-94.5 286.5v113q0 174 95.5 280.5t253.5 106.5q163 0 249.5 -82.5t86.5 -231.5h-156q0 96 -46 137.5t-134 41.5q-92 0 -142.5 -67.5t-51.5 -180.5v-123q0 -117 51 -184.5t143 -67.5q89 0 134 40.5t45 138.5h156z M1383 729q0 166 -75 308.5t-212 228t-300 85.5q-159 0 -295.5 -82t-214.5 -226t-78 -314t77.5 -314t214 -227.5t296.5 -83.5t297.5 85t213.5 229t76 311zM86 729q0 202 93.5 375t259 272.5t357.5 99.5t357.5 -99.5t259 -272.5t93.5 -375q0 -204 -95 -377.5t-259.5 -272.5 t-355.5 -99q-193 0 -357.5 100t-258.5 273t-94 376z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="909" unicode="ª" d="M604 705q-10 27 -17 68q-77 -82 -201 -82q-118 0 -183.5 61.5t-65.5 166.5q0 110 84 170.5t257 60.5h102v51q0 127 -116 127q-65 0 -101.5 -25.5t-36.5 -73.5l-173 14q0 104 87.5 168.5t223.5 64.5q135 0 213 -72t78 -205v-316q0 -97 26 -178h-177zM429 835q40 0 82 18.5 t69 43.5v136h-106q-76 -1 -119 -31t-43 -79q0 -88 117 -88z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="1023" unicode="«" d="M303 524l240 -399h-186l-280 390v19l280 390h186zM688 524l240 -399h-186l-280 390v19l280 390h186z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1129" unicode="¬" d="M961 374h-200v260h-635v171h835v-431z"/> +<glyph glyph-name="registered" horiz-adv-x="1606" unicode="®" d="M86 729q0 202 93.5 375t259 272.5t357.5 99.5t357.5 -99.5t259 -272.5t93.5 -375q0 -204 -95 -377.5t-259.5 -272.5t-355.5 -99q-193 0 -357.5 100t-258.5 273t-94 376zM1383 729q0 166 -75 308.5t-212 228t-300 85.5q-159 0 -295.5 -82t-214.5 -226t-78 -314t77.5 -314 t214 -227.5t296.5 -83.5t297.5 85t213.5 229t76 311zM652 653v-337h-151v850h281q151 0 238 -68.5t87 -194.5q0 -112 -113 -174q61 -31 85.5 -86.5t24.5 -137.5t3.5 -116t13.5 -57v-16h-155q-13 34 -13 194q0 76 -33 109.5t-110 33.5h-158zM652 787h136q74 0 121.5 32 t47.5 84q0 70 -35.5 99.5t-128.5 30.5h-141v-246z"/> +<glyph glyph-name="macron" horiz-adv-x="1026" unicode="¯" d="M878 1290h-730v167h730v-167z"/> +<glyph glyph-name="degree" horiz-adv-x="795" unicode="°" d="M126 1200q0 114 81 195t191 81q109 0 188.5 -80.5t79.5 -195.5t-79.5 -193.5t-188.5 -78.5q-108 0 -190 78.5t-82 193.5zM398 1076q53 0 87.5 35.5t34.5 88.5q0 52 -34.5 90t-87.5 38t-89 -38t-36 -90t36.5 -88t88.5 -36z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1100" unicode="±" d="M677 942h328v-241h-328v-364h-253v364h-335v241h335v343h253v-343zM977 1h-864v235h864v-235z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="763" unicode="²" d="M693 667h-620v138l287 257q56 49 80.5 91t24.5 65q0 84 -95 84q-50 0 -79.5 -31t-29.5 -78h-206q0 116 85.5 195t220.5 79q148 0 228.5 -64.5t80.5 -183.5q0 -70 -36 -128t-144 -145l-148 -115h351v-164z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="763" unicode="³" d="M273 1136h82q119 0 119 88q0 35 -28.5 56t-77.5 21q-42 0 -71.5 -15.5t-29.5 -44.5h-205q0 102 84.5 163.5t215.5 61.5q145 0 230.5 -59.5t85.5 -166.5q0 -119 -135 -169q150 -41 150 -184q0 -105 -91.5 -168.5t-239.5 -63.5q-142 0 -228 66.5t-86 180.5h206 q0 -34 34 -58.5t86 -24.5q60 0 86.5 26.5t26.5 61.5q0 92 -122 93h-92v136z"/> +<glyph glyph-name="acute" horiz-adv-x="679" unicode="´" d="M298 1536h315l-277 -310h-235z"/> +<glyph glyph-name="uni00B5" horiz-adv-x="1261" unicode="µ" d="M428 1082v-623q0 -126 40.5 -185.5t139.5 -59.5q149 0 205 105v763h289v-1082h-269l-6 68q-89 -89 -225 -89q-102 0 -174 45v-440h-289v1498h289z"/> +<glyph glyph-name="paragraph" horiz-adv-x="1003" unicode="¶" d="M650 0v520h-80q-230 0 -362.5 127t-132.5 341q0 213 133 340.5t363 127.5h298v-1456h-219z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="617" unicode="·" d="M140 697q0 69 46 112t117 43t117.5 -43t46.5 -112t-47 -111.5t-117 -42.5q-72 0 -117.5 43.5t-45.5 110.5z"/> +<glyph glyph-name="cedilla" horiz-adv-x="548" unicode="¸" d="M345 7l-11 -58q150 -27 150 -173q0 -110 -91.5 -174t-257.5 -64l-7 167q112 0 112 81q0 42 -33.5 57.5t-108.5 20.5l31 143h216z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="763" unicode="¹" d="M528 669h-204v548l-189 -41v158l374 121h19v-786z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="936" unicode="º" d="M118 1121q0 160 95.5 257.5t250.5 97.5t251 -97t96 -263v-72q0 -159 -94 -256.5t-251 -97.5q-158 0 -253 98t-95 261v72zM293 1044q0 -98 46.5 -153t126.5 -55q78 0 123.5 54t46.5 151v80q0 97 -46.5 152t-125.5 55q-78 0 -124.5 -54.5t-46.5 -156.5v-73z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="1023" unicode="»" d="M272 923l280 -390v-19l-280 -390h-187l240 399l-240 400h187zM665 923l280 -390v-19l-280 -390h-187l240 399l-240 400h187z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1470" unicode="¼" d="M494 664h-204v548l-189 -41v158l374 121h19v-786zM458 117l-141 76l711 1138l141 -76zM1302 326h88v-167h-88v-159h-205v159h-346l-12 135l357 495h206v-463zM935 326h162v212l-14 -22z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1559" unicode="½" d="M416 117l-141 76l711 1138l141 -76zM477 670h-204v548l-189 -41v158l374 121h19v-786zM1477 0h-620v138l287 257q56 49 80.5 91t24.5 65q0 84 -95 84q-50 0 -79.5 -31t-29.5 -78h-206q0 116 85.5 195t220.5 79q148 0 228.5 -64.5t80.5 -183.5q0 -70 -36 -128t-144 -145 l-148 -115h351v-164z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1655" unicode="¾" d="M619 117l-141 76l711 1138l141 -76zM1460 326h88v-167h-88v-159h-205v159h-346l-12 135l357 495h206v-463zM1093 326h162v212l-14 -22zM319 1137h82q119 0 119 88q0 35 -28.5 56t-77.5 21q-42 0 -71.5 -15.5t-29.5 -44.5h-205q0 102 84.5 163.5t215.5 61.5 q145 0 230.5 -59.5t85.5 -166.5q0 -119 -135 -169q150 -41 150 -184q0 -105 -91.5 -168.5t-239.5 -63.5q-142 0 -228 66.5t-86 180.5h206q0 -34 34 -58.5t86 -24.5q60 0 86.5 26.5t26.5 61.5q0 92 -122 93h-92v136z"/> +<glyph glyph-name="questiondown" horiz-adv-x="1019" unicode="¿" d="M666 643q0 -133 -31 -215t-110.5 -156t-108 -110t-43 -73t-14.5 -81q0 -157 154 -157q77 0 122.5 45t47.5 126h289q-2 -192 -123 -299.5t-331 -107.5q-213 0 -331 101.5t-118 289.5q0 159 153 312l97 93q50 45 69.5 94t21.5 138h256zM702 949q0 -67 -46 -110t-116 -43 t-116 43t-46 110t44.5 110t117.5 43t117.5 -43t44.5 -110z"/> +<glyph glyph-name="AE" horiz-adv-x="1925" unicode="Æ" d="M1865 0h-897l-14 333h-446l-167 -333h-339l786 1456h1016v-236h-598l15 -355h502v-236h-492l16 -394h618v-235zM633 580h311l-24 570z"/> +<glyph glyph-name="multiply" horiz-adv-x="1088" unicode="×" d="M65 373l307 313l-307 313l170 168l304 -311l305 311l170 -168l-307 -313l307 -313l-170 -168l-305 310l-304 -310z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1411" unicode="Ø" d="M1333 695q0 -215 -76 -377t-217.5 -250t-324.5 -88q-164 0 -295 70l-85 -145h-188l143 242q-197 195 -197 555v57q0 215 77.5 378.5t219 251t323.5 87.5q175 0 314 -82l74 124h187l-134 -227q179 -198 179 -537v-59zM397 695q0 -172 49 -285l447 757q-73 61 -180 61 q-151 0 -233 -117.5t-83 -344.5v-71zM1030 761q0 151 -38 256l-440 -744q70 -47 163 -47q151 0 232.5 118.5t82.5 345.5v71z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1246" unicode="Þ" d="M422 1456v-267h230q162 -1 281.5 -56.5t183.5 -158t64 -236.5q0 -202 -138.5 -324t-378.5 -127h-242v-287h-289v1456h289zM422 956v-436h223q117 0 182 59t65 157t-63.5 158t-175.5 62h-231z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1292" unicode="ß" d="M424 0h-289v1101q0 220 124 339t350 119q191 0 306.5 -99.5t115.5 -270.5q0 -108 -53.5 -195t-53.5 -164q0 -37 30.5 -76.5t118.5 -117.5q151 -134 151 -282q0 -177 -115 -275.5t-330 -98.5q-81 0 -160 16t-119 40l54 229q98 -52 219 -52q79 0 121 36.5t42 99.5 q0 46 -34.5 89.5t-116.5 109.5q-150 120 -150 270q0 96 55 186.5t55 169.5q0 70 -44.5 111.5t-112.5 41.5q-159 0 -164 -213v-1114z"/> +<glyph glyph-name="ae" horiz-adv-x="1729" unicode="æ" d="M1246 -20q-247 0 -386 147q-64 -69 -166.5 -108t-227.5 -39q-186 0 -293 89t-107 250q0 157 124 243t367 87h168v57q0 76 -40.5 119t-117.5 43q-82 0 -129.5 -35.5t-47.5 -87.5l-289 19q0 149 130.5 243.5t338.5 94.5q211 0 327 -110q126 112 326 110q212 0 333 -131.5 t121 -363.5v-157h-668q11 -116 80.5 -177t186.5 -61q77 0 142.5 16t152.5 61l77 -189q-73 -56 -180.5 -88t-221.5 -32zM521 192q49 0 107 22.5t97 57.5v189h-164q-95 -1 -150.5 -43t-55.5 -103q0 -56 40.5 -89.5t125.5 -33.5zM1223 868q-90 0 -144.5 -57.5t-67.5 -166.5h382 v28q0 94 -43.5 145t-126.5 51z"/> +<glyph glyph-name="eth" horiz-adv-x="1178" unicode="ð" d="M849 1305q255 -262 256 -654v-74q0 -172 -66.5 -309t-185.5 -212.5t-266 -75.5q-144 0 -259 63.5t-179.5 176t-64.5 248.5q0 231 123 364.5t329 133.5q136 0 244 -76q-49 152 -166 265l-191 -122l-78 114l152 97q-116 72 -264 111l91 224q238 -48 416 -180l171 109 l77 -114zM816 663q-68 83 -215 83q-113 0 -170.5 -74.5t-57.5 -203.5q0 -112 60 -183.5t158 -71.5q103 0 164 90.5t61 248.5v111z"/> +<glyph glyph-name="divide" horiz-adv-x="1168" unicode="÷" d="M1091 571h-1028v230h1028v-230zM415 1089q0 68 45.5 110t117.5 42q71 0 117.5 -41.5t46.5 -110.5q0 -67 -45 -108.5t-119 -41.5q-75 0 -119 42t-44 108zM415 277q0 68 45.5 110t117.5 42q71 0 117.5 -41.5t46.5 -110.5q0 -67 -45 -108.5t-119 -41.5q-75 0 -119 42 t-44 108z"/> +<glyph glyph-name="oslash" horiz-adv-x="1156" unicode="ø" d="M66 551q0 161 62 287t178.5 195t270.5 69q101 0 186 -29l70 143h161l-103 -211q200 -149 200 -475q0 -249 -139 -399.5t-373 -150.5q-95 0 -176 26l-72 -148h-161l103 212q-207 146 -207 481zM355 530q0 -130 41 -208l260 532q-36 14 -79 14q-106 0 -164 -82.5 t-58 -255.5zM802 551q0 114 -37 196l-256 -524q30 -10 70 -10q105 0 164 80.5t59 257.5z"/> +<glyph glyph-name="thorn" horiz-adv-x="1162" unicode="þ" d="M1087 531q0 -250 -113.5 -400.5t-306.5 -150.5q-164 0 -264 113v-509h-290v1952h290v-547q100 113 262 113q198 0 310 -147t112 -410v-14zM798 552q0 151 -53.5 233t-155.5 82q-132 0 -186 -102v-447q54 -105 188 -105q207 0 207 339z"/> +<glyph glyph-name="dotlessi" horiz-adv-x="561" unicode="ı" d="M423 0h-289v1082h289v-1082z"/> +<glyph glyph-name="OE" horiz-adv-x="1983" unicode="Å’" d="M1876 0h-886q-167 -20 -288 -20q-174 0 -312 73.5t-214.5 207t-79.5 302.5v317q0 173 75.5 309.5t214 211.5t314.5 75q123 0 290 -20h884v-243h-673v-347h575v-235h-575v-390h675v-241zM702 212q94 0 198 13v1004q-112 14 -200 14q-150 0 -232 -92.5t-83 -265.5v-309 q0 -176 83.5 -270t233.5 -94z"/> +<glyph glyph-name="oe" horiz-adv-x="1847" unicode="Å“" d="M83 551q0 161 61 286.5t177 195t270 69.5q231 0 371 -149q134 151 349 149q214 0 337 -129t123 -365v-158h-654q16 -113 81.5 -175.5t168.5 -62.5q85 0 152 16.5t149 61.5l79 -187q-73 -58 -182 -90.5t-228 -32.5q-233 0 -373 149q-138 -149 -371 -149t-371.5 149.5 t-138.5 408.5v13zM372 530q0 -155 56.5 -236.5t164.5 -81.5q106 0 163 80.5t57 258.5q0 153 -58 235t-164 82q-105 0 -162 -82t-57 -256zM1311 868q-77 0 -126 -57t-65 -164h367v26q0 97 -46.5 146t-129.5 49z"/> +<glyph glyph-name="circumflex" horiz-adv-x="1015" unicode="ˆ" d="M887 1256v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="ring" horiz-adv-x="682" unicode="Ëš" d="M119 1325q0 86 65 145.5t158 59.5q92 0 157.5 -58.5t65.5 -146.5q0 -85 -64 -143t-159 -58q-97 0 -160 59t-63 142zM234 1325q0 -44 29 -75.5t79 -31.5t79 31.5t29 75.5q0 46 -29.5 77.5t-78.5 31.5t-78.5 -31.5t-29.5 -77.5z"/> +<glyph glyph-name="tilde" horiz-adv-x="985" unicode="Ëœ" d="M870 1524q0 -113 -66 -189.5t-161 -76.5q-38 0 -67.5 8.5t-81.5 36.5t-75 34.5t-50 6.5q-35 0 -59.5 -25t-24.5 -71l-168 10q0 111 65.5 189t160.5 78q30 0 56.5 -7.5t86.5 -36.5t83 -35t48 -6q35 0 60.5 24.5t25.5 70.5z"/> +<glyph glyph-name="endash" horiz-adv-x="1294" unicode="–" d="M1188.01 596h-1035.61v236h1035.61v-236z"/> +<glyph glyph-name="emdash" horiz-adv-x="1563" unicode="—" d="M1489.98 596h-1380.78v236h1380.78v-236z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="479" unicode="‘" d="M286 1570l136 -79q-86 -136 -89 -276v-167h-229v150q0 94 52.5 200.5t129.5 171.5z"/> +<glyph glyph-name="quoteright" horiz-adv-x="470" unicode="’" d="M194 1009l-136 79q86 135 89 279v169h230v-155q0 -90 -50 -195t-133 -177z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="508" unicode="‚" d="M202 -305l-136 79q78 126 81 274v181h238l-1 -166q-1 -89 -50.5 -192t-131.5 -176z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="831" unicode="“" d="M294 1570l136 -79q-86 -136 -89 -276v-167h-229v150q0 94 52.5 200.5t129.5 171.5zM637 1570l136 -79q-86 -136 -89 -276v-167h-229v150q0 94 52.5 200.5t129.5 171.5z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="837" unicode="â€" d="M208 1009l-136 79q86 135 89 279v169h230v-155q0 -90 -50 -195t-133 -177zM555 1009l-136 79q86 135 89 279v169h230v-155q0 -90 -50 -195t-133 -177z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="825" unicode="„" d="M209 -325l-143 79q78 134 81 293v216h238l-1 -199q-1 -97 -48 -206.5t-127 -182.5zM545 -325l-143 79q86 148 89 294v215h238l-1 -203q-2 -96 -52.5 -205t-130.5 -180z"/> +<glyph glyph-name="bullet" horiz-adv-x="736" unicode="•" d="M135 766q0 104 66 167t170 63q108 0 172.5 -62t66.5 -163v-43q0 -103 -65.5 -165.5t-171.5 -62.5q-105 0 -171.5 62t-66.5 169v35z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="638" unicode="‹" d="M334 524l240 -399h-186l-280 390v19l280 390h186z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="618" unicode="›" d="M267 923l280 -390v-19l-280 -390h-187l240 399l-240 400h187z"/> +<glyph glyph-name="fraction" horiz-adv-x="913" unicode="â„" d="M171 109l-141 76l711 1138l141 -76z"/> +<glyph glyph-name="uni2074" horiz-adv-x="763" unicode="â´" d="M616 990h88v-167h-88v-159h-205v159h-346l-12 135l357 495h206v-463zM249 990h162v212l-14 -22z"/> +<glyph glyph-name="Euro" d="M894 516h-335q5 -147 78.5 -221t228.5 -74q105 0 190 31l36 -242q-124 -29 -256 -29q-263 0 -416.5 141.5t-161.5 393.5h-169v152h169v124h-169v152h171q17 252 175.5 391.5t420.5 139.5q105 0 236 -31l-36 -243q-94 32 -185 32q-283 0 -310 -289h333v-152h-335v-124h335 v-152z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1138" unicode="−" d="M1010 596h-863v236h863v-236z"/> +<glyph glyph-name="glyph162" d="M528 0h-204v548l-189 -41v158l374 121h19v-786z" horiz-adv-x="762"/> +<glyph glyph-name="glyph163" d="M693 0h-620v138l287 257q56 49 80.5 91t24.5 65q0 84 -95 84q-50 0 -79.5 -31t-29.5 -78h-206q0 116 85.5 195t220.5 79q148 0 228.5 -64.5t80.5 -183.5q0 -70 -36 -128t-144 -145l-148 -115h351v-164z" horiz-adv-x="762"/> +<glyph glyph-name="glyph164" d="M273 470h82q119 0 119 88q0 35 -28.5 56t-77.5 21q-42 0 -71.5 -15.5t-29.5 -44.5h-205q0 102 84.5 163.5t215.5 61.5q145 0 230.5 -59.5t85.5 -166.5q0 -119 -135 -169q150 -41 150 -184q0 -105 -91.5 -168.5t-239.5 -63.5q-142 0 -228 66.5t-86 180.5h206 q0 -34 34 -58.5t86 -24.5q60 0 86.5 26.5t26.5 61.5q0 92 -122 93h-92v136z" horiz-adv-x="762"/> +<glyph glyph-name="glyph165" d="M616 326h88v-167h-88v-159h-205v159h-346l-12 135l357 495h206v-463zM249 326h162v212l-14 -22z" horiz-adv-x="762"/> +<glyph glyph-name="uni00A0" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="794" unicode="Â" d="M673 507h-563v233h563v-233z"/> +<glyph glyph-name="Eth" horiz-adv-x="1361" unicode="Ã" d="M160 0v642h-180v183h180v631h448q192 0 343.5 -86.5t236.5 -246t85 -362.5v-67q0 -203 -83.5 -361t-235.5 -245t-343 -88h-451zM679 642h-219v-401h145q178 0 271 117.5t93 335.5v68q0 222 -92 336.5t-269 114.5h-148v-388h219v-183z"/> +<glyph glyph-name="Agrave" horiz-adv-x="1378" unicode="À" d="M952 300h-526l-100 -300h-319l542 1456h278l545 -1456h-319zM507 543h364l-183 545zM836 1536h-237l-276 310h315z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1378" unicode="Ã" d="M952 300h-526l-100 -300h-319l542 1456h278l545 -1456h-319zM507 543h364l-183 545zM750 1846h315l-277 -310h-235z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1378" unicode="Â" d="M952 300h-526l-100 -300h-319l542 1456h278l545 -1456h-319zM507 543h364l-183 545zM1076 1566v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1378" unicode="Ã" d="M952 300h-526l-100 -300h-319l542 1456h278l545 -1456h-319zM507 543h364l-183 545zM1068 1832q0 -113 -66 -189.5t-161 -76.5q-38 0 -67.5 8.5t-81.5 36.5t-75 34.5t-50 6.5q-35 0 -59.5 -25t-24.5 -71l-168 10q0 111 65.5 189t160.5 78q30 0 56.5 -7.5t86.5 -36.5 t83 -35t48 -6q35 0 60.5 24.5t25.5 70.5z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1378" unicode="Ä" d="M952 300h-526l-100 -300h-319l542 1456h278l545 -1456h-319zM507 543h364l-183 545zM309 1675q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM796 1675q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5 q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="Aring" horiz-adv-x="1378" unicode="Ã…" d="M952 300h-526l-100 -300h-319l542 1456h278l545 -1456h-319zM507 543h364l-183 545zM470 1730q0 86 65 145.5t158 59.5q92 0 157.5 -58.5t65.5 -146.5q0 -85 -64 -143t-159 -58q-97 0 -160 59t-63 142zM585 1730q0 -44 29 -75.5t79 -31.5t79 31.5t29 75.5 q0 46 -29.5 77.5t-78.5 31.5t-78.5 -31.5t-29.5 -77.5z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1340" unicode="Ç" d="M1273 485q-17 -235 -173.5 -370t-412.5 -135q-280 0 -440.5 188.5t-160.5 517.5v89q0 210 74 370t211.5 245.5t319.5 85.5q252 0 406 -135t178 -379h-300q-11 141 -78.5 204.5t-205.5 63.5q-150 0 -224.5 -107.5t-76.5 -333.5v-110q0 -236 71.5 -345t225.5 -109 q139 0 207.5 63.5t78.5 196.5h300zM797 6l-11 -58q150 -27 150 -173q0 -110 -91.5 -174t-257.5 -64l-7 167q112 0 112 81q0 42 -33.5 57.5t-108.5 20.5l31 143h216z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1152" unicode="È" d="M1006 631h-576v-390h676v-241h-976v1456h974v-243h-674v-347h576v-235zM779 1539h-237l-276 310h315z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1152" unicode="É" d="M1006 631h-576v-390h676v-241h-976v1456h974v-243h-674v-347h576v-235zM693 1849h315l-277 -310h-235z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1152" unicode="Ê" d="M1006 631h-576v-390h676v-241h-976v1456h974v-243h-674v-347h576v-235zM1019 1569v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1152" unicode="Ë" d="M1006 631h-576v-390h676v-241h-976v1456h974v-243h-674v-347h576v-235zM252 1678q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM739 1678q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5 t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="Igrave" horiz-adv-x="597" unicode="ÃŒ" d="M449 0h-300v1456h300v-1456zM443 1539h-237l-276 310h315z"/> +<glyph glyph-name="Iacute" horiz-adv-x="597" unicode="Ã" d="M449 0h-300v1456h300v-1456zM356 1849h315l-277 -310h-235z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="597" unicode="ÃŽ" d="M449 0h-300v1456h300v-1456zM683 1569v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="597" unicode="Ã" d="M449 0h-300v1456h300v-1456zM-84 1678q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM403 1678q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1446" unicode="Ñ" d="M1314 0h-300l-584 958v-958h-300v1456h300l585 -960v960h299v-1456zM1102 1832q0 -113 -66 -189.5t-161 -76.5q-38 0 -67.5 8.5t-81.5 36.5t-75 34.5t-50 6.5q-35 0 -59.5 -25t-24.5 -71l-168 10q0 111 65.5 189t160.5 78q30 0 56.5 -7.5t86.5 -36.5t83 -35t48 -6 q35 0 60.5 24.5t25.5 70.5z"/> +<glyph glyph-name="Ograve" horiz-adv-x="1414" unicode="Ã’" d="M1326 695q0 -215 -76 -377t-217.5 -250t-324.5 -88q-181 0 -323 87t-220 248.5t-79 371.5v72q0 215 77.5 378.5t219 251t323.5 87.5t323.5 -87.5t219 -251t77.5 -377.5v-65zM1022 761q0 229 -82 348t-234 119q-151 0 -233 -117.5t-83 -344.5v-71q0 -223 82 -346t236 -123 q151 0 232 118.5t82 345.5v71zM850 1536h-237l-276 310h315z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1414" unicode="Ó" d="M1326 695q0 -215 -76 -377t-217.5 -250t-324.5 -88q-181 0 -323 87t-220 248.5t-79 371.5v72q0 215 77.5 378.5t219 251t323.5 87.5t323.5 -87.5t219 -251t77.5 -377.5v-65zM1022 761q0 229 -82 348t-234 119q-151 0 -233 -117.5t-83 -344.5v-71q0 -223 82 -346t236 -123 q151 0 232 118.5t82 345.5v71zM764 1846h315l-277 -310h-235z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1414" unicode="Ô" d="M1326 695q0 -215 -76 -377t-217.5 -250t-324.5 -88q-181 0 -323 87t-220 248.5t-79 371.5v72q0 215 77.5 378.5t219 251t323.5 87.5t323.5 -87.5t219 -251t77.5 -377.5v-65zM1022 761q0 229 -82 348t-234 119q-151 0 -233 -117.5t-83 -344.5v-71q0 -223 82 -346t236 -123 q151 0 232 118.5t82 345.5v71zM1090 1566v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1414" unicode="Õ" d="M1326 695q0 -215 -76 -377t-217.5 -250t-324.5 -88q-181 0 -323 87t-220 248.5t-79 371.5v72q0 215 77.5 378.5t219 251t323.5 87.5t323.5 -87.5t219 -251t77.5 -377.5v-65zM1022 761q0 229 -82 348t-234 119q-151 0 -233 -117.5t-83 -344.5v-71q0 -223 82 -346t236 -123 q151 0 232 118.5t82 345.5v71zM1082 1832q0 -113 -66 -189.5t-161 -76.5q-38 0 -67.5 8.5t-81.5 36.5t-75 34.5t-50 6.5q-35 0 -59.5 -25t-24.5 -71l-168 10q0 111 65.5 189t160.5 78q30 0 56.5 -7.5t86.5 -36.5t83 -35t48 -6q35 0 60.5 24.5t25.5 70.5z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1414" unicode="Ö" d="M1326 695q0 -215 -76 -377t-217.5 -250t-324.5 -88q-181 0 -323 87t-220 248.5t-79 371.5v72q0 215 77.5 378.5t219 251t323.5 87.5t323.5 -87.5t219 -251t77.5 -377.5v-65zM1022 761q0 229 -82 348t-234 119q-151 0 -233 -117.5t-83 -344.5v-71q0 -223 82 -346t236 -123 q151 0 232 118.5t82 345.5v71zM323 1675q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM810 1675q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1348" unicode="Ù" d="M1232 1456v-959q0 -239 -149.5 -378t-408.5 -139q-255 0 -405 135t-153 371v970h300v-961q0 -143 68.5 -208.5t189.5 -65.5q253 0 257 266v969h301zM814 1536h-237l-276 310h315z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1348" unicode="Ú" d="M1232 1456v-959q0 -239 -149.5 -378t-408.5 -139q-255 0 -405 135t-153 371v970h300v-961q0 -143 68.5 -208.5t189.5 -65.5q253 0 257 266v969h301zM728 1846h315l-277 -310h-235z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1348" unicode="Û" d="M1232 1456v-959q0 -239 -149.5 -378t-408.5 -139q-255 0 -405 135t-153 371v970h300v-961q0 -143 68.5 -208.5t189.5 -65.5q253 0 257 266v969h301zM1054 1566v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="Udieresis" horiz-adv-x="1348" unicode="Ü" d="M1232 1456v-959q0 -239 -149.5 -378t-408.5 -139q-255 0 -405 135t-153 371v970h300v-961q0 -143 68.5 -208.5t189.5 -65.5q253 0 257 266v969h301zM287 1675q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM774 1675 q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1266" unicode="Ã" d="M632 800l303 656h328l-478 -928v-528h-305v528l-478 928h329zM693 1846h315l-277 -310h-235z"/> +<glyph glyph-name="agrave" horiz-adv-x="1098" unicode="à " d="M738 0q-20 39 -29 97q-105 -117 -273 -117q-159 0 -263.5 92t-104.5 232q0 172 127.5 264t368.5 93h133v62q0 75 -38.5 120t-121.5 45q-73 0 -114.5 -35t-41.5 -96h-289q0 94 58 174t164 125.5t238 45.5q200 0 317.5 -100.5t117.5 -282.5v-469q1 -154 43 -233v-17h-292z M499 201q64 0 118 28.5t80 76.5v186h-108q-217 0 -231 -150l-1 -17q0 -54 38 -89t104 -35zM695 1226h-237l-276 310h315z"/> +<glyph glyph-name="aacute" horiz-adv-x="1098" unicode="á" d="M738 0q-20 39 -29 97q-105 -117 -273 -117q-159 0 -263.5 92t-104.5 232q0 172 127.5 264t368.5 93h133v62q0 75 -38.5 120t-121.5 45q-73 0 -114.5 -35t-41.5 -96h-289q0 94 58 174t164 125.5t238 45.5q200 0 317.5 -100.5t117.5 -282.5v-469q1 -154 43 -233v-17h-292z M499 201q64 0 118 28.5t80 76.5v186h-108q-217 0 -231 -150l-1 -17q0 -54 38 -89t104 -35zM609 1536h315l-277 -310h-235z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1098" unicode="â" d="M738 0q-20 39 -29 97q-105 -117 -273 -117q-159 0 -263.5 92t-104.5 232q0 172 127.5 264t368.5 93h133v62q0 75 -38.5 120t-121.5 45q-73 0 -114.5 -35t-41.5 -96h-289q0 94 58 174t164 125.5t238 45.5q200 0 317.5 -100.5t117.5 -282.5v-469q1 -154 43 -233v-17h-292z M499 201q64 0 118 28.5t80 76.5v186h-108q-217 0 -231 -150l-1 -17q0 -54 38 -89t104 -35zM935 1256v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="atilde" horiz-adv-x="1098" unicode="ã" d="M738 0q-20 39 -29 97q-105 -117 -273 -117q-159 0 -263.5 92t-104.5 232q0 172 127.5 264t368.5 93h133v62q0 75 -38.5 120t-121.5 45q-73 0 -114.5 -35t-41.5 -96h-289q0 94 58 174t164 125.5t238 45.5q200 0 317.5 -100.5t117.5 -282.5v-469q1 -154 43 -233v-17h-292z M499 201q64 0 118 28.5t80 76.5v186h-108q-217 0 -231 -150l-1 -17q0 -54 38 -89t104 -35zM927 1523q0 -113 -66 -189.5t-161 -76.5q-38 0 -67.5 8.5t-81.5 36.5t-75 34.5t-50 6.5q-35 0 -59.5 -25t-24.5 -71l-168 10q0 111 65.5 189t160.5 78q30 0 56.5 -7.5t86.5 -36.5 t83 -35t48 -6q35 0 60.5 24.5t25.5 70.5z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1098" unicode="ä" d="M738 0q-20 39 -29 97q-105 -117 -273 -117q-159 0 -263.5 92t-104.5 232q0 172 127.5 264t368.5 93h133v62q0 75 -38.5 120t-121.5 45q-73 0 -114.5 -35t-41.5 -96h-289q0 94 58 174t164 125.5t238 45.5q200 0 317.5 -100.5t117.5 -282.5v-469q1 -154 43 -233v-17h-292z M499 201q64 0 118 28.5t80 76.5v186h-108q-217 0 -231 -150l-1 -17q0 -54 38 -89t104 -35zM168 1365q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM655 1365q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5 q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="aring" horiz-adv-x="1098" unicode="Ã¥" d="M738 0q-20 39 -29 97q-105 -117 -273 -117q-159 0 -263.5 92t-104.5 232q0 172 127.5 264t368.5 93h133v62q0 75 -38.5 120t-121.5 45q-73 0 -114.5 -35t-41.5 -96h-289q0 94 58 174t164 125.5t238 45.5q200 0 317.5 -100.5t117.5 -282.5v-469q1 -154 43 -233v-17h-292z M499 201q64 0 118 28.5t80 76.5v186h-108q-217 0 -231 -150l-1 -17q0 -54 38 -89t104 -35zM329 1420q0 86 65 145.5t158 59.5q92 0 157.5 -58.5t65.5 -146.5q0 -85 -64 -143t-159 -58q-97 0 -160 59t-63 142zM444 1420q0 -44 29 -75.5t79 -31.5t79 31.5t29 75.5 q0 46 -29.5 77.5t-78.5 31.5t-78.5 -31.5t-29.5 -77.5z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1068" unicode="ç" d="M561 213q80 0 130 44t52 117h271q-1 -110 -60 -201.5t-161.5 -142t-226.5 -50.5q-232 0 -366 147.5t-134 407.5v19q0 250 133 399t365 149q203 0 325.5 -115.5t124.5 -307.5h-271q-2 84 -52 136.5t-132 52.5q-101 0 -152.5 -73.5t-51.5 -238.5v-30q0 -167 51 -240 t155 -73zM666 6l-11 -58q150 -27 150 -173q0 -110 -91.5 -174t-257.5 -64l-7 167q112 0 112 81q0 42 -33.5 57.5t-108.5 20.5l31 143h216z"/> +<glyph glyph-name="egrave" horiz-adv-x="1107" unicode="è" d="M609 -20q-238 0 -387.5 146t-149.5 389v28q0 163 63 291.5t178.5 198t263.5 69.5q222 0 349.5 -140t127.5 -397v-118h-689q14 -106 84.5 -170t178.5 -64q167 0 261 121l142 -159q-65 -92 -176 -143.5t-246 -51.5zM576 868q-86 0 -139.5 -58t-68.5 -166h402v23 q-2 96 -52 148.5t-142 52.5zM688 1226h-237l-276 310h315z"/> +<glyph glyph-name="eacute" horiz-adv-x="1107" unicode="é" d="M609 -20q-238 0 -387.5 146t-149.5 389v28q0 163 63 291.5t178.5 198t263.5 69.5q222 0 349.5 -140t127.5 -397v-118h-689q14 -106 84.5 -170t178.5 -64q167 0 261 121l142 -159q-65 -92 -176 -143.5t-246 -51.5zM576 868q-86 0 -139.5 -58t-68.5 -166h402v23 q-2 96 -52 148.5t-142 52.5zM602 1536h315l-277 -310h-235z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1107" unicode="ê" d="M609 -20q-238 0 -387.5 146t-149.5 389v28q0 163 63 291.5t178.5 198t263.5 69.5q222 0 349.5 -140t127.5 -397v-118h-689q14 -106 84.5 -170t178.5 -64q167 0 261 121l142 -159q-65 -92 -176 -143.5t-246 -51.5zM576 868q-86 0 -139.5 -58t-68.5 -166h402v23 q-2 96 -52 148.5t-142 52.5zM928 1256v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1107" unicode="ë" d="M609 -20q-238 0 -387.5 146t-149.5 389v28q0 163 63 291.5t178.5 198t263.5 69.5q222 0 349.5 -140t127.5 -397v-118h-689q14 -106 84.5 -170t178.5 -64q167 0 261 121l142 -159q-65 -92 -176 -143.5t-246 -51.5zM576 868q-86 0 -139.5 -58t-68.5 -166h402v23 q-2 96 -52 148.5t-142 52.5zM161 1365q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM648 1365q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="igrave" horiz-adv-x="561" unicode="ì" d="M423 0h-289v1082h289v-1082zM425 1211h-237l-276 310h315z"/> +<glyph glyph-name="iacute" horiz-adv-x="561" unicode="Ã" d="M423 0h-289v1082h289v-1082zM338 1521h315l-277 -310h-235z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="561" unicode="î" d="M423 0h-289v1082h289v-1082zM665 1241v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="idieresis" horiz-adv-x="561" unicode="ï" d="M423 0h-289v1082h289v-1082zM-102 1350q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM385 1350q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="ntilde" horiz-adv-x="1147" unicode="ñ" d="M377 1082l9 -125q116 145 311 145q172 0 256 -101t86 -302v-699h-289v692q0 92 -40 133.5t-133 41.5q-122 0 -183 -104v-763h-289v1082h272zM951 1523q0 -113 -66 -189.5t-161 -76.5q-38 0 -67.5 8.5t-81.5 36.5t-75 34.5t-50 6.5q-35 0 -59.5 -25t-24.5 -71l-168 10 q0 111 65.5 189t160.5 78q30 0 56.5 -7.5t86.5 -36.5t83 -35t48 -6q35 0 60.5 24.5t25.5 70.5z"/> +<glyph glyph-name="ograve" horiz-adv-x="1158" unicode="ò" d="M66 551q0 161 62 287t178.5 195t270.5 69q219 0 357.5 -134t154.5 -364l2 -74q0 -249 -139 -399.5t-373 -150.5t-373.5 150t-139.5 408v13zM355 530q0 -154 58 -235.5t166 -81.5q105 0 164 80.5t59 257.5q0 151 -59 234t-166 83q-106 0 -164 -82.5t-58 -255.5zM720 1226 h-237l-276 310h315z"/> +<glyph glyph-name="oacute" horiz-adv-x="1158" unicode="ó" d="M66 551q0 161 62 287t178.5 195t270.5 69q219 0 357.5 -134t154.5 -364l2 -74q0 -249 -139 -399.5t-373 -150.5t-373.5 150t-139.5 408v13zM355 530q0 -154 58 -235.5t166 -81.5q105 0 164 80.5t59 257.5q0 151 -59 234t-166 83q-106 0 -164 -82.5t-58 -255.5zM634 1536 h315l-277 -310h-235z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1158" unicode="ô" d="M66 551q0 161 62 287t178.5 195t270.5 69q219 0 357.5 -134t154.5 -364l2 -74q0 -249 -139 -399.5t-373 -150.5t-373.5 150t-139.5 408v13zM355 530q0 -154 58 -235.5t166 -81.5q105 0 164 80.5t59 257.5q0 151 -59 234t-166 83q-106 0 -164 -82.5t-58 -255.5zM960 1256 v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="otilde" horiz-adv-x="1158" unicode="õ" d="M66 551q0 161 62 287t178.5 195t270.5 69q219 0 357.5 -134t154.5 -364l2 -74q0 -249 -139 -399.5t-373 -150.5t-373.5 150t-139.5 408v13zM355 530q0 -154 58 -235.5t166 -81.5q105 0 164 80.5t59 257.5q0 151 -59 234t-166 83q-106 0 -164 -82.5t-58 -255.5zM952 1523 q0 -113 -66 -189.5t-161 -76.5q-38 0 -67.5 8.5t-81.5 36.5t-75 34.5t-50 6.5q-35 0 -59.5 -25t-24.5 -71l-168 10q0 111 65.5 189t160.5 78q30 0 56.5 -7.5t86.5 -36.5t83 -35t48 -6q35 0 60.5 24.5t25.5 70.5z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1158" unicode="ö" d="M66 551q0 161 62 287t178.5 195t270.5 69q219 0 357.5 -134t154.5 -364l2 -74q0 -249 -139 -399.5t-373 -150.5t-373.5 150t-139.5 408v13zM355 530q0 -154 58 -235.5t166 -81.5q105 0 164 80.5t59 257.5q0 151 -59 234t-166 83q-106 0 -164 -82.5t-58 -255.5zM193 1365 q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM680 1365q0 53 39.5 90t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="ugrave" horiz-adv-x="1146" unicode="ù" d="M759 110q-107 -130 -296 -130q-174 0 -265.5 100t-93.5 293v709h289v-699q0 -169 154 -169q147 0 202 102v766h290v-1082h-272zM716 1226h-237l-276 310h315z"/> +<glyph glyph-name="uacute" horiz-adv-x="1146" unicode="ú" d="M759 110q-107 -130 -296 -130q-174 0 -265.5 100t-93.5 293v709h289v-699q0 -169 154 -169q147 0 202 102v766h290v-1082h-272zM630 1536h315l-277 -310h-235z"/> +<glyph glyph-name="ucircumflex" horiz-adv-x="1146" unicode="û" d="M759 110q-107 -130 -296 -130q-174 0 -265.5 100t-93.5 293v709h289v-699q0 -169 154 -169q147 0 202 102v766h290v-1082h-272zM956 1256v-12h-230l-154 145l-154 -145h-226v16l296 276h168z"/> +<glyph glyph-name="udieresis" horiz-adv-x="1146" unicode="ü" d="M759 110q-107 -130 -296 -130q-174 0 -265.5 100t-93.5 293v709h289v-699q0 -169 154 -169q147 0 202 102v766h290v-1082h-272zM189 1365q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM676 1365q0 53 39.5 90 t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +<glyph glyph-name="yacute" horiz-adv-x="1028" unicode="ý" d="M515 409l200 673h310l-435 -1250l-24 -57q-97 -212 -320 -212q-63 0 -128 19v219l44 -1q82 0 122.5 25t63.5 83l34 89l-379 1085h311zM578 1536h315l-277 -310h-235z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="1028" unicode="ÿ" d="M515 409l200 673h310l-435 -1250l-24 -57q-97 -212 -320 -212q-63 0 -128 19v219l44 -1q82 0 122.5 25t63.5 83l34 89l-379 1085h311zM137 1365q0 54 38.5 90.5t99.5 36.5q62 0 100 -37.5t38 -89.5t-38 -89t-100 -37q-59 0 -98.5 35.5t-39.5 90.5zM624 1365q0 53 39.5 90 t98.5 37q58 0 98.5 -36.5t40.5 -90.5q0 -52 -38.5 -89.5t-100.5 -37.5t-100 37.5t-38 89.5z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..41821dcabc2a4a221befb5bec40a856b2e7f840e Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff new file mode 100644 index 0000000000000000000000000000000000000000..1e71acf7f97b4a5a4b128c85f3fe5e2662bacc2d Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2 b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..1cb06f8ad7a42daf6e00128f3cbc0ee9d2392486 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Bold/RobotoDraft-Bold.woff2 differ diff --git a/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.eot b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.eot new file mode 100644 index 0000000000000000000000000000000000000000..e63e5738b907e6e8df10ce173090c9c9def37db2 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.svg b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.svg new file mode 100644 index 0000000000000000000000000000000000000000..72288ae40e3edaa2f57d319d034c455c189cab4e --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.svg @@ -0,0 +1,233 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-BoldItalic" horiz-adv-x="1150"> +<font-face slope="-12" underline-position="-100" font-weight="700" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-262 -466 1973 1936" x-height="1082" underline-thickness="100" font-family="RobotoDraft" ascent="1536" font-style="italic" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="918"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1219" unicode="fi" d="M71 0l151 870h-157l38 212h146l9 52q37 204 173 315.5t349 109.5q83 -2 162.5 -19.5t158.5 -39.5l-61 -241q-138 48 -255 50q-99 0 -163 -47.5t-83 -133.5l-9 -46h219l-38 -212h-206l-151 -870h-283zM982 0h-284l188 1082h283z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1227" unicode="fl" d="M937 1314q-86 12 -147 12q-93 0 -152.5 -43t-74.5 -122l-13 -79h209l-37 -212h-208l-151 -870h-284l151 870h-156l37 212l156 1l12 93q26 176 148 278.5t318 105.5h17l173 -7l311 -27l-257 -1526h-283z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="918"/> +<glyph glyph-name="glyph1" horiz-adv-x="10"/> +<glyph glyph-name="glyph1" horiz-adv-x="10"/> +<glyph glyph-name="glyph2" horiz-adv-x="10"/> +<glyph glyph-name="uni000D" horiz-adv-x="505" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="505" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="550" unicode="!" d="M369 447h-235l142 1009h301zM41 131q-2 66 42 111.5t112 47.5q64 2 111 -39.5t49 -108.5q2 -66 -42 -112t-113 -48q-70 0 -114.5 44t-44.5 105z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="647" unicode='"' d="M381 1382l-99 -395h-161l87 549h198zM697 1382l-99 -395h-160l86 549h197z"/> +<glyph glyph-name="numbersign" horiz-adv-x="1193" unicode="#" d="M611 410h-179l-142 -410h-186l142 410h-218l30 172h247l97 284h-222l31 174h251l144 416h184l-143 -416h180l143 416h186l-143 -416h209l-30 -174h-239l-98 -284h214l-30 -172h-243l-141 -410h-186zM490 582h179l98 284h-180z"/> +<glyph glyph-name="dollar" d="M737 390q10 70 -23 121t-135.5 97t-169.5 91q-205 138 -190 363q11 172 129 281.5t309 129.5l41 214h157l-42 -220q152 -32 231.5 -152t74.5 -311l-283 1q12 236 -139 239q-79 2 -133 -48.5t-65 -132.5q-9 -64 22.5 -113t121 -92t150.5 -80q239 -144 223 -386 q-11 -174 -128.5 -281t-311.5 -127l-39 -199h-156l39 200q-176 26 -268.5 151.5t-86.5 321.5l282 -1q-5 -121 39.5 -182t133.5 -63q85 -2 145 47.5t72 130.5z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1477" unicode="%" d="M525 1478q134 -4 211.5 -89t69.5 -213l-6 -77q-14 -137 -108 -220t-227 -79q-130 2 -208.5 85t-72.5 214l5 67q11 142 103.5 228t232.5 84zM373 1095q-5 -56 18.5 -92t74.5 -38t90.5 34.5t51.5 99.5l10 78q7 59 -17.5 95.5t-74.5 38.5q-55 2 -94.5 -37t-48.5 -98z M723 357q12 136 106 219.5t230 81.5q133 -4 211 -88t70 -213l-5 -67q-11 -145 -105.5 -230t-230.5 -81q-128 2 -208.5 85.5t-72.5 214.5zM904 277q-5 -55 21 -92.5t74 -39.5q58 -2 95 34t48 100l10 80q7 59 -18 94.5t-74 37.5q-54 2 -93.5 -34.5t-51.5 -99.5zM386 111 l-139 85l878 1124l137 -83z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1314" unicode="&" d="M41 385q10 183 217 325l98 63l-40 90q-52 126 -45 223q8 115 65 205.5t152 139t207 45.5q147 -4 241 -97.5t88 -233.5q-10 -189 -227 -332l-114 -75l188 -282q84 120 101 258h239q-19 -282 -193 -465l168 -249h-302l-55 84q-180 -107 -371 -103q-190 2 -309 114.5 t-108 289.5zM480 213q87 -3 209 59l-214 330l-24 -16q-106 -79 -121 -187q-11 -83 32 -133.5t118 -52.5zM518 1090q-4 -24 -1 -47q7 -53 49 -134l82 50q124 75 133 169q6 50 -22.5 83t-77.5 33q-62 2 -108 -43t-55 -111z"/> +<glyph glyph-name="quotesingle" horiz-adv-x="331" unicode="'" d="M389 1373l-88 -388h-181l87 551h207z"/> +<glyph glyph-name="parenleft" horiz-adv-x="707" unicode="(" d="M122 588q48 357 213.5 638.5t415.5 392.5l48 -161q-342 -261 -433 -839q-31 -196 -33 -352q-5 -411 188 -571l-63 -151q-216 120 -302 415q-57 198 -51 424q2 95 13 180z"/> +<glyph glyph-name="parenright" horiz-adv-x="710" unicode=")" d="M-56 -458l-48 158q343 265 433 848q29 187 31 345q5 411 -186 572l63 151q118 -64 202.5 -186.5t125 -295.5t38.5 -356q-6 -278 -96 -540.5t-235.5 -440.5t-327.5 -255z"/> +<glyph glyph-name="asterisk" horiz-adv-x="910" unicode="*" d="M392 966l-292 92l85 170l287 -128l43 356h192l-80 -347l307 118l26 -193l-328 -89l161 -272l-161 -104l-126 293l-222 -278l-149 119z"/> +<glyph glyph-name="plus" horiz-adv-x="1094" unicode="+" d="M712 815h350l-46 -261h-349l-71 -408h-269l71 408h-352l46 261h351l68 391h269z"/> +<glyph glyph-name="comma" horiz-adv-x="495" unicode="," d="M31 -365l-149 81l73 117q64 107 82 201l37 212h238l-29 -184q-41 -259 -252 -427z"/> +<glyph glyph-name="hyphen" horiz-adv-x="780" unicode="-" d="M638 507h-548l40 233h549z"/> +<glyph glyph-name="period" horiz-adv-x="587" unicode="." d="M200 298q67 2 114.5 -41.5t47.5 -109.5q2 -66 -44 -112.5t-113 -46.5q-67 -2 -113 40t-48 109t43 113t113 48z"/> +<glyph glyph-name="slash" horiz-adv-x="752" unicode="/" d="M77 -125h-222l794 1581h223z"/> +<glyph glyph-name="zero" d="M485 -20q-189 4 -292 128t-106 346q-1 74 8 148l41 273q49 298 193 452t369 149q189 -4 292.5 -127.5t106.5 -344.5q1 -75 -8 -149l-42 -271q-50 -300 -192.5 -454.5t-369.5 -149.5zM824 1038q0 199 -140 206q-202 9 -257 -308l-50 -338q-16 -106 -16 -176 q-5 -203 139 -210q203 -13 258 317l53 356q13 87 13 153z" unicode="0"/> +<glyph glyph-name="one" d="M674 0h-282l192 1108l-354 -107l44 247l608 210l37 1z" unicode="1"/> +<glyph glyph-name="two" d="M971 0h-970l33 210l517 485q159 149 211 242t39 182q-21 124 -143 127q-96 2 -160.5 -67t-78.5 -181l-282 -1q8 136 81 247t194.5 172.5t262.5 60.5q203 -4 316 -114t100 -293q-16 -206 -243 -430l-144 -137l-298 -268l602 -2z" unicode="2"/> +<glyph glyph-name="three" d="M422 856l135 -1q103 0 172.5 57t80.5 153q10 81 -31 129.5t-123 50.5t-140.5 -44.5t-71.5 -120.5l-282 -2q9 176 151.5 288.5t346.5 110.5q206 -4 326 -115t109 -294q-14 -208 -265 -326q98 -47 143.5 -133.5t39.5 -192.5q-7 -132 -81 -232t-198 -153.5t-268 -50.5 q-195 2 -318 117t-121 303h280q-2 -81 45.5 -132.5t132.5 -53.5q98 -2 168 55.5t82 150.5q13 100 -35.5 153t-147.5 56l-166 1z" unicode="3"/> +<glyph glyph-name="four" d="M918 548h160l-41 -233h-160l-55 -315h-282l55 315h-578l20 197l743 944h295zM330 550l306 -2l99 518l-26 -36z" unicode="4"/> +<glyph glyph-name="five" d="M154 720l196 736h796l-38 -241h-559l-96 -315q89 56 210 56q187 0 289.5 -132.5t86.5 -349.5q-12 -144 -84.5 -259t-190.5 -177t-260 -59q-123 1 -223.5 56.5t-156.5 153t-57 217.5h277q4 -89 49 -139.5t122 -52.5q100 -3 164.5 73t77.5 204q12 114 -34.5 180t-141.5 68 q-106 2 -196 -78z" unicode="5"/> +<glyph glyph-name="six" d="M991 1472l-22 -239l-55 -1q-343 -18 -495 -378q125 123 293 119q118 -2 199.5 -66t119.5 -175t27 -245q-12 -143 -85.5 -261.5t-192.5 -184t-257 -62.5q-143 4 -245.5 80.5t-149.5 209.5t-31 290l11 90q47 376 275.5 599.5t569.5 223.5h38zM616 743q-73 2 -131 -36 t-96 -97l-13 -90q-5 -45 -4 -98q2 -94 43 -151t116 -58q74 -3 135 48t90 137t19 175q-9 78 -50.5 123.5t-108.5 46.5z" unicode="6"/> +<glyph glyph-name="seven" d="M1164 1279l-740 -1279h-311l738 1222h-696l37 234h999z" unicode="7"/> +<glyph glyph-name="eight" d="M1104 1077q-14 -213 -250 -333q85 -59 127 -146t35 -190q-11 -196 -159 -314t-366 -114q-199 2 -319.5 114t-109.5 296q14 242 285 366q-147 117 -137 305q7 124 73 220t177.5 147t243.5 48q189 -4 300 -112.5t100 -286.5zM738 428q11 86 -31 143t-124 59 q-91 2 -156.5 -59t-78.5 -160q-11 -86 30.5 -141.5t125.5 -57.5q92 -2 156.5 58t77.5 158zM819 1063q9 82 -26 130.5t-104 50.5q-79 2 -134 -52.5t-66 -144.5q-9 -81 24.5 -132.5t104.5 -53.5q78 -2 134 54.5t67 147.5z" unicode="8"/> +<glyph glyph-name="nine" d="M763 583q-123 -114 -263 -112q-120 1 -204 64t-124.5 175.5t-28.5 243.5q14 161 102 291t229 192q93 41 204 39q180 -4 287 -126t121 -327q4 -71 -3 -141l-11 -86q-49 -381 -271.5 -596t-570.5 -215h-21l22 242h15q197 -3 324 85.5t193 270.5zM578 691q120 -4 212 123 l17 121q5 42 5 95q-2 96 -40 154t-110 60q-72 1 -129.5 -51.5t-87 -143.5t-21.5 -181q7 -80 47.5 -128t106.5 -49z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="571" unicode=":" d="M199 298q67 2 114.5 -41.5t47.5 -109.5q2 -66 -44 -112.5t-113 -46.5q-67 -2 -113 40t-48 109t43 113t113 48zM340 1117q67 2 114.5 -41.5t47.5 -109.5q2 -66 -44 -112.5t-113 -46.5q-67 -2 -113 40t-48 109t43 113t113 48z"/> +<glyph glyph-name="semicolon" horiz-adv-x="531" unicode=";" d="M323 1117q67 2 114.5 -41.5t47.5 -109.5q2 -66 -44 -112.5t-113 -46.5q-67 -2 -113 40t-48 109t43 113t113 48zM52 -365l-149 81l73 117q64 107 82 201l37 212h238l-29 -184q-41 -259 -252 -427z"/> +<glyph glyph-name="less" horiz-adv-x="1021" unicode="<" d="M337 612l519 -201l-46 -267l-774 365l41 236l901 365l-52 -293z"/> +<glyph glyph-name="equal" horiz-adv-x="1147" unicode="=" d="M1025 746h-869l42 236h869zM950 313h-869l42 236h869z"/> +<glyph glyph-name="greater" horiz-adv-x="1036" unicode=">" d="M685 627l-530 203l47 265l783 -365l-41 -235l-911 -366l52 292z"/> +<glyph glyph-name="question" horiz-adv-x="998" unicode="?" d="M321 446q9 130 53.5 219.5t138 165t125.5 110.5q86 95 75 202q-10 97 -113 100q-71 2 -120 -45t-65 -128l-283 -2q13 190 146.5 301.5t335.5 107.5q189 -4 295 -108t93 -277q-12 -170 -194 -323l-128 -106q-92 -85 -112 -216zM228 134q-2 67 43 113t113 48 q64 2 111 -40.5t49 -109.5q2 -63 -42 -110t-114 -49q-67 0 -112.5 41t-47.5 107z"/> +<glyph glyph-name="at" horiz-adv-x="1788" unicode="@" d="M1194 -21q-172 5 -218 143q-126 -144 -268 -141q-120 2 -182.5 97.5t-54.5 251.5q6 155 83 318t194.5 254t259.5 89q73 -2 137.5 -25t155.5 -83l-134 -582l-7 -53q-11 -105 74 -110q126 -5 204 148t95 377l3 51q5 161 -45 284t-158 187.5t-265 67.5q-164 3 -311.5 -69.5 t-263.5 -213.5t-182.5 -323.5t-73.5 -369.5q-9 -211 74 -353q117 -198 397 -201q161 -2 338 68l28 -158q-129 -86 -365 -86q-201 2 -338.5 76t-216.5 199t-100 289q-30 225 36.5 471t215 441t345 295.5t414.5 97.5q293 -5 462.5 -178.5t182.5 -472.5q6 -169 -40 -336 t-136 -282q-136 -173 -340 -168zM690 320q-11 -160 90 -163q54 -3 109 49t80 120l127 478q-31 11 -69 13q-126 5 -210 -108t-121 -331z"/> +<glyph glyph-name="A" horiz-adv-x="1347" unicode="A" d="M877 300h-508l-150 -300h-323l778 1456h271l277 -1456h-299zM489 543h351l-82 542z"/> +<glyph glyph-name="B" horiz-adv-x="1278" unicode="B" d="M21 0l253 1456l454 -1q253 -1 380 -103t115 -287q-14 -221 -255 -323q87 -30 135 -112.5t41 -194.5q-14 -206 -161.5 -320.5t-402.5 -114.5h-559zM425 634l-69 -393l231 -1q108 0 181 53.5t87 144.5q14 90 -24.5 140.5t-129.5 54.5zM461 846l199 -2q111 2 181.5 52 t84.5 139q25 176 -185 177l-216 1z"/> +<glyph glyph-name="C" horiz-adv-x="1310" unicode="C" d="M1208 486q-17 -151 -103 -267.5t-224 -179t-298 -59.5q-144 3 -251 66.5t-168.5 184t-69.5 277.5q-7 123 25.5 306t116 325t198.5 225q162 116 370 112q226 -4 358.5 -139.5t145.5 -376.5l-292 1q0 138 -55 202t-171 68q-150 5 -246.5 -107t-129.5 -327 q-32 -209 -28 -313q5 -132 59 -194.5t151 -65.5q134 -5 214.5 63.5t106.5 196.5z"/> +<glyph glyph-name="D" horiz-adv-x="1301" unicode="D" d="M21 0l253 1456l418 -1q147 -3 264.5 -66.5t190.5 -182.5t88 -268q8 -87 -2 -178l-7 -53q-44 -320 -251.5 -513.5t-503.5 -193.5h-450zM525 1213l-169 -972l122 -1q202 0 324.5 148t140.5 447l2 32q3 165 -63 253t-197 92z"/> +<glyph glyph-name="E" horiz-adv-x="1127" unicode="E" d="M982 631h-558l-68 -390h656l-42 -241h-949l253 1456h947l-43 -243h-653l-61 -347h560z"/> +<glyph glyph-name="F" horiz-adv-x="1098" unicode="F" d="M976 595h-558l-104 -595h-293l253 1456h922l-43 -243h-628l-66 -376h560z"/> +<glyph glyph-name="G" horiz-adv-x="1363" unicode="G" d="M1188 184q-78 -99 -228.5 -152.5t-339.5 -50.5q-149 1 -262 65.5t-178 185.5t-74 276q-10 144 30.5 338.5t139 341t236.5 219t306 69.5q228 -4 357 -128.5t147 -356.5l-282 1q-11 122 -65 180t-161 62q-185 6 -291.5 -162.5t-121.5 -488.5q-10 -171 52.5 -265t190.5 -96 q149 -4 254 71l49 251h-266l39 221h556z"/> +<glyph glyph-name="H" horiz-adv-x="1414" unicode="H" d="M1173 0h-293l108 624h-565l-109 -624h-293l253 1456h293l-103 -590h566l102 590h293z"/> +<glyph glyph-name="I" horiz-adv-x="589" unicode="I" d="M333 0h-293l252 1456h293z"/> +<glyph glyph-name="J" horiz-adv-x="1120" unicode="J" d="M846 1456h293l-171 -1008q-18 -138 -92 -247t-190 -167t-255 -55q-206 4 -318 122t-106 330l295 -1q-15 -206 145 -209q87 -3 148 58t79 169z"/> +<glyph glyph-name="K" horiz-adv-x="1271" unicode="K" d="M576 581l-192 -178l-70 -403h-293l253 1456h293l-112 -642l149 168l438 474h382l-629 -662l375 -794h-334z"/> +<glyph glyph-name="L" horiz-adv-x="1086" unicode="L" d="M356 241h618l-42 -241h-911l253 1456h293z"/> +<glyph glyph-name="M" horiz-adv-x="1750" unicode="M" d="M650 1456l179 -1053l543 1053h390l-253 -1456h-294l72 415l142 648l-558 -1063h-201l-195 1100l-94 -717l-67 -383h-293l253 1456h376z"/> +<glyph glyph-name="N" horiz-adv-x="1413" unicode="N" d="M1172 0h-284l-405 971l-169 -971h-293l253 1456h283l406 -973l169 973h292z"/> +<glyph glyph-name="O" horiz-adv-x="1382" unicode="O" d="M606 -20q-145 3 -255.5 68.5t-175 189t-74.5 283.5q-11 164 35 350t148 327t239.5 211t297.5 67q147 -3 257 -69.5t173 -191t72 -282.5q10 -176 -38 -362t-149 -322t-236.5 -204t-293.5 -65zM1021 768l8 95q10 178 -47.5 270t-174.5 96q-183 6 -290.5 -162t-121.5 -470 q-10 -177 47 -272.5t177 -99.5q157 -7 260 122.5t135 366.5z"/> +<glyph glyph-name="P" horiz-adv-x="1291" unicode="P" d="M404 513l-90 -513h-293l253 1456l510 -1q236 0 371 -131t118 -342q-16 -214 -178.5 -342t-414.5 -128zM445 756l244 -2q118 0 196 61t93 165t-33.5 166t-143.5 66l-276 1z"/> +<glyph glyph-name="Q" horiz-adv-x="1382" unicode="Q" d="M958 95l202 -198l-200 -157l-255 248q-57 -9 -106 -7q-218 2 -352 148t-149 393q-9 123 18 274.5t90 278.5t154.5 218t208.5 138.5t248 44.5q146 -3 256 -69t174 -190t73 -284q5 -87 -5 -174l-17 -115q-67 -372 -340 -549zM1026 863q7 185 -50.5 273.5t-172.5 92.5 q-183 6 -290.5 -162t-121.5 -470q-10 -177 47 -272.5t177 -99.5q157 -7 260 122.5t135 366.5q13 96 16 149z"/> +<glyph glyph-name="R" horiz-adv-x="1278" unicode="R" d="M645 533h-238l-93 -533h-293l253 1456l482 -1q242 0 372.5 -114t115.5 -317q-21 -300 -320 -417l205 -591v-16h-312zM449 776l218 -2q116 2 191.5 62.5t90.5 164.5q14 97 -31 152t-143 59l-250 1z"/> +<glyph glyph-name="S" horiz-adv-x="1231" unicode="S" d="M822 389q21 119 -117 182l-193 77q-336 150 -319 413q7 122 80 216t205 147.5t285 51.5q211 -4 341 -125.5t128 -325.5h-292q5 99 -43.5 154t-150.5 57q-100 2 -174 -45.5t-88 -130.5q-19 -109 146 -173l132 -50l76 -35q295 -146 276 -410q-9 -129 -82.5 -222.5 t-200 -143.5t-278.5 -47q-155 3 -276 65t-184 175q-59 105 -55 240l293 -1q-14 -237 233 -241q107 0 176 47t82 125z"/> +<glyph glyph-name="T" horiz-adv-x="1239" unicode="T" d="M1296 1213h-432l-210 -1213h-293l210 1213h-427l43 243h1152z"/> +<glyph glyph-name="U" horiz-adv-x="1318" unicode="U" d="M1349 1456l-164 -960q-34 -241 -200 -381t-412 -136q-154 3 -267.5 67.5t-167.5 182t-37 266.5l163 961h293l-163 -962q-7 -56 -1 -105q20 -162 193 -168q124 -4 203 68t102 206l164 961h294z"/> +<glyph glyph-name="V" horiz-adv-x="1309" unicode="V" d="M606 364l490 1092h336l-719 -1456h-306l-262 1456h315z"/> +<glyph glyph-name="W" horiz-adv-x="1747" unicode="W" d="M1195 423l351 1033h299l-541 -1456h-295l-77 970l-381 -970h-295l-86 1456h286l29 -1028l392 1028h249z"/> +<glyph glyph-name="X" horiz-adv-x="1272" unicode="X" d="M679 956l343 500h352l-535 -736l302 -720h-324l-191 508l-351 -508h-356l547 748l-293 708h320z"/> +<glyph glyph-name="Y" horiz-adv-x="1238" unicode="Y" d="M640 802l407 654h336l-636 -944l-88 -512h-298l95 545l-302 910l309 1z"/> +<glyph glyph-name="Z" horiz-adv-x="1214" unicode="Z" d="M378 243l708 -2l-42 -241h-1078l33 191l871 1020l-693 2l43 243h1061l-33 -187z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="562" unicode="[" d="M673 1471h-138l-248 -1587h138l-35 -223h-421l318 2033h421z"/> +<glyph glyph-name="backslash" horiz-adv-x="848" unicode="\" d="M154 1456h275l316 -1581h-276z"/> +<glyph glyph-name="bracketright" horiz-adv-x="562" unicode="]" d="M183 1694h421l-318 -2033h-421l35 223h139l248 1587h-139z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="878" unicode="^" d="M543 1183l-247 -454h-239l417 727h205l164 -727h-211z"/> +<glyph glyph-name="underscore" horiz-adv-x="897" unicode="_" d="M743 -226h-886l40 226h885z"/> +<glyph glyph-name="grave" horiz-adv-x="667" unicode="`" d="M638 1226l-211 1l-223 307l291 2z"/> +<glyph glyph-name="a" horiz-adv-x="1075" unicode="a" d="M629 0q-13 41 -11 98q-122 -122 -276 -118q-142 2 -235.5 92.5t-87.5 223.5q7 177 148.5 271.5t379.5 94.5l132 -2l14 65q6 33 3 63q-5 47 -35.5 73.5t-80.5 27.5q-66 2 -112 -32.5t-59 -99.5l-283 -1q7 155 142.5 251.5t334.5 94.5q184 -4 288 -109.5t87 -271.5 l-83 -518l-5 -64q-2 -71 17 -120l-1 -19h-277zM412 199q122 -4 213 106l35 187l-98 1q-156 -4 -225 -95q-25 -33 -31 -81q-8 -54 22.5 -85.5t83.5 -32.5z"/> +<glyph glyph-name="b" horiz-adv-x="1128" unicode="b" d="M1043 538q-30 -256 -156 -410t-326 -149q-171 4 -260 138l-41 -117h-257l266 1536h283l-109 -553q114 123 264 119q157 -2 246.5 -112.5t95.5 -305.5q2 -62 -6 -146zM763 559q9 85 6 132q-11 174 -144 177q-125 4 -207 -113l-78 -430q38 -108 162 -112q208 -6 255 302z "/> +<glyph glyph-name="c" horiz-adv-x="1046" unicode="c" d="M477 212q78 -2 130 42.5t68 118.5l265 1q-7 -114 -71.5 -205t-172 -142t-226.5 -48q-197 3 -312 136t-111 354l3 55l1 11q27 264 178 418.5t373 148.5q183 -4 290.5 -119.5t105.5 -304.5h-263q0 87 -38 137t-114 54q-202 6 -245 -295q-15 -109 -11 -184q10 -175 150 -178 z"/> +<glyph glyph-name="d" horiz-adv-x="1129" unicode="d" d="M540 1103q151 -4 244 -121l106 554h283l-266 -1536h-252l16 116q-121 -141 -282 -137q-101 1 -177 53t-117.5 149.5t-45.5 217.5q-3 63 3 122l6 45q24 166 92.5 292t168 187t221.5 58zM335 521q-8 -76 -5 -128q10 -176 142 -179q119 -5 207 112l77 430q-39 107 -156 112 q-103 3 -171.5 -79.5t-93.5 -267.5z"/> +<glyph glyph-name="e" horiz-adv-x="1084" unicode="e" d="M517 -20q-142 1 -251.5 69.5t-163.5 188t-42 263.5l3 40q15 158 92 290t198 203.5t268 67.5q209 -4 316.5 -153.5t81.5 -378.5l-16 -123h-663q-4 -105 51 -168t150 -65q154 -4 270 119l129 -160q-61 -92 -176 -143.5t-247 -49.5zM607 869q-78 2 -138.5 -49t-108.5 -177 h388l6 26q6 40 1 76q-10 58 -49 90.5t-99 33.5z"/> +<glyph glyph-name="f" horiz-adv-x="722" unicode="f" d="M79 0l151 870h-156l37 212l156 1l14 108q26 173 141 271.5t293 96.5q61 -2 153 -21l-25 -225q-48 12 -83 12q-75 1 -128.5 -38t-66.5 -117l-15 -88h209l-37 -212h-208l-151 -870h-284z"/> +<glyph glyph-name="g" horiz-adv-x="1144" unicode="g" d="M57 542q30 251 163.5 407.5t336.5 153.5q173 -4 258 -125l37 105l259 -1l-177 -1045q-29 -216 -184 -342t-384 -122q-112 2 -214 48.5t-168 127.5l140 172q94 -119 236 -123q110 -4 188 57.5t106 173.5l16 65q-118 -118 -265 -114q-158 2 -251 117.5t-102 300.5 q-3 61 5 144zM334 424q0 -94 39.5 -150.5t114.5 -59.5q115 -4 204 98l84 458q-43 94 -159 98q-108 3 -183 -87t-94 -239q-7 -73 -6 -118z"/> +<glyph glyph-name="h" horiz-adv-x="1122" unicode="h" d="M433 962q127 142 293 140q161 -4 236.5 -115.5t56.5 -304.5l-114 -682h-282l115 685q5 39 2 72q-10 108 -126 111q-114 4 -200 -98l-136 -770h-282l266 1536h283z"/> +<glyph glyph-name="i" horiz-adv-x="537" unicode="i" d="M301 0h-284l188 1082h284zM238 1357q-2 67 44 111t111 44q64 2 111 -39t49 -106q2 -62 -41.5 -108t-113.5 -48q-63 -2 -110.5 38t-49.5 108z"/> +<glyph glyph-name="j" horiz-adv-x="526" unicode="j" d="M490 1082l-194 -1141q-23 -181 -130.5 -282t-277.5 -99q-68 2 -150 19l23 230q50 -11 87 -13q133 -2 162 144l196 1142h284zM233 1357q-2 66 42 109.5t113 45.5q69 0 113.5 -41t46.5 -104q2 -67 -42 -110.5t-113 -45.5q-63 -2 -110.5 38t-49.5 108z"/> +<glyph glyph-name="k" horiz-adv-x="1071" unicode="k" d="M471 431l-131 -114l-55 -317h-282l266 1536h283l-146 -834l55 59l321 321h362l-473 -465l301 -617h-309z"/> +<glyph glyph-name="l" horiz-adv-x="537" unicode="l" d="M301 0h-284l267 1536h283z"/> +<glyph glyph-name="m" horiz-adv-x="1730" unicode="m" d="M453 1083l-23 -123q131 146 317 142q100 -2 166 -46t89 -119q143 169 336 165q149 -3 224.5 -102t63.5 -286l-2 -25l-115 -689h-283l115 691q4 37 3 69q-7 105 -120 108q-116 0 -199 -124l-3 -23l-126 -721h-282l115 689q4 37 3 69q-7 106 -119 109q-107 3 -193 -101 l-135 -766h-282l187 1082z"/> +<glyph glyph-name="n" horiz-adv-x="1123" unicode="n" d="M449 1083l-24 -128q130 151 315 147q153 -3 226 -112t53 -302l-114 -688h-282l116 691q5 39 2 71q-13 102 -128 105q-111 4 -199 -103l-135 -764h-282l188 1082z"/> +<glyph glyph-name="o" horiz-adv-x="1133" unicode="o" d="M622 1102q143 -2 246.5 -73.5t152 -197t34.5 -278.5q-23 -258 -179.5 -417.5t-386.5 -155.5q-141 2 -244 72.5t-152 195.5t-35 276q26 268 182 426t382 152zM337 421q2 -96 45 -151.5t121 -57.5q130 -4 204 119.5t69 324.5q-4 96 -46.5 153.5t-121.5 59.5 q-126 4 -201.5 -118.5t-69.5 -329.5z"/> +<glyph glyph-name="p" horiz-adv-x="1128" unicode="p" d="M1042 538q-21 -170 -89 -302t-169 -196t-224 -61q-157 4 -248 117l-99 -512h-282l259 1498l260 1l-19 -109q117 132 276 128t247 -115.5t94 -302.5q2 -62 -6 -146zM762 559l6 96q2 97 -35.5 154t-109.5 59q-123 4 -203 -104l-81 -446q37 -101 159 -105q102 -3 170 79 t94 267z"/> +<glyph glyph-name="q" horiz-adv-x="1132" unicode="q" d="M540 1103q168 -4 257 -136l46 116l252 -1l-260 -1498h-284l101 511q-113 -119 -263 -115q-101 1 -177 53t-117.5 150.5t-45.5 216.5q-3 63 3 123l6 44q24 168 92.5 294t168 185.5t221.5 56.5zM331 394q10 -178 142 -181q119 -4 204 105l82 450q-39 97 -157 101 q-106 3 -175 -83.5t-89 -241.5q-10 -103 -7 -150z"/> +<glyph glyph-name="r" horiz-adv-x="735" unicode="r" d="M744 811q-58 10 -95 10q-151 4 -239 -113l-125 -708h-282l188 1082l265 1l-26 -132q102 153 252 153q42 0 98 -14z"/> +<glyph glyph-name="s" horiz-adv-x="1031" unicode="s" d="M630 305q16 80 -111 116l-91 23q-323 89 -314 314q5 153 135.5 249.5t314.5 94.5q183 -2 296 -97t115 -253l-280 1q2 139 -138 141q-66 0 -114.5 -33t-59.5 -89q-15 -80 121 -113l40 -9q138 -33 211 -75.5t112.5 -105.5t36.5 -151q-3 -103 -66.5 -180t-174 -119 t-232.5 -39q-180 2 -300 103.5t-122 262.5l266 -2q4 -155 166 -157q78 0 128.5 32t60.5 86z"/> +<glyph glyph-name="t" horiz-adv-x="681" unicode="t" d="M575 1348l-47 -266h180l-37 -212h-180l-92 -542q-6 -51 8 -78t68 -29q16 -1 86 5l-20 -221q-75 -25 -162 -23q-139 2 -207 87t-56 230l93 571h-153l37 212h153l46 266h283z"/> +<glyph glyph-name="u" horiz-adv-x="1122" unicode="u" d="M673 112q-120 -135 -298 -132q-156 2 -236 112t-62 290l117 700h282l-119 -703q-4 -33 -1 -62q10 -100 111 -103q131 -4 217 101l135 767h284l-188 -1082h-263z"/> +<glyph glyph-name="v" horiz-adv-x="1014" unicode="v" d="M458 357l308 725h304l-523 -1082h-270l-185 1082h286z"/> +<glyph glyph-name="w" horiz-adv-x="1470" unicode="w" d="M980 394l257 688h281l-455 -1082h-236l-80 677l-316 -677h-236l-80 1082h264l17 -681l309 681h204z"/> +<glyph glyph-name="x" horiz-adv-x="1021" unicode="x" d="M524 761l227 321h317l-392 -544l219 -538h-286l-133 338l-239 -338h-319l408 566l-209 516h286z"/> +<glyph glyph-name="y" horiz-adv-x="1007" unicode="y" d="M462 412l309 670h314l-633 -1245q-68 -143 -159.5 -210t-211.5 -67q-47 0 -136 21l21 220l39 -2q138 -4 202 101l62 115l-177 1067h292z"/> +<glyph glyph-name="z" horiz-adv-x="1021" unicode="z" d="M371 235l510 -2l-41 -233h-873l33 191l603 655l-475 2l41 234h843l-32 -185z"/> +<glyph glyph-name="braceleft" horiz-adv-x="666" unicode="{" d="M438 -360q-158 53 -235 173q-77 121 -59 293l28 205q5 42 2 78q-10 113 -135 124l19 207q185 8 215 222l32 230q59 325 404 429l47 -166q-168 -65 -201 -304l-32 -229q-34 -193 -223 -289q69 -51 101 -128.5t23 -175.5l-31 -236l-4 -57q-7 -162 110 -215z"/> +<glyph glyph-name="bar" horiz-adv-x="512" unicode="|" d="M203 -270h-172l270 1726h172z"/> +<glyph glyph-name="braceright" horiz-adv-x="666" unicode="}" d="M-94 -197q168 65 201 304l32 230q34 193 226 287q-72 49 -104 128t-23 177l31 236l4 57q7 161 -109 215l64 158q161 -54 234.5 -174.5t55.5 -288.5l-28 -204q-5 -43 -2 -78q10 -115 135 -126l-19 -207q-186 -10 -215 -221l-27 -199q-51 -353 -409 -461z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1298" unicode="~" d="M1203 795q-6 -118 -52 -216.5t-124 -152.5t-179 -52q-77 2 -137.5 35t-117.5 92t-86 75t-64 17q-59 0 -99.5 -47.5t-54.5 -132.5l-209 2q12 186 109.5 301t248.5 112q77 -2 138.5 -35.5t133.5 -108t131 -74.5q62 0 104.5 50t55.5 134z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="571" unicode="¡" d="M171 639h235l-143 -1008h-300zM499 953q2 -69 -44 -114t-111 -45q-63 -2 -110.5 40t-49.5 109q-2 65 42 111t113 48q64 2 111 -39.5t49 -109.5z"/> +<glyph glyph-name="cent" horiz-adv-x="1153" unicode="¢" d="M518 212q78 -2 131 42.5t68 118.5l266 2q-11 -151 -117.5 -254.5t-273.5 -131.5l-49 -234h-196l50 236q-164 38 -243 182t-58 350q25 246 150 392.5t326 178.5l47 224h196l-47 -228q133 -32 207.5 -139.5t72.5 -272.5h-264l-1 34q-13 151 -147 157q-101 5 -167.5 -74 t-87.5 -243q-12 -110 -9 -161q5 -176 146 -179z"/> +<glyph glyph-name="sterling" horiz-adv-x="1190" unicode="£" d="M544 576l-17 -147q-16 -109 -101 -192l640 4l-43 -241h-1029l43 240l75 -2q48 19 75 59.5t41 123.5l21 155h-158l41 236h150l27 221q26 208 162 327t336 115q191 -4 296.5 -116t101.5 -302l-280 1q5 174 -136 177q-70 2 -120.5 -51t-65.5 -144l-27 -228h300l-41 -236 h-291z"/> +<glyph glyph-name="currency" horiz-adv-x="1385" unicode="¤" d="M972 105q-182 -129 -369 -125q-200 4 -331 126l-153 -132l-122 158l154 125q-57 185 -37 345q26 215 171 375l-115 157l148 130l109 -143q177 116 354 112q185 -2 321 -116l170 148l123 -159l-169 -139q62 -186 42 -352q-24 -203 -157 -360l111 -151l-149 -131zM295 599 q-15 -110 19 -209.5t110 -158.5t181 -63q114 -4 219 56t175.5 166t88.5 227q15 110 -19 209t-110 157t-180 62q-115 4 -221.5 -56.5t-175.5 -164.5t-87 -225z"/> +<glyph glyph-name="yen" horiz-adv-x="1226" unicode="Â¥" d="M643 852l373 604h337l-492 -712l225 -2l-33 -175h-308l-21 -115h310l-31 -174h-308l-49 -278h-293l49 278h-327l31 174h325l21 115h-327l31 175h261l-245 713l310 1z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="511" unicode="¦" d="M-28 -270l139 795h254l-138 -795h-255zM394 698h-254l132 758h254z"/> +<glyph glyph-name="section" horiz-adv-x="1258" unicode="§" d="M1126 489q-7 -102 -62.5 -170t-142.5 -114q95 -111 84 -275q-8 -117 -75.5 -203t-191.5 -134t-280 -45q-230 2 -358 112t-124 306h281q-4 -91 51 -137t160 -46q109 0 175 38t80 106q20 98 -136 155l-97 31q-228 70 -322 167.5t-85 245.5q10 177 205 286q-96 113 -86 275 q12 166 143 269t341 118l67 2q218 -4 339.5 -116.5t117.5 -311.5h-280q3 91 -46 141.5t-141 52.5q-103 3 -172.5 -38.5t-84.5 -113.5q-22 -117 153 -165.5t267.5 -95t143.5 -104.5q85 -96 76 -236zM479 705q-90 -55 -107 -150q-24 -121 144 -176l79 -25l130 -43 q95 56 115 149q21 110 -140 170z"/> +<glyph glyph-name="dieresis" horiz-adv-x="937" unicode="¨" d="M210 1362q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM683 1362q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="copyright" horiz-adv-x="1568" unicode="©" d="M1089 597q-10 -150 -101 -234.5t-244 -80.5q-148 4 -230.5 113.5t-69.5 273.5l11 110q19 184 122.5 291.5t258.5 105.5q145 -4 225 -87t78 -230l-152 2q13 177 -146 181q-93 2 -155.5 -69.5t-77 -196t-15 -145t1.5 -47.5q3 -73 40 -118.5t102 -48.5q169 -7 200 179z M235 722q-22 -159 29.5 -302.5t165 -228.5t262.5 -87q161 -4 306.5 78.5t246.5 230.5t126 323q22 159 -29.5 301.5t-163.5 226t-264 87.5q-162 4 -311.5 -81t-247.5 -234.5t-120 -313.5zM114 722q17 152 86 292.5t180.5 247.5t245 162t276.5 52q183 -4 325 -102.5 t214.5 -272t51.5 -366.5q-21 -189 -120.5 -356t-254.5 -272q-194 -131 -413 -127q-185 4 -326.5 103.5t-213.5 273.5t-51 365z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="892" unicode="ª" d="M619 702l-3 72q-89 -83 -201 -83q-105 0 -166.5 60t-61.5 160q2 115 94.5 177.5t260.5 62.5l106 -2l12 55l4 46q-3 75 -81 78q-120 4 -147 -99l-173 13q7 110 94.5 173.5t219.5 61.5q121 -2 193 -77t62 -200l-53 -347l-4 -59q-1 -44 8 -92h-164zM448 833q69 0 161 63 l28 137h-80q-84 -3 -135 -34.5t-60 -83.5q-7 -38 15.5 -60t70.5 -22z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="1002" unicode="«" d="M278 508l162 -382l-167 -1l-213 388l1 21l330 390h203zM651 508l162 -382l-167 -1l-213 388l1 21l330 390h203z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1105" unicode="¬" d="M894 374h-196l46 260h-617l30 171h812z"/> +<glyph glyph-name="registered" horiz-adv-x="1568" unicode="®" d="M114 722q17 152 86 292.5t180.5 247.5t245 162t276.5 52q183 -4 325 -102.5t214.5 -272t51.5 -366.5q-21 -189 -120.5 -356t-254.5 -272q-194 -131 -413 -127q-185 4 -326.5 103.5t-213.5 273.5t-51 365zM235 722q-22 -160 30 -304t164 -227t263 -87q157 -4 304.5 78 t248.5 230.5t126 323.5q22 159 -29.5 301.5t-163.5 226t-264 87.5q-162 4 -311.5 -81t-247.5 -234.5t-120 -313.5zM653 653l-53 -337h-148l133 850l256 -1q142 -5 218.5 -73t71.5 -182q-3 -58 -36 -103t-101 -84q68 -49 74 -149q1 -29 -5.5 -89.5t-4.5 -88.5l4 -63l-1 -19 l-148 1q-6 37 -4 73q1 43 12 128q7 63 -14 97t-87 38zM674 787l116 -1q82 3 134 35.5t63 87.5q11 58 -17 89t-117 34l-141 1z"/> +<glyph glyph-name="macron" horiz-adv-x="1005" unicode="¯" d="M960 1290h-710l27 167h710z"/> +<glyph glyph-name="degree" horiz-adv-x="781" unicode="°" d="M228 1191q2 117 86.5 202.5t195.5 83.5q104 -2 173.5 -82t67.5 -186q-2 -116 -84.5 -200t-193.5 -82q-105 2 -176 79.5t-69 184.5zM371 1193q-6 -45 20 -81t74 -36q51 0 93 37t51 94q6 49 -19 85.5t-72 36.5q-51 0 -94.5 -40t-52.5 -96z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1077" unicode="±" d="M711 942h319l-38 -241h-318l-57 -364h-248l57 364h-325l38 241h325l54 343h247zM855 1h-840l37 235h840z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="750" unicode="²" d="M684 667h-603l26 150l335 270q95 79 107 141q8 36 -10 57t-54 21q-97 0 -121 -112l-204 -2q8 126 96.5 202.5t216.5 74.5q131 -2 207.5 -66.5t74.5 -175.5q-5 -138 -169 -255l-78 -55l-130 -84l336 -2z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="750" unicode="³" d="M350 1136h81q54 2 90.5 26.5t45.5 68.5q5 34 -18 52.5t-59 18.5q-80 0 -108 -60l-208 -1q7 106 89.5 167t212.5 59q136 -3 214.5 -61.5t75.5 -157.5q-3 -118 -158 -183q58 -20 87 -65.5t28 -105.5q-2 -111 -97.5 -176.5t-239.5 -62.5q-129 2 -208.5 69t-81.5 180l195 -1 q7 -82 102 -82q52 0 89 25t46 68q16 80 -94 85h-94z"/> +<glyph glyph-name="acute" horiz-adv-x="669" unicode="´" d="M426 1536h327l-318 -310h-249z"/> +<glyph glyph-name="uni00B5" horiz-adv-x="1233" unicode="µ" d="M500 1082l-103 -622l-6 -83q-7 -160 125 -163q133 -4 221 104l135 764h282l-188 -1082h-248l8 69q-106 -93 -230 -91q-93 0 -169 48l-87 -442h-282l260 1498h282z"/> +<glyph glyph-name="paragraph" horiz-adv-x="983" unicode="¶" d="M535 0l90 520l-52 1q-211 3 -326.5 130t-97.5 329q19 214 168 345.5t372 131.5l313 -1l-253 -1456h-214z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="608" unicode="·" d="M154 692q-2 67 43 113t113 48q65 2 112.5 -41t49.5 -110q2 -65 -43.5 -112.5t-114.5 -47.5q-64 -2 -111 39.5t-49 110.5z"/> +<glyph glyph-name="cedilla" horiz-adv-x="542" unicode="¸" d="M222 9l-20 -64q62 -13 93.5 -56.5t31.5 -105.5q0 -115 -96 -179t-276 -69l8 170q111 5 128 88q12 61 -86 68l-35 3l43 142z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="750" unicode="¹" d="M525 669h-200l95 543l-191 -40l30 168l369 115l25 1z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="918" unicode="º" d="M581 1477q148 -4 229 -105.5t71 -250.5l-6 -66q-16 -171 -120.5 -270.5t-253.5 -95.5q-144 4 -228 103.5t-73 251.5l5 63q13 167 117.5 270.5t258.5 99.5zM372 1041q-3 -36 0 -72q5 -61 38.5 -97.5t89.5 -37.5q76 -3 131 53.5t70 156.5l11 101l-1 49q-15 132 -128 135 q-77 3 -132 -52.5t-70 -155.5z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="1002" unicode="»" d="M311 923l213 -387l-1 -22l-330 -390h-203l315 415l-161 383zM692 923l213 -387l-1 -22l-330 -390h-203l315 415l-161 383z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1436" unicode="¼" d="M490 664h-200l95 543l-191 -40l30 168l369 115l25 1zM374 119l-139 85l878 1124l137 -83zM1208 324l96 1l-31 -166h-85l-29 -159h-200l28 159h-335l14 150l419 479l203 2zM866 328l152 -3l44 216l-18 -25z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1522" unicode="½" d="M333 119l-139 85l878 1124l137 -83zM474 670h-200l95 543l-191 -40l30 168l369 115l25 1zM1329 0h-603l26 150l335 270q95 79 107 141q8 36 -10 57t-54 21q-97 0 -121 -112l-204 -2q8 126 96.5 202.5t216.5 74.5q131 -2 207.5 -66.5t74.5 -175.5q-5 -138 -169 -255 l-78 -55l-130 -84l336 -2z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1615" unicode="¾" d="M530 119l-139 85l878 1124l137 -83zM1362 324l96 1l-31 -166h-85l-29 -159h-200l28 159h-335l14 150l419 479l203 2zM1020 328l152 -3l44 216l-18 -25zM395 1137h81q54 2 90.5 26.5t45.5 68.5q5 34 -18 52.5t-59 18.5q-80 0 -108 -60l-208 -1q7 106 89.5 167t212.5 59 q136 -3 214.5 -61.5t75.5 -157.5q-3 -118 -158 -183q58 -20 87 -65.5t28 -105.5q-2 -111 -97.5 -176.5t-239.5 -62.5q-129 2 -208.5 69t-81.5 180l195 -1q7 -82 102 -82q52 0 89 25t46 68q16 80 -94 85h-94z"/> +<glyph glyph-name="questiondown" horiz-adv-x="998" unicode="¿" d="M648 644q-8 -122 -50 -211t-128 -162l-68 -57q-127 -106 -144 -216q-9 -64 17 -106t95 -44q71 -2 120.5 42t68.5 131l282 2q-13 -191 -145.5 -301.5t-335.5 -106.5q-186 2 -294 104t-97 279q11 161 179 311l145 121q86 79 109 213zM747 954q2 -69 -44 -114t-111 -45 q-64 -2 -111 39.5t-49 109.5q-2 69 44 114t111 45q64 2 111 -39.5t49 -109.5z"/> +<glyph glyph-name="AE" horiz-adv-x="1877" unicode="Æ" d="M1706 0h-871l44 333h-423l-220 -333h-347l1015 1456h996l-42 -236h-580l-47 -355h488l-42 -236h-477l-53 -394h600zM615 582l298 -2l73 552z"/> +<glyph glyph-name="multiply" horiz-adv-x="1065" unicode="×" d="M25 386l353 313l-244 313l180 155l242 -310l348 311l148 -182l-353 -314l244 -312l-179 -156l-243 310l-348 -309z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1379" unicode="Ø" d="M606 -21q-155 2 -279 72l-112 -146l-203 1l194 244q-138 232 -99 545l8 58q30 214 129.5 382t249 256t330.5 86q169 -4 294 -84l99 125l202 -1l-183 -229q120 -232 84 -529l-5 -40q-42 -333 -234.5 -538t-474.5 -202zM387 552q-5 -72 3 -144l575 764q-51 54 -152 59 q-158 5 -262.5 -122t-139.5 -360q-19 -128 -24 -197zM1044 1020l-565 -752q51 -40 139 -45q147 -5 249 108t143 329.5t34 359.5z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1219" unicode="Þ" d="M559 1456l-47 -267l177 -1q234 -1 365 -122t116 -320q-11 -141 -88 -245t-206 -159.5t-286 -55.5l-233 1l-51 -287h-282l253 1456h282zM473 956l-76 -436l198 -1q113 0 194.5 59.5t98.5 165.5q14 95 -36 151t-147 60z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1263" unicode="ß" d="M308 0h-282l188 1101q29 218 168 341t352 117q174 -4 275 -104.5t90 -257.5q-3 -46 -19 -86.5t-61 -115.5t-58 -106t-20 -68q-8 -46 12.5 -94.5t80.5 -123t86.5 -131t24.5 -109.5q-9 -179 -139.5 -282.5t-335.5 -101.5q-166 2 -279 59l76 227q89 -55 205 -53q72 0 127 38 t68 107q8 48 -13.5 96t-87.5 123.5t-92 135.5q-20 46 -17 96q3 45 19 84.5t58.5 110t57.5 106.5t20 75q8 62 -22.5 103t-93.5 44q-82 3 -133 -56t-68 -177z"/> +<glyph glyph-name="ae" horiz-adv-x="1687" unicode="æ" d="M1123 -20q-243 5 -352 146q-170 -150 -404 -146q-106 1 -189.5 42.5t-125.5 115t-37 173.5q7 164 144.5 251.5t377.5 87.5l167 -2l13 60q5 33 2 62q-14 96 -115 99q-70 2 -123 -30.5t-66 -93.5l-281 18q8 160 148 252t338 88q204 -5 302 -110q151 112 331 108 q192 -4 295.5 -139.5t79.5 -349.5l-25 -162h-642q-10 -108 42 -171t156 -65q81 -2 154 20t145 56l61 -193q-135 -117 -396 -117zM426 191q96 0 216 80l38 190l-139 1q-99 -3 -165 -45t-77 -110q-10 -53 25 -84.5t102 -31.5zM1237 869q-171 6 -256 -226h369l7 31q6 36 4 71 q-7 118 -124 124z"/> +<glyph glyph-name="eth" horiz-adv-x="1153" unicode="ð" d="M948 1302q87 -155 121 -313t13 -336l-6 -52q-34 -281 -197.5 -454t-390.5 -168q-129 3 -230.5 65.5t-153.5 174t-40 241.5q13 148 80 266t175.5 180.5t245.5 60.5q129 -4 237 -78q-6 140 -92 265l-211 -123l-62 128l161 89q-81 67 -235 109l108 222q223 -53 371 -180 l192 112l60 -129zM809 665q-27 41 -77 62t-111 21q-112 2 -186.5 -78.5t-88.5 -209.5q-12 -109 31.5 -177.5t128.5 -71.5q101 -3 173.5 78.5t103.5 236.5l23 126z"/> +<glyph glyph-name="divide" horiz-adv-x="1143" unicode="÷" d="M1054 571h-999l40 230h1000zM487 1084q-2 66 43 112t114 46q67 2 113 -40t48 -108t-43.5 -111t-112.5 -45q-68 -2 -114 39.5t-48 106.5zM346 272q-2 66 43 112t114 46q67 2 113 -40t48 -108t-43.5 -111t-112.5 -45q-68 -2 -114 39.5t-48 106.5z"/> +<glyph glyph-name="oslash" horiz-adv-x="1131" unicode="ø" d="M55 545q20 162 98 292.5t200.5 199.5t273.5 67q91 -1 180 -32l100 144l174 -1l-150 -214q114 -134 123 -328q2 -58 -6 -141q-20 -162 -97 -289t-201 -197t-275 -68q-87 1 -171 29l-103 -149l-174 1l150 215q-119 131 -127 328q-3 57 5 143zM320 423q-4 -52 6 -103 l356 540q-32 12 -66 12q-127 2 -204 -111t-92 -338zM782 651q3 48 -4 98l-353 -531q30 -8 59 -9q108 -2 182 80.5t102 242.5q11 76 14 119z"/> +<glyph glyph-name="thorn" horiz-adv-x="1137" unicode="þ" d="M1044 538q-21 -173 -89.5 -304t-169 -194.5t-223.5 -60.5q-154 4 -248 116l-98 -511h-283l338 1952h284l-108 -549q113 119 262 115q156 -2 245.5 -112.5t95.5 -305.5q2 -62 -6 -146zM764 559l6 96q2 97 -35.5 154t-109.5 59q-120 4 -202 -102l-82 -450q37 -101 159 -103 q98 -3 165.5 74.5t92.5 229.5z"/> +<glyph glyph-name="dotlessi" horiz-adv-x="554" unicode="ı" d="M307 0h-282l188 1082h282z"/> +<glyph glyph-name="OE" horiz-adv-x="1934" unicode="Å’" d="M1722 0h-842l-196 -17l-87 -1q-162 4 -284 81.5t-180 214.5t-37 298l46 299q43 276 227.5 439t445.5 163l73 -2l208 -19h877l-43 -243h-652l-61 -347h558l-41 -235h-557l-68 -390h655zM606 214q78 -3 199 9l187 1008q-90 14 -183 16q-153 0 -254 -97.5t-129 -273.5 l-48 -301q-9 -67 -3 -130q8 -106 68 -166.5t163 -64.5z"/> +<glyph glyph-name="oe" horiz-adv-x="1802" unicode="Å“" d="M77 545q26 227 158 378q161 184 409 180q107 -2 196 -41t142 -108q162 152 360 148q132 -4 224 -66.5t133 -173.5t24 -249l-25 -163h-628q-7 -105 40.5 -168t140.5 -67q137 -7 305 76l64 -190q-68 -60 -174.5 -91t-230.5 -29q-106 0 -195.5 38.5t-143.5 108.5 q-166 -152 -382 -148q-141 2 -241.5 72t-147.5 195t-31 276zM356 523l-5 -101q0 -98 41 -154t118 -58q108 -3 180 83t91 239l2 21l5 67q7 241 -161 249q-103 3 -173 -77t-93 -235zM1325 870q-128 3 -206 -159l-28 -65h355q13 66 10 102q-5 57 -39 89t-92 33z"/> +<glyph glyph-name="circumflex" horiz-adv-x="995" unicode="ˆ" d="M977 1260v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="ring" horiz-adv-x="672" unicode="Ëš" d="M241 1318q0 90 66 151.5t157 61.5q87 0 148.5 -58.5t61.5 -140.5q2 -86 -63.5 -147.5t-159.5 -61.5q-86 0 -147 56t-63 139zM354 1318q-7 -40 15 -70t65 -30q47 0 83 32.5t45 81.5q6 43 -17 72.5t-63 29.5q-47 0 -84.5 -34t-43.5 -82z"/> +<glyph glyph-name="tilde" horiz-adv-x="965" unicode="Ëœ" d="M979 1526q-7 -118 -70.5 -194.5t-160.5 -76.5q-28 0 -53.5 8.5t-76.5 37t-76.5 37.5t-54.5 8q-76 -3 -101 -98l-166 10q7 116 73.5 194t162.5 76q26 0 49.5 -7.5t79 -37.5t80 -38t52.5 -7q77 3 101 98z"/> +<glyph glyph-name="endash" horiz-adv-x="1265" unicode="–" d="M1153.01 596h-1006.81l49.2002 236h1008.01z"/> +<glyph glyph-name="emdash" horiz-adv-x="1526" unicode="—" d="M1445.98 596h-1342.38l65.5986 236h1343.98z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="475" unicode="‘" d="M428 1570l134 -82q-46 -68 -82 -137.5t-52 -151.5l-26 -151h-224l20 132q36 232 230 390z"/> +<glyph glyph-name="quoteright" horiz-adv-x="466" unicode="’" d="M285 1007l-143 84q103 148 129 260l33 185h225l-23 -148q-34 -221 -221 -381z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="503" unicode="‚" d="M57 -305l-134 82q96 144 121 261l34 191h232l-22 -143q-36 -232 -231 -391z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="816" unicode="“" d="M436 1570l134 -82q-46 -68 -82 -137.5t-52 -151.5l-26 -151h-224l20 132q36 232 230 390zM768 1570l134 -82q-46 -68 -82 -137.5t-52 -151.5l-26 -151h-224l20 132q36 232 230 390z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="822" unicode="â€" d="M299 1007l-143 84q103 148 129 260l33 185h225l-23 -148q-34 -221 -221 -381zM635 1007l-143 84q103 148 129 260l33 185h225l-23 -148q-34 -221 -221 -381z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="810" unicode="„" d="M60 -325l-140 81q96 148 124 282l40 225h232l-31 -191q-39 -238 -225 -397zM386 -325l-141 81q105 161 132 279l40 228h232l-27 -177q-38 -244 -236 -411z"/> +<glyph glyph-name="bullet" horiz-adv-x="724" unicode="•" d="M399 997q99 -2 158.5 -64t59.5 -164l-1 -40q-6 -105 -73.5 -169t-168.5 -62q-99 2 -158.5 65t-59.5 157l1 34q3 108 69 175.5t173 67.5z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="629" unicode="‹" d="M308 508l162 -382l-167 -1l-213 388l1 21l330 390h203z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="609" unicode="›" d="M306 923l213 -387l-1 -22l-330 -390h-203l315 415l-161 383z"/> +<glyph glyph-name="fraction" horiz-adv-x="896" unicode="â„" d="M94 111l-139 85l878 1124l137 -83z"/> +<glyph glyph-name="uni2074" horiz-adv-x="750" unicode="â´" d="M658 988l96 1l-31 -166h-85l-29 -159h-200l28 159h-335l14 150l419 479l203 2zM316 992l152 -3l44 216l-18 -25z"/> +<glyph glyph-name="Euro" d="M854 516h-319q-9 -66 -1 -119q12 -83 71 -128t156 -46q84 -2 193 30l12 -245q-132 -29 -243 -25q-155 1 -273.5 71t-172.5 191.5t-32 272.5l-175 -2l27 152h164l22 124h-164l27 152l154 -1q73 263 243.5 399t418.5 134q100 -2 238 -32l-59 -243q-87 33 -173 35 q-276 4 -373 -293l333 1l-27 -152h-324l-22 -124h326z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1114" unicode="−" d="M980 596h-839l41 236h840z"/> +<glyph glyph-name="glyph162" d="M409 0h-200l95 543l-191 -40l30 168l369 115l25 1z" horiz-adv-x="749"/> +<glyph glyph-name="glyph163" d="M569 0h-603l26 150l335 270q95 79 107 141q8 36 -10 57t-54 21q-97 0 -121 -112l-204 -2q8 126 96.5 202.5t216.5 74.5q131 -2 207.5 -66.5t74.5 -175.5q-5 -138 -169 -255l-78 -55l-130 -84l336 -2z" horiz-adv-x="749"/> +<glyph glyph-name="glyph164" d="M235 470h81q54 2 90.5 26.5t45.5 68.5q5 34 -18 52.5t-59 18.5q-80 0 -108 -60l-208 -1q7 106 89.5 167t212.5 59q136 -3 214.5 -61.5t75.5 -157.5q-3 -118 -158 -183q58 -20 87 -65.5t28 -105.5q-2 -111 -97.5 -176.5t-239.5 -62.5q-129 2 -208.5 69t-81.5 180l195 -1 q7 -82 102 -82q52 0 89 25t46 68q16 80 -94 85h-94z" horiz-adv-x="749"/> +<glyph glyph-name="glyph165" d="M543 324l96 1l-31 -166h-85l-29 -159h-200l28 159h-335l14 150l419 479l203 2zM201 328l152 -3l44 216l-18 -25z" horiz-adv-x="749"/> +<glyph glyph-name="uni00A0" horiz-adv-x="505" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="780" unicode="Â" d="M638 507h-548l40 233h549z"/> +<glyph glyph-name="Eth" horiz-adv-x="1331" unicode="Ã" d="M51 0l111 642h-175l33 183h174l110 631l416 -1q147 -2 265.5 -66t191.5 -183t88 -268q8 -87 -2 -178l-7 -53q-44 -320 -251.5 -513.5t-503.5 -193.5h-450zM667 642h-212l-69 -401l122 -1q202 0 324.5 148t140.5 447l2 32q3 165 -63 253t-197 92l-160 1l-68 -388h213z"/> +<glyph glyph-name="Agrave" horiz-adv-x="1347" unicode="À" d="M877 300h-508l-150 -300h-323l778 1456h271l277 -1456h-299zM489 543h351l-82 542zM966 1536l-211 1l-223 307l291 2z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1347" unicode="Ã" d="M877 300h-508l-150 -300h-323l778 1456h271l277 -1456h-299zM489 543h351l-82 542zM930 1846h327l-318 -310h-249z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1347" unicode="Â" d="M877 300h-508l-150 -300h-323l778 1456h271l277 -1456h-299zM489 543h351l-82 542zM1214 1570v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1347" unicode="Ã" d="M877 300h-508l-150 -300h-323l778 1456h271l277 -1456h-299zM489 543h351l-82 542zM1236 1834q-7 -118 -70.5 -194.5t-160.5 -76.5q-28 0 -53.5 8.5t-76.5 37t-76.5 37.5t-54.5 8q-76 -3 -101 -98l-166 10q7 116 73.5 194t162.5 76q26 0 49.5 -7.5t79 -37.5t80 -38 t52.5 -7q77 3 101 98z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1347" unicode="Ä" d="M877 300h-508l-150 -300h-323l778 1456h271l277 -1456h-299zM489 543h351l-82 542zM485 1672q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM958 1672q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92 q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="Aring" horiz-adv-x="1347" unicode="Ã…" d="M877 300h-508l-150 -300h-323l778 1456h271l277 -1456h-299zM489 543h351l-82 542zM651 1723q0 90 66 151.5t157 61.5q87 0 148.5 -58.5t61.5 -140.5q2 -86 -63.5 -147.5t-159.5 -61.5q-86 0 -147 56t-63 139zM764 1723q-7 -40 15 -70t65 -30q47 0 83 32.5t45 81.5 q6 43 -17 72.5t-63 29.5q-47 0 -84.5 -34t-43.5 -82z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1310" unicode="Ç" d="M1208 486q-17 -151 -103 -267.5t-224 -179t-298 -59.5q-144 3 -251 66.5t-168.5 184t-69.5 277.5q-7 123 25.5 306t116 325t198.5 225q162 116 370 112q226 -4 358.5 -139.5t145.5 -376.5l-292 1q0 138 -55 202t-171 68q-150 5 -246.5 -107t-129.5 -327 q-32 -209 -28 -313q5 -132 59 -194.5t151 -65.5q134 -5 214.5 63.5t106.5 196.5zM660 8l-20 -64q62 -13 93.5 -56.5t31.5 -105.5q0 -115 -96 -179t-276 -69l8 170q111 5 128 88q12 61 -86 68l-35 3l43 142z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1127" unicode="È" d="M982 631h-558l-68 -390h656l-42 -241h-949l253 1456h947l-43 -243h-653l-61 -347h560zM911 1539l-211 1l-223 307l291 2z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1127" unicode="É" d="M982 631h-558l-68 -390h656l-42 -241h-949l253 1456h947l-43 -243h-653l-61 -347h560zM875 1849h327l-318 -310h-249z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1127" unicode="Ê" d="M982 631h-558l-68 -390h656l-42 -241h-949l253 1456h947l-43 -243h-653l-61 -347h560zM1159 1573v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1127" unicode="Ë" d="M982 631h-558l-68 -390h656l-42 -241h-949l253 1456h947l-43 -243h-653l-61 -347h560zM430 1675q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM903 1675q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92 q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="Igrave" horiz-adv-x="589" unicode="ÃŒ" d="M333 0h-293l252 1456h293zM585 1539l-211 1l-223 307l291 2z"/> +<glyph glyph-name="Iacute" horiz-adv-x="589" unicode="Ã" d="M333 0h-293l252 1456h293zM548 1849h327l-318 -310h-249z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="589" unicode="ÃŽ" d="M333 0h-293l252 1456h293zM833 1573v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="589" unicode="Ã" d="M333 0h-293l252 1456h293zM104 1675q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM577 1675q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1413" unicode="Ñ" d="M1172 0h-284l-405 971l-169 -971h-293l253 1456h283l406 -973l169 973h292zM1269 1834q-7 -118 -70.5 -194.5t-160.5 -76.5q-28 0 -53.5 8.5t-76.5 37t-76.5 37.5t-54.5 8q-76 -3 -101 -98l-166 10q7 116 73.5 194t162.5 76q26 0 49.5 -7.5t79 -37.5t80 -38t52.5 -7 q77 3 101 98z"/> +<glyph glyph-name="Ograve" horiz-adv-x="1382" unicode="Ã’" d="M606 -20q-145 3 -255.5 68.5t-175 189t-74.5 283.5q-11 164 35 350t148 327t239.5 211t297.5 67q147 -3 257 -69.5t173 -191t72 -282.5q10 -176 -38 -362t-149 -322t-236.5 -204t-293.5 -65zM1021 768l8 95q10 178 -47.5 270t-174.5 96q-183 6 -290.5 -162t-121.5 -470 q-10 -177 47 -272.5t177 -99.5q157 -7 260 122.5t135 366.5zM980 1536l-211 1l-223 307l291 2z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1382" unicode="Ó" d="M606 -20q-145 3 -255.5 68.5t-175 189t-74.5 283.5q-11 164 35 350t148 327t239.5 211t297.5 67q147 -3 257 -69.5t173 -191t72 -282.5q10 -176 -38 -362t-149 -322t-236.5 -204t-293.5 -65zM1021 768l8 95q10 178 -47.5 270t-174.5 96q-183 6 -290.5 -162t-121.5 -470 q-10 -177 47 -272.5t177 -99.5q157 -7 260 122.5t135 366.5zM944 1846h327l-318 -310h-249z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1382" unicode="Ô" d="M606 -20q-145 3 -255.5 68.5t-175 189t-74.5 283.5q-11 164 35 350t148 327t239.5 211t297.5 67q147 -3 257 -69.5t173 -191t72 -282.5q10 -176 -38 -362t-149 -322t-236.5 -204t-293.5 -65zM1021 768l8 95q10 178 -47.5 270t-174.5 96q-183 6 -290.5 -162t-121.5 -470 q-10 -177 47 -272.5t177 -99.5q157 -7 260 122.5t135 366.5zM1228 1570v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1382" unicode="Õ" d="M606 -20q-145 3 -255.5 68.5t-175 189t-74.5 283.5q-11 164 35 350t148 327t239.5 211t297.5 67q147 -3 257 -69.5t173 -191t72 -282.5q10 -176 -38 -362t-149 -322t-236.5 -204t-293.5 -65zM1021 768l8 95q10 178 -47.5 270t-174.5 96q-183 6 -290.5 -162t-121.5 -470 q-10 -177 47 -272.5t177 -99.5q157 -7 260 122.5t135 366.5zM1250 1834q-7 -118 -70.5 -194.5t-160.5 -76.5q-28 0 -53.5 8.5t-76.5 37t-76.5 37.5t-54.5 8q-76 -3 -101 -98l-166 10q7 116 73.5 194t162.5 76q26 0 49.5 -7.5t79 -37.5t80 -38t52.5 -7q77 3 101 98z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1382" unicode="Ö" d="M606 -20q-145 3 -255.5 68.5t-175 189t-74.5 283.5q-11 164 35 350t148 327t239.5 211t297.5 67q147 -3 257 -69.5t173 -191t72 -282.5q10 -176 -38 -362t-149 -322t-236.5 -204t-293.5 -65zM1021 768l8 95q10 178 -47.5 270t-174.5 96q-183 6 -290.5 -162t-121.5 -470 q-10 -177 47 -272.5t177 -99.5q157 -7 260 122.5t135 366.5zM499 1672q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM972 1672q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5 t-97 34.5t-41 90.5z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1318" unicode="Ù" d="M1349 1456l-164 -960q-34 -241 -200 -381t-412 -136q-154 3 -267.5 67.5t-167.5 182t-37 266.5l163 961h293l-163 -962q-7 -56 -1 -105q20 -162 193 -168q124 -4 203 68t102 206l164 961h294zM945 1536l-211 1l-223 307l291 2z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1318" unicode="Ú" d="M1349 1456l-164 -960q-34 -241 -200 -381t-412 -136q-154 3 -267.5 67.5t-167.5 182t-37 266.5l163 961h293l-163 -962q-7 -56 -1 -105q20 -162 193 -168q124 -4 203 68t102 206l164 961h294zM909 1846h327l-318 -310h-249z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1318" unicode="Û" d="M1349 1456l-164 -960q-34 -241 -200 -381t-412 -136q-154 3 -267.5 67.5t-167.5 182t-37 266.5l163 961h293l-163 -962q-7 -56 -1 -105q20 -162 193 -168q124 -4 203 68t102 206l164 961h294zM1193 1570v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="Udieresis" horiz-adv-x="1318" unicode="Ü" d="M1349 1456l-164 -960q-34 -241 -200 -381t-412 -136q-154 3 -267.5 67.5t-167.5 182t-37 266.5l163 961h293l-163 -962q-7 -56 -1 -105q20 -162 193 -168q124 -4 203 68t102 206l164 961h294zM464 1672q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5 t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM937 1672q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1238" unicode="Ã" d="M640 802l407 654h336l-636 -944l-88 -512h-298l95 545l-302 910l309 1zM875 1846h327l-318 -310h-249z"/> +<glyph glyph-name="agrave" horiz-adv-x="1075" unicode="à " d="M629 0q-13 41 -11 98q-122 -122 -276 -118q-142 2 -235.5 92.5t-87.5 223.5q7 177 148.5 271.5t379.5 94.5l132 -2l14 65q6 33 3 63q-5 47 -35.5 73.5t-80.5 27.5q-66 2 -112 -32.5t-59 -99.5l-283 -1q7 155 142.5 251.5t334.5 94.5q184 -4 288 -109.5t87 -271.5 l-83 -518l-5 -64q-2 -71 17 -120l-1 -19h-277zM412 199q122 -4 213 106l35 187l-98 1q-156 -4 -225 -95q-25 -33 -31 -81q-8 -54 22.5 -85.5t83.5 -32.5zM776 1226l-211 1l-223 307l291 2z"/> +<glyph glyph-name="aacute" horiz-adv-x="1075" unicode="á" d="M629 0q-13 41 -11 98q-122 -122 -276 -118q-142 2 -235.5 92.5t-87.5 223.5q7 177 148.5 271.5t379.5 94.5l132 -2l14 65q6 33 3 63q-5 47 -35.5 73.5t-80.5 27.5q-66 2 -112 -32.5t-59 -99.5l-283 -1q7 155 142.5 251.5t334.5 94.5q184 -4 288 -109.5t87 -271.5 l-83 -518l-5 -64q-2 -71 17 -120l-1 -19h-277zM412 199q122 -4 213 106l35 187l-98 1q-156 -4 -225 -95q-25 -33 -31 -81q-8 -54 22.5 -85.5t83.5 -32.5zM740 1536h327l-318 -310h-249z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1075" unicode="â" d="M629 0q-13 41 -11 98q-122 -122 -276 -118q-142 2 -235.5 92.5t-87.5 223.5q7 177 148.5 271.5t379.5 94.5l132 -2l14 65q6 33 3 63q-5 47 -35.5 73.5t-80.5 27.5q-66 2 -112 -32.5t-59 -99.5l-283 -1q7 155 142.5 251.5t334.5 94.5q184 -4 288 -109.5t87 -271.5 l-83 -518l-5 -64q-2 -71 17 -120l-1 -19h-277zM412 199q122 -4 213 106l35 187l-98 1q-156 -4 -225 -95q-25 -33 -31 -81q-8 -54 22.5 -85.5t83.5 -32.5zM1024 1260v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="atilde" horiz-adv-x="1075" unicode="ã" d="M629 0q-13 41 -11 98q-122 -122 -276 -118q-142 2 -235.5 92.5t-87.5 223.5q7 177 148.5 271.5t379.5 94.5l132 -2l14 65q6 33 3 63q-5 47 -35.5 73.5t-80.5 27.5q-66 2 -112 -32.5t-59 -99.5l-283 -1q7 155 142.5 251.5t334.5 94.5q184 -4 288 -109.5t87 -271.5 l-83 -518l-5 -64q-2 -71 17 -120l-1 -19h-277zM412 199q122 -4 213 106l35 187l-98 1q-156 -4 -225 -95q-25 -33 -31 -81q-8 -54 22.5 -85.5t83.5 -32.5zM1046 1525q-7 -118 -70.5 -194.5t-160.5 -76.5q-28 0 -53.5 8.5t-76.5 37t-76.5 37.5t-54.5 8q-76 -3 -101 -98 l-166 10q7 116 73.5 194t162.5 76q26 0 49.5 -7.5t79 -37.5t80 -38t52.5 -7q77 3 101 98z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1075" unicode="ä" d="M629 0q-13 41 -11 98q-122 -122 -276 -118q-142 2 -235.5 92.5t-87.5 223.5q7 177 148.5 271.5t379.5 94.5l132 -2l14 65q6 33 3 63q-5 47 -35.5 73.5t-80.5 27.5q-66 2 -112 -32.5t-59 -99.5l-283 -1q7 155 142.5 251.5t334.5 94.5q184 -4 288 -109.5t87 -271.5 l-83 -518l-5 -64q-2 -71 17 -120l-1 -19h-277zM412 199q122 -4 213 106l35 187l-98 1q-156 -4 -225 -95q-25 -33 -31 -81q-8 -54 22.5 -85.5t83.5 -32.5zM295 1362q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5 t-43.5 90.5zM768 1362q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="aring" horiz-adv-x="1075" unicode="Ã¥" d="M629 0q-13 41 -11 98q-122 -122 -276 -118q-142 2 -235.5 92.5t-87.5 223.5q7 177 148.5 271.5t379.5 94.5l132 -2l14 65q6 33 3 63q-5 47 -35.5 73.5t-80.5 27.5q-66 2 -112 -32.5t-59 -99.5l-283 -1q7 155 142.5 251.5t334.5 94.5q184 -4 288 -109.5t87 -271.5 l-83 -518l-5 -64q-2 -71 17 -120l-1 -19h-277zM412 199q122 -4 213 106l35 187l-98 1q-156 -4 -225 -95q-25 -33 -31 -81q-8 -54 22.5 -85.5t83.5 -32.5zM461 1413q0 90 66 151.5t157 61.5q87 0 148.5 -58.5t61.5 -140.5q2 -86 -63.5 -147.5t-159.5 -61.5q-86 0 -147 56 t-63 139zM574 1413q-7 -40 15 -70t65 -30q47 0 83 32.5t45 81.5q6 43 -17 72.5t-63 29.5q-47 0 -84.5 -34t-43.5 -82z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1046" unicode="ç" d="M477 212q78 -2 130 42.5t68 118.5l265 1q-7 -114 -71.5 -205t-172 -142t-226.5 -48q-197 3 -312 136t-111 354l3 55l1 11q27 264 178 418.5t373 148.5q183 -4 290.5 -119.5t105.5 -304.5h-263q0 87 -38 137t-114 54q-202 6 -245 -295q-15 -109 -11 -184q10 -175 150 -178 zM544 8l-20 -64q62 -13 93.5 -56.5t31.5 -105.5q0 -115 -96 -179t-276 -69l8 170q111 5 128 88q12 61 -86 68l-35 3l43 142z"/> +<glyph glyph-name="egrave" horiz-adv-x="1084" unicode="è" d="M517 -20q-142 1 -251.5 69.5t-163.5 188t-42 263.5l3 40q15 158 92 290t198 203.5t268 67.5q209 -4 316.5 -153.5t81.5 -378.5l-16 -123h-663q-4 -105 51 -168t150 -65q154 -4 270 119l129 -160q-61 -92 -176 -143.5t-247 -49.5zM607 869q-78 2 -138.5 -49t-108.5 -177 h388l6 26q6 40 1 76q-10 58 -49 90.5t-99 33.5zM757 1226l-211 1l-223 307l291 2z"/> +<glyph glyph-name="eacute" horiz-adv-x="1084" unicode="é" d="M517 -20q-142 1 -251.5 69.5t-163.5 188t-42 263.5l3 40q15 158 92 290t198 203.5t268 67.5q209 -4 316.5 -153.5t81.5 -378.5l-16 -123h-663q-4 -105 51 -168t150 -65q154 -4 270 119l129 -160q-61 -92 -176 -143.5t-247 -49.5zM607 869q-78 2 -138.5 -49t-108.5 -177 h388l6 26q6 40 1 76q-10 58 -49 90.5t-99 33.5zM721 1536h327l-318 -310h-249z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1084" unicode="ê" d="M517 -20q-142 1 -251.5 69.5t-163.5 188t-42 263.5l3 40q15 158 92 290t198 203.5t268 67.5q209 -4 316.5 -153.5t81.5 -378.5l-16 -123h-663q-4 -105 51 -168t150 -65q154 -4 270 119l129 -160q-61 -92 -176 -143.5t-247 -49.5zM607 869q-78 2 -138.5 -49t-108.5 -177 h388l6 26q6 40 1 76q-10 58 -49 90.5t-99 33.5zM1005 1260v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1084" unicode="ë" d="M517 -20q-142 1 -251.5 69.5t-163.5 188t-42 263.5l3 40q15 158 92 290t198 203.5t268 67.5q209 -4 316.5 -153.5t81.5 -378.5l-16 -123h-663q-4 -105 51 -168t150 -65q154 -4 270 119l129 -160q-61 -92 -176 -143.5t-247 -49.5zM607 869q-78 2 -138.5 -49t-108.5 -177 h388l6 26q6 40 1 76q-10 58 -49 90.5t-99 33.5zM276 1362q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM749 1362q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5 t-41 90.5z"/> +<glyph glyph-name="igrave" horiz-adv-x="554" unicode="ì" d="M307 0h-282l188 1082h282zM511 1211l-211 1l-223 307l291 2z"/> +<glyph glyph-name="iacute" horiz-adv-x="554" unicode="Ã" d="M307 0h-282l188 1082h282zM474 1521h327l-318 -310h-249z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="554" unicode="î" d="M307 0h-282l188 1082h282zM759 1245v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="idieresis" horiz-adv-x="554" unicode="ï" d="M307 0h-282l188 1082h282zM30 1347q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM503 1347q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="ntilde" horiz-adv-x="1123" unicode="ñ" d="M449 1083l-24 -128q130 151 315 147q153 -3 226 -112t53 -302l-114 -688h-282l116 691q5 39 2 71q-13 102 -128 105q-111 4 -199 -103l-135 -764h-282l188 1082zM1069 1525q-7 -118 -70.5 -194.5t-160.5 -76.5q-28 0 -53.5 8.5t-76.5 37t-76.5 37.5t-54.5 8 q-76 -3 -101 -98l-166 10q7 116 73.5 194t162.5 76q26 0 49.5 -7.5t79 -37.5t80 -38t52.5 -7q77 3 101 98z"/> +<glyph glyph-name="ograve" horiz-adv-x="1133" unicode="ò" d="M622 1102q143 -2 246.5 -73.5t152 -197t34.5 -278.5q-23 -258 -179.5 -417.5t-386.5 -155.5q-141 2 -244 72.5t-152 195.5t-35 276q26 268 182 426t382 152zM337 421q2 -96 45 -151.5t121 -57.5q130 -4 204 119.5t69 324.5q-4 96 -46.5 153.5t-121.5 59.5 q-126 4 -201.5 -118.5t-69.5 -329.5zM788 1226l-211 1l-223 307l291 2z"/> +<glyph glyph-name="oacute" horiz-adv-x="1133" unicode="ó" d="M622 1102q143 -2 246.5 -73.5t152 -197t34.5 -278.5q-23 -258 -179.5 -417.5t-386.5 -155.5q-141 2 -244 72.5t-152 195.5t-35 276q26 268 182 426t382 152zM337 421q2 -96 45 -151.5t121 -57.5q130 -4 204 119.5t69 324.5q-4 96 -46.5 153.5t-121.5 59.5 q-126 4 -201.5 -118.5t-69.5 -329.5zM752 1536h327l-318 -310h-249z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1133" unicode="ô" d="M622 1102q143 -2 246.5 -73.5t152 -197t34.5 -278.5q-23 -258 -179.5 -417.5t-386.5 -155.5q-141 2 -244 72.5t-152 195.5t-35 276q26 268 182 426t382 152zM337 421q2 -96 45 -151.5t121 -57.5q130 -4 204 119.5t69 324.5q-4 96 -46.5 153.5t-121.5 59.5 q-126 4 -201.5 -118.5t-69.5 -329.5zM1036 1260v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="otilde" horiz-adv-x="1133" unicode="õ" d="M622 1102q143 -2 246.5 -73.5t152 -197t34.5 -278.5q-23 -258 -179.5 -417.5t-386.5 -155.5q-141 2 -244 72.5t-152 195.5t-35 276q26 268 182 426t382 152zM337 421q2 -96 45 -151.5t121 -57.5q130 -4 204 119.5t69 324.5q-4 96 -46.5 153.5t-121.5 59.5 q-126 4 -201.5 -118.5t-69.5 -329.5zM1058 1525q-7 -118 -70.5 -194.5t-160.5 -76.5q-28 0 -53.5 8.5t-76.5 37t-76.5 37.5t-54.5 8q-76 -3 -101 -98l-166 10q7 116 73.5 194t162.5 76q26 0 49.5 -7.5t79 -37.5t80 -38t52.5 -7q77 3 101 98z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1133" unicode="ö" d="M622 1102q143 -2 246.5 -73.5t152 -197t34.5 -278.5q-23 -258 -179.5 -417.5t-386.5 -155.5q-141 2 -244 72.5t-152 195.5t-35 276q26 268 182 426t382 152zM337 421q2 -96 45 -151.5t121 -57.5q130 -4 204 119.5t69 324.5q-4 96 -46.5 153.5t-121.5 59.5 q-126 4 -201.5 -118.5t-69.5 -329.5zM307 1362q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM780 1362q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="ugrave" horiz-adv-x="1122" unicode="ù" d="M673 112q-120 -135 -298 -132q-156 2 -236 112t-62 290l117 700h282l-119 -703q-4 -33 -1 -62q10 -100 111 -103q131 -4 217 101l135 767h284l-188 -1082h-263zM796 1226l-211 1l-223 307l291 2z"/> +<glyph glyph-name="uacute" horiz-adv-x="1122" unicode="ú" d="M673 112q-120 -135 -298 -132q-156 2 -236 112t-62 290l117 700h282l-119 -703q-4 -33 -1 -62q10 -100 111 -103q131 -4 217 101l135 767h284l-188 -1082h-263zM760 1536h327l-318 -310h-249z"/> +<glyph glyph-name="ucircumflex" horiz-adv-x="1122" unicode="û" d="M673 112q-120 -135 -298 -132q-156 2 -236 112t-62 290l117 700h282l-119 -703q-4 -33 -1 -62q10 -100 111 -103q131 -4 217 101l135 767h284l-188 -1082h-263zM1044 1260v-21l-216 5l-123 144l-175 -143l-229 -4v23l321 272l161 1z"/> +<glyph glyph-name="udieresis" horiz-adv-x="1122" unicode="ü" d="M673 112q-120 -135 -298 -132q-156 2 -236 112t-62 290l117 700h282l-119 -703q-4 -33 -1 -62q10 -100 111 -103q131 -4 217 101l135 767h284l-188 -1082h-263zM315 1362q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5 t-43.5 90.5zM788 1362q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +<glyph glyph-name="yacute" horiz-adv-x="1007" unicode="ý" d="M462 412l309 670h314l-633 -1245q-68 -143 -159.5 -210t-211.5 -67q-47 0 -136 21l21 220l39 -2q138 -4 202 101l62 115l-177 1067h292zM710 1536h327l-318 -310h-249z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="1007" unicode="ÿ" d="M462 412l309 670h314l-633 -1245q-68 -143 -159.5 -210t-211.5 -67q-47 0 -136 21l21 220l39 -2q138 -4 202 101l62 115l-177 1067h292zM265 1362q-2 54 36 91.5t95 39.5q56 2 97 -34.5t41 -90.5q2 -53 -36.5 -90.5t-94.5 -39.5q-53 -2 -94.5 33.5t-43.5 90.5zM738 1362 q-2 54 36 91.5t94 39.5q53 2 95.5 -33t44.5 -92q0 -54 -38 -91.5t-94 -39.5t-97 34.5t-41 90.5z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b53a84a130f04d5cd12b1c2f80ad76ee2ef6edce Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff new file mode 100644 index 0000000000000000000000000000000000000000..d04c5e0533286f25ba04783f83360f8608284530 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2 b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..bdcf7923eb37c3229c273b98d465d83a90737793 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/BoldItalic/RobotoDraft-BoldItalic.woff2 differ diff --git a/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.eot b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.eot new file mode 100644 index 0000000000000000000000000000000000000000..52628880796210a01ab166b17b808173f7acad2e Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.svg b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.svg new file mode 100644 index 0000000000000000000000000000000000000000..a5fc77f016b05268244f199c5d29e33f7f6409a5 --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.svg @@ -0,0 +1,233 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-Italic" horiz-adv-x="1126"> +<font-face slope="-12" underline-position="-100" font-weight="400" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-236 -496.038 1912 1938" x-height="1082" underline-thickness="100" font-family="RobotoDraft" ascent="1536" font-style="italic" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="918"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1110" unicode="fi" d="M91 0l163 939h-166l25 143l166 1l14 100q27 183 147 283q115 95 290 93q71 -2 137.5 -19.5t136.5 -41.5l-44 -158q-113 51 -224 53q-229 4 -263 -224l-13 -87h215l-25 -143h-214l-163 -939h-182zM841 0h-182l188 1082h182z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1138" unicode="fl" d="M927 1381q-129 22 -188 22q-99 0 -159 -55.5t-75 -150.5l-18 -115h225l-25 -143h-224l-163 -939h-181l164 939h-167l25 143h166l18 127q26 167 134 260t274 91q109 -2 293 -44l96 -20l-254 -1496h-181z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="918"/> +<glyph glyph-name="glyph1" horiz-adv-x="10"/> +<glyph glyph-name="glyph1" horiz-adv-x="10"/> +<glyph glyph-name="glyph2" horiz-adv-x="10"/> +<glyph glyph-name="uni000D" horiz-adv-x="502" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="502" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="521" unicode="!" d="M305 411h-164l169 1045h190zM67 90q1 47 30 77.5t77 32.5q46 2 76 -28t30 -76q0 -47 -30 -76.5t-77 -31.5t-76.5 27t-29.5 75z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="645" unicode='"' d="M393 1390l-83 -348l-110 -1l80 503l136 -9zM655 1390l-83 -348h-110l80 502l136 -9z"/> +<glyph glyph-name="numbersign" horiz-adv-x="1233" unicode="#" d="M707 410h-250l-150 -410h-144l149 410h-230l24 137h255l128 354h-248l24 139h274l152 416h145l-153 -416h251l152 416h146l-153 -416h196l-24 -139h-222l-128 -354h216l-24 -137h-241l-149 -410h-146zM505 547h250l129 354h-250z"/> +<glyph glyph-name="dollar" d="M801 382q10 86 -43 150t-179.5 112.5t-201.5 109.5q-148 121 -134 317q11 164 118.5 271.5t284.5 130.5l39 219h146l-40 -222q148 -29 220.5 -149.5t57.5 -312.5h-179q8 147 -43.5 225.5t-151.5 81.5q-113 2 -186.5 -63.5t-85.5 -176.5q-9 -86 37.5 -148t183.5 -116.5 t208 -114t103.5 -136.5t25.5 -176q-13 -171 -127.5 -276t-303.5 -125l-34 -191h-145l35 193q-164 24 -248 141t-73 303h181q-11 -131 47.5 -209t176.5 -80q127 -2 212.5 64.5t98.5 177.5z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1465" unicode="%" d="M525 1478q121 -4 192.5 -88.5t63.5 -213.5l-6 -77q-15 -134 -105.5 -219t-215.5 -81q-121 2 -194 88t-65 212l6 64q13 144 104.5 230.5t219.5 84.5zM330 1097q-5 -81 29.5 -128.5t98.5 -49.5q68 -2 118.5 48.5t61.5 131.5l9 78q7 76 -26 127t-100 53q-69 2 -120 -49 t-62 -132zM1070 658q124 -4 195 -89.5t63 -211.5l-6 -67q-13 -141 -103.5 -228.5t-218.5 -83.5q-120 2 -193.5 87t-65.5 214l6 68q13 139 102 226t221 85zM876 277q-5 -80 28.5 -128.5t99.5 -50.5q70 -2 119.5 49t60.5 132l9 79q7 75 -26 126t-100 53q-71 2 -121 -49 t-61 -131zM360 112l-99 72l881 1128l99 -71z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1245" unicode="&" d="M71 384q15 186 222 332l114 76l-43 77q-72 132 -64 245q12 165 120 265.5t272 96.5q135 -2 223 -87.5t80 -212.5q-9 -172 -213 -315l-147 -98l249 -381q91 135 114 290h161q-27 -255 -181 -427l157 -245h-202l-73 113q-174 -136 -383 -132q-189 2 -304 114.5t-102 288.5z M483 131q134 -3 284 113l-271 424l-43 -30q-179 -124 -198 -255q-15 -108 48 -179t180 -73zM478 1121q-8 -84 49 -185l27 -47l153 103q107 80 118 185q6 64 -35 106t-109 42q-83 0 -139 -60.5t-64 -143.5z"/> +<glyph glyph-name="quotesingle" horiz-adv-x="356" unicode="'" d="M374 1418l-76 -361h-128l77 479h146z"/> +<glyph glyph-name="parenleft" horiz-adv-x="689" unicode="(" d="M133 587q33 231 122.5 450t219.5 373.5t290 233.5l27 -124q-157 -117 -269.5 -305.5t-173.5 -448t-59 -511.5q0 -207 53.5 -364.5t154.5 -248.5l-45 -112q-167 116 -255.5 343t-80.5 520q2 96 14 183z"/> +<glyph glyph-name="parenright" horiz-adv-x="701" unicode=")" d="M547 585q-35 -244 -127 -461.5t-220.5 -367t-284.5 -227.5l-28 115q343 258 458 829q46 230 44 443q-5 429 -208 615l47 112q112 -78 189.5 -207.5t114 -301t32.5 -355.5q-3 -97 -15 -183z"/> +<glyph glyph-name="asterisk" horiz-adv-x="866" unicode="*" d="M384 987l-277 90l68 144l278 -113l51 348h150l-70 -344l303 108l19 -159l-315 -91l147 -275l-128 -88l-131 290l-222 -280l-114 98z"/> +<glyph glyph-name="plus" horiz-adv-x="1136" unicode="+" d="M682 781h394l-31 -175h-393l-80 -460h-182l80 460h-394l31 175h393l74 425h182z"/> +<glyph glyph-name="comma" horiz-adv-x="400" unicode="," d="M-9 -291l-104 75q116 143 144 284l26 151h177l-21 -135q-36 -228 -222 -375z"/> +<glyph glyph-name="hyphen" horiz-adv-x="558" unicode="-" d="M500 543h-475l27 151h475z"/> +<glyph glyph-name="period" horiz-adv-x="533" unicode="." d="M164 210q49 1 81 -30t31 -80t-33 -79.5t-80 -32.5t-79 27.5t-31 78.5t31 81.5t80 34.5z"/> +<glyph glyph-name="slash" horiz-adv-x="829" unicode="/" d="M51 -125h-164l864 1581h163z"/> +<glyph glyph-name="zero" d="M472 -20q-184 4 -276 130.5t-84 364.5q2 74 11 146l36 243q48 311 183 464t356 148q186 -4 277.5 -127.5t84.5 -358.5q-3 -75 -12 -147l-35 -235q-53 -329 -187 -481t-354 -147zM873 876q14 121 13 188q-5 254 -197 261q-140 5 -226.5 -103.5t-120.5 -340.5l-43 -290 q-14 -116 -13 -189q5 -265 196 -272q133 -6 219.5 98t123.5 330z" unicode="0"/> +<glyph glyph-name="one" d="M604 0h-182l214 1228l-387 -136l31 176l540 195h32z" unicode="1"/> +<glyph glyph-name="two" d="M950 0h-927l22 141l537 522l98 97q169 169 187 312q13 110 -43 179.5t-158 73.5q-131 4 -219 -76.5t-107 -220.5l-179 -1q13 134 82.5 237.5t183 159t246.5 52.5q181 -4 287.5 -109.5t91.5 -273.5q-17 -192 -221 -404l-92 -93l-468 -445h703z" unicode="2"/> +<glyph glyph-name="three" d="M416 818l120 -1q132 0 222.5 69.5t103.5 188.5q13 116 -43 182.5t-163 68.5q-114 2 -193.5 -66.5t-97.5 -184.5l-179 -1q17 180 153.5 292.5t325.5 110.5q183 -4 287.5 -114.5t90.5 -291.5q-9 -103 -79 -188t-194 -141q99 -40 148 -126.5t41 -202.5q-16 -197 -156.5 -317 t-341.5 -116q-187 4 -298 116t-103 289l181 -1q-6 -112 54 -180.5t174 -72.5q128 -4 213 73t97 206q11 119 -54 185.5t-194 70.5l-139 1z" unicode="3"/> +<glyph glyph-name="four" d="M857 489h196l-27 -151h-195l-59 -338h-182l59 338h-644l21 119l800 999h198zM243 489h432l130 716l-29 -42z" unicode="4"/> +<glyph glyph-name="five" d="M219 733l185 723h726l-27 -171h-570l-112 -398q110 65 238 63q181 -2 278 -136.5t79 -342.5q-19 -224 -159 -360t-349 -132q-174 2 -281 112t-113 293h169q7 -120 68 -186t165 -68q128 -4 215.5 91t103.5 249q14 135 -47 222.5t-179 91.5q-73 2 -129.5 -22t-112.5 -69z " unicode="5"/> +<glyph glyph-name="six" d="M955 1458l-16 -157h-35q-200 -4 -342 -124t-220 -354q136 136 318 132q115 -2 197 -63.5t120.5 -170t26.5 -239.5q-20 -221 -158.5 -364.5t-340.5 -137.5q-162 4 -266 119t-119 308q-8 105 25 284q69 373 272.5 570t517.5 197h20zM621 802q-97 2 -182 -56t-131 -148 l-7 -67l-2 -81q0 -82 25 -159t74 -117t115 -41q121 -5 207.5 90t103.5 250q10 90 -11 165t-69.5 118.5t-122.5 45.5z" unicode="6"/> +<glyph glyph-name="seven" d="M1146 1342l-791 -1342h-198l787 1304h-760l24 152h956z" unicode="7"/> +<glyph glyph-name="eight" d="M1064 1085q-9 -109 -77.5 -196.5t-186.5 -144.5q94 -54 139.5 -144.5t37.5 -197.5q-15 -193 -158 -309.5t-345 -112.5q-189 4 -299 117t-95 288q11 125 88 218.5t210 151.5q-78 54 -115.5 136t-29.5 176q14 185 145 299t322 110q174 -4 276 -113t88 -278zM798 406 q12 113 -48 188.5t-174 79.5q-124 2 -212 -78.5t-102 -207.5q-12 -116 48.5 -186t171.5 -72q126 -4 214 73.5t102 202.5zM882 1082q11 101 -41.5 170t-149.5 73q-112 2 -189 -71.5t-90 -189.5q-11 -104 42.5 -171t150.5 -69q109 -2 186.5 70.5t90.5 187.5z" unicode="8"/> +<glyph glyph-name="nine" d="M823 640q-74 -78 -157 -116.5t-165 -36.5q-115 2 -196.5 65t-119 173t-25.5 240q13 144 81 264t177.5 185.5t241.5 61.5q174 -4 273 -126t107 -327q3 -107 -25 -266q-66 -374 -260.5 -563.5t-499.5 -195.5h-45l16 156h37q215 4 352.5 120.5t207.5 365.5zM539 640 q91 -4 175 51.5t138 149.5l8 73l3 81q-4 155 -57.5 239t-153.5 88q-124 5 -211.5 -95.5t-101.5 -251.5q-7 -61 2 -124t36 -111q54 -97 162 -100z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="491" unicode=":" d="M154 210q49 1 81 -30t31 -80t-33 -79.5t-80 -32.5t-79 27.5t-31 78.5t31 81.5t80 34.5zM307 1093q49 1 81 -30t31 -80t-33 -79.5t-80 -32.5t-79 27.5t-31 78.5t31 81.5t80 34.5z"/> +<glyph glyph-name="semicolon" horiz-adv-x="430" unicode=";" d="M284 1093q49 1 81 -30t31 -80t-33 -79.5t-80 -32.5t-79 27.5t-31 78.5t31 81.5t80 34.5zM3 -291l-104 75q116 143 144 284l26 151h177l-21 -135q-36 -228 -222 -375z"/> +<glyph glyph-name="less" horiz-adv-x="1020" unicode="<" d="M263 640l565 -253l-33 -187l-730 379l26 146l861 378l-36 -205z"/> +<glyph glyph-name="equal" horiz-adv-x="1100" unicode="=" d="M994 814h-810l28 161h811zM922 399h-810l28 160h811z"/> +<glyph glyph-name="greater" horiz-adv-x="1048" unicode=">" d="M781 654l-598 259l33 182l764 -379l-26 -145l-896 -380l36 201z"/> +<glyph glyph-name="question" horiz-adv-x="948" unicode="?" d="M321 409q13 115 61 203t156 184l81 71q125 111 141 233q12 94 -31 153t-134 63q-102 2 -167.5 -54.5t-82.5 -145.5l-180 -1q19 165 141.5 264.5t299.5 97.5q168 -4 260.5 -106t78.5 -267q-17 -182 -204 -350l-122 -104q-98 -89 -121 -240zM250 90q1 47 30 77.5t77 32.5 q46 1 76.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -31q-47 -2 -76.5 27t-29.5 75z"/> +<glyph glyph-name="at" horiz-adv-x="1794" unicode="@" d="M1199 -20q-89 2 -143.5 46.5t-67.5 121.5q-136 -172 -279 -169q-116 2 -172 93t-44 247q10 161 86 328.5t186 256t240 86.5q139 -3 272 -105l-133 -558q-10 -66 -10 -93q-5 -135 92 -138q147 -6 238 165t102 441q7 180 -46 317t-168.5 207t-284.5 73q-221 4 -410 -123 t-311.5 -370t-134.5 -522q-8 -181 47 -323t167 -214.5t274 -73.5q169 -4 339 78l27 -117q-139 -87 -368 -87q-191 1 -332 84.5t-218 244t-77 370.5q-2 217 77.5 442.5t221 397t322 260t380.5 85.5q194 -3 333.5 -87t213 -245t73.5 -365q0 -225 -65.5 -401t-176 -266.5 t-250.5 -86.5zM649 294q-5 -171 112 -174q107 -5 200 144l32 53l1 11l133 506q-52 28 -107 29q-139 5 -235.5 -135t-130.5 -377z"/> +<glyph glyph-name="A" horiz-adv-x="1306" unicode="A" d="M909 380h-590l-199 -380h-201l791 1456h165l288 -1456h-185zM402 538h479l-121 679z"/> +<glyph glyph-name="B" horiz-adv-x="1247" unicode="B" d="M59 0l253 1456l427 -1q223 0 334 -100t97 -279q-18 -209 -263 -315q98 -38 146.5 -130t39.5 -203q-15 -197 -158 -312.5t-370 -115.5h-506zM365 681l-91 -524l297 -1q136 0 228 73t107 197q14 118 -41 184t-173 70zM392 835l271 -1q127 0 214.5 65t102.5 179 q13 106 -41.5 160t-180.5 59l-286 1z"/> +<glyph glyph-name="C" horiz-adv-x="1303" unicode="C" d="M1169 464q-42 -226 -204.5 -358t-389.5 -126q-135 3 -236 66.5t-157 183t-62 264.5q-4 82 7 160l17 120q47 328 230.5 517.5t446.5 184.5q205 -4 325 -132.5t127 -356.5h-187q-13 306 -240 330l-33 2q-189 5 -315.5 -140.5t-163.5 -397.5l-22 -151l-6 -88 q-6 -184 65.5 -292.5t212.5 -112.5q152 -5 251.5 73t151.5 251z"/> +<glyph glyph-name="D" horiz-adv-x="1313" unicode="D" d="M59 0l253 1456l378 -1q178 0 306.5 -89t184.5 -245.5t33 -350.5l-10 -73q-44 -318 -247 -507.5t-510 -189.5h-388zM472 1298l-198 -1141l185 -1q212 0 359.5 132t191.5 362q35 184 24 313q-15 155 -103 242.5t-236 91.5z"/> +<glyph glyph-name="E" horiz-adv-x="1139" unicode="E" d="M976 673h-612l-90 -516h712l-28 -157h-899l253 1456h889l-28 -158h-701l-81 -468h612z"/> +<glyph glyph-name="F" horiz-adv-x="1108" unicode="F" d="M951 643h-592l-112 -643h-188l253 1456h876l-28 -158h-688l-86 -498h593z"/> +<glyph glyph-name="G" horiz-adv-x="1363" unicode="G" d="M1147 192q-73 -103 -212.5 -158.5t-318.5 -53.5q-143 3 -250 67t-168 183.5t-70 271.5q-7 119 29.5 322t127.5 351t227.5 226t312.5 75q203 -4 323.5 -120.5t137.5 -327.5h-186q-11 138 -83 212t-199 78q-188 7 -314.5 -135t-166.5 -415l-19 -140l-3 -76 q0 -197 81 -304.5t227 -109.5q211 -5 335 104l60 327h-328l28 156h512z"/> +<glyph glyph-name="H" horiz-adv-x="1426" unicode="H" d="M1146 0h-188l117 673h-711l-117 -673h-188l253 1456h188l-109 -626h710l109 626h189z"/> +<glyph glyph-name="I" horiz-adv-x="550" unicode="I" d="M260 0h-187l253 1456h187z"/> +<glyph glyph-name="J" horiz-adv-x="1106" unicode="J" d="M910 1456h188l-175 -1031q-29 -206 -167 -328.5t-344 -118.5q-192 4 -297 116t-93 308h187q-11 -120 45 -191.5t168 -73.5q123 -4 208 77t104 210z"/> +<glyph glyph-name="K" horiz-adv-x="1255" unicode="K" d="M544 675l-213 -191l-84 -484h-188l253 1456h188l-124 -709l742 709h242l-677 -652l453 -804h-209z"/> +<glyph glyph-name="L" horiz-adv-x="1079" unicode="L" d="M275 157h670l-28 -157h-858l253 1456h189z"/> +<glyph glyph-name="M" horiz-adv-x="1744" unicode="M" d="M549 1456l255 -1186l668 1186h247l-253 -1456h-187l100 576l119 586l-660 -1162h-144l-260 1185l-90 -628l-97 -557h-188l253 1456h237z"/> +<glyph glyph-name="N" horiz-adv-x="1426" unicode="N" d="M1146 0h-182l-520 1130l-196 -1130h-189l253 1456h182l521 -1135l197 1135h187z"/> +<glyph glyph-name="O" horiz-adv-x="1376" unicode="O" d="M593 -20q-139 3 -241.5 67t-161.5 188.5t-65 279.5q-6 121 27 299t114 321t197 229q157 116 358 112q213 -4 336 -147.5t132 -388.5q4 -105 -21.5 -267t-91 -301t-166.5 -233q-176 -164 -417 -159zM1104 894q6 197 -69 305.5t-223 112.5q-134 4 -239.5 -72t-173 -227.5 t-85.5 -383.5l-3 -65q-6 -196 70 -307t221 -115q189 -5 313.5 136.5t165.5 397.5q20 126 23 218z"/> +<glyph glyph-name="P" horiz-adv-x="1263" unicode="P" d="M346 570l-99 -570h-188l253 1456l486 -1q225 0 347 -119.5t105 -317.5q-18 -209 -166.5 -329t-391.5 -120zM373 727l324 -1q153 0 251 77t115 214q16 123 -51 199.5t-195 80.5l-345 1z"/> +<glyph glyph-name="Q" horiz-adv-x="1376" unicode="Q" d="M907 76l217 -209l-139 -113l-254 243q-74 -16 -148 -16q-137 1 -241 66.5t-161.5 189t-63.5 279.5q-6 126 26.5 300.5t111.5 315t191 226.5q160 122 366 118q141 -3 245 -68t161 -188.5t63 -279.5q3 -84 -7 -167l-12 -85q-62 -431 -355 -612zM1095 894q7 200 -69 307 t-222 111q-134 4 -239.5 -72t-173 -227.5t-85.5 -383.5l-3 -65q-4 -115 27 -215t98.5 -152t165.5 -55q184 -7 309.5 133t167.5 395q21 127 24 224z"/> +<glyph glyph-name="R" horiz-adv-x="1233" unicode="R" d="M685 589h-336l-102 -589h-189l253 1456l438 -1q229 -1 349 -116t101 -313q-11 -137 -99.5 -241t-235.5 -157l226 -615l-1 -13h-200zM376 746l276 -1q144 0 243 76.5t116 204.5q15 125 -50 196t-198 75l-291 1z"/> +<glyph glyph-name="S" horiz-adv-x="1189" unicode="S" d="M877 375q22 160 -166 234l-173 63l-58 25q-292 133 -273 374q10 121 83 214t193.5 143.5t256.5 47.5q132 -3 235.5 -59t157.5 -156.5t48 -226.5l-189 1q10 134 -60 207.5t-200 75.5q-137 2 -229 -64t-106 -180q-20 -149 183 -226l149 -53l75 -32q282 -130 261 -386 q-11 -123 -83 -212.5t-195.5 -138.5t-265.5 -46q-137 1 -250.5 58.5t-172.5 157.5t-52 227l188 -1q-9 -130 70.5 -206.5t224.5 -78.5t239 63t109 175z"/> +<glyph glyph-name="T" horiz-adv-x="1195" unicode="T" d="M1261 1298h-453l-225 -1298h-187l225 1298h-453l28 158h1093z"/> +<glyph glyph-name="U" horiz-adv-x="1298" unicode="U" d="M1312 1456l-168 -985q-34 -227 -196 -361.5t-391 -130.5q-143 3 -248.5 64.5t-155.5 173t-33 253.5l168 986h185l-167 -987q-17 -153 52 -240.5t209 -91.5q152 -6 256.5 82.5t131.5 248.5l168 988h189z"/> +<glyph glyph-name="V" horiz-adv-x="1274" unicode="V" d="M574 257l591 1199h212l-752 -1456h-166l-295 1456h197z"/> +<glyph glyph-name="W" horiz-adv-x="1772" unicode="W" d="M446 449l-4 -176l68 172l435 1011h159l115 -1024l10 -166l63 201l372 989h193l-570 -1456h-171l-126 1069l-4 100l-42 -116l-464 -1053h-171l-114 1456h183z"/> +<glyph glyph-name="X" horiz-adv-x="1255" unicode="X" d="M666 899l425 557h232l-567 -731l339 -725h-211l-258 567l-438 -567h-232l579 743l-330 713h208z"/> +<glyph glyph-name="Y" horiz-adv-x="1203" unicode="Y" d="M611 726l495 730h224l-653 -923l-93 -533h-187l96 554l-325 902h204z"/> +<glyph glyph-name="Z" horiz-adv-x="1199" unicode="Z" d="M234 157h802l-28 -157h-1029l27 154l966 1144h-756l28 158h986l-26 -151z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="537" unicode="[" d="M650 1512h-185l-261 -1672h186l-24 -152h-367l308 1976h368z"/> +<glyph glyph-name="backslash" horiz-adv-x="825" unicode="\" d="M191 1456h164l315 -1581h-163z"/> +<glyph glyph-name="bracketright" horiz-adv-x="537" unicode="]" d="M175 1664h368l-309 -1976h-368l24 152h187l261 1672h-188z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="840" unicode="^" d="M524 1209l-268 -480h-177l417 727h124l163 -727h-158z"/> +<glyph glyph-name="underscore" horiz-adv-x="906" unicode="_" d="M763 -151h-890l27 151h890z"/> +<glyph glyph-name="grave" horiz-adv-x="624" unicode="`" d="M555 1240h-143l-205 294h205z"/> +<glyph glyph-name="a" horiz-adv-x="1091" unicode="a" d="M693 0q-7 29 -7 57l3 57q-149 -138 -316 -134q-143 2 -232.5 90.5t-81.5 221.5q10 172 150.5 268.5t369.5 96.5l189 -1l12 86q10 97 -37.5 153.5t-142.5 58.5q-93 2 -164.5 -45.5t-87.5 -125.5l-182 -1q9 95 74 168.5t167 114t211 38.5q169 -4 263 -102.5t79 -261.5 l-88 -536l-5 -77q-2 -55 12 -109l-2 -17h-184zM409 140q87 -2 164.5 41.5t133.5 120.5l39 223l-137 1q-171 0 -262 -54t-103 -153q-9 -76 35.5 -126.5t129.5 -52.5z"/> +<glyph glyph-name="b" horiz-adv-x="1125" unicode="b" d="M1013 536q-20 -166 -91 -299t-172 -197t-224 -61q-196 4 -291 147l-37 -126h-167l267 1536h181l-109 -574q130 144 316 140q156 -4 243 -115t92 -306q1 -64 -6 -124zM841 641q3 146 -49 223.5t-159 81.5q-169 4 -286 -170l-81 -471q60 -165 225 -169q106 -4 185.5 63 t120.5 187.5t44 254.5z"/> +<glyph glyph-name="c" horiz-adv-x="1050" unicode="c" d="M488 130q97 -2 175 56.5t102 153.5l171 1q-15 -102 -81.5 -186t-167.5 -131t-207 -44q-135 2 -228.5 70.5t-137.5 191t-30 275.5l5 50q19 156 91 279t188 191.5t256 64.5q170 -4 272 -114t102 -279l-169 1q-2 106 -59 171.5t-154 69.5q-141 3 -234.5 -105t-116.5 -302 l-3 -26q-6 -64 -2 -132q7 -117 66 -185t162 -71z"/> +<glyph glyph-name="d" horiz-adv-x="1130" unicode="d" d="M83 543q20 165 91 298t175 199t229 63q181 -4 278 -132l104 565h181l-266 -1536h-165l19 116q-128 -140 -316 -136q-150 4 -239 117.5t-96 304.5q-3 59 5 141zM257 439q-3 -143 51 -222t158 -81q157 -7 279 158l86 500q-60 148 -218 152q-107 3 -188.5 -64.5t-124 -189 t-43.5 -253.5z"/> +<glyph glyph-name="e" horiz-adv-x="1062" unicode="e" d="M499 -20q-202 4 -316 149t-96 371l5 43q17 161 95.5 294t191.5 200.5t244 64.5q167 -4 262 -111t104 -290q3 -65 -4 -130l-11 -83h-707q-18 -147 48.5 -250t198.5 -107q160 -4 296 144l104 -88q-68 -98 -175.5 -153.5t-239.5 -53.5zM614 951q-112 3 -195.5 -76 t-132.5 -235l526 -1l4 16q16 126 -40.5 209.5t-161.5 86.5z"/> +<glyph glyph-name="f" horiz-adv-x="700" unicode="f" d="M119 0l164 939h-167l25 143h166l18 128q26 163 126 255q105 96 268 94q51 0 129 -17l-22 -151q-48 10 -97 12q-94 0 -152.5 -58.5t-72.5 -155.5l-16 -107h224l-25 -143h-224l-163 -939h-181z"/> +<glyph glyph-name="g" horiz-adv-x="1125" unicode="g" d="M84 543q24 177 95.5 307.5t174 193t224.5 59.5q188 -4 284 -142l36 121h166l-180 -1059q-29 -207 -168 -331.5t-343 -118.5q-110 2 -210.5 52t-158.5 137l103 111q98 -145 259 -149q129 -4 218.5 72t118.5 216l20 96q-132 -132 -309 -128q-101 3 -175.5 54.5t-115.5 149 t-45 217.5q-2 59 6 142zM259 440q-3 -143 49.5 -221.5t158.5 -82.5q162 -4 279 159l85 497q-60 148 -217 154q-147 4 -241.5 -120t-111.5 -335z"/> +<glyph glyph-name="h" horiz-adv-x="1104" unicode="h" d="M369 950q142 155 327 151q152 -2 225.5 -104.5t54.5 -287.5l-118 -709h-181l119 712q6 49 1 91q-17 140 -165 143q-166 4 -286 -174l-134 -772h-181l267 1536h181z"/> +<glyph glyph-name="i" horiz-adv-x="492" unicode="i" d="M227 0h-180l188 1082h180zM376 1477q46 2 76.5 -27.5t30.5 -77.5q-1 -47 -30.5 -77t-76.5 -32t-77 27t-29 76t30 78t76 33z"/> +<glyph glyph-name="j" horiz-adv-x="484" unicode="j" d="M406 1082l-205 -1211q-20 -153 -102.5 -233t-215.5 -78q-53 2 -119 20l16 148q37 -9 83 -11q129 0 155 154l207 1211h181zM256 1366q1 47 29.5 78t76.5 33q46 2 76.5 -28.5t30.5 -76.5q-1 -47 -31 -77t-77 -32q-45 -2 -75 28t-30 75z"/> +<glyph glyph-name="k" horiz-adv-x="1017" unicode="k" d="M419 499l-142 -127l-64 -372h-181l267 1536h181l-160 -918l111 112l384 352h235l-497 -461l342 -621h-198z"/> +<glyph glyph-name="l" horiz-adv-x="492" unicode="l" d="M227 0h-180l266 1536h181z"/> +<glyph glyph-name="m" horiz-adv-x="1751" unicode="m" d="M388 1083l-23 -121q136 144 329 140q103 -2 174.5 -47t98.5 -127q152 178 359 174q162 -4 239 -109t57 -282l-119 -711h-180l118 713q6 52 0 95q-19 136 -178 139q-99 2 -179.5 -61.5t-103.5 -166.5l-123 -719h-182l120 712q13 111 -33.5 171t-144.5 62q-169 4 -269 -154 l-137 -791h-181l188 1082z"/> +<glyph glyph-name="n" horiz-adv-x="1106" unicode="n" d="M390 1083l-26 -137q146 160 332 156q153 -4 226 -106t54 -287l-118 -709h-181l119 712q6 49 1 91q-17 140 -165 143q-163 3 -286 -174l-134 -772h-181l188 1082z"/> +<glyph glyph-name="o" horiz-adv-x="1143" unicode="o" d="M632 1102q136 -2 233 -74t143.5 -198.5t31.5 -276.5l-2 -22q-19 -158 -94 -285.5t-194 -198.5t-261 -67q-135 2 -232.5 74t-142.5 196t-32 273q15 168 91 302t195.5 207.5t263.5 69.5zM264 522q-7 -63 0 -131q10 -118 70.5 -188t161.5 -73q90 -3 166 44.5t128 143.5 t67 213q8 92 3 155q-12 121 -73 191t-162 74q-140 3 -238 -110t-121 -296z"/> +<glyph glyph-name="p" horiz-adv-x="1125" unicode="p" d="M1011 536q-20 -165 -89 -297t-171 -197.5t-226 -62.5q-188 4 -288 127l-97 -522h-181l260 1498l164 1l-20 -121q134 144 321 140q156 -4 243 -115t92 -306q1 -64 -5 -124zM833 557l5 84q0 146 -55.5 223.5t-160.5 81.5q-157 4 -271 -149l-91 -519q61 -144 219 -148 q135 -3 229.5 105.5t124.5 321.5z"/> +<glyph glyph-name="q" horiz-adv-x="1139" unicode="q" d="M585 1103q183 -4 279 -131l33 110h167l-260 -1498h-180l98 516q-130 -124 -302 -120q-152 2 -243 115t-98 305q-6 124 29 261.5t104.5 240t164.5 153.5t208 48zM265 522l-5 -84q-3 -145 52.5 -225.5t159.5 -82.5q153 -4 271 146l94 532q-66 139 -216 143 q-137 3 -231 -105t-125 -324z"/> +<glyph glyph-name="r" horiz-adv-x="682" unicode="r" d="M704 917l-85 9q-174 0 -274 -157l-133 -769h-181l188 1082l175 1l-27 -126q115 151 271 147q33 0 86 -15z"/> +<glyph glyph-name="s" horiz-adv-x="1034" unicode="s" d="M701 293q15 112 -123 158l-188 55q-238 82 -230 272q7 143 130.5 234.5t290.5 89.5q164 -2 266.5 -95.5t98.5 -243.5l-180 1q2 81 -51 132t-141 53q-94 2 -162 -46q-63 -45 -73 -118q-13 -94 115 -137l91 -25q186 -48 264 -125t72 -191q-6 -101 -66 -176t-160 -114.5 t-213 -36.5q-172 2 -284 100.5t-108 253.5l181 -1q0 -91 58 -146t159 -55q99 -2 171 41.5t82 119.5z"/> +<glyph glyph-name="t" horiz-adv-x="659" unicode="t" d="M509 1344l-46 -262h197l-25 -143h-196l-113 -673q-3 -26 -1 -48q7 -78 85 -78q33 0 88 10l-14 -151q-65 -18 -132 -18q-108 2 -162 79.5t-42 208.5l110 670h-191l25 143h191l46 262h180z"/> +<glyph glyph-name="u" horiz-adv-x="1105" unicode="u" d="M718 107q-127 -131 -323 -127q-155 4 -229.5 111t-55.5 292l116 699h181l-117 -702q-5 -44 -2 -86q5 -72 43 -113t106 -44q194 -6 300 157l136 788h181l-188 -1082h-171z"/> +<glyph glyph-name="v" horiz-adv-x="972" unicode="v" d="M424 253l390 829h191l-545 -1082h-138l-212 1082h178z"/> +<glyph glyph-name="w" horiz-adv-x="1503" unicode="w" d="M1002 256l345 826h187l-493 -1082h-147l-112 818l-390 -818h-147l-117 1082h173l66 -806l384 806h146z"/> +<glyph glyph-name="x" horiz-adv-x="995" unicode="x" d="M496 688l294 394h222l-434 -544l264 -538h-197l-179 404l-305 -404h-221l447 556l-256 526h198z"/> +<glyph glyph-name="y" horiz-adv-x="950" unicode="y" d="M419 273l385 809h200l-642 -1262q-134 -263 -344 -260q-37 1 -109 18l16 150l47 -5q86 -4 148.5 38.5t110.5 137.5l65 124l-187 1059h189z"/> +<glyph glyph-name="z" horiz-adv-x="995" unicode="z" d="M234 151h608l-27 -151h-834l25 145l709 784h-565l28 153h796l-24 -140z"/> +<glyph glyph-name="braceleft" horiz-adv-x="682" unicode="{" d="M478 -365q-158 53 -232 172.5t-55 291.5l28 207q6 49 1 91q-17 136 -164 144l16 145q217 10 249 245l31 228q59 339 410 440l27 -117q-212 -70 -257 -337l-34 -240q-33 -200 -211 -294q103 -77 113 -219q3 -44 -1 -87l-31 -243l-2 -71l2 -31q17 -159 151 -212z"/> +<glyph glyph-name="bar" horiz-adv-x="494" unicode="|" d="M179 -270h-146l270 1726h146z"/> +<glyph glyph-name="braceright" horiz-adv-x="682" unicode="}" d="M-116 -251q217 71 260 344l31 226q31 208 226 301q-113 69 -126 216q-4 42 1 87l31 246l2 71q-3 184 -152 242l45 113q156 -53 228 -172.5t53 -290.5l-27 -208q-6 -50 -1 -91q16 -135 163 -143l-15 -145q-218 -10 -250 -248l-28 -207q-51 -354 -413 -458z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1361" unicode="~" d="M1245 778q-14 -163 -111.5 -271.5t-237.5 -106.5q-126 3 -249 115l-60 58q-72 67 -138 67q-136 3 -180 -164l-8 -37l-156 -3q16 162 113.5 266.5t238.5 100.5q119 -3 227 -96l89 -83q68 -61 131 -61q75 0 127.5 55t70.5 157z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="494" unicode="¡" d="M179 684h165l-169 -1044h-190zM416 999q0 -47 -29 -78t-77 -33t-77.5 29t-29.5 76q1 48 30.5 77.5t76.5 31.5q46 1 76.5 -28t29.5 -75z"/> +<glyph glyph-name="cent" horiz-adv-x="1096" unicode="¢" d="M489 130q97 -2 175.5 55.5t105.5 154.5l172 1q-21 -134 -125.5 -228.5t-264.5 -124.5l-46 -233h-181l47 236q-119 30 -191.5 124t-86.5 235q-12 111 10 244.5t82.5 238.5t153.5 171.5t212 87.5l45 226h181l-45 -225q131 -32 204.5 -133.5t73.5 -250.5h-170q0 106 -56 172 t-153 70q-152 6 -251 -122t-113 -356l-1 -42q-3 -142 55 -220.5t167 -80.5z"/> +<glyph glyph-name="sterling" horiz-adv-x="1164" unicode="£" d="M440 622l-28 -212q-20 -153 -108 -256l715 3l-29 -157h-1003l29 156l67 -2q113 41 142 262l27 206h-160l27 157h156l31 253q25 204 164 327t331 117q168 -4 264 -108.5t88 -281.5l-187 1q7 106 -42 167t-150 65q-110 4 -187 -78t-93 -211l-32 -251h310l-27 -157h-305z "/> +<glyph glyph-name="currency" horiz-adv-x="1426" unicode="¤" d="M996 110q-187 -134 -377 -130q-199 4 -335 130l-157 -136l-109 144l159 134q-30 85 -40 172q-19 150 25.5 294.5t148.5 261.5l-117 157l141 127l114 -148q179 122 361 118q188 -2 325 -121l175 152l111 -146l-173 -147q32 -87 44 -176q18 -144 -22.5 -285t-139.5 -261 l115 -150l-143 -127zM304 599q-15 -114 22 -218t116.5 -165.5t187.5 -65.5q117 -4 224.5 59t180 174t88.5 234q14 115 -22.5 218t-115.5 163.5t-187 64.5q-118 4 -226 -59t-180 -173t-88 -232z"/> +<glyph glyph-name="yen" horiz-adv-x="1213" unicode="Â¥" d="M622 783l469 673h225l-530 -720h297l-22 -125h-372l-29 -165h373l-22 -124h-372l-57 -322h-188l56 322h-367l22 124h366l29 165h-367l22 125h310l-281 720h203z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="486" unicode="¦" d="M-9 -270l138 791h182l-138 -791h-182zM341 698h-182l132 758h182z"/> +<glyph glyph-name="section" horiz-adv-x="1228" unicode="§" d="M1087 439q-18 -191 -229 -287q103 -103 90 -272q-14 -174 -158 -276t-366 -100q-217 4 -338 119t-110 314l181 1q-6 -85 25.5 -148t96.5 -97.5t153 -35.5q83 -2 157 25t120 76.5t55 118.5q12 77 -41.5 132.5t-192 100t-218.5 82.5q-242 115 -222 351q14 184 224 287 q-99 106 -86 272q8 108 75 194.5t186 133.5q123 48 264 46q207 -4 319.5 -118.5t100.5 -312.5h-180q8 126 -58 201t-190 79q-135 2 -226.5 -56.5t-106.5 -163.5q-11 -81 37 -135.5t183.5 -96.5t206.5 -73q269 -116 248 -361zM616 691l-154 52q-167 -47 -189 -198 q-14 -100 61 -161q50 -41 179 -81.5t194 -65.5q174 52 196 199q11 73 -36.5 129t-166.5 98z"/> +<glyph glyph-name="dieresis" horiz-adv-x="840" unicode="¨" d="M219 1369q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM636 1367q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="copyright" horiz-adv-x="1571" unicode="©" d="M1093 597q-14 -151 -107 -234.5t-242 -79.5q-145 4 -225 112t-66 275l10 98q20 189 123.5 298.5t260.5 107.5q142 -4 219.5 -85.5t71.5 -229.5l-143 1q6 85 -28.5 134t-124.5 51q-95 2 -158.5 -70.5t-78 -200t-13.5 -157.5l2 -35q7 -77 46.5 -122t107.5 -48 q170 -7 205 184zM230 570q22 -207 152 -338.5t320 -133.5q187 -4 353.5 107.5t258 302t71.5 380.5q-22 205 -150 334t-321 134q-189 4 -355.5 -108t-257.5 -300t-71 -378zM119 722q22 199 136 377t289 279.5t369 97.5q178 -2 320 -100t213 -271.5t50 -369.5 q-23 -203 -137 -380t-286 -277t-360 -99h-10q-183 4 -323 102t-211 271.5t-50 369.5z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="898" unicode="ª" d="M630 703l-4 74q-92 -86 -206 -86q-105 0 -165 61.5t-56 158.5q5 115 98 177t260 62l111 -1l9 54q3 27 1 51q-7 79 -92 82q-56 1 -99.5 -23.5t-58.5 -80.5l-156 11q11 109 99 172.5t219 61.5q123 -4 189.5 -78.5t56.5 -198.5l-54 -347l-4 -58q-1 -45 7 -91zM460 826 q75 0 166 68l28 143h-93q-88 -3 -140 -35t-60 -87q-5 -43 22 -66t77 -23z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="942" unicode="«" d="M261 538l178 -387h-125l-225 387l2 20l347 389h152zM581 538l178 -387h-125l-225 387l2 20l347 389h152z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1110" unicode="¬" d="M891 375h-182l47 264h-627l29 161h807z"/> +<glyph glyph-name="registered" horiz-adv-x="1572" unicode="®" d="M118 722q22 199 136 377t289 279.5t369 97.5q175 -2 316.5 -97.5t215 -269t51.5 -374.5q-23 -204 -138 -381.5t-288.5 -278.5t-365.5 -97q-179 4 -319 99.5t-213.5 270.5t-52.5 374zM229 569q12 -131 76.5 -241t167 -169t228.5 -62q187 -4 352 106t258 300t74 385 q-14 133 -78.5 241t-166 166t-227.5 61q-185 4 -350 -103t-259.5 -297.5t-74.5 -386.5zM654 654l-53 -338h-138l133 849l257 -1q139 -5 213.5 -69.5t67.5 -178.5q-3 -58 -37 -106t-115 -94q77 -44 86 -141l-1 -61q-11 -87 -9 -118l3 -64l-2 -17h-138q-6 37 -4 73l7 72l6 54 q7 66 -17 100.5t-92 38.5zM673 782l143 -1q72 2 122.5 36.5t59.5 92.5q10 63 -22.5 94t-121.5 34h-140z"/> +<glyph glyph-name="macron" horiz-adv-x="920" unicode="¯" d="M921 1313h-694l23 143h694z"/> +<glyph glyph-name="degree" horiz-adv-x="752" unicode="°" d="M236 1207q4 111 84.5 191.5t183.5 78.5q97 -2 160.5 -76.5t61.5 -175.5q-4 -112 -83.5 -190t-181.5 -76q-98 2 -163.5 74.5t-61.5 173.5zM357 1209q-6 -49 24.5 -85.5t79.5 -36.5q54 0 96.5 40t48.5 96q6 48 -22 87.5t-80 39.5q-54 0 -97.5 -42.5t-49.5 -98.5z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1071" unicode="±" d="M670 854h353l-24 -151h-352l-65 -414h-164l65 414h-374l25 151h373l65 413h163zM848 0h-811l24 152h811z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="738" unicode="²" d="M674 667h-582l20 116l355 298q99 84 111 158q7 48 -19.5 75t-74.5 28q-66 1 -106 -36.5t-54 -99.5l-154 -1q11 117 98 191.5t215 72.5q120 -2 189.5 -65t64.5 -165q-8 -123 -159 -248l-64 -51l-196 -145h379z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="738" unicode="³" d="M343 1125l78 -1q66 2 112.5 32.5t53.5 84.5q6 49 -25 73.5t-81 24.5q-112 0 -141 -93h-156q11 101 90.5 161.5t204.5 60.5q126 -3 197 -62t66 -156q-7 -119 -159 -185q118 -43 114 -172q-5 -111 -95.5 -175.5t-223.5 -62.5q-119 2 -193.5 64t-74.5 170h151 q0 -50 33 -77.5t91 -27.5q64 0 109.5 32t52.5 85q13 102 -128 107l-87 1z"/> +<glyph glyph-name="acute" horiz-adv-x="633" unicode="´" d="M447 1534h230l-306 -294h-158z"/> +<glyph glyph-name="uni00B5" horiz-adv-x="1135" unicode="µ" d="M414 1082l-103 -624q-10 -84 -7 -142q10 -183 156 -186q183 -6 280 151l139 801h182l-188 -1082h-162l19 115q-111 -138 -273 -136q-135 0 -215 75l-89 -470h-180l260 1498h181z"/> +<glyph glyph-name="paragraph" horiz-adv-x="981" unicode="¶" d="M532 0l91 520l-64 1q-211 3 -323.5 130.5t-92.5 328.5q14 142 88 251t194 167.5t264 58.5l277 -1l-252 -1456h-182z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="528" unicode="·" d="M165 726q1 49 31.5 81.5t80.5 34.5q48 2 80 -29t32 -81q-1 -49 -33 -80.5t-81 -33.5q-45 -2 -77.5 27.5t-32.5 80.5z"/> +<glyph glyph-name="cedilla" horiz-adv-x="502" unicode="¸" d="M167 0l-21 -55q129 -29 125 -163q-3 -102 -90 -159t-237 -60l4 108q166 6 182 107q12 71 -92 83l-46 6l46 133h129z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="738" unicode="¹" d="M493 674h-154l104 597l-220 -56l24 135l356 113h21z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="913" unicode="º" d="M589 1477q141 -4 221.5 -102.5t67.5 -251.5l-7 -71q-17 -166 -121.5 -266.5t-254.5 -96.5q-142 4 -222.5 104t-67.5 250l7 70q17 168 122.5 268t254.5 96zM365 1041q-10 -96 26 -153.5t113 -59.5q79 -3 135 54t71 161l9 81q8 102 -29 156.5t-109 56.5q-82 2 -138 -56 t-70 -158z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="941" unicode="»" d="M291 949l225 -387l-2 -21l-347 -389h-152l328 408l-177 389h125zM629 949l225 -387l-2 -21l-347 -389h-152l328 408l-177 389h125z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1465" unicode="¼" d="M455 664h-154l104 597l-220 -56l24 135l356 113h21zM354 120l-98 72l881 1128l98 -72zM1227 299h104l-23 -130h-103l-30 -169h-154l30 169h-363l13 112l447 508h164zM865 299h208l58 291l-22 -30z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1551" unicode="½" d="M311 120l-98 72l881 1128l98 -72zM450 664h-154l104 597l-220 -56l24 135l356 113h21zM1333 0h-582l20 116l355 298q99 84 111 158q7 48 -19.5 75t-74.5 28q-66 1 -106 -36.5t-54 -99.5l-154 -1q11 117 98 191.5t215 72.5q120 -2 189.5 -65t64.5 -165q-8 -123 -159 -248 l-64 -51l-196 -145h379z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1555" unicode="¾" d="M477 120l-98 72l881 1128l98 -72zM1316 299h104l-23 -130h-103l-30 -169h-154l30 169h-363l13 112l447 508h164zM954 299h208l58 291l-22 -30zM391 1126l78 -1q66 2 112.5 32.5t53.5 84.5q6 49 -25 73.5t-81 24.5q-112 0 -141 -93h-156q11 101 90.5 161.5t204.5 60.5 q126 -3 197 -62t66 -156q-7 -119 -159 -185q118 -43 114 -172q-5 -111 -95.5 -175.5t-223.5 -62.5q-119 2 -193.5 64t-74.5 170h151q0 -50 33 -77.5t91 -27.5q64 0 109.5 32t52.5 85q13 102 -128 107l-87 1z"/> +<glyph glyph-name="questiondown" horiz-adv-x="950" unicode="¿" d="M584 681q-12 -109 -53.5 -189.5t-146.5 -180.5l-97 -91q-119 -115 -132 -230q-13 -98 34 -156t140 -60q98 -2 164.5 54.5t84.5 150.5l180 1q-19 -167 -141 -268.5t-299 -97.5q-173 4 -268 105t-80 267q15 183 206 358l116 102q91 85 116 234zM654 1000q0 -47 -29.5 -78 t-76.5 -33q-48 -2 -77.5 29t-29.5 76q1 47 31 76.5t76 31.5q46 1 76.5 -27.5t29.5 -74.5z"/> +<glyph glyph-name="AE" horiz-adv-x="1867" unicode="Æ" d="M1719 0h-857l47 353h-540l-261 -353h-232l1106 1456h930l-27 -152h-670l-63 -471h574l-27 -151h-567l-71 -531h685zM496 527h436l96 722z"/> +<glyph glyph-name="multiply" horiz-adv-x="1069" unicode="×" d="M40 338l379 335l-261 336l128 114l262 -334l377 334l101 -131l-376 -336l262 -336l-128 -114l-263 336l-379 -336z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1376" unicode="Ø" d="M590 -21q-166 4 -283 84l-124 -155h-151l189 232q-106 171 -101 401q1 97 25.5 247t84 279.5t148.5 222t202 141t240 45.5q206 -4 335 -126l131 165h150l-208 -256q49 -116 59 -238q14 -169 -29 -391t-156 -381.5t-272 -225.5q-112 -47 -240 -44zM302 487q2 -108 33 -191 l710 908q-77 104 -233 109q-182 5 -308 -133t-170 -382q-34 -192 -32 -311zM1109 933q4 78 -7 156l-691 -886q74 -58 188 -62q191 -5 317.5 142t166.5 417q22 147 26 233z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1184" unicode="Þ" d="M491 1456l-51 -293l238 -1q208 -1 326 -114.5t103 -301.5q-11 -130 -81.5 -228.5t-189.5 -152t-264 -53.5l-279 1l-55 -313h-182l253 1456h182zM414 1011l-95 -546l257 -1q139 0 236 76.5t114 203.5q14 120 -50.5 191t-182.5 75z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1191" unicode="ß" d="M211 0h-181l190 1111q18 134 77 237t152 156t214 51q159 -4 246 -93t74 -237q-9 -95 -90 -217t-93 -198q-9 -55 18 -109t100 -128t102 -130.5t26 -116.5q-10 -164 -126 -257.5t-289 -89.5q-178 2 -292 75l59 153q106 -75 219 -77q101 0 170.5 49.5t80.5 135.5 q7 57 -20.5 110.5t-101 128.5t-104 134.5t-24.5 122.5q5 59 33 107.5t60.5 94t61 93t36.5 105.5q10 82 -28 136t-119 58q-105 3 -173 -72.5t-89 -220.5z"/> +<glyph glyph-name="ae" horiz-adv-x="1687" unicode="æ" d="M1136 -20q-121 2 -213.5 48.5t-143.5 131.5q-169 -184 -445 -180q-146 2 -230.5 88.5t-74.5 227.5q10 160 137 250t344 90l226 -1l12 86q12 104 -31 164.5t-133 64.5q-104 2 -176 -51.5t-87 -139.5l-179 19q16 151 142 239t312 86q109 -2 190.5 -45.5t115.5 -120.5 q162 169 356 165q127 -2 214 -65t124 -173.5t20 -248.5l-18 -118h-702q-9 -68 0 -132q13 -107 77.5 -169.5t168.5 -63.5q90 -2 168.5 28t152.5 77l53 -137q-138 -120 -380 -120zM375 129q70 -2 149.5 34.5t145.5 93.5l43 238l-203 1q-120 0 -203 -56.5t-95 -147.5 q-9 -74 36 -117.5t127 -45.5zM1248 952q-110 3 -195 -75.5t-138 -236.5h522l6 32q9 55 2 105q-11 80 -62 126t-135 49z"/> +<glyph glyph-name="eth" horiz-adv-x="1174" unicode="ð" d="M926 1299q177 -295 127 -666l-13 -91q-24 -167 -102.5 -300t-191 -199.5t-242.5 -63.5q-188 4 -300 141.5t-93 338.5q14 144 83 265.5t180 189.5t243 64q154 -4 265 -115q-4 182 -110 335l-239 -148l-59 108l207 126q-102 86 -280 138l70 157q220 -56 370 -192l209 130 l58 -109zM877 695q-56 126 -226 131q-144 4 -242 -97.5t-117 -270.5q-15 -139 49 -232.5t176 -96.5q127 -5 218 104.5t122 301.5z"/> +<glyph glyph-name="divide" horiz-adv-x="1144" unicode="÷" d="M1038 600h-970l33 184h969zM534 1095q0 49 30.5 81.5t80.5 34.5q48 2 80 -29t32 -81q-1 -49 -32.5 -80t-80.5 -33t-80 28t-30 79zM392 278q1 49 31.5 81.5t80.5 34.5q48 2 80 -29t32 -81q-1 -49 -33 -80t-81 -33t-79.5 28.5t-30.5 78.5z"/> +<glyph glyph-name="oslash" horiz-adv-x="1135" unicode="ø" d="M638 1104q103 -2 194 -45l102 149l132 -1l-144 -207q110 -130 117 -328q2 -55 -6 -141q-19 -156 -98.5 -287.5t-199.5 -199.5t-262 -66q-89 2 -182 37l-102 -149l-132 1l141 205q-118 124 -125 329q-2 61 4 121l2 16q36 263 191 416.5t368 149.5zM249 447 q-10 -132 41 -223l459 698q-55 29 -119 31q-157 4 -261.5 -133.5t-119.5 -372.5zM863 701q-3 74 -34 143l-456 -692q50 -23 107 -25q140 -3 240.5 107t131.5 297q13 95 11 170z"/> +<glyph glyph-name="thorn" horiz-adv-x="1155" unicode="þ" d="M1020 536q-20 -166 -90 -299t-171.5 -197.5t-225.5 -61.5q-186 4 -287 128l-97 -522h-181l339 1952h180l-106 -567q131 137 312 133q158 -4 244.5 -118t89.5 -303q1 -61 -7 -145zM842 558l5 84q0 145 -56 223t-160 80q-160 4 -272 -148l-90 -519q61 -143 218 -148 q137 -3 231.5 106.5t123.5 321.5z"/> +<glyph glyph-name="dotlessi" horiz-adv-x="501" unicode="ı" d="M227 0h-181l188 1082h181z"/> +<glyph glyph-name="OE" horiz-adv-x="1904" unicode="Å’" d="M1650 0h-812l-217 -18l-69 -1q-152 4 -261.5 83t-158 216t-27.5 296l47 299q43 274 215.5 439t415.5 163l74 -2l211 -19h825l-28 -158h-701l-81 -468h612l-28 -157h-611l-90 -516h712zM558 133q76 -3 214 10l209 1168q-108 17 -203 17q-175 2 -293 -119.5t-151 -333.5 l-47 -300q-10 -78 -3 -156q10 -131 81 -206.5t193 -79.5z"/> +<glyph glyph-name="oe" horiz-adv-x="1814" unicode="Å“" d="M638 1102q121 -2 216 -60t138 -157q178 221 395 218q125 -2 213 -65t125 -173t20 -246l-19 -122h-692q-8 -61 -2 -125q10 -108 68.5 -172.5t154.5 -67.5q172 -6 316 105l61 -127q-68 -65 -168 -98t-215 -31q-124 2 -218.5 58.5t-138.5 151.5q-171 -217 -415 -211 q-133 2 -227 73t-136.5 195.5t-26.5 273.5l2 16q36 261 186.5 415t362.5 149zM269 522q-7 -62 -3 -130q5 -117 62.5 -188.5t158.5 -74.5q136 -5 233.5 105t123.5 297l2 22l5 87q0 143 -57.5 225t-166.5 86q-140 5 -236.5 -110.5t-119.5 -296.5zM1377 951q-101 3 -183.5 -74 t-137.5 -228l510 -1l5 28q8 53 1 102q-13 79 -64.5 124.5t-130.5 48.5z"/> +<glyph glyph-name="circumflex" horiz-adv-x="945" unicode="ˆ" d="M868 1264v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="ring" horiz-adv-x="674" unicode="Ëš" d="M259 1400q2 91 66.5 154t153.5 63q82 0 139.5 -58t57.5 -143q-2 -89 -66.5 -151t-153.5 -62q-84 0 -141.5 57t-55.5 140zM355 1402q-4 -46 23 -77.5t70 -31.5q46 0 85.5 35.5t45.5 85.5q6 46 -22 79t-70 33q-46 0 -86 -36.5t-46 -87.5z"/> +<glyph glyph-name="tilde" horiz-adv-x="947" unicode="Ëœ" d="M942 1501q-12 -111 -73 -178t-154 -67q-37 0 -67.5 15.5t-60.5 34.5t-61 34t-67 14q-85 -3 -116 -112l-122 7q12 110 74.5 180t155.5 68q27 0 50.5 -8.5t76.5 -41t77.5 -41.5t51.5 -8q86 0 118 113z"/> +<glyph glyph-name="endash" horiz-adv-x="1314" unicode="–" d="M1140.41 651h-973.21l32.4004 151h973.21z"/> +<glyph glyph-name="emdash" horiz-adv-x="1561" unicode="—" d="M1451.18 651h-1297.58l43.1992 151h1297.58z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="407" unicode="‘" d="M417 1555l100 -74q-112 -140 -139 -274l-24 -134h-180l18 112q36 222 225 370z"/> +<glyph glyph-name="quoteright" horiz-adv-x="407" unicode="’" d="M237 1046l-100 74q118 147 142 285l23 131h178l-19 -121q-36 -225 -224 -369z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="405" unicode="‚" d="M-5 -283l-99 75q115 144 139 283l18 106h181l-15 -96q-35 -220 -224 -368z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="712" unicode="“" d="M425 1555l100 -74q-112 -140 -139 -274l-24 -134h-180l18 112q36 222 225 370zM730 1555l100 -74q-112 -140 -139 -274l-24 -134h-180l18 112q36 222 225 370z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="719" unicode="â€" d="M249 1046l-100 74q118 147 142 285l23 131h178l-19 -121q-36 -225 -224 -369zM546 1046l-100 74q118 147 142 285l23 131h178l-19 -121q-36 -225 -224 -369z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="694" unicode="„" d="M-4 -302l-104 75q116 151 143 302l30 171h180l-25 -156q-39 -241 -224 -392zM283 -302l-103 75q116 154 142 302l30 171h181l-25 -156q-39 -240 -225 -392z"/> +<glyph glyph-name="bullet" horiz-adv-x="679" unicode="•" d="M161 765q6 94 64.5 150.5t144.5 56.5q81 0 133.5 -54.5t52.5 -142.5l-2 -42q-6 -90 -62.5 -145t-146.5 -55q-82 0 -133.5 53t-51.5 138z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="606" unicode="‹" d="M267 540l178 -387h-125l-225 387l2 20l347 389h152z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="606" unicode="›" d="M278 949l225 -387l-2 -21l-347 -389h-152l328 408l-177 389h125z"/> +<glyph glyph-name="fraction" horiz-adv-x="913" unicode="â„" d="M81 112l-98 72l881 1128l98 -72z"/> +<glyph glyph-name="uni2074" horiz-adv-x="738" unicode="â´" d="M636 955h104l-23 -130h-103l-30 -169h-154l30 169h-363l13 112l447 508h164zM274 955h208l58 291l-22 -30z"/> +<glyph glyph-name="Euro" d="M814 541h-370q-9 -74 -2 -145q12 -120 79 -187t181 -70q95 -3 219 31l5 -161q-114 -29 -233 -27q-226 4 -345 159t-87 401l-180 -1l22 124h172l25 137h-173l22 125h165q62 269 219.5 410.5t389.5 139.5q89 0 237 -30l-34 -164q-106 36 -205 38q-161 2 -266.5 -99 t-151.5 -295h378l-22 -125h-372l-24 -137h373z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1145" unicode="−" d="M982 651h-811l27 151h811z"/> +<glyph glyph-name="glyph162" d="M377 0h-154l104 597l-220 -56l24 135l356 113h21z" horiz-adv-x="738"/> +<glyph glyph-name="glyph163" d="M559 0h-582l20 116l355 298q99 84 111 158q7 48 -19.5 75t-74.5 28q-66 1 -106 -36.5t-54 -99.5l-154 -1q11 117 98 191.5t215 72.5q120 -2 189.5 -65t64.5 -165q-8 -123 -159 -248l-64 -51l-196 -145h379z" horiz-adv-x="738"/> +<glyph glyph-name="glyph164" d="M228 459l78 -1q66 2 112.5 32.5t53.5 84.5q6 49 -25 73.5t-81 24.5q-112 0 -141 -93h-156q11 101 90.5 161.5t204.5 60.5q126 -3 197 -62t66 -156q-7 -119 -159 -185q118 -43 114 -172q-5 -111 -95.5 -175.5t-223.5 -62.5q-119 2 -193.5 64t-74.5 170h151q0 -50 33 -77.5 t91 -27.5q64 0 109.5 32t52.5 85q13 102 -128 107l-87 1z" horiz-adv-x="738"/> +<glyph glyph-name="glyph165" d="M523 299h104l-23 -130h-103l-30 -169h-154l30 169h-363l13 112l447 508h164zM161 299h208l58 291l-22 -30z" horiz-adv-x="738"/> +<glyph glyph-name="uni00A0" horiz-adv-x="502" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="558" unicode="Â" d="M500 543h-475l27 151h475z"/> +<glyph glyph-name="Eth" horiz-adv-x="1343" unicode="Ã" d="M89 0l115 666h-157l27 151h157l111 639l378 -1q178 0 306.5 -89t184.5 -245.5t33 -350.5l-10 -73q-44 -318 -247 -507.5t-510 -189.5h-388zM665 666h-273l-88 -509l185 -1q212 0 359.5 132t191.5 362q35 184 24 313q-15 155 -103 242.5t-236 91.5l-223 1l-84 -481h274z "/> +<glyph glyph-name="Agrave" horiz-adv-x="1306" unicode="À" d="M909 380h-590l-199 -380h-201l791 1456h165l288 -1456h-185zM402 538h479l-121 679zM916 1550h-143l-205 294h205z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1306" unicode="Ã" d="M909 380h-590l-199 -380h-201l791 1456h165l288 -1456h-185zM402 538h479l-121 679zM946 1844h230l-306 -294h-158z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1306" unicode="Â" d="M909 380h-590l-199 -380h-201l791 1456h165l288 -1456h-185zM402 538h479l-121 679zM1117 1574v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1306" unicode="Ã" d="M909 380h-590l-199 -380h-201l791 1456h165l288 -1456h-185zM402 538h479l-121 679zM1199 1815q-12 -111 -73 -178t-154 -67q-37 0 -67.5 15.5t-60.5 34.5t-61 34t-67 14q-85 -3 -116 -112l-122 7q12 110 74.5 180t155.5 68q27 0 50.5 -8.5t76.5 -41t77.5 -41.5t51.5 -8 q86 0 118 113z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1306" unicode="Ä" d="M909 380h-590l-199 -380h-201l791 1456h165l288 -1456h-185zM402 538h479l-121 679zM526 1679q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM943 1677q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5 t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="Aring" horiz-adv-x="1306" unicode="Ã…" d="M909 380h-590l-199 -380h-201l791 1456h165l288 -1456h-185zM402 538h479l-121 679zM641 1721q2 91 66.5 154t153.5 63q82 0 139.5 -58t57.5 -143q-2 -89 -66.5 -151t-153.5 -62q-84 0 -141.5 57t-55.5 140zM737 1723q-4 -46 23 -77.5t70 -31.5q46 0 85.5 35.5t45.5 85.5 q6 46 -22 79t-70 33q-46 0 -86 -36.5t-46 -87.5z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1303" unicode="Ç" d="M1169 464q-42 -226 -204.5 -358t-389.5 -126q-135 3 -236 66.5t-157 183t-62 264.5q-4 82 7 160l17 120q47 328 230.5 517.5t446.5 184.5q205 -4 325 -132.5t127 -356.5h-187q-13 306 -240 330l-33 2q-189 5 -315.5 -140.5t-163.5 -397.5l-22 -151l-6 -88 q-6 -184 65.5 -292.5t212.5 -112.5q152 -5 251.5 73t151.5 251zM617 -9l-21 -55q129 -29 125 -163q-3 -102 -90 -159t-237 -60l4 108q166 6 182 107q12 71 -92 83l-46 6l46 133h129z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1139" unicode="È" d="M976 673h-612l-90 -516h712l-28 -157h-899l253 1456h889l-28 -158h-701l-81 -468h612zM866 1562h-143l-205 294h205z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1139" unicode="É" d="M976 673h-612l-90 -516h712l-28 -157h-899l253 1456h889l-28 -158h-701l-81 -468h612zM896 1856h230l-306 -294h-158z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1139" unicode="Ê" d="M976 673h-612l-90 -516h712l-28 -157h-899l253 1456h889l-28 -158h-701l-81 -468h612zM1067 1586v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1139" unicode="Ë" d="M976 673h-612l-90 -516h712l-28 -157h-899l253 1456h889l-28 -158h-701l-81 -468h612zM476 1691q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM893 1689q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5 t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="Igrave" horiz-adv-x="550" unicode="ÃŒ" d="M260 0h-187l253 1456h187zM537 1562h-143l-205 294h205z"/> +<glyph glyph-name="Iacute" horiz-adv-x="550" unicode="Ã" d="M260 0h-187l253 1456h187zM566 1856h230l-306 -294h-158z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="550" unicode="ÃŽ" d="M260 0h-187l253 1456h187zM738 1586v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="550" unicode="Ã" d="M260 0h-187l253 1456h187zM147 1691q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM564 1689q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1426" unicode="Ñ" d="M1146 0h-182l-520 1130l-196 -1130h-189l253 1456h182l521 -1135l197 1135h187zM1251 1815q-12 -111 -73 -178t-154 -67q-37 0 -67.5 15.5t-60.5 34.5t-61 34t-67 14q-85 -3 -116 -112l-122 7q12 110 74.5 180t155.5 68q27 0 50.5 -8.5t76.5 -41t77.5 -41.5t51.5 -8 q86 0 118 113z"/> +<glyph glyph-name="Ograve" horiz-adv-x="1376" unicode="Ã’" d="M593 -20q-139 3 -241.5 67t-161.5 188.5t-65 279.5q-6 121 27 299t114 321t197 229q157 116 358 112q213 -4 336 -147.5t132 -388.5q4 -105 -21.5 -267t-91 -301t-166.5 -233q-176 -164 -417 -159zM1104 894q6 197 -69 305.5t-223 112.5q-134 4 -239.5 -72t-173 -227.5 t-85.5 -383.5l-3 -65q-6 -196 70 -307t221 -115q189 -5 313.5 136.5t165.5 397.5q20 126 23 218zM949 1552h-143l-205 294h205z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1376" unicode="Ó" d="M593 -20q-139 3 -241.5 67t-161.5 188.5t-65 279.5q-6 121 27 299t114 321t197 229q157 116 358 112q213 -4 336 -147.5t132 -388.5q4 -105 -21.5 -267t-91 -301t-166.5 -233q-176 -164 -417 -159zM1104 894q6 197 -69 305.5t-223 112.5q-134 4 -239.5 -72t-173 -227.5 t-85.5 -383.5l-3 -65q-6 -196 70 -307t221 -115q189 -5 313.5 136.5t165.5 397.5q20 126 23 218zM979 1846h230l-306 -294h-158z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1376" unicode="Ô" d="M593 -20q-139 3 -241.5 67t-161.5 188.5t-65 279.5q-6 121 27 299t114 321t197 229q157 116 358 112q213 -4 336 -147.5t132 -388.5q4 -105 -21.5 -267t-91 -301t-166.5 -233q-176 -164 -417 -159zM1104 894q6 197 -69 305.5t-223 112.5q-134 4 -239.5 -72t-173 -227.5 t-85.5 -383.5l-3 -65q-6 -196 70 -307t221 -115q189 -5 313.5 136.5t165.5 397.5q20 126 23 218zM1150 1576v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1376" unicode="Õ" d="M593 -20q-139 3 -241.5 67t-161.5 188.5t-65 279.5q-6 121 27 299t114 321t197 229q157 116 358 112q213 -4 336 -147.5t132 -388.5q4 -105 -21.5 -267t-91 -301t-166.5 -233q-176 -164 -417 -159zM1104 894q6 197 -69 305.5t-223 112.5q-134 4 -239.5 -72t-173 -227.5 t-85.5 -383.5l-3 -65q-6 -196 70 -307t221 -115q189 -5 313.5 136.5t165.5 397.5q20 126 23 218zM1232 1817q-12 -111 -73 -178t-154 -67q-37 0 -67.5 15.5t-60.5 34.5t-61 34t-67 14q-85 -3 -116 -112l-122 7q12 110 74.5 180t155.5 68q27 0 50.5 -8.5t76.5 -41t77.5 -41.5 t51.5 -8q86 0 118 113z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1376" unicode="Ö" d="M593 -20q-139 3 -241.5 67t-161.5 188.5t-65 279.5q-6 121 27 299t114 321t197 229q157 116 358 112q213 -4 336 -147.5t132 -388.5q4 -105 -21.5 -267t-91 -301t-166.5 -233q-176 -164 -417 -159zM1104 894q6 197 -69 305.5t-223 112.5q-134 4 -239.5 -72t-173 -227.5 t-85.5 -383.5l-3 -65q-6 -196 70 -307t221 -115q189 -5 313.5 136.5t165.5 397.5q20 126 23 218zM559 1681q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM976 1679q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5 q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1298" unicode="Ù" d="M1312 1456l-168 -985q-34 -227 -196 -361.5t-391 -130.5q-143 3 -248.5 64.5t-155.5 173t-33 253.5l168 986h185l-167 -987q-17 -153 52 -240.5t209 -91.5q152 -6 256.5 82.5t131.5 248.5l168 988h189zM911 1550h-143l-205 294h205z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1298" unicode="Ú" d="M1312 1456l-168 -985q-34 -227 -196 -361.5t-391 -130.5q-143 3 -248.5 64.5t-155.5 173t-33 253.5l168 986h185l-167 -987q-17 -153 52 -240.5t209 -91.5q152 -6 256.5 82.5t131.5 248.5l168 988h189zM941 1844h230l-306 -294h-158z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1298" unicode="Û" d="M1312 1456l-168 -985q-34 -227 -196 -361.5t-391 -130.5q-143 3 -248.5 64.5t-155.5 173t-33 253.5l168 986h185l-167 -987q-17 -153 52 -240.5t209 -91.5q152 -6 256.5 82.5t131.5 248.5l168 988h189zM1112 1574v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z "/> +<glyph glyph-name="Udieresis" horiz-adv-x="1298" unicode="Ü" d="M1312 1456l-168 -985q-34 -227 -196 -361.5t-391 -130.5q-143 3 -248.5 64.5t-155.5 173t-33 253.5l168 986h185l-167 -987q-17 -153 52 -240.5t209 -91.5q152 -6 256.5 82.5t131.5 248.5l168 988h189zM521 1679q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5 q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM938 1677q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1203" unicode="Ã" d="M611 726l495 730h224l-653 -923l-93 -533h-187l96 554l-325 902h204zM892 1844h230l-306 -294h-158z"/> +<glyph glyph-name="agrave" horiz-adv-x="1091" unicode="à " d="M693 0q-7 29 -7 57l3 57q-149 -138 -316 -134q-143 2 -232.5 90.5t-81.5 221.5q10 172 150.5 268.5t369.5 96.5l189 -1l12 86q10 97 -37.5 153.5t-142.5 58.5q-93 2 -164.5 -45.5t-87.5 -125.5l-182 -1q9 95 74 168.5t167 114t211 38.5q169 -4 263 -102.5t79 -261.5 l-88 -536l-5 -77q-2 -55 12 -109l-2 -17h-184zM409 140q87 -2 164.5 41.5t133.5 120.5l39 223l-137 1q-171 0 -262 -54t-103 -153q-9 -76 35.5 -126.5t129.5 -52.5zM774 1240h-143l-205 294h205z"/> +<glyph glyph-name="aacute" horiz-adv-x="1091" unicode="á" d="M693 0q-7 29 -7 57l3 57q-149 -138 -316 -134q-143 2 -232.5 90.5t-81.5 221.5q10 172 150.5 268.5t369.5 96.5l189 -1l12 86q10 97 -37.5 153.5t-142.5 58.5q-93 2 -164.5 -45.5t-87.5 -125.5l-182 -1q9 95 74 168.5t167 114t211 38.5q169 -4 263 -102.5t79 -261.5 l-88 -536l-5 -77q-2 -55 12 -109l-2 -17h-184zM409 140q87 -2 164.5 41.5t133.5 120.5l39 223l-137 1q-171 0 -262 -54t-103 -153q-9 -76 35.5 -126.5t129.5 -52.5zM804 1534h230l-306 -294h-158z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1091" unicode="â" d="M693 0q-7 29 -7 57l3 57q-149 -138 -316 -134q-143 2 -232.5 90.5t-81.5 221.5q10 172 150.5 268.5t369.5 96.5l189 -1l12 86q10 97 -37.5 153.5t-142.5 58.5q-93 2 -164.5 -45.5t-87.5 -125.5l-182 -1q9 95 74 168.5t167 114t211 38.5q169 -4 263 -102.5t79 -261.5 l-88 -536l-5 -77q-2 -55 12 -109l-2 -17h-184zM409 140q87 -2 164.5 41.5t133.5 120.5l39 223l-137 1q-171 0 -262 -54t-103 -153q-9 -76 35.5 -126.5t129.5 -52.5zM975 1264v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="atilde" horiz-adv-x="1091" unicode="ã" d="M693 0q-7 29 -7 57l3 57q-149 -138 -316 -134q-143 2 -232.5 90.5t-81.5 221.5q10 172 150.5 268.5t369.5 96.5l189 -1l12 86q10 97 -37.5 153.5t-142.5 58.5q-93 2 -164.5 -45.5t-87.5 -125.5l-182 -1q9 95 74 168.5t167 114t211 38.5q169 -4 263 -102.5t79 -261.5 l-88 -536l-5 -77q-2 -55 12 -109l-2 -17h-184zM409 140q87 -2 164.5 41.5t133.5 120.5l39 223l-137 1q-171 0 -262 -54t-103 -153q-9 -76 35.5 -126.5t129.5 -52.5zM1057 1505q-12 -111 -73 -178t-154 -67q-37 0 -67.5 15.5t-60.5 34.5t-61 34t-67 14q-85 -3 -116 -112 l-122 7q12 110 74.5 180t155.5 68q27 0 50.5 -8.5t76.5 -41t77.5 -41.5t51.5 -8q86 0 118 113z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1091" unicode="ä" d="M693 0q-7 29 -7 57l3 57q-149 -138 -316 -134q-143 2 -232.5 90.5t-81.5 221.5q10 172 150.5 268.5t369.5 96.5l189 -1l12 86q10 97 -37.5 153.5t-142.5 58.5q-93 2 -164.5 -45.5t-87.5 -125.5l-182 -1q9 95 74 168.5t167 114t211 38.5q169 -4 263 -102.5t79 -261.5 l-88 -536l-5 -77q-2 -55 12 -109l-2 -17h-184zM409 140q87 -2 164.5 41.5t133.5 120.5l39 223l-137 1q-171 0 -262 -54t-103 -153q-9 -76 35.5 -126.5t129.5 -52.5zM384 1369q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28 t-29.5 76zM801 1367q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="aring" horiz-adv-x="1091" unicode="Ã¥" d="M693 0q-7 29 -7 57l3 57q-149 -138 -316 -134q-143 2 -232.5 90.5t-81.5 221.5q10 172 150.5 268.5t369.5 96.5l189 -1l12 86q10 97 -37.5 153.5t-142.5 58.5q-93 2 -164.5 -45.5t-87.5 -125.5l-182 -1q9 95 74 168.5t167 114t211 38.5q169 -4 263 -102.5t79 -261.5 l-88 -536l-5 -77q-2 -55 12 -109l-2 -17h-184zM409 140q87 -2 164.5 41.5t133.5 120.5l39 223l-137 1q-171 0 -262 -54t-103 -153q-9 -76 35.5 -126.5t129.5 -52.5zM499 1411q2 91 66.5 154t153.5 63q82 0 139.5 -58t57.5 -143q-2 -89 -66.5 -151t-153.5 -62 q-84 0 -141.5 57t-55.5 140zM595 1413q-4 -46 23 -77.5t70 -31.5q46 0 85.5 35.5t45.5 85.5q6 46 -22 79t-70 33q-46 0 -86 -36.5t-46 -87.5z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1050" unicode="ç" d="M488 130q97 -2 175 56.5t102 153.5l171 1q-15 -102 -81.5 -186t-167.5 -131t-207 -44q-135 2 -228.5 70.5t-137.5 191t-30 275.5l5 50q19 156 91 279t188 191.5t256 64.5q170 -4 272 -114t102 -279l-169 1q-2 106 -59 171.5t-154 69.5q-141 3 -234.5 -105t-116.5 -302 l-3 -26q-6 -64 -2 -132q7 -117 66 -185t162 -71zM485 -9l-21 -55q129 -29 125 -163q-3 -102 -90 -159t-237 -60l4 108q166 6 182 107q12 71 -92 83l-46 6l46 133h129z"/> +<glyph glyph-name="egrave" horiz-adv-x="1062" unicode="è" d="M499 -20q-202 4 -316 149t-96 371l5 43q17 161 95.5 294t191.5 200.5t244 64.5q167 -4 262 -111t104 -290q3 -65 -4 -130l-11 -83h-707q-18 -147 48.5 -250t198.5 -107q160 -4 296 144l104 -88q-68 -98 -175.5 -153.5t-239.5 -53.5zM614 951q-112 3 -195.5 -76 t-132.5 -235l526 -1l4 16q16 126 -40.5 209.5t-161.5 86.5zM747 1240h-143l-205 294h205z"/> +<glyph glyph-name="eacute" horiz-adv-x="1062" unicode="é" d="M499 -20q-202 4 -316 149t-96 371l5 43q17 161 95.5 294t191.5 200.5t244 64.5q167 -4 262 -111t104 -290q3 -65 -4 -130l-11 -83h-707q-18 -147 48.5 -250t198.5 -107q160 -4 296 144l104 -88q-68 -98 -175.5 -153.5t-239.5 -53.5zM614 951q-112 3 -195.5 -76 t-132.5 -235l526 -1l4 16q16 126 -40.5 209.5t-161.5 86.5zM777 1534h230l-306 -294h-158z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1062" unicode="ê" d="M499 -20q-202 4 -316 149t-96 371l5 43q17 161 95.5 294t191.5 200.5t244 64.5q167 -4 262 -111t104 -290q3 -65 -4 -130l-11 -83h-707q-18 -147 48.5 -250t198.5 -107q160 -4 296 144l104 -88q-68 -98 -175.5 -153.5t-239.5 -53.5zM614 951q-112 3 -195.5 -76 t-132.5 -235l526 -1l4 16q16 126 -40.5 209.5t-161.5 86.5zM948 1264v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1062" unicode="ë" d="M499 -20q-202 4 -316 149t-96 371l5 43q17 161 95.5 294t191.5 200.5t244 64.5q167 -4 262 -111t104 -290q3 -65 -4 -130l-11 -83h-707q-18 -147 48.5 -250t198.5 -107q160 -4 296 144l104 -88q-68 -98 -175.5 -153.5t-239.5 -53.5zM614 951q-112 3 -195.5 -76 t-132.5 -235l526 -1l4 16q16 126 -40.5 209.5t-161.5 86.5zM357 1369q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM774 1367q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28 t-29.5 76z"/> +<glyph glyph-name="igrave" horiz-adv-x="501" unicode="ì" d="M227 0h-181l188 1082h181zM455 1239h-143l-205 294h205z"/> +<glyph glyph-name="iacute" horiz-adv-x="501" unicode="Ã" d="M227 0h-181l188 1082h181zM484 1533h230l-306 -294h-158z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="501" unicode="î" d="M227 0h-181l188 1082h181zM656 1263v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="idieresis" horiz-adv-x="501" unicode="ï" d="M227 0h-181l188 1082h181zM65 1368q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM482 1366q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="ntilde" horiz-adv-x="1106" unicode="ñ" d="M390 1083l-26 -137q146 160 332 156q153 -4 226 -106t54 -287l-118 -709h-181l119 712q6 49 1 91q-17 140 -165 143q-163 3 -286 -174l-134 -772h-181l188 1082zM1048 1505q-12 -111 -73 -178t-154 -67q-37 0 -67.5 15.5t-60.5 34.5t-61 34t-67 14q-85 -3 -116 -112 l-122 7q12 110 74.5 180t155.5 68q27 0 50.5 -8.5t76.5 -41t77.5 -41.5t51.5 -8q86 0 118 113z"/> +<glyph glyph-name="ograve" horiz-adv-x="1143" unicode="ò" d="M632 1102q136 -2 233 -74t143.5 -198.5t31.5 -276.5l-2 -22q-19 -158 -94 -285.5t-194 -198.5t-261 -67q-135 2 -232.5 74t-142.5 196t-32 273q15 168 91 302t195.5 207.5t263.5 69.5zM264 522q-7 -63 0 -131q10 -118 70.5 -188t161.5 -73q90 -3 166 44.5t128 143.5 t67 213q8 92 3 155q-12 121 -73 191t-162 74q-140 3 -238 -110t-121 -296zM756 1240h-143l-205 294h205z"/> +<glyph glyph-name="oacute" horiz-adv-x="1143" unicode="ó" d="M632 1102q136 -2 233 -74t143.5 -198.5t31.5 -276.5l-2 -22q-19 -158 -94 -285.5t-194 -198.5t-261 -67q-135 2 -232.5 74t-142.5 196t-32 273q15 168 91 302t195.5 207.5t263.5 69.5zM264 522q-7 -63 0 -131q10 -118 70.5 -188t161.5 -73q90 -3 166 44.5t128 143.5 t67 213q8 92 3 155q-12 121 -73 191t-162 74q-140 3 -238 -110t-121 -296zM786 1534h230l-306 -294h-158z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1143" unicode="ô" d="M632 1102q136 -2 233 -74t143.5 -198.5t31.5 -276.5l-2 -22q-19 -158 -94 -285.5t-194 -198.5t-261 -67q-135 2 -232.5 74t-142.5 196t-32 273q15 168 91 302t195.5 207.5t263.5 69.5zM264 522q-7 -63 0 -131q10 -118 70.5 -188t161.5 -73q90 -3 166 44.5t128 143.5 t67 213q8 92 3 155q-12 121 -73 191t-162 74q-140 3 -238 -110t-121 -296zM957 1264v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="otilde" horiz-adv-x="1143" unicode="õ" d="M632 1102q136 -2 233 -74t143.5 -198.5t31.5 -276.5l-2 -22q-19 -158 -94 -285.5t-194 -198.5t-261 -67q-135 2 -232.5 74t-142.5 196t-32 273q15 168 91 302t195.5 207.5t263.5 69.5zM264 522q-7 -63 0 -131q10 -118 70.5 -188t161.5 -73q90 -3 166 44.5t128 143.5 t67 213q8 92 3 155q-12 121 -73 191t-162 74q-140 3 -238 -110t-121 -296zM1039 1505q-12 -111 -73 -178t-154 -67q-37 0 -67.5 15.5t-60.5 34.5t-61 34t-67 14q-85 -3 -116 -112l-122 7q12 110 74.5 180t155.5 68q27 0 50.5 -8.5t76.5 -41t77.5 -41.5t51.5 -8q86 0 118 113 z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1143" unicode="ö" d="M632 1102q136 -2 233 -74t143.5 -198.5t31.5 -276.5l-2 -22q-19 -158 -94 -285.5t-194 -198.5t-261 -67q-135 2 -232.5 74t-142.5 196t-32 273q15 168 91 302t195.5 207.5t263.5 69.5zM264 522q-7 -63 0 -131q10 -118 70.5 -188t161.5 -73q90 -3 166 44.5t128 143.5 t67 213q8 92 3 155q-12 121 -73 191t-162 74q-140 3 -238 -110t-121 -296zM366 1369q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM783 1367q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5 q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="ugrave" horiz-adv-x="1105" unicode="ù" d="M718 107q-127 -131 -323 -127q-155 4 -229.5 111t-55.5 292l116 699h181l-117 -702q-5 -44 -2 -86q5 -72 43 -113t106 -44q194 -6 300 157l136 788h181l-188 -1082h-171zM760 1240h-143l-205 294h205z"/> +<glyph glyph-name="uacute" horiz-adv-x="1105" unicode="ú" d="M718 107q-127 -131 -323 -127q-155 4 -229.5 111t-55.5 292l116 699h181l-117 -702q-5 -44 -2 -86q5 -72 43 -113t106 -44q194 -6 300 157l136 788h181l-188 -1082h-171zM790 1534h230l-306 -294h-158z"/> +<glyph glyph-name="ucircumflex" horiz-adv-x="1105" unicode="û" d="M718 107q-127 -131 -323 -127q-155 4 -229.5 111t-55.5 292l116 699h181l-117 -702q-5 -44 -2 -86q5 -72 43 -113t106 -44q194 -6 300 157l136 788h181l-188 -1082h-171zM961 1264v-14l-147 2l-113 169l-176 -168l-153 -3v16l278 270h106z"/> +<glyph glyph-name="udieresis" horiz-adv-x="1105" unicode="ü" d="M718 107q-127 -131 -323 -127q-155 4 -229.5 111t-55.5 292l116 699h181l-117 -702q-5 -44 -2 -86q5 -72 43 -113t106 -44q194 -6 300 157l136 788h181l-188 -1082h-171zM370 1369q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32 q-47 -1 -76.5 28t-29.5 76zM787 1367q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +<glyph glyph-name="yacute" horiz-adv-x="950" unicode="ý" d="M419 273l385 809h200l-642 -1262q-134 -263 -344 -260q-37 1 -109 18l16 150l47 -5q86 -4 148.5 38.5t110.5 137.5l65 124l-187 1059h189zM733 1534h230l-306 -294h-158z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="950" unicode="ÿ" d="M419 273l385 809h200l-642 -1262q-134 -263 -344 -260q-37 1 -109 18l16 150l47 -5q86 -4 148.5 38.5t110.5 137.5l65 124l-187 1059h189zM313 1369q1 46 30 76.5t76 32.5q47 1 77.5 -28.5t29.5 -76.5q0 -46 -30 -76t-77 -32q-47 -1 -76.5 28t-29.5 76zM730 1367 q1 46 30 77t76 33q48 1 78 -28.5t29 -77.5q0 -47 -30 -76.5t-77 -31.5q-46 -1 -76.5 28t-29.5 76z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..81a268aa8ee21b3677655b8306d09a1afb57ca92 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff new file mode 100644 index 0000000000000000000000000000000000000000..c8bbf8cd702fa3ac047c99f5bf260b2a2fe4499a Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2 b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..ce9f9d0f74fe25bbcc1083910523a5443aab3f9b Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Italic/RobotoDraft-Italic.woff2 differ diff --git a/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.eot b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.eot new file mode 100644 index 0000000000000000000000000000000000000000..830eb79742c11036d25e641be3cb7bcb86956822 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.svg b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.svg new file mode 100644 index 0000000000000000000000000000000000000000..bfc86135b4083d0e6d5da7b657c18678725c9855 --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.svg @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-Light" horiz-adv-x="1135"> +<font-face underline-position="-100" font-weight="300" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-104 -495 1823 1905" x-height="1082" underline-thickness="100" font-family="RobotoDraft Light" ascent="1536" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1100" unicode="fi" d="M228 0v984h-180v98h180v111q0 173 94 268.5t265 95.5q134 0 276 -59l-20 -103q-122 53 -248 53q-247 0 -247 -257v-109h253v-98h-253v-984h-120zM928 0h-120v1082h120v-1082z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1115" unicode="fl" d="M823 1422q-148 30 -246 30q-103 0 -159 -61.5t-56 -174.5v-134h258v-98h-258v-984h-120v984h-179v98h179v138q1 164 87 250.5t240 86.5q124 0 373 -61v-1496h-119v1422z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="uni0000" horiz-adv-x="0"/> +<glyph glyph-name="glyph2" horiz-adv-x="0"/> +<glyph glyph-name="uni000D" horiz-adv-x="498" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="498" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="462" unicode="!" d="M284 405h-111l-6 1051h124zM153 70q0 34 22 57.5t60 23.5t60.5 -23.5t22.5 -57.5q0 -33 -22.5 -55.5t-60.5 -22.5t-60 22.5t-22 55.5z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="588" unicode='"' d="M243 1396l-20 -313h-80l3 453h97v-140zM479 1396l-20 -313h-81l4 453h97v-140z"/> +<glyph glyph-name="numbersign" horiz-adv-x="1191" unicode="#" d="M753 410h-314l-77 -410h-99l77 410h-255v93h272l83 441h-279v96h297l79 416h99l-79 -416h315l79 416h100l-79 -416h229v-96h-247l-83 -441h255v-93h-273l-77 -410h-100zM456 503h315l83 441h-315z"/> +<glyph glyph-name="dollar" d="M901 359q0 111 -72 181.5t-254 133.5q-226 71 -317 168.5t-91 252.5q0 163 100 264.5t272 115.5v202h102v-202q176 -16 272.5 -132t96.5 -315h-119q0 157 -81.5 249.5t-222.5 92.5q-142 0 -221.5 -74.5t-79.5 -198.5q0 -120 73 -187.5t248.5 -127t255 -114t119 -129 t39.5 -178.5q0 -164 -102.5 -264.5t-281.5 -114.5v-190h-101v189q-201 13 -311 126.5t-110 310.5h120q0 -156 91 -244.5t254 -88.5q142 0 231.5 76t89.5 198z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1513" unicode="%" d="M109 1176q0 130 80.5 215.5t204.5 85.5t204.5 -85.5t80.5 -221.5v-71q0 -128 -79.5 -213.5t-203.5 -85.5q-123 0 -205 84t-82 222v70zM206 1099q0 -93 51.5 -153t138.5 -60q85 0 135.5 60.5t50.5 156.5v73q0 93 -52 153.5t-136 60.5q-83 0 -135.5 -60t-52.5 -160v-71z M842 357q0 130 80.5 215t203.5 85t204.5 -84.5t81.5 -222.5v-71q0 -130 -80.5 -215t-203.5 -85t-204.5 84.5t-81.5 220.5v73zM938 279q0 -94 51.5 -154t138.5 -60q86 0 136.5 60.5t50.5 158.5v73q0 96 -51.5 154.5t-137.5 58.5q-84 0 -136 -59t-52 -158v-74zM434 121l-75 48 l711 1138l75 -48z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1260" unicode="&" d="M404 794q-87 105 -126.5 187.5t-39.5 163.5q0 153 91 242t244 89q139 0 225 -80.5t86 -204.5q0 -144 -166 -283l-160 -124l400 -466q91 147 91 333h111q0 -248 -128 -419l199 -232h-144l-126 146q-79 -78 -182.5 -122t-218.5 -44q-208 0 -330 106.5t-122 284.5 q0 106 62.5 200.5t219.5 212.5zM560 81q91 0 176.5 38.5t153.5 109.5l-407 472l-14 15l-46 -35q-196 -160 -196 -310q0 -131 90 -210.5t243 -79.5zM358 1149q0 -122 135 -288l131 100q64 46 105 101t41 129q0 78 -54 130.5t-144 52.5q-98 0 -156 -63t-58 -162z"/> +<glyph glyph-name="quotesingle" horiz-adv-x="348" unicode="'" d="M226 1395l-17 -305h-90q5 296 5 446h102v-141z"/> +<glyph glyph-name="parenleft" horiz-adv-x="653" unicode="(" d="M140 588q0 218 56 423.5t164 376t232 244.5l29 -81q-66 -47 -131 -137t-116 -214t-82.5 -278.5t-31.5 -350.5q0 -209 47.5 -402t130.5 -340.5t183 -221.5l-29 -77q-127 76 -235 245.5t-162.5 373t-54.5 439.5z"/> +<glyph glyph-name="parenright" horiz-adv-x="667" unicode=")" d="M514 573q0 -220 -54.5 -423.5t-161.5 -372.5t-236 -247l-29 77q98 70 181.5 217t131.5 342.5t48 424.5q0 207 -48 399.5t-132.5 344t-180.5 220.5l29 77q126 -77 233 -246t163 -375t56 -438z"/> +<glyph glyph-name="asterisk" horiz-adv-x="869" unicode="*" d="M361 1000l-332 108l32 101l332 -123l-4 370h104l-8 -373l324 127l33 -101l-333 -115l223 -294l-85 -63l-214 305l-204 -303l-85 61z"/> +<glyph glyph-name="plus" horiz-adv-x="1156" unicode="+" d="M630 740h443v-112h-443v-482h-121v482h-434v112h434v466h121v-466z"/> +<glyph glyph-name="comma" horiz-adv-x="392" unicode="," d="M131 -272l-71 52q91 122 94 253v155h117v-125q0 -208 -140 -335z"/> +<glyph glyph-name="hyphen" horiz-adv-x="586" unicode="-" d="M528 592h-479v101h479v-101z"/> +<glyph glyph-name="period" horiz-adv-x="489" unicode="." d="M145 72q0 35 22.5 59.5t62.5 24.5t63 -24.5t23 -59.5t-23 -57.5t-63 -22.5t-62.5 22.5t-22.5 57.5z"/> +<glyph glyph-name="slash" horiz-adv-x="813" unicode="/" d="M139 -125h-109l608 1581h108z"/> +<glyph glyph-name="zero" d="M1015 607q0 -308 -113 -467.5t-333 -159.5q-216 0 -331 156.5t-118 455.5v261q0 307 114 465t333 158q216 0 330 -152.5t118 -449.5v-267zM895 868q0 250 -81.5 378t-246.5 128q-162 0 -244 -125t-84 -369v-286q0 -249 84.5 -381t245.5 -132q160 0 242.5 129t83.5 378 v280z" unicode="0"/> +<glyph glyph-name="one" d="M694 0h-120v1312l-396 -147v112l496 184h20v-1461z" unicode="1"/> +<glyph glyph-name="two" d="M1049 0h-912v92l499 566q124 143 172 236t48 181q0 138 -81 218.5t-223 80.5q-147 0 -237.5 -94t-90.5 -244h-119q0 123 55.5 224t158 158.5t233.5 57.5q200 0 312.5 -105t112.5 -286q0 -102 -63.5 -223t-223.5 -302l-406 -459h765v-101z" unicode="2"/> +<glyph glyph-name="three" d="M403 793h124q103 0 180 36.5t117.5 100t40.5 146.5q0 140 -79 219t-227 79q-140 0 -229.5 -82.5t-89.5 -217.5h-120q0 113 57 206.5t158 144.5t224 51q198 0 312 -108t114 -296q0 -105 -66.5 -193.5t-182.5 -132.5q136 -38 206 -130.5t70 -220.5q0 -187 -122 -301 t-326 -114q-130 0 -238.5 52t-168 145.5t-59.5 217.5h120q0 -139 97 -226.5t249 -87.5q155 0 241.5 79.5t86.5 230.5q0 146 -93.5 223t-275.5 77h-120v102z" unicode="3"/> +<glyph glyph-name="four" d="M872 469h227v-101h-227v-368h-120v368h-685v68l674 1020h131v-987zM214 469h538v832l-53 -92z" unicode="4"/> +<glyph glyph-name="five" d="M218 746l71 710h728v-111h-625l-51 -492q117 80 274 80q197 0 314 -128t117 -341q0 -230 -114 -357t-321 -127q-190 0 -308 106t-135 297h115q17 -149 101 -225.5t227 -76.5q156 0 235.5 99t79.5 282q0 160 -89 261t-243 101q-85 0 -148 -21.5t-133 -83.5z" unicode="5"/> +<glyph glyph-name="six" d="M843 1467v-105h-14q-261 0 -411 -153.5t-166 -426.5q60 83 153 128.5t208 45.5q192 0 305.5 -132.5t113.5 -346.5q0 -142 -53 -256t-152 -177.5t-226 -63.5q-209 0 -340 151.5t-131 391.5v120q0 391 178 605.5t505 218.5h30zM594 853q-114 0 -212.5 -67.5t-131.5 -171.5 v-102q0 -190 97.5 -310t253.5 -120q140 0 226.5 111t86.5 280q0 172 -86.5 276t-233.5 104z" unicode="6"/> +<glyph glyph-name="seven" d="M1034 1387l-622 -1387h-125l618 1354h-828v102h957v-69z" unicode="7"/> +<glyph glyph-name="eight" d="M995 1081q0 -113 -66 -202.5t-174 -131.5q126 -43 202 -139t76 -222q0 -187 -127 -296.5t-336 -109.5q-211 0 -337.5 109t-126.5 297q0 124 73 221t200 140q-108 42 -172 131.5t-64 202.5q0 181 116.5 288t308.5 107t309.5 -108t117.5 -287zM913 385q0 136 -97 223.5 t-248 87.5t-247 -86t-96 -225t93 -221.5t252 -82.5q155 0 249 82t94 222zM875 1082q0 125 -86.5 208.5t-220.5 83.5q-136 0 -220.5 -80.5t-84.5 -211.5q0 -128 84.5 -206t221.5 -78q135 0 220.5 78.5t85.5 205.5z" unicode="8"/> +<glyph glyph-name="nine" d="M884 674q-64 -94 -159 -145.5t-206 -51.5q-124 0 -219 64t-147 177t-52 247q0 144 55.5 262t155 183.5t229.5 65.5q219 0 341 -153.5t122 -435.5v-108q0 -394 -168 -592t-513 -198h-22l1 104h42q261 4 397 148t143 433zM534 580q120 0 215.5 71.5t135.5 185.5v69 q0 222 -92.5 344.5t-249.5 122.5q-142 0 -233 -114.5t-91 -288.5q0 -167 87.5 -278.5t227.5 -111.5z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="430" unicode=":" d="M127 72q0 35 22.5 59.5t62.5 24.5t63 -24.5t23 -59.5t-23 -57.5t-63 -22.5t-62.5 22.5t-22.5 57.5zM129 995q0 35 22.5 59.5t62.5 24.5t63 -24.5t23 -59.5t-23 -57.5t-63 -22.5t-62.5 22.5t-22.5 57.5z"/> +<glyph glyph-name="semicolon" horiz-adv-x="399" unicode=";" d="M118 995q0 35 22.5 59.5t62.5 24.5t63 -24.5t23 -59.5t-23 -57.5t-63 -22.5t-62.5 22.5t-22.5 57.5zM131 -272l-71 52q91 122 94 253v155h117v-125q0 -208 -140 -335z"/> +<glyph glyph-name="less" horiz-adv-x="1047" unicode="<" d="M208 655l696 -300v-126l-827 379v97l827 378v-126z"/> +<glyph glyph-name="equal" horiz-adv-x="1133" unicode="=" d="M983 829h-834v106h834v-106zM983 418h-834v106h834v-106z"/> +<glyph glyph-name="greater" horiz-adv-x="1061" unicode=">" d="M835 659l-711 303v123l845 -378v-97l-845 -379v124z"/> +<glyph glyph-name="question" horiz-adv-x="930" unicode="?" d="M376 404q2 118 32 190t129 169.5t127.5 138t44 89t15.5 110.5q0 125 -66.5 196.5t-185.5 71.5q-120 0 -193.5 -68.5t-75.5 -185.5h-119q2 164 111 262.5t277 98.5q172 0 271.5 -100.5t99.5 -272.5q0 -108 -49 -202.5t-186 -220.5q-113 -95 -113 -276h-119zM360 70 q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -55.5t-60.5 -22.5q-39 0 -60.5 22.5t-21.5 55.5z"/> +<glyph glyph-name="at" horiz-adv-x="1870" unicode="@" d="M1754 513q-5 -147 -54 -272.5t-135.5 -193t-200.5 -67.5q-97 0 -158 51t-81 143q-108 -194 -298 -194q-140 0 -209 121t-51 326q15 163 74.5 290.5t155 199t204.5 71.5q77 0 135 -21.5t135 -86.5l-51 -570q-10 -116 29.5 -180t126.5 -64q123 0 199.5 120.5t85.5 326.5 q19 405 -154 609.5t-524 204.5q-211 0 -380.5 -105.5t-267.5 -298.5t-110 -445t66.5 -443.5t237 -294.5t377.5 -103q92 0 181 22t149 57l31 -80q-57 -38 -159 -63.5t-206 -25.5q-250 0 -430 112.5t-269.5 324t-77.5 494.5q12 278 122.5 492.5t302.5 332t437 117.5 q255 0 432 -106.5t262 -311.5t73 -489zM673 286q11 -100 56 -154.5t119 -54.5q185 0 273 255l45 516q-67 49 -158 49q-111 0 -192.5 -88.5t-119.5 -244t-23 -278.5z"/> +<glyph glyph-name="A" horiz-adv-x="1279" unicode="A" d="M970 408h-661l-150 -408h-129l551 1456h117l551 -1456h-128zM347 513h584l-292 793z"/> +<glyph glyph-name="B" horiz-adv-x="1255" unicode="B" d="M184 0v1456h430q234 0 355 -96.5t121 -284.5q0 -113 -61.5 -196.5t-168.5 -119.5q127 -28 204.5 -125t77.5 -224q0 -193 -124.5 -301.5t-346.5 -108.5h-487zM307 700v-596h369q158 0 250.5 80.5t92.5 223.5q0 135 -88.5 213.5t-244.5 78.5h-379zM307 803h336 q154 3 238.5 72.5t84.5 202.5q0 140 -87.5 206.5t-264.5 66.5h-307v-548z"/> +<glyph glyph-name="C" horiz-adv-x="1330" unicode="C" d="M1215 454q-25 -230 -164.5 -352t-371.5 -122q-162 0 -286.5 81t-192.5 229.5t-69 339.5v189q0 194 68 344t195.5 231.5t293.5 81.5q234 0 369.5 -126.5t157.5 -349.5h-124q-46 371 -403 371q-198 0 -315.5 -148t-117.5 -409v-178q0 -252 114.5 -402t309.5 -150 q193 0 291 92.5t121 277.5h124z"/> +<glyph glyph-name="D" horiz-adv-x="1341" unicode="D" d="M184 0v1456h407q179 0 321 -81.5t221.5 -233.5t79.5 -346v-134q0 -195 -79 -346t-222.5 -233t-329.5 -82h-398zM307 1351v-1247h276q230 0 369 152.5t139 412.5v128q0 251 -137 402t-361 152h-286z"/> +<glyph glyph-name="E" horiz-adv-x="1165" unicode="E" d="M988 698h-681v-594h783v-104h-906v1456h901v-105h-778v-549h681v-104z"/> +<glyph glyph-name="F" horiz-adv-x="1152" unicode="F" d="M986 680h-679v-680h-123v1456h902v-105h-779v-566h679v-105z"/> +<glyph glyph-name="G" horiz-adv-x="1400" unicode="G" d="M1235 173q-64 -91 -200.5 -142t-305.5 -51q-171 0 -304 82t-206 232t-74 344v184q0 303 153 478.5t411 175.5q225 0 362 -114.5t163 -315.5h-123q-27 160 -130.5 242.5t-270.5 82.5q-204 0 -323 -145t-119 -409v-172q0 -166 56.5 -293.5t162 -197.5t242.5 -70 q159 0 273 50q74 33 110 77v376h-391v104h514v-518z"/> +<glyph glyph-name="H" horiz-adv-x="1449" unicode="H" d="M1263 0h-124v698h-832v-698h-123v1456h123v-654h832v654h124v-1456z"/> +<glyph glyph-name="I" horiz-adv-x="545" unicode="I" d="M334 0h-123v1456h123v-1456z"/> +<glyph glyph-name="J" horiz-adv-x="1127" unicode="J" d="M827 1456h124v-1023q0 -207 -119.5 -330t-320.5 -123q-212 0 -326 111t-114 310h123q0 -158 83 -237.5t234 -79.5q139 0 226.5 92t89.5 250v1030z"/> +<glyph glyph-name="K" horiz-adv-x="1292" unicode="K" d="M512 723l-205 -202v-521h-123v1456h123v-785l746 785h155l-610 -648l657 -808h-150z"/> +<glyph glyph-name="L" horiz-adv-x="1079" unicode="L" d="M308 104h719v-104h-843v1456h124v-1352z"/> +<glyph glyph-name="M" horiz-adv-x="1772" unicode="M" d="M347 1456l537 -1285l539 1285h164v-1456h-123v634l10 650l-542 -1284h-95l-540 1279l10 -641v-638h-123v1456h163z"/> +<glyph glyph-name="N" horiz-adv-x="1454" unicode="N" d="M1268 0h-123l-837 1246v-1246h-124v1456h124l838 -1247v1247h122v-1456z"/> +<glyph glyph-name="O" horiz-adv-x="1386" unicode="O" d="M1260 649q0 -201 -69.5 -353t-198.5 -234t-298 -82q-255 0 -412 182.5t-157 492.5v150q0 199 70.5 352.5t199.5 236t297 82.5t296.5 -81t198.5 -229t73 -343v-174zM1137 807q0 263 -119 412t-326 149q-203 0 -323.5 -149.5t-120.5 -417.5v-152q0 -259 120 -410.5 t326 -151.5q209 0 326 149.5t117 416.5v154z"/> +<glyph glyph-name="P" horiz-adv-x="1261" unicode="P" d="M307 593v-593h-123v1456h496q227 0 358.5 -116t131.5 -319q0 -205 -126.5 -316.5t-366.5 -111.5h-370zM307 697h373q179 0 273 85t94 237q0 151 -93.5 240.5t-265.5 91.5h-381v-654z"/> +<glyph glyph-name="Q" horiz-adv-x="1386" unicode="Q" d="M1256 649q0 -208 -73.5 -362.5t-209.5 -233.5l265 -231l-85 -76l-297 257q-82 -23 -167 -23q-166 0 -295.5 82t-200.5 232.5t-72 347.5v163q0 199 70.5 352.5t199.5 236t296 82.5q170 0 299 -82t199.5 -235t70.5 -353v-157zM1133 807q0 263 -119 412t-327 149 q-202 0 -322.5 -149.5t-120.5 -417.5v-152q0 -259 119.5 -410.5t325.5 -151.5q208 0 326 149t118 416v155z"/> +<glyph glyph-name="R" horiz-adv-x="1300" unicode="R" d="M728 606h-423v-606h-124v1456h473q233 0 364 -113t131 -316q0 -140 -82 -247t-220 -148l364 -619v-13h-131zM305 711h377q155 0 249 88t94 228q0 154 -98 239t-275 85h-347v-640z"/> +<glyph glyph-name="S" horiz-adv-x="1213" unicode="S" d="M1008 358q0 121 -85 191.5t-311 134t-330 138.5q-148 106 -148 278q0 167 137.5 271.5t351.5 104.5q145 0 259.5 -56t177.5 -156t63 -223h-124q0 149 -102 239.5t-274 90.5q-167 0 -266 -74.5t-99 -194.5q0 -111 89 -181t285 -123.5t297 -111t152 -137.5t51 -189 q0 -172 -137.5 -276t-362.5 -104q-154 0 -282.5 55t-195 154t-66.5 227h123q0 -154 115 -243t306 -89q170 0 273 75t103 199z"/> +<glyph glyph-name="T" horiz-adv-x="1223" unicode="T" d="M1172 1351h-499v-1351h-123v1351h-498v105h1120v-105z"/> +<glyph glyph-name="U" horiz-adv-x="1346" unicode="U" d="M1187 1456v-994q-1 -147 -65 -256t-180.5 -167.5t-267.5 -58.5q-230 0 -368.5 125.5t-143.5 347.5v1003h122v-985q0 -184 105 -285.5t285 -101.5t284.5 102t104.5 284v986h124z"/> +<glyph glyph-name="V" horiz-adv-x="1263" unicode="V" d="M623 180l8 -31l9 31l458 1276h135l-542 -1456h-118l-542 1456h134z"/> +<glyph glyph-name="W" horiz-adv-x="1836" unicode="W" d="M453 393l45 -226l55 216l316 1073h111l312 -1073l54 -218l48 228l263 1063h126l-373 -1456h-118l-330 1139l-37 144l-36 -144l-338 -1139h-118l-372 1456h126z"/> +<glyph glyph-name="X" horiz-adv-x="1253" unicode="X" d="M627 840l410 616h147l-482 -718l497 -738h-148l-424 636l-426 -636h-146l498 738l-483 718h147z"/> +<glyph glyph-name="Y" horiz-adv-x="1226" unicode="Y" d="M611 662l445 794h142l-526 -908v-548h-123v548l-525 908h146z"/> +<glyph glyph-name="Z" horiz-adv-x="1225" unicode="Z" d="M239 104h899v-104h-1048v93l864 1258h-838v105h990v-88z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="491" unicode="[" d="M493 1562h-210v-1772h210v-102h-330v1976h330v-102z"/> +<glyph glyph-name="backslash" horiz-adv-x="807" unicode="\" d="M48 1456h117l608 -1581h-117z"/> +<glyph glyph-name="bracketright" horiz-adv-x="491" unicode="]" d="M0 1664h331v-1976h-331v102h211v1772h-211v102z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="852" unicode="^" d="M421 1298l-228 -569h-116l299 727h90l298 -727h-116z"/> +<glyph glyph-name="underscore" horiz-adv-x="884" unicode="_" d="M882 -101h-881v101h881v-101z"/> +<glyph glyph-name="grave" horiz-adv-x="585" unicode="`" d="M438 1245h-109l-226 279h144z"/> +<glyph glyph-name="a" horiz-adv-x="1097" unicode="a" d="M839 0q-18 51 -23 151q-63 -82 -160.5 -126.5t-206.5 -44.5q-156 0 -252.5 87t-96.5 220q0 158 131.5 250t366.5 92h217v123q0 116 -71.5 182.5t-208.5 66.5q-125 0 -207 -64t-82 -154l-120 1q0 129 120 223.5t295 94.5q181 0 285.5 -90.5t107.5 -252.5v-512 q0 -157 33 -235v-12h-128zM463 86q120 0 214.5 58t137.5 155v238h-214q-179 -2 -280 -65.5t-101 -174.5q0 -91 67.5 -151t175.5 -60z"/> +<glyph glyph-name="b" d="M1027 530q0 -253 -112 -401.5t-301 -148.5q-226 0 -342 168l-5 -148h-112v1536h119v-611q114 177 338 177q192 0 303.5 -146.5t111.5 -407.5v-18zM907 551q0 214 -83 330.5t-234 116.5q-115 0 -195 -56.5t-121 -165.5v-488q90 -204 318 -204q148 0 231.5 117t83.5 350z " unicode="b"/> +<glyph glyph-name="c" horiz-adv-x="1055" unicode="c" d="M556 81q125 0 209.5 70.5t91.5 182.5h115q-5 -99 -62 -180.5t-151.5 -127.5t-202.5 -46q-213 0 -337.5 148t-124.5 398v36q0 160 56 283t160.5 190t244.5 67q178 0 293.5 -106t123.5 -279h-115q-8 127 -91.5 205t-210.5 78q-162 0 -251.5 -117t-89.5 -328v-35 q0 -207 89.5 -323t252.5 -116z"/> +<glyph glyph-name="d" horiz-adv-x="1138" unicode="d" d="M108 551q0 252 112.5 401.5t305.5 149.5q219 0 334 -173v607h119v-1536h-112l-5 144q-115 -164 -338 -164q-187 0 -301.5 150.5t-114.5 406.5v14zM229 530q0 -207 83 -326.5t234 -119.5q221 0 314 195v508q-93 211 -312 211q-151 0 -235 -118.5t-84 -349.5z"/> +<glyph glyph-name="e" horiz-adv-x="1058" unicode="e" d="M575 -20q-138 0 -249.5 68t-173.5 189.5t-62 272.5v43q0 156 60.5 281t168.5 196.5t234 71.5q197 0 312.5 -134.5t115.5 -367.5v-67h-772v-23q0 -184 105.5 -306.5t265.5 -122.5q96 0 169.5 35t133.5 112l75 -57q-132 -191 -383 -191zM553 1000q-135 0 -227.5 -99 t-112.5 -266h649v13q-5 156 -89 254t-220 98z"/> +<glyph glyph-name="f" horiz-adv-x="678" unicode="f" d="M242 0v984h-179v98h179v131q0 166 84.5 255t235.5 89q68 0 127 -17l-9 -100q-50 12 -109 12q-99 0 -154 -61.5t-55 -174.5v-134h258v-98h-258v-984h-120z"/> +<glyph glyph-name="g" horiz-adv-x="1136" unicode="g" d="M108 551q0 254 112.5 402.5t305.5 148.5q221 0 336 -176l6 156h112v-1060q0 -209 -117 -331t-317 -122q-113 0 -215.5 50.5t-161.5 134.5l67 72q127 -156 302 -156q150 0 234 88.5t87 245.5v136q-115 -160 -335 -160q-188 0 -302 150t-114 405v16zM229 530 q0 -207 83 -326.5t234 -119.5q221 0 313 198v503q-42 104 -121 158.5t-190 54.5q-151 0 -235 -118.5t-84 -349.5z"/> +<glyph glyph-name="h" horiz-adv-x="1124" unicode="h" d="M275 899q59 97 151 150t201 53q174 0 259 -98t86 -294v-710h-119v711q-1 145 -61.5 216t-193.5 71q-111 0 -196.5 -69.5t-126.5 -187.5v-741h-119v1536h119v-637z"/> +<glyph glyph-name="i" horiz-adv-x="459" unicode="i" d="M290 0h-120v1082h120v-1082zM149 1395q0 34 22 57.5t60 23.5t60.5 -23.5t22.5 -57.5t-22.5 -57t-60.5 -23t-60 23t-22 57z"/> +<glyph glyph-name="j" horiz-adv-x="467" unicode="j" d="M285 1082v-1211q0 -150 -72 -229t-212 -79q-54 0 -105 19l2 99q44 -13 90 -13q178 0 178 205v1209h119zM226 1476q39 0 61 -23.5t22 -57.5t-22 -57t-61 -23q-38 0 -59.5 23t-21.5 57t21.5 57.5t59.5 23.5z"/> +<glyph glyph-name="k" horiz-adv-x="1003" unicode="k" d="M413 545l-137 -132v-413h-120v1536h120v-983l113 122l414 407h151l-459 -456l499 -626h-143z"/> +<glyph glyph-name="l" horiz-adv-x="459" unicode="l" d="M290 0h-120v1536h120v-1536z"/> +<glyph glyph-name="m" horiz-adv-x="1815" unicode="m" d="M265 1082l4 -176q60 98 150 147t200 49q256 0 325 -210q58 101 155 155.5t214 54.5q348 0 355 -380v-722h-120v713q-1 145 -62.5 215t-200.5 70q-129 -2 -218 -83.5t-99 -198.5v-716h-120v722q-1 139 -65.5 207.5t-198.5 68.5q-113 0 -194 -64.5t-120 -191.5v-742h-120 v1082h115z"/> +<glyph glyph-name="n" horiz-adv-x="1125" unicode="n" d="M270 1082l4 -185q61 100 152 152.5t201 52.5q174 0 259 -98t86 -294v-710h-119v711q-1 145 -61.5 216t-193.5 71q-111 0 -196.5 -69.5t-126.5 -187.5v-741h-119v1082h114z"/> +<glyph glyph-name="o" horiz-adv-x="1147" unicode="o" d="M90 557q0 156 60.5 281t171 194.5t250.5 69.5q216 0 350 -151.5t134 -401.5v-25q0 -157 -60.5 -282.5t-170.5 -193.5t-251 -68q-215 0 -349.5 151.5t-134.5 401.5v24zM210 524q0 -194 100.5 -318.5t263.5 -124.5q162 0 262.5 124.5t100.5 328.5v23q0 124 -46 227 t-129 159.5t-190 56.5q-160 0 -261 -125.5t-101 -328.5v-22z"/> +<glyph glyph-name="p" d="M1026 530q0 -253 -112 -401.5t-300 -148.5q-222 0 -340 156v-552h-119v1498h111l6 -153q117 173 339 173q194 0 304.5 -147t110.5 -408v-17zM906 551q0 207 -85 327t-237 120q-110 0 -189 -53t-121 -154v-519q43 -93 123 -142t189 -49q151 0 235.5 120.5t84.5 349.5z" unicode="p"/> +<glyph glyph-name="q" horiz-adv-x="1142" unicode="q" d="M108 551q0 254 112.5 402.5t307.5 148.5q219 0 333 -167l6 147h112v-1498h-120v550q-118 -154 -333 -154q-190 0 -304 150t-114 405v16zM229 530q0 -210 84.5 -329.5t234.5 -119.5q215 0 311 187v530q-45 97 -124.5 149.5t-184.5 52.5q-151 0 -236 -119.5t-85 -350.5z "/> +<glyph glyph-name="r" horiz-adv-x="689" unicode="r" d="M656 980q-38 7 -81 7q-112 0 -189.5 -62.5t-110.5 -181.5v-743h-119v1082h117l2 -172q95 192 305 192q50 0 79 -13z"/> +<glyph glyph-name="s" horiz-adv-x="1037" unicode="s" d="M804 275q0 89 -71.5 143t-215.5 84.5t-223.5 70t-118 96.5t-38.5 138q0 128 107 211.5t274 83.5q181 0 290.5 -89.5t109.5 -233.5h-120q0 95 -79.5 158t-200.5 63q-118 0 -189.5 -52.5t-71.5 -136.5q0 -81 59.5 -125.5t217 -81.5t236 -79t116.5 -101t38 -143 q0 -137 -110.5 -219t-288.5 -82q-189 0 -306.5 91.5t-117.5 231.5h120q7 -105 88.5 -163.5t215.5 -58.5q125 0 202 55t77 139z"/> +<glyph glyph-name="t" horiz-adv-x="658" unicode="t" d="M342 1359v-277h224v-98h-224v-721q0 -90 32.5 -134t108.5 -44q30 0 97 10l5 -98q-47 -17 -128 -17q-123 0 -179 71.5t-56 210.5v722h-199v98h199v277h120z"/> +<glyph glyph-name="u" horiz-adv-x="1125" unicode="u" d="M852 137q-108 -157 -345 -157q-173 0 -263 100.5t-92 297.5v704h119v-689q0 -309 250 -309q260 0 329 215v783h120v-1082h-116z"/> +<glyph glyph-name="v" horiz-adv-x="985" unicode="v" d="M493 165l329 917h123l-404 -1082h-97l-406 1082h123z"/> +<glyph glyph-name="w" horiz-adv-x="1544" unicode="w" d="M415 249l18 -93l24 98l260 828h102l257 -821l28 -114l23 105l222 830h124l-315 -1082h-102l-278 858l-13 59l-13 -60l-273 -857h-102l-314 1082h123z"/> +<glyph glyph-name="x" horiz-adv-x="996" unicode="x" d="M496 643l292 439h142l-367 -531l383 -551h-141l-308 458l-308 -458h-141l382 551l-367 531h141z"/> +<glyph glyph-name="y" horiz-adv-x="973" unicode="y" d="M499 172l316 910h129l-462 -1266l-24 -56q-89 -197 -275 -197q-43 0 -92 14l-1 99l62 -6q88 0 142.5 43.5t92.5 149.5l53 146l-408 1073h131z"/> +<glyph glyph-name="z" horiz-adv-x="996" unicode="z" d="M235 101h703v-101h-851v88l656 891h-636v103h787v-89z"/> +<glyph glyph-name="braceleft" horiz-adv-x="676" unicode="{" d="M637 -404q-168 50 -253 163t-85 300v221q0 263 -231 263v104q231 0 231 261v229q1 183 85 296t253 164l26 -79q-244 -78 -244 -391v-213q0 -246 -184 -319q184 -77 184 -318v-228q4 -292 247 -373z"/> +<glyph glyph-name="bar" horiz-adv-x="452" unicode="|" d="M279 -270h-101v1726h101v-1726z"/> +<glyph glyph-name="braceright" horiz-adv-x="676" unicode="}" d="M9 -324q243 81 247 373v224q0 253 193 321q-193 68 -193 319v213q0 316 -244 392l26 79q171 -51 254.5 -165.5t83.5 -300.5v-223q0 -261 231 -261v-104q-231 0 -231 -263v-221q0 -187 -85 -300t-253 -163z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1402" unicode="~" d="M1254 764q0 -149 -83.5 -245t-212.5 -96q-72 0 -134.5 27.5t-153.5 108t-135 101t-94 20.5q-89 0 -138.5 -59t-49.5 -171l-108 -1q0 149 81 243.5t215 94.5q74 0 140.5 -31t158.5 -113q67 -63 115 -88.5t103 -25.5q88 0 140 63t52 172h104z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="452" unicode="¡" d="M174 690h111l7 -1049h-124zM305 1022q0 -34 -22 -57t-60 -23t-60.5 23t-22.5 57t22.5 57t60.5 23t60 -23t22 -57z"/> +<glyph glyph-name="cent" horiz-adv-x="1115" unicode="¢" d="M581 81q123 0 207.5 69.5t93.5 183.5h115q-8 -139 -110.5 -237t-250.5 -114v-228h-120v229q-185 23 -291 166t-106 376v36q0 222 105.5 367.5t291.5 168.5v220h120v-219q155 -16 255 -121t106 -261h-115q-8 127 -91.5 205t-210.5 78q-162 0 -251.5 -117t-89.5 -328v-35 q0 -207 89.5 -323t252.5 -116z"/> +<glyph glyph-name="sterling" horiz-adv-x="1170" unicode="£" d="M404 645l9 -277q2 -174 -64 -264h745v-104h-997v104h98q51 13 77 107q20 74 18 156l-9 278h-188v104h184l-9 290q0 200 110.5 318.5t295.5 118.5q182 0 287.5 -105.5t105.5 -282.5h-123q0 135 -75 209t-204 74q-125 0 -199 -88.5t-74 -243.5l9 -290h344v-104h-341z"/> +<glyph glyph-name="currency" horiz-adv-x="1481" unicode="¤" d="M1131 133q-78 -72 -178 -112.5t-213 -40.5q-226 0 -391 152l-155 -158l-85 86l159 161q-124 168 -124 387q0 227 133 398l-168 171l85 87l167 -170q165 140 379 140t379 -142l170 173l86 -88l-171 -175q130 -170 130 -394q0 -215 -122 -384l163 -164l-86 -87zM257 608 q0 -138 64.5 -258t177.5 -189.5t241 -69.5q129 0 241 70t176 189.5t64 257.5q0 139 -65.5 258.5t-176.5 187.5t-239 68t-240 -68t-177.5 -187.5t-65.5 -258.5z"/> +<glyph glyph-name="yen" horiz-adv-x="1223" unicode="Â¥" d="M607 734l421 722h143l-453 -751h367v-89h-418v-204h418v-88h-418v-324h-123v324h-414v88h414v204h-414v89h366l-452 751h143z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="444" unicode="¦" d="M159 -270v771h120v-771h-120zM279 698h-120v758h120v-758z"/> +<glyph glyph-name="section" horiz-adv-x="1239" unicode="§" d="M1119 431q0 -100 -61.5 -169.5t-170.5 -102.5q91 -48 139.5 -118t48.5 -180q0 -164 -126 -260t-343 -96q-109 0 -205.5 28t-164.5 85q-134 114 -134 318l120 2q0 -156 103.5 -243.5t280.5 -87.5q160 0 254 69.5t94 182.5q0 77 -34.5 124t-114.5 86t-257 87t-264 99.5 t-131.5 123t-44.5 172.5q0 100 58.5 170.5t164.5 103.5q-86 47 -132 117t-46 178q0 161 129 258.5t342 97.5q224 0 348.5 -113t124.5 -318h-120q0 146 -96 237.5t-257 91.5q-165 0 -258 -68.5t-93 -183.5q0 -79 31 -126t107 -85t235 -83q196 -51 290.5 -102.5t138.5 -122.5 t44 -172zM454 771q-108 -13 -167 -71t-59 -147q0 -83 35.5 -131t116 -86t283.5 -94l92 -28q112 13 178 70.5t66 143.5q0 98 -67 157t-240 115z"/> +<glyph glyph-name="dieresis" horiz-adv-x="881" unicode="¨" d="M143 1396q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM580 1395q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="copyright" horiz-adv-x="1637" unicode="©" d="M1121 607q0 -152 -82 -233t-232 -81t-241.5 106t-91.5 287v90q0 174 92 280.5t241 106.5t232 -80.5t83 -232.5h-99q0 224 -216 224q-106 0 -170 -81t-64 -222v-91q0 -134 63 -215.5t171 -81.5q106 0 160.5 53t54.5 171h99zM192 729q0 -176 81.5 -330t228.5 -244t315 -90 q167 0 312 89t228.5 242.5t83.5 332.5q0 178 -83 330.5t-228.5 241t-312.5 88.5q-171 0 -318 -91t-227 -243t-80 -326zM107 729q0 202 93.5 375t259 272.5t357.5 99.5t357 -99.5t258.5 -272.5t93.5 -375q0 -197 -90 -369t-255.5 -276.5t-363.5 -104.5q-197 0 -362.5 103.5 t-256.5 275.5t-91 371z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="906" unicode="ª" d="M649 705q-15 43 -21 94q-87 -108 -222 -108q-117 0 -183 58.5t-66 158.5q0 110 83.5 171t245.5 61h139v61q0 85 -40 132t-121 47q-90 0 -141.5 -35.5t-51.5 -107.5l-107 6q0 102 83 167.5t217 65.5q124 0 197 -71.5t73 -205.5v-315q0 -92 26 -179h-111zM426 786 q53 0 110.5 30t88.5 74v168h-129q-230 0 -230 -146q0 -126 160 -126z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="933" unicode="«" d="M247 536l276 -388h-105l-295 379v19l295 379h105zM556 536l276 -388h-105l-295 379v19l295 379h105z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1117" unicode="¬" d="M936 386h-120v284h-692v106h812v-390z"/> +<glyph glyph-name="registered" horiz-adv-x="1642" unicode="®" d="M102 729q0 202 93.5 375t259 272.5t357.5 99.5t357.5 -99.5t259 -272.5t93.5 -375q0 -199 -91 -371t-256.5 -275.5t-362.5 -103.5t-362.5 103.5t-256.5 275.5t-91 371zM187 729q0 -179 83.5 -333t229 -242.5t312.5 -88.5t313 88.5t228.5 243t82.5 332.5q0 176 -81 328 t-226.5 242t-316.5 90q-168 0 -313.5 -88.5t-228.5 -241t-83 -330.5zM650 666v-345h-98v839h258q147 0 226 -61.5t79 -186.5q0 -133 -141 -197q72 -26 100 -80.5t28 -130.5t4 -110t13 -57v-16h-102q-14 36 -14 182q0 89 -37.5 126t-127.5 37h-188zM650 757h181 q81 0 133.5 42t52.5 111q0 85 -43.5 121.5t-149.5 38.5h-174v-313z"/> +<glyph glyph-name="macron" horiz-adv-x="874" unicode="¯" d="M776 1359h-670v97h670v-97z"/> +<glyph glyph-name="degree" horiz-adv-x="774" unicode="°" d="M630 1226q0 -104 -71 -175t-171 -71q-101 0 -173 71.5t-72 174.5t73 176.5t172 73.5t170.5 -73.5t71.5 -176.5zM233 1226q0 -67 44.5 -111t110.5 -44t109 44t43 111q0 69 -43 114t-109 45q-65 0 -110 -45t-45 -114z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1085" unicode="±" d="M609 829h391v-102h-391v-438h-111v438h-414v102h414v438h111v-438zM963 0h-835v101h835v-101z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="740" unicode="²" d="M667 665h-571v75l320 314q106 110 106 183q0 63 -40.5 101.5t-119.5 38.5q-87 0 -134 -44.5t-47 -117.5h-105q0 108 79 179t205 71t197 -62t71 -164q0 -101 -118 -223l-55 -55l-226 -209h438v-87z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="740" unicode="³" d="M267 1107h86q81 2 128.5 38t47.5 96q0 62 -43 99t-124 37q-76 0 -124 -37t-48 -95h-105q0 96 78.5 158t197.5 62q128 0 201 -60t73 -162q0 -56 -38 -103t-108 -71q162 -42 162 -189q0 -102 -79 -164t-209 -62q-129 0 -210.5 63.5t-81.5 166.5h106q0 -62 52.5 -102.5 t136.5 -40.5q87 0 133.5 38t46.5 104q0 142 -206 142h-73v82z"/> +<glyph glyph-name="acute" horiz-adv-x="576" unicode="´" d="M315 1524h145l-231 -279h-105z"/> +<glyph glyph-name="uni00B5" horiz-adv-x="1140" unicode="µ" d="M281 1082v-636q0 -180 63 -272.5t200 -92.5q132 0 209 57.5t106 173.5v770h120v-1082h-109l-7 154q-98 -174 -311 -174q-184 0 -271 125v-521h-119v1498h119z"/> +<glyph glyph-name="paragraph" horiz-adv-x="973" unicode="¶" d="M681 0v520h-108q-150 0 -261 58t-170 164.5t-59 245.5q0 213 133 340.5t361 127.5h224v-1456h-120z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="503" unicode="·" d="M163 717q0 35 22 59t62 24t63 -24t23 -59t-23 -58.5t-63 -23.5t-62 23.5t-22 58.5z"/> +<glyph glyph-name="cedilla" horiz-adv-x="498" unicode="¸" d="M246 0l-12 -64q165 -21 165 -171q0 -92 -79 -146t-215 -54l-7 78q89 0 145.5 32.5t56.5 87.5q0 58 -43.5 80t-132.5 30l29 127h93z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="740" unicode="¹" d="M464 669h-106v663l-232 -70v90l324 107h14v-790z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="922" unicode="º" d="M135 1132q0 153 88.5 248.5t234.5 95.5q147 0 235.5 -95.5t88.5 -253.5v-94q0 -153 -88 -248t-234 -95q-147 0 -236 94.5t-89 253.5v94zM243 1033q0 -114 56.5 -181t160.5 -67q99 0 156.5 66t57.5 186v95q0 115 -58 181.5t-158 66.5t-157.5 -68t-57.5 -185v-94z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="928" unicode="»" d="M221 944l295 -384v-19l-295 -379h-106l276 388l-276 394h106zM540 944l295 -384v-19l-295 -379h-106l276 388l-276 394h106z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1484" unicode="¼" d="M453 664h-106v663l-232 -70v90l324 107h14v-790zM414 129l-74 48l711 1138l74 -48zM1272 275h127v-88h-127v-187h-105v187h-399l-4 66l397 536h111v-514zM878 275h289v384l-31 -50z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1548" unicode="½" d="M370 129l-74 48l711 1138l74 -48zM438 664h-106v663l-232 -70v90l324 107h14v-790zM1436 0h-571v75l320 314q106 110 106 183q0 63 -40.5 101.5t-119.5 38.5q-87 0 -134 -44.5t-47 -117.5h-105q0 108 79 179t205 71t197 -62t71 -164q0 -101 -118 -223l-55 -55l-226 -209 h438v-87z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1590" unicode="¾" d="M558 129l-74 48l711 1138l74 -48zM1387 275h127v-88h-127v-187h-105v187h-399l-4 66l397 536h111v-514zM993 275h289v384l-31 -50zM314 1107h86q81 2 128.5 38t47.5 96q0 62 -43 99t-124 37q-76 0 -124 -37t-48 -95h-105q0 96 78.5 158t197.5 62q128 0 201 -60t73 -162 q0 -56 -38 -103t-108 -71q162 -42 162 -189q0 -102 -79 -164t-209 -62q-129 0 -210.5 63.5t-81.5 166.5h106q0 -62 52.5 -102.5t136.5 -40.5q87 0 133.5 38t46.5 104q0 142 -206 142h-73v82z"/> +<glyph glyph-name="questiondown" horiz-adv-x="940" unicode="¿" d="M551 687q-2 -123 -27 -182t-119 -153t-117 -124q-81 -105 -81 -236q0 -129 67 -199t195 -70q119 0 190 70t73 187h120q-2 -166 -107 -264.5t-276 -98.5q-178 0 -279.5 100t-101.5 273q0 111 53 212t196 236q85 71 92 180l2 69h120zM567 1022q0 -34 -22 -57.5t-60 -23.5 t-60.5 23.5t-22.5 57.5q0 33 22.5 56t60.5 23t60 -23t22 -56z"/> +<glyph glyph-name="AE" horiz-adv-x="1865" unicode="Æ" d="M1823 0h-817l-17 389h-596l-230 -389h-146l881 1456h864v-102h-694l23 -545h589v-102h-585l26 -606h702v-101zM460 502h525l-35 829z"/> +<glyph glyph-name="multiply" horiz-adv-x="1072" unicode="×" d="M93 179l358 365l-343 350l79 80l342 -350l343 350l79 -80l-343 -350l358 -365l-79 -79l-358 364l-357 -364z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1386" unicode="Ø" d="M1260 649q0 -201 -69.5 -353t-198.5 -234t-298 -82q-186 0 -319 97l-101 -160h-104l137 217q-182 184 -182 524v147q0 199 70.5 352.5t199.5 236t297 82.5q224 0 372 -140l107 169h103l-149 -237q134 -180 135 -461v-158zM248 649q0 -261 122 -414l632 1002 q-119 131 -310 131q-203 0 -323.5 -149.5t-120.5 -417.5v-152zM1137 807q0 211 -80 353l-623 -989q107 -84 260 -84q209 0 326 149.5t117 416.5v154z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1214" unicode="Þ" d="M303 1456v-304h325q143 0 249 -51t162.5 -145.5t56.5 -217.5q0 -185 -122 -297.5t-333 -116.5h-338v-324h-120v1456h120zM303 1051v-626h324q157 0 253 85.5t96 225.5t-91.5 225.5t-242.5 89.5h-339z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1200" unicode="ß" d="M271 0h-120v1127q0 200 95.5 308.5t265.5 108.5q153 0 248.5 -84.5t95.5 -222.5q0 -58 -13.5 -106t-49 -112.5t-48 -105.5t-12.5 -89q0 -56 41.5 -108t137 -123t140 -139.5t44.5 -147.5q0 -146 -106 -236t-270 -90q-84 0 -175 24t-131 56l34 101q37 -29 114 -55t144 -26 q122 0 196 64t74 162q0 61 -44 117.5t-135.5 123.5t-137.5 134.5t-46 144.5q0 96 63 208t63 196q0 93 -63 152.5t-154 59.5q-247 0 -251 -306v-1136z"/> +<glyph glyph-name="ae" horiz-adv-x="1732" unicode="æ" d="M1265 -20q-139 0 -238.5 54.5t-159.5 151.5q-60 -98 -174 -152t-253 -54q-169 0 -262 84.5t-93 228.5q0 157 110.5 246.5t315.5 92.5h270v88q0 132 -63.5 206t-189.5 74q-130 0 -213 -65t-83 -170l-119 13q0 144 116.5 234t298.5 90q125 0 213.5 -53.5t128.5 -159.5 q60 100 154.5 156.5t210.5 56.5q196 0 308.5 -120.5t114.5 -337.5v-106h-757v-29q0 -201 96 -314.5t268 -113.5q185 0 324 118l47 -87q-145 -132 -371 -132zM458 80q91 0 184.5 46t138.5 110v300h-256q-137 0 -223 -61t-95 -166l-1 -20q0 -97 65.5 -153t186.5 -56z M1235 1000q-132 0 -222 -98t-109 -266h635v31q0 154 -80.5 243.5t-223.5 89.5z"/> +<glyph glyph-name="eth" horiz-adv-x="1191" unicode="ð" d="M811 1303q238 -250 244 -658v-110q0 -159 -56 -286.5t-157 -198t-227 -70.5q-130 0 -236 61.5t-168 175t-62 249.5q0 229 119.5 364t318.5 135q100 0 186.5 -38.5t145.5 -105.5q-42 251 -210 419l-225 -139l-51 73l206 128q-137 106 -343 173l39 103q242 -72 409 -212 l194 121l51 -73zM935 625l-2 57q-39 83 -126 131t-198 48q-161 0 -250.5 -105t-89.5 -290q0 -103 45 -192.5t124.5 -140t180.5 -50.5q141 0 228.5 124.5t87.5 335.5v82z"/> +<glyph glyph-name="divide" horiz-adv-x="1164" unicode="÷" d="M1070 644h-998v116h998v-116zM495 1088q0 35 22 59t62 24t63 -24t23 -59t-23 -58.5t-63 -23.5t-62 23.5t-22 58.5zM495 291q0 35 22 59t62 24t63 -24t23 -59t-23 -58t-63 -23t-62 23t-22 58z"/> +<glyph glyph-name="oslash" horiz-adv-x="1140" unicode="ø" d="M89 557q0 156 60.5 281t171 194.5t250.5 69.5q114 0 214 -48l78 160h94l-100 -204q94 -72 146 -189t52 -264v-33q0 -156 -61 -282t-171 -194t-250 -68q-108 0 -200 41l-79 -161h-94l99 203q-100 71 -155 190t-55 271v33zM208 524q0 -110 35.5 -205t104.5 -156l389 794 q-75 43 -166 43q-161 0 -262 -125.5t-101 -328.5v-22zM935 557q0 103 -33 194t-96 154l-387 -790q68 -34 154 -34q161 0 261.5 124.5t100.5 328.5v23z"/> +<glyph glyph-name="thorn" horiz-adv-x="1150" unicode="þ" d="M1031 530q0 -253 -112 -401.5t-301 -148.5q-221 0 -339 156v-552h-120v1952h120v-604q117 170 337 170q192 0 303.5 -146.5t111.5 -407.5v-18zM911 551q0 207 -85 327t-237 120q-110 0 -189 -53t-121 -154v-521q42 -90 121 -139.5t191 -49.5q151 0 235.5 120.5 t84.5 349.5z"/> +<glyph glyph-name="dotlessi" horiz-adv-x="456" unicode="ı" d="M288 0h-120v1082h120v-1082z"/> +<glyph glyph-name="OE" horiz-adv-x="1913" unicode="Å’" d="M1801 0h-844q-189 -21 -311 -21q-156 0 -278 74t-190 208.5t-70 304.5v314q0 172 67 309t190 212t279 75q133 0 313 -20h839v-105h-778v-549h681v-104h-681v-594h783v-104zM646 80q133 0 249 14v1266q-118 14 -251 14q-191 0 -303 -132t-113 -357v-309q0 -227 113 -361.5 t305 -134.5z"/> +<glyph glyph-name="oe" horiz-adv-x="1892" unicode="Å“" d="M94 557q0 157 60.5 283t170 194t247.5 68q142 0 252 -69.5t172 -202.5q60 126 167 199t233 73q197 0 312 -124.5t115 -343.5v-96h-764v-29q0 -185 99 -306.5t253 -121.5q210 0 325 119l52 -82q-133 -138 -377 -138q-136 0 -247 72t-169 196q-61 -130 -170.5 -199 t-250.5 -69q-215 0 -347.5 151.5t-132.5 401.5v24zM214 524q0 -197 99 -320t261 -123q160 0 258.5 123t98.5 330v23q0 195 -99.5 319t-259.5 124t-259 -124t-99 -330v-22zM1396 1000q-130 0 -222 -101t-111 -260h640v30q0 146 -84 238.5t-223 92.5z"/> +<glyph glyph-name="circumflex" horiz-adv-x="880" unicode="ˆ" d="M715 1268v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="ring" horiz-adv-x="635" unicode="Ëš" d="M117 1395q0 80 56.5 135t136.5 55q79 0 136 -55t57 -135q0 -79 -55 -133t-138 -54t-138 54t-55 133zM194 1395q0 -50 33 -83t83 -33q49 0 83 32.5t34 83.5q0 53 -35 86t-82 33q-49 0 -82.5 -34t-33.5 -85z"/> +<glyph glyph-name="tilde" horiz-adv-x="891" unicode="Ëœ" d="M779 1485q0 -96 -56.5 -154.5t-138.5 -58.5q-76 0 -148.5 55t-129.5 55q-47 0 -78.5 -31t-31.5 -87l-90 3q0 92 54.5 152t140.5 60q48 0 82 -17t64 -38t60.5 -38t71.5 -17q46 0 78.5 33t32.5 89z"/> +<glyph glyph-name="endash" horiz-adv-x="1334" unicode="–" d="M1161.01 686h-1002.01v102h1002.01v-102z"/> +<glyph glyph-name="emdash" horiz-adv-x="1580" unicode="—" d="M1461.98 686h-1335.98v102h1335.98v-102z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="364" unicode="‘" d="M238 1554l72 -51q-90 -118 -93 -254v-128h-119v112q0 92 37.5 177t102.5 144z"/> +<glyph glyph-name="quoteright" horiz-adv-x="364" unicode="’" d="M133 1099l-71 52q90 121 93 254v131h118v-101q0 -209 -140 -336z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="353" unicode="‚" d="M112 -231l-71 52q83 111 91 230l1 154h119v-101q0 -208 -140 -335z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="612" unicode="“" d="M239 1554l72 -51q-90 -118 -93 -254v-128h-119v112q0 92 37.5 177t102.5 144zM490 1554l72 -51q-90 -118 -93 -254v-128h-119v112q0 92 37.5 177t102.5 144z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="617" unicode="â€" d="M139 1099l-71 52q90 121 93 254v131h118v-101q0 -209 -140 -336zM383 1099l-71 52q90 121 93 254v131h118v-101q0 -209 -140 -336z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="593" unicode="„" d="M112 -240l-71 52q89 123 92 261v163h119v-130q0 -217 -140 -346zM346 -240l-71 52q88 122 91 261v163h120v-130q0 -217 -140 -346z"/> +<glyph glyph-name="bullet" horiz-adv-x="662" unicode="•" d="M146 752q0 79 51 129t134 50q82 0 133 -48.5t53 -125.5v-40q0 -81 -51 -129t-134 -48q-84 0 -135 49t-51 130v33z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="609" unicode="‹" d="M232 555l276 -388h-105l-295 379v19l295 379h105z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="609" unicode="›" d="M203 944l295 -384v-19l-295 -379h-106l276 388l-276 394h106z"/> +<glyph glyph-name="fraction" horiz-adv-x="918" unicode="â„" d="M136 121l-74 48l711 1138l74 -48z"/> +<glyph glyph-name="uni2074" horiz-adv-x="740" unicode="â´" d="M567 935h127v-88h-127v-187h-105v187h-399l-4 66l397 536h111v-514zM173 935h289v384l-31 -50z"/> +<glyph glyph-name="Euro" d="M817 563h-419v-17q0 -221 108.5 -342t306.5 -121q117 0 219 34l10 -107q-116 -30 -230 -30q-249 0 -391.5 147t-145.5 409v27h-192v89h192v164h-192v90h192q0 270 143 420t392 150q99 0 232 -31l-10 -109q-112 35 -221 35q-198 0 -305.5 -118.5t-107.5 -346.5h419v-90 h-419v-164h419v-89z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1168" unicode="−" d="M1000 686h-835v102h835v-102z"/> +<glyph glyph-name="glyph162" d="M464 0h-106v663l-232 -70v90l324 107h14v-790z" horiz-adv-x="739"/> +<glyph glyph-name="glyph163" d="M667 0h-571v75l320 314q106 110 106 183q0 63 -40.5 101.5t-119.5 38.5q-87 0 -134 -44.5t-47 -117.5h-105q0 108 79 179t205 71t197 -62t71 -164q0 -101 -118 -223l-55 -55l-226 -209h438v-87z" horiz-adv-x="739"/> +<glyph glyph-name="glyph164" d="M267 442h86q81 2 128.5 38t47.5 96q0 62 -43 99t-124 37q-76 0 -124 -37t-48 -95h-105q0 96 78.5 158t197.5 62q128 0 201 -60t73 -162q0 -56 -38 -103t-108 -71q162 -42 162 -189q0 -102 -79 -164t-209 -62q-129 0 -210.5 63.5t-81.5 166.5h106q0 -62 52.5 -102.5 t136.5 -40.5q87 0 133.5 38t46.5 104q0 142 -206 142h-73v82z" horiz-adv-x="739"/> +<glyph glyph-name="glyph165" d="M567 275h127v-88h-127v-187h-105v187h-399l-4 66l397 536h111v-514zM173 275h289v384l-31 -50z" horiz-adv-x="739"/> +<glyph glyph-name="uni00A0" horiz-adv-x="498" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="586" unicode="Â" d="M528 592h-479v101h479v-101z"/> +<glyph glyph-name="Eth" horiz-adv-x="1371" unicode="Ã" d="M214 0v689h-181v102h181v665h407q179 0 321 -81.5t221.5 -233.5t79.5 -346v-134q0 -195 -79 -346t-222.5 -233t-329.5 -82h-398zM645 689h-308v-585h271q235 0 374 152.5t139 412.5v128q0 251 -137 402t-361 152h-286v-560h308v-102z"/> +<glyph glyph-name="Agrave" horiz-adv-x="1279" unicode="À" d="M970 408h-661l-150 -408h-129l551 1456h117l551 -1456h-128zM347 513h584l-292 793zM716 1560h-109l-226 279h144z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1279" unicode="Ã" d="M970 408h-661l-150 -408h-129l551 1456h117l551 -1456h-128zM347 513h584l-292 793zM762 1839h145l-231 -279h-105z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1279" unicode="Â" d="M970 408h-661l-150 -408h-129l551 1456h117l551 -1456h-128zM347 513h584l-292 793zM921 1583v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1279" unicode="Ã" d="M970 408h-661l-150 -408h-129l551 1456h117l551 -1456h-128zM347 513h584l-292 793zM983 1809q0 -96 -56.5 -154.5t-138.5 -58.5q-76 0 -148.5 55t-129.5 55q-47 0 -78.5 -31t-31.5 -87l-90 3q0 92 54.5 152t140.5 60q48 0 82 -17t64 -38t60.5 -38t71.5 -17q46 0 78.5 33 t32.5 89z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1279" unicode="Ä" d="M970 408h-661l-150 -408h-129l551 1456h117l551 -1456h-128zM347 513h584l-292 793zM349 1711q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM786 1710q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5 q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="Aring" horiz-adv-x="1279" unicode="Ã…" d="M970 408h-661l-150 -408h-129l551 1456h117l551 -1456h-128zM347 513h584l-292 793zM450 1715q0 80 56.5 135t136.5 55q79 0 136 -55t57 -135q0 -79 -55 -133t-138 -54t-138 54t-55 133zM527 1715q0 -50 33 -83t83 -33q49 0 83 32.5t34 83.5q0 53 -35 86t-82 33 q-49 0 -82.5 -34t-33.5 -85z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1330" unicode="Ç" d="M1215 454q-25 -230 -164.5 -352t-371.5 -122q-162 0 -286.5 81t-192.5 229.5t-69 339.5v189q0 194 68 344t195.5 231.5t293.5 81.5q234 0 369.5 -126.5t157.5 -349.5h-124q-46 371 -403 371q-198 0 -315.5 -148t-117.5 -409v-178q0 -252 114.5 -402t309.5 -150 q193 0 291 92.5t121 277.5h124zM728 -9l-12 -64q165 -21 165 -171q0 -92 -79 -146t-215 -54l-7 78q89 0 145.5 32.5t56.5 87.5q0 58 -43.5 80t-132.5 30l29 127h93z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1165" unicode="È" d="M988 698h-681v-594h783v-104h-906v1456h901v-105h-778v-549h681v-104zM693 1566h-109l-226 279h144z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1165" unicode="É" d="M988 698h-681v-594h783v-104h-906v1456h901v-105h-778v-549h681v-104zM739 1845h145l-231 -279h-105z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1165" unicode="Ê" d="M988 698h-681v-594h783v-104h-906v1456h901v-105h-778v-549h681v-104zM898 1589v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1165" unicode="Ë" d="M988 698h-681v-594h783v-104h-906v1456h901v-105h-778v-549h681v-104zM326 1717q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM763 1716q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56 t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="Igrave" horiz-adv-x="545" unicode="ÃŒ" d="M334 0h-123v1456h123v-1456zM348 1566h-109l-226 279h144z"/> +<glyph glyph-name="Iacute" horiz-adv-x="545" unicode="Ã" d="M334 0h-123v1456h123v-1456zM393 1845h145l-231 -279h-105z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="545" unicode="ÃŽ" d="M334 0h-123v1456h123v-1456zM553 1589v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="545" unicode="Ã" d="M334 0h-123v1456h123v-1456zM-19 1717q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM418 1716q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1454" unicode="Ñ" d="M1268 0h-123l-837 1246v-1246h-124v1456h124l838 -1247v1247h122v-1456zM1067 1809q0 -96 -56.5 -154.5t-138.5 -58.5q-76 0 -148.5 55t-129.5 55q-47 0 -78.5 -31t-31.5 -87l-90 3q0 92 54.5 152t140.5 60q48 0 82 -17t64 -38t60.5 -38t71.5 -17q46 0 78.5 33t32.5 89z "/> +<glyph glyph-name="Ograve" horiz-adv-x="1386" unicode="Ã’" d="M1260 649q0 -201 -69.5 -353t-198.5 -234t-298 -82q-255 0 -412 182.5t-157 492.5v150q0 199 70.5 352.5t199.5 236t297 82.5t296.5 -81t198.5 -229t73 -343v-174zM1137 807q0 263 -119 412t-326 149q-203 0 -323.5 -149.5t-120.5 -417.5v-152q0 -259 120 -410.5 t326 -151.5q209 0 326 149.5t117 416.5v154zM765 1572h-109l-226 279h144z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1386" unicode="Ó" d="M1260 649q0 -201 -69.5 -353t-198.5 -234t-298 -82q-255 0 -412 182.5t-157 492.5v150q0 199 70.5 352.5t199.5 236t297 82.5t296.5 -81t198.5 -229t73 -343v-174zM1137 807q0 263 -119 412t-326 149q-203 0 -323.5 -149.5t-120.5 -417.5v-152q0 -259 120 -410.5 t326 -151.5q209 0 326 149.5t117 416.5v154zM811 1851h145l-231 -279h-105z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1386" unicode="Ô" d="M1260 649q0 -201 -69.5 -353t-198.5 -234t-298 -82q-255 0 -412 182.5t-157 492.5v150q0 199 70.5 352.5t199.5 236t297 82.5t296.5 -81t198.5 -229t73 -343v-174zM1137 807q0 263 -119 412t-326 149q-203 0 -323.5 -149.5t-120.5 -417.5v-152q0 -259 120 -410.5 t326 -151.5q209 0 326 149.5t117 416.5v154zM970 1595v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1386" unicode="Õ" d="M1260 649q0 -201 -69.5 -353t-198.5 -234t-298 -82q-255 0 -412 182.5t-157 492.5v150q0 199 70.5 352.5t199.5 236t297 82.5t296.5 -81t198.5 -229t73 -343v-174zM1137 807q0 263 -119 412t-326 149q-203 0 -323.5 -149.5t-120.5 -417.5v-152q0 -259 120 -410.5 t326 -151.5q209 0 326 149.5t117 416.5v154zM1032 1821q0 -96 -56.5 -154.5t-138.5 -58.5q-76 0 -148.5 55t-129.5 55q-47 0 -78.5 -31t-31.5 -87l-90 3q0 92 54.5 152t140.5 60q48 0 82 -17t64 -38t60.5 -38t71.5 -17q46 0 78.5 33t32.5 89z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1386" unicode="Ö" d="M1260 649q0 -201 -69.5 -353t-198.5 -234t-298 -82q-255 0 -412 182.5t-157 492.5v150q0 199 70.5 352.5t199.5 236t297 82.5t296.5 -81t198.5 -229t73 -343v-174zM1137 807q0 263 -119 412t-326 149q-203 0 -323.5 -149.5t-120.5 -417.5v-152q0 -259 120 -410.5 t326 -151.5q209 0 326 149.5t117 416.5v154zM398 1723q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM835 1722q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1346" unicode="Ù" d="M1187 1456v-994q-1 -147 -65 -256t-180.5 -167.5t-267.5 -58.5q-230 0 -368.5 125.5t-143.5 347.5v1003h122v-985q0 -184 105 -285.5t285 -101.5t284.5 102t104.5 284v986h124zM756 1560h-109l-226 279h144z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1346" unicode="Ú" d="M1187 1456v-994q-1 -147 -65 -256t-180.5 -167.5t-267.5 -58.5q-230 0 -368.5 125.5t-143.5 347.5v1003h122v-985q0 -184 105 -285.5t285 -101.5t284.5 102t104.5 284v986h124zM802 1839h145l-231 -279h-105z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1346" unicode="Û" d="M1187 1456v-994q-1 -147 -65 -256t-180.5 -167.5t-267.5 -58.5q-230 0 -368.5 125.5t-143.5 347.5v1003h122v-985q0 -184 105 -285.5t285 -101.5t284.5 102t104.5 284v986h124zM961 1583v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="Udieresis" horiz-adv-x="1346" unicode="Ü" d="M1187 1456v-994q-1 -147 -65 -256t-180.5 -167.5t-267.5 -58.5q-230 0 -368.5 125.5t-143.5 347.5v1003h122v-985q0 -184 105 -285.5t285 -101.5t284.5 102t104.5 284v986h124zM389 1711q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23 q-39 0 -60.5 23t-21.5 56zM826 1710q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1226" unicode="Ã" d="M611 662l445 794h142l-526 -908v-548h-123v548l-525 908h146zM732 1833h145l-231 -279h-105z"/> +<glyph glyph-name="agrave" horiz-adv-x="1097" unicode="à " d="M839 0q-18 51 -23 151q-63 -82 -160.5 -126.5t-206.5 -44.5q-156 0 -252.5 87t-96.5 220q0 158 131.5 250t366.5 92h217v123q0 116 -71.5 182.5t-208.5 66.5q-125 0 -207 -64t-82 -154l-120 1q0 129 120 223.5t295 94.5q181 0 285.5 -90.5t107.5 -252.5v-512 q0 -157 33 -235v-12h-128zM463 86q120 0 214.5 58t137.5 155v238h-214q-179 -2 -280 -65.5t-101 -174.5q0 -91 67.5 -151t175.5 -60zM653 1245h-109l-226 279h144z"/> +<glyph glyph-name="aacute" horiz-adv-x="1097" unicode="á" d="M839 0q-18 51 -23 151q-63 -82 -160.5 -126.5t-206.5 -44.5q-156 0 -252.5 87t-96.5 220q0 158 131.5 250t366.5 92h217v123q0 116 -71.5 182.5t-208.5 66.5q-125 0 -207 -64t-82 -154l-120 1q0 129 120 223.5t295 94.5q181 0 285.5 -90.5t107.5 -252.5v-512 q0 -157 33 -235v-12h-128zM463 86q120 0 214.5 58t137.5 155v238h-214q-179 -2 -280 -65.5t-101 -174.5q0 -91 67.5 -151t175.5 -60zM699 1524h145l-231 -279h-105z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1097" unicode="â" d="M839 0q-18 51 -23 151q-63 -82 -160.5 -126.5t-206.5 -44.5q-156 0 -252.5 87t-96.5 220q0 158 131.5 250t366.5 92h217v123q0 116 -71.5 182.5t-208.5 66.5q-125 0 -207 -64t-82 -154l-120 1q0 129 120 223.5t295 94.5q181 0 285.5 -90.5t107.5 -252.5v-512 q0 -157 33 -235v-12h-128zM463 86q120 0 214.5 58t137.5 155v238h-214q-179 -2 -280 -65.5t-101 -174.5q0 -91 67.5 -151t175.5 -60zM858 1268v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="atilde" horiz-adv-x="1097" unicode="ã" d="M839 0q-18 51 -23 151q-63 -82 -160.5 -126.5t-206.5 -44.5q-156 0 -252.5 87t-96.5 220q0 158 131.5 250t366.5 92h217v123q0 116 -71.5 182.5t-208.5 66.5q-125 0 -207 -64t-82 -154l-120 1q0 129 120 223.5t295 94.5q181 0 285.5 -90.5t107.5 -252.5v-512 q0 -157 33 -235v-12h-128zM463 86q120 0 214.5 58t137.5 155v238h-214q-179 -2 -280 -65.5t-101 -174.5q0 -91 67.5 -151t175.5 -60zM920 1494q0 -96 -56.5 -154.5t-138.5 -58.5q-76 0 -148.5 55t-129.5 55q-47 0 -78.5 -31t-31.5 -87l-90 3q0 92 54.5 152t140.5 60 q48 0 82 -17t64 -38t60.5 -38t71.5 -17q46 0 78.5 33t32.5 89z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1097" unicode="ä" d="M839 0q-18 51 -23 151q-63 -82 -160.5 -126.5t-206.5 -44.5q-156 0 -252.5 87t-96.5 220q0 158 131.5 250t366.5 92h217v123q0 116 -71.5 182.5t-208.5 66.5q-125 0 -207 -64t-82 -154l-120 1q0 129 120 223.5t295 94.5q181 0 285.5 -90.5t107.5 -252.5v-512 q0 -157 33 -235v-12h-128zM463 86q120 0 214.5 58t137.5 155v238h-214q-179 -2 -280 -65.5t-101 -174.5q0 -91 67.5 -151t175.5 -60zM286 1396q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM723 1395 q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="aring" horiz-adv-x="1097" unicode="Ã¥" d="M839 0q-18 51 -23 151q-63 -82 -160.5 -126.5t-206.5 -44.5q-156 0 -252.5 87t-96.5 220q0 158 131.5 250t366.5 92h217v123q0 116 -71.5 182.5t-208.5 66.5q-125 0 -207 -64t-82 -154l-120 1q0 129 120 223.5t295 94.5q181 0 285.5 -90.5t107.5 -252.5v-512 q0 -157 33 -235v-12h-128zM463 86q120 0 214.5 58t137.5 155v238h-214q-179 -2 -280 -65.5t-101 -174.5q0 -91 67.5 -151t175.5 -60zM387 1400q0 80 56.5 135t136.5 55q79 0 136 -55t57 -135q0 -79 -55 -133t-138 -54t-138 54t-55 133zM464 1400q0 -50 33 -83t83 -33 q49 0 83 32.5t34 83.5q0 53 -35 86t-82 33q-49 0 -82.5 -34t-33.5 -85z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1055" unicode="ç" d="M556 81q125 0 209.5 70.5t91.5 182.5h115q-5 -99 -62 -180.5t-151.5 -127.5t-202.5 -46q-213 0 -337.5 148t-124.5 398v36q0 160 56 283t160.5 190t244.5 67q178 0 293.5 -106t123.5 -279h-115q-8 127 -91.5 205t-210.5 78q-162 0 -251.5 -117t-89.5 -328v-35 q0 -207 89.5 -323t252.5 -116zM589 -9l-12 -64q165 -21 165 -171q0 -92 -79 -146t-215 -54l-7 78q89 0 145.5 32.5t56.5 87.5q0 58 -43.5 80t-132.5 30l29 127h93z"/> +<glyph glyph-name="egrave" horiz-adv-x="1058" unicode="è" d="M575 -20q-138 0 -249.5 68t-173.5 189.5t-62 272.5v43q0 156 60.5 281t168.5 196.5t234 71.5q197 0 312.5 -134.5t115.5 -367.5v-67h-772v-23q0 -184 105.5 -306.5t265.5 -122.5q96 0 169.5 35t133.5 112l75 -57q-132 -191 -383 -191zM553 1000q-135 0 -227.5 -99 t-112.5 -266h649v13q-5 156 -89 254t-220 98zM640 1245h-109l-226 279h144z"/> +<glyph glyph-name="eacute" horiz-adv-x="1058" unicode="é" d="M575 -20q-138 0 -249.5 68t-173.5 189.5t-62 272.5v43q0 156 60.5 281t168.5 196.5t234 71.5q197 0 312.5 -134.5t115.5 -367.5v-67h-772v-23q0 -184 105.5 -306.5t265.5 -122.5q96 0 169.5 35t133.5 112l75 -57q-132 -191 -383 -191zM553 1000q-135 0 -227.5 -99 t-112.5 -266h649v13q-5 156 -89 254t-220 98zM686 1524h145l-231 -279h-105z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1058" unicode="ê" d="M575 -20q-138 0 -249.5 68t-173.5 189.5t-62 272.5v43q0 156 60.5 281t168.5 196.5t234 71.5q197 0 312.5 -134.5t115.5 -367.5v-67h-772v-23q0 -184 105.5 -306.5t265.5 -122.5q96 0 169.5 35t133.5 112l75 -57q-132 -191 -383 -191zM553 1000q-135 0 -227.5 -99 t-112.5 -266h649v13q-5 156 -89 254t-220 98zM845 1268v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1058" unicode="ë" d="M575 -20q-138 0 -249.5 68t-173.5 189.5t-62 272.5v43q0 156 60.5 281t168.5 196.5t234 71.5q197 0 312.5 -134.5t115.5 -367.5v-67h-772v-23q0 -184 105.5 -306.5t265.5 -122.5q96 0 169.5 35t133.5 112l75 -57q-132 -191 -383 -191zM553 1000q-135 0 -227.5 -99 t-112.5 -266h649v13q-5 156 -89 254t-220 98zM273 1396q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM710 1395q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z "/> +<glyph glyph-name="igrave" horiz-adv-x="456" unicode="ì" d="M288 0h-120v1082h120v-1082zM305 1233h-109l-226 279h144z"/> +<glyph glyph-name="iacute" horiz-adv-x="456" unicode="Ã" d="M288 0h-120v1082h120v-1082zM350 1512h145l-231 -279h-105z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="456" unicode="î" d="M288 0h-120v1082h120v-1082zM510 1256v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="idieresis" horiz-adv-x="456" unicode="ï" d="M288 0h-120v1082h120v-1082zM-62 1384q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM375 1383q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="ntilde" horiz-adv-x="1125" unicode="ñ" d="M270 1082l4 -185q61 100 152 152.5t201 52.5q174 0 259 -98t86 -294v-710h-119v711q-1 145 -61.5 216t-193.5 71q-111 0 -196.5 -69.5t-126.5 -187.5v-741h-119v1082h114zM916 1493q0 -96 -56.5 -154.5t-138.5 -58.5q-76 0 -148.5 55t-129.5 55q-47 0 -78.5 -31 t-31.5 -87l-90 3q0 92 54.5 152t140.5 60q48 0 82 -17t64 -38t60.5 -38t71.5 -17q46 0 78.5 33t32.5 89z"/> +<glyph glyph-name="ograve" horiz-adv-x="1147" unicode="ò" d="M90 557q0 156 60.5 281t171 194.5t250.5 69.5q216 0 350 -151.5t134 -401.5v-25q0 -157 -60.5 -282.5t-170.5 -193.5t-251 -68q-215 0 -349.5 151.5t-134.5 401.5v24zM210 524q0 -194 100.5 -318.5t263.5 -124.5q162 0 262.5 124.5t100.5 328.5v23q0 124 -46 227 t-129 159.5t-190 56.5q-160 0 -261 -125.5t-101 -328.5v-22zM645 1245h-109l-226 279h144z"/> +<glyph glyph-name="oacute" horiz-adv-x="1147" unicode="ó" d="M90 557q0 156 60.5 281t171 194.5t250.5 69.5q216 0 350 -151.5t134 -401.5v-25q0 -157 -60.5 -282.5t-170.5 -193.5t-251 -68q-215 0 -349.5 151.5t-134.5 401.5v24zM210 524q0 -194 100.5 -318.5t263.5 -124.5q162 0 262.5 124.5t100.5 328.5v23q0 124 -46 227 t-129 159.5t-190 56.5q-160 0 -261 -125.5t-101 -328.5v-22zM691 1524h145l-231 -279h-105z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1147" unicode="ô" d="M90 557q0 156 60.5 281t171 194.5t250.5 69.5q216 0 350 -151.5t134 -401.5v-25q0 -157 -60.5 -282.5t-170.5 -193.5t-251 -68q-215 0 -349.5 151.5t-134.5 401.5v24zM210 524q0 -194 100.5 -318.5t263.5 -124.5q162 0 262.5 124.5t100.5 328.5v23q0 124 -46 227 t-129 159.5t-190 56.5q-160 0 -261 -125.5t-101 -328.5v-22zM850 1268v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="otilde" horiz-adv-x="1147" unicode="õ" d="M90 557q0 156 60.5 281t171 194.5t250.5 69.5q216 0 350 -151.5t134 -401.5v-25q0 -157 -60.5 -282.5t-170.5 -193.5t-251 -68q-215 0 -349.5 151.5t-134.5 401.5v24zM210 524q0 -194 100.5 -318.5t263.5 -124.5q162 0 262.5 124.5t100.5 328.5v23q0 124 -46 227 t-129 159.5t-190 56.5q-160 0 -261 -125.5t-101 -328.5v-22zM912 1493q0 -96 -56.5 -154.5t-138.5 -58.5q-76 0 -148.5 55t-129.5 55q-47 0 -78.5 -31t-31.5 -87l-90 3q0 92 54.5 152t140.5 60q48 0 82 -17t64 -38t60.5 -38t71.5 -17q46 0 78.5 33t32.5 89z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1147" unicode="ö" d="M90 557q0 156 60.5 281t171 194.5t250.5 69.5q216 0 350 -151.5t134 -401.5v-25q0 -157 -60.5 -282.5t-170.5 -193.5t-251 -68q-215 0 -349.5 151.5t-134.5 401.5v24zM210 524q0 -194 100.5 -318.5t263.5 -124.5q162 0 262.5 124.5t100.5 328.5v23q0 124 -46 227 t-129 159.5t-190 56.5q-160 0 -261 -125.5t-101 -328.5v-22zM278 1396q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM715 1395q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23 q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="ugrave" horiz-adv-x="1125" unicode="ù" d="M852 137q-108 -157 -345 -157q-173 0 -263 100.5t-92 297.5v704h119v-689q0 -309 250 -309q260 0 329 215v783h120v-1082h-116zM647 1245h-109l-226 279h144z"/> +<glyph glyph-name="uacute" horiz-adv-x="1125" unicode="ú" d="M852 137q-108 -157 -345 -157q-173 0 -263 100.5t-92 297.5v704h119v-689q0 -309 250 -309q260 0 329 215v783h120v-1082h-116zM693 1524h145l-231 -279h-105z"/> +<glyph glyph-name="ucircumflex" horiz-adv-x="1125" unicode="û" d="M852 137q-108 -157 -345 -157q-173 0 -263 100.5t-92 297.5v704h119v-689q0 -309 250 -309q260 0 329 215v783h120v-1082h-116zM852 1268v-10h-111l-168 183l-167 -183h-109v13l238 255h76z"/> +<glyph glyph-name="udieresis" horiz-adv-x="1125" unicode="ü" d="M852 137q-108 -157 -345 -157q-173 0 -263 100.5t-92 297.5v704h119v-689q0 -309 250 -309q260 0 329 215v783h120v-1082h-116zM280 1396q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56zM717 1395 q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +<glyph glyph-name="yacute" horiz-adv-x="973" unicode="ý" d="M499 172l316 910h129l-462 -1266l-24 -56q-89 -197 -275 -197q-43 0 -92 14l-1 99l62 -6q88 0 142.5 43.5t92.5 149.5l53 146l-408 1073h131zM633 1524h145l-231 -279h-105z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="973" unicode="ÿ" d="M499 172l316 910h129l-462 -1266l-24 -56q-89 -197 -275 -197q-43 0 -92 14l-1 99l62 -6q88 0 142.5 43.5t92.5 149.5l53 146l-408 1073h131zM220 1396q0 34 21.5 57.5t60.5 23.5q38 0 60.5 -23.5t22.5 -57.5q0 -33 -22.5 -56t-60.5 -23q-39 0 -60.5 23t-21.5 56z M657 1395q0 34 22 57.5t60 23.5q39 0 61 -23.5t22 -57.5q0 -33 -22 -56t-61 -23q-38 0 -60 23t-22 56z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.ttf b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6b5941033e93bc79963cc33c66f11f962ed037b2 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff new file mode 100644 index 0000000000000000000000000000000000000000..1030581abcac4cfa180bc5047e5abbdc11080cb1 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff2 b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..8047ab708fb0faa47aacb6386d3f9230910b39a4 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Light/RobotoDraft-Light.woff2 differ diff --git a/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.eot b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.eot new file mode 100644 index 0000000000000000000000000000000000000000..5a8cca7bd8dd78c8d7299c750be284926bcb3809 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.svg b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.svg new file mode 100644 index 0000000000000000000000000000000000000000..b47fa7d69b9d05819f6db0a4f05e24bf257331a4 --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.svg @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-Medium" horiz-adv-x="1164"> +<font-face underline-position="-100" font-weight="500" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-85 -474 1879 1940" x-height="1082" underline-thickness="100" font-family="RobotoDraft Medium" ascent="1536" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1192" unicode="fi" d="M189 0v902h-165v180h165v74q1 127 54 218t150 137t233 46q80 0 153.5 -17t152.5 -43l-37 -201q-138 48 -252 48q-111 0 -161 -48.5t-50 -145.5v-68h213v-180h-213v-902h-243zM1047 0h-243v1082h243v-1082z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1212" unicode="fl" d="M825 1343q-102 14 -176 14q-196 0 -196 -184v-91h220v-180h-220v-902h-243v902h-165v180h165v97q1 183 108.5 280.5t303.5 97.5q122 0 446 -48v-1509h-243v1343z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="uni0000" horiz-adv-x="0"/> +<glyph glyph-name="glyph2" horiz-adv-x="0"/> +<glyph glyph-name="uni000D" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="549" unicode="!" d="M382 429h-209l-23 1027h256zM143 115q0 57 37 94.5t101 37.5t101 -37.5t37 -94.5q0 -55 -36 -92t-102 -37t-102 37t-36 92z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="664" unicode='"' d="M275 1399l-35 -387h-139v524h174v-137zM576 1399l-35 -387h-139v524h174v-137z"/> +<glyph glyph-name="numbersign" horiz-adv-x="1250" unicode="#" d="M719 410h-224l-76 -410h-168l76 410h-231v158h261l58 313h-243v159h273l78 416h167l-78 -416h225l78 416h167l-78 -416h208v-159h-238l-58 -313h221v-158h-251l-76 -410h-167zM525 568h224l58 313h-224z"/> +<glyph glyph-name="dollar" d="M819 380q0 85 -54 140.5t-180 100t-196 82.5q-233 125 -233 370q0 166 101 273t274 127v218h160v-220q174 -25 269 -147.5t95 -318.5h-242q0 126 -56.5 198.5t-153.5 72.5q-96 0 -150 -52t-54 -149q0 -87 53.5 -139.5t181.5 -99.5t201 -87t123 -91.5t77 -118.5t27 -157 q0 -169 -103.5 -274t-288.5 -124v-195h-159v194q-198 22 -304.5 142t-106.5 318h243q0 -126 63.5 -195t179.5 -69q114 0 173.5 55t59.5 146z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1504" unicode="%" d="M99 1176q0 132 85 216.5t223 84.5q140 0 224.5 -84.5t84.5 -221.5v-72q0 -131 -84.5 -215t-222.5 -84q-135 0 -222.5 82.5t-87.5 222.5v71zM269 1099q0 -69 38.5 -111.5t101.5 -42.5q62 0 100 42.5t38 115.5v73q0 69 -38.5 112t-101.5 43t-100.5 -43.5t-37.5 -114.5v-74z M799 357q0 134 87 217t222 83q136 0 222.5 -83t86.5 -224v-71q0 -130 -83.5 -214.5t-223.5 -84.5t-225.5 83.5t-85.5 220.5v73zM969 279q0 -68 39.5 -111.5t101.5 -43.5q64 0 100.5 41.5t36.5 116.5v75q0 70 -39 112t-100 42q-62 0 -100.5 -42t-38.5 -116v-74zM459 109 l-125 72l711 1138l125 -72z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1309" unicode="&" d="M86 393q0 101 55 185.5t217 200.5q-85 107 -118.5 182t-33.5 145q0 171 104 270.5t280 99.5q159 0 260.5 -93.5t101.5 -231.5q0 -91 -46 -167.5t-151 -152.5l-99 -72l281 -332q61 120 61 267h211q0 -269 -126 -441l214 -253h-282l-82 97q-156 -117 -372 -117 t-345.5 114.5t-129.5 298.5zM568 174q123 0 230 82l-318 375l-31 -22q-120 -91 -120 -208q0 -101 65 -164t174 -63zM434 1112q0 -84 103 -211l111 76l31 25q62 55 62 141q0 57 -43 97.5t-109 40.5q-71 0 -113 -48t-42 -121z"/> +<glyph glyph-name="quotesingle" horiz-adv-x="346" unicode="'" d="M267 1411l-26 -391h-159v516h185v-125z"/> +<glyph glyph-name="parenleft" horiz-adv-x="714" unicode="(" d="M128 592q0 231 62 438.5t182 371t254 229.5l48 -142q-141 -107 -228.5 -326.5t-95.5 -502.5l-1 -86q0 -303 85.5 -540.5t239.5 -361.5l-48 -135q-134 66 -254.5 230.5t-182 371t-61.5 453.5z"/> +<glyph glyph-name="parenright" horiz-adv-x="722" unicode=")" d="M593 576q0 -222 -61 -428.5t-185 -376t-259 -234.5l-48 135q150 116 237.5 354.5t87.5 544.5v23q0 278 -76 506.5t-218 366.5l-31 28l48 136q128 -62 248 -220t184 -353.5t72 -403.5z"/> +<glyph glyph-name="asterisk" horiz-adv-x="905" unicode="*" d="M332 972l-305 88l55 169l302 -117l-15 344h179l-15 -350l297 115l54 -172l-310 -88l200 -266l-145 -106l-180 288l-178 -279l-146 102z"/> +<glyph glyph-name="plus" horiz-adv-x="1141" unicode="+" d="M686 801h380v-222h-380v-433h-236v433h-382v222h382v405h236v-405z"/> +<glyph glyph-name="comma" horiz-adv-x="450" unicode="," d="M159 -328l-131 78q58 91 79.5 158.5t22.5 137.5v189h219l-1 -175q-1 -106 -53.5 -212.5t-135.5 -175.5z"/> +<glyph glyph-name="hyphen" horiz-adv-x="672" unicode="-" d="M596 521h-525v196h525v-196z"/> +<glyph glyph-name="period" horiz-adv-x="572" unicode="." d="M276 256q68 0 105 -38.5t37 -96.5q0 -57 -37 -94.5t-105 -37.5q-65 0 -103 37t-38 95t37 96.5t104 38.5z"/> +<glyph glyph-name="slash" horiz-adv-x="810" unicode="/" d="M193 -125h-191l573 1581h191z"/> +<glyph glyph-name="zero" d="M1058 613q0 -314 -117.5 -473.5t-357.5 -159.5q-236 0 -355.5 155.5t-122.5 460.5v252q0 314 117.5 471t358.5 157q239 0 356.5 -153t120.5 -458v-252zM815 885q0 205 -56 300.5t-178 95.5q-119 0 -175 -90.5t-59 -282.5v-330q0 -204 57 -304t179 -100q117 0 173 92.5 t59 289.5v329z" unicode="0"/> +<glyph glyph-name="one" d="M767 0h-242v1169l-357 -122v205l568 209h31v-1461z" unicode="1"/> +<glyph glyph-name="two" d="M1088 0h-979v167l485 529q105 117 149.5 195.5t44.5 157.5q0 104 -58.5 168t-157.5 64q-118 0 -183 -72t-65 -197h-243q0 133 60.5 239.5t173 165.5t259.5 59q212 0 334.5 -106.5t122.5 -294.5q0 -109 -61.5 -228.5t-201.5 -271.5l-356 -381h676v-194z" unicode="2"/> +<glyph glyph-name="three" d="M390 839h148q112 1 177.5 58t65.5 165q0 104 -54.5 161.5t-166.5 57.5q-98 0 -161 -56.5t-63 -147.5h-243q0 112 59.5 204t166 143.5t238.5 51.5q218 0 342.5 -109.5t124.5 -304.5q0 -98 -62.5 -184.5t-161.5 -130.5q120 -41 182.5 -129t62.5 -210q0 -196 -134.5 -312 t-353.5 -116q-210 0 -344 112t-134 298h243q0 -96 64.5 -156t173.5 -60q113 0 178 60t65 174q0 115 -68 177t-202 62h-143v192z" unicode="3"/> +<glyph glyph-name="four" d="M931 519h181v-195h-181v-324h-243v324h-629l-7 148l628 984h251v-937zM307 519h381v608l-18 -32z" unicode="4"/> +<glyph glyph-name="five" d="M174 722l79 734h782v-210h-580l-40 -348q101 58 228 58q208 0 323.5 -133t115.5 -358q0 -222 -128 -353.5t-351 -131.5q-200 0 -331.5 113.5t-142.5 299.5h235q14 -106 76 -162.5t162 -56.5q112 0 174.5 80t62.5 218q0 133 -69 210.5t-190 77.5q-66 0 -112 -17.5 t-100 -68.5z" unicode="5"/> +<glyph glyph-name="six" d="M865 1463v-201h-30q-204 -3 -326 -112t-145 -309q117 123 299 123q193 0 304.5 -136t111.5 -351q0 -222 -130.5 -359.5t-342.5 -137.5q-218 0 -353.5 161t-135.5 422v83q0 383 186.5 600t536.5 217h25zM604 768q-80 0 -146.5 -45t-97.5 -120v-74q0 -162 68 -257.5 t176 -95.5t171 81t63 213t-64 215t-170 83z" unicode="6"/> +<glyph glyph-name="seven" d="M1078 1321l-582 -1321h-255l581 1261h-753v195h1009v-135z" unicode="7"/> +<glyph glyph-name="eight" d="M1026 1072q0 -107 -55 -190.5t-150 -131.5q114 -53 175.5 -145t61.5 -208q0 -192 -130 -304.5t-346 -112.5q-217 0 -347.5 113t-130.5 304q0 117 62 210t174 143q-94 48 -148.5 131.5t-54.5 190.5q0 186 120 295t324 109q205 0 325 -109t120 -295zM815 409 q0 108 -64.5 174.5t-170.5 66.5t-169.5 -66t-63.5 -175q0 -107 62.5 -171t172.5 -64t171.5 62t61.5 173zM784 1063q0 95 -55 156.5t-148 61.5t-147 -58.5t-54 -159.5q0 -100 54.5 -159t147.5 -59t147.5 59t54.5 159z" unicode="8"/> +<glyph glyph-name="nine" d="M798 609q-122 -129 -285 -129q-192 0 -306 134.5t-114 353.5q0 144 58 261t165 182t248 65q220 0 349 -164t129 -439v-68q0 -394 -178 -601t-531 -210h-29v201h35q215 3 330 103.5t129 310.5zM564 670q73 0 137 42t99 116v95q0 161 -66 259t-171 98t-167.5 -86.5 t-62.5 -218.5q0 -137 63 -221t168 -84z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="543" unicode=":" d="M271 256q68 0 105 -38.5t37 -96.5q0 -57 -37 -94.5t-105 -37.5q-65 0 -103 37t-38 95t37 96.5t104 38.5zM271 1105q68 0 105 -38.5t37 -96.5q0 -57 -37 -94.5t-105 -37.5q-65 0 -103 37t-38 95t37 96.5t104 38.5z"/> +<glyph glyph-name="semicolon" horiz-adv-x="487" unicode=";" d="M250 1105q68 0 105 -38.5t37 -96.5q0 -57 -37 -94.5t-105 -37.5q-65 0 -103 37t-38 95t37 96.5t104 38.5zM177 -328l-131 78q58 91 79.5 158.5t22.5 137.5v189h219l-1 -175q-1 -106 -53.5 -212.5t-135.5 -175.5z"/> +<glyph glyph-name="less" horiz-adv-x="1041" unicode="<" d="M310 631l590 -224v-243l-837 373v193l837 372v-243z"/> +<glyph glyph-name="equal" horiz-adv-x="1146" unicode="=" d="M1007 780h-862v202h862v-202zM1007 356h-862v201h862v-201z"/> +<glyph glyph-name="greater" horiz-adv-x="1066" unicode=">" d="M746 636l-618 227v239l864 -372v-193l-864 -372v239z"/> +<glyph glyph-name="question" horiz-adv-x="996" unicode="?" d="M350 428q0 133 33 212t130.5 173.5t123.5 134.5q40 61 40 132q0 94 -46.5 143.5t-136.5 49.5q-86 0 -138.5 -48.5t-52.5 -131.5h-243q2 177 120.5 280t313.5 103q201 0 313.5 -102t112.5 -285q0 -163 -152 -321l-123 -121q-66 -75 -68 -219h-227zM333 117q0 59 37 95.5 t100 36.5q64 0 101 -37.5t37 -94.5q0 -55 -36 -92t-102 -37t-101.5 37t-35.5 92z"/> +<glyph glyph-name="at" horiz-adv-x="1832" unicode="@" d="M1741 518q-12 -250 -123 -394.5t-301 -144.5q-181 0 -242 154q-51 -76 -118.5 -114t-141.5 -38q-146 0 -221.5 120t-57.5 321q16 163 79.5 294t161 202.5t207.5 71.5q84 0 148.5 -21t151.5 -87l-52 -563q-19 -198 114 -198q102 0 167.5 109.5t71.5 283.5 q17 369 -142.5 565t-479.5 196q-196 0 -347.5 -98t-240.5 -283.5t-98 -422.5q-12 -241 57.5 -415.5t213 -265.5t350.5 -91q84 0 175.5 20t155.5 54l38 -137q-61 -40 -164.5 -64.5t-208.5 -24.5q-254 0 -436 107.5t-273 311.5q-94 211 -83 505q12 274 123 492.5t303.5 339.5 t438.5 121q249 0 428.5 -109.5t268.5 -315t77 -481.5zM732 422q-13 -136 24 -206.5t118 -70.5q54 0 102 47.5t78 130.5l45 493q-50 19 -97 19q-111 0 -181 -104.5t-89 -308.5z"/> +<glyph glyph-name="A" horiz-adv-x="1363" unicode="A" d="M963 339h-564l-118 -339h-263l550 1456h227l551 -1456h-264zM470 543h422l-211 604z"/> +<glyph glyph-name="B" horiz-adv-x="1292" unicode="B" d="M148 0v1456h499q247 0 376 -99t129 -295q0 -100 -54 -180t-158 -124q118 -32 182.5 -120.5t64.5 -212.5q0 -205 -131.5 -315t-376.5 -110h-531zM401 657v-455h281q119 0 186 59t67 164q0 227 -232 232h-302zM401 843h248q118 0 184.5 53.5t66.5 151.5q0 108 -61.5 156 t-191.5 48h-246v-409z"/> +<glyph glyph-name="C" horiz-adv-x="1337" unicode="C" d="M1259 474q-22 -233 -172 -363.5t-399 -130.5q-174 0 -306.5 82.5t-204.5 234.5t-75 353v136q0 206 73 363t209.5 242t315.5 85q241 0 388 -131t171 -370h-252q-18 157 -91.5 226.5t-215.5 69.5q-165 0 -253.5 -120.5t-90.5 -353.5v-129q0 -236 84.5 -360t247.5 -124 q149 0 224 67t95 223h252z"/> +<glyph glyph-name="D" horiz-adv-x="1338" unicode="D" d="M148 0v1456h430q193 0 342.5 -86t231.5 -244t82 -362v-73q0 -207 -82.5 -364t-235 -242t-349.5 -85h-419zM401 1252v-1050h165q199 0 305.5 124.5t108.5 357.5v81q0 237 -103 362t-299 125h-177z"/> +<glyph glyph-name="E" horiz-adv-x="1158" unicode="E" d="M999 650h-598v-448h699v-202h-952v1456h945v-204h-692v-402h598v-200z"/> +<glyph glyph-name="F" horiz-adv-x="1125" unicode="F" d="M987 617h-586v-617h-253v1456h925v-204h-672v-433h586v-202z"/> +<glyph glyph-name="G" horiz-adv-x="1394" unicode="G" d="M1264 189q-79 -103 -219 -156t-318 -53q-183 0 -324 83t-217.5 237.5t-79.5 360.5v114q0 330 158 515.5t441 185.5q243 0 386 -120t172 -346h-248q-42 263 -305 263q-170 0 -258.5 -122.5t-91.5 -359.5v-112q0 -236 99.5 -366.5t276.5 -130.5q194 0 276 88v285h-300v192 h552v-558z"/> +<glyph glyph-name="H" horiz-adv-x="1455" unicode="H" d="M1304 0h-252v647h-651v-647h-253v1456h253v-606h651v606h252v-1456z"/> +<glyph glyph-name="I" horiz-adv-x="578" unicode="I" d="M415 0h-252v1456h252v-1456z"/> +<glyph glyph-name="J" horiz-adv-x="1137" unicode="J" d="M744 1456h252v-1021q0 -209 -130.5 -332t-344.5 -123q-228 0 -352 115t-124 320h252q0 -116 57.5 -174.5t166.5 -58.5q102 0 162.5 67.5t60.5 186.5v1020z"/> +<glyph glyph-name="K" horiz-adv-x="1291" unicode="K" d="M566 629l-165 -175v-454h-253v1456h253v-683l140 173l426 510h306l-541 -645l572 -811h-300z"/> +<glyph glyph-name="L" horiz-adv-x="1108" unicode="L" d="M401 202h661v-202h-914v1456h253v-1254z"/> +<glyph glyph-name="M" horiz-adv-x="1793" unicode="M" d="M476 1456l420 -1116l419 1116h327v-1456h-252v480l25 642l-430 -1122h-181l-429 1121l25 -641v-480h-252v1456h328z"/> +<glyph glyph-name="N" horiz-adv-x="1454" unicode="N" d="M1303 0h-253l-649 1033v-1033h-253v1456h253l651 -1037v1037h251v-1456z"/> +<glyph glyph-name="O" horiz-adv-x="1414" unicode="O" d="M1310 690q0 -214 -74 -375.5t-211.5 -248t-316.5 -86.5q-177 0 -315.5 86.5t-214 246.5t-76.5 369v82q0 213 75.5 376t213 249.5t315.5 86.5t315.5 -85.5t212.5 -246t76 -373.5v-81zM1057 766q0 242 -91.5 371t-259.5 129q-164 0 -256.5 -128.5t-94.5 -363.5v-84 q0 -240 93.5 -371t259.5 -131q168 0 258.5 128t90.5 374v76z"/> +<glyph glyph-name="P" horiz-adv-x="1309" unicode="P" d="M401 541v-541h-253v1456h557q244 0 387.5 -127t143.5 -336q0 -214 -140.5 -333t-393.5 -119h-301zM401 744h304q135 0 206 63.5t71 183.5q0 118 -72 188.5t-198 72.5h-311v-508z"/> +<glyph glyph-name="Q" horiz-adv-x="1414" unicode="Q" d="M1305 690q0 -207 -65.5 -358.5t-183.5 -240.5l250 -195l-164 -148l-310 245q-61 -13 -131 -13q-176 0 -314.5 86.5t-214 246.5t-76.5 369v82q0 213 75.5 376t213 249.5t314.5 86.5q180 0 317.5 -85.5t212.5 -246t76 -373.5v-81zM1051 766q0 246 -92 373t-260 127 q-163 0 -255.5 -128.5t-94.5 -362.5v-85q0 -236 92.5 -369t259.5 -133q169 0 259.5 128t90.5 374v76z"/> +<glyph glyph-name="R" horiz-adv-x="1278" unicode="R" d="M683 561h-282v-561h-253v1456h512q252 0 389 -113t137 -327q0 -146 -70.5 -244.5t-196.5 -151.5l327 -607v-13h-271zM401 764h260q128 0 200 64.5t72 176.5q0 117 -66.5 181t-198.5 66h-267v-488z"/> +<glyph glyph-name="S" horiz-adv-x="1236" unicode="S" d="M909 375q0 96 -67.5 148t-243.5 105t-280 118q-199 125 -199 326q0 176 143.5 290t372.5 114q152 0 271 -56t187 -159.5t68 -229.5h-252q0 114 -71.5 178.5t-204.5 64.5q-124 0 -192.5 -53t-68.5 -148q0 -80 74 -133.5t244 -104t273 -115t151 -148t48 -195.5 q0 -182 -139.5 -289.5t-378.5 -107.5q-158 0 -290.5 58.5t-206 161.5t-73.5 240h253q0 -124 82 -192t235 -68q132 0 198.5 53.5t66.5 141.5z"/> +<glyph glyph-name="T" horiz-adv-x="1243" unicode="T" d="M1200 1252h-454v-1252h-251v1252h-450v204h1155v-204z"/> +<glyph glyph-name="U" horiz-adv-x="1335" unicode="U" d="M1213 1456v-973q0 -232 -148.5 -367.5t-395.5 -135.5q-250 0 -397 133.5t-147 370.5v972h252v-974q0 -146 74 -223t218 -77q292 0 292 308v966h252z"/> +<glyph glyph-name="V" horiz-adv-x="1325" unicode="V" d="M661 317l370 1139h278l-524 -1456h-245l-522 1456h277z"/> +<glyph glyph-name="W" horiz-adv-x="1802" unicode="W" d="M1290 360l224 1096h251l-336 -1456h-242l-277 1063l-283 -1063h-243l-336 1456h251l226 -1094l278 1094h212z"/> +<glyph glyph-name="X" horiz-adv-x="1296" unicode="X" d="M649 930l306 526h292l-440 -722l450 -734h-295l-313 534l-314 -534h-294l451 734l-441 722h292z"/> +<glyph glyph-name="Y" horiz-adv-x="1248" unicode="Y" d="M623 766l335 690h280l-488 -920v-536h-254v536l-489 920h281z"/> +<glyph glyph-name="Z" horiz-adv-x="1233" unicode="Z" d="M386 202h778v-202h-1084v164l753 1088h-748v204h1055v-160z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="561" unicode="[" d="M540 1488h-165v-1623h165v-189h-408v2002h408v-190z"/> +<glyph glyph-name="backslash" horiz-adv-x="856" unicode="\" d="M20 1456h240l608 -1581h-240z"/> +<glyph glyph-name="bracketright" horiz-adv-x="561" unicode="]" d="M12 1678h410v-2002h-410v189h167v1623h-167v190z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="875" unicode="^" d="M437 1190l-178 -461h-206l299 727h171l298 -727h-205z"/> +<glyph glyph-name="underscore" horiz-adv-x="924" unicode="_" d="M920 -191h-917v191h917v-191z"/> +<glyph glyph-name="grave" horiz-adv-x="660" unicode="`" d="M521 1233h-202l-270 303h277z"/> +<glyph glyph-name="a" horiz-adv-x="1108" unicode="a" d="M771 0q-16 31 -28 101q-116 -121 -284 -121q-163 0 -266 93t-103 230q0 173 128.5 265.5t367.5 92.5h149v71q0 84 -47 134.5t-143 50.5q-83 0 -136 -41.5t-53 -105.5h-243q0 89 59 166.5t160.5 121.5t226.5 44q190 0 303 -95.5t116 -268.5v-488q0 -146 41 -233v-17h-248z M504 175q72 0 135.5 35t95.5 94v204h-131q-135 0 -203 -47t-68 -133q0 -70 46.5 -111.5t124.5 -41.5z"/> +<glyph glyph-name="b" horiz-adv-x="1153" unicode="b" d="M1074 530q0 -252 -112.5 -401t-309.5 -149q-190 0 -296 137l-12 -117h-220v1536h243v-558q105 124 283 124q198 0 311 -147t113 -411v-14zM831 551q0 176 -62 264t-180 88q-158 0 -222 -138v-446q65 -141 224 -141q114 0 176 85t64 257v31z"/> +<glyph glyph-name="c" horiz-adv-x="1072" unicode="c" d="M569 174q91 0 151 53t64 131h229q-4 -101 -63 -188.5t-160 -138.5t-218 -51q-227 0 -360 147t-133 406v25q0 247 132 395.5t360 148.5q193 0 314.5 -112.5t127.5 -295.5h-229q-4 93 -63.5 153t-151.5 60q-118 0 -182 -85.5t-65 -259.5v-39q0 -176 63.5 -262.5 t183.5 -86.5z"/> +<glyph glyph-name="d" horiz-adv-x="1156" unicode="d" d="M79 549q0 250 116 401.5t311 151.5q172 0 278 -120v554h243v-1536h-220l-12 112q-109 -132 -291 -132q-190 0 -307.5 153t-117.5 416zM322 528q0 -165 63.5 -257.5t180.5 -92.5q149 0 218 133v462q-67 130 -216 130q-118 0 -182 -93.5t-64 -281.5z"/> +<glyph glyph-name="e" horiz-adv-x="1099" unicode="e" d="M601 -20q-231 0 -374.5 145.5t-143.5 387.5v30q0 162 62.5 289.5t175.5 198.5t252 71q221 0 341.5 -141t120.5 -399v-98h-707q11 -134 89.5 -212t197.5 -78q167 0 272 135l131 -125q-65 -97 -173.5 -150.5t-243.5 -53.5zM572 907q-100 0 -161.5 -70t-78.5 -195h463v18 q-8 122 -65 184.5t-158 62.5z"/> +<glyph glyph-name="f" horiz-adv-x="726" unicode="f" d="M210 0v902h-165v180h165v99q0 180 100 278t280 98q64 0 136 -18l-6 -190q-40 8 -93 8q-174 0 -174 -179v-96h220v-180h-220v-902h-243z"/> +<glyph glyph-name="g" horiz-adv-x="1161" unicode="g" d="M82 549q0 252 118.5 402.5t314.5 150.5q185 0 291 -129l11 109h219v-1049q0 -213 -132.5 -336t-357.5 -123q-119 0 -232.5 49.5t-172.5 129.5l115 146q112 -133 276 -133q121 0 191 65.5t70 192.5v73q-105 -117 -280 -117q-190 0 -310.5 151t-120.5 418zM324 528 q0 -163 66.5 -256.5t184.5 -93.5q147 0 218 126v476q-69 123 -216 123q-120 0 -186.5 -95t-66.5 -280z"/> +<glyph glyph-name="h" horiz-adv-x="1137" unicode="h" d="M364 964q119 138 301 138q346 0 351 -395v-707h-243v698q0 112 -48.5 158.5t-142.5 46.5q-146 0 -218 -130v-773h-243v1536h243v-572z"/> +<glyph glyph-name="i" horiz-adv-x="523" unicode="i" d="M383 0h-243v1082h243v-1082zM125 1363q0 56 35.5 93t101.5 37t102 -37t36 -93q0 -55 -36 -91.5t-102 -36.5t-101.5 36.5t-35.5 91.5z"/> +<glyph glyph-name="j" horiz-adv-x="513" unicode="j" d="M378 1082v-1178q0 -166 -82.5 -253.5t-241.5 -87.5q-67 0 -129 17v192q38 -9 86 -9q121 0 124 132v1187h243zM114 1363q0 56 35.5 93t101.5 37t102 -37t36 -93q0 -55 -36 -91.5t-102 -36.5t-101.5 36.5t-35.5 91.5z"/> +<glyph glyph-name="k" horiz-adv-x="1069" unicode="k" d="M476 464l-108 -111v-353h-243v1536h243v-886l76 95l299 337h292l-402 -451l445 -631h-281z"/> +<glyph glyph-name="l" horiz-adv-x="523" unicode="l" d="M383 0h-243v1536h243v-1536z"/> +<glyph glyph-name="m" horiz-adv-x="1782" unicode="m" d="M353 1082l7 -113q114 133 312 133q217 0 297 -166q118 166 332 166q179 0 266.5 -99t89.5 -292v-711h-243v704q0 103 -45 151t-149 48q-83 0 -135.5 -44.5t-73.5 -116.5l1 -742h-243v712q-5 191 -195 191q-146 0 -207 -119v-784h-243v1082h229z"/> +<glyph glyph-name="n" horiz-adv-x="1139" unicode="n" d="M350 1082l7 -125q120 145 315 145q338 0 344 -387v-715h-243v701q0 103 -44.5 152.5t-145.5 49.5q-147 0 -219 -133v-770h-243v1082h229z"/> +<glyph glyph-name="o" horiz-adv-x="1166" unicode="o" d="M79 551q0 159 63 286.5t177 196t262 68.5q219 0 355.5 -141t147.5 -374l1 -57q0 -160 -61.5 -286t-176 -195t-264.5 -69q-229 0 -366.5 152.5t-137.5 406.5v12zM322 530q0 -167 69 -261.5t192 -94.5t191.5 96t68.5 281q0 164 -70.5 260t-191.5 96q-119 0 -189 -94.5 t-70 -282.5z"/> +<glyph glyph-name="p" horiz-adv-x="1153" unicode="p" d="M1072 530q0 -251 -114 -400.5t-306 -149.5q-178 0 -285 117v-513h-243v1498h224l10 -110q107 130 291 130q198 0 310.5 -147.5t112.5 -409.5v-15zM830 551q0 162 -64.5 257t-184.5 95q-149 0 -214 -123v-480q66 -126 216 -126q116 0 181.5 93.5t65.5 283.5z"/> +<glyph glyph-name="q" horiz-adv-x="1163" unicode="q" d="M79 550q0 254 116 403t314 149q181 0 287 -127l14 107h216v-1498h-243v508q-106 -112 -276 -112q-194 0 -311 151.5t-117 418.5zM322 529q0 -166 65.5 -260.5t181.5 -94.5q144 0 214 123v492q-70 118 -212 118q-116 0 -182.5 -93t-66.5 -285z"/> +<glyph glyph-name="r" horiz-adv-x="720" unicode="r" d="M691 860q-48 8 -99 8q-167 0 -225 -128v-740h-243v1082h232l6 -121q88 141 244 141q52 0 86 -14z"/> +<glyph glyph-name="s" horiz-adv-x="1057" unicode="s" d="M731 294q0 65 -53.5 99t-177.5 60t-207 66q-182 88 -182 255q0 140 118 234t300 94q194 0 313.5 -96t119.5 -249h-243q0 70 -52 116.5t-138 46.5q-80 0 -130.5 -37t-50.5 -99q0 -56 47 -87t190 -62.5t224.5 -75t121 -104.5t39.5 -148q0 -146 -121 -236.5t-317 -90.5 q-133 0 -237 48t-162 132t-58 181h236q5 -86 65 -132.5t159 -46.5q96 0 146 36.5t50 95.5z"/> +<glyph glyph-name="t" horiz-adv-x="681" unicode="t" d="M429 1345v-263h191v-180h-191v-604q0 -62 24.5 -89.5t87.5 -27.5q42 0 85 10v-188q-83 -23 -160 -23q-280 0 -280 309v613h-178v180h178v263h243z"/> +<glyph glyph-name="u" horiz-adv-x="1138" unicode="u" d="M780 106q-107 -126 -304 -126q-176 0 -266.5 103t-90.5 298v701h243v-698q0 -206 171 -206q177 0 239 127v777h243v-1082h-229z"/> +<glyph glyph-name="v" horiz-adv-x="1013" unicode="v" d="M506 308l229 774h251l-375 -1082h-211l-378 1082h252z"/> +<glyph glyph-name="w" horiz-adv-x="1522" unicode="w" d="M1075 335l172 747h237l-295 -1082h-200l-232 743l-228 -743h-200l-296 1082h237l175 -739l222 739h183z"/> +<glyph glyph-name="x" horiz-adv-x="1030" unicode="x" d="M513 726l206 356h270l-331 -533l342 -549h-268l-216 370l-215 -370h-270l342 549l-330 533h268z"/> +<glyph glyph-name="y" horiz-adv-x="997" unicode="y" d="M503 348l220 734h259l-430 -1246q-99 -273 -336 -273q-53 0 -117 18v188l46 -3q92 0 138.5 33.5t73.5 112.5l35 93l-380 1077h262z"/> +<glyph glyph-name="z" horiz-adv-x="1030" unicode="z" d="M384 194h576v-194h-878v159l549 727h-539v196h847v-154z"/> +<glyph glyph-name="braceleft" horiz-adv-x="687" unicode="{" d="M609 -360q-353 99 -360 451v213q0 225 -193 225v178q193 0 193 226v212q3 180 93.5 291t266.5 161l48 -140q-173 -56 -179 -306v-216q0 -225 -173 -316q173 -92 173 -319v-213q6 -250 179 -306z"/> +<glyph glyph-name="bar" horiz-adv-x="514" unicode="|" d="M341 -270h-167v1726h167v-1726z"/> +<glyph glyph-name="braceright" horiz-adv-x="687" unicode="}" d="M27 -219q176 57 180 312v208q0 231 182 317q-182 86 -182 320v207q-4 255 -180 312l48 140q182 -51 271 -165.5t89 -299.5v-200q0 -225 194 -225v-178q-194 0 -194 -225v-197q0 -187 -89.5 -301.5t-270.5 -165.5z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1361" unicode="~" d="M1244 786q0 -176 -95 -287.5t-237 -111.5q-74 0 -136.5 28t-139.5 96.5t-110.5 85t-71.5 16.5q-67 0 -105.5 -52t-38.5 -136h-193q0 171 91 280.5t239 109.5q74 0 140.5 -29.5t139 -95.5t106 -83t72.5 -17q67 0 109 56t42 140h188z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="542" unicode="¡" d="M170 662h209l24 -1026h-257zM409 971q0 -56 -36 -93.5t-101 -37.5q-66 0 -102 37.5t-36 93.5q0 55 36 92.5t102 37.5q65 0 101 -37.5t36 -92.5z"/> +<glyph glyph-name="cent" horiz-adv-x="1149" unicode="¢" d="M591 174q89 0 149 52t66 132h228q-4 -136 -102.5 -238.5t-244.5 -130.5v-234h-200v234q-183 34 -285 177.5t-102 363.5v28q0 213 102 357t285 178v225h200v-224q158 -28 250.5 -136t96.5 -264h-228q-7 96 -66 154.5t-150 58.5q-230 0 -246 -312l-1 -72 q0 -176 63.5 -262.5t184.5 -86.5z"/> +<glyph glyph-name="sterling" horiz-adv-x="1205" unicode="£" d="M509 598l7 -176q0 -135 -64 -220h696l-1 -202h-1049v202h82q39 9 60.5 64.5t21.5 146.5l-7 185h-161v199h155l-8 242q0 202 125 319t328 117t319 -109t116 -293h-245q0 95 -52.5 147.5t-146.5 52.5q-89 0 -140.5 -65t-51.5 -169l9 -242h311v-199h-304z"/> +<glyph glyph-name="currency" horiz-adv-x="1437" unicode="¤" d="M1085 107q-159 -127 -362 -127q-202 0 -360 126l-129 -132l-141 144l135 137q-100 156 -100 353q0 200 109 365l-144 147l141 144l142 -145q155 115 347 115q194 0 349 -117l145 148l142 -145l-148 -151q107 -159 107 -361q0 -193 -98 -349l139 -141l-142 -145zM313 608 q0 -120 55 -223t150 -161.5t205 -58.5t205 59t149.5 162t54.5 222t-54.5 221t-149 160.5t-205.5 58.5t-206 -58.5t-149.5 -160.5t-54.5 -221z"/> +<glyph glyph-name="yen" horiz-adv-x="1248" unicode="Â¥" d="M621 820l315 636h280l-393 -714h269v-152h-349v-138h349v-151h-349v-301h-252v301h-354v151h354v138h-354v152h281l-393 714h281z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="508" unicode="¦" d="M136 -270v795h229v-795h-229zM365 698h-229v758h229v-758z"/> +<glyph glyph-name="section" horiz-adv-x="1272" unicode="§" d="M1164 455q0 -184 -171 -273q135 -100 135 -285q0 -173 -135 -272t-369 -99q-246 0 -390 108.5t-144 315.5l242 1q0 -110 78 -170t214 -60q121 0 191.5 47.5t70.5 126.5q0 77 -67 122.5t-254 100.5q-188 51 -283 106t-141.5 132t-46.5 186q0 184 169 274q-65 50 -99 118 t-34 168q0 170 137.5 272t367.5 102q240 0 374 -112.5t134 -316.5h-243q0 106 -72.5 170t-192.5 64q-123 0 -192.5 -47.5t-69.5 -129.5q0 -84 60 -127.5t253.5 -95.5t290.5 -108.5t142 -133t45 -184.5zM601 673q-81 21 -157 49q-108 -40 -108 -164q0 -81 49.5 -124 t198.5 -90l179 -53l46 -16q115 47 115 164q0 81 -68 129.5t-255 104.5z"/> +<glyph glyph-name="dieresis" horiz-adv-x="901" unicode="¨" d="M93 1366q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM549 1365q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="copyright" horiz-adv-x="1604" unicode="©" d="M1118 596q0 -152 -87.5 -233t-247.5 -81t-254.5 106.5t-94.5 286.5v113q0 174 95.5 280.5t253.5 106.5q163 0 249.5 -82.5t86.5 -231.5h-156q0 96 -46 137.5t-134 41.5q-92 0 -143.5 -68t-51.5 -186v-117q0 -118 52 -185t143 -67q89 0 134 40.5t45 138.5h156zM1384 729 q0 166 -75 308.5t-212 228t-300 85.5q-159 0 -295.5 -82t-214.5 -226t-78 -314t77.5 -314t214 -227.5t296.5 -83.5t297.5 85t213.5 229t76 311zM87 729q0 202 93.5 375t259 272.5t357.5 99.5t357 -99.5t258.5 -272.5t93.5 -375t-93.5 -375t-257.5 -273.5t-358 -100.5 q-193 0 -357.5 100t-258.5 273t-94 376z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="913" unicode="ª" d="M608 705l-17 68q-77 -82 -201 -82q-118 0 -183.5 61.5t-65.5 166.5q0 110 84 170.5t257 60.5h102v51q0 127 -116 127q-65 0 -101.5 -25.5t-36.5 -73.5l-173 14q0 104 87.5 168.5t223.5 64.5q137 0 214 -72.5t77 -204.5v-316q0 -97 26 -178h-177zM433 835q40 0 82 18 t69 43v137h-106q-76 -1 -119 -31t-43 -79q0 -88 117 -88z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="994" unicode="«" d="M295 537l247 -399h-167l-288 390v19l288 390h167zM654 537l247 -399h-167l-288 390v19l288 390h167z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1133" unicode="¬" d="M962 374h-200v260h-635v171h835v-431z"/> +<glyph glyph-name="registered" horiz-adv-x="1604" unicode="®" d="M87 729q0 202 93.5 375t259 272.5t357.5 99.5t357 -99.5t258.5 -272.5t93.5 -375t-93.5 -375t-257.5 -273.5t-358 -100.5q-193 0 -357.5 100t-258.5 273t-94 376zM1384 729q0 166 -75 308.5t-212 228t-300 85.5q-159 0 -295.5 -82t-214.5 -226t-78 -314t77.5 -314 t214 -227.5t296.5 -83.5t297.5 85t213.5 229t76 311zM653 653v-337h-151v850h281q153 0 239 -67.5t86 -192.5q0 -117 -120 -180q65 -29 91 -84.5t26 -137t3.5 -115.5t13.5 -57v-16h-155q-13 34 -13 194q0 76 -33 109.5t-110 33.5h-158zM653 787h143q69 0 115.5 31t46.5 85 q0 70 -35.5 99.5t-128.5 30.5h-141v-246z"/> +<glyph glyph-name="macron" horiz-adv-x="987" unicode="¯" d="M862 1298h-727v158h727v-158z"/> +<glyph glyph-name="degree" horiz-adv-x="778" unicode="°" d="M391 1476q106 0 183 -79t77 -189t-76 -187.5t-184 -77.5q-109 0 -186.5 77.5t-77.5 187.5t78.5 189t185.5 79zM391 1084q53 0 87.5 35.5t34.5 88.5q0 52 -34.5 90t-87.5 38t-89 -38t-36 -90t36.5 -88t88.5 -36z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1098" unicode="±" d="M668 899h343v-199h-343v-388h-216v388h-357v199h357v377h216v-377zM974 1h-849v196h849v-196z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="758" unicode="²" d="M690 667h-612v125l285 261q113 103 113 170q0 42 -27 68.5t-79 26.5q-58 0 -91 -33t-33 -87h-186q0 116 84.5 192.5t219.5 76.5q143 0 221 -64t78 -179q0 -107 -106 -209l-98 -87l-140 -113h371v-148z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="758" unicode="³" d="M268 1132h81q132 0 132 97q0 35 -27 61.5t-89 26.5q-48 0 -80.5 -19.5t-32.5 -54.5h-186q0 99 82.5 161t212.5 62q143 0 224.5 -60.5t81.5 -165.5q0 -119 -135 -170q149 -41 149 -183q0 -106 -88.5 -169t-231.5 -63q-135 0 -220.5 63.5t-85.5 176.5h186q0 -38 34.5 -64.5 t94.5 -26.5q63 0 93.5 27.5t30.5 69.5q0 101 -134 102h-92v129z"/> +<glyph glyph-name="acute" horiz-adv-x="667" unicode="´" d="M307 1536h277l-277 -303h-195z"/> +<glyph glyph-name="uni00B5" horiz-adv-x="1211" unicode="µ" d="M388 1082v-636q2 -141 46.5 -206t150.5 -65q168 0 227 121v786h243v-1082h-223l-7 86q-92 -107 -239 -107q-121 0 -198 55v-450h-242v1498h242z"/> +<glyph glyph-name="paragraph" horiz-adv-x="1005" unicode="¶" d="M644 0v520h-80q-230 0 -362.5 127t-132.5 341q0 213 133 340.5t363 127.5h289v-1456h-210z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="578" unicode="·" d="M142 714q0 58 37 97t104 39t104.5 -39t37.5 -97q0 -59 -39 -96t-103 -37q-65 0 -103 37t-38 96z"/> +<glyph glyph-name="cedilla" horiz-adv-x="528" unicode="¸" d="M318 3l-11 -54q150 -27 150 -173q0 -105 -86 -164t-241 -59l-7 137q66 0 101.5 23.5t35.5 65.5q0 45 -35.5 62.5t-115.5 22.5l32 139h177z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="758" unicode="¹" d="M514 672h-185v570l-201 -48v146l367 119h19v-787z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="935" unicode="º" d="M119 1121q0 160 95.5 257.5t250.5 97.5t251 -97t96 -263v-72q0 -159 -94 -256.5t-251 -97.5q-158 0 -253 98t-95 261v72zM294 1044q0 -98 46.5 -153t126.5 -55q78 0 123.5 54t46.5 151v80q0 97 -46.5 152t-125.5 55q-78 0 -124.5 -54.5t-46.5 -156.5v-73z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="994" unicode="»" d="M260 937l288 -390v-19l-288 -390h-167l247 399l-247 400h167zM633 937l288 -390v-19l-288 -390h-167l247 399l-247 400h167z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1488" unicode="¼" d="M475 664h-185v570l-201 -48v146l367 119h19v-787zM453 117l-125 72l711 1138l125 -72zM1316 314h95v-151h-95v-163h-187v163h-358l-9 121l365 505h189v-475zM943 314h186v242l-14 -22z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1579" unicode="½" d="M410 117l-125 72l711 1138l125 -72zM466 667h-185v570l-201 -48v146l367 119h19v-787zM1484 0h-612v125l285 261q113 103 113 170q0 42 -27 68.5t-79 26.5q-58 0 -91 -33t-33 -87h-186q0 116 84.5 192.5t219.5 76.5q143 0 221 -64t78 -179q0 -107 -106 -209l-98 -87 l-140 -113h371v-148z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1623" unicode="¾" d="M594 117l-125 72l711 1138l125 -72zM1437 314h95v-151h-95v-163h-187v163h-358l-9 121l365 505h189v-475zM1064 314h186v242l-14 -22zM316 1133h81q132 0 132 97q0 35 -27 61.5t-89 26.5q-48 0 -80.5 -19.5t-32.5 -54.5h-186q0 99 82.5 161t212.5 62q143 0 224.5 -60.5 t81.5 -165.5q0 -119 -135 -170q149 -41 149 -183q0 -106 -88.5 -169t-231.5 -63q-135 0 -220.5 63.5t-85.5 176.5h186q0 -38 34.5 -64.5t94.5 -26.5q63 0 93.5 27.5t30.5 69.5q0 101 -134 102h-92v129z"/> +<glyph glyph-name="questiondown" horiz-adv-x="996" unicode="¿" d="M630 661q-2 -124 -28.5 -196.5t-99.5 -151.5l-103 -106q-90 -97 -90 -203q0 -94 49 -140.5t138 -46.5q88 0 141 50t53 133h243q-2 -177 -121.5 -281t-313.5 -104q-206 0 -319 100.5t-113 284.5q0 165 155 328l92 93q78 72 88 187l2 53h227zM650 972q0 -56 -35.5 -93.5 t-101.5 -37.5t-102 37.5t-36 93.5q0 55 36 92.5t102 37.5t101.5 -37.5t35.5 -92.5z"/> +<glyph glyph-name="AE" horiz-adv-x="1925" unicode="Æ" d="M1879 0h-898l-15 340h-502l-184 -340h-290l835 1456h992v-197h-646l17 -408h548v-197h-540l20 -458h663v-196zM580 555h377l-27 648z"/> +<glyph glyph-name="multiply" horiz-adv-x="1092" unicode="×" d="M77 364l316 322l-316 322l148 150l315 -322l316 322l148 -150l-316 -322l316 -322l-148 -150l-316 321l-315 -321z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1412" unicode="Ø" d="M1314 690q0 -214 -74 -375.5t-211.5 -248t-317.5 -86.5q-164 0 -296 75l-91 -150h-169l145 238q-195 195 -195 554v67q0 213 75 375t213 249.5t316 87.5q197 0 340 -101l87 143h167l-147 -243q157 -193 158 -510v-75zM358 690q0 -207 71 -335l502 826q-87 85 -222 85 q-164 0 -256.5 -128.5t-94.5 -363.5v-84zM1061 766q0 166 -44 280l-489 -804q78 -54 183 -54q169 0 259.5 128t90.5 374v76z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1226" unicode="Þ" d="M391 1456v-280h241q244 0 381 -119t137 -319q0 -199 -137 -318.5t-380 -119.5h-242v-300h-243v1456h243zM391 981v-486h246q125 0 197.5 65t72.5 176t-70 177t-192 68h-254z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1255" unicode="ß" d="M378 0h-242v1105q0 214 114.5 333t320.5 119q187 0 294.5 -93.5t107.5 -262.5q0 -62 -13.5 -111t-48 -105.5t-45.5 -89t-11 -71.5q0 -44 32.5 -86t121.5 -116t129.5 -142.5t40.5 -143.5q0 -171 -108.5 -263.5t-306.5 -92.5q-80 0 -165.5 19.5t-123.5 44.5l49 195 q45 -28 108.5 -46.5t117.5 -18.5q97 0 142 43t45 110q0 49 -35 94.5t-122 113.5t-127.5 136t-40.5 148q0 88 63 188.5t63 177.5q0 81 -46 129.5t-126 48.5q-184 0 -188 -247v-1116z"/> +<glyph glyph-name="ae" horiz-adv-x="1729" unicode="æ" d="M1254 -20q-253 0 -393 161q-65 -77 -172 -119t-241 -42q-176 0 -276 88t-100 244q0 158 119 244t352 86h191v71q0 91 -47.5 142.5t-135.5 51.5q-91 0 -148.5 -44.5t-57.5 -110.5l-242 19q0 146 126.5 238.5t323.5 92.5q223 0 334 -133q131 135 331 133q212 0 331 -129.5 t119 -364.5v-137h-695q9 -139 85 -218t210 -79q137 0 244 58l61 34l73 -166q-70 -56 -174.5 -88t-217.5 -32zM495 164q58 0 126 29.5t113 72.5v209h-196q-104 -2 -164 -49.5t-60 -117.5q0 -65 46.5 -104.5t134.5 -39.5zM1218 907q-99 0 -162.5 -69t-79.5 -196h452v30 q0 113 -54.5 174t-155.5 61z"/> +<glyph glyph-name="eth" horiz-adv-x="1191" unicode="ð" d="M834 1303q254 -265 254 -666v-82q0 -166 -63 -297.5t-177.5 -204.5t-254.5 -73q-138 0 -251 63t-176 176t-63 249q0 149 56.5 264.5t159.5 178t235 62.5q146 0 259 -91q-49 169 -175 291l-204 -135l-78 109l172 114q-126 82 -288 124l75 195q238 -50 415 -185l180 120 l78 -109zM845 663l-1 18q-32 48 -93.5 76t-139.5 28q-126 0 -195.5 -84t-69.5 -233q0 -126 70.5 -210t180.5 -84q111 0 179.5 100t68.5 273v116z"/> +<glyph glyph-name="divide" horiz-adv-x="1169" unicode="÷" d="M1079 582h-1012v212h1012v-212zM576 1228q68 0 105 -38t37 -95t-37 -94.5t-105 -37.5q-67 0 -104 37.5t-37 94.5t37 95t104 38zM435 278q0 58 37 96t104 38q68 0 105 -38t37 -96q0 -57 -37 -94t-105 -37q-67 0 -104 37t-37 94z"/> +<glyph glyph-name="oslash" horiz-adv-x="1160" unicode="ø" d="M79 551q0 159 63 286.5t177 196t262 68.5q106 0 194 -34l71 143h145l-102 -208q196 -153 196 -473q0 -160 -61.5 -286t-176 -195t-264.5 -69q-93 0 -183 30l-72 -147h-145l102 207q-206 150 -206 481zM322 530q0 -156 64 -254l299 609q-47 22 -104 22q-119 0 -189 -94.5 t-70 -282.5zM843 551q0 148 -58 241l-296 -601q43 -17 94 -17q123 0 191.5 96t68.5 281z"/> +<glyph glyph-name="thorn" horiz-adv-x="1175" unicode="þ" d="M1079 530q0 -247 -113.5 -398.5t-307.5 -151.5q-178 0 -285 117v-513h-243v1952h243v-553q106 119 282 119q197 0 310.5 -147t113.5 -409v-16zM836 551q0 166 -65.5 259t-183.5 93q-149 0 -214 -123v-480q66 -126 216 -126q116 0 181.5 93.5t65.5 283.5z"/> +<glyph glyph-name="dotlessi" horiz-adv-x="538" unicode="ı" d="M386 0h-243v1082h243v-1082z"/> +<glyph glyph-name="OE" horiz-adv-x="1972" unicode="Å’" d="M1837 0h-867q-167 -20 -288 -20q-167 0 -299.5 73.5t-206.5 208t-76 304.5v314q0 172 72.5 309t206 212t301.5 75q123 0 290 -20h860v-204h-692v-402h598v-200h-598v-448h699v-202zM682 174q99 0 203 13v1080q-114 14 -205 14q-161 0 -248.5 -103.5t-88.5 -291.5v-310 q0 -193 89 -297.5t250 -104.5z"/> +<glyph glyph-name="oe" horiz-adv-x="1850" unicode="Å“" d="M91 551q0 248 135.5 399.5t359.5 151.5q249 0 383 -177q65 84 156.5 131t200.5 46q214 0 333 -129.5t119 -365.5v-136h-682q11 -139 83.5 -218t189.5 -79q89 0 160.5 21t142.5 71l79 -158q-71 -63 -173.5 -95.5t-222.5 -32.5q-247 0 -387 174q-134 -174 -380 -174 q-227 0 -362 150.5t-135 408.5v12zM333 530q0 -170 67 -263t188 -93q119 0 186 92.5t67 284.5q0 166 -67.5 261t-187.5 95q-117 0 -185 -93t-68 -284zM1326 907q-85 0 -145 -68.5t-80 -189.5h437v25q0 111 -56.5 172t-155.5 61z"/> +<glyph glyph-name="circumflex" horiz-adv-x="998" unicode="ˆ" d="M835 1259v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="ring" horiz-adv-x="690" unicode="Ëš" d="M342 1578q93 0 157 -61.5t64 -146.5t-62.5 -145t-158.5 -60q-97 0 -159.5 60t-62.5 145t63.5 146.5t158.5 61.5zM230 1370q0 -47 33 -79.5t79 -32.5q47 0 79.5 32t32.5 80q0 46 -31.5 79.5t-80.5 33.5t-80.5 -33.5t-31.5 -79.5z"/> +<glyph glyph-name="tilde" horiz-adv-x="984" unicode="Ëœ" d="M855 1513q0 -110 -63.5 -183t-159.5 -73q-39 0 -67.5 8.5t-81 38.5t-74 36t-47.5 6q-38 0 -64.5 -28.5t-26.5 -74.5l-149 8q0 110 63.5 185t158.5 75q57 0 137.5 -45t132.5 -45q38 0 65 28.5t27 75.5z"/> +<glyph glyph-name="endash" horiz-adv-x="1321" unicode="–" d="M1176.41 621h-1018.81v196h1018.81v-196z"/> +<glyph glyph-name="emdash" horiz-adv-x="1584" unicode="—" d="M1488.18 621h-1358.38v196h1358.38v-196z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="448" unicode="‘" d="M282 1562l124 -77q-91 -133 -94 -277v-152h-213v138q1 96 52.5 200.5t130.5 167.5z"/> +<glyph glyph-name="quoteright" horiz-adv-x="444" unicode="’" d="M175 1024l-124 77q90 131 93 277v158h213v-138q0 -103 -52.5 -207.5t-129.5 -166.5z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="462" unicode="‚" d="M173 -298l-123 78q85 127 88 275v147h218v-133q-1 -93 -52 -197t-131 -170z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="788" unicode="“" d="M291 1562l124 -77q-91 -133 -94 -277v-152h-213v138q1 96 52.5 200.5t130.5 167.5zM627 1562l124 -77q-91 -133 -94 -277v-152h-213v138q1 96 52.5 200.5t130.5 167.5z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="795" unicode="â€" d="M188 1024l-124 77q90 131 93 277v158h213v-138q0 -103 -52.5 -207.5t-129.5 -166.5zM522 1024l-124 77q90 131 93 277v158h213v-138q0 -103 -52.5 -207.5t-129.5 -166.5z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="776" unicode="„" d="M177 -318l-127 78q85 137 88 294v201h218v-186q-1 -108 -56 -222q-49 -100 -123 -165zM499 -318l-127 78q88 142 92 292v203h218v-182q0 -99 -51 -209.5t-132 -181.5z"/> +<glyph glyph-name="bullet" horiz-adv-x="715" unicode="•" d="M136 771q0 95 60.5 155.5t160.5 60.5q103 0 163 -60.5t60 -158.5v-37q0 -94 -59.5 -153.5t-162.5 -59.5q-99 0 -159.5 57.5t-62.5 150.5v45z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="626" unicode="‹" d="M316 537l247 -399h-167l-288 390v19l288 390h167z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="617" unicode="›" d="M251 937l288 -390v-19l-288 -390h-167l247 399l-247 400h167z"/> +<glyph glyph-name="fraction" horiz-adv-x="924" unicode="â„" d="M170 109l-125 72l711 1138l125 -72z"/> +<glyph glyph-name="uni2074" horiz-adv-x="758" unicode="â´" d="M607 973h95v-151h-95v-163h-187v163h-358l-9 121l365 505h189v-475zM234 973h186v242l-14 -22z"/> +<glyph glyph-name="Euro" d="M874 527h-356q6 -174 87.5 -260t233.5 -86q110 0 205 33l28 -204q-120 -29 -248 -29q-256 0 -403 144t-155 402h-172v141h172v128h-172v141h173q13 255 163 396.5t403 141.5q106 0 239 -31l-28 -205q-102 34 -203 34q-151 0 -232 -86t-90 -250h355v-141h-356v-128h356 v-141z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1155" unicode="−" d="M1007 621h-849v196h849v-196z"/> +<glyph glyph-name="glyph162" d="M514 0h-185v570l-201 -48v146l367 119h19v-787z" horiz-adv-x="758"/> +<glyph glyph-name="glyph163" d="M690 0h-612v125l285 261q113 103 113 170q0 42 -27 68.5t-79 26.5q-58 0 -91 -33t-33 -87h-186q0 116 84.5 192.5t219.5 76.5q143 0 221 -64t78 -179q0 -107 -106 -209l-98 -87l-140 -113h371v-148z" horiz-adv-x="758"/> +<glyph glyph-name="glyph164" d="M268 466h81q132 0 132 97q0 35 -27 61.5t-89 26.5q-48 0 -80.5 -19.5t-32.5 -54.5h-186q0 99 82.5 161t212.5 62q143 0 224.5 -60.5t81.5 -165.5q0 -119 -135 -170q149 -41 149 -183q0 -106 -88.5 -169t-231.5 -63q-135 0 -220.5 63.5t-85.5 176.5h186q0 -38 34.5 -64.5 t94.5 -26.5q63 0 93.5 27.5t30.5 69.5q0 101 -134 102h-92v129z" horiz-adv-x="758"/> +<glyph glyph-name="glyph165" d="M607 314h95v-151h-95v-163h-187v163h-358l-9 121l365 505h189v-475zM234 314h186v242l-14 -22z" horiz-adv-x="758"/> +<glyph glyph-name="uni00A0" horiz-adv-x="510" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="672" unicode="Â" d="M596 521h-525v196h525v-196z"/> +<glyph glyph-name="Eth" horiz-adv-x="1368" unicode="Ã" d="M178 0v652h-187v170h187v634h430q193 0 342.5 -86t231.5 -244t82 -362v-73q0 -207 -82.5 -364t-235 -242t-349.5 -85h-419zM660 652h-229v-450h163q203 0 309.5 126.5t106.5 366.5v70q0 237 -103 362t-299 125h-177v-430h229v-170z"/> +<glyph glyph-name="Agrave" horiz-adv-x="1363" unicode="À" d="M963 339h-564l-118 -339h-263l550 1456h227l551 -1456h-264zM470 543h422l-211 604zM812 1543h-202l-270 303h277z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1363" unicode="Ã" d="M963 339h-564l-118 -339h-263l550 1456h227l551 -1456h-264zM470 543h422l-211 604zM757 1846h277l-277 -303h-195z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1363" unicode="Â" d="M963 339h-564l-118 -339h-263l550 1456h227l551 -1456h-264zM470 543h422l-211 604zM1030 1569v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1363" unicode="Ã" d="M963 339h-564l-118 -339h-263l550 1456h227l551 -1456h-264zM470 543h422l-211 604zM1052 1824q0 -110 -63.5 -183t-159.5 -73q-39 0 -67.5 8.5t-81 38.5t-74 36t-47.5 6q-38 0 -64.5 -28.5t-26.5 -74.5l-149 8q0 110 63.5 185t158.5 75q57 0 137.5 -45t132.5 -45 q38 0 65 28.5t27 75.5z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1363" unicode="Ä" d="M963 339h-564l-118 -339h-263l550 1456h227l551 -1456h-264zM470 543h422l-211 604zM331 1676q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM787 1675q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="Aring" horiz-adv-x="1363" unicode="Ã…" d="M963 339h-564l-118 -339h-263l550 1456h227l551 -1456h-264zM470 543h422l-211 604zM686 1940q93 0 157 -61.5t64 -146.5t-62.5 -145t-158.5 -60q-97 0 -159.5 60t-62.5 145t63.5 146.5t158.5 61.5zM574 1732q0 -47 33 -79.5t79 -32.5q47 0 79.5 32t32.5 80 q0 46 -31.5 79.5t-80.5 33.5t-80.5 -33.5t-31.5 -79.5z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1337" unicode="Ç" d="M1259 474q-22 -233 -172 -363.5t-399 -130.5q-174 0 -306.5 82.5t-204.5 234.5t-75 353v136q0 206 73 363t209.5 242t315.5 85q241 0 388 -131t171 -370h-252q-18 157 -91.5 226.5t-215.5 69.5q-165 0 -253.5 -120.5t-90.5 -353.5v-129q0 -236 84.5 -360t247.5 -124 q149 0 224 67t95 223h252zM775 -2l-11 -54q150 -27 150 -173q0 -105 -86 -164t-241 -59l-7 137q66 0 101.5 23.5t35.5 65.5q0 45 -35.5 62.5t-115.5 22.5l32 139h177z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1158" unicode="È" d="M999 650h-598v-448h699v-202h-952v1456h945v-204h-692v-402h598v-200zM753 1550h-202l-270 303h277z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1158" unicode="É" d="M999 650h-598v-448h699v-202h-952v1456h945v-204h-692v-402h598v-200zM698 1853h277l-277 -303h-195z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1158" unicode="Ê" d="M999 650h-598v-448h699v-202h-952v1456h945v-204h-692v-402h598v-200zM971 1576v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1158" unicode="Ë" d="M999 650h-598v-448h699v-202h-952v1456h945v-204h-692v-402h598v-200zM272 1683q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM728 1682q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="Igrave" horiz-adv-x="578" unicode="ÃŒ" d="M415 0h-252v1456h252v-1456zM416 1550h-202l-270 303h277z"/> +<glyph glyph-name="Iacute" horiz-adv-x="578" unicode="Ã" d="M415 0h-252v1456h252v-1456zM360 1853h277l-277 -303h-195z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="578" unicode="ÃŽ" d="M415 0h-252v1456h252v-1456zM634 1576v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="578" unicode="Ã" d="M415 0h-252v1456h252v-1456zM-65 1683q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM391 1682q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1454" unicode="Ñ" d="M1303 0h-253l-649 1033v-1033h-253v1456h253l651 -1037v1037h251v-1456zM1093 1824q0 -110 -63.5 -183t-159.5 -73q-39 0 -67.5 8.5t-81 38.5t-74 36t-47.5 6q-38 0 -64.5 -28.5t-26.5 -74.5l-149 8q0 110 63.5 185t158.5 75q57 0 137.5 -45t132.5 -45q38 0 65 28.5 t27 75.5z"/> +<glyph glyph-name="Ograve" horiz-adv-x="1414" unicode="Ã’" d="M1310 690q0 -214 -74 -375.5t-211.5 -248t-316.5 -86.5q-177 0 -315.5 86.5t-214 246.5t-76.5 369v82q0 213 75.5 376t213 249.5t315.5 86.5t315.5 -85.5t212.5 -246t76 -373.5v-81zM1057 766q0 242 -91.5 371t-259.5 129q-164 0 -256.5 -128.5t-94.5 -363.5v-84 q0 -240 93.5 -371t259.5 -131q168 0 258.5 128t90.5 374v76zM835 1543h-202l-270 303h277z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1414" unicode="Ó" d="M1310 690q0 -214 -74 -375.5t-211.5 -248t-316.5 -86.5q-177 0 -315.5 86.5t-214 246.5t-76.5 369v82q0 213 75.5 376t213 249.5t315.5 86.5t315.5 -85.5t212.5 -246t76 -373.5v-81zM1057 766q0 242 -91.5 371t-259.5 129q-164 0 -256.5 -128.5t-94.5 -363.5v-84 q0 -240 93.5 -371t259.5 -131q168 0 258.5 128t90.5 374v76zM780 1846h277l-277 -303h-195z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1414" unicode="Ô" d="M1310 690q0 -214 -74 -375.5t-211.5 -248t-316.5 -86.5q-177 0 -315.5 86.5t-214 246.5t-76.5 369v82q0 213 75.5 376t213 249.5t315.5 86.5t315.5 -85.5t212.5 -246t76 -373.5v-81zM1057 766q0 242 -91.5 371t-259.5 129q-164 0 -256.5 -128.5t-94.5 -363.5v-84 q0 -240 93.5 -371t259.5 -131q168 0 258.5 128t90.5 374v76zM1053 1569v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1414" unicode="Õ" d="M1310 690q0 -214 -74 -375.5t-211.5 -248t-316.5 -86.5q-177 0 -315.5 86.5t-214 246.5t-76.5 369v82q0 213 75.5 376t213 249.5t315.5 86.5t315.5 -85.5t212.5 -246t76 -373.5v-81zM1057 766q0 242 -91.5 371t-259.5 129q-164 0 -256.5 -128.5t-94.5 -363.5v-84 q0 -240 93.5 -371t259.5 -131q168 0 258.5 128t90.5 374v76zM1075 1824q0 -110 -63.5 -183t-159.5 -73q-39 0 -67.5 8.5t-81 38.5t-74 36t-47.5 6q-38 0 -64.5 -28.5t-26.5 -74.5l-149 8q0 110 63.5 185t158.5 75q57 0 137.5 -45t132.5 -45q38 0 65 28.5t27 75.5z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1414" unicode="Ö" d="M1310 690q0 -214 -74 -375.5t-211.5 -248t-316.5 -86.5q-177 0 -315.5 86.5t-214 246.5t-76.5 369v82q0 213 75.5 376t213 249.5t315.5 86.5t315.5 -85.5t212.5 -246t76 -373.5v-81zM1057 766q0 242 -91.5 371t-259.5 129q-164 0 -256.5 -128.5t-94.5 -363.5v-84 q0 -240 93.5 -371t259.5 -131q168 0 258.5 128t90.5 374v76zM354 1676q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM810 1675q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1335" unicode="Ù" d="M1213 1456v-973q0 -232 -148.5 -367.5t-395.5 -135.5q-250 0 -397 133.5t-147 370.5v972h252v-974q0 -146 74 -223t218 -77q292 0 292 308v966h252zM794 1543h-202l-270 303h277z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1335" unicode="Ú" d="M1213 1456v-973q0 -232 -148.5 -367.5t-395.5 -135.5q-250 0 -397 133.5t-147 370.5v972h252v-974q0 -146 74 -223t218 -77q292 0 292 308v966h252zM739 1846h277l-277 -303h-195z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1335" unicode="Û" d="M1213 1456v-973q0 -232 -148.5 -367.5t-395.5 -135.5q-250 0 -397 133.5t-147 370.5v972h252v-974q0 -146 74 -223t218 -77q292 0 292 308v966h252zM1012 1569v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="Udieresis" horiz-adv-x="1335" unicode="Ü" d="M1213 1456v-973q0 -232 -148.5 -367.5t-395.5 -135.5q-250 0 -397 133.5t-147 370.5v972h252v-974q0 -146 74 -223t218 -77q292 0 292 308v966h252zM313 1676q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM769 1675q0 50 34 84t93 34t93 -34 t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1248" unicode="Ã" d="M623 766l335 690h280l-488 -920v-536h-254v536l-489 920h281zM698 1846h277l-277 -303h-195z"/> +<glyph glyph-name="agrave" horiz-adv-x="1108" unicode="à " d="M771 0q-16 31 -28 101q-116 -121 -284 -121q-163 0 -266 93t-103 230q0 173 128.5 265.5t367.5 92.5h149v71q0 84 -47 134.5t-143 50.5q-83 0 -136 -41.5t-53 -105.5h-243q0 89 59 166.5t160.5 121.5t226.5 44q190 0 303 -95.5t116 -268.5v-488q0 -146 41 -233v-17h-248z M504 175q72 0 135.5 35t95.5 94v204h-131q-135 0 -203 -47t-68 -133q0 -70 46.5 -111.5t124.5 -41.5zM694 1233h-202l-270 303h277z"/> +<glyph glyph-name="aacute" horiz-adv-x="1108" unicode="á" d="M771 0q-16 31 -28 101q-116 -121 -284 -121q-163 0 -266 93t-103 230q0 173 128.5 265.5t367.5 92.5h149v71q0 84 -47 134.5t-143 50.5q-83 0 -136 -41.5t-53 -105.5h-243q0 89 59 166.5t160.5 121.5t226.5 44q190 0 303 -95.5t116 -268.5v-488q0 -146 41 -233v-17h-248z M504 175q72 0 135.5 35t95.5 94v204h-131q-135 0 -203 -47t-68 -133q0 -70 46.5 -111.5t124.5 -41.5zM639 1536h277l-277 -303h-195z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1108" unicode="â" d="M771 0q-16 31 -28 101q-116 -121 -284 -121q-163 0 -266 93t-103 230q0 173 128.5 265.5t367.5 92.5h149v71q0 84 -47 134.5t-143 50.5q-83 0 -136 -41.5t-53 -105.5h-243q0 89 59 166.5t160.5 121.5t226.5 44q190 0 303 -95.5t116 -268.5v-488q0 -146 41 -233v-17h-248z M504 175q72 0 135.5 35t95.5 94v204h-131q-135 0 -203 -47t-68 -133q0 -70 46.5 -111.5t124.5 -41.5zM912 1259v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="atilde" horiz-adv-x="1108" unicode="ã" d="M771 0q-16 31 -28 101q-116 -121 -284 -121q-163 0 -266 93t-103 230q0 173 128.5 265.5t367.5 92.5h149v71q0 84 -47 134.5t-143 50.5q-83 0 -136 -41.5t-53 -105.5h-243q0 89 59 166.5t160.5 121.5t226.5 44q190 0 303 -95.5t116 -268.5v-488q0 -146 41 -233v-17h-248z M504 175q72 0 135.5 35t95.5 94v204h-131q-135 0 -203 -47t-68 -133q0 -70 46.5 -111.5t124.5 -41.5zM934 1514q0 -110 -63.5 -183t-159.5 -73q-39 0 -67.5 8.5t-81 38.5t-74 36t-47.5 6q-38 0 -64.5 -28.5t-26.5 -74.5l-149 8q0 110 63.5 185t158.5 75q57 0 137.5 -45 t132.5 -45q38 0 65 28.5t27 75.5z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1108" unicode="ä" d="M771 0q-16 31 -28 101q-116 -121 -284 -121q-163 0 -266 93t-103 230q0 173 128.5 265.5t367.5 92.5h149v71q0 84 -47 134.5t-143 50.5q-83 0 -136 -41.5t-53 -105.5h-243q0 89 59 166.5t160.5 121.5t226.5 44q190 0 303 -95.5t116 -268.5v-488q0 -146 41 -233v-17h-248z M504 175q72 0 135.5 35t95.5 94v204h-131q-135 0 -203 -47t-68 -133q0 -70 46.5 -111.5t124.5 -41.5zM213 1366q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM669 1365q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="aring" horiz-adv-x="1108" unicode="Ã¥" d="M771 0q-16 31 -28 101q-116 -121 -284 -121q-163 0 -266 93t-103 230q0 173 128.5 265.5t367.5 92.5h149v71q0 84 -47 134.5t-143 50.5q-83 0 -136 -41.5t-53 -105.5h-243q0 89 59 166.5t160.5 121.5t226.5 44q190 0 303 -95.5t116 -268.5v-488q0 -146 41 -233v-17h-248z M504 175q72 0 135.5 35t95.5 94v204h-131q-135 0 -203 -47t-68 -133q0 -70 46.5 -111.5t124.5 -41.5zM568 1630q93 0 157 -61.5t64 -146.5t-62.5 -145t-158.5 -60q-97 0 -159.5 60t-62.5 145t63.5 146.5t158.5 61.5zM456 1422q0 -47 33 -79.5t79 -32.5q47 0 79.5 32t32.5 80 q0 46 -31.5 79.5t-80.5 33.5t-80.5 -33.5t-31.5 -79.5z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1072" unicode="ç" d="M569 174q91 0 151 53t64 131h229q-4 -101 -63 -188.5t-160 -138.5t-218 -51q-227 0 -360 147t-133 406v25q0 247 132 395.5t360 148.5q193 0 314.5 -112.5t127.5 -295.5h-229q-4 93 -63.5 153t-151.5 60q-118 0 -182 -85.5t-65 -259.5v-39q0 -176 63.5 -262.5 t183.5 -86.5zM635 -2l-11 -54q150 -27 150 -173q0 -105 -86 -164t-241 -59l-7 137q66 0 101.5 23.5t35.5 65.5q0 45 -35.5 62.5t-115.5 22.5l32 139h177z"/> +<glyph glyph-name="egrave" horiz-adv-x="1099" unicode="è" d="M601 -20q-231 0 -374.5 145.5t-143.5 387.5v30q0 162 62.5 289.5t175.5 198.5t252 71q221 0 341.5 -141t120.5 -399v-98h-707q11 -134 89.5 -212t197.5 -78q167 0 272 135l131 -125q-65 -97 -173.5 -150.5t-243.5 -53.5zM572 907q-100 0 -161.5 -70t-78.5 -195h463v18 q-8 122 -65 184.5t-158 62.5zM682 1233h-202l-270 303h277z"/> +<glyph glyph-name="eacute" horiz-adv-x="1099" unicode="é" d="M601 -20q-231 0 -374.5 145.5t-143.5 387.5v30q0 162 62.5 289.5t175.5 198.5t252 71q221 0 341.5 -141t120.5 -399v-98h-707q11 -134 89.5 -212t197.5 -78q167 0 272 135l131 -125q-65 -97 -173.5 -150.5t-243.5 -53.5zM572 907q-100 0 -161.5 -70t-78.5 -195h463v18 q-8 122 -65 184.5t-158 62.5zM627 1536h277l-277 -303h-195z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1099" unicode="ê" d="M601 -20q-231 0 -374.5 145.5t-143.5 387.5v30q0 162 62.5 289.5t175.5 198.5t252 71q221 0 341.5 -141t120.5 -399v-98h-707q11 -134 89.5 -212t197.5 -78q167 0 272 135l131 -125q-65 -97 -173.5 -150.5t-243.5 -53.5zM572 907q-100 0 -161.5 -70t-78.5 -195h463v18 q-8 122 -65 184.5t-158 62.5zM900 1259v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1099" unicode="ë" d="M601 -20q-231 0 -374.5 145.5t-143.5 387.5v30q0 162 62.5 289.5t175.5 198.5t252 71q221 0 341.5 -141t120.5 -399v-98h-707q11 -134 89.5 -212t197.5 -78q167 0 272 135l131 -125q-65 -97 -173.5 -150.5t-243.5 -53.5zM572 907q-100 0 -161.5 -70t-78.5 -195h463v18 q-8 122 -65 184.5t-158 62.5zM201 1366q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM657 1365q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="igrave" horiz-adv-x="538" unicode="ì" d="M386 0h-243v1082h243v-1082zM396 1226h-202l-270 303h277z"/> +<glyph glyph-name="iacute" horiz-adv-x="538" unicode="Ã" d="M386 0h-243v1082h243v-1082zM340 1529h277l-277 -303h-195z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="538" unicode="î" d="M386 0h-243v1082h243v-1082zM614 1252v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="idieresis" horiz-adv-x="538" unicode="ï" d="M386 0h-243v1082h243v-1082zM-85 1359q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM371 1358q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="ntilde" horiz-adv-x="1139" unicode="ñ" d="M350 1082l7 -125q120 145 315 145q338 0 344 -387v-715h-243v701q0 103 -44.5 152.5t-145.5 49.5q-147 0 -219 -133v-770h-243v1082h229zM940 1514q0 -110 -63.5 -183t-159.5 -73q-39 0 -67.5 8.5t-81 38.5t-74 36t-47.5 6q-38 0 -64.5 -28.5t-26.5 -74.5l-149 8 q0 110 63.5 185t158.5 75q57 0 137.5 -45t132.5 -45q38 0 65 28.5t27 75.5z"/> +<glyph glyph-name="ograve" horiz-adv-x="1166" unicode="ò" d="M79 551q0 159 63 286.5t177 196t262 68.5q219 0 355.5 -141t147.5 -374l1 -57q0 -160 -61.5 -286t-176 -195t-264.5 -69q-229 0 -366.5 152.5t-137.5 406.5v12zM322 530q0 -167 69 -261.5t192 -94.5t191.5 96t68.5 281q0 164 -70.5 260t-191.5 96q-119 0 -189 -94.5 t-70 -282.5zM703 1233h-202l-270 303h277z"/> +<glyph glyph-name="oacute" horiz-adv-x="1166" unicode="ó" d="M79 551q0 159 63 286.5t177 196t262 68.5q219 0 355.5 -141t147.5 -374l1 -57q0 -160 -61.5 -286t-176 -195t-264.5 -69q-229 0 -366.5 152.5t-137.5 406.5v12zM322 530q0 -167 69 -261.5t192 -94.5t191.5 96t68.5 281q0 164 -70.5 260t-191.5 96q-119 0 -189 -94.5 t-70 -282.5zM648 1536h277l-277 -303h-195z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1166" unicode="ô" d="M79 551q0 159 63 286.5t177 196t262 68.5q219 0 355.5 -141t147.5 -374l1 -57q0 -160 -61.5 -286t-176 -195t-264.5 -69q-229 0 -366.5 152.5t-137.5 406.5v12zM322 530q0 -167 69 -261.5t192 -94.5t191.5 96t68.5 281q0 164 -70.5 260t-191.5 96q-119 0 -189 -94.5 t-70 -282.5zM921 1259v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="otilde" horiz-adv-x="1166" unicode="õ" d="M79 551q0 159 63 286.5t177 196t262 68.5q219 0 355.5 -141t147.5 -374l1 -57q0 -160 -61.5 -286t-176 -195t-264.5 -69q-229 0 -366.5 152.5t-137.5 406.5v12zM322 530q0 -167 69 -261.5t192 -94.5t191.5 96t68.5 281q0 164 -70.5 260t-191.5 96q-119 0 -189 -94.5 t-70 -282.5zM943 1514q0 -110 -63.5 -183t-159.5 -73q-39 0 -67.5 8.5t-81 38.5t-74 36t-47.5 6q-38 0 -64.5 -28.5t-26.5 -74.5l-149 8q0 110 63.5 185t158.5 75q57 0 137.5 -45t132.5 -45q38 0 65 28.5t27 75.5z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1166" unicode="ö" d="M79 551q0 159 63 286.5t177 196t262 68.5q219 0 355.5 -141t147.5 -374l1 -57q0 -160 -61.5 -286t-176 -195t-264.5 -69q-229 0 -366.5 152.5t-137.5 406.5v12zM322 530q0 -167 69 -261.5t192 -94.5t191.5 96t68.5 281q0 164 -70.5 260t-191.5 96q-119 0 -189 -94.5 t-70 -282.5zM222 1366q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM678 1365q0 50 34 84t93 34t93 -34t34 -84t-34 -84t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="ugrave" horiz-adv-x="1138" unicode="ù" d="M780 106q-107 -126 -304 -126q-176 0 -266.5 103t-90.5 298v701h243v-698q0 -206 171 -206q177 0 239 127v777h243v-1082h-229zM696 1233h-202l-270 303h277z"/> +<glyph glyph-name="uacute" horiz-adv-x="1138" unicode="ú" d="M780 106q-107 -126 -304 -126q-176 0 -266.5 103t-90.5 298v701h243v-698q0 -206 171 -206q177 0 239 127v777h243v-1082h-229zM641 1536h277l-277 -303h-195z"/> +<glyph glyph-name="ucircumflex" horiz-adv-x="1138" unicode="û" d="M780 106q-107 -126 -304 -126q-176 0 -266.5 103t-90.5 298v701h243v-698q0 -206 171 -206q177 0 239 127v777h243v-1082h-229zM914 1259v-11h-195l-150 156l-149 -156h-193v13l271 276h143z"/> +<glyph glyph-name="udieresis" horiz-adv-x="1138" unicode="ü" d="M780 106q-107 -126 -304 -126q-176 0 -266.5 103t-90.5 298v701h243v-698q0 -206 171 -206q177 0 239 127v777h243v-1082h-229zM215 1366q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM671 1365q0 50 34 84t93 34t93 -34t34 -84t-34 -84 t-93 -34t-93 34t-34 84z"/> +<glyph glyph-name="yacute" horiz-adv-x="997" unicode="ý" d="M503 348l220 734h259l-430 -1246q-99 -273 -336 -273q-53 0 -117 18v188l46 -3q92 0 138.5 33.5t73.5 112.5l35 93l-380 1077h262zM585 1536h277l-277 -303h-195z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="997" unicode="ÿ" d="M503 348l220 734h259l-430 -1246q-99 -273 -336 -273q-53 0 -117 18v188l46 -3q92 0 138.5 33.5t73.5 112.5l35 93l-380 1077h262zM159 1366q0 50 33.5 84t92.5 34t93 -34t34 -84t-34 -84t-93 -34t-92.5 34t-33.5 84zM615 1365q0 50 34 84t93 34t93 -34t34 -84t-34 -84 t-93 -34t-93 34t-34 84z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.ttf b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..47aa32f9938e003a064484344342d4df082c670f Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff new file mode 100644 index 0000000000000000000000000000000000000000..cd66cbf142ee7f7418eaa5bf9647a9b439c6ab7e Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff2 b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..064aec39e602232ced6be6e142334c6212c1750f Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Medium/RobotoDraft-Medium.woff2 differ diff --git a/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.eot b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..90e4fb81a5219c723aa73bb69187ff86ab9460f4 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.svg b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.svg new file mode 100644 index 0000000000000000000000000000000000000000..0eee1c6a016ecd41cbe958bc99d26af8fb5d81cf --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.svg @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-Regular" horiz-adv-x="1150"> +<font-face underline-position="-100" font-weight="400" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-68 -495 1879 1937" x-height="1082" underline-thickness="100" font-family="RobotoDraft" ascent="1536" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1134" unicode="fi" d="M202 0v939h-171v143h171v92q0 181 103.5 282t292.5 101q112 0 283 -61l-31 -156q-125 50 -238 50q-119 0 -171.5 -53.5t-52.5 -160.5v-94h221v-143h-221v-939h-186zM973 0h-186v1082h186v-1082z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1163" unicode="fl" d="M816 1379q-124 20 -200 20q-200 0 -200 -210v-107h231v-143h-231v-939h-185v939h-171v143h171v118q1 173 97 265t273 92q101 0 400 -61v-1496h-185v1379z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="uni0000" horiz-adv-x="0"/> +<glyph glyph-name="glyph2" horiz-adv-x="0"/> +<glyph glyph-name="uni000D" horiz-adv-x="507" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="507" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="527" unicode="!" d="M347 411h-167l-13 1045h194zM160 93q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -74.5t-82 -29.5t-81.5 29.5t-27.5 74.5z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="655" unicode='"' d="M277 1400l-30 -358h-111l1 494h140v-136zM547 1400l-30 -358h-111l1 494h140v-136z"/> +<glyph glyph-name="numbersign" horiz-adv-x="1261" unicode="#" d="M765 410h-264l-80 -410h-143l80 410h-239v137h265l69 354h-258v139h285l82 416h143l-82 -416h264l82 416h144l-82 -416h204v-139h-231l-69 -354h225v-137h-251l-80 -410h-144zM527 547h264l69 354h-264z"/> +<glyph glyph-name="dollar" d="M856 375q0 92 -64.5 155t-217.5 114q-213 65 -310.5 169.5t-97.5 265.5q0 164 95.5 269t262.5 125v219h149v-220q168 -23 261.5 -141t93.5 -323h-184q0 141 -67 224t-181 83q-119 0 -182 -61.5t-63 -171.5q0 -102 66.5 -162.5t219 -110t238 -109t126 -138.5t40.5 -185 q0 -169 -101.5 -272t-284.5 -122v-191h-148v191q-186 17 -291.5 132.5t-105.5 313.5h185q0 -139 73 -214t207 -75q131 0 206 63t75 172z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1500" unicode="%" d="M105 1176q0 131 83.5 216t214.5 85q133 0 215.5 -85.5t82.5 -221.5v-71q0 -132 -83.5 -215.5t-212.5 -83.5q-130 0 -215 83.5t-85 222.5v70zM243 1099q0 -78 44 -128.5t118 -50.5q71 0 114.5 49t43.5 134v73q0 78 -43 129t-117 51t-117 -51t-43 -133v-73zM814 357 q0 131 83.5 215.5t214.5 84.5t215 -84t84 -223v-71q0 -131 -83.5 -215.5t-213.5 -84.5t-215 83.5t-85 222.5v72zM952 279q0 -79 44 -129.5t118 -50.5q72 0 115 49.5t43 134.5v74q0 79 -43.5 129t-116.5 50q-71 0 -115.5 -49.5t-44.5 -133.5v-74zM447 110l-105 66l711 1138 l105 -66z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1273" unicode="&" d="M101 391q0 105 58.5 193t223.5 205q-97 118 -130 190t-33 143q0 166 98 260t266 94q150 0 248 -87.5t98 -220.5q0 -88 -44.5 -162.5t-155.5 -156.5l-107 -79l324 -387q68 130 68 289h167q0 -255 -123 -423l208 -249h-222l-97 115q-74 -66 -173.5 -100.5t-202.5 -34.5 q-213 0 -342 113t-129 298zM572 131q147 0 269 112l-355 425l-33 -24q-167 -123 -167 -253q0 -118 76.5 -189t209.5 -71zM405 1128q0 -96 118 -240l118 83q68 48 93 91.5t25 105.5q0 67 -50 111.5t-126 44.5q-82 0 -130 -55.5t-48 -140.5z"/> +<glyph glyph-name="quotesingle" horiz-adv-x="357" unicode="'" d="M253 1425l-21 -368h-129l1 479h149v-111z"/> +<glyph glyph-name="parenleft" horiz-adv-x="700" unicode="(" d="M133 591q0 226 60.5 434t180.5 378t249 240l38 -122q-146 -112 -239.5 -342t-102.5 -515l-1 -85q0 -386 141 -670q85 -170 202 -266l-38 -113q-133 74 -254 248q-236 340 -236 813z"/> +<glyph glyph-name="parenright" horiz-adv-x="712" unicode=")" d="M567 581q0 -223 -58.5 -427.5t-179 -377.5t-252.5 -246l-39 113q154 118 247.5 366.5t95.5 551.5v32q0 210 -44 390.5t-122.5 323.5t-176.5 223l39 113q132 -73 251.5 -244t179 -377t59.5 -441z"/> +<glyph glyph-name="asterisk" horiz-adv-x="882" unicode="*" d="M330 983l-302 90l46 151l302 -112l-9 344h153l-10 -349l297 110l46 -152l-307 -91l198 -271l-124 -94l-186 288l-180 -281l-125 91z"/> +<glyph glyph-name="plus" horiz-adv-x="1161" unicode="+" d="M670 781h406v-175h-406v-460h-186v460h-406v175h406v425h186v-425z"/> +<glyph glyph-name="comma" horiz-adv-x="402" unicode="," d="M134 -290l-105 72q94 131 98 270v167h181v-145q0 -101 -49.5 -202t-124.5 -162z"/> +<glyph glyph-name="hyphen" horiz-adv-x="565" unicode="-" d="M525 543h-488v151h488v-151z"/> +<glyph glyph-name="period" horiz-adv-x="539" unicode="." d="M144 97q0 48 28.5 80t85.5 32t86.5 -32t29.5 -80q0 -46 -29.5 -77t-86.5 -31t-85.5 31t-28.5 77z"/> +<glyph glyph-name="slash" horiz-adv-x="844" unicode="/" d="M177 -125h-159l608 1581h158z"/> +<glyph glyph-name="zero" d="M1034 621q0 -325 -111 -483t-347 -158q-233 0 -345 154.5t-116 461.5v247q0 321 111 477t348 156q235 0 346 -150.5t114 -464.5v-240zM849 874q0 235 -66 342.5t-209 107.5q-142 0 -207 -107t-67 -329v-296q0 -236 68.5 -348.5t207.5 -112.5q137 0 203.5 106t69.5 334 v303z" unicode="0"/> +<glyph glyph-name="one" d="M729 0h-186v1233l-373 -137v168l530 199h29v-1463z" unicode="1"/> +<glyph glyph-name="two" d="M1075 0h-954v133l504 560q112 127 154.5 206.5t42.5 164.5q0 114 -69 187t-184 73q-138 0 -214.5 -78.5t-76.5 -218.5h-185q0 201 129.5 325t346.5 124q203 0 321 -106.5t118 -283.5q0 -215 -274 -512l-390 -423h731v-151z" unicode="2"/> +<glyph glyph-name="three" d="M390 818h139q131 2 206 69t75 181q0 256 -255 256q-120 0 -191.5 -68.5t-71.5 -181.5h-185q0 173 126.5 287.5t321.5 114.5q206 0 323 -109t117 -303q0 -95 -61.5 -184t-167.5 -133q120 -38 185.5 -126t65.5 -215q0 -196 -128 -311t-333 -115t-333.5 111t-128.5 293h186 q0 -115 75 -184t201 -69q134 0 205 70t71 201q0 127 -78 195t-225 70h-139v151z" unicode="3"/> +<glyph glyph-name="four" d="M902 489h202v-151h-202v-338h-186v338h-663v109l652 1009h197v-967zM263 489h453v714l-22 -40z" unicode="4"/> +<glyph glyph-name="five" d="M206 730l74 726h746v-171h-589l-44 -397q107 63 243 63q199 0 316 -131.5t117 -355.5q0 -225 -121.5 -354.5t-339.5 -129.5q-193 0 -315 107t-139 296h175q17 -125 89 -188.5t190 -63.5q129 0 202.5 88t73.5 243q0 146 -79.5 234.5t-211.5 88.5q-121 0 -190 -53l-49 -40z " unicode="5"/> +<glyph glyph-name="six" d="M847 1457v-157h-34q-216 -4 -344 -128t-148 -349q115 132 314 132q190 0 303.5 -134t113.5 -346q0 -225 -122.5 -360t-328.5 -135q-209 0 -339 160.5t-130 413.5v71q0 402 171.5 614.5t510.5 217.5h33zM604 801q-95 0 -175 -57t-111 -143v-68q0 -180 81 -290t202 -110 q125 0 196.5 92t71.5 241q0 150 -72.5 242.5t-192.5 92.5z" unicode="6"/> +<glyph glyph-name="seven" d="M1061 1352l-603 -1352h-194l601 1304h-788v152h984v-104z" unicode="7"/> +<glyph glyph-name="eight" d="M1004 1076q0 -109 -57.5 -194t-155.5 -133q114 -49 180.5 -143t66.5 -213q0 -189 -127.5 -301t-335.5 -112q-210 0 -336.5 112.5t-126.5 300.5q0 118 64.5 213t178.5 144q-97 48 -153 133t-56 193q0 184 118 292t311 108q192 0 310.5 -108t118.5 -292zM853 397 q0 122 -77.5 199t-202.5 77t-200.5 -76t-75.5 -200t73.5 -195t204.5 -71q130 0 204 71.5t74 194.5zM575 1324q-109 0 -176.5 -67.5t-67.5 -183.5q0 -111 66.5 -179.5t177.5 -68.5t177.5 68.5t66.5 179.5t-69 181t-175 70z" unicode="8"/> +<glyph glyph-name="nine" d="M830 640q-58 -69 -138.5 -111t-176.5 -42q-126 0 -219.5 62t-144.5 174.5t-51 248.5q0 146 55.5 263t157.5 179t238 62q216 0 340.5 -161.5t124.5 -440.5v-54q0 -425 -168 -620.5t-507 -200.5h-36v156h39q229 4 352 119.5t134 365.5zM545 640q93 0 171.5 57t114.5 141v74 q0 182 -79 296t-200 114q-122 0 -196 -93.5t-74 -246.5q0 -149 71.5 -245.5t191.5 -96.5z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="496" unicode=":" d="M134 97q0 48 28.5 80t85.5 32t86.5 -32t29.5 -80q0 -46 -29.5 -77t-86.5 -31t-85.5 31t-28.5 77zM135 980q0 48 28.5 80t85.5 32t86.5 -32t29.5 -80q0 -46 -29.5 -77t-86.5 -31t-85.5 31t-28.5 77z"/> +<glyph glyph-name="semicolon" horiz-adv-x="433" unicode=";" d="M111 980q0 48 28.5 80t85.5 32t86.5 -32t29.5 -80q0 -46 -29.5 -77t-86.5 -31t-85.5 31t-28.5 77zM146 -290l-105 72q94 131 98 270v167h181v-145q0 -101 -49.5 -202t-124.5 -162z"/> +<glyph glyph-name="less" horiz-adv-x="1041" unicode="<" d="M264 644l626 -253v-196l-818 379v146l818 378v-196z"/> +<glyph glyph-name="equal" horiz-adv-x="1124" unicode="=" d="M986 814h-834v161h834v-161zM986 399h-834v160h834v-160z"/> +<glyph glyph-name="greater" horiz-adv-x="1070" unicode=">" d="M795 650l-661 259v190l854 -378v-146l-854 -379v192z"/> +<glyph glyph-name="question" horiz-adv-x="967" unicode="?" d="M357 410q2 119 27 188t102 153l131 135q84 95 84 204q0 105 -55 164.5t-160 59.5q-102 0 -164 -54t-62 -145h-185q2 162 115.5 261.5t295.5 99.5q189 0 294.5 -101.5t105.5 -278.5q0 -175 -162 -345l-109 -108q-73 -81 -73 -233h-185zM349 93q0 45 27.5 75.5t81.5 30.5 t82 -30.5t28 -75.5t-28 -74.5t-82 -29.5t-81.5 29.5t-27.5 74.5z"/> +<glyph glyph-name="at" horiz-adv-x="1839" unicode="@" d="M1738 502q-12 -242 -120 -382t-289 -140q-187 0 -240 168q-54 -85 -123.5 -126.5t-143.5 -41.5q-142 0 -215 116t-54 321q15 165 75.5 294.5t156 203.5t200.5 74q81 0 145 -21.5t144 -84.5l-52 -554q-19 -231 128 -231q113 0 183 112t76 292q19 389 -144.5 593 t-497.5 204q-201 0 -357 -99.5t-246 -287.5t-101 -434q-12 -248 60 -430.5t219.5 -279t356.5 -96.5q90 0 180.5 22t150.5 57l37 -115q-62 -39 -164.5 -64t-207.5 -25q-250 0 -430 112.5t-269.5 324t-77.5 494.5q12 275 123 494.5t301 339t429 119.5q249 0 427 -112t265 -323 t75 -494zM712 417q-14 -142 26.5 -218t128.5 -76q60 0 115.5 51t91.5 146l1 9l46 503q-56 29 -120 29q-117 0 -193.5 -119t-95.5 -325z"/> +<glyph glyph-name="A" horiz-adv-x="1336" unicode="A" d="M973 380h-610l-137 -380h-198l556 1456h168l557 -1456h-197zM421 538h495l-248 681z"/> +<glyph glyph-name="B" horiz-adv-x="1275" unicode="B" d="M169 0v1456h476q237 0 356.5 -98t119.5 -290q0 -102 -58 -180.5t-158 -121.5q118 -33 186.5 -125.5t68.5 -220.5q0 -196 -127 -308t-359 -112h-505zM361 681v-524h317q134 0 211.5 69.5t77.5 191.5q0 263 -286 263h-320zM361 835h290q126 0 201.5 63t75.5 171 q0 120 -70 174.5t-213 54.5h-284v-463z"/> +<glyph glyph-name="C" horiz-adv-x="1333" unicode="C" d="M1240 462q-27 -231 -170.5 -356.5t-381.5 -125.5q-258 0 -413.5 185t-155.5 495v140q0 203 72.5 357t205.5 236.5t308 82.5q232 0 372 -129.5t163 -358.5h-193q-25 174 -108.5 252t-233.5 78q-184 0 -288.5 -136t-104.5 -387v-141q0 -237 99 -377t277 -140 q160 0 245.5 72.5t113.5 252.5h193z"/> +<glyph glyph-name="D" horiz-adv-x="1343" unicode="D" d="M169 0v1456h411q190 0 336 -84t225.5 -239t80.5 -356v-93q0 -206 -79.5 -361t-227 -238t-343.5 -85h-403zM361 1298v-1141h202q222 0 345.5 138t123.5 393v85q0 248 -116.5 385.5t-330.5 139.5h-224z"/> +<glyph glyph-name="E" horiz-adv-x="1164" unicode="E" d="M992 673h-631v-516h733v-157h-925v1456h915v-158h-723v-468h631v-157z"/> +<glyph glyph-name="F" horiz-adv-x="1132" unicode="F" d="M972 643h-611v-643h-192v1456h902v-158h-710v-498h611v-157z"/> +<glyph glyph-name="G" horiz-adv-x="1395" unicode="G" d="M1244 191q-74 -106 -206.5 -158.5t-308.5 -52.5q-178 0 -316 83.5t-213.5 237.5t-77.5 357v127q0 329 153.5 510t431.5 181q228 0 367 -116.5t170 -330.5h-192q-54 289 -344 289q-193 0 -292.5 -135.5t-100.5 -392.5v-119q0 -245 112 -389.5t303 -144.5q108 0 189 24 t134 81v327h-337v156h528v-534z"/> +<glyph glyph-name="H" horiz-adv-x="1460" unicode="H" d="M1288 0h-193v673h-734v-673h-192v1456h192v-626h734v626h193v-1456z"/> +<glyph glyph-name="I" horiz-adv-x="557" unicode="I" d="M375 0h-192v1456h192v-1456z"/> +<glyph glyph-name="J" horiz-adv-x="1130" unicode="J" d="M779 1456h193v-1031q0 -209 -125.5 -327t-334.5 -118q-217 0 -338 111t-121 311h192q0 -125 68.5 -195t198.5 -70q119 0 192.5 75t74.5 210v1034z"/> +<glyph glyph-name="K" horiz-adv-x="1284" unicode="K" d="M539 677l-178 -185v-492h-192v1456h192v-720l647 720h232l-573 -643l618 -813h-230z"/> +<glyph glyph-name="L" horiz-adv-x="1102" unicode="L" d="M362 157h690v-157h-883v1456h193v-1299z"/> +<glyph glyph-name="M" horiz-adv-x="1788" unicode="M" d="M417 1456l476 -1188l476 1188h249v-1456h-192v567l18 612l-478 -1179h-147l-477 1176l19 -609v-567h-192v1456h248z"/> +<glyph glyph-name="N" horiz-adv-x="1460" unicode="N" d="M1288 0h-193l-733 1122v-1122h-193v1456h193l735 -1127v1127h191v-1456z"/> +<glyph glyph-name="O" horiz-adv-x="1408" unicode="O" d="M1289 681q0 -214 -72 -373.5t-204 -243.5t-308 -84q-172 0 -305 84.5t-206.5 241t-75.5 362.5v105q0 210 73 371t206.5 246.5t305.5 85.5q175 0 308.5 -84.5t205.5 -245t72 -373.5v-92zM1098 775q0 259 -104 397.5t-291 138.5q-182 0 -286.5 -138.5t-107.5 -384.5v-107 q0 -251 105.5 -394.5t290.5 -143.5q186 0 288 135.5t105 388.5v108z"/> +<glyph glyph-name="P" horiz-adv-x="1292" unicode="P" d="M361 570v-570h-192v1456h537q239 0 374.5 -122t135.5 -323q0 -212 -132.5 -326.5t-379.5 -114.5h-343zM361 727h345q154 0 236 72.5t82 209.5q0 130 -82 208t-225 81h-356v-571z"/> +<glyph glyph-name="Q" horiz-adv-x="1408" unicode="Q" d="M1281 681q0 -211 -67 -363.5t-188 -238.5l260 -204l-131 -121l-307 244q-72 -18 -152 -18q-172 0 -305 84.5t-206.5 241t-75.5 362.5v105q0 210 73 371t206.5 246.5t305.5 85.5q176 0 309.5 -85t205.5 -244.5t72 -372.5v-93zM1089 775q0 257 -102.5 396.5t-292.5 139.5 q-181 0 -285.5 -138.5t-107.5 -384.5v-107q0 -250 104.5 -394t290.5 -144t288 135.5t105 388.5v108z"/> +<glyph glyph-name="R" horiz-adv-x="1261" unicode="R" d="M703 589h-342v-589h-193v1456h482q246 0 378.5 -112t132.5 -326q0 -136 -73.5 -237t-204.5 -151l342 -618v-12h-206zM361 746h295q143 0 227.5 74t84.5 198q0 135 -80.5 207t-232.5 73h-294v-552z"/> +<glyph glyph-name="S" horiz-adv-x="1215" unicode="S" d="M598 649q-247 71 -359.5 174.5t-112.5 255.5q0 172 137.5 284.5t357.5 112.5q150 0 267.5 -58t182 -160t64.5 -223h-193q0 132 -84 207.5t-237 75.5q-142 0 -221.5 -62.5t-79.5 -173.5q0 -89 75.5 -150.5t257 -112.5t284 -112.5t152 -143.5t49.5 -193q0 -177 -138 -283.5 t-369 -106.5q-150 0 -280 57.5t-200.5 157.5t-70.5 227h193q0 -132 97.5 -208.5t260.5 -76.5q152 0 233 62t81 169t-75 165.5t-272 115.5z"/> +<glyph glyph-name="T" horiz-adv-x="1222" unicode="T" d="M1175 1298h-468v-1298h-191v1298h-467v158h1126v-158z"/> +<glyph glyph-name="U" horiz-adv-x="1328" unicode="U" d="M1194 1456v-990q-1 -206 -129.5 -337t-348.5 -147l-51 -2q-239 0 -381 129t-144 355v992h190v-986q0 -158 87 -245.5t248 -87.5q163 0 249.5 87t86.5 245v987h193z"/> +<glyph glyph-name="V" horiz-adv-x="1303" unicode="V" d="M651 255l416 1201h210l-540 -1456h-170l-539 1456h209z"/> +<glyph glyph-name="W" horiz-adv-x="1817" unicode="W" d="M483 459l28 -192l41 173l288 1016h162l281 -1016l40 -176l31 196l226 996h193l-353 -1456h-175l-300 1061l-23 111l-23 -111l-311 -1061h-175l-352 1456h192z"/> +<glyph glyph-name="X" horiz-adv-x="1284" unicode="X" d="M644 898l349 558h226l-460 -722l471 -734h-228l-358 568l-360 -568h-227l472 734l-461 722h225z"/> +<glyph glyph-name="Y" horiz-adv-x="1230" unicode="Y" d="M613 725l380 731h218l-502 -913v-543h-192v543l-502 913h220z"/> +<glyph glyph-name="Z" horiz-adv-x="1226" unicode="Z" d="M313 157h833v-157h-1060v144l798 1154h-785v158h1015v-141z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="543" unicode="[" d="M523 1512h-191v-1672h191v-152h-377v1976h377v-152z"/> +<glyph glyph-name="backslash" horiz-adv-x="840" unicode="\" d="M40 1456h176l608 -1581h-176z"/> +<glyph glyph-name="bracketright" horiz-adv-x="543" unicode="]" d="M9 1664h378v-1976h-378v152h193v1672h-193v152z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="856" unicode="^" d="M426 1211l-190 -482h-172l299 727h127l298 -727h-171z"/> +<glyph glyph-name="underscore" horiz-adv-x="924" unicode="_" d="M920 -151h-916v151h916v-151z"/> +<glyph glyph-name="grave" horiz-adv-x="633" unicode="`" d="M474 1240h-159l-258 294h223z"/> +<glyph glyph-name="a" horiz-adv-x="1114" unicode="a" d="M808 0q-16 32 -26 114q-129 -134 -308 -134q-160 0 -262.5 90.5t-102.5 229.5q0 169 128.5 262.5t361.5 93.5h180v85q0 97 -58 154.5t-171 57.5q-99 0 -166 -50t-67 -121h-186q0 81 57.5 156.5t156 119.5t216.5 44q187 0 293 -93.5t110 -257.5v-498q0 -149 38 -237v-16 h-194zM501 141q87 0 165 45t113 117v222h-145q-340 0 -340 -199q0 -87 58 -136t149 -49z"/> +<glyph glyph-name="b" horiz-adv-x="1149" unicode="b" d="M1056 529q0 -248 -114 -398.5t-306 -150.5q-205 0 -317 145l-9 -125h-170v1536h185v-573q112 139 309 139t309.5 -149t112.5 -408v-16zM871 550q0 189 -73 292t-210 103q-183 0 -263 -170v-468q85 -170 265 -170q133 0 207 103t74 310z"/> +<glyph glyph-name="c" horiz-adv-x="1072" unicode="c" d="M574 131q99 0 173 60t82 150h175q-5 -93 -64 -177t-157.5 -134t-208.5 -50q-221 0 -351.5 147.5t-130.5 403.5v31q0 158 58 281t166.5 191t256.5 68q182 0 302.5 -109t128.5 -283h-175q-8 105 -79.5 172.5t-176.5 67.5q-141 0 -218.5 -101.5t-77.5 -293.5v-35 q0 -187 77 -288t220 -101z"/> +<glyph glyph-name="d" horiz-adv-x="1155" unicode="d" d="M95 550q0 249 118 400.5t309 151.5q190 0 301 -130v564h185v-1536h-170l-9 116q-111 -136 -309 -136q-188 0 -306.5 154t-118.5 402v14zM280 529q0 -184 76 -288t210 -104q176 0 257 158v497q-83 153 -255 153q-136 0 -212 -105t-76 -311z"/> +<glyph glyph-name="e" horiz-adv-x="1085" unicode="e" d="M589 -20q-220 0 -358 144.5t-138 386.5v34q0 161 61.5 287.5t172 198t239.5 71.5q211 0 328 -139t117 -398v-77h-733q4 -160 93.5 -258.5t227.5 -98.5q98 0 166 40t119 106l113 -88q-136 -209 -408 -209zM566 950q-112 0 -188 -81.5t-94 -228.5h542v14q-8 141 -76 218.5 t-184 77.5z"/> +<glyph glyph-name="f" horiz-adv-x="711" unicode="f" d="M231 0v939h-171v143h171v111q0 174 93 269t263 95q64 0 127 -17l-10 -150q-47 9 -100 9q-90 0 -139 -52.5t-49 -150.5v-114h231v-143h-231v-939h-185z"/> +<glyph glyph-name="g" horiz-adv-x="1149" unicode="g" d="M96 550q0 253 117 402.5t310 149.5q198 0 309 -140l9 120h169v-1056q0 -210 -124.5 -331t-334.5 -121q-117 0 -229 50t-171 137l96 111q119 -147 291 -147q135 0 210.5 76t75.5 214v93q-111 -128 -303 -128q-190 0 -307.5 153t-117.5 417zM282 529q0 -183 75 -287.5 t210 -104.5q175 0 257 159v494q-85 155 -255 155q-135 0 -211 -105t-76 -311z"/> +<glyph glyph-name="h" horiz-adv-x="1128" unicode="h" d="M325 951q123 151 320 151q343 0 346 -387v-715h-185v716q-1 117 -53.5 173t-163.5 56q-90 0 -158 -48t-106 -126v-771h-185v1536h185v-585z"/> +<glyph glyph-name="i" horiz-adv-x="497" unicode="i" d="M341 0h-185v1082h185v-1082zM141 1369q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="j" horiz-adv-x="489" unicode="j" d="M331 1082v-1207q0 -312 -283 -312q-61 0 -113 18v148q32 -8 84 -8q62 0 94.5 33.5t32.5 116.5v1211h185zM127 1369q0 44 27.5 75.5t80.5 31.5q54 0 82 -31t28 -76t-28 -75t-82 -30t-81 30t-27 75z"/> +<glyph glyph-name="k" horiz-adv-x="1038" unicode="k" d="M442 501l-116 -121v-380h-185v1536h185v-929l99 119l337 356h225l-421 -452l470 -630h-217z"/> +<glyph glyph-name="l" horiz-adv-x="497" unicode="l" d="M341 0h-185v1536h185v-1536z"/> +<glyph glyph-name="m" horiz-adv-x="1795" unicode="m" d="M314 1082l5 -120q119 140 321 140q227 0 309 -174q54 78 140.5 126t204.5 48q356 0 362 -377v-725h-185v714q0 116 -53 173.5t-178 57.5q-103 0 -171 -61.5t-79 -165.5v-718h-186v709q0 236 -231 236q-182 0 -249 -155v-790h-185v1082h175z"/> +<glyph glyph-name="n" horiz-adv-x="1130" unicode="n" d="M315 1082l6 -136q124 156 324 156q343 0 346 -387v-715h-185v716q-1 117 -53.5 173t-163.5 56q-90 0 -158 -48t-106 -126v-771h-185v1082h175z"/> +<glyph glyph-name="o" horiz-adv-x="1168" unicode="o" d="M91 551q0 159 62.5 286t174 196t254.5 69q221 0 357.5 -153t136.5 -407v-13q0 -158 -60.5 -283.5t-173 -195.5t-258.5 -70q-220 0 -356.5 153t-136.5 405v13zM277 529q0 -180 83.5 -289t223.5 -109q141 0 224 110.5t83 309.5q0 178 -84.5 288.5t-224.5 110.5 q-137 0 -221 -109t-84 -312z"/> +<glyph glyph-name="p" horiz-adv-x="1149" unicode="p" d="M1054 529q0 -247 -113 -398t-306 -151q-197 0 -310 125v-521h-185v1498h169l9 -120q113 140 314 140q195 0 308.5 -147t113.5 -409v-17zM869 550q0 183 -78 289t-214 106q-168 0 -252 -149v-517q83 -148 254 -148q133 0 211.5 105.5t78.5 313.5z"/> +<glyph glyph-name="q" horiz-adv-x="1164" unicode="q" d="M95 550q0 255 117 403.5t314 148.5q192 0 303 -129l8 109h170v-1498h-185v516q-112 -120 -298 -120q-196 0 -312.5 152.5t-116.5 404.5v13zM280 529q0 -186 78.5 -292t211.5 -106q165 0 252 146v530q-88 143 -250 143q-134 0 -213 -106.5t-79 -314.5z"/> +<glyph glyph-name="r" horiz-adv-x="693" unicode="r" d="M663 916q-42 7 -91 7q-182 0 -247 -155v-768h-185v1082h180l3 -125q91 145 258 145q54 0 82 -14v-172z"/> +<glyph glyph-name="s" horiz-adv-x="1056" unicode="s" d="M770 287q0 75 -56.5 116.5t-197 71.5t-223 72t-122 100t-39.5 138q0 133 112.5 225t287.5 92q184 0 298.5 -95t114.5 -243h-186q0 76 -64.5 131t-162.5 55q-101 0 -158 -44t-57 -115q0 -67 53 -101t191.5 -65t224.5 -74t127.5 -103.5t41.5 -147.5q0 -145 -116 -232.5 t-301 -87.5q-130 0 -230 46t-156.5 128.5t-56.5 178.5h185q5 -93 74.5 -147.5t183.5 -54.5q105 0 168.5 42.5t63.5 113.5z"/> +<glyph glyph-name="t" horiz-adv-x="669" unicode="t" d="M391 1344v-262h202v-143h-202v-671q0 -65 27 -97.5t92 -32.5q32 0 88 12v-150q-73 -20 -142 -20q-124 0 -187 75t-63 213v671h-197v143h197v262h185z"/> +<glyph glyph-name="u" horiz-adv-x="1129" unicode="u" d="M808 107q-108 -127 -317 -127q-173 0 -263.5 100.5t-91.5 297.5v704h185v-699q0 -246 200 -246q212 0 282 158v787h185v-1082h-176z"/> +<glyph glyph-name="v" horiz-adv-x="992" unicode="v" d="M497 251l268 831h189l-388 -1082h-141l-392 1082h189z"/> +<glyph glyph-name="w" horiz-adv-x="1539" unicode="w" d="M1098 255l208 827h185l-315 -1082h-150l-263 820l-256 -820h-150l-314 1082h184l213 -810l252 810h149z"/> +<glyph glyph-name="x" horiz-adv-x="1015" unicode="x" d="M503 687l240 395h216l-354 -535l365 -547h-214l-250 405l-250 -405h-215l365 547l-354 535h214z"/> +<glyph glyph-name="y" horiz-adv-x="969" unicode="y" d="M494 271l252 811h198l-435 -1249q-101 -270 -321 -270l-35 3l-69 13v150l50 -4q94 0 146.5 38t86.5 139l41 110l-386 1070h202z"/> +<glyph glyph-name="z" horiz-adv-x="1015" unicode="z" d="M314 151h633v-151h-859v136l597 793h-588v153h820v-131z"/> +<glyph glyph-name="braceleft" horiz-adv-x="693" unicode="{" d="M632 -366q-177 50 -266.5 164.5t-89.5 302.5v199q0 243 -212 243v145q212 0 212 242v208q2 183 89.5 295.5t266.5 163.5l38 -115q-209 -67 -209 -349v-202q0 -227 -167 -316q167 -90 167 -319v-206q3 -275 209 -341z"/> +<glyph glyph-name="bar" horiz-adv-x="499" unicode="|" d="M324 -270h-149v1726h149v-1726z"/> +<glyph glyph-name="braceright" horiz-adv-x="693" unicode="}" d="M19 -251q203 65 210 331v220q0 231 181 315q-181 82 -181 315v203q0 282 -209 349l38 115q177 -50 266 -162.5t90 -297.5v-210q0 -239 212 -239v-145q-212 0 -212 -243v-202q0 -188 -90.5 -301t-265.5 -163z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1393" unicode="~" d="M1263 777q0 -158 -93.5 -266.5t-230.5 -108.5q-72 0 -136 26.5t-148.5 100.5t-121.5 92t-79 18q-78 0 -120 -53.5t-42 -147.5l-161 -2q0 160 92 263t231 103q76 0 146 -32t158 -112.5t152 -90.5l29 -2q76 0 123.5 58t47.5 153z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="499" unicode="¡" d="M170 684h168l13 -1044h-194zM358 996q0 -45 -27.5 -76t-81.5 -31t-82 31t-28 76t28 75t82 30t81.5 -30t27.5 -75z"/> +<glyph glyph-name="cent" horiz-adv-x="1120" unicode="¢" d="M586 131q100 0 174 60.5t82 149.5h175q-6 -126 -105 -226.5t-243 -126.5v-233h-185v234q-179 34 -279 176t-100 362v35q0 212 101 354.5t278 175.5v226h185v-223q150 -23 246 -129t102 -256h-175q-8 105 -79.5 172.5t-176.5 67.5q-141 0 -218.5 -101.5t-77.5 -293.5v-35 q0 -187 77.5 -288t218.5 -101z"/> +<glyph glyph-name="sterling" horiz-adv-x="1190" unicode="£" d="M449 622l8 -220q0 -154 -62 -245h733l-1 -157h-1032v157h77q40 9 65 74.5t27 161.5v8l-8 221h-165v157h160l-9 260q0 199 122.5 318t322.5 119q190 0 301 -106t111 -283h-191q0 107 -63.5 169t-174.5 62q-105 0 -170 -77t-65 -202l9 -260h319v-157h-314z"/> +<glyph glyph-name="currency" horiz-adv-x="1460" unicode="¤" d="M1103 112q-159 -132 -368 -132q-207 0 -366 130l-134 -136l-130 135l139 141q-104 156 -104 358q0 206 112 369l-147 151l130 136l147 -150q158 120 353 120q196 0 355 -121l149 152l132 -137l-151 -154q110 -163 110 -366q0 -196 -102 -355l143 -144l-132 -136zM311 608 q0 -123 57.5 -229t155.5 -167t211 -61t211 61.5t154.5 167t56.5 228.5q0 122 -56.5 227.5t-155 166t-210.5 60.5q-113 0 -211 -60t-155.5 -166t-57.5 -228z"/> +<glyph glyph-name="yen" horiz-adv-x="1240" unicode="Â¥" d="M614 782l364 674h219l-418 -720h312v-125h-384v-165h384v-124h-384v-322h-193v322h-378v124h378v165h-378v125h313l-418 720h220z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="491" unicode="¦" d="M147 -270v791h186v-791h-186zM333 698h-186v758h186v-758z"/> +<glyph glyph-name="section" horiz-adv-x="1256" unicode="§" d="M1145 431q0 -189 -186 -274q69 -49 105 -117t36 -168q0 -168 -130 -267.5t-358 -99.5q-112 0 -212.5 28t-170.5 85q-139 113 -139 318l186 2q0 -130 90 -205.5t246 -75.5q136 0 219 58.5t83 154.5q0 89 -71 141.5t-280 114.5q-182 48 -278 103.5t-142.5 133t-46.5 188.5 q0 186 182 274q-66 49 -101.5 117t-35.5 168q0 166 133.5 266t355.5 100q232 0 362 -113t130 -318h-185q0 125 -84 202.5t-223 77.5q-142 0 -222.5 -57.5t-80.5 -155.5q0 -69 28 -109t95.5 -72.5t211 -72.5t228 -76t141 -84.5t85.5 -113t29 -153.5zM602 691q-90 24 -165 51 q-80 -19 -117.5 -69.5t-37.5 -119.5q0 -70 27 -110t93.5 -73t208.5 -74t186 -58q78 20 120 70.5t42 119.5q0 88 -69.5 142.5t-287.5 120.5z"/> +<glyph glyph-name="dieresis" horiz-adv-x="856" unicode="¨" d="M102 1371q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM532 1369q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="copyright" horiz-adv-x="1609" unicode="©" d="M1119 597q0 -153 -86.5 -233.5t-244.5 -80.5q-157 0 -251.5 105.5t-94.5 287.5v110q0 176 95.5 281.5t250.5 105.5q160 0 246 -82t86 -231h-146q0 99 -47.5 141.5t-138.5 42.5q-94 0 -148 -69t-54 -192v-113q0 -120 54 -189t148 -69q92 0 138.5 42t46.5 143h146zM206 729 q0 -172 80 -318.5t217.5 -229.5t297.5 -83t297 83t217 229.5t80 318.5q0 170 -79 315t-216.5 228.5t-298.5 83.5q-160 0 -298 -82.5t-217.5 -228.5t-79.5 -316zM91 729q0 202 93.5 375t259 272.5t357.5 99.5t357 -99.5t258.5 -272.5t93.5 -375q0 -197 -90 -369 t-255.5 -276.5t-363.5 -104.5q-197 0 -362.5 103.5t-256.5 275.5t-91 371z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="915" unicode="ª" d="M618 705q-12 34 -18 72q-76 -86 -204 -86q-119 0 -184 62t-65 165q0 111 83.5 171t255.5 60h108v52q0 135 -124 135q-69 0 -108.5 -27t-39.5 -78l-161 12q0 103 86 168t223 65q133 0 210 -71.5t77 -205.5v-316q0 -97 26 -178h-165zM435 828q43 0 87 20t72 47v142h-112 q-83 -1 -127.5 -32.5t-44.5 -82.5q0 -94 125 -94z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="961" unicode="«" d="M280 548l258 -397h-141l-295 388v19l295 389h141zM610 548l258 -397h-141l-295 388v19l295 389h141z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1134" unicode="¬" d="M958 375h-186v264h-645v161h831v-425z"/> +<glyph glyph-name="registered" horiz-adv-x="1610" unicode="®" d="M90 729q0 202 93.5 375t259 272.5t357.5 99.5t357 -99.5t258.5 -272.5t93.5 -375q0 -197 -90 -369t-255.5 -276.5t-363.5 -104.5q-197 0 -362.5 103.5t-256.5 275.5t-91 371zM205 729q0 -172 80 -318.5t217.5 -229.5t297.5 -83q161 0 299 84.5t216.5 229.5t78.5 317 q0 171 -78.5 315.5t-216.5 228t-299 83.5q-160 0 -298 -82.5t-217.5 -228.5t-79.5 -316zM653 654v-338h-141v849h276q153 0 237.5 -65.5t84.5 -190.5q0 -123 -128 -188q122 -50 123 -204v-61q0 -86 17 -124v-16h-145q-14 36 -14 128.5t-3 109.5q-16 96 -131 100h-176z M653 782h156q72 2 116 35t44 87q0 73 -39 103.5t-139 30.5h-138v-256z"/> +<glyph glyph-name="macron" horiz-adv-x="938" unicode="¯" d="M834 1313h-714v143h714v-143z"/> +<glyph glyph-name="degree" horiz-adv-x="765" unicode="°" d="M130 1216q0 104 74.5 182t180.5 78q104 0 177.5 -77.5t73.5 -182.5q0 -106 -73.5 -181t-177.5 -75q-105 0 -180 75t-75 181zM385 1088q54 0 91 35.5t37 92.5q0 58 -37 95.5t-91 37.5q-55 0 -92.5 -39.5t-37.5 -93.5t37.5 -91t92.5 -37z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1094" unicode="±" d="M649 854h364v-151h-364v-414h-167v414h-385v151h385v413h167v-413zM970 0h-835v152h835v-152z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="751" unicode="²" d="M683 667h-599v108l300 282q109 102 109 171q0 49 -32 79.5t-92 30.5q-75 0 -110.5 -38t-35.5 -95h-157q0 114 83.5 188t215.5 74t209 -63.5t77 -173.5q0 -104 -107 -211l-84 -79l-176 -145h399v-128z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="751" unicode="³" d="M265 1125h84q74 0 110 30.5t36 78.5q0 45 -31.5 74t-101.5 29q-57 0 -94.5 -25.5t-37.5 -66.5h-157q0 98 81.5 159.5t205.5 61.5q137 0 215 -60.5t78 -164.5q0 -55 -35 -100.5t-101 -70.5q149 -41 149 -184q0 -106 -85 -168.5t-221 -62.5q-132 0 -215 63t-83 170h158 q0 -45 39.5 -75t106.5 -30q70 0 106.5 30t36.5 81q0 113 -156 115h-88v116z"/> +<glyph glyph-name="acute" horiz-adv-x="642" unicode="´" d="M316 1534h224l-268 -294h-149z"/> +<glyph glyph-name="uni00B5" horiz-adv-x="1160" unicode="µ" d="M339 1082v-633q1 -163 52.5 -241t167.5 -78q199 0 261 152v800h186v-1082h-167l-9 115q-93 -135 -263 -135q-147 0 -228 73v-469h-185v1498h185z"/> +<glyph glyph-name="paragraph" horiz-adv-x="1001" unicode="¶" d="M646 0v520h-84q-230 0 -362.5 127t-132.5 341q0 213 133 340.5t363 127.5h269v-1456h-186z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="534" unicode="·" d="M147 729q0 48 28.5 80t85.5 32t86.5 -32t29.5 -80q0 -47 -29.5 -78.5t-86.5 -31.5t-85.5 31.5t-28.5 78.5z"/> +<glyph glyph-name="cedilla" horiz-adv-x="507" unicode="¸" d="M285 0l-12 -52q153 -27 153 -173q0 -97 -80 -153.5t-223 -56.5l-7 107q79 0 122.5 26t43.5 73q0 44 -32 65t-130 30l32 134h133z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="751" unicode="¹" d="M495 674h-157v601l-216 -57v128l355 117h18v-789z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="931" unicode="º" d="M122 1123q0 158 94 255.5t248 97.5q155 0 249 -96.5t94 -262.5v-74q0 -159 -93.5 -256t-247.5 -97t-249 97t-95 262v74zM285 1043q0 -100 48.5 -157t132.5 -57q83 0 130.5 57.5t47.5 158.5v78q0 99 -48.5 156t-131.5 57q-81 0 -129 -55t-50 -152v-86z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="960" unicode="»" d="M244 949l295 -389v-19l-295 -389h-142l258 398l-258 399h142zM593 949l295 -389v-19l-295 -389h-142l258 398l-258 399h142z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1500" unicode="¼" d="M458 664h-157v601l-216 -57v128l355 117h18v-789zM443 118l-104 66l711 1138l104 -66zM1318 299h107v-130h-107v-169h-157v169h-375l-6 102l377 518h161v-490zM938 299h223v289l-17 -28z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1589" unicode="½" d="M399 118l-104 66l711 1138l104 -66zM453 664h-157v601l-216 -57v128l355 117h18v-789zM1481 0h-599v108l300 282q109 102 109 171q0 49 -32 79.5t-92 30.5q-75 0 -110.5 -38t-35.5 -95h-157q0 114 83.5 188t215.5 74t209 -63.5t77 -173.5q0 -104 -107 -211l-84 -79 l-176 -145h399v-128z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1593" unicode="¾" d="M570 118l-104 66l711 1138l104 -66zM1410 299h107v-130h-107v-169h-157v169h-375l-6 102l377 518h161v-490zM1030 299h223v289l-17 -28zM314 1126h84q74 0 110 30.5t36 78.5q0 45 -31.5 74t-101.5 29q-57 0 -94.5 -25.5t-37.5 -66.5h-157q0 98 81.5 159.5t205.5 61.5 q137 0 215 -60.5t78 -164.5q0 -55 -35 -100.5t-101 -70.5q149 -41 149 -184q0 -106 -85 -168.5t-221 -62.5q-132 0 -215 63t-83 170h158q0 -45 39.5 -75t106.5 -30q70 0 106.5 30t36.5 81q0 113 -156 115h-88v116z"/> +<glyph glyph-name="questiondown" horiz-adv-x="969" unicode="¿" d="M588 680q-1 -106 -21.5 -169.5t-68.5 -122.5t-140 -155.5t-103 -195.5l-2 -37q0 -109 58 -166.5t167 -57.5q100 0 162.5 56.5t62.5 147.5h185q-2 -161 -114.5 -263t-295.5 -102q-196 0 -303 100.5t-107 279.5q0 173 160 348l109 113q66 78 66 224h185zM596 997 q0 -45 -27.5 -76t-81.5 -31t-82 31t-28 76q0 44 28 74t82 30t81.5 -30t27.5 -74z"/> +<glyph glyph-name="AE" horiz-adv-x="1914" unicode="Æ" d="M1879 0h-883l-15 353h-564l-205 -353h-226l880 1456h951v-152h-691l20 -471h590v-151h-584l22 -531h705v-151zM518 527h456l-31 733z"/> +<glyph glyph-name="multiply" horiz-adv-x="1092" unicode="×" d="M89 329l330 336l-328 335l119 123l329 -335l329 335l119 -123l-328 -335l330 -336l-119 -123l-331 337l-331 -337z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1408" unicode="Ø" d="M1289 681q0 -214 -72 -373.5t-204 -243.5t-308 -84q-171 0 -302 82l-97 -155h-142l144 231q-190 192 -190 552v83q0 210 73 371t206.5 246.5t305.5 85.5q214 0 362 -125l103 165h141l-159 -255q137 -187 139 -481v-99zM309 681q0 -244 98 -385l564 904q-102 111 -268 111 q-182 0 -286.5 -138.5t-107.5 -384.5v-107zM1098 775q0 182 -56 313l-549 -881q91 -64 212 -64q186 0 288 135.5t105 388.5v108z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1210" unicode="Þ" d="M352 1456v-293h279q147 0 257 -52.5t169.5 -149.5t59.5 -223q0 -194 -132 -309.5t-359 -115.5h-274v-313h-186v1456h186zM352 1011v-546h277q142 0 222 75.5t80 195.5q0 123 -80 198.5t-216 76.5h-283z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1218" unicode="ß" d="M324 0h-185v1111q0 208 103.5 325.5t289.5 117.5q180 0 278.5 -89.5t98.5 -248.5q0 -125 -64 -226.5t-64 -170.5q0 -51 37.5 -98.5t131.5 -119.5t137 -140t43 -144q0 -159 -101.5 -248t-283.5 -89q-81 0 -171.5 22t-128.5 50l43 155q49 -32 116.5 -54t120.5 -22 q107 0 163.5 47t56.5 129q0 52 -37 100t-131.5 121.5t-138 142.5t-43.5 150q0 89 69.5 192.5t69.5 187.5q0 94 -52 147.5t-140 53.5q-218 0 -218 -293v-1109z"/> +<glyph glyph-name="ae" horiz-adv-x="1729" unicode="æ" d="M1262 -20q-261 0 -397 180q-65 -86 -178 -133t-254 -47q-167 0 -261 86.5t-94 237.5q0 157 113.5 244t334.5 87h223v85q0 107 -55 168.5t-159 61.5q-105 0 -175 -55t-70 -136l-184 19q0 143 121 233.5t308 90.5q115 0 203 -41.5t138 -124.5q63 79 150 122.5t192 43.5 q210 0 326 -128.5t116 -361.5v-115h-728q7 -176 94 -271.5t236 -95.5q148 0 269 76l47 31l64 -136q-158 -121 -380 -121zM469 130q72 0 151 37t129 91v237h-228q-117 -2 -187 -57t-70 -138q0 -77 53 -123.5t152 -46.5zM1218 950q-115 0 -189.5 -85.5t-91.5 -224.5h538v31 q0 132 -67 205.5t-190 73.5z"/> +<glyph glyph-name="eth" horiz-adv-x="1200" unicode="ð" d="M820 1301q249 -264 249 -673v-93q0 -158 -58.5 -284.5t-166.5 -198.5t-242 -72q-135 0 -245 64.5t-170.5 176.5t-60.5 246q0 147 56 263.5t159.5 181.5t232.5 65q163 0 284 -114q-48 195 -189 336l-218 -148l-73 99l192 131q-132 91 -315 140l57 159q239 -54 414 -193 l189 129l73 -100zM884 635l-2 56q-33 61 -102.5 97.5t-161.5 36.5q-145 0 -226 -95.5t-81 -262.5q0 -140 83.5 -238t211.5 -98q125 0 201.5 113t76.5 297v94z"/> +<glyph glyph-name="divide" horiz-adv-x="1169" unicode="÷" d="M1069 600h-998v184h998v-184zM461 1098q0 48 28.5 80t85.5 32t86.5 -32t29.5 -80q0 -47 -29.5 -78t-86.5 -31t-85.5 31t-28.5 78zM461 281q0 48 28.5 80t85.5 32t86.5 -32t29.5 -80q0 -46 -29.5 -77.5t-86.5 -31.5t-85.5 31.5t-28.5 77.5z"/> +<glyph glyph-name="oslash" horiz-adv-x="1160" unicode="ø" d="M91 551q0 159 61.5 285.5t174 196t255.5 69.5q110 0 204 -42l73 148h124l-102 -205q195 -154 195 -474q0 -158 -62 -285t-174 -195.5t-256 -68.5q-104 0 -190 35l-74 -149h-124l100 203q-205 149 -205 482zM276 529q0 -194 97 -305l343 694q-62 32 -134 32 q-138 0 -222 -109t-84 -312zM890 551q0 182 -87 293l-340 -688q55 -25 121 -25q139 0 222.5 109.5t83.5 294.5v16z"/> +<glyph glyph-name="thorn" horiz-adv-x="1180" unicode="þ" d="M1063 529q0 -247 -113 -398t-306 -151q-197 0 -310 125v-521h-185v1952h185v-566q113 132 307 132q195 0 308.5 -147t113.5 -409v-17zM878 550q0 183 -78 289t-214 106q-168 0 -252 -149v-517q83 -148 254 -148q133 0 211.5 105.5t78.5 313.5z"/> +<glyph glyph-name="dotlessi" horiz-adv-x="506" unicode="ı" d="M341 0h-186v1082h186v-1082z"/> +<glyph glyph-name="OE" horiz-adv-x="1953" unicode="Å’" d="M1801 0h-848q-178 -21 -292 -21q-162 0 -289 75t-197 210.5t-71 306.5v309q0 172 69.5 308.5t196.5 212t289 75.5q124 0 294 -20h838v-158h-723v-468h631v-157h-631v-516h733v-157zM661 130q113 0 215 14v1166q-109 15 -217 15q-173 0 -270 -114.5t-99 -321.5v-313 q0 -211 97.5 -328.5t273.5 -117.5z"/> +<glyph glyph-name="oe" horiz-adv-x="1860" unicode="Å“" d="M97 551q0 160 60.5 287t170 195.5t251.5 68.5q137 0 237.5 -58.5t161.5 -158.5q65 102 163 159.5t210 57.5q207 0 324 -127t117 -362v-116h-718q7 -170 89 -268.5t216 -98.5q188 0 308 108l74 -126q-137 -132 -382 -132q-135 0 -237.5 56t-165.5 156 q-62 -99 -161.5 -155.5t-233.5 -56.5q-220 0 -352 152t-132 406v13zM282 529q0 -183 80 -291t219 -108q137 0 217 107.5t80 313.5q0 182 -80.5 290.5t-218.5 108.5q-135 0 -216 -107t-81 -314zM1351 950q-99 0 -174 -81.5t-97 -219.5h526v26q0 125 -68.5 200t-186.5 75z"/> +<glyph glyph-name="circumflex" horiz-adv-x="964" unicode="ˆ" d="M774 1262v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="ring" horiz-adv-x="685" unicode="Ëš" d="M551 1408q0 -87 -62 -145.5t-153 -58.5q-92 0 -153.5 59t-61.5 145t61.5 147t153.5 61t153.5 -61t61.5 -147zM220 1408q0 -47 33.5 -81t82.5 -34q48 0 82 33t34 82t-33.5 83.5t-82.5 34.5q-50 0 -83 -35t-33 -83z"/> +<glyph glyph-name="tilde" horiz-adv-x="966" unicode="Ëœ" d="M830 1500q0 -108 -61.5 -175t-153.5 -67q-41 0 -71 10t-78.5 41t-70 37.5t-49.5 6.5q-41 0 -70 -31.5t-29 -80.5l-124 7q0 107 60.5 177t153.5 70q35 0 63 -10t76 -39t73.5 -38t56.5 -9q43 0 71.5 34t28.5 79z"/> +<glyph glyph-name="endash" horiz-adv-x="1344" unicode="–" d="M1164.61 651h-1002.01v151h1002.01v-151z"/> +<glyph glyph-name="emdash" horiz-adv-x="1599" unicode="—" d="M1480.78 651h-1335.98v151h1335.98v-151z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="409" unicode="‘" d="M270 1555l106 -72q-93 -127 -96 -274v-136h-184v116q0 102 48.5 202t125.5 164z"/> +<glyph glyph-name="quoteright" horiz-adv-x="409" unicode="’" d="M153 1046l-105 72q93 130 96 274v144h183v-130q-1 -100 -49.5 -199.5t-124.5 -160.5z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="407" unicode="‚" d="M141 -283l-105 73q91 127 94 273v118h185v-100q0 -101 -49.5 -202t-124.5 -162z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="724" unicode="“" d="M278 1555l106 -72q-93 -127 -96 -274v-136h-184v116q0 102 48.5 202t125.5 164zM593 1555l106 -72q-93 -127 -96 -274v-136h-184v116q0 102 48.5 202t125.5 164z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="731" unicode="â€" d="M165 1046l-105 72q93 130 96 274v144h183v-130q-1 -100 -49.5 -199.5t-124.5 -160.5zM472 1046l-105 72q93 130 96 274v144h183v-130q-1 -100 -49.5 -199.5t-124.5 -160.5z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="705" unicode="„" d="M141 -301l-105 72q91 137 94 290v185h185v-164q0 -108 -49.5 -213.5t-124.5 -169.5zM437 -301l-105 72q91 137 94 290v185h186v-164q0 -107 -48.5 -211.5t-126.5 -171.5z"/> +<glyph glyph-name="bullet" horiz-adv-x="690" unicode="•" d="M138 772q0 87 55.5 143t147.5 56q91 0 148 -54.5t57 -147.5v-37q0 -87 -55 -142t-149 -55q-93 0 -148.5 55.5t-55.5 143.5v38z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="614" unicode="‹" d="M286 550l258 -397h-141l-295 388v19l295 389h141z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="614" unicode="›" d="M231 949l295 -389v-19l-295 -389h-142l258 398l-258 399h142z"/> +<glyph glyph-name="fraction" horiz-adv-x="931" unicode="â„" d="M163 110l-104 66l711 1138l104 -66z"/> +<glyph glyph-name="uni2074" horiz-adv-x="751" unicode="â´" d="M592 955h107v-130h-107v-169h-157v169h-375l-6 102l377 518h161v-490zM212 955h223v289l-17 -28z"/> +<glyph glyph-name="Euro" d="M849 541h-384q4 -195 94 -300t255 -105q116 0 218 34l20 -160q-120 -30 -240 -30q-248 0 -390.5 146.5t-148.5 414.5h-178v124h178v137h-178v125h178q10 262 152.5 405.5t385.5 143.5q106 0 241 -31l-20 -162q-109 35 -219 35q-164 0 -252.5 -101.5t-94.5 -289.5h383 v-125h-384v-137h384v-124z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1170" unicode="−" d="M1003 651h-835v151h835v-151z"/> +<glyph glyph-name="glyph162" d="M495 0h-157v601l-216 -57v128l355 117h18v-789z" horiz-adv-x="751"/> +<glyph glyph-name="glyph163" d="M683 0h-599v108l300 282q109 102 109 171q0 49 -32 79.5t-92 30.5q-75 0 -110.5 -38t-35.5 -95h-157q0 114 83.5 188t215.5 74t209 -63.5t77 -173.5q0 -104 -107 -211l-84 -79l-176 -145h399v-128z" horiz-adv-x="751"/> +<glyph glyph-name="glyph164" d="M265 459h84q74 0 110 30.5t36 78.5q0 45 -31.5 74t-101.5 29q-57 0 -94.5 -25.5t-37.5 -66.5h-157q0 98 81.5 159.5t205.5 61.5q137 0 215 -60.5t78 -164.5q0 -55 -35 -100.5t-101 -70.5q149 -41 149 -184q0 -106 -85 -168.5t-221 -62.5q-132 0 -215 63t-83 170h158 q0 -45 39.5 -75t106.5 -30q70 0 106.5 30t36.5 81q0 113 -156 115h-88v116z" horiz-adv-x="751"/> +<glyph glyph-name="glyph165" d="M592 299h107v-130h-107v-169h-157v169h-375l-6 102l377 518h161v-490zM212 299h223v289l-17 -28z" horiz-adv-x="751"/> +<glyph glyph-name="uni00A0" horiz-adv-x="507" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="565" unicode="Â" d="M525 543h-488v151h488v-151z"/> +<glyph glyph-name="Eth" horiz-adv-x="1373" unicode="Ã" d="M199 0v666h-162v151h162v639h411q190 0 336 -84t225.5 -239t80.5 -356v-93q0 -206 -79.5 -361t-227 -238t-343.5 -85h-403zM673 666h-282v-509h201q222 0 345.5 137t124.5 386v93q0 248 -116.5 385.5t-330.5 139.5h-224v-481h282v-151z"/> +<glyph glyph-name="Agrave" horiz-adv-x="1336" unicode="À" d="M973 380h-610l-137 -380h-198l556 1456h168l557 -1456h-197zM421 538h495l-248 681zM778 1550h-159l-258 294h223z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1336" unicode="Ã" d="M973 380h-610l-137 -380h-198l556 1456h168l557 -1456h-197zM421 538h495l-248 681zM763 1844h224l-268 -294h-149z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1336" unicode="Â" d="M973 380h-610l-137 -380h-198l556 1456h168l557 -1456h-197zM421 538h495l-248 681zM975 1572v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1336" unicode="Ã" d="M973 380h-610l-137 -380h-198l556 1456h168l557 -1456h-197zM421 538h495l-248 681zM1027 1814q0 -108 -61.5 -175t-153.5 -67q-41 0 -71 10t-78.5 41t-70 37.5t-49.5 6.5q-41 0 -70 -31.5t-29 -80.5l-124 7q0 107 60.5 177t153.5 70q35 0 63 -10t76 -39t73.5 -38 t56.5 -9q43 0 71.5 34t28.5 79z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1336" unicode="Ä" d="M973 380h-610l-137 -380h-198l556 1456h168l557 -1456h-197zM421 538h495l-248 681zM351 1681q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM781 1679q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="Aring" horiz-adv-x="1336" unicode="Ã…" d="M973 380h-610l-137 -380h-198l556 1456h168l557 -1456h-197zM421 538h495l-248 681zM887 1729q0 -87 -62 -145.5t-153 -58.5q-92 0 -153.5 59t-61.5 145t61.5 147t153.5 61t153.5 -61t61.5 -147zM556 1729q0 -47 33.5 -81t82.5 -34q48 0 82 33t34 82t-33.5 83.5 t-82.5 34.5q-50 0 -83 -35t-33 -83z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1333" unicode="Ç" d="M1240 462q-27 -231 -170.5 -356.5t-381.5 -125.5q-258 0 -413.5 185t-155.5 495v140q0 203 72.5 357t205.5 236.5t308 82.5q232 0 372 -129.5t163 -358.5h-193q-25 174 -108.5 252t-233.5 78q-184 0 -288.5 -136t-104.5 -387v-141q0 -237 99 -377t277 -140 q160 0 245.5 72.5t113.5 252.5h193zM751 -9l-12 -52q153 -27 153 -173q0 -97 -80 -153.5t-223 -56.5l-7 107q79 0 122.5 26t43.5 73q0 44 -32 65t-130 30l32 134h133z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1164" unicode="È" d="M992 673h-631v-516h733v-157h-925v1456h915v-158h-723v-468h631v-157zM725 1562h-159l-258 294h223z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1164" unicode="É" d="M992 673h-631v-516h733v-157h-925v1456h915v-158h-723v-468h631v-157zM710 1856h224l-268 -294h-149z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1164" unicode="Ê" d="M992 673h-631v-516h733v-157h-925v1456h915v-158h-723v-468h631v-157zM922 1584v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1164" unicode="Ë" d="M992 673h-631v-516h733v-157h-925v1456h915v-158h-723v-468h631v-157zM298 1693q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM728 1691q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="Igrave" horiz-adv-x="557" unicode="ÃŒ" d="M375 0h-192v1456h192v-1456zM385 1562h-159l-258 294h223z"/> +<glyph glyph-name="Iacute" horiz-adv-x="557" unicode="Ã" d="M375 0h-192v1456h192v-1456zM369 1856h224l-268 -294h-149z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="557" unicode="ÃŽ" d="M375 0h-192v1456h192v-1456zM582 1584v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="557" unicode="Ã" d="M375 0h-192v1456h192v-1456zM-42 1693q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM388 1691q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1460" unicode="Ñ" d="M1288 0h-193l-733 1122v-1122h-193v1456h193l735 -1127v1127h191v-1456zM1081 1814q0 -108 -61.5 -175t-153.5 -67q-41 0 -71 10t-78.5 41t-70 37.5t-49.5 6.5q-41 0 -70 -31.5t-29 -80.5l-124 7q0 107 60.5 177t153.5 70q35 0 63 -10t76 -39t73.5 -38t56.5 -9 q43 0 71.5 34t28.5 79z"/> +<glyph glyph-name="Ograve" horiz-adv-x="1408" unicode="Ã’" d="M1289 681q0 -214 -72 -373.5t-204 -243.5t-308 -84q-172 0 -305 84.5t-206.5 241t-75.5 362.5v105q0 210 73 371t206.5 246.5t305.5 85.5q175 0 308.5 -84.5t205.5 -245t72 -373.5v-92zM1098 775q0 259 -104 397.5t-291 138.5q-182 0 -286.5 -138.5t-107.5 -384.5v-107 q0 -251 105.5 -394.5t290.5 -143.5q186 0 288 135.5t105 388.5v108zM812 1552h-159l-258 294h223z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1408" unicode="Ó" d="M1289 681q0 -214 -72 -373.5t-204 -243.5t-308 -84q-172 0 -305 84.5t-206.5 241t-75.5 362.5v105q0 210 73 371t206.5 246.5t305.5 85.5q175 0 308.5 -84.5t205.5 -245t72 -373.5v-92zM1098 775q0 259 -104 397.5t-291 138.5q-182 0 -286.5 -138.5t-107.5 -384.5v-107 q0 -251 105.5 -394.5t290.5 -143.5q186 0 288 135.5t105 388.5v108zM797 1846h224l-268 -294h-149z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1408" unicode="Ô" d="M1289 681q0 -214 -72 -373.5t-204 -243.5t-308 -84q-172 0 -305 84.5t-206.5 241t-75.5 362.5v105q0 210 73 371t206.5 246.5t305.5 85.5q175 0 308.5 -84.5t205.5 -245t72 -373.5v-92zM1098 775q0 259 -104 397.5t-291 138.5q-182 0 -286.5 -138.5t-107.5 -384.5v-107 q0 -251 105.5 -394.5t290.5 -143.5q186 0 288 135.5t105 388.5v108zM1009 1574v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1408" unicode="Õ" d="M1289 681q0 -214 -72 -373.5t-204 -243.5t-308 -84q-172 0 -305 84.5t-206.5 241t-75.5 362.5v105q0 210 73 371t206.5 246.5t305.5 85.5q175 0 308.5 -84.5t205.5 -245t72 -373.5v-92zM1098 775q0 259 -104 397.5t-291 138.5q-182 0 -286.5 -138.5t-107.5 -384.5v-107 q0 -251 105.5 -394.5t290.5 -143.5q186 0 288 135.5t105 388.5v108zM1061 1816q0 -108 -61.5 -175t-153.5 -67q-41 0 -71 10t-78.5 41t-70 37.5t-49.5 6.5q-41 0 -70 -31.5t-29 -80.5l-124 7q0 107 60.5 177t153.5 70q35 0 63 -10t76 -39t73.5 -38t56.5 -9q43 0 71.5 34 t28.5 79z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1408" unicode="Ö" d="M1289 681q0 -214 -72 -373.5t-204 -243.5t-308 -84q-172 0 -305 84.5t-206.5 241t-75.5 362.5v105q0 210 73 371t206.5 246.5t305.5 85.5q175 0 308.5 -84.5t205.5 -245t72 -373.5v-92zM1098 775q0 259 -104 397.5t-291 138.5q-182 0 -286.5 -138.5t-107.5 -384.5v-107 q0 -251 105.5 -394.5t290.5 -143.5q186 0 288 135.5t105 388.5v108zM385 1683q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM815 1681q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1328" unicode="Ù" d="M1194 1456v-990q-1 -206 -129.5 -337t-348.5 -147l-51 -2q-239 0 -381 129t-144 355v992h190v-986q0 -158 87 -245.5t248 -87.5q163 0 249.5 87t86.5 245v987h193zM773 1550h-159l-258 294h223z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1328" unicode="Ú" d="M1194 1456v-990q-1 -206 -129.5 -337t-348.5 -147l-51 -2q-239 0 -381 129t-144 355v992h190v-986q0 -158 87 -245.5t248 -87.5q163 0 249.5 87t86.5 245v987h193zM758 1844h224l-268 -294h-149z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1328" unicode="Û" d="M1194 1456v-990q-1 -206 -129.5 -337t-348.5 -147l-51 -2q-239 0 -381 129t-144 355v992h190v-986q0 -158 87 -245.5t248 -87.5q163 0 249.5 87t86.5 245v987h193zM970 1572v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="Udieresis" horiz-adv-x="1328" unicode="Ü" d="M1194 1456v-990q-1 -206 -129.5 -337t-348.5 -147l-51 -2q-239 0 -381 129t-144 355v992h190v-986q0 -158 87 -245.5t248 -87.5q163 0 249.5 87t86.5 245v987h193zM346 1681q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM776 1679 q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1230" unicode="Ã" d="M613 725l380 731h218l-502 -913v-543h-192v543l-502 913h220zM708 1844h224l-268 -294h-149z"/> +<glyph glyph-name="agrave" horiz-adv-x="1114" unicode="à " d="M808 0q-16 32 -26 114q-129 -134 -308 -134q-160 0 -262.5 90.5t-102.5 229.5q0 169 128.5 262.5t361.5 93.5h180v85q0 97 -58 154.5t-171 57.5q-99 0 -166 -50t-67 -121h-186q0 81 57.5 156.5t156 119.5t216.5 44q187 0 293 -93.5t110 -257.5v-498q0 -149 38 -237v-16 h-194zM501 141q87 0 165 45t113 117v222h-145q-340 0 -340 -199q0 -87 58 -136t149 -49zM687 1240h-159l-258 294h223z"/> +<glyph glyph-name="aacute" horiz-adv-x="1114" unicode="á" d="M808 0q-16 32 -26 114q-129 -134 -308 -134q-160 0 -262.5 90.5t-102.5 229.5q0 169 128.5 262.5t361.5 93.5h180v85q0 97 -58 154.5t-171 57.5q-99 0 -166 -50t-67 -121h-186q0 81 57.5 156.5t156 119.5t216.5 44q187 0 293 -93.5t110 -257.5v-498q0 -149 38 -237v-16 h-194zM501 141q87 0 165 45t113 117v222h-145q-340 0 -340 -199q0 -87 58 -136t149 -49zM672 1534h224l-268 -294h-149z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1114" unicode="â" d="M808 0q-16 32 -26 114q-129 -134 -308 -134q-160 0 -262.5 90.5t-102.5 229.5q0 169 128.5 262.5t361.5 93.5h180v85q0 97 -58 154.5t-171 57.5q-99 0 -166 -50t-67 -121h-186q0 81 57.5 156.5t156 119.5t216.5 44q187 0 293 -93.5t110 -257.5v-498q0 -149 38 -237v-16 h-194zM501 141q87 0 165 45t113 117v222h-145q-340 0 -340 -199q0 -87 58 -136t149 -49zM884 1262v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="atilde" horiz-adv-x="1114" unicode="ã" d="M808 0q-16 32 -26 114q-129 -134 -308 -134q-160 0 -262.5 90.5t-102.5 229.5q0 169 128.5 262.5t361.5 93.5h180v85q0 97 -58 154.5t-171 57.5q-99 0 -166 -50t-67 -121h-186q0 81 57.5 156.5t156 119.5t216.5 44q187 0 293 -93.5t110 -257.5v-498q0 -149 38 -237v-16 h-194zM501 141q87 0 165 45t113 117v222h-145q-340 0 -340 -199q0 -87 58 -136t149 -49zM936 1504q0 -108 -61.5 -175t-153.5 -67q-41 0 -71 10t-78.5 41t-70 37.5t-49.5 6.5q-41 0 -70 -31.5t-29 -80.5l-124 7q0 107 60.5 177t153.5 70q35 0 63 -10t76 -39t73.5 -38 t56.5 -9q43 0 71.5 34t28.5 79z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1114" unicode="ä" d="M808 0q-16 32 -26 114q-129 -134 -308 -134q-160 0 -262.5 90.5t-102.5 229.5q0 169 128.5 262.5t361.5 93.5h180v85q0 97 -58 154.5t-171 57.5q-99 0 -166 -50t-67 -121h-186q0 81 57.5 156.5t156 119.5t216.5 44q187 0 293 -93.5t110 -257.5v-498q0 -149 38 -237v-16 h-194zM501 141q87 0 165 45t113 117v222h-145q-340 0 -340 -199q0 -87 58 -136t149 -49zM260 1371q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM690 1369q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="aring" horiz-adv-x="1114" unicode="Ã¥" d="M808 0q-16 32 -26 114q-129 -134 -308 -134q-160 0 -262.5 90.5t-102.5 229.5q0 169 128.5 262.5t361.5 93.5h180v85q0 97 -58 154.5t-171 57.5q-99 0 -166 -50t-67 -121h-186q0 81 57.5 156.5t156 119.5t216.5 44q187 0 293 -93.5t110 -257.5v-498q0 -149 38 -237v-16 h-194zM501 141q87 0 165 45t113 117v222h-145q-340 0 -340 -199q0 -87 58 -136t149 -49zM796 1419q0 -87 -62 -145.5t-153 -58.5q-92 0 -153.5 59t-61.5 145t61.5 147t153.5 61t153.5 -61t61.5 -147zM465 1419q0 -47 33.5 -81t82.5 -34q48 0 82 33t34 82t-33.5 83.5 t-82.5 34.5q-50 0 -83 -35t-33 -83z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1072" unicode="ç" d="M574 131q99 0 173 60t82 150h175q-5 -93 -64 -177t-157.5 -134t-208.5 -50q-221 0 -351.5 147.5t-130.5 403.5v31q0 158 58 281t166.5 191t256.5 68q182 0 302.5 -109t128.5 -283h-175q-8 105 -79.5 172.5t-176.5 67.5q-141 0 -218.5 -101.5t-77.5 -293.5v-35 q0 -187 77 -288t220 -101zM604 -9l-12 -52q153 -27 153 -173q0 -97 -80 -153.5t-223 -56.5l-7 107q79 0 122.5 26t43.5 73q0 44 -32 65t-130 30l32 134h133z"/> +<glyph glyph-name="egrave" horiz-adv-x="1085" unicode="è" d="M589 -20q-220 0 -358 144.5t-138 386.5v34q0 161 61.5 287.5t172 198t239.5 71.5q211 0 328 -139t117 -398v-77h-733q4 -160 93.5 -258.5t227.5 -98.5q98 0 166 40t119 106l113 -88q-136 -209 -408 -209zM566 950q-112 0 -188 -81.5t-94 -228.5h542v14q-8 141 -76 218.5 t-184 77.5zM671 1240h-159l-258 294h223z"/> +<glyph glyph-name="eacute" horiz-adv-x="1085" unicode="é" d="M589 -20q-220 0 -358 144.5t-138 386.5v34q0 161 61.5 287.5t172 198t239.5 71.5q211 0 328 -139t117 -398v-77h-733q4 -160 93.5 -258.5t227.5 -98.5q98 0 166 40t119 106l113 -88q-136 -209 -408 -209zM566 950q-112 0 -188 -81.5t-94 -228.5h542v14q-8 141 -76 218.5 t-184 77.5zM656 1534h224l-268 -294h-149z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1085" unicode="ê" d="M589 -20q-220 0 -358 144.5t-138 386.5v34q0 161 61.5 287.5t172 198t239.5 71.5q211 0 328 -139t117 -398v-77h-733q4 -160 93.5 -258.5t227.5 -98.5q98 0 166 40t119 106l113 -88q-136 -209 -408 -209zM566 950q-112 0 -188 -81.5t-94 -228.5h542v14q-8 141 -76 218.5 t-184 77.5zM868 1262v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1085" unicode="ë" d="M589 -20q-220 0 -358 144.5t-138 386.5v34q0 161 61.5 287.5t172 198t239.5 71.5q211 0 328 -139t117 -398v-77h-733q4 -160 93.5 -258.5t227.5 -98.5q98 0 166 40t119 106l113 -88q-136 -209 -408 -209zM566 950q-112 0 -188 -81.5t-94 -228.5h542v14q-8 141 -76 218.5 t-184 77.5zM244 1371q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM674 1369q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="igrave" horiz-adv-x="506" unicode="ì" d="M341 0h-186v1082h186v-1082zM359 1239h-159l-258 294h223z"/> +<glyph glyph-name="iacute" horiz-adv-x="506" unicode="Ã" d="M341 0h-186v1082h186v-1082zM343 1533h224l-268 -294h-149z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="506" unicode="î" d="M341 0h-186v1082h186v-1082zM556 1261v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="idieresis" horiz-adv-x="506" unicode="ï" d="M341 0h-186v1082h186v-1082zM-68 1370q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM362 1368q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="ntilde" horiz-adv-x="1130" unicode="ñ" d="M315 1082l6 -136q124 156 324 156q343 0 346 -387v-715h-185v716q-1 117 -53.5 173t-163.5 56q-90 0 -158 -48t-106 -126v-771h-185v1082h175zM927 1504q0 -108 -61.5 -175t-153.5 -67q-41 0 -71 10t-78.5 41t-70 37.5t-49.5 6.5q-41 0 -70 -31.5t-29 -80.5l-124 7 q0 107 60.5 177t153.5 70q35 0 63 -10t76 -39t73.5 -38t56.5 -9q43 0 71.5 34t28.5 79z"/> +<glyph glyph-name="ograve" horiz-adv-x="1168" unicode="ò" d="M91 551q0 159 62.5 286t174 196t254.5 69q221 0 357.5 -153t136.5 -407v-13q0 -158 -60.5 -283.5t-173 -195.5t-258.5 -70q-220 0 -356.5 153t-136.5 405v13zM277 529q0 -180 83.5 -289t223.5 -109q141 0 224 110.5t83 309.5q0 178 -84.5 288.5t-224.5 110.5 q-137 0 -221 -109t-84 -312zM681 1240h-159l-258 294h223z"/> +<glyph glyph-name="oacute" horiz-adv-x="1168" unicode="ó" d="M91 551q0 159 62.5 286t174 196t254.5 69q221 0 357.5 -153t136.5 -407v-13q0 -158 -60.5 -283.5t-173 -195.5t-258.5 -70q-220 0 -356.5 153t-136.5 405v13zM277 529q0 -180 83.5 -289t223.5 -109q141 0 224 110.5t83 309.5q0 178 -84.5 288.5t-224.5 110.5 q-137 0 -221 -109t-84 -312zM666 1534h224l-268 -294h-149z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1168" unicode="ô" d="M91 551q0 159 62.5 286t174 196t254.5 69q221 0 357.5 -153t136.5 -407v-13q0 -158 -60.5 -283.5t-173 -195.5t-258.5 -70q-220 0 -356.5 153t-136.5 405v13zM277 529q0 -180 83.5 -289t223.5 -109q141 0 224 110.5t83 309.5q0 178 -84.5 288.5t-224.5 110.5 q-137 0 -221 -109t-84 -312zM878 1262v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="otilde" horiz-adv-x="1168" unicode="õ" d="M91 551q0 159 62.5 286t174 196t254.5 69q221 0 357.5 -153t136.5 -407v-13q0 -158 -60.5 -283.5t-173 -195.5t-258.5 -70q-220 0 -356.5 153t-136.5 405v13zM277 529q0 -180 83.5 -289t223.5 -109q141 0 224 110.5t83 309.5q0 178 -84.5 288.5t-224.5 110.5 q-137 0 -221 -109t-84 -312zM930 1504q0 -108 -61.5 -175t-153.5 -67q-41 0 -71 10t-78.5 41t-70 37.5t-49.5 6.5q-41 0 -70 -31.5t-29 -80.5l-124 7q0 107 60.5 177t153.5 70q35 0 63 -10t76 -39t73.5 -38t56.5 -9q43 0 71.5 34t28.5 79z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1168" unicode="ö" d="M91 551q0 159 62.5 286t174 196t254.5 69q221 0 357.5 -153t136.5 -407v-13q0 -158 -60.5 -283.5t-173 -195.5t-258.5 -70q-220 0 -356.5 153t-136.5 405v13zM277 529q0 -180 83.5 -289t223.5 -109q141 0 224 110.5t83 309.5q0 178 -84.5 288.5t-224.5 110.5 q-137 0 -221 -109t-84 -312zM254 1371q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM684 1369q0 45 27.5 76t81.5 31t82 -31t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="ugrave" horiz-adv-x="1129" unicode="ù" d="M808 107q-108 -127 -317 -127q-173 0 -263.5 100.5t-91.5 297.5v704h185v-699q0 -246 200 -246q212 0 282 158v787h185v-1082h-176zM673 1240h-159l-258 294h223z"/> +<glyph glyph-name="uacute" horiz-adv-x="1129" unicode="ú" d="M808 107q-108 -127 -317 -127q-173 0 -263.5 100.5t-91.5 297.5v704h185v-699q0 -246 200 -246q212 0 282 158v787h185v-1082h-176zM658 1534h224l-268 -294h-149z"/> +<glyph glyph-name="ucircumflex" horiz-adv-x="1129" unicode="û" d="M808 107q-108 -127 -317 -127q-173 0 -263.5 100.5t-91.5 297.5v704h185v-699q0 -246 200 -246q212 0 282 158v787h185v-1082h-176zM870 1262v-10h-153l-150 170l-149 -170h-153v12l246 272h112z"/> +<glyph glyph-name="udieresis" horiz-adv-x="1129" unicode="ü" d="M808 107q-108 -127 -317 -127q-173 0 -263.5 100.5t-91.5 297.5v704h185v-699q0 -246 200 -246q212 0 282 158v787h185v-1082h-176zM246 1371q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM676 1369q0 45 27.5 76t81.5 31t82 -31 t28 -76t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +<glyph glyph-name="yacute" horiz-adv-x="969" unicode="ý" d="M494 271l252 811h198l-435 -1249q-101 -270 -321 -270l-35 3l-69 13v150l50 -4q94 0 146.5 38t86.5 139l41 110l-386 1070h202zM599 1534h224l-268 -294h-149z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="969" unicode="ÿ" d="M494 271l252 811h198l-435 -1249q-101 -270 -321 -270l-35 3l-69 13v150l50 -4q94 0 146.5 38t86.5 139l41 110l-386 1070h202zM187 1371q0 45 27.5 75.5t81.5 30.5t82 -30.5t28 -75.5t-28 -75t-82 -30t-81.5 30t-27.5 75zM617 1369q0 45 27.5 76t81.5 31t82 -31t28 -76 t-28 -75t-82 -30t-81.5 30t-27.5 75z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ce967de9dfc31c0fa25424604f210cad274144b2 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..adf25196b7bbb5483cf461d846327ee84950558a Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2 b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..969d4996ec8f270a65c08d68f1a04329a4662150 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Regular/RobotoDraft-Regular.woff2 differ diff --git a/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.eot b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.eot new file mode 100644 index 0000000000000000000000000000000000000000..612dcb85af089452eb5c366287eeec60e8841de7 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.eot differ diff --git a/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.svg b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.svg new file mode 100644 index 0000000000000000000000000000000000000000..fa3a4732641fd8752413e35c7485fe7e5c2606c5 --- /dev/null +++ b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.svg @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> +<svg xmlns="http://www.w3.org/2000/svg"> +<defs> +<font id="RobotoDraft-Thin" horiz-adv-x="1121"> +<font-face underline-position="-100" font-weight="250" descent="-512" panose-1="2 0 0 0 0 0 0 0 0 0" units-per-em="2048" unicode-range="U+000D-2212" bbox="-143 -495 1855 1875" x-height="1082" underline-thickness="100" font-family="RobotoDraft Thin" ascent="1536" cap-height="1456"/> +<missing-glyph d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="f_i.liga" horiz-adv-x="1067" unicode="fi" d="M254 0v1027h-188v55h188v136q1 161 86 250t237 89q145 0 268 -57l-8 -52l-59 24q-83 31 -200 31q-125 0 -197.5 -76.5t-72.5 -212.5v-132h286v-55h-286v-1027h-54zM884 0h-54v1082h54v-1082z"/> +<glyph glyph-name="f_l.liga" horiz-adv-x="1067" unicode="fl" d="M830 1460q-190 43 -292 43q-107 0 -168.5 -69.5t-61.5 -197.5v-154h286v-55h-286v-1027h-54v1027h-188v55h188v158q1 150 75.5 233.5t207.5 83.5q123 0 347 -61v-1496h-54v1460z"/> +<glyph glyph-name=".notdef" d="M808 0h-708v1456h708v-1456zM754 84v1287l-274 -643zM154 1359v-1263l268 632zM194 54h515l-258 606zM451 796l258 606h-515z" horiz-adv-x="908"/> +<glyph glyph-name="uni0000" horiz-adv-x="0"/> +<glyph glyph-name="glyph2" horiz-adv-x="0"/> +<glyph glyph-name="uni000D" horiz-adv-x="490" unicode=" "/> +<glyph glyph-name="space" horiz-adv-x="490" unicode=" "/> +<glyph glyph-name="exclam" horiz-adv-x="397" unicode="!" d="M221 401h-54v1055h54v-1055zM147 49q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="quotedbl" horiz-adv-x="521" unicode='"' d="M210 1393l-10 -271h-50q5 268 5 414h55v-143zM411 1393l-10 -271h-50l6 268v146h54v-143z"/> +<glyph glyph-name="numbersign" d="M742 410h-364l-74 -410h-56l74 410h-271v52h281l95 524h-300v54h310l75 416h56l-76 -416h365l76 416h56l-76 -416h254v-54h-264l-96 -524h285v-52h-294l-75 -410h-56zM388 462h363l96 524h-365z" unicode="#"/> +<glyph glyph-name="dollar" d="M947 344q0 91 -34.5 150.5t-116.5 109.5t-242.5 105.5t-236.5 108t-112.5 122.5t-36.5 170q0 163 107 261.5t279 104.5v187h55v-187q184 -10 284 -122.5t100 -306.5h-54q0 170 -96.5 273.5t-263.5 103.5q-162 0 -259.5 -87t-97.5 -225q0 -98 32.5 -155t108 -103.5 t212.5 -93.5t210 -83.5t121 -84.5t71.5 -107t23.5 -139q0 -159 -103.5 -257.5t-277.5 -108.5v-188h-55v187q-212 8 -328 120.5t-116 309.5h54q0 -177 110.5 -277t300.5 -100q157 0 259 90t102 222z" unicode="$"/> +<glyph glyph-name="percent" horiz-adv-x="1527" unicode="%" d="M114 1176q0 129 78 215t194 86q117 0 194 -86.5t77 -219.5v-72q0 -127 -76.5 -213t-192.5 -86q-117 0 -195.5 85t-78.5 220v71zM169 1099q0 -104 59.5 -174t159.5 -70q96 0 155 69t59 180v72q0 108 -59.5 177t-156.5 69q-95 0 -156 -69t-61 -184v-70zM870 357 q0 129 77.5 214.5t193.5 85.5q117 0 194.5 -85.5t77.5 -221.5v-71q0 -129 -77.5 -214.5t-192.5 -85.5q-116 0 -194.5 85t-78.5 220v73zM925 279q0 -107 59.5 -176t158.5 -69q98 0 156.5 69.5t58.5 180.5v73q0 113 -58.5 179t-158.5 66q-99 0 -157.5 -67.5t-58.5 -181.5v-74z M422 131l-45 31l711 1138l45 -31z"/> +<glyph glyph-name="ampersand" horiz-adv-x="1247" unicode="&" d="M422 802q-88 108 -126.5 194t-38.5 171q0 141 84.5 225.5t220.5 84.5q125 0 200.5 -73.5t75.5 -190.5q0 -136 -188 -292l-156 -124l475 -539q115 160 115 374h55q0 -237 -133 -416l190 -216h-67l-157 176q-196 -196 -423 -196q-201 0 -317.5 100.5t-116.5 271.5 q0 98 56.5 193.5t199.5 216.5zM549 34q111 0 211.5 47.5t176.5 135.5l-483 547l-52 -41q-118 -102 -175.5 -191t-57.5 -180q0 -142 103.5 -230t276.5 -88zM312 1169q0 -158 150 -335l175 139q145 121 145 240q0 92 -61.5 151t-158.5 59q-113 0 -181.5 -70.5t-68.5 -183.5z "/> +<glyph glyph-name="quotesingle" horiz-adv-x="340" unicode="'" d="M200 1367l-14 -245h-50l9 243v171h55v-169z"/> +<glyph glyph-name="parenleft" horiz-adv-x="607" unicode="(" d="M148 586q0 216 53 425t150.5 375t210.5 237l19 -43q-98 -65 -185 -217t-139 -352t-55 -395v-52q0 -198 50 -401.5t139 -363t190 -226.5l-19 -43q-116 73 -211.5 231.5t-149 369t-53.5 455.5z"/> +<glyph glyph-name="parenright" horiz-adv-x="623" unicode=")" d="M461 566q0 -225 -53.5 -435.5t-149 -369t-211.5 -231.5l-19 43q104 70 193 232t137.5 362t48.5 423q0 202 -51 405.5t-139.5 361t-188.5 223.5l19 43q113 -71 210.5 -237t150.5 -375t53 -445z"/> +<glyph glyph-name="asterisk" horiz-adv-x="856" unicode="*" d="M393 1017l-363 124l18 54l362 -133l1 394h56l-7 -395l352 143l20 -53l-360 -137l249 -317l-47 -33l-242 322l-228 -325l-45 32z"/> +<glyph glyph-name="plus" horiz-adv-x="1151" unicode="+" d="M590 702h481v-53h-481v-503h-55v503h-462v53h462v504h55v-504z"/> +<glyph glyph-name="comma" horiz-adv-x="383" unicode="," d="M129 -255l-37 32q81 104 88 215l1 167h54v-146q-4 -159 -106 -268z"/> +<glyph glyph-name="hyphen" horiz-adv-x="607" unicode="-" d="M531 639h-470v54h470v-54z"/> +<glyph glyph-name="period" horiz-adv-x="439" unicode="." d="M147 49q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="slash" horiz-adv-x="782" unicode="/" d="M101 -125h-59l608 1581h59z"/> +<glyph glyph-name="zero" d="M996 594q0 -293 -114 -453.5t-320 -160.5q-205 0 -321 162t-116 456v264q0 290 114.5 452.5t320.5 162.5q207 0 321.5 -162.5t114.5 -456.5v-264zM942 862q0 265 -99.5 413t-282.5 148q-184 0 -282.5 -148.5t-98.5 -417.5v-261q0 -264 101 -413t282 -149q182 0 281 149 t99 418v261z" unicode="0"/> +<glyph glyph-name="one" d="M659 0h-54v1388l-418 -157v59l461 170h11v-1460z" unicode="1"/> +<glyph glyph-name="two" d="M1024 0h-871v54l497 573q122 143 181.5 254t59.5 204q0 160 -93 248.5t-262 88.5q-102 0 -186 -49t-131.5 -135.5t-47.5 -192.5h-54q0 117 54 217t150 157t215 57q194 0 302 -103t108 -288q0 -170 -191 -407l-91 -111l-440 -513h800v-54z" unicode="2"/> +<glyph glyph-name="three" d="M417 770h122q171 3 276.5 91t105.5 224q0 155 -94.5 246t-262.5 91q-164 0 -270 -96t-106 -252h-54q0 116 56 208t155 143t219 51q189 0 300 -106.5t111 -288.5q0 -116 -73.5 -207t-198.5 -129q143 -33 223.5 -124t80.5 -235q0 -186 -119 -296t-315 -110q-132 0 -244 57 t-169 151t-57 217h54q0 -160 118 -265.5t298 -105.5q179 0 279.5 92.5t100.5 255.5q0 161 -107.5 246t-314.5 86h-114v56z" unicode="3"/> +<glyph glyph-name="four" d="M842 451h252v-54h-252v-397h-54v397h-706v30l695 1029h65v-1005zM166 451h622v940l-84 -138z" unicode="4"/> +<glyph glyph-name="five" d="M231 762l68 694h710v-53h-661l-59 -584q52 43 137.5 70t167.5 27q196 0 313 -124t117 -328q0 -237 -106 -360.5t-304 -123.5q-187 0 -302 107t-130 296h55q16 -171 112 -260t265 -89q180 0 267.5 108.5t87.5 319.5q0 182 -101.5 291t-272.5 109q-105 0 -183 -28t-140 -88 z" unicode="5"/> +<glyph glyph-name="six" d="M840 1476v-54q-306 0 -475 -181t-182 -508q58 103 168 163.5t241 60.5q192 0 306.5 -131t114.5 -346q0 -139 -52 -254t-147 -180.5t-212 -65.5q-134 0 -242 62t-169 177t-63 262v179q0 388 183 602t529 214zM585 903q-140 0 -256.5 -80.5t-146.5 -201.5v-128 q0 -206 117 -333t303 -127q155 0 256 129.5t101 317.5q0 194 -100 308.5t-274 114.5z" unicode="6"/> +<glyph glyph-name="seven" d="M1007 1422l-641 -1422h-55l634 1402h-868v54h930v-34z" unicode="7"/> +<glyph glyph-name="eight" d="M986 1086q0 -122 -75.5 -213.5t-195.5 -127.5q143 -38 228 -138t85 -228q0 -185 -126.5 -292t-336.5 -107q-214 0 -339.5 107t-125.5 292q0 129 82.5 228.5t225.5 137.5q-120 36 -193.5 127.5t-73.5 213.5q0 180 115.5 285t304.5 105q190 0 307.5 -107t117.5 -283z M973 374q0 150 -115 247t-295 97q-181 0 -295 -96.5t-114 -247.5q0 -154 111.5 -247t299.5 -93q184 0 296 93.5t112 246.5zM932 1091q0 142 -107 236.5t-264 94.5q-161 0 -263.5 -91t-102.5 -240q0 -142 102 -230.5t266 -88.5q162 0 265.5 89.5t103.5 229.5z" unicode="8"/> +<glyph glyph-name="nine" d="M939 724q-53 -115 -164.5 -185.5t-251.5 -70.5q-120 0 -216 64.5t-150 177.5t-54 248q0 143 55 262.5t154 187.5t219 68q225 0 343 -146.5t119 -422.5v-167q0 -369 -164 -562.5t-483 -197.5h-48l2 54h43q292 3 444 178t152 512zM523 522q148 0 262 87t154 231v62 q0 253 -104.5 386.5t-299.5 133.5q-107 0 -194 -63t-135.5 -171.5t-48.5 -229.5q0 -119 47 -220.5t130 -158.5t189 -57z" unicode="9"/> +<glyph glyph-name="colon" horiz-adv-x="364" unicode=":" d="M120 49q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM125 1011q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="semicolon" horiz-adv-x="364" unicode=";" d="M126 1011q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM118 -255l-37 32q81 104 88 215l1 167h54v-146q-4 -159 -106 -268z"/> +<glyph glyph-name="less" horiz-adv-x="1053" unicode="<" d="M155 669l764 -345v-59l-837 379v50l837 378v-58z"/> +<glyph glyph-name="equal" horiz-adv-x="1142" unicode="=" d="M981 843h-834v54h834v-54zM981 436h-834v54h834v-54z"/> +<glyph glyph-name="greater" horiz-adv-x="1053" unicode=">" d="M872 668l-758 345v59l836 -378v-50l-836 -379v59z"/> +<glyph glyph-name="question" horiz-adv-x="893" unicode="?" d="M395 400q2 112 34.5 183.5t122.5 155.5t126 135t52.5 106t16.5 132q0 145 -77 228t-212 83q-144 0 -226.5 -86t-84.5 -221h-54q2 162 105 261t260 99t250 -99t93 -267q0 -115 -45 -204.5t-175 -207.5q-132 -103 -132 -298h-54zM371 49q0 23 16 39.5t39 16.5t39.5 -16.5 t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="at" horiz-adv-x="1902" unicode="@" d="M1770 523q-5 -154 -55 -283t-131 -194.5t-184 -65.5q-100 0 -162 61t-73 169q-110 -230 -333 -230q-136 0 -202.5 124.5t-48.5 331.5q24 251 145 401.5t292 150.5q115 0 198 -66l52 -44l-49 -585q-11 -123 37.5 -190.5t146.5 -67.5q134 0 216.5 129t93.5 359 q22 411 -160 621t-553 210q-224 0 -407 -112t-288 -312t-118 -452q-12 -255 72 -454.5t254 -310.5t400 -111q90 0 178 21.5t152 58.5l24 -46q-64 -42 -165.5 -65.5t-192.5 -23.5q-250 0 -430 112.5t-269.5 324t-77.5 494.5q12 280 123 492t305.5 326.5t443.5 114.5 q392 0 588.5 -229.5t177.5 -658.5zM634 279q11 -116 62.5 -180.5t133.5 -64.5q125 0 206 77.5t132 232.5l43 507q-69 82 -196 82t-223.5 -100t-136.5 -276q-34 -152 -21 -278z"/> +<glyph glyph-name="A" horiz-adv-x="1223" unicode="A" d="M967 435h-713l-162 -435h-59l545 1456h66l545 -1456h-59zM274 489h673l-336 902z"/> +<glyph glyph-name="B" horiz-adv-x="1235" unicode="B" d="M200 0v1456h383q235 0 355.5 -95.5t120.5 -277.5q0 -132 -67 -219t-189 -111q138 -18 230 -119.5t92 -232.5q0 -186 -120.5 -293.5t-335.5 -107.5h-469zM254 719v-665h421q185 0 290.5 91.5t105.5 253.5q0 138 -102 227.5t-273 92.5h-442zM254 773h349q199 0 300 76.5 t101 237.5q0 310 -409 315h-341v-629z"/> +<glyph glyph-name="C" horiz-adv-x="1327" unicode="C" d="M1190 446q-21 -225 -155 -345.5t-364 -120.5q-155 0 -274.5 78.5t-185.5 223t-67 330.5v225q0 186 65 332.5t185.5 226.5t276.5 80q228 0 363 -120t156 -344h-54q-23 201 -140 305.5t-325 104.5q-212 0 -342.5 -160t-130.5 -429v-214q0 -172 58 -304.5t166.5 -206.5 t248.5 -74q209 0 326.5 103t138.5 309h54z"/> +<glyph glyph-name="D" horiz-adv-x="1340" unicode="D" d="M200 0v1456h403q169 0 306 -80t215 -224.5t80 -323.5v-189q0 -182 -76.5 -328t-213.5 -228t-306 -83h-408zM254 1402v-1348h349q153 0 278.5 74.5t196.5 208t72 296.5v187q0 163 -69.5 296t-194 208.5t-275.5 77.5h-357z"/> +<glyph glyph-name="E" horiz-adv-x="1166" unicode="E" d="M984 722h-730v-668h832v-54h-886v1456h886v-54h-832v-626h730v-54z"/> +<glyph glyph-name="F" horiz-adv-x="1172" unicode="F" d="M1000 716h-746v-716h-54v1456h902v-54h-848v-630h746v-56z"/> +<glyph glyph-name="G" horiz-adv-x="1406" unicode="G" d="M1226 156q-55 -76 -193 -126t-304 -50q-162 0 -289 79t-198.5 223t-73.5 326v250q0 179 69 321t194 219.5t281 77.5q217 0 353.5 -111t158.5 -303h-54q-27 174 -145 267t-313 93q-220 0 -355 -157t-135 -413v-232q0 -171 63.5 -305t179 -207.5t264.5 -73.5q146 0 271 43 t172 104v424h-445v55h499v-504z"/> +<glyph glyph-name="H" horiz-adv-x="1438" unicode="H" d="M1238 0h-54v722h-930v-722h-54v1456h54v-680h930v680h54v-1456z"/> +<glyph glyph-name="I" horiz-adv-x="534" unicode="I" d="M294 0h-54v1456h54v-1456z"/> +<glyph glyph-name="J" horiz-adv-x="1125" unicode="J" d="M876 1456h54v-1014q0 -211 -115 -336.5t-305 -125.5q-204 0 -312 109t-108 312h54q0 -178 91.5 -272.5t274.5 -94.5q160 0 261.5 107t104.5 291v1024z"/> +<glyph glyph-name="K" horiz-adv-x="1300" unicode="K" d="M487 766l-233 -215v-551h-54v1456h54v-842l240 235l604 607h78l-649 -653l699 -803h-70z"/> +<glyph glyph-name="L" horiz-adv-x="1057" unicode="L" d="M255 54h747v-54h-802v1456h55v-1402z"/> +<glyph glyph-name="M" horiz-adv-x="1756" unicode="M" d="M277 1456l599 -1377l601 1377h79v-1456h-54v1376l-604 -1376h-43l-601 1369v-1369h-54v1456h77z"/> +<glyph glyph-name="N" horiz-adv-x="1449" unicode="N" d="M1249 0h-54l-940 1364v-1364h-55v1456h55l940 -1361v1361h54v-1456z"/> +<glyph glyph-name="O" horiz-adv-x="1364" unicode="O" d="M1231 619q0 -189 -67.5 -334.5t-192.5 -225t-288 -79.5q-246 0 -398 175t-152 472v210q0 188 67.5 334t193 225.5t287.5 79.5q163 0 288.5 -79.5t193.5 -226t68 -333.5v-218zM1177 839q0 264 -134 423.5t-362 159.5q-225 0 -359 -158.5t-134 -431.5v-213 q0 -174 60.5 -307.5t172.5 -205.5t262 -72q228 0 361 159t133 434v212z"/> +<glyph glyph-name="P" horiz-adv-x="1230" unicode="P" d="M254 615v-615h-54v1456h455q223 0 346.5 -112.5t123.5 -312.5q0 -198 -120.5 -306t-342.5 -110h-408zM254 669h401q197 0 306.5 95t109.5 265q0 176 -109.5 274.5t-306.5 98.5h-401v-733z"/> +<glyph glyph-name="Q" horiz-adv-x="1364" unicode="Q" d="M1231 619q0 -204 -79.5 -358t-227.5 -228l267 -261l-39 -35l-284 273q-90 -30 -185 -30q-246 0 -398 175t-152 472v210q0 188 67.5 334t193 225.5t287.5 79.5q163 0 288.5 -79.5t193.5 -226t68 -333.5v-218zM1177 839q0 264 -134 423.5t-362 159.5q-225 0 -359 -158.5 t-134 -431.5v-213q0 -174 60.5 -307.5t172.5 -205.5t262 -72q228 0 361 159t133 434v212z"/> +<glyph glyph-name="R" horiz-adv-x="1340" unicode="R" d="M754 623h-505v-623h-54v1456h464q219 0 348.5 -113t129.5 -307q0 -149 -92.5 -260.5t-235.5 -138.5l389 -623v-14h-57zM249 677h459q168 0 271.5 102t103.5 257q0 170 -114.5 268t-313.5 98h-406v-725z"/> +<glyph glyph-name="S" horiz-adv-x="1211" unicode="S" d="M1072 349q0 93 -43.5 157.5t-137 114t-282.5 101.5t-283.5 105t-138.5 123t-44 170q0 159 134 257.5t349 98.5q140 0 251.5 -54.5t172.5 -153t61 -222.5h-54q0 163 -120 269.5t-311 106.5q-192 0 -310.5 -85.5t-118.5 -214.5q0 -131 103 -211t340 -141.5t347 -142.5 q140 -103 140 -276q0 -110 -62 -194.5t-176 -130.5t-256 -46q-158 0 -284 52.5t-189.5 149.5t-63.5 229h54q0 -179 134 -278t349 -99q191 0 315 87.5t124 227.5z"/> +<glyph glyph-name="T" horiz-adv-x="1224" unicode="T" d="M1169 1402h-530v-1402h-54v1402h-530v54h1114v-54z"/> +<glyph glyph-name="U" horiz-adv-x="1365" unicode="U" d="M1180 1456v-986q0 -231 -134 -360.5t-363 -129.5t-363 129.5t-135 356.5v990h54v-984q0 -202 121.5 -320t322.5 -118t322 118t121 321v983h54z"/> +<glyph glyph-name="V" horiz-adv-x="1223" unicode="V" d="M583 142l29 -88l29 88l489 1314h59l-544 -1456h-66l-544 1456h59z"/> +<glyph glyph-name="W" horiz-adv-x="1855" unicode="W" d="M489 90l66 240l344 1126h60l342 -1126l65 -240l68 240l300 1126h59l-392 -1456h-61l-361 1214l-51 154l-49 -154l-364 -1214h-61l-393 1456h60l302 -1126z"/> +<glyph glyph-name="X" horiz-adv-x="1223" unicode="X" d="M611 785l470 671h68l-504 -713l523 -743h-67l-490 701l-492 -701h-65l523 743l-504 713h68z"/> +<glyph glyph-name="Y" horiz-adv-x="1223" unicode="Y" d="M609 602l510 854h66l-549 -903v-553h-54v553l-549 903h72z"/> +<glyph glyph-name="Z" horiz-adv-x="1224" unicode="Z" d="M168 54h962v-54h-1036v44l929 1359h-889v53h964v-38z"/> +<glyph glyph-name="bracketleft" horiz-adv-x="439" unicode="[" d="M464 1610h-229v-1868h229v-54h-283v1976h283v-54z"/> +<glyph glyph-name="backslash" horiz-adv-x="774" unicode="\" d="M57 1456h58l608 -1581h-58z"/> +<glyph glyph-name="bracketright" horiz-adv-x="439" unicode="]" d="M-8 1664h283v-1976h-283v54h228v1868h-228v54z"/> +<glyph glyph-name="asciicircum" horiz-adv-x="849" unicode="^" d="M416 1382l-266 -653h-59l299 727h52l299 -727h-61z"/> +<glyph glyph-name="underscore" horiz-adv-x="845" unicode="_" d="M845 -54h-846v54h846v-54z"/> +<glyph glyph-name="grave" horiz-adv-x="537" unicode="`" d="M403 1250h-59l-195 266h66z"/> +<glyph glyph-name="a" horiz-adv-x="1081" unicode="a" d="M871 0q-20 69 -20 198q-64 -104 -175 -161t-251 -57q-150 0 -241.5 81.5t-91.5 212.5q0 149 134.5 238.5t357.5 91.5h267v158q0 136 -85.5 211t-244.5 75q-148 0 -247 -76t-99 -188l-54 2q0 132 116 224t284 92q175 0 278 -87.5t106 -246.5v-517q0 -178 28 -242v-9h-62z M425 33q152 0 261.5 68t164.5 191v257h-250q-232 0 -355 -92q-100 -75 -100 -187q0 -99 79 -168t200 -69z"/> +<glyph glyph-name="b" d="M999 531q0 -253 -109 -402t-297 -149q-122 0 -218 50.5t-151 140.5v-171h-54v1536h54v-651q57 107 150.5 162t216.5 55q190 0 299 -145.5t109 -408.5v-17zM943 552q0 233 -92.5 364.5t-258.5 131.5q-136 0 -230.5 -70t-137.5 -208v-496q43 -115 137.5 -177.5t232.5 -62.5 q167 0 258 133t91 385z" unicode="b"/> +<glyph glyph-name="c" horiz-adv-x="1039" unicode="c" d="M539 34q147 0 242.5 78t104.5 216h54q-8 -157 -121 -252.5t-280 -95.5q-203 0 -322.5 147t-119.5 399v36q0 246 119.5 393t320.5 147q172 0 284 -103t119 -274h-54q-7 146 -102.5 234.5t-246.5 88.5q-181 0 -283.5 -130.5t-102.5 -362.5v-35q0 -227 103.5 -356.5 t284.5 -129.5z"/> +<glyph glyph-name="d" d="M122 552q0 259 109 404.5t299 145.5q122 0 215.5 -55t151.5 -164v653h54v-1536h-54v173q-55 -92 -151 -142.5t-218 -50.5q-188 0 -297 149t-109 409v14zM178 531q0 -230 91 -363.5t258 -133.5q134 0 229 59.5t141 174.5v507q-93 273 -368 273q-166 0 -258.5 -131 t-92.5 -386z" unicode="d"/> +<glyph glyph-name="e" horiz-adv-x="1032" unicode="e" d="M561 -20q-131 0 -240.5 70.5t-171.5 193.5t-62 273v45q0 150 60 275t165 195t229 70q181 0 296 -129t115 -339v-57h-811v-59q0 -132 55.5 -244.5t153 -176.5t211.5 -64q109 0 185.5 36.5t135.5 112.5l38 -27q-121 -175 -359 -175zM541 1048q-158 0 -268 -117.5 t-129 -299.5h754v13q0 110 -46.5 204.5t-128 147t-182.5 52.5z"/> +<glyph glyph-name="f" horiz-adv-x="645" unicode="f" d="M254 0v1027h-188v55h188v158q1 150 75.5 233.5t207.5 83.5q74 0 128 -17l-8 -52q-52 15 -119 15q-107 0 -168.5 -69.5t-61.5 -197.5v-154h286v-55h-286v-1027h-54z"/> +<glyph glyph-name="g" horiz-adv-x="1123" unicode="g" d="M121 552q0 259 109 404.5t299 145.5q121 0 215 -55.5t151 -162.5v198h55v-1063q0 -214 -110 -334.5t-299 -120.5q-109 0 -199.5 47t-154.5 135l38 36q63 -80 138 -122.5t176 -42.5q167 0 260 101.5t96 286.5v166q-56 -92 -151.5 -141.5t-216.5 -49.5q-188 0 -297 149 t-109 409v14zM176 531q0 -232 92 -364.5t258 -132.5q137 0 233 63.5t136 178.5v491q-88 281 -367 281q-167 0 -259.5 -131t-92.5 -386z"/> +<glyph glyph-name="h" d="M226 830q53 126 156 199t228 73q174 0 258.5 -98.5t85.5 -297.5v-706h-54v708q-1 174 -71 257.5t-222 83.5q-140 0 -242.5 -99.5t-138.5 -256.5v-693h-54v1536h54v-706z" unicode="h"/> +<glyph glyph-name="i" horiz-adv-x="422" unicode="i" d="M239 0h-54v1082h54v-1082zM157 1420q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="j" horiz-adv-x="445" unicode="j" d="M240 1082v-1211q0 -150 -75 -229t-210 -79q-49 0 -98 20l3 52q48 -18 95 -18q112 0 171.5 66.5t59.5 187.5v1211h54zM163 1420q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="k" horiz-adv-x="969" unicode="k" d="M385 585l-2 -2l-157 -135v-448h-54v1536h54v-1029l127 120l492 455h77l-497 -461l528 -621h-70z"/> +<glyph glyph-name="l" horiz-adv-x="422" unicode="l" d="M239 0h-54v1536h54v-1536z"/> +<glyph glyph-name="m" horiz-adv-x="1836" unicode="m" d="M946 0h-54v727q-1 163 -71.5 242.5t-224.5 79.5q-178 0 -291 -157q-67 -94 -89 -208v-684h-55v1082h55v-256q55 132 157 204t226 72q136 0 222.5 -60t113.5 -196q48 117 156 186.5t242 69.5q175 0 260.5 -99t86.5 -297v-706h-54v702q0 178 -71.5 263.5t-224.5 83.5 q-197 -3 -312 -157q-66 -89 -72 -172v-720z"/> +<glyph glyph-name="n" d="M226 830q53 126 156 199t228 73q174 0 258.5 -98.5t85.5 -297.5v-706h-54v708q-1 174 -71 257.5t-222 83.5q-140 0 -242.5 -99.5t-138.5 -256.5v-693h-54v1082h54v-252z" unicode="n"/> +<glyph glyph-name="o" horiz-adv-x="1127" unicode="o" d="M90 562q0 155 59.5 278.5t168 192.5t245.5 69q136 0 244 -67t168.5 -190t61.5 -277v-48q0 -156 -59 -279t-167.5 -192t-245.5 -69t-245.5 68t-168.5 190.5t-61 275.5v48zM144 520q0 -135 53.5 -247.5t149 -175.5t218.5 -63q185 0 301.5 139t116.5 358v31q0 133 -54 246 t-149.5 176.5t-216.5 63.5q-185 0 -302 -141t-117 -355v-32z"/> +<glyph glyph-name="p" d="M999 531q0 -253 -109 -402t-297 -149q-123 0 -219 50t-150 138v-584h-54v1498h54v-193q56 103 151 158t216 55q190 0 299 -145.5t109 -408.5v-17zM944 552q0 233 -92.5 364.5t-259.5 131.5q-136 0 -231 -70.5t-137 -202.5v-506q42 -112 137.5 -173.5t232.5 -61.5 q166 0 258 132t92 386z" unicode="p"/> +<glyph glyph-name="q" d="M122 552q0 259 109 404.5t299 145.5q121 0 216 -55t151 -158v193h54v-1498h-54v584q-58 -91 -153.5 -139.5t-215.5 -48.5q-188 0 -297 149t-109 409v14zM178 531q0 -230 91 -363.5t258 -133.5q134 0 229 59.5t141 174.5v507q-47 135 -142 204t-226 69q-166 0 -258.5 -131 t-92.5 -386z" unicode="q"/> +<glyph glyph-name="r" horiz-adv-x="685" unicode="r" d="M649 1043l-70 6q-138 0 -231 -89.5t-122 -250.5v-709h-54v1082h54v-225q44 113 132 179t221 66q47 0 76 -11z"/> +<glyph glyph-name="s" horiz-adv-x="1019" unicode="s" d="M839 265q0 197 -336 268q-202 43 -281 110.5t-79 185.5q0 119 100.5 196t261.5 77q175 0 281 -83.5t106 -225.5h-55q0 109 -92 182t-240 73q-142 0 -225 -62t-83 -155q0 -73 31 -114.5t101 -75t204 -64.5t212 -73t113 -99.5t35 -140.5q0 -128 -105 -206t-275 -78 q-182 0 -293.5 82.5t-111.5 212.5h54q8 -114 100.5 -177.5t250.5 -63.5q145 0 235.5 67.5t90.5 163.5z"/> +<glyph glyph-name="t" horiz-adv-x="648" unicode="t" d="M293 1374v-292h246v-55h-246v-768q0 -115 37.5 -170t125.5 -55q44 0 107 9l9 -51q-33 -12 -113 -12q-118 0 -169 65.5t-52 206.5v775h-200v55h200v292h55z"/> +<glyph glyph-name="u" d="M897 0v175q-48 -90 -140 -142.5t-233 -52.5q-177 0 -265.5 103.5t-90.5 301.5v697h54v-699q2 -172 78 -260.5t222 -88.5q155 0 252 73t123 214v761h55v-1082h-55z" unicode="u"/> +<glyph glyph-name="v" horiz-adv-x="978" unicode="v" d="M490 86l389 996h58l-421 -1082h-53l-420 1082h58z"/> +<glyph glyph-name="w" horiz-adv-x="1550" unicode="w" d="M366 313l59 -233l317 1002h55l315 -1002l61 233l220 769h63l-315 -1082h-54l-267 813l-51 194l-55 -194l-263 -813h-54l-314 1082h62z"/> +<glyph glyph-name="x" horiz-adv-x="978" unicode="x" d="M489 602l345 480h68l-380 -527l400 -555h-67l-367 508l-366 -508h-67l400 555l-380 527h68z"/> +<glyph glyph-name="y" horiz-adv-x="978" unicode="y" d="M503 84l7 20l374 978h60l-484 -1270l-24 -60q-78 -189 -258 -189q-58 0 -80 11l-1 51q32 -9 73 -9q85 0 141 49.5t97 161.5l66 179l-431 1076h59z"/> +<glyph glyph-name="z" horiz-adv-x="978" unicode="z" d="M160 54h770v-54h-843v44l711 983h-680v55h753v-48z"/> +<glyph glyph-name="braceleft" horiz-adv-x="660" unicode="{" d="M642 -441q-160 50 -239.5 163t-79.5 298v241q0 282 -250 282v66q250 0 250 280v247q1 185 80.5 298t238.5 163l15 -45q-280 -91 -280 -427v-228q0 -272 -211 -321q211 -53 211 -321v-229q0 -325 285 -421z"/> +<glyph glyph-name="bar" horiz-adv-x="406" unicode="|" d="M235 -270h-54v1726h54v-1726z"/> +<glyph glyph-name="braceright" horiz-adv-x="660" unicode="}" d="M0 -395q284 97 284 417v233q0 268 211 321q-211 49 -211 321v227q0 338 -279 428l14 45q160 -50 238.5 -162.5t80.5 -293.5v-249q0 -283 250 -283v-66q-250 0 -250 -285v-237q0 -186 -78.5 -298.5t-240.5 -163.5z"/> +<glyph glyph-name="asciitilde" horiz-adv-x="1412" unicode="~" d="M1246 752q0 -138 -73.5 -223.5t-195.5 -85.5q-71 0 -132 28t-158.5 115t-147.5 110.5t-111 23.5q-100 0 -156.5 -65t-56.5 -193h-55q0 143 71.5 227.5t196.5 84.5q72 0 135 -29.5t160 -116t147 -109.5t107 -23q101 0 157 67.5t56 189.5z"/> +<glyph glyph-name="exclamdown" horiz-adv-x="406" unicode="¡" d="M179 696h54v-1055h-54v1055zM253 1048q0 -23 -16 -39.5t-39 -16.5t-39.5 16.5t-16.5 39.5t16.5 39t39.5 16t39 -16t16 -39z"/> +<glyph glyph-name="cent" horiz-adv-x="1110" unicode="¢" d="M576 34q147 0 242.5 78t104.5 216h54q-8 -150 -113 -244.5t-260 -102.5v-226h-55v226q-191 10 -303 155t-112 390v36q0 240 112 384.5t303 154.5v217h55v-217q163 -11 264.5 -112t108.5 -264h-54q-7 146 -102.5 234.5t-246.5 88.5q-181 0 -283.5 -130.5t-102.5 -362.5 v-35q0 -227 103.5 -356.5t284.5 -129.5z"/> +<glyph glyph-name="sterling" horiz-adv-x="1150" unicode="£" d="M360 667l10 -331q4 -194 -67 -282h757l1 -54h-962v54h120q48 14 73.5 94.5t23.5 187.5l-10 331h-211v54h209l-9 318q0 204 99 320.5t267 116.5q173 0 273.5 -104t100.5 -283h-54q0 159 -85.5 246t-234.5 87q-147 0 -229.5 -100t-82.5 -283l9 -318h370v-54h-368z"/> +<glyph glyph-name="currency" horiz-adv-x="1502" unicode="¤" d="M1159 156q-81 -83 -187 -129.5t-227 -46.5t-227.5 46t-187.5 128l-176 -180l-40 39l179 182q-144 176 -144 413q0 246 154 424l-189 193l40 39l188 -192q171 162 403 162q118 0 220.5 -43.5t182.5 -120.5l191 195l41 -40l-193 -196q152 -178 152 -421q0 -234 -141 -409 l182 -186l-41 -40zM204 608q0 -154 73.5 -288t198.5 -210.5t269 -76.5q143 0 268 76.5t198.5 210.5t73.5 288q0 153 -72.5 285.5t-198 210t-269.5 77.5t-270 -77.5t-198.5 -210t-72.5 -285.5z"/> +<glyph glyph-name="yen" horiz-adv-x="1207" unicode="Â¥" d="M1079 1456h66l-489 -780h424v-55h-452v-240h452v-55h-452v-326h-54v326h-450v55h450v240h-450v55h421l-487 780h65l452 -718l24 -51h5l24 51z"/> +<glyph glyph-name="brokenbar" horiz-adv-x="398" unicode="¦" d="M172 -270v752h54v-752h-54zM226 698h-54v758h54v-758z"/> +<glyph glyph-name="section" horiz-adv-x="1223" unicode="§" d="M1094 431q0 -105 -82 -176t-222 -91q142 -54 201 -127.5t59 -185.5q0 -160 -121.5 -253t-328.5 -93q-226 0 -355.5 112.5t-129.5 318.5l54 2q0 -180 116 -279.5t315 -99.5q183 0 289 79.5t106 210.5q0 88 -36.5 141.5t-118.5 94.5t-233 81q-271 64 -378.5 153.5 t-107.5 231.5q0 109 77 180t209 91q-129 51 -185 125t-56 182q0 157 122.5 252t329.5 95q215 0 334.5 -112.5t119.5 -318.5h-54q0 167 -109 272t-291 105q-184 0 -291 -77t-107 -213q0 -91 36 -145t118.5 -96t241.5 -87q208 -52 298.5 -99t135 -112.5t44.5 -161.5zM590 766 q-59 13 -108 30q-143 -5 -225 -70.5t-82 -172.5q0 -93 39 -147t133.5 -97.5t345.5 -112.5q157 2 252 66.5t95 165.5q0 85 -41 141t-134 101t-275 96z"/> +<glyph glyph-name="dieresis" horiz-adv-x="906" unicode="¨" d="M184 1421q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM629 1421q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="copyright" horiz-adv-x="1666" unicode="©" d="M1124 616q0 -152 -78.5 -233t-219.5 -81q-144 0 -232 107.5t-88 283.5v75q0 173 89 280t231 107q143 0 221 -82.5t78 -230.5h-52q0 131 -64 195.5t-183 64.5t-192 -92t-73 -247v-74q0 -149 72.5 -240.5t192.5 -91.5q246 0 246 259h52zM179 729q0 -188 88.5 -349.5 t240 -253.5t325.5 -92q176 0 328 94t239 254.5t87 346.5q0 187 -87 346.5t-239.5 252.5t-327.5 93q-173 0 -325 -91t-240.5 -251.5t-88.5 -349.5zM123 729q0 202 93.5 375t259 272.5t357.5 99.5t357.5 -99.5t259 -272.5t93.5 -375q0 -199 -91 -371t-256.5 -275.5 t-362.5 -103.5t-362.5 103.5t-256.5 275.5t-91 371z"/> +<glyph glyph-name="ordfeminine" horiz-adv-x="898" unicode="ª" d="M680 705q-18 54 -22 118q-39 -60 -104.5 -96t-136.5 -36q-121 0 -185 57t-64 152q0 109 83.5 170.5t235.5 61.5h170v69q0 104 -49.5 162.5t-149.5 58.5q-109 0 -173 -44t-64 -135h-54q0 102 81 167.5t210 65.5q116 0 185 -72t69 -204v-316q0 -92 26 -179h-58zM418 746 q70 0 144.5 47t94.5 106v179h-167q-268 0 -268 -174q0 -158 196 -158z"/> +<glyph glyph-name="guillemotleft" horiz-adv-x="905" unicode="«" d="M216 525l294 -379h-70l-295 370v19l295 370h70zM503 525l294 -379h-70l-295 370v19l295 370h70z"/> +<glyph glyph-name="logicalnot" horiz-adv-x="1101" unicode="¬" d="M915 396h-54v304h-739v53h793v-357z"/> +<glyph glyph-name="registered" horiz-adv-x="1674" unicode="®" d="M115 729q0 202 93.5 375t259 272.5t357.5 99.5t357.5 -99.5t259 -272.5t93.5 -375q0 -199 -91 -371t-256.5 -275.5t-362.5 -103.5t-362.5 103.5t-256.5 275.5t-91 371zM170 729q0 -186 87 -346.5t239 -254.5t329 -94q176 0 328 94t239 254.5t87 346.5q0 187 -87 346.5 t-239.5 252.5t-327.5 93q-176 0 -328.5 -93t-239.5 -252.5t-87 -346.5zM648 678v-352h-55v830h239q289 0 289 -240q0 -144 -153 -206q132 -39 132 -208q0 -111 17 -160v-16h-59q-14 36 -14 176q0 92 -38.5 133t-132.5 43h-225zM648 734h205q96 0 154.5 50.5t58.5 132.5 q0 98 -51.5 140t-168.5 44h-198v-367z"/> +<glyph glyph-name="macron" horiz-adv-x="811" unicode="¯" d="M719 1403h-627v53h627v-53z"/> +<glyph glyph-name="degree" horiz-adv-x="783" unicode="°" d="M156 1236q0 97 69 168.5t167 71.5q96 0 164 -71.5t68 -168.5q0 -98 -68 -167.5t-164 -69.5q-98 0 -167 69t-69 168zM211 1236q0 -77 51 -129t130 -52q76 0 126 50.5t50 130.5q0 82 -50.5 133.5t-125.5 51.5q-78 0 -129.5 -53t-51.5 -132z"/> +<glyph glyph-name="plusminus" horiz-adv-x="1077" unicode="±" d="M569 805h419v-54h-419v-462h-54v462h-443v54h443v462h54v-462zM957 -1h-835v54h835v-54z"/> +<glyph glyph-name="uni00B2" horiz-adv-x="728" unicode="²" d="M651 664h-543v44l290 295q79 77 116 135t37 109q0 77 -49 122.5t-146 45.5q-102 0 -159 -52t-57 -137h-54q0 103 75.5 170.5t194.5 67.5q116 0 182.5 -59t66.5 -157q0 -94 -113 -217l-66 -70l-251 -248h476v-49z"/> +<glyph glyph-name="uni00B3" horiz-adv-x="728" unicode="³" d="M270 1090h75q101 1 160 45.5t59 113.5q0 77 -53.5 121.5t-148.5 44.5q-91 0 -151.5 -46.5t-60.5 -122.5h-53q0 96 75.5 157t189.5 61q119 0 187.5 -58t68.5 -160q0 -57 -40 -106.5t-115 -72.5q86 -20 130 -70t44 -122q0 -100 -74 -161t-196 -61q-124 0 -205.5 63.5 t-81.5 164.5h54q0 -78 65 -129t168 -51t159.5 46t56.5 127q0 167 -253 167h-60v49z"/> +<glyph glyph-name="acute" horiz-adv-x="511" unicode="´" d="M315 1516h66l-195 -266h-60z"/> +<glyph glyph-name="uni00B5" d="M223 1082v-661q3 -189 79.5 -288t226.5 -99q176 0 265.5 90.5t104.5 289.5v668h54v-1082h-51l-3 203q-96 -223 -361 -223q-114 0 -193.5 50t-121.5 141v-587h-52v1498h52z" unicode="µ"/> +<glyph glyph-name="paragraph" horiz-adv-x="946" unicode="¶" d="M716 0v520h-127q-150 0 -261 58t-170 164.5t-59 245.5q0 213 133 340.5t361 127.5h177v-1456h-54z"/> +<glyph glyph-name="periodcentered" horiz-adv-x="472" unicode="·" d="M179 706q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="cedilla" horiz-adv-x="490" unicode="¸" d="M207 0l-11 -76q177 -16 177 -169q0 -85 -76 -137.5t-209 -52.5l-7 49q101 0 169 39.5t68 101.5q0 56 -38.5 84t-150.5 40l25 121h53z"/> +<glyph glyph-name="uni00B9" horiz-adv-x="728" unicode="¹" d="M433 664h-54v722l-248 -81v53l293 97h9v-791z"/> +<glyph glyph-name="ordmasculine" horiz-adv-x="914" unicode="º" d="M148 1141q0 150 83.5 242.5t220.5 92.5t221 -92t84 -248v-112q0 -151 -83.5 -242.5t-219.5 -91.5q-137 0 -221.5 91t-84.5 248v112zM202 1024q0 -131 66.5 -205.5t185.5 -74.5q116 0 183 76.5t67 207.5v113q0 128 -68.5 204.5t-183.5 76.5q-114 0 -182 -76t-68 -211v-111 z"/> +<glyph glyph-name="guillemotright" horiz-adv-x="897" unicode="»" d="M198 940l294 -380v-19l-294 -370h-70l293 379l-293 390h70zM488 940l294 -380v-19l-294 -370h-70l293 379l-293 390h70z"/> +<glyph glyph-name="onequarter" horiz-adv-x="1467" unicode="¼" d="M447 664h-54v722l-248 -81v53l293 97h9v-791zM386 139l-45 31l711 1138l45 -31zM1225 253h147v-49h-147v-204h-53v204h-423l-1 32l417 553h60v-536zM818 253h354v474l-44 -71z"/> +<glyph glyph-name="onehalf" horiz-adv-x="1508" unicode="½" d="M343 139l-45 31l711 1138l45 -31zM424 664h-54v722l-248 -81v53l293 97h9v-791zM1392 0h-543v44l290 295q79 77 116 135t37 109q0 77 -49 122.5t-146 45.5q-102 0 -159 -52t-57 -137h-54q0 103 75.5 170.5t194.5 67.5q116 0 182.5 -59t66.5 -157q0 -94 -113 -217l-66 -70 l-251 -248h476v-49z"/> +<glyph glyph-name="threequarters" horiz-adv-x="1586" unicode="¾" d="M548 139l-45 31l711 1138l45 -31zM1365 253h147v-49h-147v-204h-53v204h-423l-1 32l417 553h60v-536zM958 253h354v474l-44 -71zM314 1090h75q101 1 160 45.5t59 113.5q0 77 -53.5 121.5t-148.5 44.5q-91 0 -151.5 -46.5t-60.5 -122.5h-53q0 96 75.5 157t189.5 61 q119 0 187.5 -58t68.5 -160q0 -57 -40 -106.5t-115 -72.5q86 -20 130 -70t44 -122q0 -100 -74 -161t-196 -61q-124 0 -205.5 63.5t-81.5 164.5h54q0 -78 65 -129t168 -51t159.5 46t56.5 127q0 167 -253 167h-60v49z"/> +<glyph glyph-name="questiondown" horiz-adv-x="912" unicode="¿" d="M514 695q-2 -102 -11.5 -138.5t-33.5 -69.5t-80 -84l-78 -76q-79 -79 -114 -161t-35 -183q0 -149 79 -230t220 -81q138 0 217.5 82.5t83.5 224.5h54q-2 -167 -97.5 -263.5t-257.5 -96.5q-165 0 -259 100.5t-94 265.5q0 121 52 222.5t201 237.5q51 40 73.5 81t24.5 100 l1 69h54zM538 1046q0 -23 -16 -39.5t-39 -16.5t-39.5 16.5t-16.5 39.5t16.5 39t39.5 16t39 -16t16 -39z"/> +<glyph glyph-name="AE" horiz-adv-x="1816" unicode="Æ" d="M1768 0h-752l-18 425h-627l-256 -425h-65l881 1456h776v-54h-696l26 -616h588v-54h-586l28 -678h701v-54zM403 478h593l-39 920z"/> +<glyph glyph-name="multiply" horiz-adv-x="1052" unicode="×" d="M98 36l384 393l-357 364l39 39l356 -364l357 364l39 -39l-357 -364l385 -393l-39 -37l-384 391l-384 -391z"/> +<glyph glyph-name="Oslash" horiz-adv-x="1364" unicode="Ø" d="M1231 619q0 -189 -67.5 -334.5t-192.5 -225t-288 -79.5q-195 0 -334 112l-106 -167h-66l130 205q-174 176 -174 499v208q0 188 67.5 334t193 225.5t287.5 79.5q231 0 382 -157l111 176h66l-140 -220q130 -172 131 -436v-220zM188 619q0 -284 149 -443l696 1097 q-132 149 -352 149q-225 0 -359 -158.5t-134 -431.5v-213zM1177 839q0 237 -107 388l-692 -1090q124 -103 305 -103q228 0 361 159t133 434v212z"/> +<glyph glyph-name="Thorn" horiz-adv-x="1219" unicode="Þ" d="M254 1456v-313h377q206 -2 325 -113t119 -292q0 -180 -117.5 -290t-318.5 -114h-385v-334h-54v1456h54zM254 1089v-701h371q181 0 288.5 98t107.5 250q0 153 -103.5 251t-277.5 102h-386z"/> +<glyph glyph-name="germandbls" horiz-adv-x="1183" unicode="ß" d="M218 0h-54v1143q0 191 84.5 291.5t244.5 100.5q126 0 218.5 -79.5t92.5 -198.5q0 -100 -59.5 -207t-59.5 -221q0 -59 42.5 -112t143.5 -128.5t146 -143.5t45 -148q0 -90 -52 -162.5t-139 -114t-176 -41.5q-91 0 -182.5 27.5t-129.5 61.5l25 49q44 -35 125 -60t154 -25 q135 0 228 79t93 195q0 65 -41.5 122t-145 133t-147 137.5t-43.5 132.5q0 111 56.5 224t56.5 204q0 90 -73 156t-168 66q-281 0 -285 -328v-1153z"/> +<glyph glyph-name="ae" horiz-adv-x="1735" unicode="æ" d="M1268 -20q-147 0 -247.5 67.5t-152.5 182.5v-12h1q-48 -107 -162.5 -172.5t-258.5 -65.5q-168 0 -261.5 82t-93.5 222q0 158 110.5 251t312.5 95h297v90q0 156 -72 242t-220 86q-158 0 -252.5 -76t-94.5 -201l-53 7q0 145 111.5 234.5t288.5 89.5q141 0 228.5 -74 t110.5 -214q56 137 159.5 212.5t233.5 75.5q186 0 295 -116.5t109 -329.5v-79h-787v-77q0 -218 104.5 -342t293.5 -124q204 0 332 130l30 -42q-79 -79 -165.5 -110.5t-196.5 -31.5zM447 32q81 0 159 28.5t135.5 75.5t71.5 89v350h-301q-167 -3 -265.5 -83t-98.5 -212 q0 -116 76.5 -182t222.5 -66zM1253 1048q-153 0 -257 -113.5t-123 -302.5h730v32q0 174 -93.5 279t-256.5 105z"/> +<glyph glyph-name="eth" horiz-adv-x="1183" unicode="ð" d="M802 1308q121 -125 180 -294.5t59 -398.5v-80q0 -159 -51.5 -285.5t-146.5 -198t-214 -71.5q-129 0 -233.5 63t-163.5 175t-59 247q0 231 113 359.5t315 128.5q113 0 214.5 -44.5t161.5 -128.5q-20 168 -78 289t-147 211l-235 -131l-28 48l220 123q-138 121 -371 207 l20 50q252 -92 402 -229l202 113l29 -48zM987 617l-1 55q-46 105 -149 164t-236 59q-177 0 -275 -113.5t-98 -316.5q0 -115 51.5 -215t143.5 -156t210 -56q156 0 253 133.5t101 348.5v97z"/> +<glyph glyph-name="divide" horiz-adv-x="1159" unicode="÷" d="M1071 686h-998v52h998v-52zM529 1079q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM529 301q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="oslash" d="M87 562q0 155 59.5 278.5t168 192.5t245.5 69q120 0 224 -55l84 172h63l-99 -203q95 -70 148.5 -187t53.5 -267v-42q0 -156 -59 -279t-167.5 -192t-245.5 -69q-112 0 -210 48l-84 -173h-63l98 201q-103 69 -159.5 191.5t-56.5 274.5v40zM141 520q0 -132 49.5 -240.5 t136.5 -172.5l432 888q-88 53 -199 53q-185 0 -302 -141t-117 -355v-32zM980 562q0 122 -45.5 228t-128.5 173l-430 -886q83 -43 186 -43q185 0 301.5 139t116.5 358v31z" unicode="ø"/> +<glyph glyph-name="thorn" d="M999 531q0 -253 -109 -402t-297 -149q-123 0 -219 50t-150 138v-584h-54v1952h54v-647q56 103 151 158t216 55q190 0 299 -145.5t109 -408.5v-17zM944 552q0 233 -92.5 364.5t-259.5 131.5q-136 0 -231 -70.5t-137 -202.5v-506q42 -112 137.5 -173.5t232.5 -61.5 q166 0 258 132t92 386z" unicode="þ"/> +<glyph glyph-name="dotlessi" horiz-adv-x="406" unicode="ı" d="M235 0h-54v1082h54v-1082z"/> +<glyph glyph-name="OE" horiz-adv-x="1873" unicode="Å’" d="M1801 0h-840q-199 -21 -330 -21q-150 0 -268 74.5t-183.5 209t-67.5 302.5v315q0 172 64.5 308.5t183.5 212t269 75.5q142 0 332 -20h840v-54h-832v-626h730v-54h-730v-668h832v-54zM631 33q178 0 284 13v1363q-107 13 -286 13q-209 0 -336 -147.5t-127 -399.5v-299 q0 -158 58.5 -282.5t164.5 -192.5t242 -68z"/> +<glyph glyph-name="oe" horiz-adv-x="1924" unicode="Å“" d="M92 562q0 155 59.5 278.5t168 192.5t245.5 69q166 0 284.5 -95t165.5 -260q46 161 161 258t265 97q185 0 299.5 -121t114.5 -325v-79h-811v-77q0 -126 52.5 -234t145.5 -170t202 -62q231 0 342 131l29 -42q-128 -143 -371 -143q-147 0 -266 97t-165 254 q-48 -167 -167.5 -259t-278.5 -92q-137 0 -245.5 68t-168.5 190.5t-61 275.5v48zM146 520q0 -135 53.5 -247.5t149 -175.5t218.5 -63q185 0 301.5 139t116.5 358v31q0 133 -54 246t-149.5 176.5t-216.5 63.5q-185 0 -302 -141t-117 -355v-32zM1441 1048 q-158 0 -266.5 -116.5t-127.5 -300.5h754v33q0 169 -101.5 276.5t-258.5 107.5z"/> +<glyph glyph-name="circumflex" horiz-adv-x="796" unicode="ˆ" d="M656 1274v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="ring" horiz-adv-x="586" unicode="Ëš" d="M285 1556q72 0 121.5 -51t49.5 -123t-49.5 -121t-121.5 -49q-69 0 -120 47.5t-51 122.5t50.5 124.5t120.5 49.5zM168 1382q0 -52 33 -84t84 -32t84 32t33 84q0 54 -33 87t-84 33t-84 -33t-33 -87z"/> +<glyph glyph-name="tilde" horiz-adv-x="817" unicode="Ëœ" d="M729 1472q0 -82 -50.5 -134t-125.5 -52q-81 0 -153 62.5t-134 62.5q-56 0 -88.5 -34t-32.5 -91h-55q0 80 50 129.5t126 49.5q78 0 153.5 -62t133.5 -62q54 0 87.5 36t33.5 95h55z"/> +<glyph glyph-name="endash" horiz-adv-x="1324" unicode="–" d="M1158.61 721h-1002.01v54h1002.01v-54z"/> +<glyph glyph-name="emdash" horiz-adv-x="1561" unicode="—" d="M1445.78 721h-1335.98v54h1335.98v-54z"/> +<glyph glyph-name="quoteleft" horiz-adv-x="320" unicode="‘" d="M207 1554l37 -32q-86 -108 -89 -234v-120h-54v118q4 159 106 268z"/> +<glyph glyph-name="quoteright" horiz-adv-x="320" unicode="’" d="M114 1151l-37 32q81 104 88 215l1 138h54v-117q-4 -159 -106 -268z"/> +<glyph glyph-name="quotesinglbase" horiz-adv-x="300" unicode="‚" d="M84 -182l-37 32q81 104 88 215l1 163h54v-142q-4 -159 -106 -268z"/> +<glyph glyph-name="quotedblleft" horiz-adv-x="500" unicode="“" d="M202 1554l37 -32q-86 -108 -89 -234v-120h-54v118q4 159 106 268zM387 1554l37 -32q-86 -108 -89 -234v-120h-54v118q4 159 106 268z"/> +<glyph glyph-name="quotedblright" horiz-adv-x="502" unicode="â€" d="M114 1151l-37 32q81 104 88 215l1 138h54v-117q-4 -159 -106 -268zM296 1151l-37 32q81 104 88 215l1 138h54v-117q-4 -159 -106 -268z"/> +<glyph glyph-name="quotedblbase" horiz-adv-x="481" unicode="„" d="M84 -182l-37 32q81 104 88 215l1 163h54v-142q-4 -159 -106 -268zM255 -182l-37 32q81 104 88 215l1 163h54v-142q-4 -159 -106 -268z"/> +<glyph glyph-name="bullet" horiz-adv-x="635" unicode="•" d="M155 733q0 71 45.5 115.5t120.5 44.5t121.5 -44t46.5 -119v-27q0 -71 -47 -114.5t-120 -43.5q-72 0 -119 42.5t-48 113.5v32z"/> +<glyph glyph-name="guilsinglleft" horiz-adv-x="604" unicode="‹" d="M179 560l294 -379h-70l-295 370v19l295 370h70z"/> +<glyph glyph-name="guilsinglright" horiz-adv-x="604" unicode="›" d="M176 940l294 -380v-19l-294 -370h-70l293 379l-293 390h70z"/> +<glyph glyph-name="fraction" horiz-adv-x="905" unicode="â„" d="M110 131l-45 31l711 1138l45 -31z"/> +<glyph glyph-name="uni2074" horiz-adv-x="728" unicode="â´" d="M542 917h147v-49h-147v-204h-53v204h-423l-1 32l417 553h60v-536zM135 917h354v474l-44 -71z"/> +<glyph glyph-name="Euro" d="M786 584h-455v-50q0 -239 128.5 -370t352.5 -131q118 0 220 34v-57q-105 -31 -220 -31q-249 0 -392 147.5t-143 410.5v47h-205v55h205v191h-205v56h205v42q2 257 143 402.5t390 145.5q96 0 222 -31v-58q-112 35 -222 35q-229 0 -353.5 -129t-125.5 -366v-41h455v-56h-455 v-191h455v-55z" unicode="€"/> +<glyph glyph-name="minus" horiz-adv-x="1167" unicode="−" d="M998 721h-835v54h835v-54z"/> +<glyph glyph-name="glyph162" d="M433 0h-54v722l-248 -81v53l293 97h9v-791z" horiz-adv-x="728"/> +<glyph glyph-name="glyph163" d="M651 0h-543v44l290 295q79 77 116 135t37 109q0 77 -49 122.5t-146 45.5q-102 0 -159 -52t-57 -137h-54q0 103 75.5 170.5t194.5 67.5q116 0 182.5 -59t66.5 -157q0 -94 -113 -217l-66 -70l-251 -248h476v-49z" horiz-adv-x="728"/> +<glyph glyph-name="glyph164" d="M270 426h75q101 1 160 45.5t59 113.5q0 77 -53.5 121.5t-148.5 44.5q-91 0 -151.5 -46.5t-60.5 -122.5h-53q0 96 75.5 157t189.5 61q119 0 187.5 -58t68.5 -160q0 -57 -40 -106.5t-115 -72.5q86 -20 130 -70t44 -122q0 -100 -74 -161t-196 -61q-124 0 -205.5 63.5 t-81.5 164.5h54q0 -78 65 -129t168 -51t159.5 46t56.5 127q0 167 -253 167h-60v49z" horiz-adv-x="728"/> +<glyph glyph-name="glyph165" d="M542 253h147v-49h-147v-204h-53v204h-423l-1 32l417 553h60v-536zM135 253h354v474l-44 -71z" horiz-adv-x="728"/> +<glyph glyph-name="uni00A0" horiz-adv-x="490" unicode=" "/> +<glyph glyph-name="uni00AD" horiz-adv-x="607" unicode="Â" d="M531 639h-470v54h470v-54z"/> +<glyph glyph-name="Eth" horiz-adv-x="1370" unicode="Ã" d="M230 0v713h-170v54h170v689h403q169 0 306 -80t215 -224.5t80 -323.5v-189q0 -182 -76.5 -328t-213.5 -228t-306 -83h-408zM647 713h-363v-659h339q247 0 402 166t155 427v173q0 163 -69.5 296t-194 208.5t-275.5 77.5h-357v-635h363v-54z"/> +<glyph glyph-name="Agrave" horiz-adv-x="1223" unicode="À" d="M967 435h-713l-162 -435h-59l545 1456h66l545 -1456h-59zM274 489h673l-336 902zM655 1569h-59l-195 266h66z"/> +<glyph glyph-name="Aacute" horiz-adv-x="1223" unicode="Ã" d="M967 435h-713l-162 -435h-59l545 1456h66l545 -1456h-59zM274 489h673l-336 902zM761 1835h66l-195 -266h-60z"/> +<glyph glyph-name="Acircumflex" horiz-adv-x="1223" unicode="Â" d="M967 435h-713l-162 -435h-59l545 1456h66l545 -1456h-59zM274 489h673l-336 902zM866 1593v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="Atilde" horiz-adv-x="1223" unicode="Ã" d="M967 435h-713l-162 -435h-59l545 1456h66l545 -1456h-59zM274 489h673l-336 902zM940 1806q0 -82 -50.5 -134t-125.5 -52q-81 0 -153 62.5t-134 62.5q-56 0 -88.5 -34t-32.5 -91h-55q0 80 50 129.5t126 49.5q78 0 153.5 -62t133.5 -62q54 0 87.5 36t33.5 95h55z"/> +<glyph glyph-name="Adieresis" horiz-adv-x="1223" unicode="Ä" d="M967 435h-713l-162 -435h-59l545 1456h66l545 -1456h-59zM274 489h673l-336 902zM346 1740q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM791 1740q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z "/> +<glyph glyph-name="Aring" horiz-adv-x="1223" unicode="Ã…" d="M967 435h-713l-162 -435h-59l545 1456h66l545 -1456h-59zM274 489h673l-336 902zM614 1875q72 0 121.5 -51t49.5 -123t-49.5 -121t-121.5 -49q-69 0 -120 47.5t-51 122.5t50.5 124.5t120.5 49.5zM497 1701q0 -52 33 -84t84 -32t84 32t33 84q0 54 -33 87t-84 33t-84 -33 t-33 -87z"/> +<glyph glyph-name="Ccedilla" horiz-adv-x="1327" unicode="Ç" d="M1190 446q-21 -225 -155 -345.5t-364 -120.5q-155 0 -274.5 78.5t-185.5 223t-67 330.5v225q0 186 65 332.5t185.5 226.5t276.5 80q228 0 363 -120t156 -344h-54q-23 201 -140 305.5t-325 104.5q-212 0 -342.5 -160t-130.5 -429v-214q0 -172 58 -304.5t166.5 -206.5 t248.5 -74q209 0 326.5 103t138.5 309h54zM706 -9l-11 -76q177 -16 177 -169q0 -85 -76 -137.5t-209 -52.5l-7 49q101 0 169 39.5t68 101.5q0 56 -38.5 84t-150.5 40l25 121h53z"/> +<glyph glyph-name="Egrave" horiz-adv-x="1166" unicode="È" d="M984 722h-730v-668h832v-54h-886v1456h886v-54h-832v-626h730v-54zM662 1569h-59l-195 266h66z"/> +<glyph glyph-name="Eacute" horiz-adv-x="1166" unicode="É" d="M984 722h-730v-668h832v-54h-886v1456h886v-54h-832v-626h730v-54zM768 1835h66l-195 -266h-60z"/> +<glyph glyph-name="Ecircumflex" horiz-adv-x="1166" unicode="Ê" d="M984 722h-730v-668h832v-54h-886v1456h886v-54h-832v-626h730v-54zM873 1593v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="Edieresis" horiz-adv-x="1166" unicode="Ë" d="M984 722h-730v-668h832v-54h-886v1456h886v-54h-832v-626h730v-54zM353 1740q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM798 1740q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="Igrave" horiz-adv-x="534" unicode="ÃŒ" d="M294 0h-54v1456h54v-1456zM312 1569h-59l-195 266h66z"/> +<glyph glyph-name="Iacute" horiz-adv-x="534" unicode="Ã" d="M294 0h-54v1456h54v-1456zM417 1835h66l-195 -266h-60z"/> +<glyph glyph-name="Icircumflex" horiz-adv-x="534" unicode="ÃŽ" d="M294 0h-54v1456h54v-1456zM523 1593v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="Idieresis" horiz-adv-x="534" unicode="Ã" d="M294 0h-54v1456h54v-1456zM3 1740q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM448 1740q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="Ntilde" horiz-adv-x="1449" unicode="Ñ" d="M1249 0h-54l-940 1364v-1364h-55v1456h55l940 -1361v1361h54v-1456zM1054 1806q0 -82 -50.5 -134t-125.5 -52q-81 0 -153 62.5t-134 62.5q-56 0 -88.5 -34t-32.5 -91h-55q0 80 50 129.5t126 49.5q78 0 153.5 -62t133.5 -62q54 0 87.5 36t33.5 95h55z"/> +<glyph glyph-name="Ograve" horiz-adv-x="1364" unicode="Ã’" d="M1231 619q0 -189 -67.5 -334.5t-192.5 -225t-288 -79.5q-246 0 -398 175t-152 472v210q0 188 67.5 334t193 225.5t287.5 79.5q163 0 288.5 -79.5t193.5 -226t68 -333.5v-218zM1177 839q0 264 -134 423.5t-362 159.5q-225 0 -359 -158.5t-134 -431.5v-213 q0 -174 60.5 -307.5t172.5 -205.5t262 -72q228 0 361 159t133 434v212zM719 1590h-59l-195 266h66z"/> +<glyph glyph-name="Oacute" horiz-adv-x="1364" unicode="Ó" d="M1231 619q0 -189 -67.5 -334.5t-192.5 -225t-288 -79.5q-246 0 -398 175t-152 472v210q0 188 67.5 334t193 225.5t287.5 79.5q163 0 288.5 -79.5t193.5 -226t68 -333.5v-218zM1177 839q0 264 -134 423.5t-362 159.5q-225 0 -359 -158.5t-134 -431.5v-213 q0 -174 60.5 -307.5t172.5 -205.5t262 -72q228 0 361 159t133 434v212zM825 1856h66l-195 -266h-60z"/> +<glyph glyph-name="Ocircumflex" horiz-adv-x="1364" unicode="Ô" d="M1231 619q0 -189 -67.5 -334.5t-192.5 -225t-288 -79.5q-246 0 -398 175t-152 472v210q0 188 67.5 334t193 225.5t287.5 79.5q163 0 288.5 -79.5t193.5 -226t68 -333.5v-218zM1177 839q0 264 -134 423.5t-362 159.5q-225 0 -359 -158.5t-134 -431.5v-213 q0 -174 60.5 -307.5t172.5 -205.5t262 -72q228 0 361 159t133 434v212zM930 1593v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="Otilde" horiz-adv-x="1364" unicode="Õ" d="M1231 619q0 -189 -67.5 -334.5t-192.5 -225t-288 -79.5q-246 0 -398 175t-152 472v210q0 188 67.5 334t193 225.5t287.5 79.5q163 0 288.5 -79.5t193.5 -226t68 -333.5v-218zM1177 839q0 264 -134 423.5t-362 159.5q-225 0 -359 -158.5t-134 -431.5v-213 q0 -174 60.5 -307.5t172.5 -205.5t262 -72q228 0 361 159t133 434v212zM1004 1827q0 -82 -50.5 -134t-125.5 -52q-81 0 -153 62.5t-134 62.5q-56 0 -88.5 -34t-32.5 -91h-55q0 80 50 129.5t126 49.5q78 0 153.5 -62t133.5 -62q54 0 87.5 36t33.5 95h55z"/> +<glyph glyph-name="Odieresis" horiz-adv-x="1364" unicode="Ö" d="M1231 619q0 -189 -67.5 -334.5t-192.5 -225t-288 -79.5q-246 0 -398 175t-152 472v210q0 188 67.5 334t193 225.5t287.5 79.5q163 0 288.5 -79.5t193.5 -226t68 -333.5v-218zM1177 839q0 264 -134 423.5t-362 159.5q-225 0 -359 -158.5t-134 -431.5v-213 q0 -174 60.5 -307.5t172.5 -205.5t262 -72q228 0 361 159t133 434v212zM410 1761q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM855 1761q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="Ugrave" horiz-adv-x="1365" unicode="Ù" d="M1180 1456v-986q0 -231 -134 -360.5t-363 -129.5t-363 129.5t-135 356.5v990h54v-984q0 -202 121.5 -320t322.5 -118t322 118t121 321v983h54zM740 1569h-59l-195 266h66z"/> +<glyph glyph-name="Uacute" horiz-adv-x="1365" unicode="Ú" d="M1180 1456v-986q0 -231 -134 -360.5t-363 -129.5t-363 129.5t-135 356.5v990h54v-984q0 -202 121.5 -320t322.5 -118t322 118t121 321v983h54zM846 1835h66l-195 -266h-60z"/> +<glyph glyph-name="Ucircumflex" horiz-adv-x="1365" unicode="Û" d="M1180 1456v-986q0 -231 -134 -360.5t-363 -129.5t-363 129.5t-135 356.5v990h54v-984q0 -202 121.5 -320t322.5 -118t322 118t121 321v983h54zM951 1593v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="Udieresis" horiz-adv-x="1365" unicode="Ü" d="M1180 1456v-986q0 -231 -134 -360.5t-363 -129.5t-363 129.5t-135 356.5v990h54v-984q0 -202 121.5 -320t322.5 -118t322 118t121 321v983h54zM431 1740q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM876 1740q0 23 16 39.5t39 16.5 t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="Yacute" horiz-adv-x="1223" unicode="Ã" d="M609 602l510 854h66l-549 -903v-553h-54v553l-549 903h72zM757 1824h66l-195 -266h-60z"/> +<glyph glyph-name="agrave" horiz-adv-x="1081" unicode="à " d="M871 0q-20 69 -20 198q-64 -104 -175 -161t-251 -57q-150 0 -241.5 81.5t-91.5 212.5q0 149 134.5 238.5t357.5 91.5h267v158q0 136 -85.5 211t-244.5 75q-148 0 -247 -76t-99 -188l-54 2q0 132 116 224t284 92q175 0 278 -87.5t106 -246.5v-517q0 -178 28 -242v-9h-62z M425 33q152 0 261.5 68t164.5 191v257h-250q-232 0 -355 -92q-100 -75 -100 -187q0 -99 79 -168t200 -69zM620 1250h-59l-195 266h66z"/> +<glyph glyph-name="aacute" horiz-adv-x="1081" unicode="á" d="M871 0q-20 69 -20 198q-64 -104 -175 -161t-251 -57q-150 0 -241.5 81.5t-91.5 212.5q0 149 134.5 238.5t357.5 91.5h267v158q0 136 -85.5 211t-244.5 75q-148 0 -247 -76t-99 -188l-54 2q0 132 116 224t284 92q175 0 278 -87.5t106 -246.5v-517q0 -178 28 -242v-9h-62z M425 33q152 0 261.5 68t164.5 191v257h-250q-232 0 -355 -92q-100 -75 -100 -187q0 -99 79 -168t200 -69zM726 1516h66l-195 -266h-60z"/> +<glyph glyph-name="acircumflex" horiz-adv-x="1081" unicode="â" d="M871 0q-20 69 -20 198q-64 -104 -175 -161t-251 -57q-150 0 -241.5 81.5t-91.5 212.5q0 149 134.5 238.5t357.5 91.5h267v158q0 136 -85.5 211t-244.5 75q-148 0 -247 -76t-99 -188l-54 2q0 132 116 224t284 92q175 0 278 -87.5t106 -246.5v-517q0 -178 28 -242v-9h-62z M425 33q152 0 261.5 68t164.5 191v257h-250q-232 0 -355 -92q-100 -75 -100 -187q0 -99 79 -168t200 -69zM831 1274v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="atilde" horiz-adv-x="1081" unicode="ã" d="M871 0q-20 69 -20 198q-64 -104 -175 -161t-251 -57q-150 0 -241.5 81.5t-91.5 212.5q0 149 134.5 238.5t357.5 91.5h267v158q0 136 -85.5 211t-244.5 75q-148 0 -247 -76t-99 -188l-54 2q0 132 116 224t284 92q175 0 278 -87.5t106 -246.5v-517q0 -178 28 -242v-9h-62z M425 33q152 0 261.5 68t164.5 191v257h-250q-232 0 -355 -92q-100 -75 -100 -187q0 -99 79 -168t200 -69zM905 1486q0 -82 -50.5 -134t-125.5 -52q-81 0 -153 62.5t-134 62.5q-56 0 -88.5 -34t-32.5 -91h-55q0 80 50 129.5t126 49.5q78 0 153.5 -62t133.5 -62q54 0 87.5 36 t33.5 95h55z"/> +<glyph glyph-name="adieresis" horiz-adv-x="1081" unicode="ä" d="M871 0q-20 69 -20 198q-64 -104 -175 -161t-251 -57q-150 0 -241.5 81.5t-91.5 212.5q0 149 134.5 238.5t357.5 91.5h267v158q0 136 -85.5 211t-244.5 75q-148 0 -247 -76t-99 -188l-54 2q0 132 116 224t284 92q175 0 278 -87.5t106 -246.5v-517q0 -178 28 -242v-9h-62z M425 33q152 0 261.5 68t164.5 191v257h-250q-232 0 -355 -92q-100 -75 -100 -187q0 -99 79 -168t200 -69zM311 1421q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM756 1421q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39 t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="aring" horiz-adv-x="1081" unicode="Ã¥" d="M871 0q-20 69 -20 198q-64 -104 -175 -161t-251 -57q-150 0 -241.5 81.5t-91.5 212.5q0 149 134.5 238.5t357.5 91.5h267v158q0 136 -85.5 211t-244.5 75q-148 0 -247 -76t-99 -188l-54 2q0 132 116 224t284 92q175 0 278 -87.5t106 -246.5v-517q0 -178 28 -242v-9h-62z M425 33q152 0 261.5 68t164.5 191v257h-250q-232 0 -355 -92q-100 -75 -100 -187q0 -99 79 -168t200 -69zM579 1556q72 0 121.5 -51t49.5 -123t-49.5 -121t-121.5 -49q-69 0 -120 47.5t-51 122.5t50.5 124.5t120.5 49.5zM462 1382q0 -52 33 -84t84 -32t84 32t33 84 q0 54 -33 87t-84 33t-84 -33t-33 -87z"/> +<glyph glyph-name="ccedilla" horiz-adv-x="1039" unicode="ç" d="M539 34q147 0 242.5 78t104.5 216h54q-8 -157 -121 -252.5t-280 -95.5q-203 0 -322.5 147t-119.5 399v36q0 246 119.5 393t320.5 147q172 0 284 -103t119 -274h-54q-7 146 -102.5 234.5t-246.5 88.5q-181 0 -283.5 -130.5t-102.5 -362.5v-35q0 -227 103.5 -356.5 t284.5 -129.5zM575 -9l-11 -76q177 -16 177 -169q0 -85 -76 -137.5t-209 -52.5l-7 49q101 0 169 39.5t68 101.5q0 56 -38.5 84t-150.5 40l25 121h53z"/> +<glyph glyph-name="egrave" horiz-adv-x="1032" unicode="è" d="M561 -20q-131 0 -240.5 70.5t-171.5 193.5t-62 273v45q0 150 60 275t165 195t229 70q181 0 296 -129t115 -339v-57h-811v-59q0 -132 55.5 -244.5t153 -176.5t211.5 -64q109 0 185.5 36.5t135.5 112.5l38 -27q-121 -175 -359 -175zM541 1048q-158 0 -268 -117.5 t-129 -299.5h754v13q0 110 -46.5 204.5t-128 147t-182.5 52.5zM610 1249h-59l-195 266h66z"/> +<glyph glyph-name="eacute" horiz-adv-x="1032" unicode="é" d="M561 -20q-131 0 -240.5 70.5t-171.5 193.5t-62 273v45q0 150 60 275t165 195t229 70q181 0 296 -129t115 -339v-57h-811v-59q0 -132 55.5 -244.5t153 -176.5t211.5 -64q109 0 185.5 36.5t135.5 112.5l38 -27q-121 -175 -359 -175zM541 1048q-158 0 -268 -117.5 t-129 -299.5h754v13q0 110 -46.5 204.5t-128 147t-182.5 52.5zM716 1515h66l-195 -266h-60z"/> +<glyph glyph-name="ecircumflex" horiz-adv-x="1032" unicode="ê" d="M561 -20q-131 0 -240.5 70.5t-171.5 193.5t-62 273v45q0 150 60 275t165 195t229 70q181 0 296 -129t115 -339v-57h-811v-59q0 -132 55.5 -244.5t153 -176.5t211.5 -64q109 0 185.5 36.5t135.5 112.5l38 -27q-121 -175 -359 -175zM541 1048q-158 0 -268 -117.5 t-129 -299.5h754v13q0 110 -46.5 204.5t-128 147t-182.5 52.5zM821 1274v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="edieresis" horiz-adv-x="1032" unicode="ë" d="M561 -20q-131 0 -240.5 70.5t-171.5 193.5t-62 273v45q0 150 60 275t165 195t229 70q181 0 296 -129t115 -339v-57h-811v-59q0 -132 55.5 -244.5t153 -176.5t211.5 -64q109 0 185.5 36.5t135.5 112.5l38 -27q-121 -175 -359 -175zM541 1048q-158 0 -268 -117.5 t-129 -299.5h754v13q0 110 -46.5 204.5t-128 147t-182.5 52.5zM301 1420q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM746 1420q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="igrave" horiz-adv-x="406" unicode="ì" d="M235 0h-54v1082h54v-1082zM253 1227h-59l-195 266h66z"/> +<glyph glyph-name="iacute" horiz-adv-x="406" unicode="Ã" d="M235 0h-54v1082h54v-1082zM358 1493h66l-195 -266h-60z"/> +<glyph glyph-name="icircumflex" horiz-adv-x="406" unicode="î" d="M235 0h-54v1082h54v-1082zM464 1274v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="idieresis" horiz-adv-x="406" unicode="ï" d="M235 0h-54v1082h54v-1082zM-56 1398q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM389 1398q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="ntilde" d="M226 830q53 126 156 199t228 73q174 0 258.5 -98.5t85.5 -297.5v-706h-54v708q-1 174 -71 257.5t-222 83.5q-140 0 -242.5 -99.5t-138.5 -256.5v-693h-54v1082h54v-252zM906 1484q0 -82 -50.5 -134t-125.5 -52q-81 0 -153 62.5t-134 62.5q-56 0 -88.5 -34t-32.5 -91h-55 q0 80 50 129.5t126 49.5q78 0 153.5 -62t133.5 -62q54 0 87.5 36t33.5 95h55z" unicode="ñ"/> +<glyph glyph-name="ograve" horiz-adv-x="1127" unicode="ò" d="M90 562q0 155 59.5 278.5t168 192.5t245.5 69q136 0 244 -67t168.5 -190t61.5 -277v-48q0 -156 -59 -279t-167.5 -192t-245.5 -69t-245.5 68t-168.5 190.5t-61 275.5v48zM144 520q0 -135 53.5 -247.5t149 -175.5t218.5 -63q185 0 301.5 139t116.5 358v31q0 133 -54 246 t-149.5 176.5t-216.5 63.5q-185 0 -302 -141t-117 -355v-32zM610 1248h-59l-195 266h66z"/> +<glyph glyph-name="oacute" horiz-adv-x="1127" unicode="ó" d="M90 562q0 155 59.5 278.5t168 192.5t245.5 69q136 0 244 -67t168.5 -190t61.5 -277v-48q0 -156 -59 -279t-167.5 -192t-245.5 -69t-245.5 68t-168.5 190.5t-61 275.5v48zM144 520q0 -135 53.5 -247.5t149 -175.5t218.5 -63q185 0 301.5 139t116.5 358v31q0 133 -54 246 t-149.5 176.5t-216.5 63.5q-185 0 -302 -141t-117 -355v-32zM716 1514h66l-195 -266h-60z"/> +<glyph glyph-name="ocircumflex" horiz-adv-x="1127" unicode="ô" d="M90 562q0 155 59.5 278.5t168 192.5t245.5 69q136 0 244 -67t168.5 -190t61.5 -277v-48q0 -156 -59 -279t-167.5 -192t-245.5 -69t-245.5 68t-168.5 190.5t-61 275.5v48zM144 520q0 -135 53.5 -247.5t149 -175.5t218.5 -63q185 0 301.5 139t116.5 358v31q0 133 -54 246 t-149.5 176.5t-216.5 63.5q-185 0 -302 -141t-117 -355v-32zM821 1274v-10h-68l-187 196l-185 -196h-64v14l230 239h40z"/> +<glyph glyph-name="otilde" horiz-adv-x="1127" unicode="õ" d="M90 562q0 155 59.5 278.5t168 192.5t245.5 69q136 0 244 -67t168.5 -190t61.5 -277v-48q0 -156 -59 -279t-167.5 -192t-245.5 -69t-245.5 68t-168.5 190.5t-61 275.5v48zM144 520q0 -135 53.5 -247.5t149 -175.5t218.5 -63q185 0 301.5 139t116.5 358v31q0 133 -54 246 t-149.5 176.5t-216.5 63.5q-185 0 -302 -141t-117 -355v-32zM895 1484q0 -82 -50.5 -134t-125.5 -52q-81 0 -153 62.5t-134 62.5q-56 0 -88.5 -34t-32.5 -91h-55q0 80 50 129.5t126 49.5q78 0 153.5 -62t133.5 -62q54 0 87.5 36t33.5 95h55z"/> +<glyph glyph-name="odieresis" horiz-adv-x="1127" unicode="ö" d="M90 562q0 155 59.5 278.5t168 192.5t245.5 69q136 0 244 -67t168.5 -190t61.5 -277v-48q0 -156 -59 -279t-167.5 -192t-245.5 -69t-245.5 68t-168.5 190.5t-61 275.5v48zM144 520q0 -135 53.5 -247.5t149 -175.5t218.5 -63q185 0 301.5 139t116.5 358v31q0 133 -54 246 t-149.5 176.5t-216.5 63.5q-185 0 -302 -141t-117 -355v-32zM301 1419q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM746 1419q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +<glyph glyph-name="ugrave" d="M897 0v175q-48 -90 -140 -142.5t-233 -52.5q-177 0 -265.5 103.5t-90.5 301.5v697h54v-699q2 -172 78 -260.5t222 -88.5q155 0 252 73t123 214v761h55v-1082h-55zM623 1250h-59l-195 266h66z" unicode="ù"/> +<glyph glyph-name="uacute" d="M897 0v175q-48 -90 -140 -142.5t-233 -52.5q-177 0 -265.5 103.5t-90.5 301.5v697h54v-699q2 -172 78 -260.5t222 -88.5q155 0 252 73t123 214v761h55v-1082h-55zM729 1516h66l-195 -266h-60z" unicode="ú"/> +<glyph glyph-name="ucircumflex" d="M897 0v175q-48 -90 -140 -142.5t-233 -52.5q-177 0 -265.5 103.5t-90.5 301.5v697h54v-699q2 -172 78 -260.5t222 -88.5q155 0 252 73t123 214v761h55v-1082h-55zM834 1274v-10h-68l-187 196l-185 -196h-64v14l230 239h40z" unicode="û"/> +<glyph glyph-name="udieresis" d="M897 0v175q-48 -90 -140 -142.5t-233 -52.5q-177 0 -265.5 103.5t-90.5 301.5v697h54v-699q2 -172 78 -260.5t222 -88.5q155 0 252 73t123 214v761h55v-1082h-55zM314 1421q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM759 1421 q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z" unicode="ü"/> +<glyph glyph-name="yacute" horiz-adv-x="978" unicode="ý" d="M503 84l7 20l374 978h60l-484 -1270l-24 -60q-78 -189 -258 -189q-58 0 -80 11l-1 51q32 -9 73 -9q85 0 141 49.5t97 161.5l66 179l-431 1076h59zM668 1516h66l-195 -266h-60z"/> +<glyph glyph-name="ydieresis" horiz-adv-x="978" unicode="ÿ" d="M503 84l7 20l374 978h60l-484 -1270l-24 -60q-78 -189 -258 -189q-58 0 -80 11l-1 51q32 -9 73 -9q85 0 141 49.5t97 161.5l66 179l-431 1076h59zM253 1421q0 23 16 39.5t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39zM698 1421q0 23 16 39.5 t39 16.5t39.5 -16.5t16.5 -39.5t-16.5 -39t-39.5 -16t-39 16t-16 39z"/> +</font> +</defs> +</svg> diff --git a/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.ttf b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.ttf new file mode 100644 index 0000000000000000000000000000000000000000..22eff2fdc973faa6539da890563714b2b02d4395 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.ttf differ diff --git a/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff new file mode 100644 index 0000000000000000000000000000000000000000..fae08e807ca83ea7779ce639edd3c761880e93a5 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff differ diff --git a/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff2 b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..13d10944965389a4ca22e392216d5be8606dd5d9 Binary files /dev/null and b/www/lib/ionic/fonts/robotdraft/Thin/RobotoDraft-Thin.woff2 differ diff --git a/www/lib/ionic/js/angular/angular-animate.js b/www/lib/ionic/js/angular/angular-animate.js index 8cd592d7bbe67b3ba5735bf4e74c08d3c09db6bf..fc0e217f7ee003a59632025f62ae7e636967a756 100644 --- a/www/lib/ionic/js/angular/angular-animate.js +++ b/www/lib/ionic/js/angular/angular-animate.js @@ -1,2137 +1,3721 @@ /** - * @license AngularJS v1.3.13 - * (c) 2010-2014 Google, Inc. http://angularjs.org + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org * License: MIT */ (function(window, angular, undefined) {'use strict'; -/* jshint maxlen: false */ +/* jshint ignore:start */ +var noop = angular.noop; +var extend = angular.extend; +var jqLite = angular.element; +var forEach = angular.forEach; +var isArray = angular.isArray; +var isString = angular.isString; +var isObject = angular.isObject; +var isUndefined = angular.isUndefined; +var isDefined = angular.isDefined; +var isFunction = angular.isFunction; +var isElement = angular.isElement; + +var ELEMENT_NODE = 1; +var COMMENT_NODE = 8; + +var NG_ANIMATE_CLASSNAME = 'ng-animate'; +var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren'; + +var isPromiseLike = function(p) { + return p && p.then ? true : false; +} + +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function packageStyles(options) { + var styles = {}; + if (options && (options.to || options.from)) { + styles.to = options.to; + styles.from = options.from; + } + return styles; +} + +function pendClasses(classes, fix, isPrefix) { + var className = ''; + classes = isArray(classes) + ? classes + : classes && isString(classes) && classes.length + ? classes.split(/\s+/) + : []; + forEach(classes, function(klass, i) { + if (klass && klass.length > 0) { + className += (i > 0) ? ' ' : ''; + className += isPrefix ? fix + klass + : klass + fix; + } + }); + return className; +} + +function removeFromArray(arr, val) { + var index = arr.indexOf(val); + if (val >= 0) { + arr.splice(index, 1); + } +} + +function stripCommentsFromElement(element) { + if (element instanceof jqLite) { + switch (element.length) { + case 0: + return []; + break; + + case 1: + // there is no point of stripping anything if the element + // is the only element within the jqLite wrapper. + // (it's important that we retain the element instance.) + if (element[0].nodeType === ELEMENT_NODE) { + return element; + } + break; + + default: + return jqLite(extractElementNode(element)); + break; + } + } + + if (element.nodeType === ELEMENT_NODE) { + return jqLite(element); + } +} + +function extractElementNode(element) { + if (!element[0]) return element; + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType == ELEMENT_NODE) { + return elm; + } + } +} + +function $$addClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.addClass(elm, className); + }); +} + +function $$removeClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.removeClass(elm, className); + }); +} + +function applyAnimationClassesFactory($$jqLite) { + return function(element, options) { + if (options.addClass) { + $$addClass($$jqLite, element, options.addClass); + options.addClass = null; + } + if (options.removeClass) { + $$removeClass($$jqLite, element, options.removeClass); + options.removeClass = null; + } + } +} + +function prepareAnimationOptions(options) { + options = options || {}; + if (!options.$$prepared) { + var domOperation = options.domOperation || noop; + options.domOperation = function() { + options.$$domOperationFired = true; + domOperation(); + domOperation = noop; + }; + options.$$prepared = true; + } + return options; +} + +function applyAnimationStyles(element, options) { + applyAnimationFromStyles(element, options); + applyAnimationToStyles(element, options); +} + +function applyAnimationFromStyles(element, options) { + if (options.from) { + element.css(options.from); + options.from = null; + } +} + +function applyAnimationToStyles(element, options) { + if (options.to) { + element.css(options.to); + options.to = null; + } +} + +function mergeAnimationOptions(element, target, newOptions) { + var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || ''); + var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || ''); + var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove); + + extend(target, newOptions); + + if (classes.addClass) { + target.addClass = classes.addClass; + } else { + target.addClass = null; + } + + if (classes.removeClass) { + target.removeClass = classes.removeClass; + } else { + target.removeClass = null; + } + + return target; +} + +function resolveElementClasses(existing, toAdd, toRemove) { + var ADD_CLASS = 1; + var REMOVE_CLASS = -1; + + var flags = {}; + existing = splitClassesToLookup(existing); + + toAdd = splitClassesToLookup(toAdd); + forEach(toAdd, function(value, key) { + flags[key] = ADD_CLASS; + }); + + toRemove = splitClassesToLookup(toRemove); + forEach(toRemove, function(value, key) { + flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS; + }); + + var classes = { + addClass: '', + removeClass: '' + }; + + forEach(flags, function(val, klass) { + var prop, allow; + if (val === ADD_CLASS) { + prop = 'addClass'; + allow = !existing[klass]; + } else if (val === REMOVE_CLASS) { + prop = 'removeClass'; + allow = existing[klass]; + } + if (allow) { + if (classes[prop].length) { + classes[prop] += ' '; + } + classes[prop] += klass; + } + }); + + function splitClassesToLookup(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + var obj = {}; + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; + } + + return classes; +} + +function getDomNode(element) { + return (element instanceof angular.element) ? element[0] : element; +} + +var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) { + var tickQueue = []; + var cancelFn; + + function scheduler(tasks) { + // we make a copy since RAFScheduler mutates the state + // of the passed in array variable and this would be difficult + // to track down on the outside code + tickQueue.push([].concat(tasks)); + nextTick(); + } + + /* waitUntilQuiet does two things: + * 1. It will run the FINAL `fn` value only when an uncancelled RAF has passed through + * 2. It will delay the next wave of tasks from running until the quiet `fn` has run. + * + * The motivation here is that animation code can request more time from the scheduler + * before the next wave runs. This allows for certain DOM properties such as classes to + * be resolved in time for the next animation to run. + */ + scheduler.waitUntilQuiet = function(fn) { + if (cancelFn) cancelFn(); + + cancelFn = $$rAF(function() { + cancelFn = null; + fn(); + nextTick(); + }); + }; + + return scheduler; + + function nextTick() { + if (!tickQueue.length) return; + + var updatedQueue = []; + for (var i = 0; i < tickQueue.length; i++) { + var innerQueue = tickQueue[i]; + runNextTask(innerQueue); + if (innerQueue.length) { + updatedQueue.push(innerQueue); + } + } + tickQueue = updatedQueue; + + if (!cancelFn) { + $$rAF(function() { + if (!cancelFn) nextTick(); + }); + } + } + + function runNextTask(tasks) { + var nextTask = tasks.shift(); + nextTask(); + } +}]; + +var $$AnimateChildrenDirective = [function() { + return function(scope, element, attrs) { + var val = attrs.ngAnimateChildren; + if (angular.isString(val) && val.length === 0) { //empty attribute + element.data(NG_ANIMATE_CHILDREN_DATA, true); + } else { + attrs.$observe('ngAnimateChildren', function(value) { + value = value === 'on' || value === 'true'; + element.data(NG_ANIMATE_CHILDREN_DATA, value); + }); + } + }; +}]; /** - * @ngdoc module - * @name ngAnimate - * @description - * - * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives. - * - * <div doc-module-components="ngAnimate"></div> - * - * # Usage + * @ngdoc service + * @name $animateCss + * @kind object * - * To see animations in action, all that is required is to define the appropriate CSS classes - * or to register a JavaScript animation via the `myModule.animation()` function. The directives that support animation automatically are: - * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation - * by using the `$animate` service. - * - * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives: - * - * | Directive | Supported Animations | - * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| - * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | - * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | - * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | - * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | - * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | - * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) | - * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) | - * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | - * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | - * | {@link module:ngMessages#animations ngMessage} | enter and leave | - * - * You can find out more information about animations upon visiting each directive page. - * - * Below is an example of how to apply animations to a directive that supports animation hooks: - * - * ```html - * <style type="text/css"> - * .slide.ng-enter, .slide.ng-leave { - * -webkit-transition:0.5s linear all; - * transition:0.5s linear all; - * } + * @description + * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes + * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT + * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or + * directives to create more complex animations that can be purely driven using CSS code. * - * .slide.ng-enter { } /* starting animations for enter */ - * .slide.ng-enter.ng-enter-active { } /* terminal animations for enter */ - * .slide.ng-leave { } /* starting animations for leave */ - * .slide.ng-leave.ng-leave-active { } /* terminal animations for leave */ - * </style> + * Note that only browsers that support CSS transitions and/or keyframe animations are capable of + * rendering animations triggered via `$animateCss` (bad news for IE9 and lower). * - * <!-- - * the animate service will automatically add .ng-enter and .ng-leave to the element - * to trigger the CSS transition/animations - * --> - * <ANY class="slide" ng-include="..."></ANY> - * ``` + * ## Usage + * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that + * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however, + * any automatic control over cancelling animations and/or preventing animations from being run on + * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to + * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger + * the CSS animation. * - * Keep in mind that, by default, if an animation is running, any child elements cannot be animated - * until the parent element's animation has completed. This blocking feature can be overridden by - * placing the `ng-animate-children` attribute on a parent container tag. + * The example below shows how we can create a folding animation on an element using `ng-if`: * * ```html - * <div class="slide-animation" ng-if="on" ng-animate-children> - * <div class="fade-animation" ng-if="on"> - * <div class="explode-animation" ng-if="on"> - * ... - * </div> - * </div> + * <!-- notice the `fold-animation` CSS class --> + * <div ng-if="onOff" class="fold-animation"> + * This element will go BOOM * </div> + * <button ng-click="onOff=true">Fold In</button> * ``` * - * When the `on` expression value changes and an animation is triggered then each of the elements within - * will all animate without the block being applied to child elements. - * - * ## Are animations run when the application starts? - * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid - * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work, - * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering - * layout changes in the application will trigger animations as normal. + * Now we create the **JavaScript animation** that will trigger the CSS transition: * - * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular - * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests - * are complete. - * - * ## CSS-defined Animations - * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes - * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported - * and can be used to play along with this naming structure. - * - * The following code below demonstrates how to perform animations using **CSS transitions** with Angular: - * - * ```html - * <style type="text/css"> - * /* - * The animate class is apart of the element and the ng-enter class - * is attached to the element once the enter animation event is triggered - * */ - * .reveal-animation.ng-enter { - * -webkit-transition: 1s linear all; /* Safari/Chrome */ - * transition: 1s linear all; /* All other modern browsers and IE10+ */ - * - * /* The animation preparation code */ - * opacity: 0; - * } + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` * - * /* - * Keep in mind that you want to combine both CSS - * classes together to avoid any CSS-specificity - * conflicts - * */ - * .reveal-animation.ng-enter.ng-enter-active { - * /* The animation code itself */ - * opacity: 1; - * } - * </style> + * ## More Advanced Uses * - * <div class="view-container"> - * <div ng-view class="reveal-animation"></div> - * </div> - * ``` + * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks + * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code. * - * The following code below demonstrates how to perform animations using **CSS animations** with Angular: + * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation, + * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with + * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order + * to provide a working animation that will run in CSS. * - * ```html - * <style type="text/css"> - * .reveal-animation.ng-enter { - * -webkit-animation: enter_sequence 1s linear; /* Safari/Chrome */ - * animation: enter_sequence 1s linear; /* IE10+ and Future Browsers */ - * } - * @-webkit-keyframes enter_sequence { - * from { opacity:0; } - * to { opacity:1; } - * } - * @keyframes enter_sequence { - * from { opacity:0; } - * to { opacity:1; } - * } - * </style> + * The example below showcases a more advanced version of the `.fold-animation` from the example above: * - * <div class="view-container"> - * <div ng-view class="reveal-animation"></div> - * </div> + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * addClass: 'red large-text pulse-twice', + * easing: 'ease-out', + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); * ``` * - * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing. - * - * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add - * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically - * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be - * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end - * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element - * has no CSS transition/animation classes applied to it. - * - * ### Structural transition animations - * - * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition - * value to force the browser into rendering the styles defined in the setup (`.ng-enter`, `.ng-leave` - * or `.ng-move`) class. This means that any active transition animations operating on the element - * will be cut off to make way for the enter, leave or move animation. - * - * ### Class-based transition animations - * - * Class-based transitions refer to transition animations that are triggered when a CSS class is - * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`, - * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`). - * They are different when compared to structural animations since they **do not cancel existing - * animations** nor do they **block successive transitions** from rendering on the same element. - * This distinction allows for **multiple class-based transitions** to be performed on the same element. - * - * In addition to ngAnimate supporting the default (natural) functionality of class-based transition - * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the - * developer in further styling the element throughout the transition animation. Earlier versions - * of ngAnimate may have caused natural CSS transitions to break and not render properly due to - * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class - * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of - * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS - * class transitions are compatible with ngAnimate. - * - * There is, however, one special case when dealing with class-based transitions in ngAnimate. - * When rendering class-based transitions that make use of the setup and active CSS classes - * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define - * the transition value **on the active CSS class** and not the setup class. + * Since we're adding/removing CSS classes then the CSS transition will also pick those up: * * ```css - * .fade-add { - * /* remember to place a 0s transition here - * to ensure that the styles are applied instantly - * even if the element already has a transition style */ - * transition:0s linear all; - * - * /* starting CSS styles */ - * opacity:1; + * /* since a hardcoded duration value of 1 was provided in the JavaScript animation code, + * the CSS classes below will be transitioned despite them being defined as regular CSS classes */ + * .red { background:red; } + * .large-text { font-size:20px; } + * + * /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */ + * .pulse-twice { + * animation: 0.5s pulse linear 2; + * -webkit-animation: 0.5s pulse linear 2; * } - * .fade-add.fade-add-active { - * /* this will be the length of the animation */ - * transition:1s linear all; - * opacity:0; - * } - * ``` * - * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it - * has a duration of zero. This may not be required, however, incase the browser is unable to render - * the styling present in this CSS class instantly then it could be that the browser is attempting - * to perform an unnecessary transition. - * - * This workaround, however, does not apply to standard class-based transitions that are rendered - * when a CSS class containing a transition is applied to an element: + * @keyframes pulse { + * from { transform: scale(0.5); } + * to { transform: scale(1.5); } + * } * - * ```css - * /* this works as expected */ - * .fade { - * transition:1s linear all; - * opacity:0; + * @-webkit-keyframes pulse { + * from { -webkit-transform: scale(0.5); } + * to { -webkit-transform: scale(1.5); } * } * ``` * - * Please keep this in mind when coding the CSS markup that will be used within class-based transitions. - * Also, try not to mix the two class-based animation flavors together since the CSS code may become - * overly complex. - * - * - * ### Preventing Collisions With Third Party Libraries - * - * Some third-party frameworks place animation duration defaults across many element or className - * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which - * is expecting actual animations on these elements and has to wait for their completion. - * - * You can prevent this unwanted behavior by using a prefix on all your animation classes: + * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen. * - * ```css - * /* prefixed with animate- */ - * .animate-fade-add.animate-fade-add-active { - * transition:1s linear all; - * opacity:0; - * } - * ``` + * ## How the Options are handled * - * You then configure `$animate` to enforce this prefix: + * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation + * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline + * styles using the `from` and `to` properties. * * ```js - * $animateProvider.classNameFilter(/animate-/); + * var animator = $animateCss(element, { + * from: { background:'red' }, + * to: { background:'blue' } + * }); + * animator.start(); * ``` - * </div> - * - * ### CSS Staggering Animations - * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a - * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be - * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for - * the animation. The style property expected within the stagger class can either be a **transition-delay** or an - * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). * * ```css - * .my-animation.ng-enter { - * /* standard transition code */ - * -webkit-transition: 1s linear all; - * transition: 1s linear all; - * opacity:0; + * .rotating-animation { + * animation:0.5s rotate linear; + * -webkit-animation:0.5s rotate linear; * } - * .my-animation.ng-enter-stagger { - * /* this will have a 100ms delay between each successive leave animation */ - * -webkit-transition-delay: 0.1s; - * transition-delay: 0.1s; * - * /* in case the stagger doesn't work then these two values - * must be set to 0 to avoid an accidental CSS inheritance */ - * -webkit-transition-duration: 0s; - * transition-duration: 0s; + * @keyframes rotate { + * from { transform: rotate(0deg); } + * to { transform: rotate(360deg); } * } - * .my-animation.ng-enter.ng-enter-active { - * /* standard transition styles */ - * opacity:1; + * + * @-webkit-keyframes rotate { + * from { -webkit-transform: rotate(0deg); } + * to { -webkit-transform: rotate(360deg); } * } * ``` * - * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations - * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this - * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation - * will also be reset if more than 10ms has passed after the last animation has been fired. - * - * The following code will issue the **ng-leave-stagger** event on the element provided: - * - * ```js - * var kids = parent.children(); - * - * $animate.leave(kids[0]); //stagger index=0 - * $animate.leave(kids[1]); //stagger index=1 - * $animate.leave(kids[2]); //stagger index=2 - * $animate.leave(kids[3]); //stagger index=3 - * $animate.leave(kids[4]); //stagger index=4 - * - * $timeout(function() { - * //stagger has reset itself - * $animate.leave(kids[5]); //stagger index=0 - * $animate.leave(kids[6]); //stagger index=1 - * }, 100, false); - * ``` + * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is + * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition + * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition + * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied + * and spread across the transition and keyframe animation. * - * Stagger animations are currently only supported within CSS-defined animations. + * ## What is returned * - * ## JavaScript-defined Animations - * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not - * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module. + * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually + * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are + * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties: * * ```js - * //!annotate="YourApp" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application. - * var ngModule = angular.module('YourApp', ['ngAnimate']); - * ngModule.animation('.my-crazy-animation', function() { - * return { - * enter: function(element, done) { - * //run the animation here and call done when the animation is complete - * return function(cancelled) { - * //this (optional) function will be called when the animation - * //completes or when the animation is cancelled (the cancelled - * //flag will be set to true if cancelled). - * }; - * }, - * leave: function(element, done) { }, - * move: function(element, done) { }, - * - * //animation that can be triggered before the class is added - * beforeAddClass: function(element, className, done) { }, - * - * //animation that can be triggered after the class is added - * addClass: function(element, className, done) { }, - * - * //animation that can be triggered before the class is removed - * beforeRemoveClass: function(element, className, done) { }, - * - * //animation that can be triggered after the class is removed - * removeClass: function(element, className, done) { } - * }; - * }); + * var animator = $animateCss(element, { ... }); * ``` * - * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run - * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits - * the element's CSS class attribute value and then run the matching animation event function (if found). - * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will - * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported). - * - * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned. - * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run, - * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation - * or transition code that is defined via a stylesheet). - * - * - * ### Applying Directive-specific Styles to an Animation - * In some cases a directive or service may want to provide `$animate` with extra details that the animation will - * include into its animation. Let's say for example we wanted to render an animation that animates an element - * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click - * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function - * call to `$animate.addClass`. + * Now what do the contents of our `animator` variable look like: * * ```js - * canvas.on('click', function(e) { - * $animate.addClass(element, 'on', { - * to: { - * left : e.client.x + 'px', - * top : e.client.y + 'px' - * } - * }): - * }); - * ``` + * { + * // starts the animation + * start: Function, * - * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will - * also include and transition the styling of the `left` and `top` properties into its running animation. If we want - * to provide some starting animation values then we can do so by placing the starting animations styles into an object - * called `from` in the same object as the `to` animations. - * - * ```js - * canvas.on('click', function(e) { - * $animate.addClass(element, 'on', { - * from: { - * position: 'absolute', - * left: '0px', - * top: '0px' - * }, - * to: { - * left : e.client.x + 'px', - * top : e.client.y + 'px' - * } - * }): - * }); + * // ends (aborts) the animation + * end: Function + * } * ``` * - * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the - * element. If `ngAnimate` is not present then the styles will be applied immediately. - * + * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends. + * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and stlyes may have been + * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties + * and that changing them will not reconfigure the parameters of the animation. + * + * ### runner.done() vs runner.then() + * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the + * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**. + * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()` + * unless you really need a digest to kick off afterwards. + * + * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss + * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code). + * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works. + * + * @param {DOMElement} element the element that will be animated + * @param {object} options the animation-related options that will be applied during the animation + * + * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied + * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.) + * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both). + * * `transition` - The raw CSS transition style that will be used (e.g. `1s linear all`). + * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`). + * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation. + * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition. + * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation. + * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation. + * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0` + * is provided then the animation will be skipped entirely. + * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is + * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value + * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same + * CSS delay value. + * * `stagger` - A numeric time value representing the delay between successively animated elements + * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.}) + * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a + * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`) + * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occuring on the classes being added and removed.) + * + * @return {object} an object with start and end methods and details about the animation. + * + * * `start` - The method to start the animation. This will return a `Promise` when called. + * * `end` - This method will cancel the animation and remove all applied CSS classes and styles. */ -angular.module('ngAnimate', ['ng']) +// Detect proper transitionend/animationend event names. +var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; + +// If unprefixed events are not supported but webkit-prefixed are, use the latter. +// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. +// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` +// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. +// Register both events in case `window.onanimationend` is not supported because of that, +// do the same for `transitionend` as Safari is likely to exhibit similar behavior. +// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit +// therefore there is no reason to test anymore for other vendor prefixes: +// http://caniuse.com/#search=transition +if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { + CSS_PREFIX = '-webkit-'; + TRANSITION_PROP = 'WebkitTransition'; + TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; +} else { + TRANSITION_PROP = 'transition'; + TRANSITIONEND_EVENT = 'transitionend'; +} + +if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { + CSS_PREFIX = '-webkit-'; + ANIMATION_PROP = 'WebkitAnimation'; + ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; +} else { + ANIMATION_PROP = 'animation'; + ANIMATIONEND_EVENT = 'animationend'; +} + +var DURATION_KEY = 'Duration'; +var PROPERTY_KEY = 'Property'; +var DELAY_KEY = 'Delay'; +var TIMING_KEY = 'TimingFunction'; +var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; +var ANIMATION_PLAYSTATE_KEY = 'PlayState'; +var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; +var CLOSING_TIME_BUFFER = 1.5; +var ONE_SECOND = 1000; +var BASE_TEN = 10; + +var SAFE_FAST_FORWARD_DURATION_VALUE = 9999; + +var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY; +var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY; + +var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY; +var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY; + +var DETECT_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + transitionProperty: TRANSITION_PROP + PROPERTY_KEY, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP, + animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY +}; + +var DETECT_STAGGER_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP +}; + +function computeCssStyles($window, element, properties) { + var styles = Object.create(null); + var detectedStyles = $window.getComputedStyle(element) || {}; + forEach(properties, function(formalStyleName, actualStyleName) { + var val = detectedStyles[formalStyleName]; + if (val) { + var c = val.charAt(0); + + // only numerical-based values have a negative sign or digit as the first value + if (c === '-' || c === '+' || c >= 0) { + val = parseMaxTime(val); + } - /** - * @ngdoc provider - * @name $animateProvider - * @description - * - * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module. - * When an animation is triggered, the $animate service will query the $animate service to find any animations that match - * the provided name value. - * - * Requires the {@link ngAnimate `ngAnimate`} module to be installed. - * - * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. - * - */ - .directive('ngAnimateChildren', function() { - var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren'; - return function(scope, element, attrs) { - var val = attrs.ngAnimateChildren; - if (angular.isString(val) && val.length === 0) { //empty attribute - element.data(NG_ANIMATE_CHILDREN, true); + // by setting this to null in the event that the delay is not set or is set directly as 0 + // then we can still allow for zegative values to be used later on and not mistake this + // value for being greater than any other negative value. + if (val === 0) { + val = null; + } + styles[actualStyleName] = val; + } + }); + + return styles; +} + +function parseMaxTime(str) { + var maxValue = 0; + var values = str.split(/\s*,\s*/); + forEach(values, function(value) { + // it's always safe to consider only second values and omit `ms` values since + // getComputedStyle will always handle the conversion for us + if (value.charAt(value.length - 1) == 's') { + value = value.substring(0, value.length - 1); + } + value = parseFloat(value) || 0; + maxValue = maxValue ? Math.max(value, maxValue) : value; + }); + return maxValue; +} + +function truthyTimingValue(val) { + return val === 0 || val != null; +} + +function getCssTransitionDurationStyle(duration, applyOnlyDuration) { + var style = TRANSITION_PROP; + var value = duration + 's'; + if (applyOnlyDuration) { + style += DURATION_KEY; + } else { + value += ' linear all'; + } + return [style, value]; +} + +function getCssKeyframeDurationStyle(duration) { + return [ANIMATION_DURATION_PROP, duration + 's']; +} + +function getCssDelayStyle(delay, isKeyframeAnimation) { + var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP; + return [prop, delay + 's']; +} + +function blockTransitions(node, duration) { + // we use a negative delay value since it performs blocking + // yet it doesn't kill any existing transitions running on the + // same element which makes this safe for class-based animations + var value = duration ? '-' + duration + 's' : ''; + applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]); + return [TRANSITION_DELAY_PROP, value]; +} + +function blockKeyframeAnimations(node, applyBlock) { + var value = applyBlock ? 'paused' : ''; + var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY; + applyInlineStyle(node, [key, value]); + return [key, value]; +} + +function applyInlineStyle(node, styleTuple) { + var prop = styleTuple[0]; + var value = styleTuple[1]; + node.style[prop] = value; +} + +function createLocalCacheLookup() { + var cache = Object.create(null); + return { + flush: function() { + cache = Object.create(null); + }, + + count: function(key) { + var entry = cache[key]; + return entry ? entry.total : 0; + }, + + get: function(key) { + var entry = cache[key]; + return entry && entry.value; + }, + + put: function(key, value) { + if (!cache[key]) { + cache[key] = { total: 1, value: value }; } else { - scope.$watch(val, function(value) { - element.data(NG_ANIMATE_CHILDREN, !!value); - }); + cache[key].total++; } - }; - }) - - //this private service is only used within CSS-enabled animations - //IE8 + IE9 do not support rAF natively, but that is fine since they - //also don't support transitions and keyframes which means that the code - //below will never be used by the two browsers. - .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) { - var bod = $document[0].body; - return function(fn) { - //the returned function acts as the cancellation function - return $$rAF(function() { - //the line below will force the browser to perform a repaint - //so that all the animated elements within the animation frame - //will be properly updated and drawn on screen. This is - //required to perform multi-class CSS based animations with - //Firefox. DO NOT REMOVE THIS LINE. - var a = bod.offsetWidth + 1; - fn(); - }); - }; - }]) - - .config(['$provide', '$animateProvider', function($provide, $animateProvider) { - var noop = angular.noop; - var forEach = angular.forEach; - var selectors = $animateProvider.$$selectors; - var isArray = angular.isArray; - var isString = angular.isString; - var isObject = angular.isObject; - - var ELEMENT_NODE = 1; - var NG_ANIMATE_STATE = '$$ngAnimateState'; - var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren'; - var NG_ANIMATE_CLASS_NAME = 'ng-animate'; - var rootAnimateState = {running: true}; - - function extractElementNode(element) { - for (var i = 0; i < element.length; i++) { - var elm = element[i]; - if (elm.nodeType == ELEMENT_NODE) { - return elm; + } + }; +} + +var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { + var gcsLookup = createLocalCacheLookup(); + var gcsStaggerLookup = createLocalCacheLookup(); + + this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', + '$document', '$sniffer', '$$rAFScheduler', + function($window, $$jqLite, $$AnimateRunner, $timeout, + $document, $sniffer, $$rAFScheduler) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var parentCounter = 0; + function gcsHashFn(node, extraClasses) { + var KEY = "$$ngAnimateParentKey"; + var parentNode = node.parentNode; + var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter); + return parentID + '-' + node.getAttribute('class') + '-' + extraClasses; + } + + function computeCachedCssStyles(node, className, cacheKey, properties) { + var timings = gcsLookup.get(cacheKey); + + if (!timings) { + timings = computeCssStyles($window, node, properties); + if (timings.animationIterationCount === 'infinite') { + timings.animationIterationCount = 1; } } + + // we keep putting this in multiple times even though the value and the cacheKey are the same + // because we're keeping an interal tally of how many duplicate animations are detected. + gcsLookup.put(cacheKey, timings); + return timings; } - function prepareElement(element) { - return element && angular.element(element); + function computeCachedCssStaggerStyles(node, className, cacheKey, properties) { + var stagger; + + // if we have one or more existing matches of matching elements + // containing the same parent + CSS styles (which is how cacheKey works) + // then staggering is possible + if (gcsLookup.count(cacheKey) > 0) { + stagger = gcsStaggerLookup.get(cacheKey); + + if (!stagger) { + var staggerClassName = pendClasses(className, '-stagger'); + + $$jqLite.addClass(node, staggerClassName); + + stagger = computeCssStyles($window, node, properties); + + // force the conversion of a null value to zero incase not set + stagger.animationDuration = Math.max(stagger.animationDuration, 0); + stagger.transitionDuration = Math.max(stagger.transitionDuration, 0); + + $$jqLite.removeClass(node, staggerClassName); + + gcsStaggerLookup.put(cacheKey, stagger); + } + } + + return stagger || {}; } - function stripCommentsFromElement(element) { - return angular.element(extractElementNode(element)); + var bod = getDomNode($document).body; + var rafWaitQueue = []; + function waitUntilQuiet(callback) { + rafWaitQueue.push(callback); + $$rAFScheduler.waitUntilQuiet(function() { + gcsLookup.flush(); + gcsStaggerLookup.flush(); + + //the line below will force the browser to perform a repaint so + //that all the animated elements within the animation frame will + //be properly updated and drawn on screen. This is required to + //ensure that the preparation animation is properly flushed so that + //the active state picks up from there. DO NOT REMOVE THIS LINE. + //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH + //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND + //WILL TAKE YEARS AWAY FROM YOUR LIFE. + var width = bod.offsetWidth + 1; + + // we use a for loop to ensure that if the queue is changed + // during this looping then it will consider new requests + for (var i = 0; i < rafWaitQueue.length; i++) { + rafWaitQueue[i](width); + } + rafWaitQueue.length = 0; + }); } - function isMatchingElement(elm1, elm2) { - return extractElementNode(elm1) == extractElementNode(elm2); + return init; + + function computeTimings(node, className, cacheKey) { + var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES); + var aD = timings.animationDelay; + var tD = timings.transitionDelay; + timings.maxDelay = aD && tD + ? Math.max(aD, tD) + : (aD || tD); + timings.maxDuration = Math.max( + timings.animationDuration * timings.animationIterationCount, + timings.transitionDuration); + + return timings; } - var $$jqLite; - $provide.decorator('$animate', - ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest', '$$jqLite', - function($delegate, $$q, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document, $templateRequest, $$$jqLite) { - - $$jqLite = $$$jqLite; - $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); - - // Wait until all directive and route-related templates are downloaded and - // compiled. The $templateRequest.totalPendingRequests variable keeps track of - // all of the remote templates being currently downloaded. If there are no - // templates currently downloading then the watcher will still fire anyway. - var deregisterWatch = $rootScope.$watch( - function() { return $templateRequest.totalPendingRequests; }, - function(val, oldVal) { - if (val !== 0) return; - deregisterWatch(); - - // Now that all templates have been downloaded, $animate will wait until - // the post digest queue is empty before enabling animations. By having two - // calls to $postDigest calls we can ensure that the flag is enabled at the - // very end of the post digest queue. Since all of the animations in $animate - // use $postDigest, it's important that the code below executes at the end. - // This basically means that the page is fully downloaded and compiled before - // any animations are triggered. - $rootScope.$$postDigest(function() { - $rootScope.$$postDigest(function() { - rootAnimateState.running = false; - }); - }); - } - ); - var globalAnimationCounter = 0; - var classNameFilter = $animateProvider.classNameFilter(); - var isAnimatableClassName = !classNameFilter - ? function() { return true; } - : function(className) { - return classNameFilter.test(className); - }; + function init(element, options) { + var node = getDomNode(element); + if (!node || !node.parentNode) { + return closeAndReturnNoopAnimator(); + } - function classBasedAnimationsBlocked(element, setter) { - var data = element.data(NG_ANIMATE_STATE) || {}; - if (setter) { - data.running = true; - data.structural = true; - element.data(NG_ANIMATE_STATE, data); - } - return data.disabled || (data.running && data.structural); + options = prepareAnimationOptions(options); + + var temporaryStyles = []; + var classes = element.attr('class'); + var styles = packageStyles(options); + var animationClosed; + var animationPaused; + var animationCompleted; + var runner; + var runnerHost; + var maxDelay; + var maxDelayTime; + var maxDuration; + var maxDurationTime; + + if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) { + return closeAndReturnNoopAnimator(); } - function runAnimationPostDigest(fn) { - var cancelFn, defer = $$q.defer(); - defer.promise.$$cancelFn = function() { - cancelFn && cancelFn(); - }; - $rootScope.$$postDigest(function() { - cancelFn = fn(function() { - defer.resolve(); - }); - }); - return defer.promise; + var method = options.event && isArray(options.event) + ? options.event.join(' ') + : options.event; + + var isStructural = method && options.structural; + var structuralClassName = ''; + var addRemoveClassName = ''; + + if (isStructural) { + structuralClassName = pendClasses(method, 'ng-', true); + } else if (method) { + structuralClassName = method; } - function parseAnimateOptions(options) { - // some plugin code may still be passing in the callback - // function as the last param for the $animate methods so - // it's best to only allow string or array values for now - if (isObject(options)) { - if (options.tempClasses && isString(options.tempClasses)) { - options.tempClasses = options.tempClasses.split(/\s+/); - } - return options; + if (options.addClass) { + addRemoveClassName += pendClasses(options.addClass, '-add'); + } + + if (options.removeClass) { + if (addRemoveClassName.length) { + addRemoveClassName += ' '; } + addRemoveClassName += pendClasses(options.removeClass, '-remove'); } - function resolveElementClasses(element, cache, runningAnimations) { - runningAnimations = runningAnimations || {}; + // there may be a situation where a structural animation is combined together + // with CSS classes that need to resolve before the animation is computed. + // However this means that there is no explicit CSS code to block the animation + // from happening (by setting 0s none in the class name). If this is the case + // we need to apply the classes before the first rAF so we know to continue if + // there actually is a detected transition or keyframe animation + if (options.applyClassesEarly && addRemoveClassName.length) { + applyAnimationClasses(element, options); + addRemoveClassName = ''; + } - var lookup = {}; - forEach(runningAnimations, function(data, selector) { - forEach(selector.split(' '), function(s) { - lookup[s]=data; - }); - }); + var setupClasses = [structuralClassName, addRemoveClassName].join(' ').trim(); + var fullClassName = classes + ' ' + setupClasses; + var activeClasses = pendClasses(setupClasses, '-active'); + var hasToStyles = styles.to && Object.keys(styles.to).length > 0; + var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0; + + // there is no way we can trigger an animation if no styles and + // no classes are being applied which would then trigger a transition, + // unless there a is raw keyframe value that is applied to the element. + if (!containsKeyframeAnimation + && !hasToStyles + && !setupClasses) { + return closeAndReturnNoopAnimator(); + } - var hasClasses = Object.create(null); - forEach((element.attr('class') || '').split(/\s+/), function(className) { - hasClasses[className] = true; - }); + var cacheKey, stagger; + if (options.stagger > 0) { + var staggerVal = parseFloat(options.stagger); + stagger = { + transitionDelay: staggerVal, + animationDelay: staggerVal, + transitionDuration: 0, + animationDuration: 0 + }; + } else { + cacheKey = gcsHashFn(node, fullClassName); + stagger = computeCachedCssStaggerStyles(node, setupClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES); + } - var toAdd = [], toRemove = []; - forEach((cache && cache.classes) || [], function(status, className) { - var hasClass = hasClasses[className]; - var matchingAnimation = lookup[className] || {}; - - // When addClass and removeClass is called then $animate will check to - // see if addClass and removeClass cancel each other out. When there are - // more calls to removeClass than addClass then the count falls below 0 - // and then the removeClass animation will be allowed. Otherwise if the - // count is above 0 then that means an addClass animation will commence. - // Once an animation is allowed then the code will also check to see if - // there exists any on-going animation that is already adding or remvoing - // the matching CSS class. - if (status === false) { - //does it have the class or will it have the class - if (hasClass || matchingAnimation.event == 'addClass') { - toRemove.push(className); - } - } else if (status === true) { - //is the class missing or will it be removed? - if (!hasClass || matchingAnimation.event == 'removeClass') { - toAdd.push(className); - } - } - }); + $$jqLite.addClass(element, setupClasses); - return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')]; - } - - function lookup(name) { - if (name) { - var matches = [], - flagMap = {}, - classes = name.substr(1).split('.'); - - //the empty string value is the default animation - //operation which performs CSS transition and keyframe - //animations sniffing. This is always included for each - //element animation procedure if the browser supports - //transitions and/or keyframe animations. The default - //animation is added to the top of the list to prevent - //any previous animations from affecting the element styling - //prior to the element being animated. - if ($sniffer.transitions || $sniffer.animations) { - matches.push($injector.get(selectors[''])); - } + var applyOnlyDuration; - for (var i=0; i < classes.length; i++) { - var klass = classes[i], - selectorFactoryName = selectors[klass]; - if (selectorFactoryName && !flagMap[klass]) { - matches.push($injector.get(selectorFactoryName)); - flagMap[klass] = true; - } - } - return matches; - } + if (options.transitionStyle) { + var transitionStyle = [TRANSITION_PROP, options.transitionStyle]; + applyInlineStyle(node, transitionStyle); + temporaryStyles.push(transitionStyle); } - function animationRunner(element, animationEvent, className, options) { - //transcluded directives may sometimes fire an animation using only comment nodes - //best to catch this early on to prevent any animation operations from occurring - var node = element[0]; - if (!node) { - return; - } + if (options.duration >= 0) { + applyOnlyDuration = node.style[TRANSITION_PROP].length > 0; + var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration); - if (options) { - options.to = options.to || {}; - options.from = options.from || {}; - } + // we set the duration so that it will be picked up by getComputedStyle later + applyInlineStyle(node, durationStyle); + temporaryStyles.push(durationStyle); + } - var classNameAdd; - var classNameRemove; - if (isArray(className)) { - classNameAdd = className[0]; - classNameRemove = className[1]; - if (!classNameAdd) { - className = classNameRemove; - animationEvent = 'removeClass'; - } else if (!classNameRemove) { - className = classNameAdd; - animationEvent = 'addClass'; - } else { - className = classNameAdd + ' ' + classNameRemove; - } - } + if (options.keyframeStyle) { + var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle]; + applyInlineStyle(node, keyframeStyle); + temporaryStyles.push(keyframeStyle); + } - var isSetClassOperation = animationEvent == 'setClass'; - var isClassBased = isSetClassOperation - || animationEvent == 'addClass' - || animationEvent == 'removeClass' - || animationEvent == 'animate'; + var itemIndex = stagger + ? options.staggerIndex >= 0 + ? options.staggerIndex + : gcsLookup.count(cacheKey) + : 0; + + var isFirst = itemIndex === 0; + + // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY + // without causing any combination of transitions to kick in. By adding a negative delay value + // it forces the setup class' transition to end immediately. We later then remove the negative + // transition delay to allow for the transition to naturally do it's thing. The beauty here is + // that if there is no transition defined then nothing will happen and this will also allow + // other transitions to be stacked on top of each other without any chopping them out. + if (isFirst) { + blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE); + } - var currentClassName = element.attr('class'); - var classes = currentClassName + ' ' + className; - if (!isAnimatableClassName(classes)) { - return; + var timings = computeTimings(node, fullClassName, cacheKey); + var relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + var flags = {}; + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all'; + flags.applyTransitionDuration = hasToStyles && ( + (flags.hasTransitions && !flags.hasTransitionAll) + || (flags.hasAnimations && !flags.hasTransitions)); + flags.applyAnimationDuration = options.duration && flags.hasAnimations; + flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); + flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; + flags.recalculateTimingStyles = addRemoveClassName.length > 0; + + if (flags.applyTransitionDuration || flags.applyAnimationDuration) { + maxDuration = options.duration ? parseFloat(options.duration) : maxDuration; + + if (flags.applyTransitionDuration) { + flags.hasTransitions = true; + timings.transitionDuration = maxDuration; + applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0; + temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration)); } - var beforeComplete = noop, - beforeCancel = [], - before = [], - afterComplete = noop, - afterCancel = [], - after = []; - - var animationLookup = (' ' + classes).replace(/\s+/g,'.'); - forEach(lookup(animationLookup), function(animationFactory) { - var created = registerAnimation(animationFactory, animationEvent); - if (!created && isSetClassOperation) { - registerAnimation(animationFactory, 'addClass'); - registerAnimation(animationFactory, 'removeClass'); - } - }); - - function registerAnimation(animationFactory, event) { - var afterFn = animationFactory[event]; - var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)]; - if (afterFn || beforeFn) { - if (event == 'leave') { - beforeFn = afterFn; - //when set as null then animation knows to skip this phase - afterFn = null; - } - after.push({ - event: event, fn: afterFn - }); - before.push({ - event: event, fn: beforeFn - }); - return true; - } + if (flags.applyAnimationDuration) { + flags.hasAnimations = true; + timings.animationDuration = maxDuration; + temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration)); } + } - function run(fns, cancellations, allCompleteFn) { - var animations = []; - forEach(fns, function(animation) { - animation.fn && animations.push(animation); - }); - - var count = 0; - function afterAnimationComplete(index) { - if (cancellations) { - (cancellations[index] || noop)(); - if (++count < animations.length) return; - cancellations = null; - } - allCompleteFn(); - } + if (maxDuration === 0 && !flags.recalculateTimingStyles) { + return closeAndReturnNoopAnimator(); + } - //The code below adds directly to the array in order to work with - //both sync and async animations. Sync animations are when the done() - //operation is called right away. DO NOT REFACTOR! - forEach(animations, function(animation, index) { - var progress = function() { - afterAnimationComplete(index); - }; - switch (animation.event) { - case 'setClass': - cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options)); - break; - case 'animate': - cancellations.push(animation.fn(element, className, options.from, options.to, progress)); - break; - case 'addClass': - cancellations.push(animation.fn(element, classNameAdd || className, progress, options)); - break; - case 'removeClass': - cancellations.push(animation.fn(element, classNameRemove || className, progress, options)); - break; - default: - cancellations.push(animation.fn(element, progress, options)); - break; - } - }); + // we need to recalculate the delay value since we used a pre-emptive negative + // delay value and the delay value is required for the final event checking. This + // property will ensure that this will happen after the RAF phase has passed. + if (options.duration == null && timings.transitionDuration > 0) { + flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst; + } - if (cancellations && cancellations.length === 0) { - allCompleteFn(); - } - } + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + if (!options.skipBlocking) { + flags.blockTransition = timings.transitionDuration > 0; + flags.blockKeyframeAnimation = timings.animationDuration > 0 && + stagger.animationDelay > 0 && + stagger.animationDuration === 0; + } - return { - node: node, - event: animationEvent, - className: className, - isClassBased: isClassBased, - isSetClassOperation: isSetClassOperation, - applyStyles: function() { - if (options) { - element.css(angular.extend(options.from || {}, options.to || {})); - } - }, - before: function(allCompleteFn) { - beforeComplete = allCompleteFn; - run(before, beforeCancel, function() { - beforeComplete = noop; - allCompleteFn(); - }); - }, - after: function(allCompleteFn) { - afterComplete = allCompleteFn; - run(after, afterCancel, function() { - afterComplete = noop; - allCompleteFn(); - }); - }, - cancel: function() { - if (beforeCancel) { - forEach(beforeCancel, function(cancelFn) { - (cancelFn || noop)(true); - }); - beforeComplete(true); - } - if (afterCancel) { - forEach(afterCancel, function(cancelFn) { - (cancelFn || noop)(true); - }); - afterComplete(true); - } - } - }; + applyAnimationFromStyles(element, options); + if (!flags.blockTransition) { + blockTransitions(node, false); } - /** - * @ngdoc service - * @name $animate - * @kind object - * - * @description - * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations. - * When any of these operations are run, the $animate service - * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object) - * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run. - * - * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives - * will work out of the box without any extra configuration. - * - * Requires the {@link ngAnimate `ngAnimate`} module to be installed. - * - * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. - * ## Callback Promises - * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The - * promise itself is then resolved once the animation has completed itself, has been cancelled or has been - * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still - * call the resolve function of the animation.) - * - * ```js - * $animate.enter(element, container).then(function() { - * //...this is called once the animation is complete... - * }); - * ``` - * - * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope, - * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using - * `$scope.$apply(...)`; - * - * ```js - * $animate.leave(element).then(function() { - * $scope.$apply(function() { - * $location.path('/new-page'); - * }); - * }); - * ``` - * - * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided - * promise that was returned when the animation was started. - * - * ```js - * var promise = $animate.addClass(element, 'super-long-animation'); - * promise.then(function() { - * //this will still be called even if cancelled - * }); - * - * element.on('click', function() { - * //tooo lazy to wait for the animation to end - * $animate.cancel(promise); - * }); - * ``` - * - * (Keep in mind that the promise cancellation is unique to `$animate` since promises in - * general cannot be cancelled.) - * - */ + applyBlocking(maxDuration); + + // TODO(matsko): for 1.5 change this code to have an animator object for better debugging return { - /** - * @ngdoc method - * @name $animate#animate - * @kind function - * - * @description - * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element. - * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation - * will take on the provided styles. For example, if a transition animation is set for the given className then the - * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is - * detected then the provided styles will be given in as function paramters. - * - * ```js - * ngModule.animation('.my-inline-animation', function() { - * return { - * animate : function(element, className, from, to, done) { - * //styles - * } - * } - * }); - * ``` - * - * Below is a breakdown of each step that occurs during the `animate` animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------| - * | 1. `$animate.animate(...)` is called | `class="my-animation"` | - * | 2. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 3. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 4. the `className` class value is added to the element | `class="my-animation ng-animate className"` | - * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate className"` | - * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.className` class styling is applied right away| `class="my-animation ng-animate className"` | - * | 7. `$animate` applies the provided collection of `from` CSS styles to the element | `class="my-animation ng-animate className"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate className"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate className"` | - * | 10. the `className-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate className className-active"` | - * | 11. `$animate` applies the collection of `to` CSS styles to the element which are then handled by the transition | `class="my-animation ng-animate className className-active"` | - * | 12. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate className className-active"` | - * | 13. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 14. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the enter animation - * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation - * @param {object} to a collection of CSS styles that the element will animate towards - * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`) - * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - animate: function(element, from, to, className, options) { - className = className || 'ng-inline-animate'; - options = parseAnimateOptions(options) || {}; - options.from = to ? from : null; - options.to = to ? to : from; - - return runAnimationPostDigest(function(done) { - return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#enter - * @kind function - * - * @description - * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once - * the animation is started, the following CSS classes will be present on the element for the duration of the animation: - * - * Below is a breakdown of each step that occurs during enter animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------| - * | 1. `$animate.enter(...)` is called | `class="my-animation"` | - * | 2. element is inserted into the `parentElement` element or beside the `afterElement` element | `class="my-animation"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 5. the `.ng-enter` class is added to the element | `class="my-animation ng-animate ng-enter"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-enter"` | - * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-enter` class styling is applied right away | `class="my-animation ng-animate ng-enter"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-enter"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-enter"` | - * | 10. the `.ng-enter-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-enter ng-enter-active"` | - * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-enter ng-enter-active"` | - * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 13. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the enter animation - * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation - * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation - * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - enter: function(element, parentElement, afterElement, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - parentElement = prepareElement(parentElement); - afterElement = prepareElement(afterElement); - - classBasedAnimationsBlocked(element, true); - $delegate.enter(element, parentElement, afterElement); - return runAnimationPostDigest(function(done) { - return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#leave - * @kind function - * - * @description - * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once - * the animation is started, the following CSS classes will be added for the duration of the animation: - * - * Below is a breakdown of each step that occurs during leave animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------| - * | 1. `$animate.leave(...)` is called | `class="my-animation"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. the `.ng-leave` class is added to the element | `class="my-animation ng-animate ng-leave"` | - * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-leave"` | - * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.ng-leave` class styling is applied right away | `class="my-animation ng-animate ng-leave"` | - * | 7. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-leave"` | - * | 8. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-leave"` | - * | 9. the `.ng-leave-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-leave ng-leave-active"` | - * | 10. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-leave ng-leave-active"` | - * | 11. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 12. The element is removed from the DOM | ... | - * | 13. The returned promise is resolved. | ... | - * - * @param {DOMElement} element the element that will be the focus of the leave animation - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - leave: function(element, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - - cancelChildAnimations(element); - classBasedAnimationsBlocked(element, true); - return runAnimationPostDigest(function(done) { - return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() { - $delegate.leave(element); - }, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#move - * @kind function - * - * @description - * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or - * add the element directly after the afterElement element if present. Then the move animation will be run. Once - * the animation is started, the following CSS classes will be added for the duration of the animation: - * - * Below is a breakdown of each step that occurs during move animation: - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------| - * | 1. `$animate.move(...)` is called | `class="my-animation"` | - * | 2. element is moved into the parentElement element or beside the afterElement element | `class="my-animation"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 5. the `.ng-move` class is added to the element | `class="my-animation ng-animate ng-move"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-move"` | - * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-move` class styling is applied right away | `class="my-animation ng-animate ng-move"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-move"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-move"` | - * | 10. the `.ng-move-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-move ng-move-active"` | - * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-move ng-move-active"` | - * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 13. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the move animation - * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation - * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - move: function(element, parentElement, afterElement, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - parentElement = prepareElement(parentElement); - afterElement = prepareElement(afterElement); - - cancelChildAnimations(element); - classBasedAnimationsBlocked(element, true); - $delegate.move(element, parentElement, afterElement); - return runAnimationPostDigest(function(done) { - return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#addClass - * - * @description - * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class. - * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide - * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions - * or keyframes are defined on the -add-active or base CSS class). - * - * Below is a breakdown of each step that occurs during addClass animation: - * - * | Animation Step | What the element class attribute looks like | - * |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| - * | 1. `$animate.addClass(element, 'super')` is called | `class="my-animation"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 3. the `.super-add` class is added to the element | `class="my-animation ng-animate super-add"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate super-add"` | - * | 5. the `.super` and `.super-add-active` classes are added (this triggers the CSS transition/animation) | `class="my-animation ng-animate super super-add super-add-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super super-add super-add-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super super-add super-add-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation super"` | - * | 9. The super class is kept on the element | `class="my-animation super"` | - * | 10. The returned promise is resolved. | `class="my-animation super"` | - * - * @param {DOMElement} element the element that will be animated - * @param {string} className the CSS class that will be added to the element and then animated - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - addClass: function(element, className, options) { - return this.setClass(element, className, [], options); - }, - - /** - * @ngdoc method - * @name $animate#removeClass - * - * @description - * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value - * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in - * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if - * no CSS transitions or keyframes are defined on the -remove or base CSS classes). - * - * Below is a breakdown of each step that occurs during removeClass animation: - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| - * | 1. `$animate.removeClass(element, 'super')` is called | `class="my-animation super"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation super ng-animate"` | - * | 3. the `.super-remove` class is added to the element | `class="my-animation super ng-animate super-remove"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation super ng-animate super-remove"` | - * | 5. the `.super-remove-active` classes are added and `.super` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 9. The returned promise is resolved. | `class="my-animation"` | - * - * - * @param {DOMElement} element the element that will be animated - * @param {string} className the CSS class that will be animated and then removed from the element - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - removeClass: function(element, className, options) { - return this.setClass(element, [], className, options); - }, - - /** - * - * @ngdoc method - * @name $animate#setClass - * - * @description Adds and/or removes the given CSS classes to and from the element. - * Once complete, the `done()` callback will be fired (if provided). - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------| - * | 1. `$animate.setClass(element, 'on', 'off')` is called | `class="my-animation off"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate off"` | - * | 3. the `.on-add` and `.off-remove` classes are added to the element | `class="my-animation ng-animate on-add off-remove off"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate on-add off-remove off"` | - * | 5. the `.on`, `.on-add-active` and `.off-remove-active` classes are added and `.off` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation on"` | - * | 9. The returned promise is resolved. | `class="my-animation on"` | - * - * @param {DOMElement} element the element which will have its CSS classes changed - * removed from it - * @param {string} add the CSS classes which will be added to the element - * @param {string} remove the CSS class which will be removed from the element - * CSS classes have been set on the element - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - setClass: function(element, add, remove, options) { - options = parseAnimateOptions(options); - - var STORAGE_KEY = '$$animateClasses'; - element = angular.element(element); - element = stripCommentsFromElement(element); - - if (classBasedAnimationsBlocked(element)) { - return $delegate.$$setClassImmediately(element, add, remove, options); - } + $$willAnimate: true, + end: endFn, + start: function() { + if (animationClosed) return; + + runnerHost = { + end: endFn, + cancel: cancelFn, + resume: null, //this will be set during the start() phase + pause: null + }; - // we're using a combined array for both the add and remove - // operations since the ORDER OF addClass and removeClass matters - var classes, cache = element.data(STORAGE_KEY); - var hasCache = !!cache; - if (!cache) { - cache = {}; - cache.classes = {}; - } - classes = cache.classes; + runner = new $$AnimateRunner(runnerHost); - add = isArray(add) ? add : add.split(' '); - forEach(add, function(c) { - if (c && c.length) { - classes[c] = true; - } - }); + waitUntilQuiet(start); - remove = isArray(remove) ? remove : remove.split(' '); - forEach(remove, function(c) { - if (c && c.length) { - classes[c] = false; - } - }); + // we don't have access to pause/resume the animation + // since it hasn't run yet. AnimateRunner will therefore + // set noop functions for resume and pause and they will + // later be overridden once the animation is triggered + return runner; + } + }; - if (hasCache) { - if (options && cache.options) { - cache.options = angular.extend(cache.options || {}, options); - } + function endFn() { + close(); + } - //the digest cycle will combine all the animations into one function - return cache.promise; - } else { - element.data(STORAGE_KEY, cache = { - classes: classes, - options: options - }); - } + function cancelFn() { + close(true); + } - return cache.promise = runAnimationPostDigest(function(done) { - var parentElement = element.parent(); - var elementNode = extractElementNode(element); - var parentNode = elementNode.parentNode; - // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed - if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) { - done(); - return; - } + function close(rejected) { // jshint ignore:line + // if the promise has been called already then we shouldn't close + // the animation again + if (animationClosed || (animationCompleted && animationPaused)) return; + animationClosed = true; + animationPaused = false; - var cache = element.data(STORAGE_KEY); - element.removeData(STORAGE_KEY); - - var state = element.data(NG_ANIMATE_STATE) || {}; - var classes = resolveElementClasses(element, cache, state.active); - return !classes - ? done() - : performAnimation('setClass', classes, element, parentElement, null, function() { - if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]); - if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]); - }, cache.options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#cancel - * @kind function - * - * @param {Promise} animationPromise The animation promise that is returned when an animation is started. - * - * @description - * Cancels the provided animation. - */ - cancel: function(promise) { - promise.$$cancelFn(); - }, - - /** - * @ngdoc method - * @name $animate#enabled - * @kind function - * - * @param {boolean=} value If provided then set the animation on or off. - * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation - * @return {boolean} Current animation state. - * - * @description - * Globally enables/disables animations. - * - */ - enabled: function(value, element) { - switch (arguments.length) { - case 2: - if (value) { - cleanup(element); - } else { - var data = element.data(NG_ANIMATE_STATE) || {}; - data.disabled = true; - element.data(NG_ANIMATE_STATE, data); - } - break; + $$jqLite.removeClass(element, setupClasses); + $$jqLite.removeClass(element, activeClasses); - case 1: - rootAnimateState.disabled = !value; - break; + blockKeyframeAnimations(node, false); + blockTransitions(node, false); - default: - value = !rootAnimateState.disabled; - break; - } - return !!value; - } - }; + forEach(temporaryStyles, function(entry) { + // There is only one way to remove inline style properties entirely from elements. + // By using `removeProperty` this works, but we need to convert camel-cased CSS + // styles down to hyphenated values. + node.style[entry[0]] = ''; + }); - /* - all animations call this shared animation triggering function internally. - The animationEvent variable refers to the JavaScript animation event that will be triggered - and the className value is the name of the animation that will be applied within the - CSS code. Element, `parentElement` and `afterElement` are provided DOM elements for the animation - and the onComplete callback will be fired once the animation is fully complete. - */ - function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) { - var noopCancel = noop; - var runner = animationRunner(element, animationEvent, className, options); - if (!runner) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - closeAnimation(); - return noopCancel; + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + + // the reason why we have this option is to allow a synchronous closing callback + // that is fired as SOON as the animation ends (when the CSS is removed) or if + // the animation never takes off at all. A good example is a leave animation since + // the element must be removed just after the animation is over or else the element + // will appear on screen for one animation frame causing an overbearing flicker. + if (options.onDone) { + options.onDone(); } - animationEvent = runner.event; - className = runner.className; - var elementEvents = angular.element._data(runner.node); - elementEvents = elementEvents && elementEvents.events; + // if the preparation function fails then the promise is not setup + if (runner) { + runner.complete(!rejected); + } + } - if (!parentElement) { - parentElement = afterElement ? afterElement.parent() : element.parent(); + function applyBlocking(duration) { + if (flags.blockTransition) { + blockTransitions(node, duration); } - //skip the animation if animations are disabled, a parent is already being animated, - //the element is not currently attached to the document body or then completely close - //the animation if any matching animations are not found at all. - //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found. - if (animationsDisabled(element, parentElement)) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - closeAnimation(); - return noopCancel; + if (flags.blockKeyframeAnimation) { + blockKeyframeAnimations(node, !!duration); } + } - var ngAnimateState = element.data(NG_ANIMATE_STATE) || {}; - var runningAnimations = ngAnimateState.active || {}; - var totalActiveAnimations = ngAnimateState.totalActive || 0; - var lastAnimation = ngAnimateState.last; - var skipAnimation = false; - - if (totalActiveAnimations > 0) { - var animationsToCancel = []; - if (!runner.isClassBased) { - if (animationEvent == 'leave' && runningAnimations['ng-leave']) { - skipAnimation = true; - } else { - //cancel all animations when a structural animation takes place - for (var klass in runningAnimations) { - animationsToCancel.push(runningAnimations[klass]); - } - ngAnimateState = {}; - cleanup(element, true); - } - } else if (lastAnimation.event == 'setClass') { - animationsToCancel.push(lastAnimation); - cleanup(element, className); - } else if (runningAnimations[className]) { - var current = runningAnimations[className]; - if (current.event == animationEvent) { - skipAnimation = true; - } else { - animationsToCancel.push(current); - cleanup(element, className); - } - } + function closeAndReturnNoopAnimator() { + runner = new $$AnimateRunner({ + end: endFn, + cancel: cancelFn + }); - if (animationsToCancel.length > 0) { - forEach(animationsToCancel, function(operation) { - operation.cancel(); - }); - } - } + close(); - if (runner.isClassBased - && !runner.isSetClassOperation - && animationEvent != 'animate' - && !skipAnimation) { - skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR - } + return { + $$willAnimate: false, + start: function() { + return runner; + }, + end: endFn + }; + } - if (skipAnimation) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - fireDoneCallbackAsync(); - return noopCancel; + function start() { + if (animationClosed) return; + if (!node.parentNode) { + close(); + return; } - runningAnimations = ngAnimateState.active || {}; - totalActiveAnimations = ngAnimateState.totalActive || 0; - - if (animationEvent == 'leave') { - //there's no need to ever remove the listener since the element - //will be removed (destroyed) after the leave animation ends or - //is cancelled midway - element.one('$destroy', function(e) { - var element = angular.element(this); - var state = element.data(NG_ANIMATE_STATE); - if (state) { - var activeLeaveAnimation = state.active['ng-leave']; - if (activeLeaveAnimation) { - activeLeaveAnimation.cancel(); - cleanup(element, 'ng-leave'); - } + var startTime, events = []; + + // even though we only pause keyframe animations here the pause flag + // will still happen when transitions are used. Only the transition will + // not be paused since that is not possible. If the animation ends when + // paused then it will not complete until unpaused or cancelled. + var playPause = function(playAnimation) { + if (!animationCompleted) { + animationPaused = !playAnimation; + if (timings.animationDuration) { + var value = blockKeyframeAnimations(node, animationPaused); + animationPaused + ? temporaryStyles.push(value) + : removeFromArray(temporaryStyles, value); } - }); - } + } else if (animationPaused && playAnimation) { + animationPaused = false; + close(); + } + }; - //the ng-animate class does nothing, but it's here to allow for - //parent animations to find and cancel child animations when needed - $$jqLite.addClass(element, NG_ANIMATE_CLASS_NAME); - if (options && options.tempClasses) { - forEach(options.tempClasses, function(className) { - $$jqLite.addClass(element, className); - }); + // checking the stagger duration prevents an accidently cascade of the CSS delay style + // being inherited from the parent. If the transition duration is zero then we can safely + // rely that the delay value is an intential stagger delay style. + var maxStagger = itemIndex > 0 + && ((timings.transitionDuration && stagger.transitionDuration === 0) || + (timings.animationDuration && stagger.animationDuration === 0)) + && Math.max(stagger.animationDelay, stagger.transitionDelay); + if (maxStagger) { + $timeout(triggerAnimationStart, + Math.floor(maxStagger * itemIndex * ONE_SECOND), + false); + } else { + triggerAnimationStart(); } - var localAnimationCount = globalAnimationCounter++; - totalActiveAnimations++; - runningAnimations[className] = runner; + // this will decorate the existing promise runner with pause/resume methods + runnerHost.resume = function() { + playPause(true); + }; - element.data(NG_ANIMATE_STATE, { - last: runner, - active: runningAnimations, - index: localAnimationCount, - totalActive: totalActiveAnimations - }); + runnerHost.pause = function() { + playPause(false); + }; - //first we run the before animations and when all of those are complete - //then we perform the DOM operation and run the next set of animations - fireBeforeCallbackAsync(); - runner.before(function(cancelled) { - var data = element.data(NG_ANIMATE_STATE); - cancelled = cancelled || - !data || !data.active[className] || - (runner.isClassBased && data.active[className].event != animationEvent); - - fireDOMOperation(); - if (cancelled === true) { - closeAnimation(); - } else { - fireAfterCallbackAsync(); - runner.after(closeAnimation); - } - }); + function triggerAnimationStart() { + // just incase a stagger animation kicks in when the animation + // itself was cancelled entirely + if (animationClosed) return; - return runner.cancel; + applyBlocking(false); - function fireDOMCallback(animationPhase) { - var eventName = '$animate:' + animationPhase; - if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) { - $$asyncCallback(function() { - element.triggerHandler(eventName, { - event: animationEvent, - className: className - }); - }); - } - } + forEach(temporaryStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[key] = value; + }); - function fireBeforeCallbackAsync() { - fireDOMCallback('before'); - } + applyAnimationClasses(element, options); + $$jqLite.addClass(element, activeClasses); - function fireAfterCallbackAsync() { - fireDOMCallback('after'); - } + if (flags.recalculateTimingStyles) { + fullClassName = node.className + ' ' + setupClasses; + cacheKey = gcsHashFn(node, fullClassName); - function fireDoneCallbackAsync() { - fireDOMCallback('close'); - doneCallback(); - } + timings = computeTimings(node, fullClassName, cacheKey); + relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + if (maxDuration === 0) { + close(); + return; + } - //it is less complicated to use a flag than managing and canceling - //timeouts containing multiple callbacks. - function fireDOMOperation() { - if (!fireDOMOperation.hasBeenRun) { - fireDOMOperation.hasBeenRun = true; - domOperation(); + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; } - } - function closeAnimation() { - if (!closeAnimation.hasBeenRun) { - if (runner) { //the runner doesn't exist if it fails to instantiate - runner.applyStyles(); - } + if (flags.applyTransitionDelay || flags.applyAnimationDelay) { + relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay) + ? parseFloat(options.delay) + : relativeDelay; - closeAnimation.hasBeenRun = true; - if (options && options.tempClasses) { - forEach(options.tempClasses, function(className) { - $$jqLite.removeClass(element, className); - }); + maxDelay = Math.max(relativeDelay, 0); + + var delayStyle; + if (flags.applyTransitionDelay) { + timings.transitionDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; } - var data = element.data(NG_ANIMATE_STATE); - if (data) { - - /* only structural animations wait for reflow before removing an - animation, but class-based animations don't. An example of this - failing would be when a parent HTML tag has a ng-class attribute - causing ALL directives below to skip animations during the digest */ - if (runner && runner.isClassBased) { - cleanup(element, className); - } else { - $$asyncCallback(function() { - var data = element.data(NG_ANIMATE_STATE) || {}; - if (localAnimationCount == data.index) { - cleanup(element, className, animationEvent); - } - }); - element.data(NG_ANIMATE_STATE, data); - } + if (flags.applyAnimationDelay) { + timings.animationDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay, true); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; } - fireDoneCallbackAsync(); } - } - } - function cancelChildAnimations(element) { - var node = extractElementNode(element); - if (node) { - var nodes = angular.isFunction(node.getElementsByClassName) ? - node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) : - node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME); - forEach(nodes, function(element) { - element = angular.element(element); - var data = element.data(NG_ANIMATE_STATE); - if (data && data.active) { - forEach(data.active, function(runner) { - runner.cancel(); - }); - } - }); - } - } + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; - function cleanup(element, className) { - if (isMatchingElement(element, $rootElement)) { - if (!rootAnimateState.disabled) { - rootAnimateState.running = false; - rootAnimateState.structural = false; + if (options.easing) { + var easeProp, easeVal = options.easing; + if (flags.hasTransitions) { + easeProp = TRANSITION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + if (flags.hasAnimations) { + easeProp = ANIMATION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } } - } else if (className) { - var data = element.data(NG_ANIMATE_STATE) || {}; - var removeAnimations = className === true; - if (!removeAnimations && data.active && data.active[className]) { - data.totalActive--; - delete data.active[className]; + if (timings.transitionDuration) { + events.push(TRANSITIONEND_EVENT); } - if (removeAnimations || !data.totalActive) { - $$jqLite.removeClass(element, NG_ANIMATE_CLASS_NAME); - element.removeData(NG_ANIMATE_STATE); + if (timings.animationDuration) { + events.push(ANIMATIONEND_EVENT); } - } - } - function animationsDisabled(element, parentElement) { - if (rootAnimateState.disabled) { - return true; + startTime = Date.now(); + element.on(events.join(' '), onAnimationProgress); + $timeout(onAnimationExpired, maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime); + + applyAnimationToStyles(element, options); } - if (isMatchingElement(element, $rootElement)) { - return rootAnimateState.running; + function onAnimationExpired() { + // although an expired animation is a failed animation, getting to + // this outcome is very easy if the CSS code screws up. Therefore we + // should still continue normally as if the animation completed correctly. + close(); } - var allowChildAnimations, parentRunningAnimation, hasParent; - do { - //the element did not reach the root element which means that it - //is not apart of the DOM. Therefore there is no reason to do - //any animations on it - if (parentElement.length === 0) break; - - var isRoot = isMatchingElement(parentElement, $rootElement); - var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {}); - if (state.disabled) { - return true; - } + function onAnimationProgress(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); - //no matter what, for an animation to work it must reach the root element - //this implies that the element is attached to the DOM when the animation is run - if (isRoot) { - hasParent = true; - } + /* Firefox (or possibly just Gecko) likes to not round values up + * when a ms measurement is used for the animation */ + var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); - //once a flag is found that is strictly false then everything before - //it will be discarded and all child animations will be restricted - if (allowChildAnimations !== false) { - var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN); - if (angular.isDefined(animateChildrenFlag)) { - allowChildAnimations = animateChildrenFlag; - } + /* $manualTimeStamp is a mocked timeStamp value which is set + * within browserTrigger(). This is only here so that tests can + * mock animations properly. Real events fallback to event.timeStamp, + * or, if they don't, then a timeStamp is automatically created for them. + * We're checking to see if the timeStamp surpasses the expected delay, + * but we're using elapsedTime instead of the timeStamp on the 2nd + * pre-condition since animations sometimes close off early */ + if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { + // we set this flag to ensure that if the transition is paused then, when resumed, + // the animation will automatically close itself since transitions cannot be paused. + animationCompleted = true; + close(); } - - parentRunningAnimation = parentRunningAnimation || - state.running || - (state.last && !state.last.isClassBased); } - while (parentElement = parentElement.parent()); - - return !hasParent || (!allowChildAnimations && parentRunningAnimation); - } - }]); - - $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow', - function($window, $sniffer, $timeout, $$animateReflow) { - // Detect proper transitionend/animationend event names. - var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; - - // If unprefixed events are not supported but webkit-prefixed are, use the latter. - // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. - // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` - // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. - // Register both events in case `window.onanimationend` is not supported because of that, - // do the same for `transitionend` as Safari is likely to exhibit similar behavior. - // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit - // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition - if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { - CSS_PREFIX = '-webkit-'; - TRANSITION_PROP = 'WebkitTransition'; - TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; - } else { - TRANSITION_PROP = 'transition'; - TRANSITIONEND_EVENT = 'transitionend'; } + } + }]; +}]; - if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { - CSS_PREFIX = '-webkit-'; - ANIMATION_PROP = 'WebkitAnimation'; - ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; - } else { - ANIMATION_PROP = 'animation'; - ANIMATIONEND_EVENT = 'animationend'; - } - - var DURATION_KEY = 'Duration'; - var PROPERTY_KEY = 'Property'; - var DELAY_KEY = 'Delay'; - var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; - var ANIMATION_PLAYSTATE_KEY = 'PlayState'; - var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey'; - var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data'; - var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; - var CLOSING_TIME_BUFFER = 1.5; - var ONE_SECOND = 1000; - - var lookupCache = {}; - var parentCounter = 0; - var animationReflowQueue = []; - var cancelAnimationReflow; - function clearCacheAfterReflow() { - if (!cancelAnimationReflow) { - cancelAnimationReflow = $$animateReflow(function() { - animationReflowQueue = []; - cancelAnimationReflow = null; - lookupCache = {}; - }); - } - } +var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateCssDriver'); - function afterReflow(element, callback) { - if (cancelAnimationReflow) { - cancelAnimationReflow(); - } - animationReflowQueue.push(callback); - cancelAnimationReflow = $$animateReflow(function() { - forEach(animationReflowQueue, function(fn) { - fn(); - }); + var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim'; + var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor'; - animationReflowQueue = []; - cancelAnimationReflow = null; - lookupCache = {}; - }); - } + var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out'; + var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in'; - var closingTimer = null; - var closingTimestamp = 0; - var animationElementQueue = []; - function animationCloseHandler(element, totalTime) { - var node = extractElementNode(element); - element = angular.element(node); + this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$document', '$sniffer', + function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $document, $sniffer) { - //this item will be garbage collected by the closing - //animation timeout - animationElementQueue.push(element); + // only browsers that support these properties can render animations + if (!$sniffer.animations && !$sniffer.transitions) return noop; - //but it may not need to cancel out the existing timeout - //if the timestamp is less than the previous one - var futureTimestamp = Date.now() + totalTime; - if (futureTimestamp <= closingTimestamp) { - return; - } + var bodyNode = getDomNode($document).body; + var rootNode = getDomNode($rootElement); - $timeout.cancel(closingTimer); + var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode); - closingTimestamp = futureTimestamp; - closingTimer = $timeout(function() { - closeAllAnimations(animationElementQueue); - animationElementQueue = []; - }, totalTime, false); - } + return function initDriverFn(animationDetails) { + return animationDetails.from && animationDetails.to + ? prepareFromToAnchorAnimation(animationDetails.from, + animationDetails.to, + animationDetails.classes, + animationDetails.anchors) + : prepareRegularAnimation(animationDetails); + }; - function closeAllAnimations(elements) { - forEach(elements, function(element) { - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (elementData) { - forEach(elementData.closeAnimationFns, function(fn) { - fn(); - }); - } - }); - } + function filterCssClasses(classes) { + //remove all the `ng-` stuff + return classes.replace(/\bng-\S+\b/g, ''); + } - function getElementAnimationDetails(element, cacheKey) { - var data = cacheKey ? lookupCache[cacheKey] : null; - if (!data) { - var transitionDuration = 0; - var transitionDelay = 0; - var animationDuration = 0; - var animationDelay = 0; + function getUniqueValues(a, b) { + if (isString(a)) a = a.split(' '); + if (isString(b)) b = b.split(' '); + return a.filter(function(val) { + return b.indexOf(val) === -1; + }).join(' '); + } + + function prepareAnchoredAnimation(classes, outAnchor, inAnchor) { + var clone = jqLite(getDomNode(outAnchor).cloneNode(true)); + var startingClasses = filterCssClasses(getClassVal(clone)); - //we want all the styles defined before and after - forEach(element, function(element) { - if (element.nodeType == ELEMENT_NODE) { - var elementStyles = $window.getComputedStyle(element) || {}; + outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); - var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY]; - transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration); + clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME); - var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY]; - transitionDelay = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay); + rootBodyElement.append(clone); - var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY]; - animationDelay = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay); + var animatorIn, animatorOut = prepareOutAnimation(); + + // the user may not end up using the `out` animation and + // only making use of the `in` animation or vice-versa. + // In either case we should allow this and not assume the + // animation is over unless both animations are not used. + if (!animatorOut) { + animatorIn = prepareInAnimation(); + if (!animatorIn) { + return end(); + } + } - var aDuration = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]); + var startingAnimator = animatorOut || animatorIn; - if (aDuration > 0) { - aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1; + return { + start: function() { + var runner; + + var currentAnimation = startingAnimator.start(); + currentAnimation.done(function() { + currentAnimation = null; + if (!animatorIn) { + animatorIn = prepareInAnimation(); + if (animatorIn) { + currentAnimation = animatorIn.start(); + currentAnimation.done(function() { + currentAnimation = null; + end(); + runner.complete(); + }); + return currentAnimation; } - animationDuration = Math.max(aDuration, animationDuration); } + // in the event that there is no `in` animation + end(); + runner.complete(); }); - data = { - total: 0, - transitionDelay: transitionDelay, - transitionDuration: transitionDuration, - animationDelay: animationDelay, - animationDuration: animationDuration - }; - if (cacheKey) { - lookupCache[cacheKey] = data; + + runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn + }); + + return runner; + + function endFn() { + if (currentAnimation) { + currentAnimation.end(); + } } } - return data; - } + }; - function parseMaxTime(str) { - var maxValue = 0; - var values = isString(str) ? - str.split(/\s*,\s*/) : - []; - forEach(values, function(value) { - maxValue = Math.max(parseFloat(value) || 0, maxValue); + function calculateAnchorStyles(anchor) { + var styles = {}; + + var coords = getDomNode(anchor).getBoundingClientRect(); + + // we iterate directly since safari messes up and doesn't return + // all the keys for the coods object when iterated + forEach(['width','height','top','left'], function(key) { + var value = coords[key]; + switch (key) { + case 'top': + value += bodyNode.scrollTop; + break; + case 'left': + value += bodyNode.scrollLeft; + break; + } + styles[key] = Math.floor(value) + 'px'; }); - return maxValue; + return styles; } - function getCacheKey(element) { - var parentElement = element.parent(); - var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY); - if (!parentID) { - parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter); - parentID = parentCounter; - } - return parentID + '-' + extractElementNode(element).getAttribute('class'); + function prepareOutAnimation() { + var animator = $animateCss(clone, { + addClass: NG_OUT_ANCHOR_CLASS_NAME, + delay: true, + from: calculateAnchorStyles(outAnchor) + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; } - function animateSetup(animationEvent, element, className, styles) { - var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0; + function getClassVal(element) { + return element.attr('class') || ''; + } - var cacheKey = getCacheKey(element); - var eventCacheKey = cacheKey + ' ' + className; - var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; + function prepareInAnimation() { + var endingClasses = filterCssClasses(getClassVal(inAnchor)); + var toAdd = getUniqueValues(endingClasses, startingClasses); + var toRemove = getUniqueValues(startingClasses, endingClasses); - var stagger = {}; - if (itemIndex > 0) { - var staggerClassName = className + '-stagger'; - var staggerCacheKey = cacheKey + ' ' + staggerClassName; - var applyClasses = !lookupCache[staggerCacheKey]; + var animator = $animateCss(clone, { + to: calculateAnchorStyles(inAnchor), + addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd, + removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove, + delay: true + }); - applyClasses && $$jqLite.addClass(element, staggerClassName); + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } - stagger = getElementAnimationDetails(element, staggerCacheKey); + function end() { + clone.remove(); + outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + } + } - applyClasses && $$jqLite.removeClass(element, staggerClassName); + function prepareFromToAnchorAnimation(from, to, classes, anchors) { + var fromAnimation = prepareRegularAnimation(from); + var toAnimation = prepareRegularAnimation(to); + + var anchorAnimations = []; + forEach(anchors, function(anchor) { + var outElement = anchor['out']; + var inElement = anchor['in']; + var animator = prepareAnchoredAnimation(classes, outElement, inElement); + if (animator) { + anchorAnimations.push(animator); } + }); - $$jqLite.addClass(element, className); + // no point in doing anything when there are no elements to animate + if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return; - var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {}; - var timings = getElementAnimationDetails(element, eventCacheKey); - var transitionDuration = timings.transitionDuration; - var animationDuration = timings.animationDuration; + return { + start: function() { + var animationRunners = []; - if (structural && transitionDuration === 0 && animationDuration === 0) { - $$jqLite.removeClass(element, className); - return false; - } + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } - var blockTransition = styles || (structural && transitionDuration > 0); - var blockAnimation = animationDuration > 0 && - stagger.animationDelay > 0 && - stagger.animationDuration === 0; - - var closeAnimationFns = formerData.closeAnimationFns || []; - element.data(NG_ANIMATE_CSS_DATA_KEY, { - stagger: stagger, - cacheKey: eventCacheKey, - running: formerData.running || 0, - itemIndex: itemIndex, - blockTransition: blockTransition, - closeAnimationFns: closeAnimationFns - }); + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + forEach(anchorAnimations, function(animation) { + animationRunners.push(animation.start()); + }); + + var runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn // CSS-driven animations cannot be cancelled, only ended + }); + + $$AnimateRunner.all(animationRunners, function(status) { + runner.complete(status); + }); - var node = extractElementNode(element); + return runner; - if (blockTransition) { - blockTransitions(node, true); - if (styles) { - element.css(styles); + function endFn() { + forEach(animationRunners, function(runner) { + runner.end(); + }); } } + }; + } - if (blockAnimation) { - blockAnimations(node, true); + function prepareRegularAnimation(animationDetails) { + var element = animationDetails.element; + var options = animationDetails.options || {}; + + if (animationDetails.structural) { + // structural animations ensure that the CSS classes are always applied + // before the detection starts. + options.structural = options.applyClassesEarly = true; + + // we special case the leave animation since we want to ensure that + // the element is removed as soon as the animation is over. Otherwise + // a flicker might appear or the element may not be removed at all + options.event = animationDetails.event; + if (options.event === 'leave') { + options.onDone = options.domOperation; } + } else { + options.event = null; + } + + var animator = $animateCss(element, options); - return true; + // the driver lookup code inside of $$animation attempts to spawn a + // driver one by one until a driver returns a.$$willAnimate animator object. + // $animateCss will always return an object, however, it will pass in + // a flag as a hint as to whether an animation was detected or not + return animator.$$willAnimate ? animator : null; + } + }]; +}]; + +// TODO(matsko): use caching here to speed things up for detection +// TODO(matsko): add documentation +// by the time... + +var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) { + this.$get = ['$injector', '$$AnimateRunner', '$$rAFMutex', '$$jqLite', + function($injector, $$AnimateRunner, $$rAFMutex, $$jqLite) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + // $animateJs(element, 'enter'); + return function(element, event, classes, options) { + // the `classes` argument is optional and if it is not used + // then the classes will be resolved from the element's className + // property as well as options.addClass/options.removeClass. + if (arguments.length === 3 && isObject(classes)) { + options = classes; + classes = null; } - function animateRun(animationEvent, element, className, activeAnimationComplete, styles) { - var node = extractElementNode(element); - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (node.getAttribute('class').indexOf(className) == -1 || !elementData) { - activeAnimationComplete(); - return; + options = prepareAnimationOptions(options); + if (!classes) { + classes = element.attr('class') || ''; + if (options.addClass) { + classes += ' ' + options.addClass; } + if (options.removeClass) { + classes += ' ' + options.removeClass; + } + } - var activeClassName = ''; - var pendingClassName = ''; - forEach(className.split(' '), function(klass, i) { - var prefix = (i > 0 ? ' ' : '') + klass; - activeClassName += prefix + '-active'; - pendingClassName += prefix + '-pending'; - }); + var classesToAdd = options.addClass; + var classesToRemove = options.removeClass; + + // the lookupAnimations function returns a series of animation objects that are + // matched up with one or more of the CSS classes. These animation objects are + // defined via the module.animation factory function. If nothing is detected then + // we don't return anything which then makes $animation query the next driver. + var animations = lookupAnimations(classes); + var before, after; + if (animations.length) { + var afterFn, beforeFn; + if (event == 'leave') { + beforeFn = 'leave'; + afterFn = 'afterLeave'; // TODO(matsko): get rid of this + } else { + beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + afterFn = event; + } - var style = ''; - var appliedStyles = []; - var itemIndex = elementData.itemIndex; - var stagger = elementData.stagger; - var staggerTime = 0; - if (itemIndex > 0) { - var transitionStaggerDelay = 0; - if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { - transitionStaggerDelay = stagger.transitionDelay * itemIndex; - } + if (event !== 'enter' && event !== 'move') { + before = packageAnimations(element, event, options, animations, beforeFn); + } + after = packageAnimations(element, event, options, animations, afterFn); + } - var animationStaggerDelay = 0; - if (stagger.animationDelay > 0 && stagger.animationDuration === 0) { - animationStaggerDelay = stagger.animationDelay * itemIndex; - appliedStyles.push(CSS_PREFIX + 'animation-play-state'); - } + // no matching animations + if (!before && !after) return; - staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100; - } + function applyOptions() { + options.domOperation(); + applyAnimationClasses(element, options); + } + + return { + start: function() { + var closeActiveAnimations; + var chain = []; - if (!staggerTime) { - $$jqLite.addClass(element, activeClassName); - if (elementData.blockTransition) { - blockTransitions(node, false); + if (before) { + chain.push(function(fn) { + closeActiveAnimations = before(fn); + }); } - } - var eventCacheKey = elementData.cacheKey + ' ' + activeClassName; - var timings = getElementAnimationDetails(element, eventCacheKey); - var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration); - if (maxDuration === 0) { - $$jqLite.removeClass(element, activeClassName); - animateClose(element, className); - activeAnimationComplete(); - return; - } + if (chain.length) { + chain.push(function(fn) { + applyOptions(); + fn(true); + }); + } else { + applyOptions(); + } - if (!staggerTime && styles && Object.keys(styles).length > 0) { - if (!timings.transitionDuration) { - element.css('transition', timings.animationDuration + 's linear all'); - appliedStyles.push('transition'); + if (after) { + chain.push(function(fn) { + closeActiveAnimations = after(fn); + }); } - element.css(styles); - } - var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay); - var maxDelayTime = maxDelay * ONE_SECOND; + var animationClosed = false; + var runner = new $$AnimateRunner({ + end: function() { + endAnimations(); + }, + cancel: function() { + endAnimations(true); + } + }); + + $$AnimateRunner.chain(chain, onComplete); + return runner; + + function onComplete(success) { + animationClosed = true; + applyOptions(); + applyAnimationStyles(element, options); + runner.complete(success); + } - if (appliedStyles.length > 0) { - //the element being animated may sometimes contain comment nodes in - //the jqLite object, so we're safe to use a single variable to house - //the styles since there is always only one element being animated - var oldStyle = node.getAttribute('style') || ''; - if (oldStyle.charAt(oldStyle.length - 1) !== ';') { - oldStyle += ';'; + function endAnimations(cancelled) { + if (!animationClosed) { + (closeActiveAnimations || noop)(cancelled); + onComplete(cancelled); + } } - node.setAttribute('style', oldStyle + ' ' + style); } + }; - var startTime = Date.now(); - var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; - var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER; - var totalTime = (staggerTime + animationTime) * ONE_SECOND; + function executeAnimationFn(fn, element, event, options, onDone) { + var args; + switch (event) { + case 'animate': + args = [element, options.from, options.to, onDone]; + break; - var staggerTimeout; - if (staggerTime > 0) { - $$jqLite.addClass(element, pendingClassName); - staggerTimeout = $timeout(function() { - staggerTimeout = null; + case 'setClass': + args = [element, classesToAdd, classesToRemove, onDone]; + break; - if (timings.transitionDuration > 0) { - blockTransitions(node, false); - } - if (timings.animationDuration > 0) { - blockAnimations(node, false); - } + case 'addClass': + args = [element, classesToAdd, onDone]; + break; - $$jqLite.addClass(element, activeClassName); - $$jqLite.removeClass(element, pendingClassName); + case 'removeClass': + args = [element, classesToRemove, onDone]; + break; - if (styles) { - if (timings.transitionDuration === 0) { - element.css('transition', timings.animationDuration + 's linear all'); - } - element.css(styles); - appliedStyles.push('transition'); - } - }, staggerTime * ONE_SECOND, false); + default: + args = [element, onDone]; + break; } - element.on(css3AnimationEvents, onAnimationProgress); - elementData.closeAnimationFns.push(function() { - onEnd(); - activeAnimationComplete(); - }); + args.push(options); - elementData.running++; - animationCloseHandler(element, totalTime); - return onEnd; - - // This will automatically be called by $animate so - // there is no need to attach this internally to the - // timeout done method. - function onEnd() { - element.off(css3AnimationEvents, onAnimationProgress); - $$jqLite.removeClass(element, activeClassName); - $$jqLite.removeClass(element, pendingClassName); - if (staggerTimeout) { - $timeout.cancel(staggerTimeout); + var value = fn.apply(fn, args); + if (value) { + if (isFunction(value.start)) { + value = value.start(); } - animateClose(element, className); - var node = extractElementNode(element); - for (var i in appliedStyles) { - node.style.removeProperty(appliedStyles[i]); + + if (value instanceof $$AnimateRunner) { + value.done(onDone); + } else if (isFunction(value)) { + // optional onEnd / onCancel callback + return value; } } - function onAnimationProgress(event) { - event.stopPropagation(); - var ev = event.originalEvent || event; - var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); + return noop; + } - /* Firefox (or possibly just Gecko) likes to not round values up - * when a ms measurement is used for the animation */ - var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); + function groupEventedAnimations(element, event, options, animations, fnName) { + var operations = []; + forEach(animations, function(ani) { + var animation = ani[fnName]; + if (!animation) return; + + // note that all of these animations will run in parallel + operations.push(function() { + var runner; + var endProgressCb; + + var resolved = false; + var onAnimationComplete = function(rejected) { + if (!resolved) { + resolved = true; + (endProgressCb || noop)(rejected); + runner.complete(!rejected); + } + }; - /* $manualTimeStamp is a mocked timeStamp value which is set - * within browserTrigger(). This is only here so that tests can - * mock animations properly. Real events fallback to event.timeStamp, - * or, if they don't, then a timeStamp is automatically created for them. - * We're checking to see if the timeStamp surpasses the expected delay, - * but we're using elapsedTime instead of the timeStamp on the 2nd - * pre-condition since animations sometimes close off early */ - if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { - activeAnimationComplete(); + runner = new $$AnimateRunner({ + end: function() { + onAnimationComplete(); + }, + cancel: function() { + onAnimationComplete(true); + } + }); + + endProgressCb = executeAnimationFn(animation, element, event, options, function(result) { + var cancelled = result === false; + onAnimationComplete(cancelled); + }); + + return runner; + }); + }); + + return operations; + } + + function packageAnimations(element, event, options, animations, fnName) { + var operations = groupEventedAnimations(element, event, options, animations, fnName); + if (operations.length === 0) { + var a,b; + if (fnName === 'beforeSetClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass'); + } else if (fnName === 'setClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass'); + } + + if (a) { + operations = operations.concat(a); + } + if (b) { + operations = operations.concat(b); + } + } + + if (operations.length === 0) return; + + // TODO(matsko): add documentation + return function startAnimation(callback) { + var runners = []; + if (operations.length) { + forEach(operations, function(animateFn) { + runners.push(animateFn()); + }); } + + runners.length ? $$AnimateRunner.all(runners, callback) : callback(); + + return function endFn(reject) { + forEach(runners, function(runner) { + reject ? runner.cancel() : runner.end(); + }); + }; + }; + } + }; + + function lookupAnimations(classes) { + classes = isArray(classes) ? classes : classes.split(' '); + var matches = [], flagMap = {}; + for (var i=0; i < classes.length; i++) { + var klass = classes[i], + animationFactory = $animateProvider.$$registeredAnimations[klass]; + if (animationFactory && !flagMap[klass]) { + matches.push($injector.get(animationFactory)); + flagMap[klass] = true; } } + return matches; + } + }]; +}]; + +var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateJsDriver'); + this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) { + return function initDriverFn(animationDetails) { + if (animationDetails.from && animationDetails.to) { + var fromAnimation = prepareAnimation(animationDetails.from); + var toAnimation = prepareAnimation(animationDetails.to); + if (!fromAnimation && !toAnimation) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + $$AnimateRunner.all(animationRunners, done); + + var runner = new $$AnimateRunner({ + end: endFnFactory(), + cancel: endFnFactory() + }); + + return runner; + + function endFnFactory() { + return function() { + forEach(animationRunners, function(runner) { + // at this point we cannot cancel animations for groups just yet. 1.5+ + runner.end(); + }); + }; + } - function blockTransitions(node, bool) { - node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : ''; + function done(status) { + runner.complete(status); + } + } + }; + } else { + return prepareAnimation(animationDetails); } + }; - function blockAnimations(node, bool) { - node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : ''; + function prepareAnimation(animationDetails) { + // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations + var element = animationDetails.element; + var event = animationDetails.event; + var options = animationDetails.options; + var classes = animationDetails.classes; + return $$animateJs(element, event, classes, options); + } + }]; +}]; + +var NG_ANIMATE_ATTR_NAME = 'data-ng-animate'; +var NG_ANIMATE_PIN_DATA = '$ngAnimatePin'; +var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { + var PRE_DIGEST_STATE = 1; + var RUNNING_STATE = 2; + + var rules = this.rules = { + skip: [], + cancel: [], + join: [] + }; + + function isAllowed(ruleType, element, currentAnimation, previousAnimation) { + return rules[ruleType].some(function(fn) { + return fn(element, currentAnimation, previousAnimation); + }); + } + + function hasAnimationClasses(options, and) { + options = options || {}; + var a = (options.addClass || '').length > 0; + var b = (options.removeClass || '').length > 0; + return and ? a && b : a || b; + } + + rules.join.push(function(element, newAnimation, currentAnimation) { + // if the new animation is class-based then we can just tack that on + return !newAnimation.structural && hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // there is no need to animate anything if no classes are being added and + // there is no structural animation that will be triggered + return !newAnimation.structural && !hasAnimationClasses(newAnimation.options); + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // why should we trigger a new structural animation if the element will + // be removed from the DOM anyway? + return currentAnimation.event == 'leave' && newAnimation.structural; + }); + + rules.skip.push(function(element, newAnimation, currentAnimation) { + // if there is a current animation then skip the class-based animation + return currentAnimation.structural && !newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // there can never be two structural animations running at the same time + return currentAnimation.structural && newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // if the previous animation is already running, but the new animation will + // be triggered, but the new animation is structural + return currentAnimation.state === RUNNING_STATE && newAnimation.structural; + }); + + rules.cancel.push(function(element, newAnimation, currentAnimation) { + var nO = newAnimation.options; + var cO = currentAnimation.options; + + // if the exact same CSS class is added/removed then it's safe to cancel it + return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass); + }); + + this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap', + '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', + function($$rAF, $rootScope, $rootElement, $document, $$HashMap, + $$animation, $$AnimateRunner, $templateRequest, $$jqLite) { + + var activeAnimationsLookup = new $$HashMap(); + var disabledElementsLookup = new $$HashMap(); + + var animationsEnabled = null; + + // Wait until all directive and route-related templates are downloaded and + // compiled. The $templateRequest.totalPendingRequests variable keeps track of + // all of the remote templates being currently downloaded. If there are no + // templates currently downloading then the watcher will still fire anyway. + var deregisterWatch = $rootScope.$watch( + function() { return $templateRequest.totalPendingRequests === 0; }, + function(isEmpty) { + if (!isEmpty) return; + deregisterWatch(); + + // Now that all templates have been downloaded, $animate will wait until + // the post digest queue is empty before enabling animations. By having two + // calls to $postDigest calls we can ensure that the flag is enabled at the + // very end of the post digest queue. Since all of the animations in $animate + // use $postDigest, it's important that the code below executes at the end. + // This basically means that the page is fully downloaded and compiled before + // any animations are triggered. + $rootScope.$$postDigest(function() { + $rootScope.$$postDigest(function() { + // we check for null directly in the event that the application already called + // .enabled() with whatever arguments that it provided it with + if (animationsEnabled === null) { + animationsEnabled = true; + } + }); + }); } + ); - function animateBefore(animationEvent, element, className, styles) { - if (animateSetup(animationEvent, element, className, styles)) { - return function(cancelled) { - cancelled && animateClose(element, className); - }; - } + var bodyElement = jqLite($document[0].body); + + var callbackRegistry = {}; + + // remember that the classNameFilter is set during the provider/config + // stage therefore we can optimize here and setup a helper function + var classNameFilter = $animateProvider.classNameFilter(); + var isAnimatableClassName = !classNameFilter + ? function() { return true; } + : function(className) { + return classNameFilter.test(className); + }; + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + function normalizeAnimationOptions(element, options) { + return mergeAnimationOptions(element, options, {}); + } + + function findCallbacks(element, event) { + var targetNode = getDomNode(element); + + var matches = []; + var entries = callbackRegistry[event]; + if (entries) { + forEach(entries, function(entry) { + if (entry.node.contains(targetNode)) { + matches.push(entry.callback); + } + }); } - function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) { - if (element.data(NG_ANIMATE_CSS_DATA_KEY)) { - return animateRun(animationEvent, element, className, afterAnimationComplete, styles); + return matches; + } + + function triggerCallback(event, element, phase, data) { + $$rAF(function() { + forEach(findCallbacks(element, event), function(callback) { + callback(element, phase, data); + }); + }); + } + + return { + on: function(event, container, callback) { + var node = extractElementNode(container); + callbackRegistry[event] = callbackRegistry[event] || []; + callbackRegistry[event].push({ + node: node, + callback: callback + }); + }, + + off: function(event, container, callback) { + var entries = callbackRegistry[event]; + if (!entries) return; + + callbackRegistry[event] = arguments.length === 1 + ? null + : filterFromRegistry(entries, container, callback); + + function filterFromRegistry(list, matchContainer, matchCallback) { + var containerNode = extractElementNode(matchContainer); + return list.filter(function(entry) { + var isMatch = entry.node === containerNode && + (!matchCallback || entry.callback === matchCallback); + return !isMatch; + }); + } + }, + + pin: function(element, parentElement) { + assertArg(isElement(element), 'element', 'not an element'); + assertArg(isElement(parentElement), 'parentElement', 'not an element'); + element.data(NG_ANIMATE_PIN_DATA, parentElement); + }, + + push: function(element, event, options, domOperation) { + options = options || {}; + options.domOperation = domOperation; + return queueAnimation(element, event, options); + }, + + // this method has four signatures: + // () - global getter + // (bool) - global setter + // (element) - element getter + // (element, bool) - element setter<F37> + enabled: function(element, bool) { + var argCount = arguments.length; + + if (argCount === 0) { + // () - Global getter + bool = !!animationsEnabled; } else { - animateClose(element, className); - afterAnimationComplete(); + var hasElement = isElement(element); + + if (!hasElement) { + // (bool) - Global setter + bool = animationsEnabled = !!element; + } else { + var node = getDomNode(element); + var recordExists = disabledElementsLookup.get(node); + + if (argCount === 1) { + // (element) - Element getter + bool = !recordExists; + } else { + // (element, bool) - Element setter + bool = !!bool; + if (!bool) { + disabledElementsLookup.put(node, true); + } else if (recordExists) { + disabledElementsLookup.remove(node); + } + } + } } + + return bool; + } + }; + + function queueAnimation(element, event, options) { + var node, parent; + element = stripCommentsFromElement(element); + if (element) { + node = getDomNode(element); + parent = element.parent(); } - function animate(animationEvent, element, className, animationComplete, options) { - //If the animateSetup function doesn't bother returning a - //cancellation function then it means that there is no animation - //to perform at all - var preReflowCancellation = animateBefore(animationEvent, element, className, options.from); - if (!preReflowCancellation) { - clearCacheAfterReflow(); - animationComplete(); - return; - } + options = prepareAnimationOptions(options); - //There are two cancellation functions: one is before the first - //reflow animation and the second is during the active state - //animation. The first function will take care of removing the - //data from the element which will not make the 2nd animation - //happen in the first place - var cancel = preReflowCancellation; - afterReflow(element, function() { - //once the reflow is complete then we point cancel to - //the new cancellation function which will remove all of the - //animation properties from the active animation - cancel = animateAfter(animationEvent, element, className, animationComplete, options.to); - }); + // we create a fake runner with a working promise. + // These methods will become available after the digest has passed + var runner = new $$AnimateRunner(); - return function(cancelled) { - (cancel || noop)(cancelled); - }; + // there are situations where a directive issues an animation for + // a jqLite wrapper that contains only comment nodes... If this + // happens then there is no way we can perform an animation + if (!node) { + close(); + return runner; + } + + if (isArray(options.addClass)) { + options.addClass = options.addClass.join(' '); } - function animateClose(element, className) { - $$jqLite.removeClass(element, className); - var data = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (data) { - if (data.running) { - data.running--; + if (isArray(options.removeClass)) { + options.removeClass = options.removeClass.join(' '); + } + + if (options.from && !isObject(options.from)) { + options.from = null; + } + + if (options.to && !isObject(options.to)) { + options.to = null; + } + + var className = [node.className, options.addClass, options.removeClass].join(' '); + if (!isAnimatableClassName(className)) { + close(); + return runner; + } + + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // this is a hard disable of all animations for the application or on + // the element itself, therefore there is no need to continue further + // past this point if not enabled + var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node); + var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {}; + var hasExistingAnimation = !!existingAnimation.state; + + // there is no point in traversing the same collection of parent ancestors if a followup + // animation will be run on the same element that already did all that checking work + if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) { + skipAnimations = !areAnimationsAllowed(element, parent, event); + } + + if (skipAnimations) { + close(); + return runner; + } + + if (isStructural) { + closeChildAnimations(element); + } + + var newAnimation = { + structural: isStructural, + element: element, + event: event, + close: close, + options: options, + runner: runner + }; + + if (hasExistingAnimation) { + var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation); + if (skipAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + close(); + return runner; + } else { + mergeAnimationOptions(element, existingAnimation.options, options); + return existingAnimation.runner; + } + } + + var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation); + if (cancelAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + // this will end the animation right away and it is safe + // to do so since the animation is already running and the + // runner callback code will run in async + existingAnimation.runner.end(); + } else if (existingAnimation.structural) { + // this means that the animation is queued into a digest, but + // hasn't started yet. Therefore it is safe to run the close + // method which will call the runner methods in async. + existingAnimation.close(); + } else { + // this will merge the existing animation options into this new follow-up animation + mergeAnimationOptions(element, newAnimation.options, existingAnimation.options); } - if (!data.running || data.running === 0) { - element.removeData(NG_ANIMATE_CSS_DATA_KEY); + } else { + // a joined animation means that this animation will take over the existing one + // so an example would involve a leave animation taking over an enter. Then when + // the postDigest kicks in the enter will be ignored. + var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation); + if (joinAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + normalizeAnimationOptions(element, options); + } else { + event = newAnimation.event = existingAnimation.event; + options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options); + return runner; + } } } + } else { + // normalization in this case means that it removes redundant CSS classes that + // already exist (addClass) or do not exist (removeClass) on the element + normalizeAnimationOptions(element, options); } - return { - animate: function(element, className, from, to, animationCompleted, options) { - options = options || {}; - options.from = from; - options.to = to; - return animate('animate', element, className, animationCompleted, options); - }, - - enter: function(element, animationCompleted, options) { - options = options || {}; - return animate('enter', element, 'ng-enter', animationCompleted, options); - }, - - leave: function(element, animationCompleted, options) { - options = options || {}; - return animate('leave', element, 'ng-leave', animationCompleted, options); - }, - - move: function(element, animationCompleted, options) { - options = options || {}; - return animate('move', element, 'ng-move', animationCompleted, options); - }, - - beforeSetClass: function(element, add, remove, animationCompleted, options) { - options = options || {}; - var className = suffixClasses(remove, '-remove') + ' ' + - suffixClasses(add, '-add'); - var cancellationMethod = animateBefore('setClass', element, className, options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; + // when the options are merged and cleaned up we may end up not having to do + // an animation at all, therefore we should check this before issuing a post + // digest callback. Structural animations will always run no matter what. + var isValidAnimation = newAnimation.structural; + if (!isValidAnimation) { + // animate (from/to) can be quickly checked first, otherwise we check if any classes are present + isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0) + || hasAnimationClasses(newAnimation.options); + } + + if (!isValidAnimation) { + close(); + clearElementAnimationState(element); + return runner; + } + + if (isStructural) { + closeParentClassBasedAnimations(parent); + } + + // the counter keeps track of cancelled animations + var counter = (existingAnimation.counter || 0) + 1; + newAnimation.counter = counter; + + markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation); + + $rootScope.$$postDigest(function() { + var animationDetails = activeAnimationsLookup.get(node); + var animationCancelled = !animationDetails; + animationDetails = animationDetails || {}; + + // if addClass/removeClass is called before something like enter then the + // registered parent element may not be present. The code below will ensure + // that a final value for parent element is obtained + var parentElement = element.parent() || []; + + // animate/structural/class-based animations all have requirements. Otherwise there + // is no point in performing an animation. The parent node must also be set. + var isValidAnimation = parentElement.length > 0 + && (animationDetails.event === 'animate' + || animationDetails.structural + || hasAnimationClasses(animationDetails.options)); + + // this means that the previous animation was cancelled + // even if the follow-up animation is the same event + if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) { + // if another animation did not take over then we need + // to make sure that the domOperation and options are + // handled accordingly + if (animationCancelled) { + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); } - clearCacheAfterReflow(); - animationCompleted(); - }, - - beforeAddClass: function(element, className, animationCompleted, options) { - options = options || {}; - var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; + + // if the event changed from something like enter to leave then we do + // it, otherwise if it's the same then the end result will be the same too + if (animationCancelled || (isStructural && animationDetails.event !== event)) { + options.domOperation(); + runner.end(); } - clearCacheAfterReflow(); - animationCompleted(); - }, - - beforeRemoveClass: function(element, className, animationCompleted, options) { - options = options || {}; - var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; + + // in the event that the element animation was not cancelled or a follow-up animation + // isn't allowed to animate from here then we need to clear the state of the element + // so that any future animations won't read the expired animation data. + if (!isValidAnimation) { + clearElementAnimationState(element); } - clearCacheAfterReflow(); - animationCompleted(); - }, - - setClass: function(element, add, remove, animationCompleted, options) { - options = options || {}; - remove = suffixClasses(remove, '-remove'); - add = suffixClasses(add, '-add'); - var className = remove + ' ' + add; - return animateAfter('setClass', element, className, animationCompleted, options.to); - }, - - addClass: function(element, className, animationCompleted, options) { - options = options || {}; - return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to); - }, - - removeClass: function(element, className, animationCompleted, options) { - options = options || {}; - return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to); + + return; } - }; - function suffixClasses(classes, suffix) { - var className = ''; - classes = isArray(classes) ? classes : classes.split(/\s+/); - forEach(classes, function(klass, i) { - if (klass && klass.length > 0) { - className += (i > 0 ? ' ' : '') + klass + suffix; + // this combined multiple class to addClass / removeClass into a setClass event + // so long as a structural event did not take over the animation + event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true) + ? 'setClass' + : animationDetails.event; + + if (animationDetails.structural) { + closeParentClassBasedAnimations(parentElement); + } + + markElementAnimationState(element, RUNNING_STATE); + var realRunner = $$animation(element, event, animationDetails.options); + realRunner.done(function(status) { + close(!status); + var animationDetails = activeAnimationsLookup.get(node); + if (animationDetails && animationDetails.counter === counter) { + clearElementAnimationState(getDomNode(element)); + } + notifyProgress(runner, event, 'close', {}); + }); + + // this will update the runner's flow-control events based on + // the `realRunner` object. + runner.setHost(realRunner); + notifyProgress(runner, event, 'start', {}); + }); + + return runner; + + function notifyProgress(runner, event, phase, data) { + triggerCallback(event, element, phase, data); + runner.progress(event, phase, data); + } + + function close(reject) { // jshint ignore:line + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + runner.complete(!reject); + } + } + + function closeChildAnimations(element) { + var node = getDomNode(element); + var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']'); + forEach(children, function(child) { + var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME)); + var animationDetails = activeAnimationsLookup.get(child); + switch (state) { + case RUNNING_STATE: + animationDetails.runner.end(); + /* falls through */ + case PRE_DIGEST_STATE: + if (animationDetails) { + activeAnimationsLookup.remove(child); + } + break; + } + }); + } + + function clearElementAnimationState(element) { + var node = getDomNode(element); + node.removeAttribute(NG_ANIMATE_ATTR_NAME); + activeAnimationsLookup.remove(node); + } + + function isMatchingElement(nodeOrElmA, nodeOrElmB) { + return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB); + } + + function closeParentClassBasedAnimations(startingElement) { + var parentNode = getDomNode(startingElement); + do { + if (!parentNode || parentNode.nodeType !== ELEMENT_NODE) break; + + var animationDetails = activeAnimationsLookup.get(parentNode); + if (animationDetails) { + examineParentAnimation(parentNode, animationDetails); + } + + parentNode = parentNode.parentNode; + } while (true); + + // since animations are detected from CSS classes, we need to flush all parent + // class-based animations so that the parent classes are all present for child + // animations to properly function (otherwise any CSS selectors may not work) + function examineParentAnimation(node, animationDetails) { + // enter/leave/move always have priority + if (animationDetails.structural || !hasAnimationClasses(animationDetails.options)) return; + + if (animationDetails.state === RUNNING_STATE) { + animationDetails.runner.end(); + } + clearElementAnimationState(node); + } + } + + function areAnimationsAllowed(element, parentElement, event) { + var bodyElementDetected = false; + var rootElementDetected = false; + var parentAnimationDetected = false; + var animateChildren; + + var parentHost = element.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; + } + + while (parentElement && parentElement.length) { + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + } + + var parentNode = parentElement[0]; + if (parentNode.nodeType !== ELEMENT_NODE) { + // no point in inspecting the #document element + break; + } + + var details = activeAnimationsLookup.get(parentNode) || {}; + // either an enter, leave or move animation will commence + // therefore we can't allow any animations to take place + // but if a parent animation is class-based then that's ok + if (!parentAnimationDetected) { + parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode); + } + + if (isUndefined(animateChildren) || animateChildren === true) { + var value = parentElement.data(NG_ANIMATE_CHILDREN_DATA); + if (isDefined(value)) { + animateChildren = value; + } + } + + // there is no need to continue traversing at this point + if (parentAnimationDetected && animateChildren === false) break; + + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + if (!rootElementDetected) { + parentHost = parentElement.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; + } } + } + + if (!bodyElementDetected) { + // we also need to ensure that the element is or will be apart of the body element + // otherwise it is pointless to even issue an animation to be rendered + bodyElementDetected = isMatchingElement(parentElement, bodyElement); + } + + parentElement = parentElement.parent(); + } + + var allowAnimation = !parentAnimationDetected || animateChildren; + return allowAnimation && rootElementDetected && bodyElementDetected; + } + + function markElementAnimationState(element, state, details) { + details = details || {}; + details.state = state; + + var node = getDomNode(element); + node.setAttribute(NG_ANIMATE_ATTR_NAME, state); + + var oldValue = activeAnimationsLookup.get(node); + var newValue = oldValue + ? extend(oldValue, details) + : details; + activeAnimationsLookup.put(node, newValue); + } + }]; +}]; + +var $$rAFMutexFactory = ['$$rAF', function($$rAF) { + return function() { + var passed = false; + $$rAF(function() { + passed = true; + }); + return function(fn) { + passed ? fn() : $$rAF(fn); + }; + }; +}]; + +var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) { + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + AnimateRunner.chain = function(chain, callback) { + var index = 0; + + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + + chain[index](function(response) { + if (response === false) { + callback(false); + return; + } + index++; + next(); + }); + } + }; + + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + + function AnimateRunner(host) { + this.setHost(host); + + this._doneCallbacks = []; + this._runInAnimationFrame = $$rAFMutex(); + this._state = 0; + } + + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._runInAnimationFrame(function() { + self._resolve(response); + }); + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); }); - return className; + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + + return AnimateRunner; +}]; + +var $$AnimationProvider = ['$animateProvider', function($animateProvider) { + var NG_ANIMATE_REF_ATTR = 'ng-animate-ref'; + + var drivers = this.drivers = []; + + var RUNNER_STORAGE_KEY = '$$animationRunner'; + + function setRunner(element, runner) { + element.data(RUNNER_STORAGE_KEY, runner); + } + + function removeRunner(element) { + element.removeData(RUNNER_STORAGE_KEY); + } + + function getRunner(element) { + return element.data(RUNNER_STORAGE_KEY); + } + + this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$rAFScheduler', + function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$rAFScheduler) { + + var animationQueue = []; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var totalPendingClassBasedAnimations = 0; + var totalActiveClassBasedAnimations = 0; + var classBasedAnimationsQueue = []; + + // TODO(matsko): document the signature in a better way + return function(element, event, options) { + options = prepareAnimationOptions(options); + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // there is no animation at the current moment, however + // these runner methods will get later updated with the + // methods leading into the driver's end/cancel methods + // for now they just stop the animation from starting + var runner = new $$AnimateRunner({ + end: function() { close(); }, + cancel: function() { close(true); } + }); + + if (!drivers.length) { + close(); + return runner; + } + + setRunner(element, runner); + + var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass)); + var tempClasses = options.tempClasses; + if (tempClasses) { + classes += ' ' + tempClasses; + options.tempClasses = null; + } + + var classBasedIndex; + if (!isStructural) { + classBasedIndex = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations += 1; } - }]); - }]); + + animationQueue.push({ + // this data is used by the postDigest code and passed into + // the driver step function + element: element, + classes: classes, + event: event, + classBasedIndex: classBasedIndex, + structural: isStructural, + options: options, + beforeStart: beforeStart, + close: close + }); + + element.on('$destroy', handleDestroyedElement); + + // we only want there to be one function called within the post digest + // block. This way we can group animations for all the animations that + // were apart of the same postDigest flush call. + if (animationQueue.length > 1) return runner; + + $rootScope.$$postDigest(function() { + totalActiveClassBasedAnimations = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations = 0; + classBasedAnimationsQueue.length = 0; + + var animations = []; + forEach(animationQueue, function(entry) { + // the element was destroyed early on which removed the runner + // form its storage. This means we can't animate this element + // at all and it already has been closed due to destruction. + if (getRunner(entry.element)) { + animations.push(entry); + } + }); + + // now any future animations will be in another postDigest + animationQueue.length = 0; + + forEach(groupAnimations(animations), function(animationEntry) { + if (animationEntry.structural) { + triggerAnimationStart(); + } else { + classBasedAnimationsQueue.push({ + node: getDomNode(animationEntry.element), + fn: triggerAnimationStart + }); + + if (animationEntry.classBasedIndex === totalActiveClassBasedAnimations - 1) { + // we need to sort each of the animations in order of parent to child + // relationships. This ensures that the child classes are applied at the + // right time. + classBasedAnimationsQueue = classBasedAnimationsQueue.sort(function(a,b) { + return b.node.contains(a.node); + }).map(function(entry) { + return entry.fn; + }); + + $$rAFScheduler(classBasedAnimationsQueue); + } + } + + function triggerAnimationStart() { + // it's important that we apply the `ng-animate` CSS class and the + // temporary classes before we do any driver invoking since these + // CSS classes may be required for proper CSS detection. + animationEntry.beforeStart(); + + var startAnimationFn, closeFn = animationEntry.close; + + // in the event that the element was removed before the digest runs or + // during the RAF sequencing then we should not trigger the animation. + var targetElement = animationEntry.anchors + ? (animationEntry.from.element || animationEntry.to.element) + : animationEntry.element; + + if (getRunner(targetElement) && getDomNode(targetElement).parentNode) { + var operation = invokeFirstDriver(animationEntry); + if (operation) { + startAnimationFn = operation.start; + } + } + + if (!startAnimationFn) { + closeFn(); + } else { + var animationRunner = startAnimationFn(); + animationRunner.done(function(status) { + closeFn(!status); + }); + updateAnimationRunners(animationEntry, animationRunner); + } + } + }); + }); + + return runner; + + // TODO(matsko): change to reference nodes + function getAnchorNodes(node) { + var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']'; + var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) + ? [node] + : node.querySelectorAll(SELECTOR); + var anchors = []; + forEach(items, function(node) { + var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); + if (attr && attr.length) { + anchors.push(node); + } + }); + return anchors; + } + + function groupAnimations(animations) { + var preparedAnimations = []; + var refLookup = {}; + forEach(animations, function(animation, index) { + var element = animation.element; + var node = getDomNode(element); + var event = animation.event; + var enterOrMove = ['enter', 'move'].indexOf(event) >= 0; + var anchorNodes = animation.structural ? getAnchorNodes(node) : []; + + if (anchorNodes.length) { + var direction = enterOrMove ? 'to' : 'from'; + + forEach(anchorNodes, function(anchor) { + var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); + refLookup[key] = refLookup[key] || {}; + refLookup[key][direction] = { + animationID: index, + element: jqLite(anchor) + }; + }); + } else { + preparedAnimations.push(animation); + } + }); + + var usedIndicesLookup = {}; + var anchorGroups = {}; + forEach(refLookup, function(operations, key) { + var from = operations.from; + var to = operations.to; + + if (!from || !to) { + // only one of these is set therefore we can't have an + // anchor animation since all three pieces are required + var index = from ? from.animationID : to.animationID; + var indexKey = index.toString(); + if (!usedIndicesLookup[indexKey]) { + usedIndicesLookup[indexKey] = true; + preparedAnimations.push(animations[index]); + } + return; + } + + var fromAnimation = animations[from.animationID]; + var toAnimation = animations[to.animationID]; + var lookupKey = from.animationID.toString(); + if (!anchorGroups[lookupKey]) { + var group = anchorGroups[lookupKey] = { + structural: true, + beforeStart: function() { + fromAnimation.beforeStart(); + toAnimation.beforeStart(); + }, + close: function() { + fromAnimation.close(); + toAnimation.close(); + }, + classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), + from: fromAnimation, + to: toAnimation, + anchors: [] // TODO(matsko): change to reference nodes + }; + + // the anchor animations require that the from and to elements both have at least + // one shared CSS class which effictively marries the two elements together to use + // the same animation driver and to properly sequence the anchor animation. + if (group.classes.length) { + preparedAnimations.push(group); + } else { + preparedAnimations.push(fromAnimation); + preparedAnimations.push(toAnimation); + } + } + + anchorGroups[lookupKey].anchors.push({ + 'out': from.element, 'in': to.element + }); + }); + + return preparedAnimations; + } + + function cssClassesIntersection(a,b) { + a = a.split(' '); + b = b.split(' '); + var matches = []; + + for (var i = 0; i < a.length; i++) { + var aa = a[i]; + if (aa.substring(0,3) === 'ng-') continue; + + for (var j = 0; j < b.length; j++) { + if (aa === b[j]) { + matches.push(aa); + break; + } + } + } + + return matches.join(' '); + } + + function invokeFirstDriver(animationDetails) { + // we loop in reverse order since the more general drivers (like CSS and JS) + // may attempt more elements, but custom drivers are more particular + for (var i = drivers.length - 1; i >= 0; i--) { + var driverName = drivers[i]; + if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check + + var factory = $injector.get(driverName); + var driver = factory(animationDetails); + if (driver) { + return driver; + } + } + } + + function beforeStart() { + element.addClass(NG_ANIMATE_CLASSNAME); + if (tempClasses) { + $$jqLite.addClass(element, tempClasses); + } + } + + function updateAnimationRunners(animation, newRunner) { + if (animation.from && animation.to) { + update(animation.from.element); + update(animation.to.element); + } else { + update(animation.element); + } + + function update(element) { + getRunner(element).setHost(newRunner); + } + } + + function handleDestroyedElement() { + var runner = getRunner(element); + if (runner && (event !== 'leave' || !options.$$domOperationFired)) { + runner.end(); + } + } + + function close(rejected) { // jshint ignore:line + element.off('$destroy', handleDestroyedElement); + removeRunner(element); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + + if (tempClasses) { + $$jqLite.removeClass(element, tempClasses); + } + + element.removeClass(NG_ANIMATE_CLASSNAME); + runner.complete(!rejected); + } + }; + }]; +}]; + +/* global angularAnimateModule: true, + + $$rAFMutexFactory, + $$rAFSchedulerFactory, + $$AnimateChildrenDirective, + $$AnimateRunnerFactory, + $$AnimateQueueProvider, + $$AnimationProvider, + $AnimateCssProvider, + $$AnimateCssDriverProvider, + $$AnimateJsProvider, + $$AnimateJsDriverProvider, +*/ + +/** + * @ngdoc module + * @name ngAnimate + * @description + * + * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via + * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app. + * + * <div doc-module-components="ngAnimate"></div> + * + * # Usage + * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based + * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For + * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within + * the HTML element that the animation will be triggered on. + * + * ## Directive Support + * The following directives are "animation aware": + * + * | Directive | Supported Animations | + * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| + * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | + * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | + * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | + * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | + * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | + * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) | + * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) | + * | {@link ng.directive:form#animation-hooks form} & {@link ng.directive:ngModel#animation-hooks ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) | + * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | + * | {@link module:ngMessages#animations ngMessage} | enter and leave | + * + * (More information can be found by visiting each the documentation associated with each directive.) + * + * ## CSS-based Animations + * + * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML + * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation. + * + * The example below shows how an `enter` animation can be made possible on a element using `ng-if`: + * + * ```html + * <div ng-if="bool" class="fade"> + * Fade me in out + * </div> + * <button ng-click="bool=true">Fade In!</button> + * <button ng-click="bool=false">Fade Out!</button> + * ``` + * + * Notice the CSS class **fade**? We can now create the CSS transition code that references this class: + * + * ```css + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter { + * transition:0.5s linear all; + * opacity:0; + * } + * + * /* The finishing CSS styles for the enter animation */ + * .fade.ng-enter.ng-enter-active { + * opacity:1; + * } + * ``` + * + * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two + * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition + * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards. + * + * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions: + * + * ```css + * /* now the element will fade out before it is removed from the DOM */ + * .fade.ng-leave { + * transition:0.5s linear all; + * opacity:1; + * } + * .fade.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class: + * + * ```css + * /* there is no need to define anything inside of the destination + * CSS class since the keyframe will take charge of the animation */ + * .fade.ng-leave { + * animation: my_fade_animation 0.5s linear; + * -webkit-animation: my_fade_animation 0.5s linear; + * } + * + * @keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * + * @-webkit-keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * ``` + * + * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element. + * + * ### CSS Class-based Animations + * + * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different + * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added + * and removed. + * + * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class: + * + * ```html + * <div ng-show="bool" class="fade"> + * Show and hide me + * </div> + * <button ng-click="bool=true">Toggle</button> + * + * <style> + * .fade.ng-hide { + * transition:0.5s linear all; + * opacity:0; + * } + * </style> + * ``` + * + * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since + * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest. + * + * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation + * with CSS styles. + * + * ```html + * <div ng-class="{on:onOff}" class="highlight"> + * Highlight this box + * </div> + * <button ng-click="onOff=!onOff">Toggle</button> + * + * <style> + * .highlight { + * transition:0.5s linear all; + * } + * .highlight.on-add { + * background:white; + * } + * .highlight.on { + * background:yellow; + * } + * .highlight.on-remove { + * background:black; + * } + * </style> + * ``` + * + * We can also make use of CSS keyframes by placing them within the CSS classes. + * + * + * ### CSS Staggering Animations + * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a + * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be + * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for + * the animation. The style property expected within the stagger class can either be a **transition-delay** or an + * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). + * + * ```css + * .my-animation.ng-enter { + * /* standard transition code */ + * transition: 1s linear all; + * opacity:0; + * } + * .my-animation.ng-enter-stagger { + * /* this will have a 100ms delay between each successive leave animation */ + * transition-delay: 0.1s; + * + * /* in case the stagger doesn't work then the duration value + * must be set to 0 to avoid an accidental CSS inheritance */ + * transition-duration: 0s; + * } + * .my-animation.ng-enter.ng-enter-active { + * /* standard transition styles */ + * opacity:1; + * } + * ``` + * + * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations + * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this + * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation + * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired. + * + * The following code will issue the **ng-leave-stagger** event on the element provided: + * + * ```js + * var kids = parent.children(); + * + * $animate.leave(kids[0]); //stagger index=0 + * $animate.leave(kids[1]); //stagger index=1 + * $animate.leave(kids[2]); //stagger index=2 + * $animate.leave(kids[3]); //stagger index=3 + * $animate.leave(kids[4]); //stagger index=4 + * + * window.requestAnimationFrame(function() { + * //stagger has reset itself + * $animate.leave(kids[5]); //stagger index=0 + * $animate.leave(kids[6]); //stagger index=1 + * + * $scope.$digest(); + * }); + * ``` + * + * Stagger animations are currently only supported within CSS-defined animations. + * + * ### The `ng-animate` CSS class + * + * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation. + * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations). + * + * Therefore, animations can be applied to an element using this temporary class directly via CSS. + * + * ```css + * .zipper.ng-animate { + * transition:0.5s linear all; + * } + * .zipper.ng-enter { + * opacity:0; + * } + * .zipper.ng-enter.ng-enter-active { + * opacity:1; + * } + * .zipper.ng-leave { + * opacity:1; + * } + * .zipper.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove + * the CSS class once an animation has completed.) + * + * + * ## JavaScript-based Animations + * + * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared + * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the + * `module.animation()` module function we can register the ainmation. + * + * Let's see an example of a enter/leave animation using `ngRepeat`: + * + * ```html + * <div ng-repeat="item in items" class="slide"> + * {{ item }} + * </div> + * ``` + * + * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`: + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * // make note that other events (like addClass/removeClass) + * // have different function input parameters + * enter: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * + * // remember to call doneFn so that angular + * // knows that the animation has concluded + * }, + * + * move: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * }, + * + * leave: function(element, doneFn) { + * jQuery(element).fadeOut(1000, doneFn); + * } + * } + * }] + * ``` + * + * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as + * greensock.js and velocity.js. + * + * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define + * our animations inside of the same registered animation, however, the function input arguments are a bit different: + * + * ```html + * <div ng-class="color" class="colorful"> + * this box is moody + * </div> + * <button ng-click="color='red'">Change to red</button> + * <button ng-click="color='blue'">Change to blue</button> + * <button ng-click="color='green'">Change to green</button> + * ``` + * + * ```js + * myModule.animation('.colorful', [function() { + * return { + * addClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * removeClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * setClass: function(element, addedClass, removedClass, doneFn) { + * // do some cool animation and call the doneFn + * } + * } + * }] + * ``` + * + * ## CSS + JS Animations Together + * + * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular, + * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking + * charge of the animation**: + * + * ```html + * <div ng-if="bool" class="slide"> + * Slide in and out + * </div> + * ``` + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * enter: function(element, doneFn) { + * jQuery(element).slideIn(1000, doneFn); + * } + * } + * }] + * ``` + * + * ```css + * .slide.ng-enter { + * transition:0.5s linear all; + * transform:translateY(-100px); + * } + * .slide.ng-enter.ng-enter-active { + * transform:translateY(0); + * } + * ``` + * + * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the + * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from + * our own JS-based animation code: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { +* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`. + * var runner = $animateCss(element, { + * event: 'enter', + * structural: true + * }).start(); +* runner.done(doneFn); + * } + * } + * }] + * ``` + * + * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework. + * + * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or + * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that + * data into `$animateCss` directly: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var runner = $animateCss(element, { + * event: 'enter', + * addClass: 'maroon-setting', + * from: { height:0 }, + * to: { height: 200 } + * }).start(); + * + * runner.done(doneFn); + * } + * } + * }] + * ``` + * + * Now we can fill in the rest via our transition CSS code: + * + * ```css + * /* the transition tells ngAnimate to make the animation happen */ + * .slide.ng-enter { transition:0.5s linear all; } + * + * /* this extra CSS class will be absorbed into the transition + * since the $animateCss code is adding the class */ + * .maroon-setting { background:red; } + * ``` + * + * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over. + * + * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}. + * + * ## Animation Anchoring (via `ng-animate-ref`) + * + * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between + * structural areas of an application (like views) by pairing up elements using an attribute + * called `ng-animate-ref`. + * + * Let's say for example we have two views that are managed by `ng-view` and we want to show + * that there is a relationship between two components situated in within these views. By using the + * `ng-animate-ref` attribute we can identify that the two components are paired together and we + * can then attach an animation, which is triggered when the view changes. + * + * Say for example we have the following template code: + * + * ```html + * <!-- index.html --> + * <div ng-view class="view-animation"> + * </div> + * + * <!-- home.html --> + * <a href="#/banner-page"> + * <img src="./banner.jpg" class="banner" ng-animate-ref="banner"> + * </a> + * + * <!-- banner-page.html --> + * <img src="./banner.jpg" class="banner" ng-animate-ref="banner"> + * ``` + * + * Now, when the view changes (once the link is clicked), ngAnimate will examine the + * HTML contents to see if there is a match reference between any components in the view + * that is leaving and the view that is entering. It will scan both the view which is being + * removed (leave) and inserted (enter) to see if there are any paired DOM elements that + * contain a matching ref value. + * + * The two images match since they share the same ref value. ngAnimate will now create a + * transport element (which is a clone of the first image element) and it will then attempt + * to animate to the position of the second image element in the next view. For the animation to + * work a special CSS class called `ng-anchor` will be added to the transported element. + * + * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then + * ngAnimate will handle the entire transition for us as well as the addition and removal of + * any changes of CSS classes between the elements: + * + * ```css + * .banner.ng-anchor { + * /* this animation will last for 1 second since there are + * two phases to the animation (an `in` and an `out` phase) */ + * transition:0.5s linear all; + * } + * ``` + * + * We also **must** include animations for the views that are being entered and removed + * (otherwise anchoring wouldn't be possible since the new view would be inserted right away). + * + * ```css + * .view-animation.ng-enter, .view-animation.ng-leave { + * transition:0.5s linear all; + * position:fixed; + * left:0; + * top:0; + * width:100%; + * } + * .view-animation.ng-enter { + * transform:translateX(100%); + * } + * .view-animation.ng-leave, + * .view-animation.ng-enter.ng-enter-active { + * transform:translateX(0%); + * } + * .view-animation.ng-leave.ng-leave-active { + * transform:translateX(-100%); + * } + * ``` + * + * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur: + * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away + * from its origin. Once that animation is over then the `in` stage occurs which animates the + * element to its destination. The reason why there are two animations is to give enough time + * for the enter animation on the new element to be ready. + * + * The example above sets up a transition for both the in and out phases, but we can also target the out or + * in phases directly via `ng-anchor-out` and `ng-anchor-in`. + * + * ```css + * .banner.ng-anchor-out { + * transition: 0.5s linear all; + * + * /* the scale will be applied during the out animation, + * but will be animated away when the in animation runs */ + * transform: scale(1.2); + * } + * + * .banner.ng-anchor-in { + * transition: 1s linear all; + * } + * ``` + * + * + * + * + * ### Anchoring Demo + * + <example module="anchoringExample" + name="anchoringExample" + id="anchoringExample" + deps="angular-animate.js;angular-route.js" + animations="true"> + <file name="index.html"> + <a href="#/">Home</a> + <hr /> + <div class="view-container"> + <div ng-view class="view"></div> + </div> + </file> + <file name="script.js"> + angular.module('anchoringExample', ['ngAnimate', 'ngRoute']) + .config(['$routeProvider', function($routeProvider) { + $routeProvider.when('/', { + templateUrl: 'home.html', + controller: 'HomeController as home' + }); + $routeProvider.when('/profile/:id', { + templateUrl: 'profile.html', + controller: 'ProfileController as profile' + }); + }]) + .run(['$rootScope', function($rootScope) { + $rootScope.records = [ + { id:1, title: "Miss Beulah Roob" }, + { id:2, title: "Trent Morissette" }, + { id:3, title: "Miss Ava Pouros" }, + { id:4, title: "Rod Pouros" }, + { id:5, title: "Abdul Rice" }, + { id:6, title: "Laurie Rutherford Sr." }, + { id:7, title: "Nakia McLaughlin" }, + { id:8, title: "Jordon Blanda DVM" }, + { id:9, title: "Rhoda Hand" }, + { id:10, title: "Alexandrea Sauer" } + ]; + }]) + .controller('HomeController', [function() { + //empty + }]) + .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) { + var index = parseInt($routeParams.id, 10); + var record = $rootScope.records[index - 1]; + + this.title = record.title; + this.id = record.id; + }]); + </file> + <file name="home.html"> + <h2>Welcome to the home page</h1> + <p>Please click on an element</p> + <a class="record" + ng-href="#/profile/{{ record.id }}" + ng-animate-ref="{{ record.id }}" + ng-repeat="record in records"> + {{ record.title }} + </a> + </file> + <file name="profile.html"> + <div class="profile record" ng-animate-ref="{{ profile.id }}"> + {{ profile.title }} + </div> + </file> + <file name="animations.css"> + .record { + display:block; + font-size:20px; + } + .profile { + background:black; + color:white; + font-size:100px; + } + .view-container { + position:relative; + } + .view-container > .view.ng-animate { + position:absolute; + top:0; + left:0; + width:100%; + min-height:500px; + } + .view.ng-enter, .view.ng-leave, + .record.ng-anchor { + transition:0.5s linear all; + } + .view.ng-enter { + transform:translateX(100%); + } + .view.ng-enter.ng-enter-active, .view.ng-leave { + transform:translateX(0%); + } + .view.ng-leave.ng-leave-active { + transform:translateX(-100%); + } + .record.ng-anchor-out { + background:red; + } + </file> + </example> + * + * ### How is the element transported? + * + * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting + * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element + * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The + * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match + * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied + * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class + * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element + * will become visible since the shim class will be removed. + * + * ### How is the morphing handled? + * + * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out + * what CSS classes differ between the starting element and the destination element. These different CSS classes + * will be added/removed on the anchor element and a transition will be applied (the transition that is provided + * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will + * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that + * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since + * the cloned element is placed inside of root element which is likely close to the body element). + * + * Note that if the root element is on the `<html>` element then the cloned node will be placed inside of body. + * + * + * ## Using $animate in your directive code + * + * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application? + * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's + * imagine we have a greeting box that shows and hides itself when the data changes + * + * ```html + * <greeting-box active="onOrOff">Hi there</greeting-box> + * ``` + * + * ```js + * ngModule.directive('greetingBox', ['$animate', function($animate) { + * return function(scope, element, attrs) { + * attrs.$observe('active', function(value) { + * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on'); + * }); + * }); + * }]); + * ``` + * + * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element + * in our HTML code then we can trigger a CSS or JS animation to happen. + * + * ```css + * /* normally we would create a CSS class to reference on the element */ + * greeting-box.on { transition:0.5s linear all; background:green; color:white; } + * ``` + * + * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's + * possible be sure to visit the {@link ng.$animate $animate service API page}. + * + * + * ### Preventing Collisions With Third Party Libraries + * + * Some third-party frameworks place animation duration defaults across many element or className + * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which + * is expecting actual animations on these elements and has to wait for their completion. + * + * You can prevent this unwanted behavior by using a prefix on all your animation classes: + * + * ```css + * /* prefixed with animate- */ + * .animate-fade-add.animate-fade-add-active { + * transition:1s linear all; + * opacity:0; + * } + * ``` + * + * You then configure `$animate` to enforce this prefix: + * + * ```js + * $animateProvider.classNameFilter(/animate-/); + * ``` + * + * This also may provide your application with a speed boost since only specific elements containing CSS class prefix + * will be evaluated for animation when any DOM changes occur in the application. + * + * ## Callbacks and Promises + * + * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger + * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has + * ended by chaining onto the returned promise that animation method returns. + * + * ```js + * // somewhere within the depths of the directive + * $animate.enter(element, parent).then(function() { + * //the animation has completed + * }); + * ``` + * + * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case + * anymore.) + * + * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering + * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view + * routing controller to hook into that: + * + * ```js + * ngModule.controller('HomePageController', ['$animate', function($animate) { + * $animate.on('enter', ngViewElement, function(element) { + * // the animation for this route has completed + * }]); + * }]) + * ``` + * + * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.) + */ + +/** + * @ngdoc service + * @name $animate + * @kind object + * + * @description + * The ngAnimate `$animate` service documentation is the same for the core `$animate` service. + * + * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}. + */ +angular.module('ngAnimate', []) + .directive('ngAnimateChildren', $$AnimateChildrenDirective) + + .factory('$$rAFMutex', $$rAFMutexFactory) + .factory('$$rAFScheduler', $$rAFSchedulerFactory) + + .factory('$$AnimateRunner', $$AnimateRunnerFactory) + + .provider('$$animateQueue', $$AnimateQueueProvider) + .provider('$$animation', $$AnimationProvider) + + .provider('$animateCss', $AnimateCssProvider) + .provider('$$animateCssDriver', $$AnimateCssDriverProvider) + + .provider('$$animateJs', $$AnimateJsProvider) + .provider('$$animateJsDriver', $$AnimateJsDriverProvider); })(window, window.angular); diff --git a/www/lib/ionic/js/angular/angular-animate.min.js b/www/lib/ionic/js/angular/angular-animate.min.js index 6ed98ee6738f3beb8647724bd3c08cfdbb0937ae..a99eac13cc8ac9296c2b8e24a4f382e5ece80cf1 100644 --- a/www/lib/ionic/js/angular/angular-animate.min.js +++ b/www/lib/ionic/js/angular/angular-animate.min.js @@ -1,33 +1,52 @@ /* - AngularJS v1.3.13 - (c) 2010-2014 Google, Inc. http://angularjs.org + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org License: MIT */ -(function(N,f,W){'use strict';f.module("ngAnimate",["ng"]).directive("ngAnimateChildren",function(){return function(X,C,g){g=g.ngAnimateChildren;f.isString(g)&&0===g.length?C.data("$$ngAnimateChildren",!0):X.$watch(g,function(f){C.data("$$ngAnimateChildren",!!f)})}}).factory("$$animateReflow",["$$rAF","$document",function(f,C){return function(g){return f(function(){g()})}}]).config(["$provide","$animateProvider",function(X,C){function g(f){for(var n=0;n<f.length;n++){var g=f[n];if(1==g.nodeType)return g}} -function ba(f,n){return g(f)==g(n)}var t=f.noop,n=f.forEach,da=C.$$selectors,aa=f.isArray,ea=f.isString,ga=f.isObject,r={running:!0},u;X.decorator("$animate",["$delegate","$$q","$injector","$sniffer","$rootElement","$$asyncCallback","$rootScope","$document","$templateRequest","$$jqLite",function(O,N,M,Y,y,H,P,W,Z,Q){function R(a,c){var b=a.data("$$ngAnimateState")||{};c&&(b.running=!0,b.structural=!0,a.data("$$ngAnimateState",b));return b.disabled||b.running&&b.structural}function D(a){var c,b=N.defer(); -b.promise.$$cancelFn=function(){c&&c()};P.$$postDigest(function(){c=a(function(){b.resolve()})});return b.promise}function I(a){if(ga(a))return a.tempClasses&&ea(a.tempClasses)&&(a.tempClasses=a.tempClasses.split(/\s+/)),a}function S(a,c,b){b=b||{};var d={};n(b,function(e,a){n(a.split(" "),function(a){d[a]=e})});var h=Object.create(null);n((a.attr("class")||"").split(/\s+/),function(e){h[e]=!0});var f=[],l=[];n(c&&c.classes||[],function(e,a){var b=h[a],c=d[a]||{};!1===e?(b||"addClass"==c.event)&& -l.push(a):!0===e&&(b&&"removeClass"!=c.event||f.push(a))});return 0<f.length+l.length&&[f.join(" "),l.join(" ")]}function T(a){if(a){var c=[],b={};a=a.substr(1).split(".");(Y.transitions||Y.animations)&&c.push(M.get(da[""]));for(var d=0;d<a.length;d++){var f=a[d],k=da[f];k&&!b[f]&&(c.push(M.get(k)),b[f]=!0)}return c}}function U(a,c,b,d){function h(e,a){var b=e[a],c=e["before"+a.charAt(0).toUpperCase()+a.substr(1)];if(b||c)return"leave"==a&&(c=b,b=null),u.push({event:a,fn:b}),J.push({event:a,fn:c}), -!0}function k(c,l,w){var E=[];n(c,function(a){a.fn&&E.push(a)});var m=0;n(E,function(c,f){var p=function(){a:{if(l){(l[f]||t)();if(++m<E.length)break a;l=null}w()}};switch(c.event){case "setClass":l.push(c.fn(a,e,A,p,d));break;case "animate":l.push(c.fn(a,b,d.from,d.to,p));break;case "addClass":l.push(c.fn(a,e||b,p,d));break;case "removeClass":l.push(c.fn(a,A||b,p,d));break;default:l.push(c.fn(a,p,d))}});l&&0===l.length&&w()}var l=a[0];if(l){d&&(d.to=d.to||{},d.from=d.from||{});var e,A;aa(b)&&(e= -b[0],A=b[1],e?A?b=e+" "+A:(b=e,c="addClass"):(b=A,c="removeClass"));var w="setClass"==c,E=w||"addClass"==c||"removeClass"==c||"animate"==c,p=a.attr("class")+" "+b;if(x(p)){var ca=t,m=[],J=[],g=t,s=[],u=[],p=(" "+p).replace(/\s+/g,".");n(T(p),function(a){!h(a,c)&&w&&(h(a,"addClass"),h(a,"removeClass"))});return{node:l,event:c,className:b,isClassBased:E,isSetClassOperation:w,applyStyles:function(){d&&a.css(f.extend(d.from||{},d.to||{}))},before:function(a){ca=a;k(J,m,function(){ca=t;a()})},after:function(a){g= -a;k(u,s,function(){g=t;a()})},cancel:function(){m&&(n(m,function(a){(a||t)(!0)}),ca(!0));s&&(n(s,function(a){(a||t)(!0)}),g(!0))}}}}}function G(a,c,b,d,h,k,l,e){function A(e){var l="$animate:"+e;J&&J[l]&&0<J[l].length&&H(function(){b.triggerHandler(l,{event:a,className:c})})}function w(){A("before")}function E(){A("after")}function p(){p.hasBeenRun||(p.hasBeenRun=!0,k())}function g(){if(!g.hasBeenRun){m&&m.applyStyles();g.hasBeenRun=!0;l&&l.tempClasses&&n(l.tempClasses,function(a){u.removeClass(b, -a)});var w=b.data("$$ngAnimateState");w&&(m&&m.isClassBased?B(b,c):(H(function(){var e=b.data("$$ngAnimateState")||{};fa==e.index&&B(b,c,a)}),b.data("$$ngAnimateState",w)));A("close");e()}}var m=U(b,a,c,l);if(!m)return p(),w(),E(),g(),t;a=m.event;c=m.className;var J=f.element._data(m.node),J=J&&J.events;d||(d=h?h.parent():b.parent());if(z(b,d))return p(),w(),E(),g(),t;d=b.data("$$ngAnimateState")||{};var L=d.active||{},s=d.totalActive||0,q=d.last;h=!1;if(0<s){s=[];if(m.isClassBased)"setClass"==q.event? -(s.push(q),B(b,c)):L[c]&&(v=L[c],v.event==a?h=!0:(s.push(v),B(b,c)));else if("leave"==a&&L["ng-leave"])h=!0;else{for(var v in L)s.push(L[v]);d={};B(b,!0)}0<s.length&&n(s,function(a){a.cancel()})}!m.isClassBased||m.isSetClassOperation||"animate"==a||h||(h="addClass"==a==b.hasClass(c));if(h)return p(),w(),E(),A("close"),e(),t;L=d.active||{};s=d.totalActive||0;if("leave"==a)b.one("$destroy",function(a){a=f.element(this);var e=a.data("$$ngAnimateState");e&&(e=e.active["ng-leave"])&&(e.cancel(),B(a,"ng-leave"))}); -u.addClass(b,"ng-animate");l&&l.tempClasses&&n(l.tempClasses,function(a){u.addClass(b,a)});var fa=K++;s++;L[c]=m;b.data("$$ngAnimateState",{last:m,active:L,index:fa,totalActive:s});w();m.before(function(e){var l=b.data("$$ngAnimateState");e=e||!l||!l.active[c]||m.isClassBased&&l.active[c].event!=a;p();!0===e?g():(E(),m.after(g))});return m.cancel}function q(a){if(a=g(a))a=f.isFunction(a.getElementsByClassName)?a.getElementsByClassName("ng-animate"):a.querySelectorAll(".ng-animate"),n(a,function(a){a= -f.element(a);(a=a.data("$$ngAnimateState"))&&a.active&&n(a.active,function(a){a.cancel()})})}function B(a,c){if(ba(a,y))r.disabled||(r.running=!1,r.structural=!1);else if(c){var b=a.data("$$ngAnimateState")||{},d=!0===c;!d&&b.active&&b.active[c]&&(b.totalActive--,delete b.active[c]);if(d||!b.totalActive)u.removeClass(a,"ng-animate"),a.removeData("$$ngAnimateState")}}function z(a,c){if(r.disabled)return!0;if(ba(a,y))return r.running;var b,d,g;do{if(0===c.length)break;var k=ba(c,y),l=k?r:c.data("$$ngAnimateState")|| -{};if(l.disabled)return!0;k&&(g=!0);!1!==b&&(k=c.data("$$ngAnimateChildren"),f.isDefined(k)&&(b=k));d=d||l.running||l.last&&!l.last.isClassBased}while(c=c.parent());return!g||!b&&d}u=Q;y.data("$$ngAnimateState",r);var $=P.$watch(function(){return Z.totalPendingRequests},function(a,c){0===a&&($(),P.$$postDigest(function(){P.$$postDigest(function(){r.running=!1})}))}),K=0,V=C.classNameFilter(),x=V?function(a){return V.test(a)}:function(){return!0};return{animate:function(a,c,b,d,h){d=d||"ng-inline-animate"; -h=I(h)||{};h.from=b?c:null;h.to=b?b:c;return D(function(b){return G("animate",d,f.element(g(a)),null,null,t,h,b)})},enter:function(a,c,b,d){d=I(d);a=f.element(a);c=c&&f.element(c);b=b&&f.element(b);R(a,!0);O.enter(a,c,b);return D(function(h){return G("enter","ng-enter",f.element(g(a)),c,b,t,d,h)})},leave:function(a,c){c=I(c);a=f.element(a);q(a);R(a,!0);return D(function(b){return G("leave","ng-leave",f.element(g(a)),null,null,function(){O.leave(a)},c,b)})},move:function(a,c,b,d){d=I(d);a=f.element(a); -c=c&&f.element(c);b=b&&f.element(b);q(a);R(a,!0);O.move(a,c,b);return D(function(h){return G("move","ng-move",f.element(g(a)),c,b,t,d,h)})},addClass:function(a,c,b){return this.setClass(a,c,[],b)},removeClass:function(a,c,b){return this.setClass(a,[],c,b)},setClass:function(a,c,b,d){d=I(d);a=f.element(a);a=f.element(g(a));if(R(a))return O.$$setClassImmediately(a,c,b,d);var h,k=a.data("$$animateClasses"),l=!!k;k||(k={classes:{}});h=k.classes;c=aa(c)?c:c.split(" ");n(c,function(a){a&&a.length&&(h[a]= -!0)});b=aa(b)?b:b.split(" ");n(b,function(a){a&&a.length&&(h[a]=!1)});if(l)return d&&k.options&&(k.options=f.extend(k.options||{},d)),k.promise;a.data("$$animateClasses",k={classes:h,options:d});return k.promise=D(function(e){var l=a.parent(),b=g(a),c=b.parentNode;if(!c||c.$$NG_REMOVED||b.$$NG_REMOVED)e();else{b=a.data("$$animateClasses");a.removeData("$$animateClasses");var c=a.data("$$ngAnimateState")||{},d=S(a,b,c.active);return d?G("setClass",d,a,l,null,function(){d[0]&&O.$$addClassImmediately(a, -d[0]);d[1]&&O.$$removeClassImmediately(a,d[1])},b.options,e):e()}})},cancel:function(a){a.$$cancelFn()},enabled:function(a,c){switch(arguments.length){case 2:if(a)B(c);else{var b=c.data("$$ngAnimateState")||{};b.disabled=!0;c.data("$$ngAnimateState",b)}break;case 1:r.disabled=!a;break;default:a=!r.disabled}return!!a}}}]);C.register("",["$window","$sniffer","$timeout","$$animateReflow",function(r,C,M,Y){function y(){b||(b=Y(function(){c=[];b=null;x={}}))}function H(a,e){b&&b();c.push(e);b=Y(function(){n(c, -function(a){a()});c=[];b=null;x={}})}function P(a,e){var b=g(a);a=f.element(b);k.push(a);b=Date.now()+e;b<=h||(M.cancel(d),h=b,d=M(function(){X(k);k=[]},e,!1))}function X(a){n(a,function(a){(a=a.data("$$ngAnimateCSS3Data"))&&n(a.closeAnimationFns,function(a){a()})})}function Z(a,e){var b=e?x[e]:null;if(!b){var c=0,d=0,f=0,g=0;n(a,function(a){if(1==a.nodeType){a=r.getComputedStyle(a)||{};c=Math.max(Q(a[z+"Duration"]),c);d=Math.max(Q(a[z+"Delay"]),d);g=Math.max(Q(a[K+"Delay"]),g);var e=Q(a[K+"Duration"]); -0<e&&(e*=parseInt(a[K+"IterationCount"],10)||1);f=Math.max(e,f)}});b={total:0,transitionDelay:d,transitionDuration:c,animationDelay:g,animationDuration:f};e&&(x[e]=b)}return b}function Q(a){var e=0;a=ea(a)?a.split(/\s*,\s*/):[];n(a,function(a){e=Math.max(parseFloat(a)||0,e)});return e}function R(b,e,c,d){b=0<=["ng-enter","ng-leave","ng-move"].indexOf(c);var f,p=e.parent(),h=p.data("$$ngAnimateKey");h||(p.data("$$ngAnimateKey",++a),h=a);f=h+"-"+g(e).getAttribute("class");var p=f+" "+c,h=x[p]?++x[p].total: -0,m={};if(0<h){var n=c+"-stagger",m=f+" "+n;(f=!x[m])&&u.addClass(e,n);m=Z(e,m);f&&u.removeClass(e,n)}u.addClass(e,c);var n=e.data("$$ngAnimateCSS3Data")||{},k=Z(e,p);f=k.transitionDuration;k=k.animationDuration;if(b&&0===f&&0===k)return u.removeClass(e,c),!1;c=d||b&&0<f;b=0<k&&0<m.animationDelay&&0===m.animationDuration;e.data("$$ngAnimateCSS3Data",{stagger:m,cacheKey:p,running:n.running||0,itemIndex:h,blockTransition:c,closeAnimationFns:n.closeAnimationFns||[]});p=g(e);c&&(I(p,!0),d&&e.css(d)); -b&&(p.style[K+"PlayState"]="paused");return!0}function D(a,e,b,c,d){function f(){e.off(D,h);u.removeClass(e,k);u.removeClass(e,t);z&&M.cancel(z);G(e,b);var a=g(e),c;for(c in s)a.style.removeProperty(s[c])}function h(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-H,0)>=C&&b>=x&&c()}var m=g(e);a=e.data("$$ngAnimateCSS3Data");if(-1!=m.getAttribute("class").indexOf(b)&&a){var k="",t="";n(b.split(" "),function(a, -b){var e=(0<b?" ":"")+a;k+=e+"-active";t+=e+"-pending"});var s=[],q=a.itemIndex,v=a.stagger,r=0;if(0<q){r=0;0<v.transitionDelay&&0===v.transitionDuration&&(r=v.transitionDelay*q);var y=0;0<v.animationDelay&&0===v.animationDuration&&(y=v.animationDelay*q,s.push(B+"animation-play-state"));r=Math.round(100*Math.max(r,y))/100}r||(u.addClass(e,k),a.blockTransition&&I(m,!1));var F=Z(e,a.cacheKey+" "+k),x=Math.max(F.transitionDuration,F.animationDuration);if(0===x)u.removeClass(e,k),G(e,b),c();else{!r&& -d&&0<Object.keys(d).length&&(F.transitionDuration||(e.css("transition",F.animationDuration+"s linear all"),s.push("transition")),e.css(d));var q=Math.max(F.transitionDelay,F.animationDelay),C=1E3*q;0<s.length&&(v=m.getAttribute("style")||"",";"!==v.charAt(v.length-1)&&(v+=";"),m.setAttribute("style",v+" "));var H=Date.now(),D=V+" "+$,q=1E3*(r+1.5*(q+x)),z;0<r&&(u.addClass(e,t),z=M(function(){z=null;0<F.transitionDuration&&I(m,!1);0<F.animationDuration&&(m.style[K+"PlayState"]="");u.addClass(e,k); -u.removeClass(e,t);d&&(0===F.transitionDuration&&e.css("transition",F.animationDuration+"s linear all"),e.css(d),s.push("transition"))},1E3*r,!1));e.on(D,h);a.closeAnimationFns.push(function(){f();c()});a.running++;P(e,q);return f}}else c()}function I(a,b){a.style[z+"Property"]=b?"none":""}function S(a,b,c,d){if(R(a,b,c,d))return function(a){a&&G(b,c)}}function T(a,b,c,d,f){if(b.data("$$ngAnimateCSS3Data"))return D(a,b,c,d,f);G(b,c);d()}function U(a,b,c,d,f){var g=S(a,b,c,f.from);if(g){var h=g;H(b, -function(){h=T(a,b,c,d,f.to)});return function(a){(h||t)(a)}}y();d()}function G(a,b){u.removeClass(a,b);var c=a.data("$$ngAnimateCSS3Data");c&&(c.running&&c.running--,c.running&&0!==c.running||a.removeData("$$ngAnimateCSS3Data"))}function q(a,b){var c="";a=aa(a)?a:a.split(/\s+/);n(a,function(a,d){a&&0<a.length&&(c+=(0<d?" ":"")+a+b)});return c}var B="",z,$,K,V;N.ontransitionend===W&&N.onwebkittransitionend!==W?(B="-webkit-",z="WebkitTransition",$="webkitTransitionEnd transitionend"):(z="transition", -$="transitionend");N.onanimationend===W&&N.onwebkitanimationend!==W?(B="-webkit-",K="WebkitAnimation",V="webkitAnimationEnd animationend"):(K="animation",V="animationend");var x={},a=0,c=[],b,d=null,h=0,k=[];return{animate:function(a,b,c,d,f,g){g=g||{};g.from=c;g.to=d;return U("animate",a,b,f,g)},enter:function(a,b,c){c=c||{};return U("enter",a,"ng-enter",b,c)},leave:function(a,b,c){c=c||{};return U("leave",a,"ng-leave",b,c)},move:function(a,b,c){c=c||{};return U("move",a,"ng-move",b,c)},beforeSetClass:function(a, -b,c,d,f){f=f||{};b=q(c,"-remove")+" "+q(b,"-add");if(f=S("setClass",a,b,f.from))return H(a,d),f;y();d()},beforeAddClass:function(a,b,c,d){d=d||{};if(b=S("addClass",a,q(b,"-add"),d.from))return H(a,c),b;y();c()},beforeRemoveClass:function(a,b,c,d){d=d||{};if(b=S("removeClass",a,q(b,"-remove"),d.from))return H(a,c),b;y();c()},setClass:function(a,b,c,d,f){f=f||{};c=q(c,"-remove");b=q(b,"-add");return T("setClass",a,c+" "+b,d,f.to)},addClass:function(a,b,c,d){d=d||{};return T("addClass",a,q(b,"-add"), -c,d.to)},removeClass:function(a,b,c,d){d=d||{};return T("removeClass",a,q(b,"-remove"),c,d.to)}}}])}])})(window,window.angular); +(function(F,t,W){'use strict';function ua(a,b,c){if(!a)throw ngMinErr("areq",b||"?",c||"required");return a}function va(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;X(a)&&(a=a.join(" "));X(b)&&(b=b.join(" "));return a+" "+b}function Ea(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function ba(a,b,c){var d="";a=X(a)?a:a&&U(a)&&a.length?a.split(/\s+/):[];u(a,function(a,s){a&&0<a.length&&(d+=0<s?" ":"",d+=c?b+a:a+b)});return d}function Fa(a){if(a instanceof G)switch(a.length){case 0:return[]; +case 1:if(1===a[0].nodeType)return a;break;default:return G(ka(a))}if(1===a.nodeType)return G(a)}function ka(a){if(!a[0])return a;for(var b=0;b<a.length;b++){var c=a[b];if(1==c.nodeType)return c}}function Ga(a,b,c){u(b,function(b){a.addClass(b,c)})}function Ha(a,b,c){u(b,function(b){a.removeClass(b,c)})}function ha(a){return function(b,c){c.addClass&&(Ga(a,b,c.addClass),c.addClass=null);c.removeClass&&(Ha(a,b,c.removeClass),c.removeClass=null)}}function ia(a){a=a||{};if(!a.$$prepared){var b=a.domOperation|| +H;a.domOperation=function(){a.$$domOperationFired=!0;b();b=H};a.$$prepared=!0}return a}function ca(a,b){wa(a,b);xa(a,b)}function wa(a,b){b.from&&(a.css(b.from),b.from=null)}function xa(a,b){b.to&&(a.css(b.to),b.to=null)}function R(a,b,c){var d=(b.addClass||"")+" "+(c.addClass||""),e=(b.removeClass||"")+" "+(c.removeClass||"");a=Ia(a.attr("class"),d,e);ya(b,c);b.addClass=a.addClass?a.addClass:null;b.removeClass=a.removeClass?a.removeClass:null;return b}function Ia(a,b,c){function d(a){U(a)&&(a=a.split(" ")); +var b={};u(a,function(a){a.length&&(b[a]=!0)});return b}var e={};a=d(a);b=d(b);u(b,function(a,b){e[b]=1});c=d(c);u(c,function(a,b){e[b]=1===e[b]?null:-1});var s={addClass:"",removeClass:""};u(e,function(b,c){var d,e;1===b?(d="addClass",e=!a[c]):-1===b&&(d="removeClass",e=a[c]);e&&(s[d].length&&(s[d]+=" "),s[d]+=c)});return s}function z(a){return a instanceof t.element?a[0]:a}function za(a,b,c){var d=Object.create(null),e=a.getComputedStyle(b)||{};u(c,function(a,b){var c=e[a];if(c){var k=c.charAt(0); +if("-"===k||"+"===k||0<=k)c=Ja(c);0===c&&(c=null);d[b]=c}});return d}function Ja(a){var b=0;a=a.split(/\s*,\s*/);u(a,function(a){"s"==a.charAt(a.length-1)&&(a=a.substring(0,a.length-1));a=parseFloat(a)||0;b=b?Math.max(a,b):a});return b}function la(a){return 0===a||null!=a}function Aa(a,b){var c=O,d=a+"s";b?c+="Duration":d+=" linear all";return[c,d]}function ja(a,b){var c=b?"-"+b+"s":"";da(a,[ea,c]);return[ea,c]}function ma(a,b){var c=b?"paused":"",d=V+"PlayState";da(a,[d,c]);return[d,c]}function da(a, +b){a.style[b[0]]=b[1]}function Ba(){var a=Object.create(null);return{flush:function(){a=Object.create(null)},count:function(b){return(b=a[b])?b.total:0},get:function(b){return(b=a[b])&&b.value},put:function(b,c){a[b]?a[b].total++:a[b]={total:1,value:c}}}}var H=t.noop,ya=t.extend,G=t.element,u=t.forEach,X=t.isArray,U=t.isString,na=t.isObject,Ka=t.isUndefined,La=t.isDefined,Ca=t.isFunction,oa=t.isElement,O,pa,V,qa;F.ontransitionend===W&&F.onwebkittransitionend!==W?(O="WebkitTransition",pa="webkitTransitionEnd transitionend"): +(O="transition",pa="transitionend");F.onanimationend===W&&F.onwebkitanimationend!==W?(V="WebkitAnimation",qa="webkitAnimationEnd animationend"):(V="animation",qa="animationend");var ra=V+"Delay",sa=V+"Duration",ea=O+"Delay";F=O+"Duration";var Ma={transitionDuration:F,transitionDelay:ea,transitionProperty:O+"Property",animationDuration:sa,animationDelay:ra,animationIterationCount:V+"IterationCount"},Na={transitionDuration:F,transitionDelay:ea,animationDuration:sa,animationDelay:ra};t.module("ngAnimate", +[]).directive("ngAnimateChildren",[function(){return function(a,b,c){a=c.ngAnimateChildren;t.isString(a)&&0===a.length?b.data("$$ngAnimateChildren",!0):c.$observe("ngAnimateChildren",function(a){b.data("$$ngAnimateChildren","on"===a||"true"===a)})}}]).factory("$$rAFMutex",["$$rAF",function(a){return function(){var b=!1;a(function(){b=!0});return function(c){b?c():a(c)}}}]).factory("$$rAFScheduler",["$$rAF",function(a){function b(a){d.push([].concat(a));c()}function c(){if(d.length){for(var b=[],n= +0;n<d.length;n++){var h=d[n];h.shift()();h.length&&b.push(h)}d=b;e||a(function(){e||c()})}}var d=[],e;b.waitUntilQuiet=function(b){e&&e();e=a(function(){e=null;b();c()})};return b}]).factory("$$AnimateRunner",["$q","$$rAFMutex",function(a,b){function c(a){this.setHost(a);this._doneCallbacks=[];this._runInAnimationFrame=b();this._state=0}c.chain=function(a,b){function c(){if(n===a.length)b(!0);else a[n](function(a){!1===a?b(!1):(n++,c())})}var n=0;c()};c.all=function(a,b){function c(s){h=h&&s;++n=== +a.length&&b(h)}var n=0,h=!0;u(a,function(a){a.done(c)})};c.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===this._state?a():this._doneCallbacks.push(a)},progress:H,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&& +this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end();this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=this;0===b._state&&(b._state=1,b._runInAnimationFrame(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(u(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=0,this._state=2)}};return c}]).provider("$$animateQueue",["$animateProvider", +function(a){function b(a,b,c,h){return d[a].some(function(a){return a(b,c,h)})}function c(a,b){a=a||{};var c=0<(a.addClass||"").length,d=0<(a.removeClass||"").length;return b?c&&d:c||d}var d=this.rules={skip:[],cancel:[],join:[]};d.join.push(function(a,b,d){return!b.structural&&c(b.options)});d.skip.push(function(a,b,d){return!b.structural&&!c(b.options)});d.skip.push(function(a,b,c){return"leave"==c.event&&b.structural});d.skip.push(function(a,b,c){return c.structural&&!b.structural});d.cancel.push(function(a, +b,c){return c.structural&&b.structural});d.cancel.push(function(a,b,c){return 2===c.state&&b.structural});d.cancel.push(function(a,b,c){a=b.options;c=c.options;return a.addClass&&a.addClass===c.removeClass||a.removeClass&&a.removeClass===c.addClass});this.$get=["$$rAF","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite",function(d,s,n,h,k,D,A,Z,I){function w(a,b){var c=z(a),f=[],m=l[b];m&&u(m,function(a){a.node.contains(c)&&f.push(a.callback)}); +return f}function B(a,b,c,f){d(function(){u(w(b,a),function(a){a(b,c,f)})})}function r(a,S,p){function d(b,c,f,p){B(c,a,f,p);b.progress(c,f,p)}function g(b){Da(a,p);ca(a,p);p.domOperation();l.complete(!b)}var P,E;if(a=Fa(a))P=z(a),E=a.parent();p=ia(p);var l=new A;if(!P)return g(),l;X(p.addClass)&&(p.addClass=p.addClass.join(" "));X(p.removeClass)&&(p.removeClass=p.removeClass.join(" "));p.from&&!na(p.from)&&(p.from=null);p.to&&!na(p.to)&&(p.to=null);var e=[P.className,p.addClass,p.removeClass].join(" "); +if(!v(e))return g(),l;var M=0<=["enter","move","leave"].indexOf(S),h=!x||L.get(P),e=!h&&m.get(P)||{},k=!!e.state;h||k&&1==e.state||(h=!ta(a,E,S));if(h)return g(),l;M&&K(a);h={structural:M,element:a,event:S,close:g,options:p,runner:l};if(k){if(b("skip",a,h,e)){if(2===e.state)return g(),l;R(a,e.options,p);return e.runner}if(b("cancel",a,h,e))2===e.state?e.runner.end():e.structural?e.close():R(a,h.options,e.options);else if(b("join",a,h,e))if(2===e.state)R(a,p,{});else return S=h.event=e.event,p=R(a, +e.options,h.options),l}else R(a,p,{});(k=h.structural)||(k="animate"===h.event&&0<Object.keys(h.options.to||{}).length||c(h.options));if(!k)return g(),C(a),l;M&&f(E);var r=(e.counter||0)+1;h.counter=r;ga(a,1,h);s.$$postDigest(function(){var b=m.get(P),v=!b,b=b||{},e=a.parent()||[],E=0<e.length&&("animate"===b.event||b.structural||c(b.options));if(v||b.counter!==r||!E){v&&(Da(a,p),ca(a,p));if(v||M&&b.event!==S)p.domOperation(),l.end();E||C(a)}else S=!b.structural&&c(b.options,!0)?"setClass":b.event, +b.structural&&f(e),ga(a,2),b=D(a,S,b.options),b.done(function(b){g(!b);(b=m.get(P))&&b.counter===r&&C(z(a));d(l,S,"close",{})}),l.setHost(b),d(l,S,"start",{})});return l}function K(a){a=z(a).querySelectorAll("[data-ng-animate]");u(a,function(a){var b=parseInt(a.getAttribute("data-ng-animate")),c=m.get(a);switch(b){case 2:c.runner.end();case 1:c&&m.remove(a)}})}function C(a){a=z(a);a.removeAttribute("data-ng-animate");m.remove(a)}function E(a,b){return z(a)===z(b)}function f(a){a=z(a);do{if(!a||1!== +a.nodeType)break;var b=m.get(a);if(b){var f=a;!b.structural&&c(b.options)&&(2===b.state&&b.runner.end(),C(f))}a=a.parentNode}while(1)}function ta(a,b,c){var f=c=!1,d=!1,v;for((a=a.data("$ngAnimatePin"))&&(b=a);b&&b.length;){f||(f=E(b,n));a=b[0];if(1!==a.nodeType)break;var e=m.get(a)||{};d||(d=e.structural||L.get(a));if(Ka(v)||!0===v)a=b.data("$$ngAnimateChildren"),La(a)&&(v=a);if(d&&!1===v)break;f||(f=E(b,n),f||(a=b.data("$ngAnimatePin"))&&(b=a));c||(c=E(b,g));b=b.parent()}return(!d||v)&&f&&c}function ga(a, +b,c){c=c||{};c.state=b;a=z(a);a.setAttribute("data-ng-animate",b);c=(b=m.get(a))?ya(b,c):c;m.put(a,c)}var m=new k,L=new k,x=null,M=s.$watch(function(){return 0===Z.totalPendingRequests},function(a){a&&(M(),s.$$postDigest(function(){s.$$postDigest(function(){null===x&&(x=!0)})}))}),g=G(h[0].body),l={},P=a.classNameFilter(),v=P?function(a){return P.test(a)}:function(){return!0},Da=ha(I);return{on:function(a,b,c){b=ka(b);l[a]=l[a]||[];l[a].push({node:b,callback:c})},off:function(a,b,c){function f(a, +b,c){var d=ka(b);return a.filter(function(a){return!(a.node===d&&(!c||a.callback===c))})}var d=l[a];d&&(l[a]=1===arguments.length?null:f(d,b,c))},pin:function(a,b){ua(oa(a),"element","not an element");ua(oa(b),"parentElement","not an element");a.data("$ngAnimatePin",b)},push:function(a,b,c,f){c=c||{};c.domOperation=f;return r(a,b,c)},enabled:function(a,b){var c=arguments.length;if(0===c)b=!!x;else if(oa(a)){var f=z(a),d=L.get(f);1===c?b=!d:(b=!!b)?d&&L.remove(f):L.put(f,!0)}else b=x=!!a;return b}}}]}]).provider("$$animation", +["$animateProvider",function(a){function b(a){return a.data("$$animationRunner")}var c=this.drivers=[];this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$rAFScheduler",function(a,e,s,n,h){var k=[],D=ha(a),A=0,Z=0,I=[];return function(w,B,r){function K(a){a=a.hasAttribute("ng-animate-ref")?[a]:a.querySelectorAll("[ng-animate-ref]");var b=[];u(a,function(a){var c=a.getAttribute("ng-animate-ref");c&&c.length&&b.push(a)});return b}function C(a){var b=[],c={};u(a,function(a,f){var d=z(a.element), +m=0<=["enter","move"].indexOf(a.event),d=a.structural?K(d):[];if(d.length){var g=m?"to":"from";u(d,function(a){var b=a.getAttribute("ng-animate-ref");c[b]=c[b]||{};c[b][g]={animationID:f,element:G(a)}})}else b.push(a)});var f={},d={};u(c,function(c,m){var g=c.from,e=c.to;if(g&&e){var l=a[g.animationID],h=a[e.animationID],x=g.animationID.toString();if(!d[x]){var B=d[x]={structural:!0,beforeStart:function(){l.beforeStart();h.beforeStart()},close:function(){l.close();h.close()},classes:E(l.classes,h.classes), +from:l,to:h,anchors:[]};B.classes.length?b.push(B):(b.push(l),b.push(h))}d[x].anchors.push({out:g.element,"in":e.element})}else g=g?g.animationID:e.animationID,e=g.toString(),f[e]||(f[e]=!0,b.push(a[g]))});return b}function E(a,b){a=a.split(" ");b=b.split(" ");for(var c=[],f=0;f<a.length;f++){var d=a[f];if("ng-"!==d.substring(0,3))for(var g=0;g<b.length;g++)if(d===b[g]){c.push(d);break}}return c.join(" ")}function f(a){for(var b=c.length-1;0<=b;b--){var f=c[b];if(s.has(f)&&(f=s.get(f)(a)))return f}} +function ta(a,c){a.from&&a.to?(b(a.from.element).setHost(c),b(a.to.element).setHost(c)):b(a.element).setHost(c)}function ga(){var a=b(w);!a||"leave"===B&&r.$$domOperationFired||a.end()}function m(b){w.off("$destroy",ga);w.removeData("$$animationRunner");D(w,r);ca(w,r);r.domOperation();g&&a.removeClass(w,g);w.removeClass("ng-animate");x.complete(!b)}r=ia(r);var L=0<=["enter","move","leave"].indexOf(B),x=new n({end:function(){m()},cancel:function(){m(!0)}});if(!c.length)return m(),x;w.data("$$animationRunner", +x);var M=va(w.attr("class"),va(r.addClass,r.removeClass)),g=r.tempClasses;g&&(M+=" "+g,r.tempClasses=null);var l;L||(l=A,A+=1);k.push({element:w,classes:M,event:B,classBasedIndex:l,structural:L,options:r,beforeStart:function(){w.addClass("ng-animate");g&&a.addClass(w,g)},close:m});w.on("$destroy",ga);if(1<k.length)return x;e.$$postDigest(function(){Z=A;A=0;I.length=0;var a=[];u(k,function(c){b(c.element)&&a.push(c)});k.length=0;u(C(a),function(a){function c(){a.beforeStart();var d,g=a.close,e=a.anchors? +a.from.element||a.to.element:a.element;b(e)&&z(e).parentNode&&(e=f(a))&&(d=e.start);d?(d=d(),d.done(function(a){g(!a)}),ta(a,d)):g()}a.structural?c():(I.push({node:z(a.element),fn:c}),a.classBasedIndex===Z-1&&(I=I.sort(function(a,b){return b.node.contains(a.node)}).map(function(a){return a.fn}),h(I)))})});return x}}]}]).provider("$animateCss",["$animateProvider",function(a){var b=Ba(),c=Ba();this.$get=["$window","$$jqLite","$$AnimateRunner","$timeout","$document","$sniffer","$$rAFScheduler",function(a, +e,s,n,h,k,D){function A(a,b){var c=a.parentNode;return(c.$$ngAnimateParentKey||(c.$$ngAnimateParentKey=++r))+"-"+a.getAttribute("class")+"-"+b}function Z(h,f,B,k){var m;0<b.count(B)&&(m=c.get(B),m||(f=ba(f,"-stagger"),e.addClass(h,f),m=za(a,h,k),m.animationDuration=Math.max(m.animationDuration,0),m.transitionDuration=Math.max(m.transitionDuration,0),e.removeClass(h,f),c.put(B,m)));return m||{}}function I(a){C.push(a);D.waitUntilQuiet(function(){b.flush();c.flush();for(var a=K.offsetWidth+1,d=0;d< +C.length;d++)C[d](a);C.length=0})}function w(c,f,e){f=b.get(e);f||(f=za(a,c,Ma),"infinite"===f.animationIterationCount&&(f.animationIterationCount=1));b.put(e,f);c=f;e=c.animationDelay;f=c.transitionDelay;c.maxDelay=e&&f?Math.max(e,f):e||f;c.maxDuration=Math.max(c.animationDuration*c.animationIterationCount,c.transitionDuration);return c}var B=ha(e),r=0,K=z(h).body,C=[];return function(a,c){function d(){m()}function h(){m(!0)}function m(b){if(!(K||C&&D)){K=!0;D=!1;e.removeClass(a,Y);e.removeClass(a, +W);ma(g,!1);ja(g,!1);u(l,function(a){g.style[a[0]]=""});B(a,c);ca(a,c);if(c.onDone)c.onDone();p&&p.complete(!b)}}function L(a){q.blockTransition&&ja(g,a);q.blockKeyframeAnimation&&ma(g,!!a)}function x(){p=new s({end:d,cancel:h});m();return{$$willAnimate:!1,start:function(){return p},end:d}}function M(){function b(){if(!K){L(!1);u(l,function(a){g.style[a[0]]=a[1]});B(a,c);e.addClass(a,W);if(q.recalculateTimingStyles){fa=g.className+" "+Y;$=A(g,fa);y=w(g,fa,$);Q=y.maxDelay;H=Math.max(Q,0);J=y.maxDuration; +if(0===J){m();return}q.hasTransitions=0<y.transitionDuration;q.hasAnimations=0<y.animationDuration}if(q.applyTransitionDelay||q.applyAnimationDelay){Q="boolean"!==typeof c.delay&&la(c.delay)?parseFloat(c.delay):Q;H=Math.max(Q,0);var k;q.applyTransitionDelay&&(y.transitionDelay=Q,k=[ea,Q+"s"],l.push(k),g.style[k[0]]=k[1]);q.applyAnimationDelay&&(y.animationDelay=Q,k=[ra,Q+"s"],l.push(k),g.style[k[0]]=k[1])}F=1E3*H;G=1E3*J;if(c.easing){var r=c.easing;q.hasTransitions&&(k=O+"TimingFunction",l.push([k, +r]),g.style[k]=r);q.hasAnimations&&(k=V+"TimingFunction",l.push([k,r]),g.style[k]=r)}y.transitionDuration&&p.push(pa);y.animationDuration&&p.push(qa);x=Date.now();a.on(p.join(" "),h);n(d,F+1.5*G);xa(a,c)}}function d(){m()}function h(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-x,0)>=F&&b>=J&&(C=!0,m())}if(!K)if(g.parentNode){var x,p=[],k=function(a){if(C)D&&a&&(D=!1,m());else if(D=!a,y.animationDuration)if(a= +ma(g,D),D)l.push(a);else{var b=l,c=b.indexOf(a);0<=a&&b.splice(c,1)}},r=0<U&&(y.transitionDuration&&0===T.transitionDuration||y.animationDuration&&0===T.animationDuration)&&Math.max(T.animationDelay,T.transitionDelay);r?n(b,Math.floor(r*U*1E3),!1):b();t.resume=function(){k(!0)};t.pause=function(){k(!1)}}else m()}var g=z(a);if(!g||!g.parentNode)return x();c=ia(c);var l=[],r=a.attr("class"),v=Ea(c),K,D,C,p,t,H,F,J,G;if(0===c.duration||!k.animations&&!k.transitions)return x();var aa=c.event&&X(c.event)? +c.event.join(" "):c.event,R="",N="";aa&&c.structural?R=ba(aa,"ng-",!0):aa&&(R=aa);c.addClass&&(N+=ba(c.addClass,"-add"));c.removeClass&&(N.length&&(N+=" "),N+=ba(c.removeClass,"-remove"));c.applyClassesEarly&&N.length&&(B(a,c),N="");var Y=[R,N].join(" ").trim(),fa=r+" "+Y,W=ba(Y,"-active"),r=v.to&&0<Object.keys(v.to).length;if(!(0<(c.keyframeStyle||"").length||r||Y))return x();var $,T;0<c.stagger?(v=parseFloat(c.stagger),T={transitionDelay:v,animationDelay:v,transitionDuration:0,animationDuration:0}): +($=A(g,fa),T=Z(g,Y,$,Na));e.addClass(a,Y);c.transitionStyle&&(v=[O,c.transitionStyle],da(g,v),l.push(v));0<=c.duration&&(v=0<g.style[O].length,v=Aa(c.duration,v),da(g,v),l.push(v));c.keyframeStyle&&(v=[V,c.keyframeStyle],da(g,v),l.push(v));var U=T?0<=c.staggerIndex?c.staggerIndex:b.count($):0;(aa=0===U)&&ja(g,9999);var y=w(g,fa,$),Q=y.maxDelay;H=Math.max(Q,0);J=y.maxDuration;var q={};q.hasTransitions=0<y.transitionDuration;q.hasAnimations=0<y.animationDuration;q.hasTransitionAll=q.hasTransitions&& +"all"==y.transitionProperty;q.applyTransitionDuration=r&&(q.hasTransitions&&!q.hasTransitionAll||q.hasAnimations&&!q.hasTransitions);q.applyAnimationDuration=c.duration&&q.hasAnimations;q.applyTransitionDelay=la(c.delay)&&(q.applyTransitionDuration||q.hasTransitions);q.applyAnimationDelay=la(c.delay)&&q.hasAnimations;q.recalculateTimingStyles=0<N.length;if(q.applyTransitionDuration||q.applyAnimationDuration)J=c.duration?parseFloat(c.duration):J,q.applyTransitionDuration&&(q.hasTransitions=!0,y.transitionDuration= +J,v=0<g.style[O+"Property"].length,l.push(Aa(J,v))),q.applyAnimationDuration&&(q.hasAnimations=!0,y.animationDuration=J,l.push([sa,J+"s"]));if(0===J&&!q.recalculateTimingStyles)return x();null==c.duration&&0<y.transitionDuration&&(q.recalculateTimingStyles=q.recalculateTimingStyles||aa);F=1E3*H;G=1E3*J;c.skipBlocking||(q.blockTransition=0<y.transitionDuration,q.blockKeyframeAnimation=0<y.animationDuration&&0<T.animationDelay&&0===T.animationDuration);wa(a,c);q.blockTransition||ja(g,!1);L(J);return{$$willAnimate:!0, +end:d,start:function(){if(!K)return t={end:d,cancel:h,resume:null,pause:null},p=new s(t),I(M),p}}}}]}]).provider("$$animateCssDriver",["$$animationProvider",function(a){a.drivers.push("$$animateCssDriver");this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$document","$sniffer",function(a,c,d,e,s,n){function h(a){return a.replace(/\bng-\S+\b/g,"")}function k(a,b){U(a)&&(a=a.split(" "));U(b)&&(b=b.split(" "));return a.filter(function(a){return-1===b.indexOf(a)}).join(" ")}function D(c, +e,A){function D(a){var b={},c=z(a).getBoundingClientRect();u(["width","height","top","left"],function(a){var d=c[a];switch(a){case "top":d+=I.scrollTop;break;case "left":d+=I.scrollLeft}b[a]=Math.floor(d)+"px"});return b}function s(){var c=h(A.attr("class")||""),d=k(c,t),c=k(t,c),d=a(n,{to:D(A),addClass:"ng-anchor-in "+d,removeClass:"ng-anchor-out "+c,delay:!0});return d.$$willAnimate?d:null}function f(){n.remove();e.removeClass("ng-animate-shim");A.removeClass("ng-animate-shim")}var n=G(z(e).cloneNode(!0)), +t=h(n.attr("class")||"");e.addClass("ng-animate-shim");A.addClass("ng-animate-shim");n.addClass("ng-anchor");w.append(n);var m;c=function(){var c=a(n,{addClass:"ng-anchor-out",delay:!0,from:D(e)});return c.$$willAnimate?c:null}();if(!c&&(m=s(),!m))return f();var L=c||m;return{start:function(){function a(){c&&c.end()}var b,c=L.start();c.done(function(){c=null;if(!m&&(m=s()))return c=m.start(),c.done(function(){c=null;f();b.complete()}),c;f();b.complete()});return b=new d({end:a,cancel:a})}}}function A(a, +b,c,e){var h=t(a),f=t(b),k=[];u(e,function(a){(a=D(c,a.out,a["in"]))&&k.push(a)});if(h||f||0!==k.length)return{start:function(){function a(){u(b,function(a){a.end()})}var b=[];h&&b.push(h.start());f&&b.push(f.start());u(k,function(a){b.push(a.start())});var c=new d({end:a,cancel:a});d.all(b,function(a){c.complete(a)});return c}}}function t(c){var d=c.element,e=c.options||{};c.structural?(e.structural=e.applyClassesEarly=!0,e.event=c.event,"leave"===e.event&&(e.onDone=e.domOperation)):e.event=null; +c=a(d,e);return c.$$willAnimate?c:null}if(!n.animations&&!n.transitions)return H;var I=z(s).body;c=z(e);var w=G(I.parentNode===c?I:c);return function(a){return a.from&&a.to?A(a.from,a.to,a.classes,a.anchors):t(a)}}]}]).provider("$$animateJs",["$animateProvider",function(a){this.$get=["$injector","$$AnimateRunner","$$rAFMutex","$$jqLite",function(b,c,d,e){function s(c){c=X(c)?c:c.split(" ");for(var d=[],e={},A=0;A<c.length;A++){var n=c[A],s=a.$$registeredAnimations[n];s&&!e[n]&&(d.push(b.get(s)),e[n]= +!0)}return d}var n=ha(e);return function(a,b,d,e){function t(){e.domOperation();n(a,e)}function z(a,b,d,e,g){switch(d){case "animate":b=[b,e.from,e.to,g];break;case "setClass":b=[b,r,K,g];break;case "addClass":b=[b,r,g];break;case "removeClass":b=[b,K,g];break;default:b=[b,g]}b.push(e);if(a=a.apply(a,b))if(Ca(a.start)&&(a=a.start()),a instanceof c)a.done(g);else if(Ca(a))return a;return H}function w(a,b,d,e,g){var f=[];u(e,function(e){var h=e[g];h&&f.push(function(){var e,g,f=!1,l=function(a){f|| +(f=!0,(g||H)(a),e.complete(!a))};e=new c({end:function(){l()},cancel:function(){l(!0)}});g=z(h,a,b,d,function(a){l(!1===a)});return e})});return f}function B(a,b,d,e,g){var f=w(a,b,d,e,g);if(0===f.length){var h,k;"beforeSetClass"===g?(h=w(a,"removeClass",d,e,"beforeRemoveClass"),k=w(a,"addClass",d,e,"beforeAddClass")):"setClass"===g&&(h=w(a,"removeClass",d,e,"removeClass"),k=w(a,"addClass",d,e,"addClass"));h&&(f=f.concat(h));k&&(f=f.concat(k))}if(0!==f.length)return function(a){var b=[];f.length&& +u(f,function(a){b.push(a())});b.length?c.all(b,a):a();return function(a){u(b,function(b){a?b.cancel():b.end()})}}}3===arguments.length&&na(d)&&(e=d,d=null);e=ia(e);d||(d=a.attr("class")||"",e.addClass&&(d+=" "+e.addClass),e.removeClass&&(d+=" "+e.removeClass));var r=e.addClass,K=e.removeClass,C=s(d),E,f;if(C.length){var F,G;"leave"==b?(G="leave",F="afterLeave"):(G="before"+b.charAt(0).toUpperCase()+b.substr(1),F=b);"enter"!==b&&"move"!==b&&(E=B(a,b,e,C,G));f=B(a,b,e,C,F)}if(E||f)return{start:function(){function b(c){n= +!0;t();ca(a,e);g.complete(c)}var d,k=[];E&&k.push(function(a){d=E(a)});k.length?k.push(function(a){t();a(!0)}):t();f&&k.push(function(a){d=f(a)});var n=!1,g=new c({end:function(){n||((d||H)(void 0),b(void 0))},cancel:function(){n||((d||H)(!0),b(!0))}});c.chain(k,b);return g}}}}]}]).provider("$$animateJsDriver",["$$animationProvider",function(a){a.drivers.push("$$animateJsDriver");this.$get=["$$animateJs","$$AnimateRunner",function(a,c){function d(c){return a(c.element,c.event,c.classes,c.options)} +return function(a){if(a.from&&a.to){var b=d(a.from),n=d(a.to);if(b||n)return{start:function(){function a(){return function(){u(d,function(a){a.end()})}}var d=[];b&&d.push(b.start());n&&d.push(n.start());c.all(d,function(a){e.complete(a)});var e=new c({end:a(),cancel:a()});return e}}}else return d(a)}}]}])})(window,window.angular); //# sourceMappingURL=angular-animate.min.js.map diff --git a/www/lib/ionic/js/angular/angular-resource.js b/www/lib/ionic/js/angular/angular-resource.js index 30361935829296d7793024c80acb41b28d3367a9..797f9eeafb8b7f647ee7680858e6beabd33e8e7f 100644 --- a/www/lib/ionic/js/angular/angular-resource.js +++ b/www/lib/ionic/js/angular/angular-resource.js @@ -1,6 +1,6 @@ /** - * @license AngularJS v1.3.13 - * (c) 2010-2014 Google, Inc. http://angularjs.org + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org * License: MIT */ (function(window, angular, undefined) {'use strict'; @@ -10,7 +10,7 @@ var $resourceMinErr = angular.$$minErr('$resource'); // Helper functions and regex to lookup a dotted path on an object // stopping at undefined/null. The path must be composed of ASCII // identifiers (just like $parse) -var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/; +var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/; function isValidDottedPath(path) { return (path != null && path !== '' && path !== 'hasOwnProperty' && @@ -90,7 +90,7 @@ function shallowClearAndCopy(src, dst) { }]); * ``` * - * @param {string} url A parametrized URL template with parameters prefixed by `:` as in + * @param {string} url A parameterized URL template with parameters prefixed by `:` as in * `/user/:username`. If you are using a URL with a port number (e.g. * `http://example.com:8080/api`), it will be respected. * @@ -213,7 +213,9 @@ function shallowClearAndCopy(src, dst) { * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` * - non-GET instance actions: `instance.$action([parameters], [success], [error])` * - * Success callback is called with (value, responseHeaders) arguments. Error callback is called + * + * Success callback is called with (value, responseHeaders) arguments, where the value is + * the populated resource instance or collection object. The error callback is called * with (httpResponse) argument. * * Class actions return empty instance (with additional properties below). @@ -585,8 +587,8 @@ angular.module('ngResource', ['ng']). if (angular.isArray(data) !== (!!action.isArray)) { throw $resourceMinErr('badcfg', 'Error in resource configuration for action `{0}`. Expected response to ' + - 'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object', - angular.isArray(data) ? 'array' : 'object'); + 'contain an {1} but got an {2} (Request: {3} {4})', name, action.isArray ? 'array' : 'object', + angular.isArray(data) ? 'array' : 'object', httpConfig.method, httpConfig.url); } // jshint +W018 if (action.isArray) { diff --git a/www/lib/ionic/js/angular/angular-resource.min.js b/www/lib/ionic/js/angular/angular-resource.min.js index 35ec1c7dff7fb091558267906175f71c4afabdb1..07981179090e578d47dfe87e5f1fbaabf1f136f3 100644 --- a/www/lib/ionic/js/angular/angular-resource.min.js +++ b/www/lib/ionic/js/angular/angular-resource.min.js @@ -1,13 +1,13 @@ /* - AngularJS v1.3.13 - (c) 2010-2014 Google, Inc. http://angularjs.org + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org License: MIT */ -(function(I,d,B){'use strict';function D(f,q){q=q||{};d.forEach(q,function(d,h){delete q[h]});for(var h in f)!f.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(q[h]=f[h]);return q}var w=d.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var f=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}}; -this.$get=["$http","$q",function(q,h){function t(d,g){this.template=d;this.defaults=s({},f.defaults,g);this.urlParams={}}function v(x,g,l,m){function c(b,k){var c={};k=s({},g,k);r(k,function(a,k){u(a)&&(a=a());var d;if(a&&a.charAt&&"@"==a.charAt(0)){d=b;var e=a.substr(1);if(null==e||""===e||"hasOwnProperty"===e||!C.test("."+e))throw w("badmember",e);for(var e=e.split("."),n=0,g=e.length;n<g&&d!==B;n++){var h=e[n];d=null!==d?d[h]:B}}else d=a;c[k]=d});return c}function F(b){return b.resource}function e(b){D(b|| -{},this)}var G=new t(x,m);l=s({},f.defaults.actions,l);e.prototype.toJSON=function(){var b=s({},this);delete b.$promise;delete b.$resolved;return b};r(l,function(b,k){var g=/^(POST|PUT|PATCH)$/i.test(b.method);e[k]=function(a,y,m,x){var n={},f,l,z;switch(arguments.length){case 4:z=x,l=m;case 3:case 2:if(u(y)){if(u(a)){l=a;z=y;break}l=y;z=m}else{n=a;f=y;l=m;break}case 1:u(a)?l=a:g?f=a:n=a;break;case 0:break;default:throw w("badargs",arguments.length);}var t=this instanceof e,p=t?f:b.isArray?[]:new e(f), -A={},v=b.interceptor&&b.interceptor.response||F,C=b.interceptor&&b.interceptor.responseError||B;r(b,function(b,a){"params"!=a&&"isArray"!=a&&"interceptor"!=a&&(A[a]=H(b))});g&&(A.data=f);G.setUrlParams(A,s({},c(f,b.params||{}),n),b.url);n=q(A).then(function(a){var c=a.data,g=p.$promise;if(c){if(d.isArray(c)!==!!b.isArray)throw w("badcfg",k,b.isArray?"array":"object",d.isArray(c)?"array":"object");b.isArray?(p.length=0,r(c,function(a){"object"===typeof a?p.push(new e(a)):p.push(a)})):(D(c,p),p.$promise= -g)}p.$resolved=!0;a.resource=p;return a},function(a){p.$resolved=!0;(z||E)(a);return h.reject(a)});n=n.then(function(a){var b=v(a);(l||E)(b,a.headers);return b},C);return t?n:(p.$promise=n,p.$resolved=!1,p)};e.prototype["$"+k]=function(a,b,c){u(a)&&(c=b,b=a,a={});a=e[k].call(this,a,this,b,c);return a.$promise||a}});e.bind=function(b){return v(x,s({},g,b),l)};return e}var E=d.noop,r=d.forEach,s=d.extend,H=d.copy,u=d.isFunction;t.prototype={setUrlParams:function(f,g,l){var m=this,c=l||m.template,h, -e,q=m.urlParams={};r(c.split(/\W/),function(b){if("hasOwnProperty"===b)throw w("badname");!/^\d+$/.test(b)&&b&&(new RegExp("(^|[^\\\\]):"+b+"(\\W|$)")).test(c)&&(q[b]=!0)});c=c.replace(/\\:/g,":");g=g||{};r(m.urlParams,function(b,k){h=g.hasOwnProperty(k)?g[k]:m.defaults[k];d.isDefined(h)&&null!==h?(e=encodeURIComponent(h).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),c=c.replace(new RegExp(":"+ -k+"(\\W|$)","g"),function(b,a){return e+a})):c=c.replace(new RegExp("(/?):"+k+"(\\W|$)","g"),function(b,a,c){return"/"==c.charAt(0)?c:a+c})});m.defaults.stripTrailingSlashes&&(c=c.replace(/\/+$/,"")||"/");c=c.replace(/\/\.(?=\w+($|\?))/,".");f.url=c.replace(/\/\\\./,"/.");r(g,function(b,c){m.urlParams[c]||(f.params=f.params||{},f.params[c]=b)})}};return v}]})})(window,window.angular); +(function(I,d,B){'use strict';function D(f,q){q=q||{};d.forEach(q,function(d,h){delete q[h]});for(var h in f)!f.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(q[h]=f[h]);return q}var x=d.$$minErr("$resource"),C=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var f=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}}; +this.$get=["$http","$q",function(q,h){function u(d,g){this.template=d;this.defaults=s({},f.defaults,g);this.urlParams={}}function w(y,g,l,m){function c(b,k){var c={};k=s({},g,k);r(k,function(a,k){v(a)&&(a=a());var d;if(a&&a.charAt&&"@"==a.charAt(0)){d=b;var e=a.substr(1);if(null==e||""===e||"hasOwnProperty"===e||!C.test("."+e))throw x("badmember",e);for(var e=e.split("."),n=0,g=e.length;n<g&&d!==B;n++){var h=e[n];d=null!==d?d[h]:B}}else d=a;c[k]=d});return c}function F(b){return b.resource}function e(b){D(b|| +{},this)}var G=new u(y,m);l=s({},f.defaults.actions,l);e.prototype.toJSON=function(){var b=s({},this);delete b.$promise;delete b.$resolved;return b};r(l,function(b,k){var g=/^(POST|PUT|PATCH)$/i.test(b.method);e[k]=function(a,z,m,y){var n={},f,l,A;switch(arguments.length){case 4:A=y,l=m;case 3:case 2:if(v(z)){if(v(a)){l=a;A=z;break}l=z;A=m}else{n=a;f=z;l=m;break}case 1:v(a)?l=a:g?f=a:n=a;break;case 0:break;default:throw x("badargs",arguments.length);}var u=this instanceof e,p=u?f:b.isArray?[]:new e(f), +t={},w=b.interceptor&&b.interceptor.response||F,C=b.interceptor&&b.interceptor.responseError||B;r(b,function(b,a){"params"!=a&&"isArray"!=a&&"interceptor"!=a&&(t[a]=H(b))});g&&(t.data=f);G.setUrlParams(t,s({},c(f,b.params||{}),n),b.url);n=q(t).then(function(a){var c=a.data,g=p.$promise;if(c){if(d.isArray(c)!==!!b.isArray)throw x("badcfg",k,b.isArray?"array":"object",d.isArray(c)?"array":"object",t.method,t.url);b.isArray?(p.length=0,r(c,function(a){"object"===typeof a?p.push(new e(a)):p.push(a)})): +(D(c,p),p.$promise=g)}p.$resolved=!0;a.resource=p;return a},function(a){p.$resolved=!0;(A||E)(a);return h.reject(a)});n=n.then(function(a){var b=w(a);(l||E)(b,a.headers);return b},C);return u?n:(p.$promise=n,p.$resolved=!1,p)};e.prototype["$"+k]=function(a,b,c){v(a)&&(c=b,b=a,a={});a=e[k].call(this,a,this,b,c);return a.$promise||a}});e.bind=function(b){return w(y,s({},g,b),l)};return e}var E=d.noop,r=d.forEach,s=d.extend,H=d.copy,v=d.isFunction;u.prototype={setUrlParams:function(f,g,l){var m=this, +c=l||m.template,h,e,q=m.urlParams={};r(c.split(/\W/),function(b){if("hasOwnProperty"===b)throw x("badname");!/^\d+$/.test(b)&&b&&(new RegExp("(^|[^\\\\]):"+b+"(\\W|$)")).test(c)&&(q[b]=!0)});c=c.replace(/\\:/g,":");g=g||{};r(m.urlParams,function(b,k){h=g.hasOwnProperty(k)?g[k]:m.defaults[k];d.isDefined(h)&&null!==h?(e=encodeURIComponent(h).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi, +"+"),c=c.replace(new RegExp(":"+k+"(\\W|$)","g"),function(b,a){return e+a})):c=c.replace(new RegExp("(/?):"+k+"(\\W|$)","g"),function(b,a,c){return"/"==c.charAt(0)?c:a+c})});m.defaults.stripTrailingSlashes&&(c=c.replace(/\/+$/,"")||"/");c=c.replace(/\/\.(?=\w+($|\?))/,".");f.url=c.replace(/\/\\\./,"/.");r(g,function(b,c){m.urlParams[c]||(f.params=f.params||{},f.params[c]=b)})}};return w}]})})(window,window.angular); //# sourceMappingURL=angular-resource.min.js.map diff --git a/www/lib/ionic/js/angular/angular-sanitize.js b/www/lib/ionic/js/angular/angular-sanitize.js index b629a52433e49800a732b3b6af83a4536add2dce..bebe1a72ab684038733e4bdc2615ab4cc9ebeae0 100644 --- a/www/lib/ionic/js/angular/angular-sanitize.js +++ b/www/lib/ionic/js/angular/angular-sanitize.js @@ -1,10 +1,21 @@ /** - * @license AngularJS v1.3.13 - * (c) 2010-2014 Google, Inc. http://angularjs.org + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org * License: MIT */ (function(window, angular, undefined) {'use strict'; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + var $sanitizeMinErr = angular.$$minErr('$sanitize'); /** @@ -200,10 +211,11 @@ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a // SVG Elements // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements -var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," + - "desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," + - "line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," + - "stop,svg,switch,text,title,tspan,use"); +// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted. +// They can potentially allow for arbitrary javascript to be executed. See #11290 +var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," + + "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," + + "radialGradient,rect,stop,svg,switch,text,title,tspan,use"); // Special Elements (can contain anything) var specialElements = makeMap("script,style"); @@ -221,36 +233,37 @@ var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href"); var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + - 'scope,scrolling,shape,size,span,start,summary,target,title,type,' + + 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' + 'valign,value,vspace,width'); // SVG attributes (without "id" and "name" attributes) // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + - 'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' + - 'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' + - 'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' + - 'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' + - 'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' + - 'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' + - 'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' + - 'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' + - 'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' + - 'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' + - 'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' + - 'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' + - 'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' + - 'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' + - 'zoomAndPan'); + 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + + 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + + 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + + 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' + + 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' + + 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' + + 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' + + 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' + + 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' + + 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' + + 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' + + 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' + + 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' + + 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true); var validAttrs = angular.extend({}, uriAttrs, svgAttrs, htmlAttrs); -function makeMap(str) { +function makeMap(str, lowercaseKeys) { var obj = {}, items = str.split(','), i; - for (i = 0; i < items.length; i++) obj[items[i]] = true; + for (i = 0; i < items.length; i++) { + obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true; + } return obj; } @@ -378,8 +391,9 @@ function htmlParser(html, handler) { unary = voidElements[tagName] || !!unary; - if (!unary) + if (!unary) { stack.push(tagName); + } var attrs = {}; @@ -398,11 +412,12 @@ function htmlParser(html, handler) { function parseEndTag(tag, tagName) { var pos = 0, i; tagName = angular.lowercase(tagName); - if (tagName) + if (tagName) { // Find the closest opened tag of the same type - for (pos = stack.length - 1; pos >= 0; pos--) - if (stack[pos] == tagName) - break; + for (pos = stack.length - 1; pos >= 0; pos--) { + if (stack[pos] == tagName) break; + } + } if (pos >= 0) { // Close all the open elements, up the stack @@ -416,7 +431,6 @@ function htmlParser(html, handler) { } var hiddenPre=document.createElement("pre"); -var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; /** * decodes all entities into regular string * @param value @@ -425,22 +439,10 @@ var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; function decodeEntities(value) { if (!value) { return ''; } - // Note: IE8 does not preserve spaces at the start/end of innerHTML - // so we must capture them and reattach them afterward - var parts = spaceRe.exec(value); - var spaceBefore = parts[1]; - var spaceAfter = parts[3]; - var content = parts[2]; - if (content) { - hiddenPre.innerHTML=content.replace(/</g,"<"); - // innerText depends on styling as it doesn't display hidden elements. - // Therefore, it's better to use textContent not to cause unnecessary - // reflows. However, IE<9 don't support textContent so the innerText - // fallback is necessary. - content = 'textContent' in hiddenPre ? - hiddenPre.textContent : hiddenPre.innerText; - } - return spaceBefore + content + spaceAfter; + hiddenPre.innerHTML = value.replace(/</g,"<"); + // innerText depends on styling as it doesn't display hidden elements. + // Therefore, it's better to use textContent not to cause unnecessary reflows. + return hiddenPre.textContent; } /** @@ -629,8 +631,8 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); */ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { var LINKY_URL_REGEXP = - /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"â€â€™]/, - MAILTO_REGEXP = /^mailto:/; + /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"â€â€™]/i, + MAILTO_REGEXP = /^mailto:/i; return function(text, target) { if (!text) return text; diff --git a/www/lib/ionic/js/angular/angular-sanitize.min.js b/www/lib/ionic/js/angular/angular-sanitize.min.js index e6c2b1e60b3fad7c4a024956d7fb8dd6a3b98885..e8c42264872712dfe09f334f528265a96b75ff29 100644 --- a/www/lib/ionic/js/angular/angular-sanitize.min.js +++ b/www/lib/ionic/js/angular/angular-sanitize.min.js @@ -1,16 +1,16 @@ /* - AngularJS v1.3.13 - (c) 2010-2014 Google, Inc. http://angularjs.org + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org License: MIT */ -(function(n,h,p){'use strict';function E(a){var d=[];s(d,h.noop).chars(a);return d.join("")}function g(a){var d={};a=a.split(",");var c;for(c=0;c<a.length;c++)d[a[c]]=!0;return d}function F(a,d){function c(a,b,c,l){b=h.lowercase(b);if(t[b])for(;f.last()&&u[f.last()];)e("",f.last());v[b]&&f.last()==b&&e("",b);(l=w[b]||!!l)||f.push(b);var m={};c.replace(G,function(a,b,d,c,e){m[b]=r(d||c||e||"")});d.start&&d.start(b,m,l)}function e(a,b){var c=0,e;if(b=h.lowercase(b))for(c=f.length-1;0<=c&&f[c]!=b;c--); -if(0<=c){for(e=f.length-1;e>=c;e--)d.end&&d.end(f[e]);f.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,k,f=[],m=a,l;for(f.last=function(){return f[f.length-1]};a;){l="";k=!0;if(f.last()&&x[f.last()])a=a.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(a,b){b=b.replace(H,"$1").replace(I,"$1");d.chars&&d.chars(r(b));return""}),e("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(d.comment&& -d.comment(a.substring(4,b)),a=a.substring(b+3),k=!1);else if(y.test(a)){if(b=a.match(y))a=a.replace(b[0],""),k=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,e),k=!1}else K.test(a)&&((b=a.match(A))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(A,c)),k=!1):(l+="<",a=a.substring(1)));k&&(b=a.indexOf("<"),l+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),d.chars&&d.chars(r(l)))}if(a==m)throw L("badparse",a);m=a}e()}function r(a){if(!a)return"";var d=M.exec(a);a=d[1]; -var c=d[3];if(d=d[2])q.innerHTML=d.replace(/</g,"<"),d="textContent"in q?q.textContent:q.innerText;return a+d+c}function B(a){return a.replace(/&/g,"&").replace(N,function(a){var c=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(c-55296)+(a-56320)+65536)+";"}).replace(O,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"<").replace(/>/g,">")}function s(a,d){var c=!1,e=h.bind(a,a.push);return{start:function(a,k,f){a=h.lowercase(a);!c&&x[a]&&(c=a);c||!0!==C[a]||(e("<"),e(a), -h.forEach(k,function(c,f){var k=h.lowercase(f),g="img"===a&&"src"===k||"background"===k;!0!==P[k]||!0===D[k]&&!d(c,g)||(e(" "),e(f),e('="'),e(B(c)),e('"'))}),e(f?"/>":">"))},end:function(a){a=h.lowercase(a);c||!0!==C[a]||(e("</"),e(a),e(">"));a==c&&(c=!1)},chars:function(a){c||e(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,z=/^<\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, -K=/^</,J=/^<\//,H=/\x3c!--(.*?)--\x3e/g,y=/<!DOCTYPE([^>]*?)>/i,I=/<!\[CDATA\[(.*?)]]\x3e/g,N=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,O=/([^\#-~| |!])/g,w=g("area,br,col,hr,img,wbr");n=g("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr");p=g("rp,rt");var v=h.extend({},p,n),t=h.extend({},n,g("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),u=h.extend({},p,g("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")); -n=g("animate,animateColor,animateMotion,animateTransform,circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,stop,svg,switch,text,title,tspan,use");var x=g("script,style"),C=h.extend({},w,t,u,v,n),D=g("background,cite,href,longdesc,src,usemap,xlink:href");n=g("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,target,title,type,valign,value,vspace,width"); -p=g("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan"); -var P=h.extend({},D,p,n),q=document.createElement("pre"),M=/^(\s*)([\s\S]*?)(\s*)$/;h.module("ngSanitize",[]).provider("$sanitize",function(){this.$get=["$$sanitizeUri",function(a){return function(d){var c=[];F(d,s(c,function(c,b){return!/^unsafe/.test(a(c,b))}));return c.join("")}}]});h.module("ngSanitize").filter("linky",["$sanitize",function(a){var d=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/,c=/^mailto:/;return function(e,b){function k(a){a&&g.push(E(a))} -function f(a,c){g.push("<a ");h.isDefined(b)&&g.push('target="',b,'" ');g.push('href="',a.replace(/"/g,"""),'">');k(c);g.push("</a>")}if(!e)return e;for(var m,l=e,g=[],n,p;m=l.match(d);)n=m[0],m[2]||m[4]||(n=(m[3]?"http://":"mailto:")+n),p=m.index,k(l.substr(0,p)),f(n,m[0].replace(c,"")),l=l.substring(p+m[0].length);k(l);return a(g.join(""))}}])})(window,window.angular); +(function(n,h,p){'use strict';function E(a){var f=[];r(f,h.noop).chars(a);return f.join("")}function g(a,f){var d={},c=a.split(","),b;for(b=0;b<c.length;b++)d[f?h.lowercase(c[b]):c[b]]=!0;return d}function F(a,f){function d(a,b,d,l){b=h.lowercase(b);if(s[b])for(;e.last()&&t[e.last()];)c("",e.last());u[b]&&e.last()==b&&c("",b);(l=v[b]||!!l)||e.push(b);var m={};d.replace(G,function(b,a,f,c,d){m[a]=q(f||c||d||"")});f.start&&f.start(b,m,l)}function c(b,a){var c=0,d;if(a=h.lowercase(a))for(c=e.length- +1;0<=c&&e[c]!=a;c--);if(0<=c){for(d=e.length-1;d>=c;d--)f.end&&f.end(e[d]);e.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,k,e=[],m=a,l;for(e.last=function(){return e[e.length-1]};a;){l="";k=!0;if(e.last()&&w[e.last()])a=a.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*"+e.last()+"[^>]*>","i"),function(a,b){b=b.replace(H,"$1").replace(I,"$1");f.chars&&f.chars(q(b));return""}),c("",e.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e", +b)===b&&(f.comment&&f.comment(a.substring(4,b)),a=a.substring(b+3),k=!1);else if(x.test(a)){if(b=a.match(x))a=a.replace(b[0],""),k=!1}else if(J.test(a)){if(b=a.match(y))a=a.substring(b[0].length),b[0].replace(y,c),k=!1}else K.test(a)&&((b=a.match(z))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(z,d)),k=!1):(l+="<",a=a.substring(1)));k&&(b=a.indexOf("<"),l+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),f.chars&&f.chars(q(l)))}if(a==m)throw L("badparse",a);m=a}c()}function q(a){if(!a)return"";A.innerHTML= +a.replace(/</g,"<");return A.textContent}function B(a){return a.replace(/&/g,"&").replace(M,function(a){var d=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(d-55296)+(a-56320)+65536)+";"}).replace(N,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"<").replace(/>/g,">")}function r(a,f){var d=!1,c=h.bind(a,a.push);return{start:function(a,k,e){a=h.lowercase(a);!d&&w[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(k,function(d,e){var k=h.lowercase(e),g="img"===a&&"src"===k|| +"background"===k;!0!==O[k]||!0===D[k]&&!f(d,g)||(c(" "),c(e),c('="'),c(B(d)),c('"'))}),c(e?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(B(a))}}}var L=h.$$minErr("$sanitize"),z=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,y=/^<\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^</,J=/^<\//,H=/\x3c!--(.*?)--\x3e/g,x=/<!DOCTYPE([^>]*?)>/i, +I=/<!\[CDATA\[(.*?)]]\x3e/g,M=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,N=/([^\#-~| |!])/g,v=g("area,br,col,hr,img,wbr");n=g("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr");p=g("rp,rt");var u=h.extend({},p,n),s=h.extend({},n,g("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),t=h.extend({},p,g("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")); +n=g("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan,use");var w=g("script,style"),C=h.extend({},v,s,t,u,n),D=g("background,cite,href,longdesc,src,usemap,xlink:href");n=g("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,valign,value,vspace,width"); +p=g("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan", +!0);var O=h.extend({},D,p,n),A=document.createElement("pre");h.module("ngSanitize",[]).provider("$sanitize",function(){this.$get=["$$sanitizeUri",function(a){return function(f){var d=[];F(f,r(d,function(c,b){return!/^unsafe/.test(a(c,b))}));return d.join("")}}]});h.module("ngSanitize").filter("linky",["$sanitize",function(a){var f=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,d=/^mailto:/i;return function(c,b){function k(a){a&&g.push(E(a))}function e(a, +c){g.push("<a ");h.isDefined(b)&&g.push('target="',b,'" ');g.push('href="',a.replace(/"/g,"""),'">');k(c);g.push("</a>")}if(!c)return c;for(var m,l=c,g=[],n,p;m=l.match(f);)n=m[0],m[2]||m[4]||(n=(m[3]?"http://":"mailto:")+n),p=m.index,k(l.substr(0,p)),e(n,m[0].replace(d,"")),l=l.substring(p+m[0].length);k(l);return a(g.join(""))}}])})(window,window.angular); //# sourceMappingURL=angular-sanitize.min.js.map diff --git a/www/lib/ionic/js/angular/angular.js b/www/lib/ionic/js/angular/angular.js index 897902824419a3a0dc8917491ce4cd507b7e895e..f7442c0b031cc8afab578e779f9adda096d7eb47 100644 --- a/www/lib/ionic/js/angular/angular.js +++ b/www/lib/ionic/js/angular/angular.js @@ -1,6 +1,6 @@ /** - * @license AngularJS v1.3.13 - * (c) 2010-2014 Google, Inc. http://angularjs.org + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org * License: MIT */ (function(window, document, undefined) {'use strict'; @@ -38,28 +38,33 @@ function minErr(module, ErrorConstructor) { ErrorConstructor = ErrorConstructor || Error; return function() { - var code = arguments[0], - prefix = '[' + (module ? module + ':' : '') + code + '] ', - template = arguments[1], - templateArgs = arguments, + var SKIP_INDEXES = 2; - message, i; + var templateArgs = arguments, + code = templateArgs[0], + message = '[' + (module ? module + ':' : '') + code + '] ', + template = templateArgs[1], + paramPrefix, i; - message = prefix + template.replace(/\{\d+\}/g, function(match) { - var index = +match.slice(1, -1), arg; + message += template.replace(/\{\d+\}/g, function(match) { + var index = +match.slice(1, -1), + shiftedIndex = index + SKIP_INDEXES; - if (index + 2 < templateArgs.length) { - return toDebugString(templateArgs[index + 2]); + if (shiftedIndex < templateArgs.length) { + return toDebugString(templateArgs[shiftedIndex]); } + return match; }); - message = message + '\nhttp://errors.angularjs.org/1.3.13/' + + message += '\nhttp://errors.angularjs.org/1.4.3/' + (module ? module + '/' : '') + code; - for (i = 2; i < arguments.length; i++) { - message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' + - encodeURIComponent(toDebugString(arguments[i])); + + for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { + message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' + + encodeURIComponent(toDebugString(templateArgs[i])); } + return new ErrorConstructor(message); }; } @@ -86,20 +91,21 @@ function minErr(module, ErrorConstructor) { nodeName_: true, isArrayLike: true, forEach: true, - sortedKeys: true, forEachSorted: true, reverseParams: true, nextUid: true, setHashKey: true, extend: true, - int: true, + toInt: true, inherit: true, + merge: true, noop: true, identity: true, valueFn: true, isUndefined: true, isDefined: true, isObject: true, + isBlankObject: true, isString: true, isNumber: true, isDate: true, @@ -123,12 +129,15 @@ function minErr(module, ErrorConstructor) { shallowCopy: true, equals: true, csp: true, + jq: true, concat: true, sliceArgs: true, bind: true, toJsonReplacer: true, toJson: true, fromJson: true, + convertTimezoneToLocal: true, + timezoneToOffset: true, startingTag: true, tryDecodeURIComponent: true, parseKeyValue: true, @@ -149,6 +158,7 @@ function minErr(module, ErrorConstructor) { createMap: true, NODE_TYPE_ELEMENT: true, + NODE_TYPE_ATTRIBUTE: true, NODE_TYPE_TEXT: true, NODE_TYPE_COMMENT: true, NODE_TYPE_DOCUMENT: true, @@ -235,6 +245,7 @@ var splice = [].splice, push = [].push, toString = Object.prototype.toString, + getPrototypeOf = Object.getPrototypeOf, ngMinErr = minErr('ng'), /** @name angular */ @@ -260,7 +271,9 @@ function isArrayLike(obj) { return false; } - var length = obj.length; + // Support: iOS 8.2 (not reproducible in simulator) + // "length" in obj used to prevent JIT error (gh-11508) + var length = "length" in Object(obj) && obj.length; if (obj.nodeType === NODE_TYPE_ELEMENT && length) { return true; @@ -325,23 +338,32 @@ function forEach(obj, iterator, context) { } } else if (obj.forEach && obj.forEach !== forEach) { obj.forEach(iterator, context, obj); - } else { + } else if (isBlankObject(obj)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in obj) { + iterator.call(context, obj[key], key, obj); + } + } else if (typeof obj.hasOwnProperty === 'function') { + // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed for (key in obj) { if (obj.hasOwnProperty(key)) { iterator.call(context, obj[key], key, obj); } } + } else { + // Slow path for objects which do not have a method `hasOwnProperty` + for (key in obj) { + if (hasOwnProperty.call(obj, key)) { + iterator.call(context, obj[key], key, obj); + } + } } } return obj; } -function sortedKeys(obj) { - return Object.keys(obj).sort(); -} - function forEachSorted(obj, iterator, context) { - var keys = sortedKeys(obj); + var keys = Object.keys(obj).sort(); for (var i = 0; i < keys.length; i++) { iterator.call(context, obj[keys[i]], keys[i]); } @@ -386,6 +408,35 @@ function setHashKey(obj, h) { } } + +function baseExtend(dst, objs, deep) { + var h = dst.$$hashKey; + + for (var i = 0, ii = objs.length; i < ii; ++i) { + var obj = objs[i]; + if (!isObject(obj) && !isFunction(obj)) continue; + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + var src = obj[key]; + + if (deep && isObject(src)) { + if (isDate(src)) { + dst[key] = new Date(src.valueOf()); + } else { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [src], true); + } + } else { + dst[key] = src; + } + } + } + + setHashKey(dst, h); + return dst; +} + /** * @ngdoc function * @name angular.extend @@ -396,31 +447,44 @@ function setHashKey(obj, h) { * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. - * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy). + * + * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use + * {@link angular.merge} for this. * * @param {Object} dst Destination object. * @param {...Object} src Source object(s). * @returns {Object} Reference to `dst`. */ function extend(dst) { - var h = dst.$$hashKey; + return baseExtend(dst, slice.call(arguments, 1), false); +} - for (var i = 1, ii = arguments.length; i < ii; i++) { - var obj = arguments[i]; - if (obj) { - var keys = Object.keys(obj); - for (var j = 0, jj = keys.length; j < jj; j++) { - var key = keys[j]; - dst[key] = obj[key]; - } - } - } - setHashKey(dst, h); - return dst; +/** +* @ngdoc function +* @name angular.merge +* @module ng +* @kind function +* +* @description +* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s) +* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so +* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`. +* +* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source +* objects, performing a deep copy. +* +* @param {Object} dst Destination object. +* @param {...Object} src Source object(s). +* @returns {Object} Reference to `dst`. +*/ +function merge(dst) { + return baseExtend(dst, slice.call(arguments, 1), true); } -function int(str) { + + +function toInt(str) { return parseInt(str, 10); } @@ -473,6 +537,11 @@ identity.$inject = []; function valueFn(value) {return function() {return value;};} +function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; +} + + /** * @ngdoc function * @name angular.isUndefined @@ -522,6 +591,16 @@ function isObject(value) { } +/** + * Determine if a value is an object with a null prototype + * + * @returns {boolean} True if `value` is an `Object` with a null prototype + */ +function isBlankObject(value) { + return value !== null && typeof value === 'object' && !getPrototypeOf(value); +} + + /** * @ngdoc function * @name angular.isString @@ -546,6 +625,12 @@ function isString(value) {return typeof value === 'string';} * @description * Determines if a reference is a `Number`. * + * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`. + * + * If you wish to exclude these then you can use the native + * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) + * method. + * * @param {*} value Reference to check. * @returns {boolean} True if `value` is a `Number`. */ @@ -652,6 +737,12 @@ function isPromiseLike(obj) { } +var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; +function isTypedArray(value) { + return TYPED_ARRAY_REGEXP.test(toString.call(value)); +} + + var trim = function(value) { return isString(value) ? value.trim() : value; }; @@ -689,8 +780,9 @@ function isElement(node) { */ function makeMap(str) { var obj = {}, items = str.split(","), i; - for (i = 0; i < items.length; i++) + for (i = 0; i < items.length; i++) { obj[items[i]] = true; + } return obj; } @@ -705,9 +797,10 @@ function includes(array, obj) { function arrayRemove(array, value) { var index = array.indexOf(value); - if (index >= 0) + if (index >= 0) { array.splice(index, 1); - return value; + } + return index; } /** @@ -773,20 +866,40 @@ function copy(source, destination, stackSource, stackDest) { throw ngMinErr('cpws', "Can't copy! Making copies of Window or Scope instances is not supported."); } + if (isTypedArray(destination)) { + throw ngMinErr('cpta', + "Can't copy! TypedArray destination cannot be mutated."); + } if (!destination) { destination = source; - if (source) { + if (isObject(source)) { + var index; + if (stackSource && (index = stackSource.indexOf(source)) !== -1) { + return stackDest[index]; + } + + // TypedArray, Date and RegExp have specific copy functionality and must be + // pushed onto the stack before returning. + // Array and other objects create the base object and recurse to copy child + // objects. The array/object will be pushed onto the stack when recursed. if (isArray(source)) { - destination = copy(source, [], stackSource, stackDest); + return copy(source, [], stackSource, stackDest); + } else if (isTypedArray(source)) { + destination = new source.constructor(source); } else if (isDate(source)) { destination = new Date(source.getTime()); } else if (isRegExp(source)) { destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); destination.lastIndex = source.lastIndex; - } else if (isObject(source)) { - var emptyObject = Object.create(Object.getPrototypeOf(source)); - destination = copy(source, emptyObject, stackSource, stackDest); + } else { + var emptyObject = Object.create(getPrototypeOf(source)); + return copy(source, emptyObject, stackSource, stackDest); + } + + if (stackDest) { + stackSource.push(source); + stackDest.push(destination); } } } else { @@ -797,23 +910,15 @@ function copy(source, destination, stackSource, stackDest) { stackDest = stackDest || []; if (isObject(source)) { - var index = stackSource.indexOf(source); - if (index !== -1) return stackDest[index]; - stackSource.push(source); stackDest.push(destination); } - var result; + var result, key; if (isArray(source)) { destination.length = 0; for (var i = 0; i < source.length; i++) { - result = copy(source[i], null, stackSource, stackDest); - if (isObject(source[i])) { - stackSource.push(source[i]); - stackDest.push(result); - } - destination.push(result); + destination.push(copy(source[i], null, stackSource, stackDest)); } } else { var h = destination.$$hashKey; @@ -824,19 +929,28 @@ function copy(source, destination, stackSource, stackDest) { delete destination[key]; }); } - for (var key in source) { - if (source.hasOwnProperty(key)) { - result = copy(source[key], null, stackSource, stackDest); - if (isObject(source[key])) { - stackSource.push(source[key]); - stackDest.push(result); + if (isBlankObject(source)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in source) { + destination[key] = copy(source[key], null, stackSource, stackDest); + } + } else if (source && typeof source.hasOwnProperty === 'function') { + // Slow path, which must rely on hasOwnProperty + for (key in source) { + if (source.hasOwnProperty(key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); + } + } + } else { + // Slowest path --- hasOwnProperty can't be called as a method + for (key in source) { + if (hasOwnProperty.call(source, key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); } - destination[key] = result; } } setHashKey(destination,h); } - } return destination; } @@ -914,18 +1028,19 @@ function equals(o1, o2) { } else if (isDate(o1)) { if (!isDate(o2)) return false; return equals(o1.getTime(), o2.getTime()); - } else if (isRegExp(o1) && isRegExp(o2)) { - return o1.toString() == o2.toString(); + } else if (isRegExp(o1)) { + return isRegExp(o2) ? o1.toString() == o2.toString() : false; } else { - if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false; - keySet = {}; + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || + isArray(o2) || isDate(o2) || isRegExp(o2)) return false; + keySet = createMap(); for (key in o1) { if (key.charAt(0) === '$' || isFunction(o1[key])) continue; if (!equals(o1[key], o2[key])) return false; keySet[key] = true; } for (key in o2) { - if (!keySet.hasOwnProperty(key) && + if (!(key in keySet) && key.charAt(0) !== '$' && o2[key] !== undefined && !isFunction(o2[key])) return false; @@ -956,7 +1071,58 @@ var csp = function() { return (csp.isActive_ = active); }; +/** + * @ngdoc directive + * @module ng + * @name ngJq + * + * @element ANY + * @param {string=} ngJq the name of the library available under `window` + * to be used for angular.element + * @description + * Use this directive to force the angular.element library. This should be + * used to force either jqLite by leaving ng-jq blank or setting the name of + * the jquery variable under window (eg. jQuery). + * + * Since angular looks for this directive when it is loaded (doesn't wait for the + * DOMContentLoaded event), it must be placed on an element that comes before the script + * which loads angular. Also, only the first instance of `ng-jq` will be used and all + * others ignored. + * + * @example + * This example shows how to force jqLite using the `ngJq` directive to the `html` tag. + ```html + <!doctype html> + <html ng-app ng-jq> + ... + ... + </html> + ``` + * @example + * This example shows how to use a jQuery based library of a different name. + * The library name must be available at the top most 'window'. + ```html + <!doctype html> + <html ng-app ng-jq="jQueryLib"> + ... + ... + </html> + ``` + */ +var jq = function() { + if (isDefined(jq.name_)) return jq.name_; + var el; + var i, ii = ngAttrPrefixes.length, prefix, name; + for (i = 0; i < ii; ++i) { + prefix = ngAttrPrefixes[i]; + if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { + name = el.getAttribute(prefix + 'jq'); + break; + } + } + return (jq.name_ = name); +}; function concat(array1, array2, index) { return array1.concat(slice.call(array2, index)); @@ -1035,8 +1201,8 @@ function toJsonReplacer(key, value) { * stripped since angular uses this notation internally. * * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. - * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace. - * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2). + * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace. + * If set to an integer, the JSON output will contain that many spaces per indentation. * @returns {string|undefined} JSON-ified string representing `obj`. */ function toJson(obj, pretty) { @@ -1067,6 +1233,26 @@ function fromJson(json) { } +function timezoneToOffset(timezone, fallback) { + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; +} + + +function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; +} + + +function convertTimezoneToLocal(date, timezone, reverse) { + reverse = reverse ? -1 : 1; + var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); +} + + /** * @returns {string} Returns the string representation of the element. */ @@ -1195,10 +1381,9 @@ var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; function getNgAttribute(element, ngAttr) { var attr, i, ii = ngAttrPrefixes.length; - element = jqLite(element); for (i = 0; i < ii; ++i) { attr = ngAttrPrefixes[i] + ngAttr; - if (isString(attr = element.attr(attr))) { + if (isString(attr = element.getAttribute(attr))) { return attr; } } @@ -1529,7 +1714,12 @@ function bindJQuery() { } // bind to jQuery if present; - jQuery = window.jQuery; + var jqName = jq(); + jQuery = window.jQuery; // use default jQuery. + if (isDefined(jqName)) { // `ngJq` present + jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`. + } + // Use jQuery if it exists with proper functionality, otherwise default to us. // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older @@ -1668,6 +1858,7 @@ function createMap() { } var NODE_TYPE_ELEMENT = 1; +var NODE_TYPE_ATTRIBUTE = 2; var NODE_TYPE_TEXT = 3; var NODE_TYPE_COMMENT = 8; var NODE_TYPE_DOCUMENT = 9; @@ -1819,7 +2010,7 @@ function setupModuleLoader(window) { * @description * See {@link auto.$provide#provider $provide.provider()}. */ - provider: invokeLater('$provide', 'provider'), + provider: invokeLaterAndSetModuleName('$provide', 'provider'), /** * @ngdoc method @@ -1830,7 +2021,7 @@ function setupModuleLoader(window) { * @description * See {@link auto.$provide#factory $provide.factory()}. */ - factory: invokeLater('$provide', 'factory'), + factory: invokeLaterAndSetModuleName('$provide', 'factory'), /** * @ngdoc method @@ -1841,7 +2032,7 @@ function setupModuleLoader(window) { * @description * See {@link auto.$provide#service $provide.service()}. */ - service: invokeLater('$provide', 'service'), + service: invokeLaterAndSetModuleName('$provide', 'service'), /** * @ngdoc method @@ -1866,6 +2057,18 @@ function setupModuleLoader(window) { */ constant: invokeLater('$provide', 'constant', 'unshift'), + /** + * @ngdoc method + * @name angular.Module#decorator + * @module ng + * @param {string} The name of the service to decorate. + * @param {Function} This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. + * @description + * See {@link auto.$provide#decorator $provide.decorator()}. + */ + decorator: invokeLaterAndSetModuleName('$provide', 'decorator'), + /** * @ngdoc method * @name angular.Module#animation @@ -1879,7 +2082,7 @@ function setupModuleLoader(window) { * * * Defines an animation hook that can be later used with - * {@link ngAnimate.$animate $animate} service and directives that use this service. + * {@link $animate $animate} service and directives that use this service. * * ```js * module.animation('.animation-name', function($inject1, $inject2) { @@ -1898,18 +2101,25 @@ function setupModuleLoader(window) { * See {@link ng.$animateProvider#register $animateProvider.register()} and * {@link ngAnimate ngAnimate module} for more information. */ - animation: invokeLater('$animateProvider', 'register'), + animation: invokeLaterAndSetModuleName('$animateProvider', 'register'), /** * @ngdoc method * @name angular.Module#filter * @module ng - * @param {string} name Filter name. + * @param {string} name Filter name - this must be a valid angular expression identifier * @param {Function} filterFactory Factory function for creating new instance of filter. * @description * See {@link ng.$filterProvider#register $filterProvider.register()}. + * + * <div class="alert alert-warning"> + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + * </div> */ - filter: invokeLater('$filterProvider', 'register'), + filter: invokeLaterAndSetModuleName('$filterProvider', 'register'), /** * @ngdoc method @@ -1921,7 +2131,7 @@ function setupModuleLoader(window) { * @description * See {@link ng.$controllerProvider#register $controllerProvider.register()}. */ - controller: invokeLater('$controllerProvider', 'register'), + controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'), /** * @ngdoc method @@ -1934,7 +2144,7 @@ function setupModuleLoader(window) { * @description * See {@link ng.$compileProvider#directive $compileProvider.directive()}. */ - directive: invokeLater('$compileProvider', 'directive'), + directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'), /** * @ngdoc method @@ -1984,6 +2194,19 @@ function setupModuleLoader(window) { return moduleInstance; }; } + + /** + * @param {string} provider + * @param {string} method + * @returns {angular.Module} + */ + function invokeLaterAndSetModuleName(provider, method) { + return function(recipeName, factoryFunction) { + if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; + invokeQueue.push([provider, method, arguments]); + return moduleInstance; + }; + } }); }; }); @@ -2075,6 +2298,8 @@ function toDebugString(obj) { $AnchorScrollProvider, $AnimateProvider, + $$CoreAnimateQueueProvider, + $$CoreAnimateRunnerProvider, $BrowserProvider, $CacheFactoryProvider, $ControllerProvider, @@ -2083,7 +2308,10 @@ function toDebugString(obj) { $FilterProvider, $InterpolateProvider, $IntervalProvider, + $$HashMapProvider, $HttpProvider, + $HttpParamSerializerProvider, + $HttpParamSerializerJQLikeProvider, $HttpBackendProvider, $LocationProvider, $LogProvider, @@ -2100,9 +2328,9 @@ function toDebugString(obj) { $$TestabilityProvider, $TimeoutProvider, $$RAFProvider, - $$AsyncCallbackProvider, $WindowProvider, - $$jqLiteProvider + $$jqLiteProvider, + $$CookieReaderProvider */ @@ -2121,11 +2349,11 @@ function toDebugString(obj) { * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". */ var version = { - full: '1.3.13', // all of these placeholder strings will be replaced by grunt's + full: '1.4.3', // all of these placeholder strings will be replaced by grunt's major: 1, // package task - minor: 3, - dot: 13, - codeName: 'meticulous-riffleshuffle' + minor: 4, + dot: 3, + codeName: 'foam-acceleration' }; @@ -2134,6 +2362,7 @@ function publishExternalAPI(angular) { 'bootstrap': bootstrap, 'copy': copy, 'extend': extend, + 'merge': merge, 'equals': equals, 'element': jqLite, 'forEach': forEach, @@ -2230,6 +2459,8 @@ function publishExternalAPI(angular) { $provide.provider({ $anchorScroll: $AnchorScrollProvider, $animate: $AnimateProvider, + $$animateQueue: $$CoreAnimateQueueProvider, + $$AnimateRunner: $$CoreAnimateRunnerProvider, $browser: $BrowserProvider, $cacheFactory: $CacheFactoryProvider, $controller: $ControllerProvider, @@ -2239,6 +2470,8 @@ function publishExternalAPI(angular) { $interpolate: $InterpolateProvider, $interval: $IntervalProvider, $http: $HttpProvider, + $httpParamSerializer: $HttpParamSerializerProvider, + $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, $httpBackend: $HttpBackendProvider, $location: $LocationProvider, $log: $LogProvider, @@ -2255,13 +2488,25 @@ function publishExternalAPI(angular) { $timeout: $TimeoutProvider, $window: $WindowProvider, $$rAF: $$RAFProvider, - $$asyncCallback: $$AsyncCallbackProvider, - $$jqLite: $$jqLiteProvider + $$jqLite: $$jqLiteProvider, + $$HashMap: $$HashMapProvider, + $$cookieReader: $$CookieReaderProvider }); } ]); } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* global JQLitePrototype: true, addEventListenerFn: true, removeEventListenerFn: true, @@ -2290,7 +2535,7 @@ function publishExternalAPI(angular) { * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most * commonly needed functionality with the goal of having a very small footprint.</div> * - * To use jQuery, simply load it before `DOMContentLoaded` event fired. + * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. * * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or * jqLite; they are never raw DOM references.</div> @@ -2306,7 +2551,7 @@ function publishExternalAPI(angular) { * - [`children()`](http://api.jquery.com/children/) - Does not support selectors * - [`clone()`](http://api.jquery.com/clone/) * - [`contents()`](http://api.jquery.com/contents/) - * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()` + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'. * - [`data()`](http://api.jquery.com/data/) * - [`detach()`](http://api.jquery.com/detach/) * - [`empty()`](http://api.jquery.com/empty/) @@ -2433,6 +2678,13 @@ function jqLiteAcceptsData(node) { return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; } +function jqLiteHasData(node) { + for (var key in jqCache[node.ng339]) { + return true; + } + return false; +} + function jqLiteBuildFragment(html, context) { var tmp, tag, wrap, fragment = context.createDocumentFragment(), @@ -2807,7 +3059,8 @@ function getAliasedAttrName(element, name) { forEach({ data: jqLiteData, - removeData: jqLiteRemoveData + removeData: jqLiteRemoveData, + hasData: jqLiteHasData }, function(fn, name) { JQLite[name] = fn; }); @@ -2849,6 +3102,10 @@ forEach({ }, attr: function(element, name, value) { + var nodeType = element.nodeType; + if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { + return; + } var lowercasedName = lowercase(name); if (BOOLEAN_ATTR[lowercasedName]) { if (isDefined(value)) { @@ -3113,8 +3370,9 @@ forEach({ children: function(element) { var children = []; forEach(element.childNodes, function(element) { - if (element.nodeType === NODE_TYPE_ELEMENT) + if (element.nodeType === NODE_TYPE_ELEMENT) { children.push(element); + } }); return children; }, @@ -3360,6 +3618,12 @@ HashMap.prototype = { } }; +var $$HashMapProvider = [function() { + this.$get = [function() { + return HashMap; + }]; +}]; + /** * @ngdoc function * @module ng @@ -3539,7 +3803,7 @@ function annotate(fn, strictDi, name) { * Return an instance of the service. * * @param {string} name The name of the instance to retrieve. - * @param {string} caller An optional string to provide the origin of the function call for error messages. + * @param {string=} caller An optional string to provide the origin of the function call for error messages. * @return {*} The instance. */ @@ -3550,8 +3814,8 @@ function annotate(fn, strictDi, name) { * @description * Invoke the method and supply the method arguments from the `$injector`. * - * @param {!Function} fn The function to invoke. Function parameters are injected according to the - * {@link guide/di $inject Annotation} rules. + * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are + * injected according to the {@link guide/di $inject Annotation} rules. * @param {Object=} self The `this` for the invoked method. * @param {Object=} locals Optional object. If preset then any argument names are read from this * object first, before the `$injector` is consulted. @@ -3818,8 +4082,8 @@ function annotate(fn, strictDi, name) { * configure your service in a provider. * * @param {string} name The name of the instance. - * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand - * for `$provide.provider(name, {$get: $getFn})`. + * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation. + * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`. * @returns {Object} registered provider instance * * @example @@ -3854,7 +4118,8 @@ function annotate(fn, strictDi, name) { * as a type/class. * * @param {string} name The name of the instance. - * @param {Function} constructor A class (constructor function) that will be instantiated. + * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function) + * that will be instantiated. * @returns {Object} registered provider instance * * @example @@ -3953,7 +4218,7 @@ function annotate(fn, strictDi, name) { * object which replaces or wraps and delegates to the original service. * * @param {string} name The name of the service to decorate. - * @param {function()} decorator This function will be invoked when the service needs to be + * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be * instantiated and should return the decorated service instance. The function is called using * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. * Local injection arguments: @@ -4004,7 +4269,7 @@ function createInjector(modulesToLoad, strictDi) { })); - forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); }); + forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); }); return instanceInjector; @@ -4247,9 +4512,10 @@ function $AnchorScrollProvider() { * @requires $rootScope * * @description - * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and - * scrolls to the related element, according to the rules specified in the - * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). + * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the + * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified + * in the + * [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). * * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to * match any anchor whenever it changes. This can be disabled by calling @@ -4258,6 +4524,9 @@ function $AnchorScrollProvider() { * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a * vertical scroll-offset (either fixed or dynamic). * + * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of + * {@link ng.$location#hash $location.hash()} will be used. + * * @property {(number|function|jqLite)} yOffset * If set, specifies a vertical scroll-offset. This is often useful when there are fixed * positioned elements at the top of the page, such as navbars, headers etc. @@ -4441,8 +4710,9 @@ function $AnchorScrollProvider() { } } - function scroll() { - var hash = $location.hash(), elm; + function scroll(hash) { + hash = isString(hash) ? hash : $location.hash(); + var elm; // empty hash, scroll to the top of the page if (!hash) scrollTo(null); @@ -4476,6 +4746,168 @@ function $AnchorScrollProvider() { } var $animateMinErr = minErr('$animate'); +var ELEMENT_NODE = 1; +var NG_ANIMATE_CLASSNAME = 'ng-animate'; + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function extractElementNode(element) { + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType === ELEMENT_NODE) { + return elm; + } + } +} + +function splitClasses(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + // Use createMap() to prevent class assumptions involving property names in + // Object.prototype + var obj = createMap(); + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; +} + +// if any other type of options value besides an Object value is +// passed into the $animate.method() animation then this helper code +// will be run which will ignore it. While this patch is not the +// greatest solution to this, a lot of existing plugins depend on +// $animate to either call the callback (< 1.2) or return a promise +// that can be changed. This helper function ensures that the options +// are wiped clean incase a callback function is provided. +function prepareAnimateOptions(options) { + return isObject(options) + ? options + : {}; +} + +var $$CoreAnimateRunnerProvider = function() { + this.$get = ['$q', '$$rAF', function($q, $$rAF) { + function AnimateRunner() {} + AnimateRunner.all = noop; + AnimateRunner.chain = noop; + AnimateRunner.prototype = { + end: noop, + cancel: noop, + resume: noop, + pause: noop, + complete: noop, + then: function(pass, fail) { + return $q(function(resolve) { + $$rAF(function() { + resolve(); + }); + }).then(pass, fail); + } + }; + return AnimateRunner; + }]; +}; + +// this is prefixed with Core since it conflicts with +// the animateQueueProvider defined in ngAnimate/animateQueue.js +var $$CoreAnimateQueueProvider = function() { + var postDigestQueue = new HashMap(); + var postDigestElements = []; + + this.$get = ['$$AnimateRunner', '$rootScope', + function($$AnimateRunner, $rootScope) { + return { + enabled: noop, + on: noop, + off: noop, + pin: noop, + + push: function(element, event, options, domOperation) { + domOperation && domOperation(); + + options = options || {}; + options.from && element.css(options.from); + options.to && element.css(options.to); + + if (options.addClass || options.removeClass) { + addRemoveClassesPostDigest(element, options.addClass, options.removeClass); + } + + return new $$AnimateRunner(); // jshint ignore:line + } + }; + + function addRemoveClassesPostDigest(element, add, remove) { + var data = postDigestQueue.get(element); + var classVal; + + if (!data) { + postDigestQueue.put(element, data = {}); + postDigestElements.push(element); + } + + if (add) { + forEach(add.split(' '), function(className) { + if (className) { + data[className] = true; + } + }); + } + + if (remove) { + forEach(remove.split(' '), function(className) { + if (className) { + data[className] = false; + } + }); + } + + if (postDigestElements.length > 1) return; + + $rootScope.$$postDigest(function() { + forEach(postDigestElements, function(element) { + var data = postDigestQueue.get(element); + if (data) { + var existing = splitClasses(element.attr('class')); + var toAdd = ''; + var toRemove = ''; + forEach(data, function(status, className) { + var hasClass = !!existing[className]; + if (status !== hasClass) { + if (status) { + toAdd += (toAdd.length ? ' ' : '') + className; + } else { + toRemove += (toRemove.length ? ' ' : '') + className; + } + } + }); + + forEach(element, function(elm) { + toAdd && jqLiteAddClass(elm, toAdd); + toRemove && jqLiteRemoveClass(elm, toRemove); + }); + postDigestQueue.remove(element); + } + }); + + postDigestElements.length = 0; + }); + } + }]; +}; /** * @ngdoc provider @@ -4483,20 +4915,18 @@ var $animateMinErr = minErr('$animate'); * * @description * Default implementation of $animate that doesn't perform any animations, instead just - * synchronously performs DOM - * updates and calls done() callbacks. + * synchronously performs DOM updates and resolves the returned runner promise. * - * In order to enable animations the ngAnimate module has to be loaded. + * In order to enable animations the `ngAnimate` module has to be loaded. * - * To see the functional implementation check out src/ngAnimate/animate.js + * To see the functional implementation check out `src/ngAnimate/animate.js`. */ var $AnimateProvider = ['$provide', function($provide) { + var provider = this; + this.$$registeredAnimations = Object.create(null); - this.$$selectors = {}; - - - /** + /** * @ngdoc method * @name $animateProvider#register * @@ -4505,33 +4935,43 @@ var $AnimateProvider = ['$provide', function($provide) { * animation object which contains callback functions for each event that is expected to be * animated. * - * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction` - * must be called once the element animation is complete. If a function is returned then the - * animation service will use this function to cancel the animation whenever a cancel event is - * triggered. + * * `eventFn`: `function(element, ... , doneFunction, options)` + * The element to animate, the `doneFunction` and the options fed into the animation. Depending + * on the type of animation additional arguments will be injected into the animation function. The + * list below explains the function signatures for the different animation methods: * + * - setClass: function(element, addedClasses, removedClasses, doneFunction, options) + * - addClass: function(element, addedClasses, doneFunction, options) + * - removeClass: function(element, removedClasses, doneFunction, options) + * - enter, leave, move: function(element, doneFunction, options) + * - animate: function(element, fromStyles, toStyles, doneFunction, options) + * + * Make sure to trigger the `doneFunction` once the animation is fully complete. * * ```js * return { - * eventFn : function(element, done) { - * //code to run the animation - * //once complete, then run done() - * return function cancellationFunction() { - * //code to cancel the animation - * } - * } - * } + * //enter, leave, move signature + * eventFn : function(element, done, options) { + * //code to run the animation + * //once complete, then run done() + * return function endFunction(wasCancelled) { + * //code to cancel the animation + * } + * } + * } * ``` * - * @param {string} name The name of the animation. + * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to). * @param {Function} factory The factory function that will be executed to return the animation * object. */ this.register = function(name, factory) { + if (name && name.charAt(0) !== '.') { + throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name); + } + var key = name + '-animation'; - if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel', - "Expecting class selector starting with '.' got '{0}'.", name); - this.$$selectors[name.substr(1)] = key; + provider.$$registeredAnimations[name.substr(1)] = key; $provide.factory(key, factory); }; @@ -4542,8 +4982,8 @@ var $AnimateProvider = ['$provide', function($provide) { * @description * Sets and/or returns the CSS class regular expression that is checked when performing * an animation. Upon bootstrap the classNameFilter value is not set at all and will - * therefore enable $animate to attempt to perform an animation on any element. - * When setting the classNameFilter value, animations will only be performed on elements + * therefore enable $animate to attempt to perform an animation on any element that is triggered. + * When setting the `classNameFilter` value, animations will only be performed on elements * that successfully match the filter expression. This in turn can boost performance * for low-powered devices as well as applications containing a lot of structural operations. * @param {RegExp=} expression The className expression which will be checked against all animations @@ -4552,295 +4992,344 @@ var $AnimateProvider = ['$provide', function($provide) { this.classNameFilter = function(expression) { if (arguments.length === 1) { this.$$classNameFilter = (expression instanceof RegExp) ? expression : null; - } - return this.$$classNameFilter; - }; - - this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) { - - var currentDefer; - - function runAnimationPostDigest(fn) { - var cancelFn, defer = $$q.defer(); - defer.promise.$$cancelFn = function ngAnimateMaybeCancel() { - cancelFn && cancelFn(); - }; - - $rootScope.$$postDigest(function ngAnimatePostDigest() { - cancelFn = fn(function ngAnimateNotifyComplete() { - defer.resolve(); - }); - }); - - return defer.promise; - } - - function resolveElementClasses(element, classes) { - var toAdd = [], toRemove = []; - - var hasClasses = createMap(); - forEach((element.attr('class') || '').split(/\s+/), function(className) { - hasClasses[className] = true; - }); + if (this.$$classNameFilter) { + var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)"); + if (reservedRegex.test(this.$$classNameFilter.toString())) { + throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME); - forEach(classes, function(status, className) { - var hasClass = hasClasses[className]; - - // If the most recent class manipulation (via $animate) was to remove the class, and the - // element currently has the class, the class is scheduled for removal. Otherwise, if - // the most recent class manipulation (via $animate) was to add the class, and the - // element does not currently have the class, the class is scheduled to be added. - if (status === false && hasClass) { - toRemove.push(className); - } else if (status === true && !hasClass) { - toAdd.push(className); } - }); - - return (toAdd.length + toRemove.length) > 0 && - [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null]; - } - - function cachedClassManipulation(cache, classes, op) { - for (var i=0, ii = classes.length; i < ii; ++i) { - var className = classes[i]; - cache[className] = op; - } - } - - function asyncPromise() { - // only serve one instance of a promise in order to save CPU cycles - if (!currentDefer) { - currentDefer = $$q.defer(); - $$asyncCallback(function() { - currentDefer.resolve(); - currentDefer = null; - }); } - return currentDefer.promise; } + return this.$$classNameFilter; + }; - function applyStyles(element, options) { - if (angular.isObject(options)) { - var styles = extend(options.from || {}, options.to || {}); - element.css(styles); + this.$get = ['$$animateQueue', function($$animateQueue) { + function domInsert(element, parentElement, afterElement) { + // if for some reason the previous element was removed + // from the dom sometime before this code runs then let's + // just stick to using the parent element as the anchor + if (afterElement) { + var afterNode = extractElementNode(afterElement); + if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { + afterElement = null; + } } + afterElement ? afterElement.after(element) : parentElement.prepend(element); } /** - * * @ngdoc service * @name $animate - * @description The $animate service provides rudimentary DOM manipulation functions to - * insert, remove and move elements within the DOM, as well as adding and removing classes. - * This service is the core service used by the ngAnimate $animator service which provides - * high-level animation hooks for CSS and JavaScript. + * @description The $animate service exposes a series of DOM utility methods that provide support + * for animation hooks. The default behavior is the application of DOM operations, however, + * when an animation is detected (and animations are enabled), $animate will do the heavy lifting + * to ensure that animation runs with the triggered DOM operation. * - * $animate is available in the AngularJS core, however, the ngAnimate module must be included - * to enable full out animation support. Otherwise, $animate will only perform simple DOM - * manipulation operations. + * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't + * included and only when it is active then the animation hooks that `$animate` triggers will be + * functional. Once active then all structural `ng-` directives will trigger animations as they perform + * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`, + * `ngShow`, `ngHide` and `ngMessages` also provide support for animations. * - * To learn more about enabling animation support, click here to visit the {@link ngAnimate - * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service - * page}. + * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives. + * + * To learn more about enabling animation support, click here to visit the + * {@link ngAnimate ngAnimate module page}. */ return { - animate: function(element, from, to) { - applyStyles(element, { from: from, to: to }); - return asyncPromise(); - }, + // we don't call it directly since non-existant arguments may + // be interpreted as null within the sub enabled function /** * * @ngdoc method - * @name $animate#enter + * @name $animate#on * @kind function - * @description Inserts the element into the DOM either after the `after` element or - * as the first child within the `parent` element. When the function is called a promise - * is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will be inserted into the DOM - * @param {DOMElement} parent the parent element which will append the element as - * a child (if the after element is not present) - * @param {DOMElement} after the sibling element which will append the element - * after itself - * @param {object=} options an optional collection of styles that will be applied to the element. - * @return {Promise} the animation callback promise + * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...) + * has fired on the given element or among any of its children. Once the listener is fired, the provided callback + * is fired with the following params: + * + * ```js + * $animate.on('enter', container, + * function callback(element, phase) { + * // cool we detected an enter animation within the container + * } + * ); + * ``` + * + * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself + * as well as among its children + * @param {Function} callback the callback function that will be fired when the listener is triggered + * + * The arguments present in the callback function are: + * * `element` - The captured DOM element that the animation was fired on. + * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends). */ - enter: function(element, parent, after, options) { - applyStyles(element, options); - after ? after.after(element) - : parent.prepend(element); - return asyncPromise(); - }, + on: $$animateQueue.on, /** * * @ngdoc method - * @name $animate#leave + * @name $animate#off * @kind function - * @description Removes the element from the DOM. When the function is called a promise - * is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will be removed from the DOM - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise + * @description Deregisters an event listener based on the event which has been associated with the provided element. This method + * can be used in three different ways depending on the arguments: + * + * ```js + * // remove all the animation event listeners listening for `enter` + * $animate.off('enter'); + * + * // remove all the animation event listeners listening for `enter` on the given element and its children + * $animate.off('enter', container); + * + * // remove the event listener function provided by `listenerFn` that is set + * // to listen for `enter` on the given `element` as well as its children + * $animate.off('enter', container, callback); + * ``` + * + * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement=} container the container element the event listener was placed on + * @param {Function=} callback the callback function that was registered as the listener */ - leave: function(element, options) { - element.remove(); - return asyncPromise(); - }, + off: $$animateQueue.off, /** - * * @ngdoc method - * @name $animate#move + * @name $animate#pin * @kind function - * @description Moves the position of the provided element within the DOM to be placed - * either after the `after` element or inside of the `parent` element. When the function - * is called a promise is returned that will be resolved at a later time. + * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists + * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the + * element despite being outside the realm of the application or within another application. Say for example if the application + * was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated + * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind + * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association. * - * @param {DOMElement} element the element which will be moved around within the - * DOM - * @param {DOMElement} parent the parent element where the element will be - * inserted into (if the after element is not present) - * @param {DOMElement} after the sibling element where the element will be - * positioned next to - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise + * Note that this feature is only active when the `ngAnimate` module is used. + * + * @param {DOMElement} element the external element that will be pinned + * @param {DOMElement} parentElement the host parent element that will be associated with the external element */ - move: function(element, parent, after, options) { - // Do not remove element before insert. Removing will cause data associated with the - // element to be dropped. Insert will implicitly do the remove. - return this.enter(element, parent, after, options); - }, + pin: $$animateQueue.pin, /** * * @ngdoc method - * @name $animate#addClass + * @name $animate#enabled * @kind function - * @description Adds the provided className CSS class value to the provided element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have the className value - * added to it - * @param {string} className the CSS class which will be added to the element - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise - */ - addClass: function(element, className, options) { - return this.setClass(element, className, [], options); - }, - - $$addClassImmediately: function(element, className, options) { - element = jqLite(element); - className = !isString(className) - ? (isArray(className) ? className.join(' ') : '') - : className; - forEach(element, function(element) { - jqLiteAddClass(element, className); - }); - applyStyles(element, options); - return asyncPromise(); + * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This + * function can be called in four ways: + * + * ```js + * // returns true or false + * $animate.enabled(); + * + * // changes the enabled state for all animations + * $animate.enabled(false); + * $animate.enabled(true); + * + * // returns true or false if animations are enabled for an element + * $animate.enabled(element); + * + * // changes the enabled state for an element and its children + * $animate.enabled(element, true); + * $animate.enabled(element, false); + * ``` + * + * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state + * @param {boolean=} enabled whether or not the animations will be enabled for the element + * + * @return {boolean} whether or not animations are enabled + */ + enabled: $$animateQueue.enabled, + + /** + * @ngdoc method + * @name $animate#cancel + * @kind function + * @description Cancels the provided animation. + * + * @param {Promise} animationPromise The animation promise that is returned when an animation is started. + */ + cancel: function(runner) { + runner.end && runner.end(); }, /** * * @ngdoc method - * @name $animate#removeClass + * @name $animate#enter * @kind function - * @description Removes the provided className CSS class value from the provided element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have the className value - * removed from it - * @param {string} className the CSS class which will be removed from the element - * @param {object=} options an optional collection of options that will be applied to the element. + * @description Inserts the element into the DOM either after the `after` element (if provided) or + * as the first child within the `parent` element and then triggers an animation. + * A promise is returned that will be resolved during the next digest once the animation + * has completed. + * + * @param {DOMElement} element the element which will be inserted into the DOM + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * * @return {Promise} the animation callback promise */ - removeClass: function(element, className, options) { - return this.setClass(element, [], className, options); + enter: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options)); + }, + + /** + * + * @ngdoc method + * @name $animate#move + * @kind function + * @description Inserts (moves) the element into its new position in the DOM either after + * the `after` element (if provided) or as the first child within the `parent` element + * and then triggers an animation. A promise is returned that will be resolved + * during the next digest once the animation has completed. + * + * @param {DOMElement} element the element which will be moved into the new DOM position + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + move: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'move', prepareAnimateOptions(options)); }, - $$removeClassImmediately: function(element, className, options) { - element = jqLite(element); - className = !isString(className) - ? (isArray(className) ? className.join(' ') : '') - : className; - forEach(element, function(element) { - jqLiteRemoveClass(element, className); + /** + * @ngdoc method + * @name $animate#leave + * @kind function + * @description Triggers an animation and then removes the element from the DOM. + * When the function is called a promise is returned that will be resolved during the next + * digest once the animation has completed. + * + * @param {DOMElement} element the element which will be removed from the DOM + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + leave: function(element, options) { + return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() { + element.remove(); }); - applyStyles(element, options); - return asyncPromise(); }, /** + * @ngdoc method + * @name $animate#addClass + * @kind function + * + * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon + * execution, the addClass operation will only be handled after the next digest and it will not trigger an + * animation if element already contains the CSS class or if the class is removed at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + addClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addclass, className); + return $$animateQueue.push(element, 'addClass', options); + }, + + /** + * @ngdoc method + * @name $animate#removeClass + * @kind function + * + * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon + * execution, the removeClass operation will only be handled after the next digest and it will not trigger an + * animation if element does not contain the CSS class or if the class is added at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element * + * @return {Promise} the animation callback promise + */ + removeClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.removeClass = mergeClasses(options.removeClass, className); + return $$animateQueue.push(element, 'removeClass', options); + }, + + /** * @ngdoc method * @name $animate#setClass * @kind function - * @description Adds and/or removes the given CSS classes to and from the element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have its CSS classes changed - * removed from it - * @param {string} add the CSS classes which will be added to the element - * @param {string} remove the CSS class which will be removed from the element - * @param {object=} options an optional collection of options that will be applied to the element. + * + * @description Performs both the addition and removal of a CSS classes on an element and (during the process) + * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and + * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has + * passed. Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * * @return {Promise} the animation callback promise */ setClass: function(element, add, remove, options) { - var self = this; - var STORAGE_KEY = '$$animateClasses'; - var createdCache = false; - element = jqLite(element); - - var cache = element.data(STORAGE_KEY); - if (!cache) { - cache = { - classes: {}, - options: options - }; - createdCache = true; - } else if (options && cache.options) { - cache.options = angular.extend(cache.options || {}, options); - } - - var classes = cache.classes; - - add = isArray(add) ? add : add.split(' '); - remove = isArray(remove) ? remove : remove.split(' '); - cachedClassManipulation(classes, add, true); - cachedClassManipulation(classes, remove, false); - - if (createdCache) { - cache.promise = runAnimationPostDigest(function(done) { - var cache = element.data(STORAGE_KEY); - element.removeData(STORAGE_KEY); - - // in the event that the element is removed before postDigest - // is run then the cache will be undefined and there will be - // no need anymore to add or remove and of the element classes - if (cache) { - var classes = resolveElementClasses(element, cache.classes); - if (classes) { - self.$$setClassImmediately(element, classes[0], classes[1], cache.options); - } - } - - done(); - }); - element.data(STORAGE_KEY, cache); - } - - return cache.promise; + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addClass, add); + options.removeClass = mergeClasses(options.removeClass, remove); + return $$animateQueue.push(element, 'setClass', options); }, - $$setClassImmediately: function(element, add, remove, options) { - add && this.$$addClassImmediately(element, add); - remove && this.$$removeClassImmediately(element, remove); - applyStyles(element, options); - return asyncPromise(); - }, + /** + * @ngdoc method + * @name $animate#animate + * @kind function + * + * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. + * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take + * on the provided styles. For example, if a transition animation is set for the given className then the provided from and + * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles + * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter). + * + * @param {DOMElement} element the element which the CSS styles will be applied to + * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. + * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation. + * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If + * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element. + * (Note that if no animation is detected then this value will not be appplied to the element.) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + animate: function(element, from, to, className, options) { + options = prepareAnimateOptions(options); + options.from = options.from ? extend(options.from, from) : from; + options.to = options.to ? extend(options.to, to) : to; - enabled: noop, - cancel: noop + className = className || 'ng-inline-animate'; + options.tempClasses = mergeClasses(options.tempClasses, className); + return $$animateQueue.push(element, 'animate', options); + } }; }]; }]; @@ -4919,7 +5408,7 @@ function Browser(window, document, $log, $sniffer) { function getHash(url) { var index = url.indexOf('#'); - return index === -1 ? '' : url.substr(index + 1); + return index === -1 ? '' : url.substr(index); } /** @@ -4929,11 +5418,6 @@ function Browser(window, document, $log, $sniffer) { * @param {function()} callback Function that will be called when no outstanding request */ self.notifyWhenNoOutstandingRequests = function(callback) { - // force browser to execute all pollFns - this is needed so that cookies and other pollers fire - // at some deterministic time in respect to the test runner's actions. Leaving things up to the - // regular poller would result in flaky tests. - forEach(pollFns, function(pollFn) { pollFn(); }); - if (outstandingRequestCount === 0) { callback(); } else { @@ -4941,44 +5425,6 @@ function Browser(window, document, $log, $sniffer) { } }; - ////////////////////////////////////////////////////////////// - // Poll Watcher API - ////////////////////////////////////////////////////////////// - var pollFns = [], - pollTimeout; - - /** - * @name $browser#addPollFn - * - * @param {function()} fn Poll function to add - * - * @description - * Adds a function to the list of functions that poller periodically executes, - * and starts polling if not started yet. - * - * @returns {function()} the added function - */ - self.addPollFn = function(fn) { - if (isUndefined(pollTimeout)) startPoller(100, setTimeout); - pollFns.push(fn); - return fn; - }; - - /** - * @param {number} interval How often should browser call poll functions (ms) - * @param {function()} setTimeout Reference to a real or fake `setTimeout` function. - * - * @description - * Configures the poller to run in the specified intervals, using the specified - * setTimeout fn and kicks it off. - */ - function startPoller(interval, setTimeout) { - (function check() { - forEach(pollFns, function(pollFn) { pollFn(); }); - pollTimeout = setTimeout(check, interval); - })(); - } - ////////////////////////////////////////////////////////////// // URL API ////////////////////////////////////////////////////////////// @@ -5046,7 +5492,7 @@ function Browser(window, document, $log, $sniffer) { // Do the assignment again so that those two variables are referentially identical. lastHistoryState = cachedState; } else { - if (!sameBase) { + if (!sameBase || reloadLocation) { reloadLocation = url; } if (replace) { @@ -5089,11 +5535,19 @@ function Browser(window, document, $log, $sniffer) { fireUrlChange(); } + function getCurrentState() { + try { + return history.state; + } catch (e) { + // MSIE can reportedly throw when there is no state (UNCONFIRMED). + } + } + // This variable should be used *only* inside the cacheState function. var lastCachedState = null; function cacheState() { // This should be the only place in $browser where `history.state` is read. - cachedState = window.history.state; + cachedState = getCurrentState(); cachedState = isUndefined(cachedState) ? null : cachedState; // Prevent callbacks fo fire twice if both hashchange & popstate were fired. @@ -5155,6 +5609,16 @@ function Browser(window, document, $log, $sniffer) { return callback; }; + /** + * @private + * Remove popstate and hashchange handler from window. + * + * NOTE: this api is intended for use only by $rootScope. + */ + self.$$applicationDestroyed = function() { + jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange); + }; + /** * Checks whether the url has changed outside of Angular. * Needs to be exported to be able to check for changes that have been done in sync, @@ -5180,89 +5644,6 @@ function Browser(window, document, $log, $sniffer) { return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; }; - ////////////////////////////////////////////////////////////// - // Cookies API - ////////////////////////////////////////////////////////////// - var lastCookies = {}; - var lastCookieString = ''; - var cookiePath = self.baseHref(); - - function safeDecodeURIComponent(str) { - try { - return decodeURIComponent(str); - } catch (e) { - return str; - } - } - - /** - * @name $browser#cookies - * - * @param {string=} name Cookie name - * @param {string=} value Cookie value - * - * @description - * The cookies method provides a 'private' low level access to browser cookies. - * It is not meant to be used directly, use the $cookie service instead. - * - * The return values vary depending on the arguments that the method was called with as follows: - * - * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify - * it - * - cookies(name, value) -> set name to value, if value is undefined delete the cookie - * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that - * way) - * - * @returns {Object} Hash of all cookies (if called without any parameter) - */ - self.cookies = function(name, value) { - var cookieLength, cookieArray, cookie, i, index; - - if (name) { - if (value === undefined) { - rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath + - ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; - } else { - if (isString(value)) { - cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + - ';path=' + cookiePath).length + 1; - - // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: - // - 300 cookies - // - 20 cookies per unique domain - // - 4096 bytes per cookie - if (cookieLength > 4096) { - $log.warn("Cookie '" + name + - "' possibly not set or overflowed because it was too large (" + - cookieLength + " > 4096 bytes)!"); - } - } - } - } else { - if (rawDocument.cookie !== lastCookieString) { - lastCookieString = rawDocument.cookie; - cookieArray = lastCookieString.split("; "); - lastCookies = {}; - - for (i = 0; i < cookieArray.length; i++) { - cookie = cookieArray[i]; - index = cookie.indexOf('='); - if (index > 0) { //ignore nameless cookies - name = safeDecodeURIComponent(cookie.substring(0, index)); - // the first value that is seen for a cookie is the most - // specific one. values for the same cookie name that - // follow are for less specific paths. - if (lastCookies[name] === undefined) { - lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); - } - } - } - } - return lastCookies; - } - }; - - /** * @name $browser#defer * @param {function()} fn A function, who's execution should be deferred. @@ -5477,13 +5858,13 @@ function $CacheFactoryProvider() { * @returns {*} the value stored. */ put: function(key, value) { + if (isUndefined(value)) return; if (capacity < Number.MAX_VALUE) { var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); refresh(lruEntry); } - if (isUndefined(value)) return; if (!(key in data)) size++; data[key] = value; @@ -5690,7 +6071,7 @@ function $CacheFactoryProvider() { * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, * element with ng-app attribute), otherwise the template will be ignored. * - * Adding via the $templateCache service: + * Adding via the `$templateCache` service: * * ```js * var myApp = angular.module('myApp', []); @@ -5718,6 +6099,17 @@ function $TemplateCacheProvider() { }]; } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! * * DOM-related variables: @@ -5782,7 +6174,8 @@ function $TemplateCacheProvider() { * templateNamespace: 'html', * scope: false, * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, - * controllerAs: 'stringAlias', + * controllerAs: 'stringIdentifier', + * bindToController: false, * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], * compile: function compile(tElement, tAttrs, transclude) { * return { @@ -5929,7 +6322,8 @@ function $TemplateCacheProvider() { * Require another directive and inject its controller as the fourth argument to the linking function. The * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the * injected argument will be an array in corresponding order. If no such directive can be - * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with: + * found, or if the directive does not have a controller, then an error is raised (unless no link function + * is specified, in which case error checking is skipped). The name can be prefixed with: * * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. @@ -5942,9 +6336,10 @@ function $TemplateCacheProvider() { * * * #### `controllerAs` - * Controller alias at the directive scope. An alias for the controller so it - * can be referenced at the directive template. The directive needs to define a scope for this - * configuration to be used. Useful in the case when directive is used as component. + * Identifier name for a reference to the controller in the directive's scope. + * This allows the controller to be referenced from the directive template. The directive + * needs to define a scope for this configuration to be used. Useful in the case when + * directive is used as component. * * * #### `restrict` @@ -6063,7 +6458,7 @@ function $TemplateCacheProvider() { * `templateUrl` declaration or manual compilation inside the compile function. * </div> * - * <div class="alert alert-error"> + * <div class="alert alert-danger"> * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it * e.g. does not know about the right outer scope. Please use the transclude function that is passed * to the link function instead. @@ -6100,9 +6495,18 @@ function $TemplateCacheProvider() { * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared * between all directive linking functions. * - * * `controller` - a controller instance - A controller instance if at least one directive on the - * element defines a controller. The controller is shared among all the directives, which allows - * the directives to use the controllers as a communication channel. + * * `controller` - the directive's required controller instance(s) - Instances are shared + * among all directives, which allows the directives to use the controllers as a communication + * channel. The exact value depends on the directive's `require` property: + * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one + * * `string`: the controller instance + * * `array`: array of controller instances + * + * If a required controller cannot be found, and it is optional, the instance is `null`, + * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown. + * + * Note that you can also require the directive's own controller - it will be made available like + * like any other controller. * * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. * This is the same as the `$transclude` @@ -6195,7 +6599,7 @@ function $TemplateCacheProvider() { * * <div class="alert alert-info"> * **Best Practice**: if you intend to add and remove transcluded content manually in your directive - * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it), + * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it), * then you are also responsible for calling `$destroy` on the transclusion scope. * </div> * @@ -6319,8 +6723,8 @@ function $TemplateCacheProvider() { }]); </script> <div ng-controller="GreeterController"> - <input ng-model="name"> <br> - <textarea ng-model="html"></textarea> <br> + <input ng-model="name"> <br/> + <textarea ng-model="html"></textarea> <br/> <div compile="html"></div> </div> </file> @@ -6342,7 +6746,7 @@ function $TemplateCacheProvider() { * @param {string|DOMElement} element Element or HTML string to compile into a template function. * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. * - * <div class="alert alert-error"> + * <div class="alert alert-danger"> * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it * e.g. will not use the right outer scope. Please pass the transclude function as a * `parentBoundTranscludeFn` to the link function instead. @@ -6357,7 +6761,7 @@ function $TemplateCacheProvider() { * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the * `template` and call the `cloneAttachFn` function allowing the caller to attach the * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is - * called as: <br> `cloneAttachFn(clonedElement, scope)` where: + * called as: <br/> `cloneAttachFn(clonedElement, scope)` where: * * * `clonedElement` - is a clone of the original `element` passed into the compiler. * * `scope` - is the current scope with which the linking function is working with. @@ -6430,7 +6834,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { // 'on' and be composed of only English letters. var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; - function parseIsolateBindings(scope, directiveName) { + function parseIsolateBindings(scope, directiveName, isController) { var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; var bindings = {}; @@ -6440,9 +6844,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!match) { throw $compileMinErr('iscp', - "Invalid isolate scope definition for directive '{0}'." + + "Invalid {3} for directive '{0}'." + " Definition: {... {1}: '{2}' ...}", - directiveName, scopeName, definition); + directiveName, scopeName, definition, + (isController ? "controller bindings definition" : + "isolate scope definition")); } bindings[scopeName] = { @@ -6456,6 +6862,55 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return bindings; } + function parseDirectiveBindings(directive, directiveName) { + var bindings = { + isolateScope: null, + bindToController: null + }; + if (isObject(directive.scope)) { + if (directive.bindToController === true) { + bindings.bindToController = parseIsolateBindings(directive.scope, + directiveName, true); + bindings.isolateScope = {}; + } else { + bindings.isolateScope = parseIsolateBindings(directive.scope, + directiveName, false); + } + } + if (isObject(directive.bindToController)) { + bindings.bindToController = + parseIsolateBindings(directive.bindToController, directiveName, true); + } + if (isObject(bindings.bindToController)) { + var controller = directive.controller; + var controllerAs = directive.controllerAs; + if (!controller) { + // There is no controller, there may or may not be a controllerAs property + throw $compileMinErr('noctrl', + "Cannot bind to controller without directive '{0}'s controller.", + directiveName); + } else if (!identifierForController(controller, controllerAs)) { + // There is a controller, but no identifier or controllerAs property + throw $compileMinErr('noident', + "Cannot bind to controller without identifier for directive '{0}'.", + directiveName); + } + } + return bindings; + } + + function assertValidDirectiveName(name) { + var letter = name.charAt(0); + if (!letter || letter !== lowercase(letter)) { + throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); + } + if (name !== name.trim()) { + throw $compileMinErr('baddir', + "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces", + name); + } + } + /** * @ngdoc method * @name $compileProvider#directive @@ -6474,6 +6929,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { this.directive = function registerDirective(name, directiveFactory) { assertNotHasOwnProperty(name, 'directive'); if (isString(name)) { + assertValidDirectiveName(name); assertArg(directiveFactory, 'directiveFactory'); if (!hasDirectives.hasOwnProperty(name)) { hasDirectives[name] = []; @@ -6493,9 +6949,12 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { directive.name = directive.name || name; directive.require = directive.require || (directive.controller && directive.name); directive.restrict = directive.restrict || 'EA'; - if (isObject(directive.scope)) { - directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name); + var bindings = directive.$$bindings = + parseDirectiveBindings(directive, directive.name); + if (isObject(bindings.isolateScope)) { + directive.$$isolateBindings = bindings.isolateScope; } + directive.$$moduleName = directiveFactory.$$moduleName; directives.push(directive); } catch (e) { $exceptionHandler(e); @@ -7056,14 +7515,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (nodeLinkFn.scope) { childScope = scope.$new(); compile.$$addScopeInfo(jqLite(node), childScope); + var destroyBindings = nodeLinkFn.$$destroyBindings; + if (destroyBindings) { + nodeLinkFn.$$destroyBindings = null; + childScope.$on('$destroyed', destroyBindings); + } } else { childScope = scope; } if (nodeLinkFn.transcludeOnThisElement) { childBoundTranscludeFn = createBoundTranscludeFn( - scope, nodeLinkFn.transclude, parentBoundTranscludeFn, - nodeLinkFn.elementTranscludeOnThisElement); + scope, nodeLinkFn.transclude, parentBoundTranscludeFn); } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { childBoundTranscludeFn = parentBoundTranscludeFn; @@ -7075,7 +7538,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { childBoundTranscludeFn = null; } - nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn); + nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn, + nodeLinkFn); } else if (childLinkFn) { childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); @@ -7084,7 +7548,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } } - function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) { + function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) { var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { @@ -7183,6 +7647,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } break; case NODE_TYPE_TEXT: /* Text Node */ + if (msie === 11) { + // Workaround for #11781 + while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) { + node.nodeValue = node.nodeValue + node.nextSibling.nodeValue; + node.parentNode.removeChild(node.nextSibling); + } + } addTextInterpolateDirective(directives, node.nodeValue); break; case NODE_TYPE_COMMENT: /* Comment */ @@ -7282,9 +7753,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { previousCompileContext = previousCompileContext || {}; var terminalPriority = -Number.MAX_VALUE, - newScopeDirective, + newScopeDirective = previousCompileContext.newScopeDirective, controllerDirectives = previousCompileContext.controllerDirectives, - controllers, newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, templateDirective = previousCompileContext.templateDirective, nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, @@ -7342,7 +7812,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (!directive.templateUrl && directive.controller) { directiveValue = directive.controller; - controllerDirectives = controllerDirectives || {}; + controllerDirectives = controllerDirectives || createMap(); assertNoDuplicate("'" + directiveName + "' controller", controllerDirectives[directiveName], directive, $compileNode); controllerDirectives[directiveName] = directive; @@ -7449,6 +7919,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { controllerDirectives: controllerDirectives, + newScopeDirective: (newScopeDirective !== directive) && newScopeDirective, newIsolateScopeDirective: newIsolateScopeDirective, templateDirective: templateDirective, nonTlbTranscludeDirective: nonTlbTranscludeDirective @@ -7476,7 +7947,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; - nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective; nodeLinkFn.templateOnThisElement = hasTemplate; nodeLinkFn.transclude = childTranscludeFn; @@ -7510,53 +7980,77 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { function getControllers(directiveName, require, $element, elementControllers) { - var value, retrievalMethod = 'data', optional = false; - var $searchElement = $element; - var match; - if (isString(require)) { - match = require.match(REQUIRE_PREFIX_REGEXP); - require = require.substring(match[0].length); + var value; - if (match[3]) { - if (match[1]) match[3] = null; - else match[1] = match[3]; - } - if (match[1] === '^') { - retrievalMethod = 'inheritedData'; - } else if (match[1] === '^^') { - retrievalMethod = 'inheritedData'; - $searchElement = $element.parent(); - } - if (match[2] === '?') { - optional = true; + if (isString(require)) { + var match = require.match(REQUIRE_PREFIX_REGEXP); + var name = require.substring(match[0].length); + var inheritType = match[1] || match[3]; + var optional = match[2] === '?'; + + //If only parents then start at the parent element + if (inheritType === '^^') { + $element = $element.parent(); + //Otherwise attempt getting the controller from elementControllers in case + //the element is transcluded (and has no data) and to avoid .data if possible + } else { + value = elementControllers && elementControllers[name]; + value = value && value.instance; } - value = null; - - if (elementControllers && retrievalMethod === 'data') { - if (value = elementControllers[require]) { - value = value.instance; - } + if (!value) { + var dataName = '$' + name + 'Controller'; + value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); } - value = value || $searchElement[retrievalMethod]('$' + require + 'Controller'); if (!value && !optional) { throw $compileMinErr('ctreq', "Controller '{0}', required by directive '{1}', can't be found!", - require, directiveName); + name, directiveName); } - return value || null; } else if (isArray(require)) { value = []; - forEach(require, function(require) { - value.push(getControllers(directiveName, require, $element, elementControllers)); - }); + for (var i = 0, ii = require.length; i < ii; i++) { + value[i] = getControllers(directiveName, require[i], $element, elementControllers); + } } - return value; + + return value || null; } + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + } + return elementControllers; + } - function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, + thisLinkFn) { var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, attrs; @@ -7580,126 +8074,53 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } if (controllerDirectives) { - // TODO: merge `controllers` and `elementControllers` into single object. - controllers = {}; - elementControllers = {}; - forEach(controllerDirectives, function(directive) { - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }, controllerInstance; - - controller = directive.controller; - if (controller == '@') { - controller = attrs[directive.name]; - } - - controllerInstance = $controller(controller, locals, true, directive.controllerAs); - - // For directives with element transclusion the element is a comment, - // but jQuery .data doesn't support attaching data to comment nodes as it's hard to - // clean up (http://bugs.jquery.com/ticket/8335). - // Instead, we save the controllers for the element in a local hash and attach to .data - // later, once we have the actual element. - elementControllers[directive.name] = controllerInstance; - if (!hasElementTranscludeDirective) { - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); - } - - controllers[directive.name] = controllerInstance; - }); + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); } if (newIsolateScopeDirective) { + // Initialize isolate scope bindings for new isolate scope directive. compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || templateDirective === newIsolateScopeDirective.$$originalDirective))); compile.$$addScopeClass($element, true); - - var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name]; - var isolateBindingContext = isolateScope; - if (isolateScopeController && isolateScopeController.identifier && - newIsolateScopeDirective.bindToController === true) { - isolateBindingContext = isolateScopeController.instance; + isolateScope.$$isolateBindings = + newIsolateScopeDirective.$$isolateBindings; + initializeDirectiveBindings(scope, attrs, isolateScope, + isolateScope.$$isolateBindings, + newIsolateScopeDirective, isolateScope); + } + if (elementControllers) { + // Initialize bindToController bindings for new/isolate scopes + var scopeDirective = newIsolateScopeDirective || newScopeDirective; + var bindings; + var controllerForBindings; + if (scopeDirective && elementControllers[scopeDirective.name]) { + bindings = scopeDirective.$$bindings.bindToController; + controller = elementControllers[scopeDirective.name]; + + if (controller && controller.identifier && bindings) { + controllerForBindings = controller; + thisLinkFn.$$destroyBindings = + initializeDirectiveBindings(scope, attrs, controller.instance, + bindings, scopeDirective); + } } - - forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) { - var attrName = definition.attrName, - optional = definition.optional, - mode = definition.mode, // @, =, or & - lastValue, - parentGet, parentSet, compare; - - switch (mode) { - - case '@': - attrs.$observe(attrName, function(value) { - isolateBindingContext[scopeName] = value; - }); - attrs.$$observers[attrName].$$scope = scope; - if (attrs[attrName]) { - // If the attribute has been provided then we trigger an interpolation to ensure - // the value is there for use in the link fn - isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope); - } - break; - - case '=': - if (optional && !attrs[attrName]) { - return; - } - parentGet = $parse(attrs[attrName]); - if (parentGet.literal) { - compare = equals; - } else { - compare = function(a, b) { return a === b || (a !== a && b !== b); }; - } - parentSet = parentGet.assign || function() { - // reset the change, or we will throw this exception on every $digest - lastValue = isolateBindingContext[scopeName] = parentGet(scope); - throw $compileMinErr('nonassign', - "Expression '{0}' used with directive '{1}' is non-assignable!", - attrs[attrName], newIsolateScopeDirective.name); - }; - lastValue = isolateBindingContext[scopeName] = parentGet(scope); - var parentValueWatch = function parentValueWatch(parentValue) { - if (!compare(parentValue, isolateBindingContext[scopeName])) { - // we are out of sync and need to copy - if (!compare(parentValue, lastValue)) { - // parent changed and it has precedence - isolateBindingContext[scopeName] = parentValue; - } else { - // if the parent can be assigned then do so - parentSet(scope, parentValue = isolateBindingContext[scopeName]); - } - } - return lastValue = parentValue; - }; - parentValueWatch.$stateful = true; - var unwatch; - if (definition.collection) { - unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); - } else { - unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); - } - isolateScope.$on('$destroy', unwatch); - break; - - case '&': - parentGet = $parse(attrs[attrName]); - isolateBindingContext[scopeName] = function(locals) { - return parentGet(scope, locals); - }; - break; + for (i in elementControllers) { + controller = elementControllers[i]; + var controllerResult = controller(); + + if (controllerResult !== controller.instance) { + // If the controller constructor has a return value, overwrite the instance + // from setupControllers and update the element data + controller.instance = controllerResult; + $element.data('$' + i + 'Controller', controllerResult); + if (controller === controllerForBindings) { + // Remove and re-install bindToController bindings + thisLinkFn.$$destroyBindings(); + thisLinkFn.$$destroyBindings = + initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); + } } - }); - } - if (controllers) { - forEach(controllers, function(controller) { - controller(); - }); - controllers = null; + } } // PRELINKING @@ -7883,7 +8304,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { $compileNode.empty(); - $templateRequest($sce.getTrustedResourceUrl(templateUrl)) + $templateRequest(templateUrl) .then(function(content) { var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; @@ -7957,7 +8378,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { childBoundTranscludeFn = boundTranscludeFn; } afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, - childBoundTranscludeFn); + childBoundTranscludeFn, afterTemplateNodeLinkFn); } linkQueue = null; }); @@ -7974,7 +8395,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { if (afterTemplateNodeLinkFn.transcludeOnThisElement) { childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn); + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn, + afterTemplateNodeLinkFn); } }; } @@ -7990,11 +8412,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { return a.index - b.index; } - function assertNoDuplicate(what, previousDirective, directive, element) { + + function wrapModuleNameIfDefined(moduleName) { + return moduleName ? + (' (module: ' + moduleName + ')') : + ''; + } + if (previousDirective) { - throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}', - previousDirective.name, directive.name, what, startingTag(element)); + throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}', + previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName), + directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element)); } } @@ -8175,26 +8604,28 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var fragment = document.createDocumentFragment(); fragment.appendChild(firstElementToRemove); - // Copy over user data (that includes Angular's $scope etc.). Don't copy private - // data here because there's no public interface in jQuery to do that and copying over - // event listeners (which is the main use of private data) wouldn't work anyway. - jqLite(newNode).data(jqLite(firstElementToRemove).data()); - - // Remove data of the replaced element. We cannot just call .remove() - // on the element it since that would deallocate scope that is needed - // for the new node. Instead, remove the data "manually". - if (!jQuery) { - delete jqLite.cache[firstElementToRemove[jqLite.expando]]; - } else { - // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after - // the replaced element. The cleanData version monkey-patched by Angular would cause - // the scope to be trashed and we do need the very same scope to work with the new - // element. However, we cannot just cache the non-patched version and use it here as - // that would break if another library patches the method after Angular does (one - // example is jQuery UI). Instead, set a flag indicating scope destroying should be - // skipped this one time. - skipDestroyOnNextJQueryCleanData = true; - jQuery.cleanData([firstElementToRemove]); + if (jqLite.hasData(firstElementToRemove)) { + // Copy over user data (that includes Angular's $scope etc.). Don't copy private + // data here because there's no public interface in jQuery to do that and copying over + // event listeners (which is the main use of private data) wouldn't work anyway. + jqLite(newNode).data(jqLite(firstElementToRemove).data()); + + // Remove data of the replaced element. We cannot just call .remove() + // on the element it since that would deallocate scope that is needed + // for the new node. Instead, remove the data "manually". + if (!jQuery) { + delete jqLite.cache[firstElementToRemove[jqLite.expando]]; + } else { + // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after + // the replaced element. The cleanData version monkey-patched by Angular would cause + // the scope to be trashed and we do need the very same scope to work with the new + // element. However, we cannot just cache the non-patched version and use it here as + // that would break if another library patches the method after Angular does (one + // example is jQuery UI). Instead, set a flag indicating scope destroying should be + // skipped this one time. + skipDestroyOnNextJQueryCleanData = true; + jQuery.cleanData([firstElementToRemove]); + } } for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { @@ -8221,22 +8652,126 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { $exceptionHandler(e, startingTag($element)); } } - }]; -} -var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; -/** - * Converts all accepted directives format into proper directive name. - * @param name Name to normalize - */ -function directiveNormalize(name) { - return camelCase(name.replace(PREFIX_REGEXP, '')); -} -/** - * @ngdoc type - * @name $compile.directive.Attributes - * + // Set up $watches for isolate scope and controller bindings. This process + // only occurs for isolate scopes and new scopes with controllerAs. + function initializeDirectiveBindings(scope, attrs, destination, bindings, + directive, newScope) { + var onNewScopeDestroyed; + forEach(bindings, function(definition, scopeName) { + var attrName = definition.attrName, + optional = definition.optional, + mode = definition.mode, // @, =, or & + lastValue, + parentGet, parentSet, compare; + + if (!hasOwnProperty.call(attrs, attrName)) { + // In the case of user defined a binding with the same name as a method in Object.prototype but didn't set + // the corresponding attribute. We need to make sure subsequent code won't access to the prototype function + attrs[attrName] = undefined; + } + + switch (mode) { + + case '@': + if (!attrs[attrName] && !optional) { + destination[scopeName] = undefined; + } + + attrs.$observe(attrName, function(value) { + destination[scopeName] = value; + }); + attrs.$$observers[attrName].$$scope = scope; + if (attrs[attrName]) { + // If the attribute has been provided then we trigger an interpolation to ensure + // the value is there for use in the link fn + destination[scopeName] = $interpolate(attrs[attrName])(scope); + } + break; + + case '=': + if (optional && !attrs[attrName]) { + return; + } + parentGet = $parse(attrs[attrName]); + + if (parentGet.literal) { + compare = equals; + } else { + compare = function(a, b) { return a === b || (a !== a && b !== b); }; + } + parentSet = parentGet.assign || function() { + // reset the change, or we will throw this exception on every $digest + lastValue = destination[scopeName] = parentGet(scope); + throw $compileMinErr('nonassign', + "Expression '{0}' used with directive '{1}' is non-assignable!", + attrs[attrName], directive.name); + }; + lastValue = destination[scopeName] = parentGet(scope); + var parentValueWatch = function parentValueWatch(parentValue) { + if (!compare(parentValue, destination[scopeName])) { + // we are out of sync and need to copy + if (!compare(parentValue, lastValue)) { + // parent changed and it has precedence + destination[scopeName] = parentValue; + } else { + // if the parent can be assigned then do so + parentSet(scope, parentValue = destination[scopeName]); + } + } + return lastValue = parentValue; + }; + parentValueWatch.$stateful = true; + var unwatch; + if (definition.collection) { + unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); + } else { + unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); + } + onNewScopeDestroyed = (onNewScopeDestroyed || []); + onNewScopeDestroyed.push(unwatch); + break; + + case '&': + parentGet = $parse(attrs[attrName]); + + // Don't assign noop to destination if expression is not valid + if (parentGet === noop && optional) break; + + destination[scopeName] = function(locals) { + return parentGet(scope, locals); + }; + break; + } + }); + var destroyBindings = onNewScopeDestroyed ? function destroyBindings() { + for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) { + onNewScopeDestroyed[i](); + } + } : noop; + if (newScope && destroyBindings !== noop) { + newScope.$on('$destroy', destroyBindings); + return noop; + } + return destroyBindings; + } + }]; +} + +var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; +/** + * Converts all accepted directives format into proper directive name. + * @param name Name to normalize + */ +function directiveNormalize(name) { + return camelCase(name.replace(PREFIX_REGEXP, '')); +} + +/** + * @ngdoc type + * @name $compile.directive.Attributes + * * @description * A shared object between directive compile / linking functions which contains normalized DOM * element attributes. The values reflect current binding state `{{ }}`. The normalization is @@ -8328,6 +8863,17 @@ function removeComments(jqNodes) { var $controllerMinErr = minErr('$controller'); + +var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; +function identifierForController(controller, ident) { + if (ident && isString(ident)) return ident; + if (isString(controller)) { + var match = CNTRL_REG.exec(controller); + if (match) return match[3]; + } +} + + /** * @ngdoc provider * @name $controllerProvider @@ -8340,9 +8886,7 @@ var $controllerMinErr = minErr('$controller'); */ function $ControllerProvider() { var controllers = {}, - globals = false, - CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; - + globals = false; /** * @ngdoc method @@ -8450,8 +8994,16 @@ function $ControllerProvider() { addIdentifier(locals, identifier, instance, constructor || expression.name); } - return extend(function() { - $injector.invoke(expression, instance, locals, constructor); + var instantiate; + return instantiate = extend(function() { + var result = $injector.invoke(expression, instance, locals, constructor); + if (result !== instance && (isObject(result) || isFunction(result))) { + instance = result; + if (identifier) { + // If result changed, re-assign controllerAs value to scope. + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + } return instance; }, { instance: instance, @@ -8568,6 +9120,123 @@ var JSON_ENDS = { }; var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; +function serializeValue(v) { + if (isObject(v)) { + return isDate(v) ? v.toISOString() : toJson(v); + } + return v; +} + + +function $HttpParamSerializerProvider() { + /** + * @ngdoc service + * @name $httpParamSerializer + * @description + * + * Default {@link $http `$http`} params serializer that converts objects to strings + * according to the following rules: + * + * * `{'foo': 'bar'}` results in `foo=bar` + * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object) + * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element) + * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object) + * + * Note that serializer will sort the request parameters alphabetically. + * */ + + this.$get = function() { + return function ngParamSerializer(params) { + if (!params) return ''; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (isArray(value)) { + forEach(value, function(v, k) { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v))); + }); + } else { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value))); + } + }); + + return parts.join('&'); + }; + }; +} + +function $HttpParamSerializerJQLikeProvider() { + /** + * @ngdoc service + * @name $httpParamSerializerJQLike + * @description + * + * Alternative {@link $http `$http`} params serializer that follows + * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic. + * The serializer will also sort the params alphabetically. + * + * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property: + * + * ```js + * $http({ + * url: myUrl, + * method: 'GET', + * params: myParams, + * paramSerializer: '$httpParamSerializerJQLike' + * }); + * ``` + * + * It is also possible to set it as the default `paramSerializer` in the + * {@link $httpProvider#defaults `$httpProvider`}. + * + * Additionally, you can inject the serializer and use it explicitly, for example to serialize + * form data for submission: + * + * ```js + * .controller(function($http, $httpParamSerializerJQLike) { + * //... + * + * $http({ + * url: myUrl, + * method: 'POST', + * data: $httpParamSerializerJQLike(myData), + * headers: { + * 'Content-Type': 'application/x-www-form-urlencoded' + * } + * }); + * + * }); + * ``` + * + * */ + this.$get = function() { + return function jQueryLikeParamSerializer(params) { + if (!params) return ''; + var parts = []; + serialize(params, '', true); + return parts.join('&'); + + function serialize(toSerialize, prefix, topLevel) { + if (toSerialize === null || isUndefined(toSerialize)) return; + if (isArray(toSerialize)) { + forEach(toSerialize, function(value) { + serialize(value, prefix + '[]'); + }); + } else if (isObject(toSerialize) && !isDate(toSerialize)) { + forEachSorted(toSerialize, function(value, key) { + serialize(value, prefix + + (topLevel ? '' : '[') + + key + + (topLevel ? '' : ']')); + }); + } else { + parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize))); + } + } + }; + }; +} + function defaultHttpResponseTransform(data, headers) { if (isString(data)) { // Strip json vulnerability protection prefix and trim whitespace @@ -8596,19 +9265,24 @@ function isJsonLike(str) { * @returns {Object} Parsed headers as key value object */ function parseHeaders(headers) { - var parsed = createMap(), key, val, i; - - if (!headers) return parsed; - - forEach(headers.split('\n'), function(line) { - i = line.indexOf(':'); - key = lowercase(trim(line.substr(0, i))); - val = trim(line.substr(i + 1)); + var parsed = createMap(), i; + function fillInParsed(key, val) { if (key) { parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; } - }); + } + + if (isString(headers)) { + forEach(headers.split('\n'), function(line) { + i = line.indexOf(':'); + fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1))); + }); + } else if (isObject(headers)) { + forEach(headers, function(headerVal, headerKey) { + fillInParsed(lowercase(headerKey), trim(headerVal)); + }); + } return parsed; } @@ -8627,7 +9301,7 @@ function parseHeaders(headers) { * - if called with no arguments returns an object containing all headers. */ function headersGetter(headers) { - var headersObj = isObject(headers) ? headers : undefined; + var headersObj; return function(name) { if (!headersObj) headersObj = parseHeaders(headers); @@ -8657,8 +9331,9 @@ function headersGetter(headers) { * @returns {*} Transformed data. */ function transformData(data, headers, status, fns) { - if (isFunction(fns)) + if (isFunction(fns)) { return fns(data, headers, status); + } forEach(fns, function(fn) { data = fn(data, headers, status); @@ -8689,7 +9364,7 @@ function $HttpProvider() { * * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`} * that will provide the cache for all requests who set their `cache` property to `true`. - * If you set the `default.cache = false` then only requests that specify their own custom + * If you set the `defaults.cache = false` then only requests that specify their own custom * cache object will be cached. See {@link $http#caching $http Caching} for more information. * * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. @@ -8706,6 +9381,12 @@ function $HttpProvider() { * - **`defaults.headers.put`** * - **`defaults.headers.patch`** * + * + * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function + * used to the prepare string representation of request parameters (specified as an object). + * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}. + * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}. + * **/ var defaults = this.defaults = { // transform incoming response data @@ -8727,7 +9408,9 @@ function $HttpProvider() { }, xsrfCookieName: 'XSRF-TOKEN', - xsrfHeaderName: 'X-XSRF-TOKEN' + xsrfHeaderName: 'X-XSRF-TOKEN', + + paramSerializer: '$httpParamSerializer' }; var useApplyAsync = false; @@ -8741,7 +9424,7 @@ function $HttpProvider() { * significant performance improvement for bigger applications that make many HTTP requests * concurrently (common during application bootstrap). * - * Defaults to false. If no value is specifed, returns the current configured value. + * Defaults to false. If no value is specified, returns the current configured value. * * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window @@ -8773,11 +9456,17 @@ function $HttpProvider() { **/ var interceptorFactories = this.interceptors = []; - this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector', - function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) { + this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', + function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) { var defaultCache = $cacheFactory('$http'); + /** + * Make sure that default param serializer is exposed as a function + */ + defaults.paramSerializer = isString(defaults.paramSerializer) ? + $injector.get(defaults.paramSerializer) : defaults.paramSerializer; + /** * Interceptors stored in reverse order. Inner interceptors before outer interceptors. * The reversal is needed so that we can build up the interception chain around the @@ -8906,7 +9595,7 @@ function $HttpProvider() { * To add or overwrite these defaults, simply add or remove a property from these configuration * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object * with the lowercased HTTP method name as the key, e.g. - * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }. + * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`. * * The defaults can also be set at runtime via the `$http.defaults` object in the same * fashion. For example: @@ -8930,7 +9619,7 @@ function $HttpProvider() { * headers: { * 'Content-Type': undefined * }, - * data: { test: 'test' }, + * data: { test: 'test' } * } * * $http(req).success(function(){...}).error(function(){...}); @@ -9162,19 +9851,21 @@ function $HttpProvider() { * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time, * or the per-request config object. * + * In order to prevent collisions in environments where multiple Angular apps share the + * same domain or subdomain, we recommend that each application uses unique cookie name. + * * * @param {object} config Object describing the request to be made and how it should be * processed. The object has following properties: * * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. - * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned - * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be - * JSONified. + * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized + * with the `paramSerializer` and appended as GET parameters. * - **data** – `{string|Object}` – Data to be sent as the request message data. * - **headers** – `{Object}` – Map of strings or functions which return strings representing * HTTP headers to send to the server. If the return value of a function is null, the - * header will not be sent. + * header will not be sent. Functions accept a config object as an argument. * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. * - **transformRequest** – @@ -9188,7 +9879,14 @@ function $HttpProvider() { * transform function or an array of such functions. The transform function takes the http * response body, headers and status and returns its transformed (typically deserialized) version. * See {@link ng.$http#overriding-the-default-transformations-per-request - * Overriding the Default Transformations} + * Overriding the Default TransformationjqLiks} + * - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to + * prepare the string representation of request parameters (specified as an object). + * If specified as string, it is interpreted as function registered with the + * {@link $injector $injector}, which means you can create your own serializer + * by registering it as a {@link auto.$provide#service service}. + * The default serializer is the {@link $httpParamSerializer $httpParamSerializer}; + * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike} * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the * GET request, otherwise if a cache instance built with * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for @@ -9199,7 +9897,7 @@ function $HttpProvider() { * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) * for more information. * - **responseType** - `{string}` - see - * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype). * * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the * standard `then` method and two http specific methods: `success` and `error`. The `then` @@ -9224,11 +9922,11 @@ function $HttpProvider() { <example module="httpExample"> <file name="index.html"> <div ng-controller="FetchController"> - <select ng-model="method"> + <select ng-model="method" aria-label="Request method"> <option>GET</option> <option>JSONP</option> </select> - <input type="text" ng-model="url" size="80"/> + <input type="text" ng-model="url" size="80" aria-label="URL" /> <button id="fetchbtn" ng-click="fetch()">fetch</button><br> <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button> <button id="samplejsonpbtn" @@ -9317,11 +10015,14 @@ function $HttpProvider() { var config = extend({ method: 'get', transformRequest: defaults.transformRequest, - transformResponse: defaults.transformResponse + transformResponse: defaults.transformResponse, + paramSerializer: defaults.paramSerializer }, requestConfig); config.headers = mergeHeaders(requestConfig); config.method = uppercase(config.method); + config.paramSerializer = isString(config.paramSerializer) ? + $injector.get(config.paramSerializer) : config.paramSerializer; var serverRequest = function(config) { var headers = config.headers; @@ -9365,6 +10066,8 @@ function $HttpProvider() { } promise.success = function(fn) { + assertArgFn(fn, 'fn'); + promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); @@ -9372,6 +10075,8 @@ function $HttpProvider() { }; promise.error = function(fn) { + assertArgFn(fn, 'fn'); + promise.then(null, function(response) { fn(response.data, response.status, response.headers, config); }); @@ -9393,12 +10098,12 @@ function $HttpProvider() { : $q.reject(resp); } - function executeHeaderFns(headers) { + function executeHeaderFns(headers, config) { var headerContent, processedHeaders = {}; forEach(headers, function(headerFn, header) { if (isFunction(headerFn)) { - headerContent = headerFn(); + headerContent = headerFn(config); if (headerContent != null) { processedHeaders[header] = headerContent; } @@ -9432,7 +10137,7 @@ function $HttpProvider() { } // execute if header value is a function for merged headers - return executeHeaderFns(reqHeaders); + return executeHeaderFns(reqHeaders, shallowCopy(config)); } } @@ -9547,7 +10252,7 @@ function $HttpProvider() { function createShortMethods(names) { forEach(arguments, function(name) { $http[name] = function(url, config) { - return $http(extend(config || {}, { + return $http(extend({}, config || {}, { method: name, url: url })); @@ -9559,7 +10264,7 @@ function $HttpProvider() { function createShortMethodsWithData(name) { forEach(arguments, function(name) { $http[name] = function(url, data, config) { - return $http(extend(config || {}, { + return $http(extend({}, config || {}, { method: name, url: url, data: data @@ -9581,7 +10286,7 @@ function $HttpProvider() { cache, cachedResp, reqHeaders = config.headers, - url = buildUrl(config.url, config.params); + url = buildUrl(config.url, config.paramSerializer(config.params)); $http.pendingRequests.push(config); promise.then(removePendingReq, removePendingReq); @@ -9619,7 +10324,7 @@ function $HttpProvider() { // send the request to the backend if (isUndefined(cachedResp)) { var xsrfValue = urlIsSameOrigin(config.url) - ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName] + ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] : undefined; if (xsrfValue) { reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; @@ -9688,27 +10393,9 @@ function $HttpProvider() { } - function buildUrl(url, params) { - if (!params) return url; - var parts = []; - forEachSorted(params, function(value, key) { - if (value === null || isUndefined(value)) return; - if (!isArray(value)) value = [value]; - - forEach(value, function(v) { - if (isObject(v)) { - if (isDate(v)) { - v = v.toISOString(); - } else { - v = toJson(v); - } - } - parts.push(encodeUriQuery(key) + '=' + - encodeUriQuery(v)); - }); - }); - if (parts.length > 0) { - url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); + function buildUrl(url, serializedParams) { + if (serializedParams.length > 0) { + url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams; } return url; } @@ -9824,7 +10511,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } } - xhr.send(post || null); + xhr.send(post); } if (timeout > 0) { @@ -9852,7 +10539,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc }; function jsonpReq(url, callbackId, done) { - // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.: + // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.: // - fetches local scripts via XHR and evals them // - adds and immediately removes script elements from the document var script = rawDocument.createElement('script'), callback = null; @@ -9888,7 +10575,17 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc } } -var $interpolateMinErr = minErr('$interpolate'); +var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate'); +$interpolateMinErr.throwNoconcat = function(text) { + throw $interpolateMinErr('noconcat', + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + + "interpolations that concatenate multiple expressions when a trusted value is " + + "required. See http://docs.angularjs.org/api/ng.$sce", text); +}; + +$interpolateMinErr.interr = function(text, err) { + return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString()); +}; /** * @ngdoc provider @@ -9976,6 +10673,28 @@ function $InterpolateProvider() { return '\\\\\\' + ch; } + function unescapeText(text) { + return text.replace(escapedStartRegexp, startSymbol). + replace(escapedEndRegexp, endSymbol); + } + + function stringify(value) { + if (value == null) { // null || undefined + return ''; + } + switch (typeof value) { + case 'string': + break; + case 'number': + value = '' + value; + break; + default: + value = toJson(value); + } + + return value; + } + /** * @ngdoc service * @name $interpolate @@ -10110,10 +10829,7 @@ function $InterpolateProvider() { // make it obvious that you bound the value to some user controlled value. This helps reduce // the load when auditing for XSS issues. if (trustedContext && concat.length > 1) { - throw $interpolateMinErr('noconcat', - "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + - "interpolations that concatenate multiple expressions when a trusted value is " + - "required. See http://docs.angularjs.org/api/ng.$sce", text); + $interpolateMinErr.throwNoconcat(text); } if (!mustHaveExpression || expressions.length) { @@ -10131,23 +10847,6 @@ function $InterpolateProvider() { $sce.valueOf(value); }; - var stringify = function(value) { - if (value == null) { // null || undefined - return ''; - } - switch (typeof value) { - case 'string': - break; - case 'number': - value = '' + value; - break; - default: - value = toJson(value); - } - - return value; - }; - return extend(function interpolationFn(context) { var i = 0; var ii = expressions.length; @@ -10160,16 +10859,14 @@ function $InterpolateProvider() { return compute(values); } catch (err) { - var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, - err.toString()); - $exceptionHandler(newErr); + $exceptionHandler($interpolateMinErr.interr(text, err)); } }, { // all of these properties are undocumented for now exp: text, //just for compatibility with regular watchers created via $watch expressions: expressions, - $$watchDelegate: function(scope, listener, objectEquality) { + $$watchDelegate: function(scope, listener) { var lastValue; return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { var currValue = compute(values); @@ -10177,24 +10874,17 @@ function $InterpolateProvider() { listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); } lastValue = currValue; - }, objectEquality); + }); } }); } - function unescapeText(text) { - return text.replace(escapedStartRegexp, startSymbol). - replace(escapedEndRegexp, endSymbol); - } - function parseStringifyInterceptor(value) { try { value = getValue(value); return allOrNothing && !isDefined(value) ? value : stringify(value); } catch (err) { - var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, - err.toString()); - $exceptionHandler(newErr); + $exceptionHandler($interpolateMinErr.interr(text, err)); } } } @@ -10273,6 +10963,7 @@ function $IntervalProvider() { * indefinitely. * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. * @returns {promise} A promise which will be notified on each iteration. * * @example @@ -10351,7 +11042,7 @@ function $IntervalProvider() { * * <div> * <div ng-controller="ExampleController"> - * Date format: <input ng-model="format"> <hr/> + * <label>Date format: <input ng-model="format"></label> <hr/> * Current time is: <span my-current-time="format"></span> * <hr/> * Blood 1 : <font color='red'>{{blood_1}}</font> @@ -10366,7 +11057,9 @@ function $IntervalProvider() { * </example> */ function interval(fn, delay, count, invokeApply) { - var setInterval = $window.setInterval, + var hasParams = arguments.length > 4, + args = hasParams ? sliceArgs(arguments, 4) : [], + setInterval = $window.setInterval, clearInterval = $window.clearInterval, iteration = 0, skipApply = (isDefined(invokeApply) && !invokeApply), @@ -10375,7 +11068,9 @@ function $IntervalProvider() { count = isDefined(count) ? count : 0; - promise.then(null, null, fn); + promise.then(null, null, (!hasParams) ? fn : function() { + fn.apply(null, args); + }); promise.$$intervalId = setInterval(function tick() { deferred.notify(iteration++); @@ -10479,7 +11174,15 @@ function $LocaleProvider() { mediumDate: 'MMM d, y', shortDate: 'M/d/yy', mediumTime: 'h:mm:ss a', - shortTime: 'h:mm a' + shortTime: 'h:mm a', + ERANAMES: [ + "Before Christ", + "Anno Domini" + ], + ERAS: [ + "BC", + "AD" + ] }, pluralCat: function(num) { @@ -10519,7 +11222,7 @@ function parseAbsoluteUrl(absoluteUrl, locationObj) { locationObj.$$protocol = parsedUrl.protocol; locationObj.$$host = parsedUrl.hostname; - locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; + locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; } @@ -10677,7 +11380,7 @@ function LocationHashbangUrl(appBase, hashPrefix) { var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); var withoutHashUrl; - if (withoutBaseUrl.charAt(0) === '#') { + if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') { // The rest of the url starts with a hash so we have // got either a hashbang path or a plain hash fragment @@ -10691,7 +11394,15 @@ function LocationHashbangUrl(appBase, hashPrefix) { // There was no hashbang path nor hash fragment: // If we are in HTML5 mode we use what is left as the path; // Otherwise we ignore what is left - withoutHashUrl = this.$$html5 ? withoutBaseUrl : ''; + if (this.$$html5) { + withoutHashUrl = withoutBaseUrl; + } else { + withoutHashUrl = ''; + if (isUndefined(withoutBaseUrl)) { + appBase = url; + this.replace(); + } + } } parseAppUrl(withoutHashUrl, this); @@ -10865,8 +11576,9 @@ var locationPrototype = { * @return {string} url */ url: function(url) { - if (isUndefined(url)) + if (isUndefined(url)) { return this.$$url; + } var match = PATH_MATCH.exec(url); if (match[1] || url === '') this.path(decodeURIComponent(match[1])); @@ -10905,11 +11617,19 @@ var locationPrototype = { * * Return host of current url. * + * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only. + * * * ```js * // given url http://example.com/#/some/path?foo=bar&baz=xoxo * var host = $location.host(); * // => "example.com" + * + * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo + * host = $location.host(); + * // => "example.com" + * host = location.host; + * // => "example.com:8080" * ``` * * @return {string} host of current url. @@ -11105,8 +11825,9 @@ forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], fun * @return {object} state */ Location.prototype.state = function(state) { - if (!arguments.length) + if (!arguments.length) { return this.$$state; + } if (Location !== LocationHtml5Url || !this.$$html5) { throw $locationMinErr('nostate', 'History API state support is available only ' + @@ -11131,8 +11852,9 @@ function locationGetter(property) { function locationGetterSetter(property, preprocess) { return function(value) { - if (isUndefined(value)) + if (isUndefined(value)) { return this[property]; + } this[property] = preprocess(value); this.$$compose(); @@ -11481,12 +12203,13 @@ function $LocationProvider() { <file name="index.html"> <div ng-controller="LogController"> <p>Reload this page with open console, enter text and hit the log button...</p> - Message: - <input type="text" ng-model="message"/> + <label>Message: + <input type="text" ng-model="message" /></label> <button ng-click="$log.log(message)">log</button> <button ng-click="$log.warn(message)">warn</button> <button ng-click="$log.info(message)">info</button> <button ng-click="$log.error(message)">error</button> + <button ng-click="$log.debug(message)">debug</button> </div> </file> </example> @@ -11617,6 +12340,17 @@ function $LogProvider() { }]; } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + var $parseMinErr = minErr('$parse'); // Sandboxing Angular Expressions @@ -11699,57 +12433,8 @@ function ensureSafeFunction(obj, fullExpression) { } } -//Keyword constants -var CONSTANTS = createMap(); -forEach({ - 'null': function() { return null; }, - 'true': function() { return true; }, - 'false': function() { return false; }, - 'undefined': function() {} -}, function(constantGetter, name) { - constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true; - CONSTANTS[name] = constantGetter; -}); - -//Not quite a constant, but can be lex/parsed the same -CONSTANTS['this'] = function(self) { return self; }; -CONSTANTS['this'].sharedGetter = true; - - -//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter -var OPERATORS = extend(createMap(), { - '+':function(self, locals, a, b) { - a=a(self, locals); b=b(self, locals); - if (isDefined(a)) { - if (isDefined(b)) { - return a + b; - } - return a; - } - return isDefined(b) ? b : undefined;}, - '-':function(self, locals, a, b) { - a=a(self, locals); b=b(self, locals); - return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0); - }, - '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);}, - '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);}, - '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);}, - '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);}, - '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);}, - '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);}, - '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);}, - '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);}, - '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);}, - '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);}, - '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);}, - '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);}, - '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);}, - '!':function(self, locals, a) {return !a(self, locals);}, - - //Tokenized as operators but parsed as assignment/filters - '=':true, - '|':true -}); +var OPERATORS = createMap(); +forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; }); var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; @@ -11901,8 +12586,9 @@ Lexer.prototype = { if (escape) { if (ch === 'u') { var hex = this.text.substring(this.index + 1, this.index + 5); - if (!hex.match(/[\da-f]{4}/i)) + if (!hex.match(/[\da-f]{4}/i)) { this.throwError('Invalid unicode escape [\\u' + hex + ']'); + } this.index += 4; string += String.fromCharCode(parseInt(hex, 16)); } else { @@ -11930,295 +12616,106 @@ Lexer.prototype = { } }; - -function isConstant(exp) { - return exp.constant; -} - -/** - * @constructor - */ -var Parser = function(lexer, $filter, options) { +var AST = function(lexer, options) { this.lexer = lexer; - this.$filter = $filter; this.options = options; }; -Parser.ZERO = extend(function() { - return 0; -}, { - sharedGetter: true, - constant: true -}); - -Parser.prototype = { - constructor: Parser, - - parse: function(text) { +AST.Program = 'Program'; +AST.ExpressionStatement = 'ExpressionStatement'; +AST.AssignmentExpression = 'AssignmentExpression'; +AST.ConditionalExpression = 'ConditionalExpression'; +AST.LogicalExpression = 'LogicalExpression'; +AST.BinaryExpression = 'BinaryExpression'; +AST.UnaryExpression = 'UnaryExpression'; +AST.CallExpression = 'CallExpression'; +AST.MemberExpression = 'MemberExpression'; +AST.Identifier = 'Identifier'; +AST.Literal = 'Literal'; +AST.ArrayExpression = 'ArrayExpression'; +AST.Property = 'Property'; +AST.ObjectExpression = 'ObjectExpression'; +AST.ThisExpression = 'ThisExpression'; + +// Internal use only +AST.NGValueParameter = 'NGValueParameter'; + +AST.prototype = { + ast: function(text) { this.text = text; this.tokens = this.lexer.lex(text); - var value = this.statements(); + var value = this.program(); if (this.tokens.length !== 0) { this.throwError('is an unexpected token', this.tokens[0]); } - value.literal = !!value.literal; - value.constant = !!value.constant; - return value; }, - primary: function() { - var primary; - if (this.expect('(')) { - primary = this.filterChain(); - this.consume(')'); - } else if (this.expect('[')) { - primary = this.arrayDeclaration(); - } else if (this.expect('{')) { - primary = this.object(); - } else if (this.peek().identifier && this.peek().text in CONSTANTS) { - primary = CONSTANTS[this.consume().text]; - } else if (this.peek().identifier) { - primary = this.identifier(); - } else if (this.peek().constant) { - primary = this.constant(); - } else { - this.throwError('not a primary expression', this.peek()); + program: function() { + var body = []; + while (true) { + if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) + body.push(this.expressionStatement()); + if (!this.expect(';')) { + return { type: AST.Program, body: body}; + } } + }, - var next, context; - while ((next = this.expect('(', '[', '.'))) { - if (next.text === '(') { - primary = this.functionCall(primary, context); - context = null; - } else if (next.text === '[') { - context = primary; - primary = this.objectIndex(primary); - } else if (next.text === '.') { - context = primary; - primary = this.fieldAccess(primary); - } else { - this.throwError('IMPOSSIBLE'); - } + expressionStatement: function() { + return { type: AST.ExpressionStatement, expression: this.filterChain() }; + }, + + filterChain: function() { + var left = this.expression(); + var token; + while ((token = this.expect('|'))) { + left = this.filter(left); } - return primary; + return left; }, - throwError: function(msg, token) { - throw $parseMinErr('syntax', - 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', - token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); + expression: function() { + return this.assignment(); }, - peekToken: function() { - if (this.tokens.length === 0) - throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); - return this.tokens[0]; + assignment: function() { + var result = this.ternary(); + if (this.expect('=')) { + result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='}; + } + return result; }, - peek: function(e1, e2, e3, e4) { - return this.peekAhead(0, e1, e2, e3, e4); - }, - peekAhead: function(i, e1, e2, e3, e4) { - if (this.tokens.length > i) { - var token = this.tokens[i]; - var t = token.text; - if (t === e1 || t === e2 || t === e3 || t === e4 || - (!e1 && !e2 && !e3 && !e4)) { - return token; - } - } - return false; - }, - - expect: function(e1, e2, e3, e4) { - var token = this.peek(e1, e2, e3, e4); - if (token) { - this.tokens.shift(); - return token; - } - return false; - }, - - consume: function(e1) { - if (this.tokens.length === 0) { - throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); - } - - var token = this.expect(e1); - if (!token) { - this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); - } - return token; - }, - - unaryFn: function(op, right) { - var fn = OPERATORS[op]; - return extend(function $parseUnaryFn(self, locals) { - return fn(self, locals, right); - }, { - constant:right.constant, - inputs: [right] - }); - }, - - binaryFn: function(left, op, right, isBranching) { - var fn = OPERATORS[op]; - return extend(function $parseBinaryFn(self, locals) { - return fn(self, locals, left, right); - }, { - constant: left.constant && right.constant, - inputs: !isBranching && [left, right] - }); - }, - - identifier: function() { - var id = this.consume().text; - - //Continue reading each `.identifier` unless it is a method invocation - while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) { - id += this.consume().text + this.consume().text; - } - - return getterFn(id, this.options, this.text); - }, - - constant: function() { - var value = this.consume().value; - - return extend(function $parseConstant() { - return value; - }, { - constant: true, - literal: true - }); - }, - - statements: function() { - var statements = []; - while (true) { - if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) - statements.push(this.filterChain()); - if (!this.expect(';')) { - // optimize for the common case where there is only one statement. - // TODO(size): maybe we should not support multiple statements? - return (statements.length === 1) - ? statements[0] - : function $parseStatements(self, locals) { - var value; - for (var i = 0, ii = statements.length; i < ii; i++) { - value = statements[i](self, locals); - } - return value; - }; - } - } - }, - - filterChain: function() { - var left = this.expression(); - var token; - while ((token = this.expect('|'))) { - left = this.filter(left); - } - return left; - }, - - filter: function(inputFn) { - var fn = this.$filter(this.consume().text); - var argsFn; - var args; - - if (this.peek(':')) { - argsFn = []; - args = []; // we can safely reuse the array - while (this.expect(':')) { - argsFn.push(this.expression()); - } - } - - var inputs = [inputFn].concat(argsFn || []); - - return extend(function $parseFilter(self, locals) { - var input = inputFn(self, locals); - if (args) { - args[0] = input; - - var i = argsFn.length; - while (i--) { - args[i + 1] = argsFn[i](self, locals); - } - - return fn.apply(undefined, args); - } - - return fn(input); - }, { - constant: !fn.$stateful && inputs.every(isConstant), - inputs: !fn.$stateful && inputs - }); - }, - - expression: function() { - return this.assignment(); - }, - - assignment: function() { - var left = this.ternary(); - var right; - var token; - if ((token = this.expect('='))) { - if (!left.assign) { - this.throwError('implies assignment but [' + - this.text.substring(0, token.index) + '] can not be assigned to', token); - } - right = this.ternary(); - return extend(function $parseAssignment(scope, locals) { - return left.assign(scope, right(scope, locals), locals); - }, { - inputs: [left, right] - }); - } - return left; - }, - - ternary: function() { - var left = this.logicalOR(); - var middle; - var token; - if ((token = this.expect('?'))) { - middle = this.assignment(); - if (this.consume(':')) { - var right = this.assignment(); - - return extend(function $parseTernary(self, locals) { - return left(self, locals) ? middle(self, locals) : right(self, locals); - }, { - constant: left.constant && middle.constant && right.constant - }); - } - } - - return left; + ternary: function() { + var test = this.logicalOR(); + var alternate; + var consequent; + if (this.expect('?')) { + alternate = this.expression(); + if (this.consume(':')) { + consequent = this.expression(); + return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent}; + } + } + return test; }, logicalOR: function() { var left = this.logicalAND(); - var token; - while ((token = this.expect('||'))) { - left = this.binaryFn(left, token.text, this.logicalAND(), true); + while (this.expect('||')) { + left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() }; } return left; }, logicalAND: function() { var left = this.equality(); - var token; - while ((token = this.expect('&&'))) { - left = this.binaryFn(left, token.text, this.equality(), true); + while (this.expect('&&')) { + left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()}; } return left; }, @@ -12227,7 +12724,7 @@ Parser.prototype = { var left = this.relational(); var token; while ((token = this.expect('==','!=','===','!=='))) { - left = this.binaryFn(left, token.text, this.relational()); + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() }; } return left; }, @@ -12236,7 +12733,7 @@ Parser.prototype = { var left = this.additive(); var token; while ((token = this.expect('<', '>', '<=', '>='))) { - left = this.binaryFn(left, token.text, this.additive()); + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() }; } return left; }, @@ -12245,7 +12742,7 @@ Parser.prototype = { var left = this.multiplicative(); var token; while ((token = this.expect('+','-'))) { - left = this.binaryFn(left, token.text, this.multiplicative()); + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() }; } return left; }, @@ -12254,1332 +12751,2283 @@ Parser.prototype = { var left = this.unary(); var token; while ((token = this.expect('*','/','%'))) { - left = this.binaryFn(left, token.text, this.unary()); + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() }; } return left; }, unary: function() { var token; - if (this.expect('+')) { - return this.primary(); - } else if ((token = this.expect('-'))) { - return this.binaryFn(Parser.ZERO, token.text, this.unary()); - } else if ((token = this.expect('!'))) { - return this.unaryFn(token.text, this.unary()); + if ((token = this.expect('+', '-', '!'))) { + return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() }; } else { return this.primary(); } }, - fieldAccess: function(object) { - var getter = this.identifier(); + primary: function() { + var primary; + if (this.expect('(')) { + primary = this.filterChain(); + this.consume(')'); + } else if (this.expect('[')) { + primary = this.arrayDeclaration(); + } else if (this.expect('{')) { + primary = this.object(); + } else if (this.constants.hasOwnProperty(this.peek().text)) { + primary = copy(this.constants[this.consume().text]); + } else if (this.peek().identifier) { + primary = this.identifier(); + } else if (this.peek().constant) { + primary = this.constant(); + } else { + this.throwError('not a primary expression', this.peek()); + } - return extend(function $parseFieldAccess(scope, locals, self) { - var o = self || object(scope, locals); - return (o == null) ? undefined : getter(o); - }, { - assign: function(scope, value, locals) { - var o = object(scope, locals); - if (!o) object.assign(scope, o = {}, locals); - return getter.assign(o, value); + var next; + while ((next = this.expect('(', '[', '.'))) { + if (next.text === '(') { + primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() }; + this.consume(')'); + } else if (next.text === '[') { + primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true }; + this.consume(']'); + } else if (next.text === '.') { + primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false }; + } else { + this.throwError('IMPOSSIBLE'); } - }); + } + return primary; }, - objectIndex: function(obj) { - var expression = this.text; + filter: function(baseExpression) { + var args = [baseExpression]; + var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true}; - var indexFn = this.expression(); - this.consume(']'); + while (this.expect(':')) { + args.push(this.expression()); + } - return extend(function $parseObjectIndex(self, locals) { - var o = obj(self, locals), - i = indexFn(self, locals), - v; - - ensureSafeMemberName(i, expression); - if (!o) return undefined; - v = ensureSafeObject(o[i], expression); - return v; - }, { - assign: function(self, value, locals) { - var key = ensureSafeMemberName(indexFn(self, locals), expression); - // prevent overwriting of Function.constructor which would break ensureSafeObject check - var o = ensureSafeObject(obj(self, locals), expression); - if (!o) obj.assign(self, o = {}, locals); - return o[key] = value; - } - }); + return result; }, - functionCall: function(fnGetter, contextGetter) { - var argsFn = []; + parseArguments: function() { + var args = []; if (this.peekToken().text !== ')') { do { - argsFn.push(this.expression()); + args.push(this.expression()); } while (this.expect(',')); } - this.consume(')'); - - var expressionText = this.text; - // we can safely reuse the array across invocations - var args = argsFn.length ? [] : null; - - return function $parseFunctionCall(scope, locals) { - var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope; - var fn = fnGetter(scope, locals, context) || noop; - - if (args) { - var i = argsFn.length; - while (i--) { - args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText); - } - } - - ensureSafeObject(context, expressionText); - ensureSafeFunction(fn, expressionText); - - // IE doesn't have apply for some native functions - var v = fn.apply - ? fn.apply(context, args) - : fn(args[0], args[1], args[2], args[3], args[4]); + return args; + }, - if (args) { - // Free-up the memory (arguments of the last function call). - args.length = 0; - } + identifier: function() { + var token = this.consume(); + if (!token.identifier) { + this.throwError('is not a valid identifier', token); + } + return { type: AST.Identifier, name: token.text }; + }, - return ensureSafeObject(v, expressionText); - }; + constant: function() { + // TODO check that it is a constant + return { type: AST.Literal, value: this.consume().value }; }, - // This is used with json array declaration arrayDeclaration: function() { - var elementFns = []; + var elements = []; if (this.peekToken().text !== ']') { do { if (this.peek(']')) { // Support trailing commas per ES5.1. break; } - elementFns.push(this.expression()); + elements.push(this.expression()); } while (this.expect(',')); } this.consume(']'); - return extend(function $parseArrayLiteral(self, locals) { - var array = []; - for (var i = 0, ii = elementFns.length; i < ii; i++) { - array.push(elementFns[i](self, locals)); - } - return array; - }, { - literal: true, - constant: elementFns.every(isConstant), - inputs: elementFns - }); + return { type: AST.ArrayExpression, elements: elements }; }, object: function() { - var keys = [], valueFns = []; + var properties = [], property; if (this.peekToken().text !== '}') { do { if (this.peek('}')) { // Support trailing commas per ES5.1. break; } - var token = this.consume(); - if (token.constant) { - keys.push(token.value); - } else if (token.identifier) { - keys.push(token.text); + property = {type: AST.Property, kind: 'init'}; + if (this.peek().constant) { + property.key = this.constant(); + } else if (this.peek().identifier) { + property.key = this.identifier(); } else { - this.throwError("invalid key", token); + this.throwError("invalid key", this.peek()); } this.consume(':'); - valueFns.push(this.expression()); + property.value = this.expression(); + properties.push(property); } while (this.expect(',')); } this.consume('}'); - return extend(function $parseObjectLiteral(self, locals) { - var object = {}; - for (var i = 0, ii = valueFns.length; i < ii; i++) { - object[keys[i]] = valueFns[i](self, locals); - } - return object; - }, { - literal: true, - constant: valueFns.every(isConstant), - inputs: valueFns - }); - } -}; + return {type: AST.ObjectExpression, properties: properties }; + }, + throwError: function(msg, token) { + throw $parseMinErr('syntax', + 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', + token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); + }, -////////////////////////////////////////////////// -// Parser helper functions -////////////////////////////////////////////////// + consume: function(e1) { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } -function setter(obj, locals, path, setValue, fullExp) { - ensureSafeObject(obj, fullExp); - ensureSafeObject(locals, fullExp); + var token = this.expect(e1); + if (!token) { + this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); + } + return token; + }, - var element = path.split('.'), key; - for (var i = 0; element.length > 1; i++) { - key = ensureSafeMemberName(element.shift(), fullExp); - var propertyObj = (i === 0 && locals && locals[key]) || obj[key]; - if (!propertyObj) { - propertyObj = {}; - obj[key] = propertyObj; + peekToken: function() { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); } - obj = ensureSafeObject(propertyObj, fullExp); - } - key = ensureSafeMemberName(element.shift(), fullExp); - ensureSafeObject(obj[key], fullExp); - obj[key] = setValue; - return setValue; -} + return this.tokens[0]; + }, -var getterFnCacheDefault = createMap(); -var getterFnCacheExpensive = createMap(); + peek: function(e1, e2, e3, e4) { + return this.peekAhead(0, e1, e2, e3, e4); + }, -function isPossiblyDangerousMemberName(name) { - return name == 'constructor'; -} + peekAhead: function(i, e1, e2, e3, e4) { + if (this.tokens.length > i) { + var token = this.tokens[i]; + var t = token.text; + if (t === e1 || t === e2 || t === e3 || t === e4 || + (!e1 && !e2 && !e3 && !e4)) { + return token; + } + } + return false; + }, -/** - * Implementation of the "Black Hole" variant from: - * - http://jsperf.com/angularjs-parse-getter/4 - * - http://jsperf.com/path-evaluation-simplified/7 - */ -function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) { - ensureSafeMemberName(key0, fullExp); - ensureSafeMemberName(key1, fullExp); - ensureSafeMemberName(key2, fullExp); - ensureSafeMemberName(key3, fullExp); - ensureSafeMemberName(key4, fullExp); - var eso = function(o) { - return ensureSafeObject(o, fullExp); - }; - var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity; - var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity; - var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity; - var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity; - var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity; + expect: function(e1, e2, e3, e4) { + var token = this.peek(e1, e2, e3, e4); + if (token) { + this.tokens.shift(); + return token; + } + return false; + }, - return function cspSafeGetter(scope, locals) { - var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope; - if (pathVal == null) return pathVal; - pathVal = eso0(pathVal[key0]); + /* `undefined` is not a constant, it is an identifier, + * but using it as an identifier is not supported + */ + constants: { + 'true': { type: AST.Literal, value: true }, + 'false': { type: AST.Literal, value: false }, + 'null': { type: AST.Literal, value: null }, + 'undefined': {type: AST.Literal, value: undefined }, + 'this': {type: AST.ThisExpression } + } +}; - if (!key1) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso1(pathVal[key1]); +function ifDefined(v, d) { + return typeof v !== 'undefined' ? v : d; +} - if (!key2) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso2(pathVal[key2]); +function plusFn(l, r) { + if (typeof l === 'undefined') return r; + if (typeof r === 'undefined') return l; + return l + r; +} - if (!key3) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso3(pathVal[key3]); +function isStateless($filter, filterName) { + var fn = $filter(filterName); + return !fn.$stateful; +} - if (!key4) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso4(pathVal[key4]); +function findConstantAndWatchExpressions(ast, $filter) { + var allConstants; + var argsToWatch; + switch (ast.type) { + case AST.Program: + allConstants = true; + forEach(ast.body, function(expr) { + findConstantAndWatchExpressions(expr.expression, $filter); + allConstants = allConstants && expr.expression.constant; + }); + ast.constant = allConstants; + break; + case AST.Literal: + ast.constant = true; + ast.toWatch = []; + break; + case AST.UnaryExpression: + findConstantAndWatchExpressions(ast.argument, $filter); + ast.constant = ast.argument.constant; + ast.toWatch = ast.argument.toWatch; + break; + case AST.BinaryExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch); + break; + case AST.LogicalExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.ConditionalExpression: + findConstantAndWatchExpressions(ast.test, $filter); + findConstantAndWatchExpressions(ast.alternate, $filter); + findConstantAndWatchExpressions(ast.consequent, $filter); + ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.Identifier: + ast.constant = false; + ast.toWatch = [ast]; + break; + case AST.MemberExpression: + findConstantAndWatchExpressions(ast.object, $filter); + if (ast.computed) { + findConstantAndWatchExpressions(ast.property, $filter); + } + ast.constant = ast.object.constant && (!ast.computed || ast.property.constant); + ast.toWatch = [ast]; + break; + case AST.CallExpression: + allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false; + argsToWatch = []; + forEach(ast.arguments, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast]; + break; + case AST.AssignmentExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = [ast]; + break; + case AST.ArrayExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.elements, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ObjectExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.properties, function(property) { + findConstantAndWatchExpressions(property.value, $filter); + allConstants = allConstants && property.value.constant; + if (!property.value.constant) { + argsToWatch.push.apply(argsToWatch, property.value.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ThisExpression: + ast.constant = false; + ast.toWatch = []; + break; + } +} - return pathVal; - }; +function getInputs(body) { + if (body.length != 1) return; + var lastExpression = body[0].expression; + var candidate = lastExpression.toWatch; + if (candidate.length !== 1) return candidate; + return candidate[0] !== lastExpression ? candidate : undefined; } -function getterFnWithEnsureSafeObject(fn, fullExpression) { - return function(s, l) { - return fn(s, l, ensureSafeObject, fullExpression); - }; +function isAssignable(ast) { + return ast.type === AST.Identifier || ast.type === AST.MemberExpression; } -function getterFn(path, options, fullExp) { - var expensiveChecks = options.expensiveChecks; - var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault); - var fn = getterFnCache[path]; - if (fn) return fn; +function assignableAST(ast) { + if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) { + return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='}; + } +} +function isLiteral(ast) { + return ast.body.length === 0 || + ast.body.length === 1 && ( + ast.body[0].expression.type === AST.Literal || + ast.body[0].expression.type === AST.ArrayExpression || + ast.body[0].expression.type === AST.ObjectExpression); +} - var pathKeys = path.split('.'), - pathKeysLength = pathKeys.length; +function isConstant(ast) { + return ast.constant; +} - // http://jsperf.com/angularjs-parse-getter/6 - if (options.csp) { - if (pathKeysLength < 6) { - fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks); - } else { - fn = function cspSafeGetter(scope, locals) { - var i = 0, val; - do { - val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], - pathKeys[i++], fullExp, expensiveChecks)(scope, locals); +function ASTCompiler(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} - locals = undefined; // clear after first iteration - scope = val; - } while (i < pathKeysLength); - return val; - }; - } - } else { - var code = ''; - if (expensiveChecks) { - code += 's = eso(s, fe);\nl = eso(l, fe);\n'; - } - var needsEnsureSafeObject = expensiveChecks; - forEach(pathKeys, function(key, index) { - ensureSafeMemberName(key, fullExp); - var lookupJs = (index - // we simply dereference 's' on any .dot notation - ? 's' - // but if we are first then we check locals first, and if so read it first - : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '.' + key; - if (expensiveChecks || isPossiblyDangerousMemberName(key)) { - lookupJs = 'eso(' + lookupJs + ', fe)'; - needsEnsureSafeObject = true; - } - code += 'if(s == null) return undefined;\n' + - 's=' + lookupJs + ';\n'; +ASTCompiler.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.state = { + nextId: 0, + filters: {}, + expensiveChecks: expensiveChecks, + fn: {vars: [], body: [], own: {}}, + assign: {vars: [], body: [], own: {}}, + inputs: [] + }; + findConstantAndWatchExpressions(ast, self.$filter); + var extra = ''; + var assignable; + this.stage = 'assign'; + if ((assignable = assignableAST(ast))) { + this.state.computing = 'assign'; + var result = this.nextId(); + this.recurse(assignable, result); + extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l'); + } + var toWatch = getInputs(ast.body); + self.stage = 'inputs'; + forEach(toWatch, function(watch, key) { + var fnKey = 'fn' + key; + self.state[fnKey] = {vars: [], body: [], own: {}}; + self.state.computing = fnKey; + var intoId = self.nextId(); + self.recurse(watch, intoId); + self.return_(intoId); + self.state.inputs.push(fnKey); + watch.watchId = key; }); - code += 'return s;'; + this.state.computing = 'fn'; + this.stage = 'main'; + this.recurse(ast); + var fnString = + // The build and minification steps remove the string "use strict" from the code, but this is done using a regex. + // This is a workaround for this until we do a better job at only removing the prefix only when we should. + '"' + this.USE + ' ' + this.STRICT + '";\n' + + this.filterPrefix() + + 'var fn=' + this.generateFunction('fn', 's,l,a,i') + + extra + + this.watchFns() + + 'return fn;'; /* jshint -W054 */ - var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject + var fn = (new Function('$filter', + 'ensureSafeMemberName', + 'ensureSafeObject', + 'ensureSafeFunction', + 'ifDefined', + 'plus', + 'text', + fnString))( + this.$filter, + ensureSafeMemberName, + ensureSafeObject, + ensureSafeFunction, + ifDefined, + plusFn, + expression); /* jshint +W054 */ - evaledFnGetter.toString = valueFn(code); - if (needsEnsureSafeObject) { - evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp); - } - fn = evaledFnGetter; - } + this.state = this.stage = undefined; + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, - fn.sharedGetter = true; - fn.assign = function(self, value, locals) { - return setter(self, locals, path, value, path); - }; - getterFnCache[path] = fn; - return fn; -} + USE: 'use', -var objectValueOf = Object.prototype.valueOf; + STRICT: 'strict', -function getValueOf(value) { - return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); -} + watchFns: function() { + var result = []; + var fns = this.state.inputs; + var self = this; + forEach(fns, function(name) { + result.push('var ' + name + '=' + self.generateFunction(name, 's')); + }); + if (fns.length) { + result.push('fn.inputs=[' + fns.join(',') + '];'); + } + return result.join(''); + }, -/////////////////////////////////// + generateFunction: function(name, params) { + return 'function(' + params + '){' + + this.varsPrefix(name) + + this.body(name) + + '};'; + }, -/** - * @ngdoc service - * @name $parse - * @kind function - * - * @description - * - * Converts Angular {@link guide/expression expression} into a function. - * - * ```js - * var getter = $parse('user.name'); - * var setter = getter.assign; - * var context = {user:{name:'angular'}}; - * var locals = {user:{name:'local'}}; - * - * expect(getter(context)).toEqual('angular'); - * setter(context, 'newValue'); - * expect(context.user.name).toEqual('newValue'); - * expect(getter(context, locals)).toEqual('local'); - * ``` - * - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - * - * The returned function also has the following properties: - * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript - * literal. - * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript - * constant literals. - * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be - * set to a function to change its value on the given context. - * - */ + filterPrefix: function() { + var parts = []; + var self = this; + forEach(this.state.filters, function(id, filter) { + parts.push(id + '=$filter(' + self.escape(filter) + ')'); + }); + if (parts.length) return 'var ' + parts.join(',') + ';'; + return ''; + }, + varsPrefix: function(section) { + return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : ''; + }, -/** - * @ngdoc provider - * @name $parseProvider - * - * @description - * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} - * service. - */ -function $ParseProvider() { - var cacheDefault = createMap(); - var cacheExpensive = createMap(); + body: function(section) { + return this.state[section].body.join(''); + }, + recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var left, right, self = this, args, expression; + recursionFn = recursionFn || noop; + if (!skipWatchIdCheck && isDefined(ast.watchId)) { + intoId = intoId || this.nextId(); + this.if_('i', + this.lazyAssign(intoId, this.computedMember('i', ast.watchId)), + this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true) + ); + return; + } + switch (ast.type) { + case AST.Program: + forEach(ast.body, function(expression, pos) { + self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; }); + if (pos !== ast.body.length - 1) { + self.current().body.push(right, ';'); + } else { + self.return_(right); + } + }); + break; + case AST.Literal: + expression = this.escape(ast.value); + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.UnaryExpression: + this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; }); + expression = ast.operator + '(' + this.ifDefined(right, 0) + ')'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.BinaryExpression: + this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; }); + this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; }); + if (ast.operator === '+') { + expression = this.plus(left, right); + } else if (ast.operator === '-') { + expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0); + } else { + expression = '(' + left + ')' + ast.operator + '(' + right + ')'; + } + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.LogicalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.left, intoId); + self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); + recursionFn(intoId); + break; + case AST.ConditionalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.test, intoId); + self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); + recursionFn(intoId); + break; + case AST.Identifier: + intoId = intoId || this.nextId(); + if (nameId) { + nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s'); + nameId.computed = false; + nameId.name = ast.name; + } + ensureSafeMemberName(ast.name); + self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)), + function() { + self.if_(self.stage === 'inputs' || 's', function() { + if (create && create !== 1) { + self.if_( + self.not(self.nonComputedMember('s', ast.name)), + self.lazyAssign(self.nonComputedMember('s', ast.name), '{}')); + } + self.assign(intoId, self.nonComputedMember('s', ast.name)); + }); + }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name)) + ); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) { + self.addEnsureSafeObject(intoId); + } + recursionFn(intoId); + break; + case AST.MemberExpression: + left = nameId && (nameId.context = this.nextId()) || this.nextId(); + intoId = intoId || this.nextId(); + self.recurse(ast.object, left, undefined, function() { + self.if_(self.notNull(left), function() { + if (ast.computed) { + right = self.nextId(); + self.recurse(ast.property, right); + self.addEnsureSafeMemberName(right); + if (create && create !== 1) { + self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); + } + expression = self.ensureSafeObject(self.computedMember(left, right)); + self.assign(intoId, expression); + if (nameId) { + nameId.computed = true; + nameId.name = right; + } + } else { + ensureSafeMemberName(ast.property.name); + if (create && create !== 1) { + self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}')); + } + expression = self.nonComputedMember(left, ast.property.name); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) { + expression = self.ensureSafeObject(expression); + } + self.assign(intoId, expression); + if (nameId) { + nameId.computed = false; + nameId.name = ast.property.name; + } + } + }, function() { + self.assign(intoId, 'undefined'); + }); + recursionFn(intoId); + }, !!create); + break; + case AST.CallExpression: + intoId = intoId || this.nextId(); + if (ast.filter) { + right = self.filter(ast.callee.name); + args = []; + forEach(ast.arguments, function(expr) { + var argument = self.nextId(); + self.recurse(expr, argument); + args.push(argument); + }); + expression = right + '(' + args.join(',') + ')'; + self.assign(intoId, expression); + recursionFn(intoId); + } else { + right = self.nextId(); + left = {}; + args = []; + self.recurse(ast.callee, right, left, function() { + self.if_(self.notNull(right), function() { + self.addEnsureSafeFunction(right); + forEach(ast.arguments, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(self.ensureSafeObject(argument)); + }); + }); + if (left.name) { + if (!self.state.expensiveChecks) { + self.addEnsureSafeObject(left.context); + } + expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')'; + } else { + expression = right + '(' + args.join(',') + ')'; + } + expression = self.ensureSafeObject(expression); + self.assign(intoId, expression); + }, function() { + self.assign(intoId, 'undefined'); + }); + recursionFn(intoId); + }); + } + break; + case AST.AssignmentExpression: + right = this.nextId(); + left = {}; + if (!isAssignable(ast.left)) { + throw $parseMinErr('lval', 'Trying to assing a value to a non l-value'); + } + this.recurse(ast.left, undefined, left, function() { + self.if_(self.notNull(left.context), function() { + self.recurse(ast.right, right); + self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + expression = self.member(left.context, left.name, left.computed) + ast.operator + right; + self.assign(intoId, expression); + recursionFn(intoId || expression); + }); + }, 1); + break; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(argument); + }); + }); + expression = '[' + args.join(',') + ']'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + self.recurse(property.value, self.nextId(), undefined, function(expr) { + args.push(self.escape( + property.key.type === AST.Identifier ? property.key.name : + ('' + property.key.value)) + + ':' + expr); + }); + }); + expression = '{' + args.join(',') + '}'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.ThisExpression: + this.assign(intoId, 's'); + recursionFn('s'); + break; + case AST.NGValueParameter: + this.assign(intoId, 'v'); + recursionFn('v'); + break; + } + }, + getHasOwnProperty: function(element, property) { + var key = element + '.' + property; + var own = this.current().own; + if (!own.hasOwnProperty(key)) { + own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')'); + } + return own[key]; + }, - this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { - var $parseOptions = { - csp: $sniffer.csp, - expensiveChecks: false - }, - $parseOptionsExpensive = { - csp: $sniffer.csp, - expensiveChecks: true - }; + assign: function(id, value) { + if (!id) return; + this.current().body.push(id, '=', value, ';'); + return id; + }, - function wrapSharedExpression(exp) { - var wrapped = exp; + filter: function(filterName) { + if (!this.state.filters.hasOwnProperty(filterName)) { + this.state.filters[filterName] = this.nextId(true); + } + return this.state.filters[filterName]; + }, - if (exp.sharedGetter) { - wrapped = function $parseWrapper(self, locals) { - return exp(self, locals); - }; - wrapped.literal = exp.literal; - wrapped.constant = exp.constant; - wrapped.assign = exp.assign; - } + ifDefined: function(id, defaultValue) { + return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')'; + }, + + plus: function(left, right) { + return 'plus(' + left + ',' + right + ')'; + }, + + return_: function(id) { + this.current().body.push('return ', id, ';'); + }, - return wrapped; + if_: function(test, alternate, consequent) { + if (test === true) { + alternate(); + } else { + var body = this.current().body; + body.push('if(', test, '){'); + alternate(); + body.push('}'); + if (consequent) { + body.push('else{'); + consequent(); + body.push('}'); + } } + }, - return function $parse(exp, interceptorFn, expensiveChecks) { - var parsedExpression, oneTime, cacheKey; + not: function(expression) { + return '!(' + expression + ')'; + }, - switch (typeof exp) { - case 'string': - cacheKey = exp = exp.trim(); + notNull: function(expression) { + return expression + '!=null'; + }, - var cache = (expensiveChecks ? cacheExpensive : cacheDefault); - parsedExpression = cache[cacheKey]; + nonComputedMember: function(left, right) { + return left + '.' + right; + }, - if (!parsedExpression) { - if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { - oneTime = true; - exp = exp.substring(2); - } + computedMember: function(left, right) { + return left + '[' + right + ']'; + }, - var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; - var lexer = new Lexer(parseOptions); - var parser = new Parser(lexer, $filter, parseOptions); - parsedExpression = parser.parse(exp); + member: function(left, right, computed) { + if (computed) return this.computedMember(left, right); + return this.nonComputedMember(left, right); + }, - if (parsedExpression.constant) { - parsedExpression.$$watchDelegate = constantWatchDelegate; - } else if (oneTime) { - //oneTime is not part of the exp passed to the Parser so we may have to - //wrap the parsedExpression before adding a $$watchDelegate - parsedExpression = wrapSharedExpression(parsedExpression); - parsedExpression.$$watchDelegate = parsedExpression.literal ? - oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; - } else if (parsedExpression.inputs) { - parsedExpression.$$watchDelegate = inputsWatchDelegate; - } + addEnsureSafeObject: function(item) { + this.current().body.push(this.ensureSafeObject(item), ';'); + }, - cache[cacheKey] = parsedExpression; - } - return addInterceptor(parsedExpression, interceptorFn); + addEnsureSafeMemberName: function(item) { + this.current().body.push(this.ensureSafeMemberName(item), ';'); + }, - case 'function': - return addInterceptor(exp, interceptorFn); + addEnsureSafeFunction: function(item) { + this.current().body.push(this.ensureSafeFunction(item), ';'); + }, - default: - return addInterceptor(noop, interceptorFn); - } - }; + ensureSafeObject: function(item) { + return 'ensureSafeObject(' + item + ',text)'; + }, - function collectExpressionInputs(inputs, list) { - for (var i = 0, ii = inputs.length; i < ii; i++) { - var input = inputs[i]; - if (!input.constant) { - if (input.inputs) { - collectExpressionInputs(input.inputs, list); - } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better? - list.push(input); - } - } - } + ensureSafeMemberName: function(item) { + return 'ensureSafeMemberName(' + item + ',text)'; + }, - return list; - } + ensureSafeFunction: function(item) { + return 'ensureSafeFunction(' + item + ',text)'; + }, - function expressionInputDirtyCheck(newValue, oldValueOfValue) { + lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var self = this; + return function() { + self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck); + }; + }, - if (newValue == null || oldValueOfValue == null) { // null/undefined - return newValue === oldValueOfValue; - } + lazyAssign: function(id, value) { + var self = this; + return function() { + self.assign(id, value); + }; + }, - if (typeof newValue === 'object') { + stringEscapeRegex: /[^ a-zA-Z0-9]/g, - // attempt to convert the value to a primitive type - // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can - // be cheaply dirty-checked - newValue = getValueOf(newValue); + stringEscapeFn: function(c) { + return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }, - if (typeof newValue === 'object') { - // objects/arrays are not supported - deep-watching them would be too expensive - return false; - } + escape: function(value) { + if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'"; + if (isNumber(value)) return value.toString(); + if (value === true) return 'true'; + if (value === false) return 'false'; + if (value === null) return 'null'; + if (typeof value === 'undefined') return 'undefined'; - // fall-through to the primitive equality check - } + throw $parseMinErr('esc', 'IMPOSSIBLE'); + }, - //Primitive or NaN - return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); + nextId: function(skip, init) { + var id = 'v' + (this.state.nextId++); + if (!skip) { + this.current().vars.push(id + (init ? '=' + init : '')); } + return id; + }, - function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var inputExpressions = parsedExpression.$$inputs || - (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, [])); - - var lastResult; + current: function() { + return this.state[this.state.computing]; + } +}; - if (inputExpressions.length === 1) { - var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails - inputExpressions = inputExpressions[0]; - return scope.$watch(function expressionInputWatch(scope) { - var newInputValue = inputExpressions(scope); - if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) { - lastResult = parsedExpression(scope); - oldInputValue = newInputValue && getValueOf(newInputValue); - } - return lastResult; - }, listener, objectEquality); - } - var oldInputValueOfValues = []; - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails - } +function ASTInterpreter(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} - return scope.$watch(function expressionInputsWatch(scope) { - var changed = false; +ASTInterpreter.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.expression = expression; + this.expensiveChecks = expensiveChecks; + findConstantAndWatchExpressions(ast, self.$filter); + var assignable; + var assign; + if ((assignable = assignableAST(ast))) { + assign = this.recurse(assignable); + } + var toWatch = getInputs(ast.body); + var inputs; + if (toWatch) { + inputs = []; + forEach(toWatch, function(watch, key) { + var input = self.recurse(watch); + watch.input = input; + inputs.push(input); + watch.watchId = key; + }); + } + var expressions = []; + forEach(ast.body, function(expression) { + expressions.push(self.recurse(expression.expression)); + }); + var fn = ast.body.length === 0 ? function() {} : + ast.body.length === 1 ? expressions[0] : + function(scope, locals) { + var lastValue; + forEach(expressions, function(exp) { + lastValue = exp(scope, locals); + }); + return lastValue; + }; + if (assign) { + fn.assign = function(scope, value, locals) { + return assign(scope, locals, value); + }; + } + if (inputs) { + fn.inputs = inputs; + } + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - var newInputValue = inputExpressions[i](scope); - if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { - oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + recurse: function(ast, context, create) { + var left, right, self = this, args, expression; + if (ast.input) { + return this.inputs(ast.input, ast.watchId); + } + switch (ast.type) { + case AST.Literal: + return this.value(ast.value, context); + case AST.UnaryExpression: + right = this.recurse(ast.argument); + return this['unary' + ast.operator](right, context); + case AST.BinaryExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.LogicalExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.ConditionalExpression: + return this['ternary?:']( + this.recurse(ast.test), + this.recurse(ast.alternate), + this.recurse(ast.consequent), + context + ); + case AST.Identifier: + ensureSafeMemberName(ast.name, self.expression); + return self.identifier(ast.name, + self.expensiveChecks || isPossiblyDangerousMemberName(ast.name), + context, create, self.expression); + case AST.MemberExpression: + left = this.recurse(ast.object, false, !!create); + if (!ast.computed) { + ensureSafeMemberName(ast.property.name, self.expression); + right = ast.property.name; + } + if (ast.computed) right = this.recurse(ast.property); + return ast.computed ? + this.computedMember(left, right, context, create, self.expression) : + this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression); + case AST.CallExpression: + args = []; + forEach(ast.arguments, function(expr) { + args.push(self.recurse(expr)); + }); + if (ast.filter) right = this.$filter(ast.callee.name); + if (!ast.filter) right = this.recurse(ast.callee, true); + return ast.filter ? + function(scope, locals, assign, inputs) { + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(args[i](scope, locals, assign, inputs)); + } + var value = right.apply(undefined, values, inputs); + return context ? {context: undefined, name: undefined, value: value} : value; + } : + function(scope, locals, assign, inputs) { + var rhs = right(scope, locals, assign, inputs); + var value; + if (rhs.value != null) { + ensureSafeObject(rhs.context, self.expression); + ensureSafeFunction(rhs.value, self.expression); + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression)); + } + value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression); } + return context ? {value: value} : value; + }; + case AST.AssignmentExpression: + left = this.recurse(ast.left, true, 1); + right = this.recurse(ast.right); + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + ensureSafeObject(lhs.value, self.expression); + lhs.context[lhs.name] = rhs; + return context ? {value: rhs} : rhs; + }; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + args.push(self.recurse(expr)); + }); + return function(scope, locals, assign, inputs) { + var value = []; + for (var i = 0; i < args.length; ++i) { + value.push(args[i](scope, locals, assign, inputs)); } - - if (changed) { - lastResult = parsedExpression(scope); + return context ? {value: value} : value; + }; + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + args.push({key: property.key.type === AST.Identifier ? + property.key.name : + ('' + property.key.value), + value: self.recurse(property.value) + }); + }); + return function(scope, locals, assign, inputs) { + var value = {}; + for (var i = 0; i < args.length; ++i) { + value[args[i].key] = args[i].value(scope, locals, assign, inputs); } - - return lastResult; - }, listener, objectEquality); - } - - function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch, lastValue; - return unwatch = scope.$watch(function oneTimeWatch(scope) { - return parsedExpression(scope); - }, function oneTimeListener(value, old, scope) { - lastValue = value; - if (isFunction(listener)) { - listener.apply(this, arguments); - } - if (isDefined(value)) { - scope.$$postDigest(function() { - if (isDefined(lastValue)) { - unwatch(); - } - }); - } - }, objectEquality); + return context ? {value: value} : value; + }; + case AST.ThisExpression: + return function(scope) { + return context ? {value: scope} : scope; + }; + case AST.NGValueParameter: + return function(scope, locals, assign, inputs) { + return context ? {value: assign} : assign; + }; } + }, - function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch, lastValue; - return unwatch = scope.$watch(function oneTimeWatch(scope) { - return parsedExpression(scope); - }, function oneTimeListener(value, old, scope) { - lastValue = value; - if (isFunction(listener)) { - listener.call(this, value, old, scope); - } - if (isAllDefined(value)) { - scope.$$postDigest(function() { - if (isAllDefined(lastValue)) unwatch(); - }); + 'unary+': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = +arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary-': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = -arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary!': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = !argument(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary+': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = plusFn(lhs, rhs); + return context ? {value: arg} : arg; + }; + }, + 'binary-': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0); + return context ? {value: arg} : arg; + }; + }, + 'binary*': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary/': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary%': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary===': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary&&': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary||': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'ternary?:': function(test, alternate, consequent, context) { + return function(scope, locals, assign, inputs) { + var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + value: function(value, context) { + return function() { return context ? {context: undefined, name: undefined, value: value} : value; }; + }, + identifier: function(name, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var base = locals && (name in locals) ? locals : scope; + if (create && create !== 1 && base && !(base[name])) { + base[name] = {}; + } + var value = base ? base[name] : undefined; + if (expensiveChecks) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: base, name: name, value: value}; + } else { + return value; + } + }; + }, + computedMember: function(left, right, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs; + var value; + if (lhs != null) { + rhs = right(scope, locals, assign, inputs); + ensureSafeMemberName(rhs, expression); + if (create && create !== 1 && lhs && !(lhs[rhs])) { + lhs[rhs] = {}; } - }, objectEquality); - - function isAllDefined(value) { - var allDefined = true; - forEach(value, function(val) { - if (!isDefined(val)) allDefined = false; - }); - return allDefined; + value = lhs[rhs]; + ensureSafeObject(value, expression); } - } + if (context) { + return {context: lhs, name: rhs, value: value}; + } else { + return value; + } + }; + }, + nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + if (create && create !== 1 && lhs && !(lhs[right])) { + lhs[right] = {}; + } + var value = lhs != null ? lhs[right] : undefined; + if (expensiveChecks || isPossiblyDangerousMemberName(right)) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: lhs, name: right, value: value}; + } else { + return value; + } + }; + }, + inputs: function(input, watchId) { + return function(scope, value, locals, inputs) { + if (inputs) return inputs[watchId]; + return input(scope, value, locals); + }; + } +}; - function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch; - return unwatch = scope.$watch(function constantWatch(scope) { - return parsedExpression(scope); - }, function constantListener(value, old, scope) { - if (isFunction(listener)) { - listener.apply(this, arguments); - } - unwatch(); - }, objectEquality); - } +/** + * @constructor + */ +var Parser = function(lexer, $filter, options) { + this.lexer = lexer; + this.$filter = $filter; + this.options = options; + this.ast = new AST(this.lexer); + this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : + new ASTCompiler(this.ast, $filter); +}; - function addInterceptor(parsedExpression, interceptorFn) { - if (!interceptorFn) return parsedExpression; - var watchDelegate = parsedExpression.$$watchDelegate; +Parser.prototype = { + constructor: Parser, - var regularWatch = - watchDelegate !== oneTimeLiteralWatchDelegate && - watchDelegate !== oneTimeWatchDelegate; + parse: function(text) { + return this.astCompiler.compile(text, this.options.expensiveChecks); + } +}; - var fn = regularWatch ? function regularInterceptedExpression(scope, locals) { - var value = parsedExpression(scope, locals); - return interceptorFn(value, scope, locals); - } : function oneTimeInterceptedExpression(scope, locals) { - var value = parsedExpression(scope, locals); - var result = interceptorFn(value, scope, locals); - // we only return the interceptor's result if the - // initial value is defined (for bind-once) - return isDefined(value) ? result : value; - }; +////////////////////////////////////////////////// +// Parser helper functions +////////////////////////////////////////////////// - // Propagate $$watchDelegates other then inputsWatchDelegate - if (parsedExpression.$$watchDelegate && - parsedExpression.$$watchDelegate !== inputsWatchDelegate) { - fn.$$watchDelegate = parsedExpression.$$watchDelegate; - } else if (!interceptorFn.$stateful) { - // If there is an interceptor, but no watchDelegate then treat the interceptor like - // we treat filters - it is assumed to be a pure function unless flagged with $stateful - fn.$$watchDelegate = inputsWatchDelegate; - fn.inputs = [parsedExpression]; - } +function setter(obj, path, setValue, fullExp) { + ensureSafeObject(obj, fullExp); - return fn; + var element = path.split('.'), key; + for (var i = 0; element.length > 1; i++) { + key = ensureSafeMemberName(element.shift(), fullExp); + var propertyObj = ensureSafeObject(obj[key], fullExp); + if (!propertyObj) { + propertyObj = {}; + obj[key] = propertyObj; } - }]; + obj = propertyObj; + } + key = ensureSafeMemberName(element.shift(), fullExp); + ensureSafeObject(obj[key], fullExp); + obj[key] = setValue; + return setValue; +} + +var getterFnCacheDefault = createMap(); +var getterFnCacheExpensive = createMap(); + +function isPossiblyDangerousMemberName(name) { + return name == 'constructor'; +} + +var objectValueOf = Object.prototype.valueOf; + +function getValueOf(value) { + return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); } +/////////////////////////////////// + /** * @ngdoc service - * @name $q - * @requires $rootScope + * @name $parse + * @kind function * * @description - * A service that helps you run functions asynchronously, and use their return values (or exceptions) - * when they are done processing. - * - * This is an implementation of promises/deferred objects inspired by - * [Kris Kowal's Q](https://github.com/kriskowal/q). - * - * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred - * implementations, and the other which resembles ES6 promises to some degree. - * - * # $q constructor - * - * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` - * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony, - * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). * - * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are - * available yet. - * - * It can be used like so: + * Converts Angular {@link guide/expression expression} into a function. * * ```js - * // for the purpose of this example let's assume that variables `$q` and `okToGreet` - * // are available in the current lexical scope (they could have been injected or passed in). - * - * function asyncGreet(name) { - * // perform some asynchronous operation, resolve or reject the promise when appropriate. - * return $q(function(resolve, reject) { - * setTimeout(function() { - * if (okToGreet(name)) { - * resolve('Hello, ' + name + '!'); - * } else { - * reject('Greeting ' + name + ' is not allowed.'); - * } - * }, 1000); - * }); - * } + * var getter = $parse('user.name'); + * var setter = getter.assign; + * var context = {user:{name:'angular'}}; + * var locals = {user:{name:'local'}}; * - * var promise = asyncGreet('Robin Hood'); - * promise.then(function(greeting) { - * alert('Success: ' + greeting); - * }, function(reason) { - * alert('Failed: ' + reason); - * }); + * expect(getter(context)).toEqual('angular'); + * setter(context, 'newValue'); + * expect(context.user.name).toEqual('newValue'); + * expect(getter(context, locals)).toEqual('local'); * ``` * - * Note: progress/notify callbacks are not currently supported via the ES6-style interface. * - * However, the more traditional CommonJS-style usage is still available, and documented below. + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: * - * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an - * interface for interacting with an object that represents the result of an action that is - * performed asynchronously, and may or may not be finished at any given point in time. + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. * - * From the perspective of dealing with error handling, deferred and promise APIs are to - * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. + * The returned function also has the following properties: + * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript + * literal. + * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript + * constant literals. + * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be + * set to a function to change its value on the given context. * - * ```js - * // for the purpose of this example let's assume that variables `$q` and `okToGreet` - * // are available in the current lexical scope (they could have been injected or passed in). - * - * function asyncGreet(name) { - * var deferred = $q.defer(); - * - * setTimeout(function() { - * deferred.notify('About to greet ' + name + '.'); - * - * if (okToGreet(name)) { - * deferred.resolve('Hello, ' + name + '!'); - * } else { - * deferred.reject('Greeting ' + name + ' is not allowed.'); - * } - * }, 1000); - * - * return deferred.promise; - * } - * - * var promise = asyncGreet('Robin Hood'); - * promise.then(function(greeting) { - * alert('Success: ' + greeting); - * }, function(reason) { - * alert('Failed: ' + reason); - * }, function(update) { - * alert('Got notification: ' + update); - * }); - * ``` - * - * At first it might not be obvious why this extra complexity is worth the trouble. The payoff - * comes in the way of guarantees that promise and deferred APIs make, see - * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. - * - * Additionally the promise api allows for composition that is very hard to do with the - * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. - * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the - * section on serial or parallel joining of promises. - * - * # The Deferred API - * - * A new instance of deferred is constructed by calling `$q.defer()`. - * - * The purpose of the deferred object is to expose the associated Promise instance as well as APIs - * that can be used for signaling the successful or unsuccessful completion, as well as the status - * of the task. - * - * **Methods** - * - * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection - * constructed via `$q.reject`, the promise will be rejected instead. - * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to - * resolving it with a rejection constructed via `$q.reject`. - * - `notify(value)` - provides updates on the status of the promise's execution. This may be called - * multiple times before the promise is either resolved or rejected. - * - * **Properties** - * - * - promise – `{Promise}` – promise object associated with this deferred. - * - * - * # The Promise API - * - * A new promise instance is created when a deferred instance is created and can be retrieved by - * calling `deferred.promise`. - * - * The purpose of the promise object is to allow for interested parties to get access to the result - * of the deferred task when it completes. - * - * **Methods** - * - * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or - * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously - * as soon as the result is available. The callbacks are called with a single argument: the result - * or rejection reason. Additionally, the notify callback may be called zero or more times to - * provide a progress indication, before the promise is resolved or rejected. - * - * This method *returns a new promise* which is resolved or rejected via the return value of the - * `successCallback`, `errorCallback`. It also notifies via the return value of the - * `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback - * method. - * - * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` - * - * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, - * but to do so without modifying the final value. This is useful to release resources or do some - * clean-up that needs to be done whether the promise was rejected or resolved. See the [full - * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for - * more information. - * - * # Chaining promises - * - * Because calling the `then` method of a promise returns a new derived promise, it is easily - * possible to create a chain of promises: - * - * ```js - * promiseB = promiseA.then(function(result) { - * return result + 1; - * }); - * - * // promiseB will be resolved immediately after promiseA is resolved and its value - * // will be the result of promiseA incremented by 1 - * ``` - * - * It is possible to create chains of any length and since a promise can be resolved with another - * promise (which will defer its resolution further), it is possible to pause/defer resolution of - * the promises at any point in the chain. This makes it possible to implement powerful APIs like - * $http's response interceptors. - * - * - * # Differences between Kris Kowal's Q and $q - * - * There are two main differences: - * - * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation - * mechanism in angular, which means faster propagation of resolution or rejection into your - * models and avoiding unnecessary browser repaints, which would result in flickering UI. - * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains - * all the important functionality needed for common async tasks. - * - * # Testing - * - * ```js - * it('should simulate promise', inject(function($q, $rootScope) { - * var deferred = $q.defer(); - * var promise = deferred.promise; - * var resolvedValue; - * - * promise.then(function(value) { resolvedValue = value; }); - * expect(resolvedValue).toBeUndefined(); - * - * // Simulate resolving of promise - * deferred.resolve(123); - * // Note that the 'then' function does not get called synchronously. - * // This is because we want the promise API to always be async, whether or not - * // it got called synchronously or asynchronously. - * expect(resolvedValue).toBeUndefined(); - * - * // Propagate promise resolution to 'then' functions using $apply(). - * $rootScope.$apply(); - * expect(resolvedValue).toEqual(123); - * })); - * ``` - * - * @param {function(function, function)} resolver Function which is responsible for resolving or - * rejecting the newly created promise. The first parameter is a function which resolves the - * promise, the second parameter is a function which rejects the promise. - * - * @returns {Promise} The newly created promise. */ -function $QProvider() { - - this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { - return qFactory(function(callback) { - $rootScope.$evalAsync(callback); - }, $exceptionHandler); - }]; -} -function $$QProvider() { - this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { - return qFactory(function(callback) { - $browser.defer(callback); - }, $exceptionHandler); - }]; -} /** - * Constructs a promise manager. + * @ngdoc provider + * @name $parseProvider * - * @param {function(function)} nextTick Function for executing functions in the next turn. - * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for - * debugging purposes. - * @returns {object} Promise manager. + * @description + * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} + * service. */ -function qFactory(nextTick, exceptionHandler) { - var $qMinErr = minErr('$q', TypeError); - function callOnce(self, resolveFn, rejectFn) { - var called = false; - function wrap(fn) { - return function(value) { - if (called) return; - called = true; - fn.call(self, value); - }; - } +function $ParseProvider() { + var cacheDefault = createMap(); + var cacheExpensive = createMap(); - return [wrap(resolveFn), wrap(rejectFn)]; - } + this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { + var $parseOptions = { + csp: $sniffer.csp, + expensiveChecks: false + }, + $parseOptionsExpensive = { + csp: $sniffer.csp, + expensiveChecks: true + }; - /** - * @ngdoc method - * @name ng.$q#defer - * @kind function - * - * @description - * Creates a `Deferred` object which represents a task which will finish in the future. - * - * @returns {Deferred} Returns a new instance of deferred. - */ - var defer = function() { - return new Deferred(); - }; + return function $parse(exp, interceptorFn, expensiveChecks) { + var parsedExpression, oneTime, cacheKey; - function Promise() { - this.$$state = { status: 0 }; - } + switch (typeof exp) { + case 'string': + exp = exp.trim(); + cacheKey = exp; - Promise.prototype = { - then: function(onFulfilled, onRejected, progressBack) { - var result = new Deferred(); + var cache = (expensiveChecks ? cacheExpensive : cacheDefault); + parsedExpression = cache[cacheKey]; - this.$$state.pending = this.$$state.pending || []; - this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); - if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); + if (!parsedExpression) { + if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { + oneTime = true; + exp = exp.substring(2); + } + var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; + var lexer = new Lexer(parseOptions); + var parser = new Parser(lexer, $filter, parseOptions); + parsedExpression = parser.parse(exp); + if (parsedExpression.constant) { + parsedExpression.$$watchDelegate = constantWatchDelegate; + } else if (oneTime) { + parsedExpression.$$watchDelegate = parsedExpression.literal ? + oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; + } else if (parsedExpression.inputs) { + parsedExpression.$$watchDelegate = inputsWatchDelegate; + } + cache[cacheKey] = parsedExpression; + } + return addInterceptor(parsedExpression, interceptorFn); - return result.promise; - }, + case 'function': + return addInterceptor(exp, interceptorFn); - "catch": function(callback) { - return this.then(null, callback); - }, + default: + return noop; + } + }; - "finally": function(callback, progressBack) { - return this.then(function(value) { - return handleCallback(value, true, callback); - }, function(error) { - return handleCallback(error, false, callback); - }, progressBack); - } - }; + function expressionInputDirtyCheck(newValue, oldValueOfValue) { - //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native - function simpleBind(context, fn) { - return function(value) { - fn.call(context, value); - }; - } + if (newValue == null || oldValueOfValue == null) { // null/undefined + return newValue === oldValueOfValue; + } - function processQueue(state) { - var fn, promise, pending; + if (typeof newValue === 'object') { - pending = state.pending; - state.processScheduled = false; - state.pending = undefined; - for (var i = 0, ii = pending.length; i < ii; ++i) { - promise = pending[i][0]; - fn = pending[i][state.status]; - try { - if (isFunction(fn)) { - promise.resolve(fn(state.value)); - } else if (state.status === 1) { - promise.resolve(state.value); - } else { - promise.reject(state.value); + // attempt to convert the value to a primitive type + // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can + // be cheaply dirty-checked + newValue = getValueOf(newValue); + + if (typeof newValue === 'object') { + // objects/arrays are not supported - deep-watching them would be too expensive + return false; } - } catch (e) { - promise.reject(e); - exceptionHandler(e); + + // fall-through to the primitive equality check } + + //Primitive or NaN + return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); } - } - function scheduleProcessQueue(state) { - if (state.processScheduled || !state.pending) return; - state.processScheduled = true; - nextTick(function() { processQueue(state); }); - } + function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { + var inputExpressions = parsedExpression.inputs; + var lastResult; - function Deferred() { - this.promise = new Promise(); - //Necessary to support unbound execution :/ - this.resolve = simpleBind(this, this.resolve); - this.reject = simpleBind(this, this.reject); - this.notify = simpleBind(this, this.notify); - } + if (inputExpressions.length === 1) { + var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails + inputExpressions = inputExpressions[0]; + return scope.$watch(function expressionInputWatch(scope) { + var newInputValue = inputExpressions(scope); + if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) { + lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]); + oldInputValueOf = newInputValue && getValueOf(newInputValue); + } + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } - Deferred.prototype = { - resolve: function(val) { - if (this.promise.$$state.status) return; - if (val === this.promise) { - this.$$reject($qMinErr( - 'qcycle', - "Expected promise to be resolved with value other than itself '{0}'", - val)); - } else { - this.$$resolve(val); + var oldInputValueOfValues = []; + var oldInputValues = []; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails + oldInputValues[i] = null; } - }, + return scope.$watch(function expressionInputsWatch(scope) { + var changed = false; - $$resolve: function(val) { - var then, fns; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + var newInputValue = inputExpressions[i](scope); + if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { + oldInputValues[i] = newInputValue; + oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + } + } - fns = callOnce(this, this.$$resolve, this.$$reject); - try { - if ((isObject(val) || isFunction(val))) then = val && val.then; - if (isFunction(then)) { - this.promise.$$state.status = -1; - then.call(val, fns[0], fns[1], this.notify); - } else { - this.promise.$$state.value = val; - this.promise.$$state.status = 1; - scheduleProcessQueue(this.promise.$$state); + if (changed) { + lastResult = parsedExpression(scope, undefined, undefined, oldInputValues); } - } catch (e) { - fns[1](e); - exceptionHandler(e); - } - }, - reject: function(reason) { - if (this.promise.$$state.status) return; - this.$$reject(reason); - }, + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } - $$reject: function(reason) { - this.promise.$$state.value = reason; - this.promise.$$state.status = 2; - scheduleProcessQueue(this.promise.$$state); - }, + function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.apply(this, arguments); + } + if (isDefined(value)) { + scope.$$postDigest(function() { + if (isDefined(lastValue)) { + unwatch(); + } + }); + } + }, objectEquality); + } - notify: function(progress) { - var callbacks = this.promise.$$state.pending; + function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.call(this, value, old, scope); + } + if (isAllDefined(value)) { + scope.$$postDigest(function() { + if (isAllDefined(lastValue)) unwatch(); + }); + } + }, objectEquality); - if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) { - nextTick(function() { - var callback, result; - for (var i = 0, ii = callbacks.length; i < ii; i++) { - result = callbacks[i][0]; - callback = callbacks[i][3]; - try { - result.notify(isFunction(callback) ? callback(progress) : progress); - } catch (e) { - exceptionHandler(e); - } - } + function isAllDefined(value) { + var allDefined = true; + forEach(value, function(val) { + if (!isDefined(val)) allDefined = false; }); + return allDefined; } } - }; - - /** - * @ngdoc method - * @name $q#reject - * @kind function - * - * @description - * Creates a promise that is resolved as rejected with the specified `reason`. This api should be - * used to forward rejection in a chain of promises. If you are dealing with the last promise in - * a promise chain, you don't need to worry about it. - * - * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of - * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via - * a promise error callback and you want to forward the error to the promise derived from the - * current promise, you have to "rethrow" the error by returning a rejection constructed via - * `reject`. - * - * ```js - * promiseB = promiseA.then(function(result) { - * // success: do something and resolve promiseB - * // with the old or a new result - * return result; - * }, function(reason) { - * // error: handle the error if possible and - * // resolve promiseB with newPromiseOrValue, - * // otherwise forward the rejection to promiseB - * if (canHandle(reason)) { - * // handle the error and recover - * return newPromiseOrValue; - * } - * return $q.reject(reason); - * }); - * ``` - * - * @param {*} reason Constant, message, exception or an object representing the rejection reason. - * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. - */ - var reject = function(reason) { - var result = new Deferred(); - result.reject(reason); - return result.promise; - }; - var makePromise = function makePromise(value, resolved) { - var result = new Deferred(); - if (resolved) { - result.resolve(value); - } else { - result.reject(value); + function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch; + return unwatch = scope.$watch(function constantWatch(scope) { + return parsedExpression(scope); + }, function constantListener(value, old, scope) { + if (isFunction(listener)) { + listener.apply(this, arguments); + } + unwatch(); + }, objectEquality); } - return result.promise; - }; - var handleCallback = function handleCallback(value, isResolved, callback) { - var callbackOutput = null; - try { - if (isFunction(callback)) callbackOutput = callback(); - } catch (e) { - return makePromise(e, false); - } - if (isPromiseLike(callbackOutput)) { - return callbackOutput.then(function() { - return makePromise(value, isResolved); - }, function(error) { - return makePromise(error, false); - }); - } else { - return makePromise(value, isResolved); - } - }; + function addInterceptor(parsedExpression, interceptorFn) { + if (!interceptorFn) return parsedExpression; + var watchDelegate = parsedExpression.$$watchDelegate; - /** - * @ngdoc method - * @name $q#when - * @kind function - * - * @description - * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. - * This is useful when you are dealing with an object that might or might not be a promise, or if - * the promise comes from a source that can't be trusted. - * - * @param {*} value Value or a promise - * @returns {Promise} Returns a promise of the passed value or promise - */ - - - var when = function(value, callback, errback, progressBack) { - var result = new Deferred(); - result.resolve(value); - return result.promise.then(callback, errback, progressBack); - }; - - /** - * @ngdoc method - * @name $q#all - * @kind function - * - * @description - * Combines multiple promises into a single promise that is resolved when all of the input - * promises are resolved. - * - * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises. - * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, - * each value corresponding to the promise at the same index/key in the `promises` array/hash. - * If any of the promises is resolved with a rejection, this resulting promise will be rejected - * with the same rejection value. - */ - - function all(promises) { - var deferred = new Deferred(), - counter = 0, - results = isArray(promises) ? [] : {}; - - forEach(promises, function(promise, key) { - counter++; - when(promise).then(function(value) { - if (results.hasOwnProperty(key)) return; - results[key] = value; - if (!(--counter)) deferred.resolve(results); - }, function(reason) { - if (results.hasOwnProperty(key)) return; - deferred.reject(reason); - }); - }); - - if (counter === 0) { - deferred.resolve(results); - } - - return deferred.promise; - } - - var $Q = function Q(resolver) { - if (!isFunction(resolver)) { - throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); - } - - if (!(this instanceof Q)) { - // More useful when $Q is the Promise itself. - return new Q(resolver); - } + var regularWatch = + watchDelegate !== oneTimeLiteralWatchDelegate && + watchDelegate !== oneTimeWatchDelegate; - var deferred = new Deferred(); + var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + return interceptorFn(value, scope, locals); + } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + var result = interceptorFn(value, scope, locals); + // we only return the interceptor's result if the + // initial value is defined (for bind-once) + return isDefined(value) ? result : value; + }; - function resolveFn(value) { - deferred.resolve(value); - } + // Propagate $$watchDelegates other then inputsWatchDelegate + if (parsedExpression.$$watchDelegate && + parsedExpression.$$watchDelegate !== inputsWatchDelegate) { + fn.$$watchDelegate = parsedExpression.$$watchDelegate; + } else if (!interceptorFn.$stateful) { + // If there is an interceptor, but no watchDelegate then treat the interceptor like + // we treat filters - it is assumed to be a pure function unless flagged with $stateful + fn.$$watchDelegate = inputsWatchDelegate; + fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]; + } - function rejectFn(reason) { - deferred.reject(reason); + return fn; } - - resolver(resolveFn, rejectFn); - - return deferred.promise; - }; - - $Q.defer = defer; - $Q.reject = reject; - $Q.when = when; - $Q.all = all; - - return $Q; -} - -function $$RAFProvider() { //rAF - this.$get = ['$window', '$timeout', function($window, $timeout) { - var requestAnimationFrame = $window.requestAnimationFrame || - $window.webkitRequestAnimationFrame; - - var cancelAnimationFrame = $window.cancelAnimationFrame || - $window.webkitCancelAnimationFrame || - $window.webkitCancelRequestAnimationFrame; - - var rafSupported = !!requestAnimationFrame; - var raf = rafSupported - ? function(fn) { - var id = requestAnimationFrame(fn); - return function() { - cancelAnimationFrame(id); - }; - } - : function(fn) { - var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 - return function() { - $timeout.cancel(timer); - }; - }; - - raf.supported = rafSupported; - - return raf; }]; } /** - * DESIGN NOTES + * @ngdoc service + * @name $q + * @requires $rootScope * - * The design decisions behind the scope are heavily favored for speed and memory consumption. + * @description + * A service that helps you run functions asynchronously, and use their return values (or exceptions) + * when they are done processing. * - * The typical use of scope is to watch the expressions, which most of the time return the same - * value as last time so we optimize the operation. + * This is an implementation of promises/deferred objects inspired by + * [Kris Kowal's Q](https://github.com/kriskowal/q). * - * Closures construction is expensive in terms of speed as well as memory: - * - No closures, instead use prototypical inheritance for API - * - Internal state needs to be stored on scope directly, which means that private state is - * exposed as $$____ properties + * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred + * implementations, and the other which resembles ES6 promises to some degree. * - * Loop operations are optimized by using while(count--) { ... } - * - this means that in order to keep the same order of execution as addition we have to add - * items to the array at the beginning (unshift) instead of at the end (push) + * # $q constructor * - * Child scopes are created and removed often - * - Using an array would be slow since inserts in middle are expensive so we use linked list + * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` + * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony, + * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). * - * There are few watches then a lot of observers. This is why you don't want the observer to be - * implemented in the same way as watch. Watch requires return of initialization function which - * are expensive to construct. - */ - - -/** - * @ngdoc provider - * @name $rootScopeProvider - * @description + * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are + * available yet. * - * Provider for the $rootScope service. - */ - -/** - * @ngdoc method - * @name $rootScopeProvider#digestTtl - * @description + * It can be used like so: * - * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and - * assuming that the model is unstable. + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). * - * The current default is 10 iterations. + * function asyncGreet(name) { + * // perform some asynchronous operation, resolve or reject the promise when appropriate. + * return $q(function(resolve, reject) { + * setTimeout(function() { + * if (okToGreet(name)) { + * resolve('Hello, ' + name + '!'); + * } else { + * reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * }); + * } * - * In complex applications it's possible that the dependencies between `$watch`s will result in - * several digest iterations. However if an application needs more than the default 10 digest - * iterations for its model to stabilize then you should investigate what is causing the model to - * continuously change during the digest. + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }); + * ``` * - * Increasing the TTL could have performance implications, so you should not change it without - * proper justification. + * Note: progress/notify callbacks are not currently supported via the ES6-style interface. * - * @param {number} limit The number of digest iterations. - */ - - -/** - * @ngdoc service - * @name $rootScope - * @description + * However, the more traditional CommonJS-style usage is still available, and documented below. * - * Every application has a single root {@link ng.$rootScope.Scope scope}. - * All other scopes are descendant scopes of the root scope. Scopes provide separation - * between the model and the view, via a mechanism for watching the model for changes. - * They also provide an event emission/broadcast and subscription facility. See the - * {@link guide/scope developer guide on scopes}. - */ -function $RootScopeProvider() { - var TTL = 10; - var $rootScopeMinErr = minErr('$rootScope'); - var lastDirtyWatch = null; - var applyAsyncId = null; - - this.digestTtl = function(value) { - if (arguments.length) { - TTL = value; - } - return TTL; - }; - - this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', - function($injector, $exceptionHandler, $parse, $browser) { - - /** - * @ngdoc type - * @name $rootScope.Scope - * - * @description - * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the - * {@link auto.$injector $injector}. Child scopes are created using the - * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when - * compiled HTML template is executed.) - * - * Here is a simple scope snippet to show how you can interact with the scope. - * ```html - * <file src="./test/ng/rootScopeSpec.js" tag="docs1" /> - * ``` - * - * # Inheritance - * A scope can inherit from a parent scope, as in this example: - * ```js - var parent = $rootScope; - var child = parent.$new(); - - parent.salutation = "Hello"; - expect(child.salutation).toEqual('Hello'); - - child.salutation = "Welcome"; + * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an + * interface for interacting with an object that represents the result of an action that is + * performed asynchronously, and may or may not be finished at any given point in time. + * + * From the perspective of dealing with error handling, deferred and promise APIs are to + * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * var deferred = $q.defer(); + * + * setTimeout(function() { + * deferred.notify('About to greet ' + name + '.'); + * + * if (okToGreet(name)) { + * deferred.resolve('Hello, ' + name + '!'); + * } else { + * deferred.reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * + * return deferred.promise; + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }, function(update) { + * alert('Got notification: ' + update); + * }); + * ``` + * + * At first it might not be obvious why this extra complexity is worth the trouble. The payoff + * comes in the way of guarantees that promise and deferred APIs make, see + * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. + * + * Additionally the promise api allows for composition that is very hard to do with the + * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. + * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the + * section on serial or parallel joining of promises. + * + * # The Deferred API + * + * A new instance of deferred is constructed by calling `$q.defer()`. + * + * The purpose of the deferred object is to expose the associated Promise instance as well as APIs + * that can be used for signaling the successful or unsuccessful completion, as well as the status + * of the task. + * + * **Methods** + * + * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection + * constructed via `$q.reject`, the promise will be rejected instead. + * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to + * resolving it with a rejection constructed via `$q.reject`. + * - `notify(value)` - provides updates on the status of the promise's execution. This may be called + * multiple times before the promise is either resolved or rejected. + * + * **Properties** + * + * - promise – `{Promise}` – promise object associated with this deferred. + * + * + * # The Promise API + * + * A new promise instance is created when a deferred instance is created and can be retrieved by + * calling `deferred.promise`. + * + * The purpose of the promise object is to allow for interested parties to get access to the result + * of the deferred task when it completes. + * + * **Methods** + * + * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or + * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously + * as soon as the result is available. The callbacks are called with a single argument: the result + * or rejection reason. Additionally, the notify callback may be called zero or more times to + * provide a progress indication, before the promise is resolved or rejected. + * + * This method *returns a new promise* which is resolved or rejected via the return value of the + * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved + * with the value which is resolved in that promise using + * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)). + * It also notifies via the return value of the `notifyCallback` method. The promise cannot be + * resolved or rejected from the notifyCallback method. + * + * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` + * + * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, + * but to do so without modifying the final value. This is useful to release resources or do some + * clean-up that needs to be done whether the promise was rejected or resolved. See the [full + * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for + * more information. + * + * # Chaining promises + * + * Because calling the `then` method of a promise returns a new derived promise, it is easily + * possible to create a chain of promises: + * + * ```js + * promiseB = promiseA.then(function(result) { + * return result + 1; + * }); + * + * // promiseB will be resolved immediately after promiseA is resolved and its value + * // will be the result of promiseA incremented by 1 + * ``` + * + * It is possible to create chains of any length and since a promise can be resolved with another + * promise (which will defer its resolution further), it is possible to pause/defer resolution of + * the promises at any point in the chain. This makes it possible to implement powerful APIs like + * $http's response interceptors. + * + * + * # Differences between Kris Kowal's Q and $q + * + * There are two main differences: + * + * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation + * mechanism in angular, which means faster propagation of resolution or rejection into your + * models and avoiding unnecessary browser repaints, which would result in flickering UI. + * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains + * all the important functionality needed for common async tasks. + * + * # Testing + * + * ```js + * it('should simulate promise', inject(function($q, $rootScope) { + * var deferred = $q.defer(); + * var promise = deferred.promise; + * var resolvedValue; + * + * promise.then(function(value) { resolvedValue = value; }); + * expect(resolvedValue).toBeUndefined(); + * + * // Simulate resolving of promise + * deferred.resolve(123); + * // Note that the 'then' function does not get called synchronously. + * // This is because we want the promise API to always be async, whether or not + * // it got called synchronously or asynchronously. + * expect(resolvedValue).toBeUndefined(); + * + * // Propagate promise resolution to 'then' functions using $apply(). + * $rootScope.$apply(); + * expect(resolvedValue).toEqual(123); + * })); + * ``` + * + * @param {function(function, function)} resolver Function which is responsible for resolving or + * rejecting the newly created promise. The first parameter is a function which resolves the + * promise, the second parameter is a function which rejects the promise. + * + * @returns {Promise} The newly created promise. + */ +function $QProvider() { + + this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { + return qFactory(function(callback) { + $rootScope.$evalAsync(callback); + }, $exceptionHandler); + }]; +} + +function $$QProvider() { + this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { + return qFactory(function(callback) { + $browser.defer(callback); + }, $exceptionHandler); + }]; +} + +/** + * Constructs a promise manager. + * + * @param {function(function)} nextTick Function for executing functions in the next turn. + * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for + * debugging purposes. + * @returns {object} Promise manager. + */ +function qFactory(nextTick, exceptionHandler) { + var $qMinErr = minErr('$q', TypeError); + function callOnce(self, resolveFn, rejectFn) { + var called = false; + function wrap(fn) { + return function(value) { + if (called) return; + called = true; + fn.call(self, value); + }; + } + + return [wrap(resolveFn), wrap(rejectFn)]; + } + + /** + * @ngdoc method + * @name ng.$q#defer + * @kind function + * + * @description + * Creates a `Deferred` object which represents a task which will finish in the future. + * + * @returns {Deferred} Returns a new instance of deferred. + */ + var defer = function() { + return new Deferred(); + }; + + function Promise() { + this.$$state = { status: 0 }; + } + + Promise.prototype = { + then: function(onFulfilled, onRejected, progressBack) { + var result = new Deferred(); + + this.$$state.pending = this.$$state.pending || []; + this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); + if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); + + return result.promise; + }, + + "catch": function(callback) { + return this.then(null, callback); + }, + + "finally": function(callback, progressBack) { + return this.then(function(value) { + return handleCallback(value, true, callback); + }, function(error) { + return handleCallback(error, false, callback); + }, progressBack); + } + }; + + //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native + function simpleBind(context, fn) { + return function(value) { + fn.call(context, value); + }; + } + + function processQueue(state) { + var fn, deferred, pending; + + pending = state.pending; + state.processScheduled = false; + state.pending = undefined; + for (var i = 0, ii = pending.length; i < ii; ++i) { + deferred = pending[i][0]; + fn = pending[i][state.status]; + try { + if (isFunction(fn)) { + deferred.resolve(fn(state.value)); + } else if (state.status === 1) { + deferred.resolve(state.value); + } else { + deferred.reject(state.value); + } + } catch (e) { + deferred.reject(e); + exceptionHandler(e); + } + } + } + + function scheduleProcessQueue(state) { + if (state.processScheduled || !state.pending) return; + state.processScheduled = true; + nextTick(function() { processQueue(state); }); + } + + function Deferred() { + this.promise = new Promise(); + //Necessary to support unbound execution :/ + this.resolve = simpleBind(this, this.resolve); + this.reject = simpleBind(this, this.reject); + this.notify = simpleBind(this, this.notify); + } + + Deferred.prototype = { + resolve: function(val) { + if (this.promise.$$state.status) return; + if (val === this.promise) { + this.$$reject($qMinErr( + 'qcycle', + "Expected promise to be resolved with value other than itself '{0}'", + val)); + } else { + this.$$resolve(val); + } + + }, + + $$resolve: function(val) { + var then, fns; + + fns = callOnce(this, this.$$resolve, this.$$reject); + try { + if ((isObject(val) || isFunction(val))) then = val && val.then; + if (isFunction(then)) { + this.promise.$$state.status = -1; + then.call(val, fns[0], fns[1], this.notify); + } else { + this.promise.$$state.value = val; + this.promise.$$state.status = 1; + scheduleProcessQueue(this.promise.$$state); + } + } catch (e) { + fns[1](e); + exceptionHandler(e); + } + }, + + reject: function(reason) { + if (this.promise.$$state.status) return; + this.$$reject(reason); + }, + + $$reject: function(reason) { + this.promise.$$state.value = reason; + this.promise.$$state.status = 2; + scheduleProcessQueue(this.promise.$$state); + }, + + notify: function(progress) { + var callbacks = this.promise.$$state.pending; + + if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) { + nextTick(function() { + var callback, result; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + result = callbacks[i][0]; + callback = callbacks[i][3]; + try { + result.notify(isFunction(callback) ? callback(progress) : progress); + } catch (e) { + exceptionHandler(e); + } + } + }); + } + } + }; + + /** + * @ngdoc method + * @name $q#reject + * @kind function + * + * @description + * Creates a promise that is resolved as rejected with the specified `reason`. This api should be + * used to forward rejection in a chain of promises. If you are dealing with the last promise in + * a promise chain, you don't need to worry about it. + * + * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of + * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via + * a promise error callback and you want to forward the error to the promise derived from the + * current promise, you have to "rethrow" the error by returning a rejection constructed via + * `reject`. + * + * ```js + * promiseB = promiseA.then(function(result) { + * // success: do something and resolve promiseB + * // with the old or a new result + * return result; + * }, function(reason) { + * // error: handle the error if possible and + * // resolve promiseB with newPromiseOrValue, + * // otherwise forward the rejection to promiseB + * if (canHandle(reason)) { + * // handle the error and recover + * return newPromiseOrValue; + * } + * return $q.reject(reason); + * }); + * ``` + * + * @param {*} reason Constant, message, exception or an object representing the rejection reason. + * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. + */ + var reject = function(reason) { + var result = new Deferred(); + result.reject(reason); + return result.promise; + }; + + var makePromise = function makePromise(value, resolved) { + var result = new Deferred(); + if (resolved) { + result.resolve(value); + } else { + result.reject(value); + } + return result.promise; + }; + + var handleCallback = function handleCallback(value, isResolved, callback) { + var callbackOutput = null; + try { + if (isFunction(callback)) callbackOutput = callback(); + } catch (e) { + return makePromise(e, false); + } + if (isPromiseLike(callbackOutput)) { + return callbackOutput.then(function() { + return makePromise(value, isResolved); + }, function(error) { + return makePromise(error, false); + }); + } else { + return makePromise(value, isResolved); + } + }; + + /** + * @ngdoc method + * @name $q#when + * @kind function + * + * @description + * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. + * This is useful when you are dealing with an object that might or might not be a promise, or if + * the promise comes from a source that can't be trusted. + * + * @param {*} value Value or a promise + * @returns {Promise} Returns a promise of the passed value or promise + */ + + + var when = function(value, callback, errback, progressBack) { + var result = new Deferred(); + result.resolve(value); + return result.promise.then(callback, errback, progressBack); + }; + + /** + * @ngdoc method + * @name $q#resolve + * @kind function + * + * @description + * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6. + * + * @param {*} value Value or a promise + * @returns {Promise} Returns a promise of the passed value or promise + */ + var resolve = when; + + /** + * @ngdoc method + * @name $q#all + * @kind function + * + * @description + * Combines multiple promises into a single promise that is resolved when all of the input + * promises are resolved. + * + * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises. + * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, + * each value corresponding to the promise at the same index/key in the `promises` array/hash. + * If any of the promises is resolved with a rejection, this resulting promise will be rejected + * with the same rejection value. + */ + + function all(promises) { + var deferred = new Deferred(), + counter = 0, + results = isArray(promises) ? [] : {}; + + forEach(promises, function(promise, key) { + counter++; + when(promise).then(function(value) { + if (results.hasOwnProperty(key)) return; + results[key] = value; + if (!(--counter)) deferred.resolve(results); + }, function(reason) { + if (results.hasOwnProperty(key)) return; + deferred.reject(reason); + }); + }); + + if (counter === 0) { + deferred.resolve(results); + } + + return deferred.promise; + } + + var $Q = function Q(resolver) { + if (!isFunction(resolver)) { + throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); + } + + if (!(this instanceof Q)) { + // More useful when $Q is the Promise itself. + return new Q(resolver); + } + + var deferred = new Deferred(); + + function resolveFn(value) { + deferred.resolve(value); + } + + function rejectFn(reason) { + deferred.reject(reason); + } + + resolver(resolveFn, rejectFn); + + return deferred.promise; + }; + + $Q.defer = defer; + $Q.reject = reject; + $Q.when = when; + $Q.resolve = resolve; + $Q.all = all; + + return $Q; +} + +function $$RAFProvider() { //rAF + this.$get = ['$window', '$timeout', function($window, $timeout) { + var requestAnimationFrame = $window.requestAnimationFrame || + $window.webkitRequestAnimationFrame; + + var cancelAnimationFrame = $window.cancelAnimationFrame || + $window.webkitCancelAnimationFrame || + $window.webkitCancelRequestAnimationFrame; + + var rafSupported = !!requestAnimationFrame; + var rafFn = rafSupported + ? function(fn) { + var id = requestAnimationFrame(fn); + return function() { + cancelAnimationFrame(id); + }; + } + : function(fn) { + var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 + return function() { + $timeout.cancel(timer); + }; + }; + + queueFn.supported = rafSupported; + + var cancelLastRAF; + var taskCount = 0; + var taskQueue = []; + return queueFn; + + function flush() { + for (var i = 0; i < taskQueue.length; i++) { + var task = taskQueue[i]; + if (task) { + taskQueue[i] = null; + task(); + } + } + taskCount = taskQueue.length = 0; + } + + function queueFn(asyncFn) { + var index = taskQueue.length; + + taskCount++; + taskQueue.push(asyncFn); + + if (index === 0) { + cancelLastRAF = rafFn(flush); + } + + return function cancelQueueFn() { + if (index >= 0) { + taskQueue[index] = null; + index = null; + + if (--taskCount === 0 && cancelLastRAF) { + cancelLastRAF(); + cancelLastRAF = null; + taskQueue.length = 0; + } + } + }; + } + }]; +} + +/** + * DESIGN NOTES + * + * The design decisions behind the scope are heavily favored for speed and memory consumption. + * + * The typical use of scope is to watch the expressions, which most of the time return the same + * value as last time so we optimize the operation. + * + * Closures construction is expensive in terms of speed as well as memory: + * - No closures, instead use prototypical inheritance for API + * - Internal state needs to be stored on scope directly, which means that private state is + * exposed as $$____ properties + * + * Loop operations are optimized by using while(count--) { ... } + * - this means that in order to keep the same order of execution as addition we have to add + * items to the array at the beginning (unshift) instead of at the end (push) + * + * Child scopes are created and removed often + * - Using an array would be slow since inserts in middle are expensive so we use linked list + * + * There are few watches then a lot of observers. This is why you don't want the observer to be + * implemented in the same way as watch. Watch requires return of initialization function which + * are expensive to construct. + */ + + +/** + * @ngdoc provider + * @name $rootScopeProvider + * @description + * + * Provider for the $rootScope service. + */ + +/** + * @ngdoc method + * @name $rootScopeProvider#digestTtl + * @description + * + * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that the dependencies between `$watch`s will result in + * several digest iterations. However if an application needs more than the default 10 digest + * iterations for its model to stabilize then you should investigate what is causing the model to + * continuously change during the digest. + * + * Increasing the TTL could have performance implications, so you should not change it without + * proper justification. + * + * @param {number} limit The number of digest iterations. + */ + + +/** + * @ngdoc service + * @name $rootScope + * @description + * + * Every application has a single root {@link ng.$rootScope.Scope scope}. + * All other scopes are descendant scopes of the root scope. Scopes provide separation + * between the model and the view, via a mechanism for watching the model for changes. + * They also provide an event emission/broadcast and subscription facility. See the + * {@link guide/scope developer guide on scopes}. + */ +function $RootScopeProvider() { + var TTL = 10; + var $rootScopeMinErr = minErr('$rootScope'); + var lastDirtyWatch = null; + var applyAsyncId = null; + + this.digestTtl = function(value) { + if (arguments.length) { + TTL = value; + } + return TTL; + }; + + function createChildScopeClass(parent) { + function ChildScope() { + this.$$watchers = this.$$nextSibling = + this.$$childHead = this.$$childTail = null; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$id = nextUid(); + this.$$ChildScope = null; + } + ChildScope.prototype = parent; + return ChildScope; + } + + this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', + function($injector, $exceptionHandler, $parse, $browser) { + + function destroyChildScope($event) { + $event.currentScope.$$destroyed = true; + } + + /** + * @ngdoc type + * @name $rootScope.Scope + * + * @description + * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the + * {@link auto.$injector $injector}. Child scopes are created using the + * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when + * compiled HTML template is executed.) + * + * Here is a simple scope snippet to show how you can interact with the scope. + * ```html + * <file src="./test/ng/rootScopeSpec.js" tag="docs1" /> + * ``` + * + * # Inheritance + * A scope can inherit from a parent scope, as in this example: + * ```js + var parent = $rootScope; + var child = parent.$new(); + + parent.salutation = "Hello"; + expect(child.salutation).toEqual('Hello'); + + child.salutation = "Welcome"; expect(child.salutation).toEqual('Welcome'); expect(parent.salutation).toEqual('Hello'); * ``` @@ -13607,6 +15055,7 @@ function $RootScopeProvider() { this.$$destroyed = false; this.$$listeners = {}; this.$$listenerCount = {}; + this.$$watchersCount = 0; this.$$isolateBindings = null; } @@ -13677,15 +15126,7 @@ function $RootScopeProvider() { // Only create a child scope class if somebody asks for one, // but cache it to allow the VM to optimize lookups. if (!this.$$ChildScope) { - this.$$ChildScope = function ChildScope() { - this.$$watchers = this.$$nextSibling = - this.$$childHead = this.$$childTail = null; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$id = nextUid(); - this.$$ChildScope = null; - }; - this.$$ChildScope.prototype = this; + this.$$ChildScope = createChildScopeClass(this); } child = new this.$$ChildScope(); } @@ -13703,13 +15144,9 @@ function $RootScopeProvider() { // prototypically. In all other cases, this property needs to be set // when the parent scope is destroyed. // The listener needs to be added after the parent is set - if (isolate || parent != this) child.$on('$destroy', destroyChild); + if (isolate || parent != this) child.$on('$destroy', destroyChildScope); return child; - - function destroyChild() { - child.$$destroyed = true; - } }, /** @@ -13828,11 +15265,11 @@ function $RootScopeProvider() { * comparing for reference equality. * @returns {function()} Returns a deregistration function for this listener. */ - $watch: function(watchExp, listener, objectEquality) { + $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) { var get = $parse(watchExp); if (get.$$watchDelegate) { - return get.$$watchDelegate(this, listener, objectEquality, get); + return get.$$watchDelegate(this, listener, objectEquality, get, watchExp); } var scope = this, array = scope.$$watchers, @@ -13840,7 +15277,7 @@ function $RootScopeProvider() { fn: listener, last: initWatchVal, get: get, - exp: watchExp, + exp: prettyPrintExpression || watchExp, eq: !!objectEquality }; @@ -13856,9 +15293,12 @@ function $RootScopeProvider() { // we use unshift since we use a while loop in $digest for speed. // the while loop reads in reverse order. array.unshift(watcher); + incrementWatchersCount(this, 1); return function deregisterWatch() { - arrayRemove(array, watcher); + if (arrayRemove(array, watcher) >= 0) { + incrementWatchersCount(scope, -1); + } lastDirtyWatch = null; }; }, @@ -14266,7 +15706,7 @@ function $RootScopeProvider() { // Insanity Warning: scope depth-first traversal // yes, this code is a bit crazy, but it works and we have tests to prove it! // this piece should be kept in sync with the traversal in $broadcast - if (!(next = (current.$$childHead || + if (!(next = ((current.$$watchersCount && current.$$childHead) || (current !== target && current.$$nextSibling)))) { while (current !== target && !(next = current.$$nextSibling)) { current = current.$parent; @@ -14333,22 +15773,27 @@ function $RootScopeProvider() { * clean up DOM bindings before an element is removed from the DOM. */ $destroy: function() { - // we can't destroy the root scope or a scope that has been already destroyed + // We can't destroy a scope that has been already destroyed. if (this.$$destroyed) return; var parent = this.$parent; this.$broadcast('$destroy'); this.$$destroyed = true; - if (this === $rootScope) return; + if (this === $rootScope) { + //Remove handlers attached to window when $rootScope is removed + $browser.$$applicationDestroyed(); + } + + incrementWatchersCount(this, -this.$$watchersCount); for (var eventName in this.$$listenerCount) { decrementListenerCount(this, this.$$listenerCount[eventName], eventName); } // sever all the references to parent scopes (after this cleanup, the current scope should // not be retained by any of our references and should be eligible for garbage collection) - if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; @@ -14762,6 +16207,11 @@ function $RootScopeProvider() { $rootScope.$$phase = null; } + function incrementWatchersCount(current, count) { + do { + current.$$watchersCount += count; + } while ((current = current.$parent)); + } function decrementListenerCount(current, count, name) { do { @@ -14870,6 +16320,17 @@ function $$SanitizeUriProvider() { }; } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + var $sceMinErr = minErr('$sce'); var SCE_CONTEXTS = { @@ -15283,7 +16744,7 @@ function $SceDelegateProvider() { * Here's an example of a binding in a privileged context: * * ``` - * <input ng-model="userHtml"> + * <input ng-model="userHtml" aria-label="User input"> * <div ng-bind-html="userHtml"></div> * ``` * @@ -15667,7 +17128,7 @@ function $SceProvider() { * escaping. * * @param {string} type The kind of context in which this value is safe for use. e.g. url, - * resource_url, html, js and css. + * resourceUrl, html, js and css. * @param {*} value The value that that should be considered trusted/safe. * @returns {*} A value that can be used to stand in for the provided `value` in places * where Angular expects a $sce.trustAs() return value. @@ -15936,7 +17397,7 @@ function $SnifferProvider() { this.$get = ['$window', '$document', function($window, $document) { var eventSupport = {}, android = - int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), + toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), boxee = /Boxee/i.test(($window.navigator || {}).userAgent), document = $document[0] || {}, vendorPrefix, @@ -15963,8 +17424,8 @@ function $SnifferProvider() { animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); if (android && (!transitions || !animations)) { - transitions = isString(document.body.style.webkitTransition); - animations = isString(document.body.style.webkitAnimation); + transitions = isString(bodyStyle.webkitTransition); + animations = isString(bodyStyle.webkitAnimation); } } @@ -16012,23 +17473,34 @@ var $compileMinErr = minErr('$compile'); * @name $templateRequest * * @description - * The `$templateRequest` service downloads the provided template using `$http` and, upon success, - * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data - * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted - * by setting the 2nd parameter of the function to true). - * - * @param {string} tpl The HTTP request template URL + * The `$templateRequest` service runs security checks then downloads the provided template using + * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request + * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the + * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the + * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted + * when `tpl` is of type string and `$templateCache` has the matching entry. + * + * @param {string|TrustedResourceUrl} tpl The HTTP request template URL * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty * - * @return {Promise} the HTTP Promise for the given. + * @return {Promise} a promise for the HTTP response data of the given URL. * * @property {number} totalPendingRequests total amount of pending template requests being downloaded. */ function $TemplateRequestProvider() { - this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) { + this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) { function handleRequestFn(tpl, ignoreRequestError) { handleRequestFn.totalPendingRequests++; + // We consider the template cache holds only trusted templates, so + // there's no need to go through whitelisting again for keys that already + // are included in there. This also makes Angular accept any script + // directive, no matter its name. However, we still need to unwrap trusted + // types. + if (!isString(tpl) || !$templateCache.get(tpl)) { + tpl = $sce.getTrustedResourceUrl(tpl); + } + var transformResponse = $http.defaults && $http.defaults.transformResponse; if (isArray(transformResponse)) { @@ -16049,12 +17521,14 @@ function $TemplateRequestProvider() { handleRequestFn.totalPendingRequests--; }) .then(function(response) { + $templateCache.put(tpl, response.data); return response.data; }, handleError); function handleError(resp) { if (!ignoreRequestError) { - throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl); + throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})', + tpl, resp.status, resp.statusText); } return $q.reject(resp); } @@ -16184,6 +17658,7 @@ function $$TestabilityProvider() { function $TimeoutProvider() { this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', function($rootScope, $browser, $q, $$q, $exceptionHandler) { + var deferreds = {}; @@ -16196,31 +17671,42 @@ function $TimeoutProvider() { * block and delegates any exceptions to * {@link ng.$exceptionHandler $exceptionHandler} service. * - * The return value of registering a timeout function is a promise, which will be resolved when - * the timeout is reached and the timeout function is executed. + * The return value of calling `$timeout` is a promise, which will be resolved when + * the delay has passed and the timeout function, if provided, is executed. * * To cancel a timeout request, call `$timeout.cancel(promise)`. * * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to * synchronously flush the queue of deferred functions. * - * @param {function()} fn A function, whose execution should be delayed. + * If you only want a promise that will be resolved after some specified delay + * then you can call `$timeout` without the `fn` function. + * + * @param {function()=} fn A function, whose execution should be delayed. * @param {number=} [delay=0] Delay in milliseconds. * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this * promise will be resolved with is the return value of the `fn` function. * */ function timeout(fn, delay, invokeApply) { - var skipApply = (isDefined(invokeApply) && !invokeApply), + if (!isFunction(fn)) { + invokeApply = delay; + delay = fn; + fn = noop; + } + + var args = sliceArgs(arguments, 3), + skipApply = (isDefined(invokeApply) && !invokeApply), deferred = (skipApply ? $$q : $q).defer(), promise = deferred.promise, timeoutId; timeoutId = $browser.defer(function() { try { - deferred.resolve(fn()); + deferred.resolve(fn.apply(null, args)); } catch (e) { deferred.reject(e); $exceptionHandler(e); @@ -16395,7 +17881,7 @@ function urlIsSameOrigin(requestUrl) { }]); </script> <div ng-controller="ExampleController"> - <input type="text" ng-model="greeting" /> + <input type="text" ng-model="greeting" aria-label="greeting" /> <button ng-click="doGreeting(greeting)">ALERT</button> </div> </file> @@ -16412,6 +17898,61 @@ function $WindowProvider() { this.$get = valueFn(window); } +/** + * @name $$cookieReader + * @requires $document + * + * @description + * This is a private service for reading cookies used by $http and ngCookies + * + * @return {Object} a key/value map of the current cookies + */ +function $$CookieReader($document) { + var rawDocument = $document[0] || {}; + var lastCookies = {}; + var lastCookieString = ''; + + function safeDecodeURIComponent(str) { + try { + return decodeURIComponent(str); + } catch (e) { + return str; + } + } + + return function() { + var cookieArray, cookie, i, index, name; + var currentCookieString = rawDocument.cookie || ''; + + if (currentCookieString !== lastCookieString) { + lastCookieString = currentCookieString; + cookieArray = lastCookieString.split('; '); + lastCookies = {}; + + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf('='); + if (index > 0) { //ignore nameless cookies + name = safeDecodeURIComponent(cookie.substring(0, index)); + // the first value that is seen for a cookie is the most + // specific one. values for the same cookie name that + // follow are for less specific paths. + if (lastCookies[name] === undefined) { + lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); + } + } + } + } + return lastCookies; + }; +} + +$$CookieReader.$inject = ['$document']; + +function $$CookieReaderProvider() { + this.$get = $$CookieReader; +} + /* global currencyFilter: true, dateFilter: true, filterFilter: true, @@ -16432,6 +17973,13 @@ function $WindowProvider() { * Dependency Injected. To achieve this a filter definition consists of a factory function which is * annotated with dependencies and is responsible for creating a filter function. * + * <div class="alert alert-warning"> + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + * </div> + * * ```js * // Filter registration * function MyModule($provide, $filterProvider) { @@ -16513,6 +18061,13 @@ function $FilterProvider($provide) { * @name $filterProvider#register * @param {string|Object} name Name of the filter function, or an object map of filters where * the keys are the filter names and the values are the filter factories. + * + * <div class="alert alert-warning"> + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + * </div> * @returns {Object} Registered filter instance, or if a map of filters was provided then a map * of the registered filter instances. */ @@ -16594,9 +18149,11 @@ function $FilterProvider($provide) { * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but * **will** be matched by `{$: 'John'}`. * - * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The - * function is called for each element of `array`. The final result is an array of those - * elements that the predicate returned true for. + * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters. + * The function is called for each element of the array, with the element, its index, and + * the entire array itself as arguments. + * + * The final result is an array of those elements that the predicate returned true for. * * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in * determining if the expected value (from the filter expression) and actual value (from @@ -16614,6 +18171,9 @@ function $FilterProvider($provide) { * - `false|undefined`: A short hand for a function which will look for a substring match in case * insensitive way. * + * Primitive values are converted to strings. Objects are not compared against primitives, + * unless they have a custom `toString` method (e.g. `Date` objects). + * * @example <example> <file name="index.html"> @@ -16624,7 +18184,7 @@ function $FilterProvider($provide) { {name:'Julie', phone:'555-8765'}, {name:'Juliette', phone:'555-5678'}]"></div> - Search: <input ng-model="searchText"> + <label>Search: <input ng-model="searchText"></label> <table id="searchTextResults"> <tr><th>Name</th><th>Phone</th></tr> <tr ng-repeat="friend in friends | filter:searchText"> @@ -16633,10 +18193,10 @@ function $FilterProvider($provide) { </tr> </table> <hr> - Any: <input ng-model="search.$"> <br> - Name only <input ng-model="search.name"><br> - Phone only <input ng-model="search.phone"><br> - Equality <input type="checkbox" ng-model="strict"><br> + <label>Any: <input ng-model="search.$"></label> <br> + <label>Name only <input ng-model="search.name"></label><br> + <label>Phone only <input ng-model="search.phone"></label><br> + <label>Equality <input type="checkbox" ng-model="strict"></label><br> <table id="searchObjResults"> <tr><th>Name</th><th>Phone</th></tr> <tr ng-repeat="friendObj in friends | filter:search:strict"> @@ -16684,16 +18244,24 @@ function $FilterProvider($provide) { */ function filterFilter() { return function(array, expression, comparator) { - if (!isArray(array)) return array; + if (!isArrayLike(array)) { + if (array == null) { + return array; + } else { + throw minErr('filter')('notarray', 'Expected array but received: {0}', array); + } + } + var expressionType = getTypeForFilter(expression); var predicateFn; var matchAgainstAnyProp; - switch (typeof expression) { + switch (expressionType) { case 'function': predicateFn = expression; break; case 'boolean': + case 'null': case 'number': case 'string': matchAgainstAnyProp = true; @@ -16706,7 +18274,7 @@ function filterFilter() { return array; } - return array.filter(predicateFn); + return Array.prototype.filter.call(array, predicateFn); }; } @@ -16719,8 +18287,16 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) { comparator = equals; } else if (!isFunction(comparator)) { comparator = function(actual, expected) { - if (isObject(actual) || isObject(expected)) { - // Prevent an object to be considered equal to a string like `'[object'` + if (isUndefined(actual)) { + // No substring matching against `undefined` + return false; + } + if ((actual === null) || (expected === null)) { + // No substring matching against `null`; only match against `null` + return actual === expected; + } + if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) { + // Should not compare primitives against objects, unless they have custom `toString` method return false; } @@ -16741,8 +18317,8 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) { } function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { - var actualType = typeof actual; - var expectedType = typeof expected; + var actualType = getTypeForFilter(actual); + var expectedType = getTypeForFilter(expected); if ((expectedType === 'string') && (expected.charAt(0) === '!')) { return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); @@ -16767,7 +18343,7 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc } else if (expectedType === 'object') { for (key in expected) { var expectedVal = expected[key]; - if (isFunction(expectedVal)) { + if (isFunction(expectedVal) || isUndefined(expectedVal)) { continue; } @@ -16789,6 +18365,11 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc } } +// Used for easily differentiating between `null` and actual `object` +function getTypeForFilter(val) { + return (val === null) ? 'null' : typeof val; +} + /** * @ngdoc filter * @name currency @@ -16814,7 +18395,7 @@ function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatc }]); </script> <div ng-controller="ExampleController"> - <input type="number" ng-model="amount"> <br> + <input type="number" ng-model="amount" aria-label="amount"> <br> default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br> custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span> no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span> @@ -16869,8 +18450,11 @@ function currencyFilter($locale) { * @description * Formats a number as text. * + * If the input is null or undefined, it will just be returned. + * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned. * If the input is not a number an empty string is returned. * + * * @param {number|string} number Number to format. * @param {(number|string)=} fractionSize Number of decimal places to round the number to. * If this is not provided then the fraction size is computed from the current locale's number @@ -16887,7 +18471,7 @@ function currencyFilter($locale) { }]); </script> <div ng-controller="ExampleController"> - Enter number: <input ng-model='val'><br> + <label>Enter number: <input ng-model='val'></label><br> Default formatting: <span id='number-default'>{{val | number}}</span><br> No fractions: <span>{{val | number:0}}</span><br> Negative number: <span>{{-val | number:4}}</span> @@ -16927,16 +18511,22 @@ function numberFilter($locale) { var DECIMAL_SEP = '.'; function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - if (!isFinite(number) || isObject(number)) return ''; + if (isObject(number)) return ''; var isNegative = number < 0; number = Math.abs(number); + + var isInfinity = number === Infinity; + if (!isInfinity && !isFinite(number)) return ''; + var numStr = number + '', formatedText = '', + hasExponent = false, parts = []; - var hasExponent = false; - if (numStr.indexOf('e') !== -1) { + if (isInfinity) formatedText = '\u221e'; + + if (!isInfinity && numStr.indexOf('e') !== -1) { var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); if (match && match[2] == '-' && match[3] > fractionSize + 1) { number = 0; @@ -16946,7 +18536,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { } } - if (!hasExponent) { + if (!isInfinity && !hasExponent) { var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; // determine fractionSize if it is not specified @@ -17015,8 +18605,9 @@ function padNumber(num, digits, trim) { } num = '' + num; while (num.length < digits) num = '0' + num; - if (trim) + if (trim) { num = num.substr(num.length - digits); + } return neg + num; } @@ -17025,8 +18616,9 @@ function dateGetter(name, size, offset, trim) { offset = offset || 0; return function(date) { var value = date['get' + name](); - if (offset > 0 || value > -offset) + if (offset > 0 || value > -offset) { value += offset; + } if (value === 0 && offset == -12) value = 12; return padNumber(value, size, trim); }; @@ -17041,8 +18633,8 @@ function dateStrGetter(name, shortForm) { }; } -function timeZoneGetter(date) { - var zone = -1 * date.getTimezoneOffset(); +function timeZoneGetter(date, formats, offset) { + var zone = -1 * offset; var paddedZone = (zone >= 0) ? "+" : ""; paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + @@ -17081,6 +18673,14 @@ function ampmGetter(date, formats) { return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; } +function eraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; +} + +function longEraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; +} + var DATE_FORMATS = { yyyy: dateGetter('FullYear', 4), yy: dateGetter('FullYear', 2, 0, true), @@ -17107,10 +18707,14 @@ var DATE_FORMATS = { a: ampmGetter, Z: timeZoneGetter, ww: weekGetter(2), - w: weekGetter(1) + w: weekGetter(1), + G: eraGetter, + GG: eraGetter, + GGG: eraGetter, + GGGG: longEraGetter }; -var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/, +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, NUMBER_STRING = /^\-?\d+$/; /** @@ -17147,6 +18751,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year + * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD') + * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini') * * `format` string can also be one of the following predefined * {@link guide/i18n localizable formats}: @@ -17172,7 +18778,9 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d * specified in the string input, the time is considered to be in the local timezone. * @param {string=} format Formatting rules (see Description). If not specified, * `mediumDate` is used. - * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported. + * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) * If not specified, the timezone of the browser will be used. * @returns {string} Formatted string or the input if input is not recognized as date/millis. * @@ -17218,13 +18826,13 @@ function dateFilter($locale) { timeSetter = match[8] ? date.setUTCHours : date.setHours; if (match[9]) { - tzHour = int(match[9] + match[10]); - tzMin = int(match[9] + match[11]); + tzHour = toInt(match[9] + match[10]); + tzMin = toInt(match[9] + match[11]); } - dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3])); - var h = int(match[4] || 0) - tzHour; - var m = int(match[5] || 0) - tzMin; - var s = int(match[6] || 0); + dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3])); + var h = toInt(match[4] || 0) - tzHour; + var m = toInt(match[5] || 0) - tzMin; + var s = toInt(match[6] || 0); var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); timeSetter.call(date, h, m, s, ms); return date; @@ -17241,14 +18849,14 @@ function dateFilter($locale) { format = format || 'mediumDate'; format = $locale.DATETIME_FORMATS[format] || format; if (isString(date)) { - date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date); + date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date); } if (isNumber(date)) { date = new Date(date); } - if (!isDate(date)) { + if (!isDate(date) || !isFinite(date.getTime())) { return date; } @@ -17263,13 +18871,14 @@ function dateFilter($locale) { } } - if (timezone && timezone === 'UTC') { - date = new Date(date.getTime()); - date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); + var dateTimezoneOffset = date.getTimezoneOffset(); + if (timezone) { + dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + date = convertTimezoneToLocal(date, timezone, true); } forEach(parts, function(value) { fn = DATE_FORMATS[value]; - text += fn ? fn(date, $locale.DATETIME_FORMATS) + text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); }); @@ -17355,7 +18964,10 @@ var uppercaseFilter = valueFn(uppercase); * @param {string|number} limit The length of the returned array or string. If the `limit` number * is positive, `limit` number of items from the beginning of the source array/string are copied. * If the number is negative, `limit` number of items from the end of the source array/string - * are copied. The `limit` will be trimmed if it exceeds `array.length` + * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined, + * the input will be returned unchanged. + * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin` + * indicates an offset from the end of `input`. Defaults to `0`. * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array * had less than `limit` elements. * @@ -17374,11 +18986,20 @@ var uppercaseFilter = valueFn(uppercase); }]); </script> <div ng-controller="ExampleController"> - Limit {{numbers}} to: <input type="number" step="1" ng-model="numLimit"> + <label> + Limit {{numbers}} to: + <input type="number" step="1" ng-model="numLimit"> + </label> <p>Output numbers: {{ numbers | limitTo:numLimit }}</p> - Limit {{letters}} to: <input type="number" step="1" ng-model="letterLimit"> + <label> + Limit {{letters}} to: + <input type="number" step="1" ng-model="letterLimit"> + </label> <p>Output letters: {{ letters | limitTo:letterLimit }}</p> - Limit {{longNumber}} to: <input type="number" step="1" ng-model="longNumberLimit"> + <label> + Limit {{longNumber}} to: + <input type="number" step="1" ng-model="longNumberLimit"> + </label> <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p> </div> </file> @@ -17427,21 +19048,28 @@ var uppercaseFilter = valueFn(uppercase); </example> */ function limitToFilter() { - return function(input, limit) { - if (isNumber(input)) input = input.toString(); - if (!isArray(input) && !isString(input)) return input; - + return function(input, limit, begin) { if (Math.abs(Number(limit)) === Infinity) { limit = Number(limit); } else { - limit = int(limit); + limit = toInt(limit); } + if (isNaN(limit)) return input; + + if (isNumber(input)) input = input.toString(); + if (!isArray(input) && !isString(input)) return input; - //NaN check on limit - if (limit) { - return limit > 0 ? input.slice(0, limit) : input.slice(limit); + begin = (!begin || isNaN(begin)) ? 0 : toInt(begin); + begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin; + + if (limit >= 0) { + return input.slice(begin, begin + limit); } else { - return isString(input) ? "" : []; + if (begin === 0) { + return input.slice(limit, input.length); + } else { + return input.slice(Math.max(0, begin + limit), begin); + } } }; } @@ -17454,7 +19082,7 @@ function limitToFilter() { * @description * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically * for strings and numerically for numbers. Note: if you notice numbers are not being sorted - * correctly, make sure they are actually being saved as numbers and not strings. + * as expected, make sure they are actually being saved as numbers and not strings. * * @param {Array} array The array to sort. * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be @@ -17463,7 +19091,7 @@ function limitToFilter() { * Can be one of: * * - `function`: Getter function. The result of this function will be sorted using the - * `<`, `=`, `>` operator. + * `<`, `===`, `>` operator. * - `string`: An Angular expression. The result of this expression is used to compare elements * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by * 3 first characters of a property called `name`). The result of a constant expression @@ -17480,6 +19108,43 @@ function limitToFilter() { * @param {boolean=} reverse Reverse the order of the array. * @returns {Array} Sorted copy of the source array. * + * + * @example + * The example below demonstrates a simple ngRepeat, where the data is sorted + * by age in descending order (predicate is set to `'-age'`). + * `reverse` is not set, which means it defaults to `false`. + <example module="orderByExample"> + <file name="index.html"> + <script> + angular.module('orderByExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.friends = + [{name:'John', phone:'555-1212', age:10}, + {name:'Mary', phone:'555-9876', age:19}, + {name:'Mike', phone:'555-4321', age:21}, + {name:'Adam', phone:'555-5678', age:35}, + {name:'Julie', phone:'555-8765', age:29}]; + }]); + </script> + <div ng-controller="ExampleController"> + <table class="friend"> + <tr> + <th>Name</th> + <th>Phone Number</th> + <th>Age</th> + </tr> + <tr ng-repeat="friend in friends | orderBy:'-age'"> + <td>{{friend.name}}</td> + <td>{{friend.phone}}</td> + <td>{{friend.age}}</td> + </tr> + </table> + </div> + </file> + </example> + * + * The predicate and reverse parameters can be controlled dynamically through scope properties, + * as shown in the next example. * @example <example module="orderByExample"> <file name="index.html"> @@ -17492,19 +19157,40 @@ function limitToFilter() { {name:'Mike', phone:'555-4321', age:21}, {name:'Adam', phone:'555-5678', age:35}, {name:'Julie', phone:'555-8765', age:29}]; - $scope.predicate = '-age'; + $scope.predicate = 'age'; + $scope.reverse = true; + $scope.order = function(predicate) { + $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false; + $scope.predicate = predicate; + }; }]); </script> + <style type="text/css"> + .sortorder:after { + content: '\25b2'; + } + .sortorder.reverse:after { + content: '\25bc'; + } + </style> <div ng-controller="ExampleController"> <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre> <hr/> [ <a href="" ng-click="predicate=''">unsorted</a> ] <table class="friend"> <tr> - <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a> - (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th> - <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th> - <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th> + <th> + <a href="" ng-click="order('name')">Name</a> + <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span> + </th> + <th> + <a href="" ng-click="order('phone')">Phone Number</a> + <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span> + </th> + <th> + <a href="" ng-click="order('age')">Age</a> + <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span> + </th> </tr> <tr ng-repeat="friend in friends | orderBy:predicate:reverse"> <td>{{friend.name}}</td> @@ -17564,90 +19250,116 @@ function limitToFilter() { orderByFilter.$inject = ['$parse']; function orderByFilter($parse) { return function(array, sortPredicate, reverseOrder) { + if (!(isArrayLike(array))) return array; - sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate]; + + if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; } if (sortPredicate.length === 0) { sortPredicate = ['+']; } - sortPredicate = sortPredicate.map(function(predicate) { - var descending = false, get = predicate || identity; - if (isString(predicate)) { + + var predicates = processPredicates(sortPredicate, reverseOrder); + + // The next three lines are a version of a Swartzian Transform idiom from Perl + // (sometimes called the Decorate-Sort-Undecorate idiom) + // See https://en.wikipedia.org/wiki/Schwartzian_transform + var compareValues = Array.prototype.map.call(array, getComparisonObject); + compareValues.sort(doComparison); + array = compareValues.map(function(item) { return item.value; }); + + return array; + + function getComparisonObject(value, index) { + return { + value: value, + predicateValues: predicates.map(function(predicate) { + return getPredicateValue(predicate.get(value), index); + }) + }; + } + + function doComparison(v1, v2) { + var result = 0; + for (var index=0, length = predicates.length; index < length; ++index) { + result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending; + if (result) break; + } + return result; + } + }; + + function processPredicates(sortPredicate, reverseOrder) { + reverseOrder = reverseOrder ? -1 : 1; + return sortPredicate.map(function(predicate) { + var descending = 1, get = identity; + + if (isFunction(predicate)) { + get = predicate; + } else if (isString(predicate)) { if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { - descending = predicate.charAt(0) == '-'; + descending = predicate.charAt(0) == '-' ? -1 : 1; predicate = predicate.substring(1); } - if (predicate === '') { - // Effectively no predicate was passed so we compare identity - return reverseComparator(compare, descending); - } - get = $parse(predicate); - if (get.constant) { - var key = get(); - return reverseComparator(function(a, b) { - return compare(a[key], b[key]); - }, descending); + if (predicate !== '') { + get = $parse(predicate); + if (get.constant) { + var key = get(); + get = function(value) { return value[key]; }; + } } } - return reverseComparator(function(a, b) { - return compare(get(a),get(b)); - }, descending); + return { get: get, descending: descending * reverseOrder }; }); - return slice.call(array).sort(reverseComparator(comparator, reverseOrder)); + } - function comparator(o1, o2) { - for (var i = 0; i < sortPredicate.length; i++) { - var comp = sortPredicate[i](o1, o2); - if (comp !== 0) return comp; - } - return 0; - } - function reverseComparator(comp, descending) { - return descending - ? function(a, b) {return comp(b,a);} - : comp; + function isPrimitive(value) { + switch (typeof value) { + case 'number': /* falls through */ + case 'boolean': /* falls through */ + case 'string': + return true; + default: + return false; } + } - function isPrimitive(value) { - switch (typeof value) { - case 'number': /* falls through */ - case 'boolean': /* falls through */ - case 'string': - return true; - default: - return false; - } + function objectValue(value, index) { + // If `valueOf` is a valid function use that + if (typeof value.valueOf === 'function') { + value = value.valueOf(); + if (isPrimitive(value)) return value; } - - function objectToString(value) { - if (value === null) return 'null'; - if (typeof value.valueOf === 'function') { - value = value.valueOf(); - if (isPrimitive(value)) return value; - } - if (typeof value.toString === 'function') { - value = value.toString(); - if (isPrimitive(value)) return value; - } - return ''; + // If `toString` is a valid function and not the one from `Object.prototype` use that + if (hasCustomToString(value)) { + value = value.toString(); + if (isPrimitive(value)) return value; } + // We have a basic object so we use the position of the object in the collection + return index; + } - function compare(v1, v2) { - var t1 = typeof v1; - var t2 = typeof v2; - if (t1 === t2 && t1 === "object") { - v1 = objectToString(v1); - v2 = objectToString(v2); - } - if (t1 === t2) { - if (t1 === "string") { - v1 = v1.toLowerCase(); - v2 = v2.toLowerCase(); - } - if (v1 === v2) return 0; - return v1 < v2 ? -1 : 1; - } else { - return t1 < t2 ? -1 : 1; + function getPredicateValue(value, index) { + var type = typeof value; + if (value === null) { + type = 'string'; + value = 'null'; + } else if (type === 'string') { + value = value.toLowerCase(); + } else if (type === 'object') { + value = objectValue(value, index); + } + return { value: value, type: type }; + } + + function compare(v1, v2) { + var result = 0; + if (v1.type === v2.type) { + if (v1.value !== v2.value) { + result = v1.value < v2.value ? -1 : 1; } + } else { + result = v1.type < v2.type ? -1 : 1; } - }; + return result; + } } function ngDirective(directive) { @@ -17676,7 +19388,7 @@ function ngDirective(directive) { var htmlAnchorDirective = valueFn({ restrict: 'E', compile: function(element, attr) { - if (!attr.href && !attr.xlinkHref && !attr.name) { + if (!attr.href && !attr.xlinkHref) { return function(scope, element) { // If the linked element is not an anchor tag anymore, do nothing if (element[0].nodeName.toLowerCase() !== 'a') return; @@ -17763,7 +19475,7 @@ var htmlAnchorDirective = valueFn({ }, 5000, 'page should navigate to /123'); }); - xit('should execute ng-click but not reload when href empty string and name specified', function() { + it('should execute ng-click but not reload when href empty string and name specified', function() { element(by.id('link-4')).click(); expect(element(by.model('value')).getAttribute('value')).toEqual('4'); expect(element(by.id('link-4')).getAttribute('href')).toBe(''); @@ -17808,12 +19520,12 @@ var htmlAnchorDirective = valueFn({ * * The buggy way to write it: * ```html - * <img src="http://www.gravatar.com/avatar/{{hash}}"/> + * <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/> * ``` * * The correct way to write it: * ```html - * <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/> + * <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" /> * ``` * * @element IMG @@ -17834,12 +19546,12 @@ var htmlAnchorDirective = valueFn({ * * The buggy way to write it: * ```html - * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/> + * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/> * ``` * * The correct way to write it: * ```html - * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/> + * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" /> * ``` * * @element IMG @@ -17854,25 +19566,29 @@ var htmlAnchorDirective = valueFn({ * * @description * - * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs: + * This directive sets the `disabled` attribute on the element if the + * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `disabled` + * attribute. The following example would make the button enabled on Chrome/Firefox + * but not on older IEs: + * * ```html - * <div ng-init="scope = { isDisabled: false }"> - * <button disabled="{{scope.isDisabled}}">Disabled</button> + * <!-- See below for an example of ng-disabled being used correctly --> + * <div ng-init="isDisabled = false"> + * <button disabled="{{isDisabled}}">Disabled</button> * </div> * ``` * - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as disabled. (Their presence means true and their absence means false.) + * This is because the HTML specification does not require browsers to preserve the values of + * boolean attributes such as `disabled` (Their presence means true and their absence means false.) * If we put an Angular interpolation expression into such an attribute then the * binding information would be lost when the browser removes the attribute. - * The `ngDisabled` directive solves this problem for the `disabled` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. * * @example <example> <file name="index.html"> - Click me to toggle: <input type="checkbox" ng-model="checked"><br/> + <label>Click me to toggle: <input type="checkbox" ng-model="checked"></label><br/> <button ng-model="button" ng-disabled="checked">Button</button> </file> <file name="protractor.js" type="protractor"> @@ -17886,7 +19602,7 @@ var htmlAnchorDirective = valueFn({ * * @element INPUT * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, - * then special attribute "disabled" will be set on the element + * then the `disabled` attribute will be set on the element */ @@ -17897,6 +19613,13 @@ var htmlAnchorDirective = valueFn({ * @priority 100 * * @description + * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy. + * + * Note that this directive should not be used together with {@link ngModel `ngModel`}, + * as this can lead to unexpected behavior. + * + * ### Why do we need `ngChecked`? + * * The HTML specification does not require browsers to preserve the values of boolean attributes * such as checked. (Their presence means true and their absence means false.) * If we put an Angular interpolation expression into such an attribute then the @@ -17907,8 +19630,8 @@ var htmlAnchorDirective = valueFn({ * @example <example> <file name="index.html"> - Check me to check both: <input type="checkbox" ng-model="master"><br/> - <input id="checkSlave" type="checkbox" ng-checked="master"> + <label>Check me to check both: <input type="checkbox" ng-model="master"></label><br/> + <input id="checkSlave" type="checkbox" ng-checked="master" aria-label="Slave input"> </file> <file name="protractor.js" type="protractor"> it('should check both checkBoxes', function() { @@ -17921,7 +19644,7 @@ var htmlAnchorDirective = valueFn({ * * @element INPUT * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, - * then special attribute "checked" will be set on the element + * then the `checked` attribute will be set on the element */ @@ -17942,8 +19665,8 @@ var htmlAnchorDirective = valueFn({ * @example <example> <file name="index.html"> - Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/> - <input type="text" ng-readonly="checked" value="I'm Angular"/> + <label>Check me to make text readonly: <input type="checkbox" ng-model="checked"></label><br/> + <input type="text" ng-readonly="checked" value="I'm Angular" aria-label="Readonly field" /> </file> <file name="protractor.js" type="protractor"> it('should toggle readonly attr', function() { @@ -17978,8 +19701,8 @@ var htmlAnchorDirective = valueFn({ * @example <example> <file name="index.html"> - Check me to select: <input type="checkbox" ng-model="selected"><br/> - <select> + <label>Check me to select: <input type="checkbox" ng-model="selected"></label><br/> + <select aria-label="ngSelected demo"> <option>Hello!</option> <option id="greet" ng-selected="selected">Greetings!</option> </select> @@ -18015,7 +19738,7 @@ var htmlAnchorDirective = valueFn({ * @example <example> <file name="index.html"> - Check me check multiple: <input type="checkbox" ng-model="open"><br/> + <label>Check me check multiple: <input type="checkbox" ng-model="open"></label><br/> <details id="details" ng-open="open"> <summary>Show/Hide me</summary> </details> @@ -18036,22 +19759,34 @@ var htmlAnchorDirective = valueFn({ var ngAttributeAliasDirectives = {}; - // boolean attrs are evaluated forEach(BOOLEAN_ATTR, function(propName, attrName) { // binding to multiple is not supported if (propName == "multiple") return; + function defaultLinkFn(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); + } + var normalized = directiveNormalize('ng-' + attrName); + var linkFn = defaultLinkFn; + + if (propName === 'checked') { + linkFn = function(scope, element, attr) { + // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input + if (attr.ngModel !== attr[normalized]) { + defaultLinkFn(scope, element, attr); + } + }; + } + ngAttributeAliasDirectives[normalized] = function() { return { restrict: 'A', priority: 100, - link: function(scope, element, attr) { - scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { - attr.$set(attrName, !!value); - }); - } + link: linkFn }; }; }); @@ -18434,7 +20169,7 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { * * # Alias: {@link ng.directive:ngForm `ngForm`} * - * In Angular forms can be nested. This means that the outer form is valid when all of the child + * In Angular, forms can be nested. This means that the outer form is valid when all of the child * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to * `<form>` but can be nested. This allows you to have nested forms, which is very useful when @@ -18533,11 +20268,11 @@ function FormController(element, attrs, $scope, $animate, $interpolate) { <form name="myForm" ng-controller="FormController" class="my-form"> userType: <input name="input" ng-model="userType" required> <span class="error" ng-show="myForm.input.$error.required">Required!</span><br> - <tt>userType = {{userType}}</tt><br> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br> + <code>userType = {{userType}}</code><br> + <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br> + <code>myForm.input.$error = {{myForm.input.$error}}</code><br> + <code>myForm.$valid = {{myForm.$valid}}</code><br> + <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br> </form> </file> <file name="protractor.js" type="protractor"> @@ -18572,10 +20307,12 @@ var formDirectiveFactory = function(isNgForm) { name: 'form', restrict: isNgForm ? 'EAC' : 'E', controller: FormController, - compile: function ngFormCompile(formElement) { + compile: function ngFormCompile(formElement, attr) { // Setup initial state of the control formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); + var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false); + return { pre: function ngFormPreLink(scope, formElement, attr, controller) { // if `action` attr is not present on the form, prevent the default action (submission) @@ -18606,23 +20343,21 @@ var formDirectiveFactory = function(isNgForm) { }); } - var parentFormCtrl = controller.$$parentForm, - alias = controller.$name; - - if (alias) { - setter(scope, null, alias, controller, alias); - attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) { - if (alias === newValue) return; - setter(scope, null, alias, undefined, alias); - alias = newValue; - setter(scope, null, alias, controller, alias); - parentFormCtrl.$$renameControl(controller, alias); + var parentFormCtrl = controller.$$parentForm; + + if (nameAttr) { + setter(scope, controller.$name, controller, controller.$name); + attr.$observe(nameAttr, function(newValue) { + if (controller.$name === newValue) return; + setter(scope, controller.$name, undefined, controller.$name); + parentFormCtrl.$$renameControl(controller, newValue); + setter(scope, controller.$name, controller, controller.$name); }); } formElement.on('$destroy', function() { parentFormCtrl.$removeControl(controller); - if (alias) { - setter(scope, null, alias, undefined, alias); + if (nameAttr) { + setter(scope, attr[nameAttr], undefined, controller.$name); } extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards }); @@ -18651,7 +20386,7 @@ var ngFormDirective = formDirectiveFactory(true); var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; -var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; +var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; @@ -18684,9 +20419,13 @@ var inputType = { * as in the ngPattern directive. * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. @@ -18706,13 +20445,16 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="ExampleController"> - Single word: <input type="text" name="input" ng-model="example.text" - ng-pattern="example.word" required ng-trim="false"> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.pattern"> - Single word only!</span> - + <label>Single word: + <input type="text" name="input" ng-model="example.text" + ng-pattern="example.word" required ng-trim="false"> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.pattern"> + Single word only!</span> + </div> <tt>text = {{example.text}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -18791,13 +20533,15 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a date in 2013: + <label for="exampleInput">Pick a date in 2013:</label> <input type="date" id="exampleInput" name="input" ng-model="example.value" placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.date"> - Not a valid date!</span> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.date"> + Not a valid date!</span> + </div> <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -18884,13 +20628,15 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a date between in 2013: + <label for="exampleInput">Pick a date between in 2013:</label> <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value" placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.datetimelocal"> - Not a valid date!</span> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.datetimelocal"> + Not a valid date!</span> + </div> <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -18978,13 +20724,15 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a between 8am and 5pm: + <label for="exampleInput">Pick a between 8am and 5pm:</label> <input type="time" id="exampleInput" name="input" ng-model="example.value" placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.time"> - Not a valid date!</span> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.time"> + Not a valid date!</span> + </div> <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -19071,13 +20819,17 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a date between in 2013: - <input id="exampleInput" type="week" name="input" ng-model="example.value" - placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.week"> - Not a valid date!</span> + <label>Pick a date between in 2013: + <input id="exampleInput" type="week" name="input" ng-model="example.value" + placeholder="YYYY-W##" min="2012-W32" + max="2013-W52" required /> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.week"> + Not a valid date!</span> + </div> <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -19164,13 +20916,15 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a month in 2013: + <label for="exampleInput">Pick a month in 2013:</label> <input id="exampleInput" type="month" name="input" ng-model="example.value" placeholder="yyyy-MM" min="2013-01" max="2013-12" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.month"> - Not a valid month!</span> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.month"> + Not a valid month!</span> + </div> <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -19225,7 +20979,21 @@ var inputType = { * Text input with number validation and transformation. Sets the `number` validation * error if not a valid number. * - * The model must always be a number, otherwise Angular will throw an error. + * <div class="alert alert-warning"> + * The model must always be of type `number` otherwise Angular will throw an error. + * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt} + * error docs for more information and an example of how to convert your model if necessary. + * </div> + * + * ## Issues with HTML5 constraint validation + * + * In browsers that follow the + * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29), + * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}. + * If a non-number is entered in the input, the browser will report the value as an empty string, + * which means the view / model values in `ngModel` and subsequently the scope value + * will also be an empty string. + * * * @param {string} ngModel Assignable angular expression to data-bind to. * @param {string=} name Property name of the form under which the control is published. @@ -19245,9 +21013,13 @@ var inputType = { * as in the ngPattern directive. * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. * @@ -19263,12 +21035,16 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="ExampleController"> - Number: <input type="number" name="input" ng-model="example.value" - min="0" max="99" required> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.number"> - Not valid number!</span> + <label>Number: + <input type="number" name="input" ng-model="example.value" + min="0" max="99" required> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.number"> + Not valid number!</span> + </div> <tt>value = {{example.value}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -19335,9 +21111,13 @@ var inputType = { * as in the ngPattern directive. * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. * @@ -19353,11 +21133,15 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="ExampleController"> - URL: <input type="url" name="input" ng-model="url.text" required> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.url"> - Not valid url!</span> + <label>URL: + <input type="url" name="input" ng-model="url.text" required> + <label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.url"> + Not valid url!</span> + </div> <tt>text = {{url.text}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -19426,9 +21210,13 @@ var inputType = { * as in the ngPattern directive. * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. * @@ -19444,11 +21232,15 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="ExampleController"> - Email: <input type="email" name="input" ng-model="email.text" required> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.email"> - Not valid email!</span> + <label>Email: + <input type="email" name="input" ng-model="email.text" required> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.email"> + Not valid email!</span> + </div> <tt>text = {{email.text}}</tt><br/> <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> @@ -19494,12 +21286,15 @@ var inputType = { * HTML radio button. * * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string} value The value to which the expression should be set when selected. + * @param {string} value The value to which the `ngModel` expression should be set when selected. + * Note that `value` only supports `string` values, i.e. the scope model needs to be a string, + * too. Use `ngValue` if you need complex models (`number`, `object`, ...). * @param {string=} name Property name of the form under which the control is published. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. - * @param {string} ngValue Angular expression which sets the value to which the expression should - * be set when selected. + * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio + * is selected. Should be used instead of the `value` attribute if you need + * a non-string `ngModel` (`boolean`, `array`, ...). * * @example <example name="radio-input-directive" module="radioExample"> @@ -19517,9 +21312,18 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="ExampleController"> - <input type="radio" ng-model="color.name" value="red"> Red <br/> - <input type="radio" ng-model="color.name" ng-value="specialValue"> Green <br/> - <input type="radio" ng-model="color.name" value="blue"> Blue <br/> + <label> + <input type="radio" ng-model="color.name" value="red"> + Red + </label><br/> + <label> + <input type="radio" ng-model="color.name" ng-value="specialValue"> + Green + </label><br/> + <label> + <input type="radio" ng-model="color.name" value="blue"> + Blue + </label><br/> <tt>color = {{color.name | json}}</tt><br/> </form> Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. @@ -19567,9 +21371,13 @@ var inputType = { }]); </script> <form name="myForm" ng-controller="ExampleController"> - Value1: <input type="checkbox" ng-model="checkboxModel.value1"> <br/> - Value2: <input type="checkbox" ng-model="checkboxModel.value2" - ng-true-value="'YES'" ng-false-value="'NO'"> <br/> + <label>Value1: + <input type="checkbox" ng-model="checkboxModel.value1"> + </label><br/> + <label>Value2: + <input type="checkbox" ng-model="checkboxModel.value2" + ng-true-value="'YES'" ng-false-value="'NO'"> + </label><br/> <tt>value1 = {{checkboxModel.value1}}</tt><br/> <tt>value2 = {{checkboxModel.value2}}</tt><br/> </form> @@ -19794,8 +21602,8 @@ function createDateInputType(type, regexp, parseDate, format) { // parser/formatter in the processing chain so that the model // contains some different data format! var parsedDate = parseDate(value, previousDate); - if (timezone === 'UTC') { - parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset()); + if (timezone) { + parsedDate = convertTimezoneToLocal(parsedDate, timezone); } return parsedDate; } @@ -19808,9 +21616,8 @@ function createDateInputType(type, regexp, parseDate, format) { } if (isValidDate(value)) { previousDate = value; - if (previousDate && timezone === 'UTC') { - var timezoneOffset = 60000 * previousDate.getTimezoneOffset(); - previousDate = new Date(previousDate.getTime() + timezoneOffset); + if (previousDate && timezone) { + previousDate = convertTimezoneToLocal(previousDate, timezone, true); } return $filter('date')(value, format, timezone); } else { @@ -19888,7 +21695,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { return value; }); - if (attr.min || attr.ngMin) { + if (isDefined(attr.min) || attr.ngMin) { var minVal; ctrl.$validators.min = function(value) { return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; @@ -19904,7 +21711,7 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { }); } - if (attr.max || attr.ngMax) { + if (isDefined(attr.max) || attr.ngMax) { var maxVal; ctrl.$validators.max = function(value) { return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; @@ -20034,9 +21841,15 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any * length. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. @@ -20067,9 +21880,15 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any * length. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. * @param {string=} ngChange Angular expression to be executed when input changes due to user * interaction with the input element. * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. @@ -20087,26 +21906,36 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt </script> <div ng-controller="ExampleController"> <form name="myForm"> - User name: <input type="text" name="userName" ng-model="user.name" required> - <span class="error" ng-show="myForm.userName.$error.required"> - Required!</span><br> - Last name: <input type="text" name="lastName" ng-model="user.last" - ng-minlength="3" ng-maxlength="10"> - <span class="error" ng-show="myForm.lastName.$error.minlength"> - Too short!</span> - <span class="error" ng-show="myForm.lastName.$error.maxlength"> - Too long!</span><br> + <label> + User name: + <input type="text" name="userName" ng-model="user.name" required> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.userName.$error.required"> + Required!</span> + </div> + <label> + Last name: + <input type="text" name="lastName" ng-model="user.last" + ng-minlength="3" ng-maxlength="10"> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.lastName.$error.minlength"> + Too short!</span> + <span class="error" ng-show="myForm.lastName.$error.maxlength"> + Too long!</span> + </div> </form> <hr> <tt>user = {{user}}</tt><br/> - <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br> - <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br> - <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br> - <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br> - <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br> - <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br> + <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/> + <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/> + <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/> + <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/> + <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/> </div> </file> <file name="protractor.js" type="protractor"> @@ -20295,7 +22124,7 @@ var ngValueDirective = function() { }]); </script> <div ng-controller="ExampleController"> - Enter name: <input type="text" ng-model="name"><br> + <label>Enter name: <input type="text" ng-model="name"></label><br> Hello <span ng-bind="name"></span>! </div> </file> @@ -20356,8 +22185,8 @@ var ngBindDirective = ['$compile', function($compile) { }]); </script> <div ng-controller="ExampleController"> - Salutation: <input type="text" ng-model="salutation"><br> - Name: <input type="text" ng-model="name"><br> + <label>Salutation: <input type="text" ng-model="salutation"></label><br> + <label>Name: <input type="text" ng-model="name"></label><br> <pre ng-bind-template="{{salutation}} {{name}}!"></pre> </div> </file> @@ -20582,7 +22411,9 @@ function classDirective(name, selector) { } function digestClassCounts(classes, count) { - var classCounts = element.data('$classCounts') || {}; + // Use createMap() to prevent class assumptions involving property + // names in Object.prototype + var classCounts = element.data('$classCounts') || createMap(); var classesToUpdate = []; forEach(classes, function(className) { if (count > 0 || classCounts[className]) { @@ -20639,12 +22470,15 @@ function classDirective(name, selector) { } function arrayClasses(classVal) { + var classes = []; if (isArray(classVal)) { - return classVal; + forEach(classVal, function(v) { + classes = classes.concat(arrayClasses(v)); + }); + return classes; } else if (isString(classVal)) { return classVal.split(' '); } else if (isObject(classVal)) { - var classes = []; forEach(classVal, function(v, k) { if (v) { classes = classes.concat(k.split(' ')); @@ -20672,16 +22506,18 @@ function classDirective(name, selector) { * 1. If the expression evaluates to a string, the string should be one or more space-delimited class * names. * - * 2. If the expression evaluates to an array, each element of the array should be a string that is - * one or more space-delimited class names. - * - * 3. If the expression evaluates to an object, then for each key-value pair of the + * 2. If the expression evaluates to an object, then for each key-value pair of the * object with a truthy value the corresponding key is used as a class name. * + * 3. If the expression evaluates to an array, each element of the array should either be a string as in + * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array + * to give you more control over what CSS classes appear. See the code below for an example of this. + * + * * The directive won't add duplicate classes if a particular class was already set. * - * When the expression changes, the previously added classes are removed and only then the - * new classes are added. + * When the expression changes, the previously added classes are removed and only then are the + * new classes added. * * @animations * **add** - happens just before the class is applied to the elements @@ -20698,22 +22534,39 @@ function classDirective(name, selector) { * @example Example that demonstrates basic bindings via ngClass directive. <example> <file name="index.html"> - <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p> - <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br> - <input type="checkbox" ng-model="important"> important (apply "bold" class)<br> - <input type="checkbox" ng-model="error"> error (apply "red" class) + <p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p> + <label> + <input type="checkbox" ng-model="deleted"> + deleted (apply "strike" class) + </label><br> + <label> + <input type="checkbox" ng-model="important"> + important (apply "bold" class) + </label><br> + <label> + <input type="checkbox" ng-model="error"> + error (apply "has-error" class) + </label> <hr> <p ng-class="style">Using String Syntax</p> - <input type="text" ng-model="style" placeholder="Type: bold strike red"> + <input type="text" ng-model="style" + placeholder="Type: bold strike red" aria-label="Type: bold strike red"> <hr> <p ng-class="[style1, style2, style3]">Using Array Syntax</p> - <input ng-model="style1" placeholder="Type: bold, strike or red"><br> - <input ng-model="style2" placeholder="Type: bold, strike or red"><br> - <input ng-model="style3" placeholder="Type: bold, strike or red"><br> + <input ng-model="style1" + placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red"><br> + <input ng-model="style2" + placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 2"><br> + <input ng-model="style3" + placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 3"><br> + <hr> + <p ng-class="[style4, {orange: warning}]">Using Array and Map Syntax</p> + <input ng-model="style4" placeholder="Type: bold, strike" aria-label="Type: bold, strike"><br> + <label><input type="checkbox" ng-model="warning"> warning (apply "orange" class)</label> </file> <file name="style.css"> .strike { - text-decoration: line-through; + text-decoration: line-through; } .bold { font-weight: bold; @@ -20721,6 +22574,13 @@ function classDirective(name, selector) { .red { color: red; } + .has-error { + color: red; + background-color: yellow; + } + .orange { + color: orange; + } </file> <file name="protractor.js" type="protractor"> var ps = element.all(by.css('p')); @@ -20728,13 +22588,13 @@ function classDirective(name, selector) { it('should let you toggle the class', function() { expect(ps.first().getAttribute('class')).not.toMatch(/bold/); - expect(ps.first().getAttribute('class')).not.toMatch(/red/); + expect(ps.first().getAttribute('class')).not.toMatch(/has-error/); element(by.model('important')).click(); expect(ps.first().getAttribute('class')).toMatch(/bold/); element(by.model('error')).click(); - expect(ps.first().getAttribute('class')).toMatch(/red/); + expect(ps.first().getAttribute('class')).toMatch(/has-error/); }); it('should let you toggle string example', function() { @@ -20745,11 +22605,18 @@ function classDirective(name, selector) { }); it('array example should have 3 classes', function() { - expect(ps.last().getAttribute('class')).toBe(''); + expect(ps.get(2).getAttribute('class')).toBe(''); element(by.model('style1')).sendKeys('bold'); element(by.model('style2')).sendKeys('strike'); element(by.model('style3')).sendKeys('red'); - expect(ps.last().getAttribute('class')).toBe('bold strike red'); + expect(ps.get(2).getAttribute('class')).toBe('bold strike red'); + }); + + it('array with map example should have 2 classes', function() { + expect(ps.last().getAttribute('class')).toBe(''); + element(by.model('style4')).sendKeys('bold'); + element(by.model('warning')).click(); + expect(ps.last().getAttribute('class')).toBe('bold orange'); }); </file> </example> @@ -20799,8 +22666,8 @@ function classDirective(name, selector) { The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure. Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure - to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and - {@link ng.$animate#removeClass $animate.removeClass}. + to view the step by step details of {@link $animate#addClass $animate.addClass} and + {@link $animate#removeClass $animate.removeClass}. */ var ngClassDirective = classDirective('', true); @@ -20933,17 +22800,13 @@ var ngClassEvenDirective = classDirective('Even', 1); * document; alternatively, the css rule above must be included in the external stylesheet of the * application. * - * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they - * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css - * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below. - * * @element ANY * * @example <example> <file name="index.html"> <div id="template1" ng-cloak>{{ 'hello' }}</div> - <div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div> + <div id="template2" class="ng-cloak">{{ 'world' }}</div> </file> <file name="protractor.js" type="protractor"> it('should remove the template directive and css class', function() { @@ -21027,20 +22890,20 @@ var ngCloakDirective = ngDirective({ * <example name="ngControllerAs" module="controllerAsExample"> * <file name="index.html"> * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings"> - * Name: <input type="text" ng-model="settings.name"/> - * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/> + * <label>Name: <input type="text" ng-model="settings.name"/></label> + * <button ng-click="settings.greet()">greet</button><br/> * Contact: * <ul> * <li ng-repeat="contact in settings.contacts"> - * <select ng-model="contact.type"> + * <select ng-model="contact.type" aria-label="Contact method" id="select_{{$index}}"> * <option>phone</option> * <option>email</option> * </select> - * <input type="text" ng-model="contact.value"/> - * [ <a href="" ng-click="settings.clearContact(contact)">clear</a> - * | <a href="" ng-click="settings.removeContact(contact)">X</a> ] + * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" /> + * <button ng-click="settings.clearContact(contact)">clear</button> + * <button ng-click="settings.removeContact(contact)" aria-label="Remove">X</button> * </li> - * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li> + * <li><button ng-click="settings.addContact()">add</button></li> * </ul> * </div> * </file> @@ -21090,12 +22953,12 @@ var ngCloakDirective = ngDirective({ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe('john.smith@example.org'); * - * firstRepeat.element(by.linkText('clear')).click(); + * firstRepeat.element(by.buttonText('clear')).click(); * * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe(''); * - * container.element(by.linkText('add')).click(); + * container.element(by.buttonText('add')).click(); * * expect(container.element(by.repeater('contact in settings.contacts').row(2)) * .element(by.model('contact.value')) @@ -21110,20 +22973,20 @@ var ngCloakDirective = ngDirective({ * <example name="ngController" module="controllerExample"> * <file name="index.html"> * <div id="ctrl-exmpl" ng-controller="SettingsController2"> - * Name: <input type="text" ng-model="name"/> - * [ <a href="" ng-click="greet()">greet</a> ]<br/> + * <label>Name: <input type="text" ng-model="name"/></label> + * <button ng-click="greet()">greet</button><br/> * Contact: * <ul> * <li ng-repeat="contact in contacts"> - * <select ng-model="contact.type"> + * <select ng-model="contact.type" id="select_{{$index}}"> * <option>phone</option> * <option>email</option> * </select> - * <input type="text" ng-model="contact.value"/> - * [ <a href="" ng-click="clearContact(contact)">clear</a> - * | <a href="" ng-click="removeContact(contact)">X</a> ] + * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" /> + * <button ng-click="clearContact(contact)">clear</button> + * <button ng-click="removeContact(contact)">X</button> * </li> - * <li>[ <a href="" ng-click="addContact()">add</a> ]</li> + * <li>[ <button ng-click="addContact()">add</button> ]</li> * </ul> * </div> * </file> @@ -21173,12 +23036,12 @@ var ngCloakDirective = ngDirective({ * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe('john.smith@example.org'); * - * firstRepeat.element(by.linkText('clear')).click(); + * firstRepeat.element(by.buttonText('clear')).click(); * * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) * .toBe(''); * - * container.element(by.linkText('add')).click(); + * container.element(by.buttonText('add')).click(); * * expect(container.element(by.repeater('contact in contacts').row(2)) * .element(by.model('contact.value')) @@ -21859,6 +23722,7 @@ forEach( * @ngdoc directive * @name ngIf * @restrict A + * @multiElement * * @description * The `ngIf` directive removes or recreates a portion of the DOM tree based on an @@ -21901,7 +23765,7 @@ forEach( * @example <example module="ngAnimate" deps="angular-animate.js" animations="true"> <file name="index.html"> - Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/> + <label>Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /></label><br/> Show when checked: <span ng-if="checked" class="animate-if"> This is removed when the checkbox is unchecked. @@ -22157,8 +24021,8 @@ var ngIfDirective = ['$animate', function($animate) { * @param {Object} angularEvent Synthetic event object. * @param {String} src URL of content to load. */ -var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce', - function($templateRequest, $anchorScroll, $animate, $sce) { +var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', + function($templateRequest, $anchorScroll, $animate) { return { restrict: 'ECA', priority: 400, @@ -22194,7 +24058,7 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce } }; - scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) { + scope.$watch(srcExp, function ngIncludeWatchAction(src) { var afterAnimation = function() { if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { $anchorScroll(); @@ -22282,7 +24146,7 @@ var ngIncludeFillContentDirective = ['$compile', * The `ngInit` directive allows you to evaluate an expression in the * current scope. * - * <div class="alert alert-error"> + * <div class="alert alert-danger"> * The only appropriate use of `ngInit` is for aliasing special properties of * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you * should use {@link guide/controller controllers} rather than `ngInit` @@ -22369,9 +24233,11 @@ var ngInitDirective = ngDirective({ * </file> * <file name="index.html"> * <form name="myForm" ng-controller="ExampleController"> - * List: <input name="namesInput" ng-model="names" ng-list required> - * <span class="error" ng-show="myForm.namesInput.$error.required"> + * <label>List: <input name="namesInput" ng-model="names" ng-list required></label> + * <span role="alert"> + * <span class="error" ng-show="myForm.namesInput.$error.required"> * Required!</span> + * </span> * <br> * <tt>names = {{names}}</tt><br/> * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/> @@ -22595,8 +24461,8 @@ is set to `true`. The parse error is stored in `ngModel.$error.parse`. * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) * collaborate together to achieve the desired result. * - * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element - * contents be edited in place by the user. This will not work on older browsers. + * `contenteditable` is an HTML5 attribute, which tells the browser to let the element + * contents be edited in place by the user. * * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize} * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`). @@ -22658,7 +24524,7 @@ is set to `true`. The parse error is stored in `ngModel.$error.parse`. required>Change me!</div> <span ng-show="myForm.myWidget.$error.required">Required!</span> <hr> - <textarea ng-model="userContent"></textarea> + <textarea ng-model="userContent" aria-label="Dynamic textarea"></textarea> </form> </file> <file name="protractor.js" type="protractor"> @@ -22710,1129 +24576,1876 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ ngModelGet = parsedNgModel, ngModelSet = parsedNgModelAssign, pendingDebounce = null, + parserValid, ctrl = this; - this.$$setOptions = function(options) { - ctrl.$options = options; - if (options && options.getterSetter) { - var invokeModelGetter = $parse($attr.ngModel + '()'), - invokeModelSetter = $parse($attr.ngModel + '($$$p)'); + this.$$setOptions = function(options) { + ctrl.$options = options; + if (options && options.getterSetter) { + var invokeModelGetter = $parse($attr.ngModel + '()'), + invokeModelSetter = $parse($attr.ngModel + '($$$p)'); + + ngModelGet = function($scope) { + var modelValue = parsedNgModel($scope); + if (isFunction(modelValue)) { + modelValue = invokeModelGetter($scope); + } + return modelValue; + }; + ngModelSet = function($scope, newValue) { + if (isFunction(parsedNgModel($scope))) { + invokeModelSetter($scope, {$$$p: ctrl.$modelValue}); + } else { + parsedNgModelAssign($scope, ctrl.$modelValue); + } + }; + } else if (!parsedNgModel.assign) { + throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}", + $attr.ngModel, startingTag($element)); + } + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$render + * + * @description + * Called when the view needs to be updated. It is expected that the user of the ng-model + * directive will implement this method. + * + * The `$render()` method is invoked in the following situations: + * + * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last + * committed value then `$render()` is called to update the input control. + * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and + * the `$viewValue` are different from last time. + * + * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of + * `$modelValue` and `$viewValue` are actually different from their previous value. If `$modelValue` + * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be + * invoked if you only change a property on the objects. + */ + this.$render = noop; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$isEmpty + * + * @description + * This is called when we need to determine if the value of an input is empty. + * + * For instance, the required directive does this to work out if the input has data or not. + * + * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. + * + * You can override this for input directives whose concept of being empty is different from the + * default. The `checkboxInputType` directive does this because in its case a value of `false` + * implies empty. + * + * @param {*} value The value of the input to check for emptiness. + * @returns {boolean} True if `value` is "empty". + */ + this.$isEmpty = function(value) { + return isUndefined(value) || value === '' || value === null || value !== value; + }; + + var parentForm = $element.inheritedData('$formController') || nullFormCtrl, + currentValidationRunId = 0; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setValidity + * + * @description + * Change the validity state, and notify the form. + * + * This method can be called within $parsers/$formatters or a custom validation implementation. + * However, in most cases it should be sufficient to use the `ngModel.$validators` and + * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically. + * + * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned + * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` + * (for unfulfilled `$asyncValidators`), so that it is available for data-binding. + * The `validationErrorKey` should be in camelCase and will get converted into dash-case + * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` + * class and can be bound to as `{{someForm.someControl.$error.myError}}` . + * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined), + * or skipped (null). Pending is used for unfulfilled `$asyncValidators`. + * Skipped is used by Angular when validators do not run because of parse errors and + * when `$asyncValidators` do not run because any of the `$validators` failed. + */ + addSetValidityMethod({ + ctrl: this, + $element: $element, + set: function(object, property) { + object[property] = true; + }, + unset: function(object, property) { + delete object[property]; + }, + parentForm: parentForm, + $animate: $animate + }); + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setPristine + * + * @description + * Sets the control to its pristine state. + * + * This method can be called to remove the `ng-dirty` class and set the control to its pristine + * state (`ng-pristine` class). A model is considered to be pristine when the control + * has not been changed from when first compiled. + */ + this.$setPristine = function() { + ctrl.$dirty = false; + ctrl.$pristine = true; + $animate.removeClass($element, DIRTY_CLASS); + $animate.addClass($element, PRISTINE_CLASS); + }; - ngModelGet = function($scope) { - var modelValue = parsedNgModel($scope); - if (isFunction(modelValue)) { - modelValue = invokeModelGetter($scope); - } - return modelValue; - }; - ngModelSet = function($scope, newValue) { - if (isFunction(parsedNgModel($scope))) { - invokeModelSetter($scope, {$$$p: ctrl.$modelValue}); - } else { - parsedNgModelAssign($scope, ctrl.$modelValue); - } - }; - } else if (!parsedNgModel.assign) { - throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}", - $attr.ngModel, startingTag($element)); - } + /** + * @ngdoc method + * @name ngModel.NgModelController#$setDirty + * + * @description + * Sets the control to its dirty state. + * + * This method can be called to remove the `ng-pristine` class and set the control to its dirty + * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed + * from when first compiled. + */ + this.$setDirty = function() { + ctrl.$dirty = true; + ctrl.$pristine = false; + $animate.removeClass($element, PRISTINE_CLASS); + $animate.addClass($element, DIRTY_CLASS); + parentForm.$setDirty(); }; /** * @ngdoc method - * @name ngModel.NgModelController#$render + * @name ngModel.NgModelController#$setUntouched * * @description - * Called when the view needs to be updated. It is expected that the user of the ng-model - * directive will implement this method. + * Sets the control to its untouched state. * - * The `$render()` method is invoked in the following situations: + * This method can be called to remove the `ng-touched` class and set the control to its + * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched + * by default, however this function can be used to restore that state if the model has + * already been touched by the user. + */ + this.$setUntouched = function() { + ctrl.$touched = false; + ctrl.$untouched = true; + $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setTouched * - * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last - * committed value then `$render()` is called to update the input control. - * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and - * the `$viewValue` are different to last time. + * @description + * Sets the control to its touched state. * - * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of - * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue` - * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be - * invoked if you only change a property on the objects. + * This method can be called to remove the `ng-untouched` class and set the control to its + * touched state (`ng-touched` class). A model is considered to be touched when the user has + * first focused the control element and then shifted focus away from the control (blur event). */ - this.$render = noop; + this.$setTouched = function() { + ctrl.$touched = true; + ctrl.$untouched = false; + $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS); + }; /** * @ngdoc method - * @name ngModel.NgModelController#$isEmpty + * @name ngModel.NgModelController#$rollbackViewValue * * @description - * This is called when we need to determine if the value of an input is empty. + * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`, + * which may be caused by a pending debounced event or because the input is waiting for a some + * future event. * - * For instance, the required directive does this to work out if the input has data or not. + * If you have an input that uses `ng-model-options` to set up debounced events or events such + * as blur you can have a situation where there is a period when the `$viewValue` + * is out of synch with the ngModel's `$modelValue`. * - * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. + * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue` + * programmatically before these debounced/future events have resolved/occurred, because Angular's + * dirty checking mechanism is not able to tell whether the model has actually changed or not. * - * You can override this for input directives whose concept of being empty is different to the - * default. The `checkboxInputType` directive does this because in its case a value of `false` - * implies empty. + * The `$rollbackViewValue()` method should be called before programmatically changing the model of an + * input which may have such events pending. This is important in order to make sure that the + * input field will be updated with the new model value and any pending operations are cancelled. * - * @param {*} value The value of the input to check for emptiness. - * @returns {boolean} True if `value` is "empty". + * <example name="ng-model-cancel-update" module="cancel-update-example"> + * <file name="app.js"> + * angular.module('cancel-update-example', []) + * + * .controller('CancelUpdateController', ['$scope', function($scope) { + * $scope.resetWithCancel = function(e) { + * if (e.keyCode == 27) { + * $scope.myForm.myInput1.$rollbackViewValue(); + * $scope.myValue = ''; + * } + * }; + * $scope.resetWithoutCancel = function(e) { + * if (e.keyCode == 27) { + * $scope.myValue = ''; + * } + * }; + * }]); + * </file> + * <file name="index.html"> + * <div ng-controller="CancelUpdateController"> + * <p>Try typing something in each input. See that the model only updates when you + * blur off the input. + * </p> + * <p>Now see what happens if you start typing then press the Escape key</p> + * + * <form name="myForm" ng-model-options="{ updateOn: 'blur' }"> + * <p id="inputDescription1">With $rollbackViewValue()</p> + * <input name="myInput1" aria-describedby="inputDescription1" ng-model="myValue" + * ng-keydown="resetWithCancel($event)"><br/> + * myValue: "{{ myValue }}" + * + * <p id="inputDescription2">Without $rollbackViewValue()</p> + * <input name="myInput2" aria-describedby="inputDescription2" ng-model="myValue" + * ng-keydown="resetWithoutCancel($event)"><br/> + * myValue: "{{ myValue }}" + * </form> + * </div> + * </file> + * </example> */ - this.$isEmpty = function(value) { - return isUndefined(value) || value === '' || value === null || value !== value; + this.$rollbackViewValue = function() { + $timeout.cancel(pendingDebounce); + ctrl.$viewValue = ctrl.$$lastCommittedViewValue; + ctrl.$render(); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$validate + * + * @description + * Runs each of the registered validators (first synchronous validators and then + * asynchronous validators). + * If the validity changes to invalid, the model will be set to `undefined`, + * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. + * If the validity changes to valid, it will set the model to the last available valid + * `$modelValue`, i.e. either the last parsed value or the last value set from the scope. + */ + this.$validate = function() { + // ignore $validate before model is initialized + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + return; + } + + var viewValue = ctrl.$$lastCommittedViewValue; + // Note: we use the $$rawModelValue as $modelValue might have been + // set to undefined during a view -> model update that found validation + // errors. We can't parse the view here, since that could change + // the model although neither viewValue nor the model on the scope changed + var modelValue = ctrl.$$rawModelValue; + + var prevValid = ctrl.$valid; + var prevModelValue = ctrl.$modelValue; + + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + + ctrl.$$runValidators(modelValue, viewValue, function(allValid) { + // If there was no change in validity, don't update the model + // This prevents changing an invalid modelValue to undefined + if (!allowInvalid && prevValid !== allValid) { + // Note: Don't check ctrl.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + ctrl.$modelValue = allValid ? modelValue : undefined; + + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); + } + } + }); + }; - var parentForm = $element.inheritedData('$formController') || nullFormCtrl, - currentValidationRunId = 0; + this.$$runValidators = function(modelValue, viewValue, doneCallback) { + currentValidationRunId++; + var localValidationRunId = currentValidationRunId; + + // check parser error + if (!processParseErrors()) { + validationDone(false); + return; + } + if (!processSyncValidators()) { + validationDone(false); + return; + } + processAsyncValidators(); + + function processParseErrors() { + var errorKey = ctrl.$$parserName || 'parse'; + if (parserValid === undefined) { + setValidity(errorKey, null); + } else { + if (!parserValid) { + forEach(ctrl.$validators, function(v, name) { + setValidity(name, null); + }); + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + } + // Set the parse error last, to prevent unsetting it, should a $validators key == parserName + setValidity(errorKey, parserValid); + return parserValid; + } + return true; + } + + function processSyncValidators() { + var syncValidatorsValid = true; + forEach(ctrl.$validators, function(validator, name) { + var result = validator(modelValue, viewValue); + syncValidatorsValid = syncValidatorsValid && result; + setValidity(name, result); + }); + if (!syncValidatorsValid) { + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + return false; + } + return true; + } + + function processAsyncValidators() { + var validatorPromises = []; + var allValid = true; + forEach(ctrl.$asyncValidators, function(validator, name) { + var promise = validator(modelValue, viewValue); + if (!isPromiseLike(promise)) { + throw $ngModelMinErr("$asyncValidators", + "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); + } + setValidity(name, undefined); + validatorPromises.push(promise.then(function() { + setValidity(name, true); + }, function(error) { + allValid = false; + setValidity(name, false); + })); + }); + if (!validatorPromises.length) { + validationDone(true); + } else { + $q.all(validatorPromises).then(function() { + validationDone(allValid); + }, noop); + } + } + + function setValidity(name, isValid) { + if (localValidationRunId === currentValidationRunId) { + ctrl.$setValidity(name, isValid); + } + } - /** - * @ngdoc method - * @name ngModel.NgModelController#$setValidity - * - * @description - * Change the validity state, and notify the form. - * - * This method can be called within $parsers/$formatters or a custom validation implementation. - * However, in most cases it should be sufficient to use the `ngModel.$validators` and - * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically. - * - * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned - * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` - * (for unfulfilled `$asyncValidators`), so that it is available for data-binding. - * The `validationErrorKey` should be in camelCase and will get converted into dash-case - * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` - * class and can be bound to as `{{someForm.someControl.$error.myError}}` . - * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined), - * or skipped (null). Pending is used for unfulfilled `$asyncValidators`. - * Skipped is used by Angular when validators do not run because of parse errors and - * when `$asyncValidators` do not run because any of the `$validators` failed. - */ - addSetValidityMethod({ - ctrl: this, - $element: $element, - set: function(object, property) { - object[property] = true; - }, - unset: function(object, property) { - delete object[property]; - }, - parentForm: parentForm, - $animate: $animate - }); + function validationDone(allValid) { + if (localValidationRunId === currentValidationRunId) { - /** - * @ngdoc method - * @name ngModel.NgModelController#$setPristine - * - * @description - * Sets the control to its pristine state. - * - * This method can be called to remove the `ng-dirty` class and set the control to its pristine - * state (`ng-pristine` class). A model is considered to be pristine when the control - * has not been changed from when first compiled. - */ - this.$setPristine = function() { - ctrl.$dirty = false; - ctrl.$pristine = true; - $animate.removeClass($element, DIRTY_CLASS); - $animate.addClass($element, PRISTINE_CLASS); + doneCallback(allValid); + } + } }; /** * @ngdoc method - * @name ngModel.NgModelController#$setDirty + * @name ngModel.NgModelController#$commitViewValue * * @description - * Sets the control to its dirty state. + * Commit a pending update to the `$modelValue`. * - * This method can be called to remove the `ng-pristine` class and set the control to its dirty - * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed - * from when first compiled. + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. this method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. */ - this.$setDirty = function() { - ctrl.$dirty = true; - ctrl.$pristine = false; - $animate.removeClass($element, PRISTINE_CLASS); - $animate.addClass($element, DIRTY_CLASS); - parentForm.$setDirty(); + this.$commitViewValue = function() { + var viewValue = ctrl.$viewValue; + + $timeout.cancel(pendingDebounce); + + // If the view value has not changed then we should just exit, except in the case where there is + // a native validator on the element. In this case the validation state may have changed even though + // the viewValue has stayed empty. + if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) { + return; + } + ctrl.$$lastCommittedViewValue = viewValue; + + // change to dirty + if (ctrl.$pristine) { + this.$setDirty(); + } + this.$$parseAndValidate(); }; - /** - * @ngdoc method - * @name ngModel.NgModelController#$setUntouched - * - * @description - * Sets the control to its untouched state. - * - * This method can be called to remove the `ng-touched` class and set the control to its - * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched - * by default, however this function can be used to restore that state if the model has - * already been touched by the user. - */ - this.$setUntouched = function() { - ctrl.$touched = false; - ctrl.$untouched = true; - $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS); + this.$$parseAndValidate = function() { + var viewValue = ctrl.$$lastCommittedViewValue; + var modelValue = viewValue; + parserValid = isUndefined(modelValue) ? undefined : true; + + if (parserValid) { + for (var i = 0; i < ctrl.$parsers.length; i++) { + modelValue = ctrl.$parsers[i](modelValue); + if (isUndefined(modelValue)) { + parserValid = false; + break; + } + } + } + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + // ctrl.$modelValue has not been touched yet... + ctrl.$modelValue = ngModelGet($scope); + } + var prevModelValue = ctrl.$modelValue; + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + ctrl.$$rawModelValue = modelValue; + + if (allowInvalid) { + ctrl.$modelValue = modelValue; + writeToModelIfNeeded(); + } + + // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. + // This can happen if e.g. $setViewValue is called from inside a parser + ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { + if (!allowInvalid) { + // Note: Don't check ctrl.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + ctrl.$modelValue = allValid ? modelValue : undefined; + writeToModelIfNeeded(); + } + }); + + function writeToModelIfNeeded() { + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); + } + } }; - /** - * @ngdoc method - * @name ngModel.NgModelController#$setTouched - * - * @description - * Sets the control to its touched state. - * - * This method can be called to remove the `ng-untouched` class and set the control to its - * touched state (`ng-touched` class). A model is considered to be touched when the user has - * first focused the control element and then shifted focus away from the control (blur event). - */ - this.$setTouched = function() { - ctrl.$touched = true; - ctrl.$untouched = false; - $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS); + this.$$writeModelToScope = function() { + ngModelSet($scope, ctrl.$modelValue); + forEach(ctrl.$viewChangeListeners, function(listener) { + try { + listener(); + } catch (e) { + $exceptionHandler(e); + } + }); }; /** * @ngdoc method - * @name ngModel.NgModelController#$rollbackViewValue + * @name ngModel.NgModelController#$setViewValue * * @description - * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`, - * which may be caused by a pending debounced event or because the input is waiting for a some - * future event. + * Update the view value. * - * If you have an input that uses `ng-model-options` to set up debounced events or events such - * as blur you can have a situation where there is a period when the `$viewValue` - * is out of synch with the ngModel's `$modelValue`. + * This method should be called when an input directive want to change the view value; typically, + * this is done from within a DOM event handler. * - * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue` - * programmatically before these debounced/future events have resolved/occurred, because Angular's - * dirty checking mechanism is not able to tell whether the model has actually changed or not. + * For example {@link ng.directive:input input} calls it when the value of the input changes and + * {@link ng.directive:select select} calls it when an option is selected. * - * The `$rollbackViewValue()` method should be called before programmatically changing the model of an - * input which may have such events pending. This is important in order to make sure that the - * input field will be updated with the new model value and any pending operations are cancelled. + * If the new `value` is an object (rather than a string or a number), we should make a copy of the + * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep + * watch of objects, it only looks for a change of identity. If you only change the property of + * the object then ngModel will not realise that the object has changed and will not invoke the + * `$parsers` and `$validators` pipelines. * - * <example name="ng-model-cancel-update" module="cancel-update-example"> - * <file name="app.js"> - * angular.module('cancel-update-example', []) + * For this reason, you should not change properties of the copy once it has been passed to + * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly. * - * .controller('CancelUpdateController', ['$scope', function($scope) { - * $scope.resetWithCancel = function(e) { - * if (e.keyCode == 27) { - * $scope.myForm.myInput1.$rollbackViewValue(); - * $scope.myValue = ''; - * } - * }; - * $scope.resetWithoutCancel = function(e) { - * if (e.keyCode == 27) { - * $scope.myValue = ''; - * } - * }; - * }]); - * </file> - * <file name="index.html"> - * <div ng-controller="CancelUpdateController"> - * <p>Try typing something in each input. See that the model only updates when you - * blur off the input. - * </p> - * <p>Now see what happens if you start typing then press the Escape key</p> + * When this method is called, the new `value` will be staged for committing through the `$parsers` + * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged + * value sent directly for processing, finally to be applied to `$modelValue` and then the + * **expression** specified in the `ng-model` attribute. * - * <form name="myForm" ng-model-options="{ updateOn: 'blur' }"> - * <p>With $rollbackViewValue()</p> - * <input name="myInput1" ng-model="myValue" ng-keydown="resetWithCancel($event)"><br/> - * myValue: "{{ myValue }}" + * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called. * - * <p>Without $rollbackViewValue()</p> - * <input name="myInput2" ng-model="myValue" ng-keydown="resetWithoutCancel($event)"><br/> - * myValue: "{{ myValue }}" - * </form> - * </div> - * </file> - * </example> + * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn` + * and the `default` trigger is not listed, all those actions will remain pending until one of the + * `updateOn` events is triggered on the DOM element. + * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions} + * directive is used with a custom debounce for this particular event. + * + * Note that calling this function does not trigger a `$digest`. + * + * @param {string} value Value from the view. + * @param {string} trigger Event that triggered the update. */ - this.$rollbackViewValue = function() { + this.$setViewValue = function(value, trigger) { + ctrl.$viewValue = value; + if (!ctrl.$options || ctrl.$options.updateOnDefault) { + ctrl.$$debounceViewValueCommit(trigger); + } + }; + + this.$$debounceViewValueCommit = function(trigger) { + var debounceDelay = 0, + options = ctrl.$options, + debounce; + + if (options && isDefined(options.debounce)) { + debounce = options.debounce; + if (isNumber(debounce)) { + debounceDelay = debounce; + } else if (isNumber(debounce[trigger])) { + debounceDelay = debounce[trigger]; + } else if (isNumber(debounce['default'])) { + debounceDelay = debounce['default']; + } + } + $timeout.cancel(pendingDebounce); - ctrl.$viewValue = ctrl.$$lastCommittedViewValue; - ctrl.$render(); + if (debounceDelay) { + pendingDebounce = $timeout(function() { + ctrl.$commitViewValue(); + }, debounceDelay); + } else if ($rootScope.$$phase) { + ctrl.$commitViewValue(); + } else { + $scope.$apply(function() { + ctrl.$commitViewValue(); + }); + } }; - /** - * @ngdoc method - * @name ngModel.NgModelController#$validate - * - * @description - * Runs each of the registered validators (first synchronous validators and then - * asynchronous validators). - * If the validity changes to invalid, the model will be set to `undefined`, - * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. - * If the validity changes to valid, it will set the model to the last available valid - * modelValue, i.e. either the last parsed value or the last value set from the scope. - */ - this.$validate = function() { - // ignore $validate before model is initialized - if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { - return; + // model -> value + // Note: we cannot use a normal scope.$watch as we want to detect the following: + // 1. scope value is 'a' + // 2. user enters 'b' + // 3. ng-change kicks in and reverts scope value to 'a' + // -> scope value did not change since the last digest as + // ng-change executes in apply phase + // 4. view should be changed back to 'a' + $scope.$watch(function ngModelWatch() { + var modelValue = ngModelGet($scope); + + // if scope model value and ngModel value are out of sync + // TODO(perf): why not move this to the action fn? + if (modelValue !== ctrl.$modelValue && + // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator + (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue) + ) { + ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; + parserValid = undefined; + + var formatters = ctrl.$formatters, + idx = formatters.length; + + var viewValue = modelValue; + while (idx--) { + viewValue = formatters[idx](viewValue); + } + if (ctrl.$viewValue !== viewValue) { + ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; + ctrl.$render(); + + ctrl.$$runValidators(modelValue, viewValue, noop); + } } - var viewValue = ctrl.$$lastCommittedViewValue; - // Note: we use the $$rawModelValue as $modelValue might have been - // set to undefined during a view -> model update that found validation - // errors. We can't parse the view here, since that could change - // the model although neither viewValue nor the model on the scope changed - var modelValue = ctrl.$$rawModelValue; + return modelValue; + }); +}]; + + +/** + * @ngdoc directive + * @name ngModel + * + * @element input + * @priority 1 + * + * @description + * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a + * property on the scope using {@link ngModel.NgModelController NgModelController}, + * which is created and exposed by this directive. + * + * `ngModel` is responsible for: + * + * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` + * require. + * - Providing validation behavior (i.e. required, number, email, url). + * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors). + * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations. + * - Registering the control with its parent {@link ng.directive:form form}. + * + * Note: `ngModel` will try to bind to the property given by evaluating the expression on the + * current scope. If the property doesn't already exist on this scope, it will be created + * implicitly and added to the scope. + * + * For best practices on using `ngModel`, see: + * + * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) + * + * For basic examples, how to use `ngModel`, see: + * + * - {@link ng.directive:input input} + * - {@link input[text] text} + * - {@link input[checkbox] checkbox} + * - {@link input[radio] radio} + * - {@link input[number] number} + * - {@link input[email] email} + * - {@link input[url] url} + * - {@link input[date] date} + * - {@link input[datetime-local] datetime-local} + * - {@link input[time] time} + * - {@link input[month] month} + * - {@link input[week] week} + * - {@link ng.directive:select select} + * - {@link ng.directive:textarea textarea} + * + * # CSS classes + * The following CSS classes are added and removed on the associated input/select/textarea element + * depending on the validity of the model. + * + * - `ng-valid`: the model is valid + * - `ng-invalid`: the model is invalid + * - `ng-valid-[key]`: for each valid key added by `$setValidity` + * - `ng-invalid-[key]`: for each invalid key added by `$setValidity` + * - `ng-pristine`: the control hasn't been interacted with yet + * - `ng-dirty`: the control has been interacted with + * - `ng-touched`: the control has been blurred + * - `ng-untouched`: the control hasn't been blurred + * - `ng-pending`: any `$asyncValidators` are unfulfilled + * + * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * + * ## Animation Hooks + * + * Animations within models are triggered when any of the associated CSS classes are added and removed + * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`, + * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself. + * The animations that are triggered within ngModel are similar to how they work in ngClass and + * animations can be hooked into using CSS transitions, keyframes as well as JS animations. + * + * The following example shows a simple way to utilize CSS transitions to style an input element + * that has been rendered as invalid after it has been validated: + * + * <pre> + * //be sure to include ngAnimate as a module to hook into more + * //advanced animations + * .my-input { + * transition:0.5s linear all; + * background: white; + * } + * .my-input.ng-invalid { + * background: red; + * color:white; + * } + * </pre> + * + * @example + * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample"> + <file name="index.html"> + <script> + angular.module('inputExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.val = '1'; + }]); + </script> + <style> + .my-input { + -webkit-transition:all linear 0.5s; + transition:all linear 0.5s; + background: transparent; + } + .my-input.ng-invalid { + color:white; + background: red; + } + </style> + <p id="inputDescription"> + Update input to see transitions when valid/invalid. + Integer is a valid value. + </p> + <form name="testForm" ng-controller="ExampleController"> + <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" + aria-describedby="inputDescription" /> + </form> + </file> + * </example> + * + * ## Binding to a getter/setter + * + * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a + * function that returns a representation of the model when called with zero arguments, and sets + * the internal state of a model when called with an argument. It's sometimes useful to use this + * for models that have an internal representation that's different from what the model exposes + * to the view. + * + * <div class="alert alert-success"> + * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more + * frequently than other parts of your code. + * </div> + * + * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that + * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to + * a `<form>`, which will enable this behavior for all `<input>`s within it. See + * {@link ng.directive:ngModelOptions `ngModelOptions`} for more. + * + * The following example shows how to use `ngModel` with a getter/setter: + * + * @example + * <example name="ngModel-getter-setter" module="getterSetterExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ getterSetter: true }" /> + </label> + </form> + <pre>user.name = <span ng-bind="user.name()"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('getterSetterExample', []) + .controller('ExampleController', ['$scope', function($scope) { + var _name = 'Brian'; + $scope.user = { + name: function(newName) { + // Note that newName can be undefined for two reasons: + // 1. Because it is called as a getter and thus called with no arguments + // 2. Because the property should actually be set to undefined. This happens e.g. if the + // input is invalid + return arguments.length ? (_name = newName) : _name; + } + }; + }]); + </file> + * </example> + */ +var ngModelDirective = ['$rootScope', function($rootScope) { + return { + restrict: 'A', + require: ['ngModel', '^?form', '^?ngModelOptions'], + controller: NgModelController, + // Prelink needs to run before any input directive + // so that we can set the NgModelOptions in NgModelController + // before anyone else uses it. + priority: 1, + compile: function ngModelCompile(element) { + // Setup initial state of the control + element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); + + return { + pre: function ngModelPreLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0], + formCtrl = ctrls[1] || nullFormCtrl; - // Check if the there's a parse error, so we don't unset it accidentially - var parserName = ctrl.$$parserName || 'parse'; - var parserValid = ctrl.$error[parserName] ? false : undefined; + modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options); - var prevValid = ctrl.$valid; - var prevModelValue = ctrl.$modelValue; + // notify others, especially parent forms + formCtrl.$addControl(modelCtrl); - var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + attr.$observe('name', function(newValue) { + if (modelCtrl.$name !== newValue) { + formCtrl.$$renameControl(modelCtrl, newValue); + } + }); - ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) { - // If there was no change in validity, don't update the model - // This prevents changing an invalid modelValue to undefined - if (!allowInvalid && prevValid !== allValid) { - // Note: Don't check ctrl.$valid here, as we could have - // external validators (e.g. calculated on the server), - // that just call $setValidity and need the model value - // to calculate their validity. - ctrl.$modelValue = allValid ? modelValue : undefined; + scope.$on('$destroy', function() { + formCtrl.$removeControl(modelCtrl); + }); + }, + post: function ngModelPostLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0]; + if (modelCtrl.$options && modelCtrl.$options.updateOn) { + element.on(modelCtrl.$options.updateOn, function(ev) { + modelCtrl.$$debounceViewValueCommit(ev && ev.type); + }); + } - if (ctrl.$modelValue !== prevModelValue) { - ctrl.$$writeModelToScope(); - } - } - }); + element.on('blur', function(ev) { + if (modelCtrl.$touched) return; + if ($rootScope.$$phase) { + scope.$evalAsync(modelCtrl.$setTouched); + } else { + scope.$apply(modelCtrl.$setTouched); + } + }); + } + }; + } }; +}]; - this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) { - currentValidationRunId++; - var localValidationRunId = currentValidationRunId; +var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; - // check parser error - if (!processParseErrors(parseValid)) { - validationDone(false); - return; - } - if (!processSyncValidators()) { - validationDone(false); - return; - } - processAsyncValidators(); +/** + * @ngdoc directive + * @name ngModelOptions + * + * @description + * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of + * events that will trigger a model update and/or a debouncing delay so that the actual update only + * takes place when a timer expires; this timer will be reset after another change takes place. + * + * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might + * be different from the value in the actual model. This means that if you update the model you + * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in + * order to make sure it is synchronized with the model and that any debounced action is canceled. + * + * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`} + * method is by making sure the input is placed inside a form that has a `name` attribute. This is + * important because `form` controllers are published to the related scope under the name in their + * `name` attribute. + * + * Any pending changes will take place immediately when an enclosing form is submitted via the + * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` + * to have access to the updated model. + * + * `ngModelOptions` has an effect on the element it's declared on and its descendants. + * + * @param {Object} ngModelOptions options to apply to the current model. Valid keys are: + * - `updateOn`: string specifying which event should the input be bound to. You can set several + * events using an space delimited list. There is a special event called `default` that + * matches the default events belonging of the control. + * - `debounce`: integer value which contains the debounce model update value in milliseconds. A + * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a + * custom value for each event. For example: + * `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"` + * - `allowInvalid`: boolean value which indicates that the model can be set with values that did + * not validate correctly instead of the default behavior of setting the model to undefined. + * - `getterSetter`: boolean value which determines whether or not to treat functions bound to + `ngModel` as getters/setters. + * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for + * `<input type="date">`, `<input type="time">`, ... . It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) + * If not specified, the timezone of the browser will be used. + * + * @example - function processParseErrors(parseValid) { - var errorKey = ctrl.$$parserName || 'parse'; - if (parseValid === undefined) { - setValidity(errorKey, null); - } else { - setValidity(errorKey, parseValid); - if (!parseValid) { - forEach(ctrl.$validators, function(v, name) { - setValidity(name, null); - }); - forEach(ctrl.$asyncValidators, function(v, name) { - setValidity(name, null); - }); - return false; - } - } - return true; - } + The following example shows how to override immediate updates. Changes on the inputs within the + form will update the model only when the control loses focus (blur event). If `escape` key is + pressed while the input field is focused, the value is reset to the value in the current model. - function processSyncValidators() { - var syncValidatorsValid = true; - forEach(ctrl.$validators, function(validator, name) { - var result = validator(modelValue, viewValue); - syncValidatorsValid = syncValidatorsValid && result; - setValidity(name, result); + <example name="ngModelOptions-directive-blur" module="optionsExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ updateOn: 'blur' }" + ng-keyup="cancel($event)" /> + </label><br /> + <label>Other data: + <input type="text" ng-model="user.data" /> + </label><br /> + </form> + <pre>user.name = <span ng-bind="user.name"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('optionsExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.user = { name: 'say', data: '' }; + + $scope.cancel = function(e) { + if (e.keyCode == 27) { + $scope.userForm.userName.$rollbackViewValue(); + } + }; + }]); + </file> + <file name="protractor.js" type="protractor"> + var model = element(by.binding('user.name')); + var input = element(by.model('user.name')); + var other = element(by.model('user.data')); + + it('should allow custom events', function() { + input.sendKeys(' hello'); + input.click(); + expect(model.getText()).toEqual('say'); + other.click(); + expect(model.getText()).toEqual('say hello'); }); - if (!syncValidatorsValid) { - forEach(ctrl.$asyncValidators, function(v, name) { - setValidity(name, null); - }); - return false; - } - return true; - } - function processAsyncValidators() { - var validatorPromises = []; - var allValid = true; - forEach(ctrl.$asyncValidators, function(validator, name) { - var promise = validator(modelValue, viewValue); - if (!isPromiseLike(promise)) { - throw $ngModelMinErr("$asyncValidators", - "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); - } - setValidity(name, undefined); - validatorPromises.push(promise.then(function() { - setValidity(name, true); - }, function(error) { - allValid = false; - setValidity(name, false); + it('should $rollbackViewValue when model changes', function() { + input.sendKeys(' hello'); + expect(input.getAttribute('value')).toEqual('say hello'); + input.sendKeys(protractor.Key.ESCAPE); + expect(input.getAttribute('value')).toEqual('say'); + other.click(); + expect(model.getText()).toEqual('say'); + }); + </file> + </example> + + This one shows how to debounce model changes. Model will be updated only 1 sec after last change. + If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty. + + <example name="ngModelOptions-directive-debounce" module="optionsExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ debounce: 1000 }" /> + </label> + <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button> + <br /> + </form> + <pre>user.name = <span ng-bind="user.name"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('optionsExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.user = { name: 'say' }; + }]); + </file> + </example> + + This one shows how to bind to getter/setters: + + <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ getterSetter: true }" /> + </label> + </form> + <pre>user.name = <span ng-bind="user.name()"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('getterSetterExample', []) + .controller('ExampleController', ['$scope', function($scope) { + var _name = 'Brian'; + $scope.user = { + name: function(newName) { + // Note that newName can be undefined for two reasons: + // 1. Because it is called as a getter and thus called with no arguments + // 2. Because the property should actually be set to undefined. This happens e.g. if the + // input is invalid + return arguments.length ? (_name = newName) : _name; + } + }; + }]); + </file> + </example> + */ +var ngModelOptionsDirective = function() { + return { + restrict: 'A', + controller: ['$scope', '$attrs', function($scope, $attrs) { + var that = this; + this.$options = copy($scope.$eval($attrs.ngModelOptions)); + // Allow adding/overriding bound events + if (this.$options.updateOn !== undefined) { + this.$options.updateOnDefault = false; + // extract "default" pseudo-event from list of events that can trigger a model update + this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() { + that.$options.updateOnDefault = true; + return ' '; })); - }); - if (!validatorPromises.length) { - validationDone(true); } else { - $q.all(validatorPromises).then(function() { - validationDone(allValid); - }, noop); - } - } - - function setValidity(name, isValid) { - if (localValidationRunId === currentValidationRunId) { - ctrl.$setValidity(name, isValid); - } - } - - function validationDone(allValid) { - if (localValidationRunId === currentValidationRunId) { - - doneCallback(allValid); + this.$options.updateOnDefault = true; } - } + }] }; +}; - /** - * @ngdoc method - * @name ngModel.NgModelController#$commitViewValue - * - * @description - * Commit a pending update to the `$modelValue`. - * - * Updates may be pending by a debounced event or because the input is waiting for a some future - * event defined in `ng-model-options`. this method is rarely needed as `NgModelController` - * usually handles calling this in response to input events. - */ - this.$commitViewValue = function() { - var viewValue = ctrl.$viewValue; - $timeout.cancel(pendingDebounce); - // If the view value has not changed then we should just exit, except in the case where there is - // a native validator on the element. In this case the validation state may have changed even though - // the viewValue has stayed empty. - if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) { - return; - } - ctrl.$$lastCommittedViewValue = viewValue; +// helper methods +function addSetValidityMethod(context) { + var ctrl = context.ctrl, + $element = context.$element, + classCache = {}, + set = context.set, + unset = context.unset, + parentForm = context.parentForm, + $animate = context.$animate; - // change to dirty - if (ctrl.$pristine) { - this.$setDirty(); - } - this.$$parseAndValidate(); - }; + classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS)); - this.$$parseAndValidate = function() { - var viewValue = ctrl.$$lastCommittedViewValue; - var modelValue = viewValue; - var parserValid = isUndefined(modelValue) ? undefined : true; + ctrl.$setValidity = setValidity; - if (parserValid) { - for (var i = 0; i < ctrl.$parsers.length; i++) { - modelValue = ctrl.$parsers[i](modelValue); - if (isUndefined(modelValue)) { - parserValid = false; - break; - } - } + function setValidity(validationErrorKey, state, controller) { + if (state === undefined) { + createAndSet('$pending', validationErrorKey, controller); + } else { + unsetAndCleanup('$pending', validationErrorKey, controller); } - if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { - // ctrl.$modelValue has not been touched yet... - ctrl.$modelValue = ngModelGet($scope); + if (!isBoolean(state)) { + unset(ctrl.$error, validationErrorKey, controller); + unset(ctrl.$$success, validationErrorKey, controller); + } else { + if (state) { + unset(ctrl.$error, validationErrorKey, controller); + set(ctrl.$$success, validationErrorKey, controller); + } else { + set(ctrl.$error, validationErrorKey, controller); + unset(ctrl.$$success, validationErrorKey, controller); + } } - var prevModelValue = ctrl.$modelValue; - var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; - ctrl.$$rawModelValue = modelValue; - - if (allowInvalid) { - ctrl.$modelValue = modelValue; - writeToModelIfNeeded(); + if (ctrl.$pending) { + cachedToggleClass(PENDING_CLASS, true); + ctrl.$valid = ctrl.$invalid = undefined; + toggleValidationCss('', null); + } else { + cachedToggleClass(PENDING_CLASS, false); + ctrl.$valid = isObjectEmpty(ctrl.$error); + ctrl.$invalid = !ctrl.$valid; + toggleValidationCss('', ctrl.$valid); } - // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. - // This can happen if e.g. $setViewValue is called from inside a parser - ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { - if (!allowInvalid) { - // Note: Don't check ctrl.$valid here, as we could have - // external validators (e.g. calculated on the server), - // that just call $setValidity and need the model value - // to calculate their validity. - ctrl.$modelValue = allValid ? modelValue : undefined; - writeToModelIfNeeded(); - } - }); - - function writeToModelIfNeeded() { - if (ctrl.$modelValue !== prevModelValue) { - ctrl.$$writeModelToScope(); - } + // re-read the state as the set/unset methods could have + // combined state in ctrl.$error[validationError] (used for forms), + // where setting/unsetting only increments/decrements the value, + // and does not replace it. + var combinedState; + if (ctrl.$pending && ctrl.$pending[validationErrorKey]) { + combinedState = undefined; + } else if (ctrl.$error[validationErrorKey]) { + combinedState = false; + } else if (ctrl.$$success[validationErrorKey]) { + combinedState = true; + } else { + combinedState = null; } - }; - this.$$writeModelToScope = function() { - ngModelSet($scope, ctrl.$modelValue); - forEach(ctrl.$viewChangeListeners, function(listener) { - try { - listener(); - } catch (e) { - $exceptionHandler(e); - } - }); - }; + toggleValidationCss(validationErrorKey, combinedState); + parentForm.$setValidity(validationErrorKey, combinedState, ctrl); + } - /** - * @ngdoc method - * @name ngModel.NgModelController#$setViewValue - * - * @description - * Update the view value. - * - * This method should be called when an input directive want to change the view value; typically, - * this is done from within a DOM event handler. - * - * For example {@link ng.directive:input input} calls it when the value of the input changes and - * {@link ng.directive:select select} calls it when an option is selected. - * - * If the new `value` is an object (rather than a string or a number), we should make a copy of the - * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep - * watch of objects, it only looks for a change of identity. If you only change the property of - * the object then ngModel will not realise that the object has changed and will not invoke the - * `$parsers` and `$validators` pipelines. - * - * For this reason, you should not change properties of the copy once it has been passed to - * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly. - * - * When this method is called, the new `value` will be staged for committing through the `$parsers` - * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged - * value sent directly for processing, finally to be applied to `$modelValue` and then the - * **expression** specified in the `ng-model` attribute. - * - * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called. - * - * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn` - * and the `default` trigger is not listed, all those actions will remain pending until one of the - * `updateOn` events is triggered on the DOM element. - * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions} - * directive is used with a custom debounce for this particular event. - * - * Note that calling this function does not trigger a `$digest`. - * - * @param {string} value Value from the view. - * @param {string} trigger Event that triggered the update. - */ - this.$setViewValue = function(value, trigger) { - ctrl.$viewValue = value; - if (!ctrl.$options || ctrl.$options.updateOnDefault) { - ctrl.$$debounceViewValueCommit(trigger); + function createAndSet(name, value, controller) { + if (!ctrl[name]) { + ctrl[name] = {}; } - }; - - this.$$debounceViewValueCommit = function(trigger) { - var debounceDelay = 0, - options = ctrl.$options, - debounce; + set(ctrl[name], value, controller); + } - if (options && isDefined(options.debounce)) { - debounce = options.debounce; - if (isNumber(debounce)) { - debounceDelay = debounce; - } else if (isNumber(debounce[trigger])) { - debounceDelay = debounce[trigger]; - } else if (isNumber(debounce['default'])) { - debounceDelay = debounce['default']; - } + function unsetAndCleanup(name, value, controller) { + if (ctrl[name]) { + unset(ctrl[name], value, controller); } - - $timeout.cancel(pendingDebounce); - if (debounceDelay) { - pendingDebounce = $timeout(function() { - ctrl.$commitViewValue(); - }, debounceDelay); - } else if ($rootScope.$$phase) { - ctrl.$commitViewValue(); - } else { - $scope.$apply(function() { - ctrl.$commitViewValue(); - }); + if (isObjectEmpty(ctrl[name])) { + ctrl[name] = undefined; } - }; - - // model -> value - // Note: we cannot use a normal scope.$watch as we want to detect the following: - // 1. scope value is 'a' - // 2. user enters 'b' - // 3. ng-change kicks in and reverts scope value to 'a' - // -> scope value did not change since the last digest as - // ng-change executes in apply phase - // 4. view should be changed back to 'a' - $scope.$watch(function ngModelWatch() { - var modelValue = ngModelGet($scope); + } - // if scope model value and ngModel value are out of sync - // TODO(perf): why not move this to the action fn? - if (modelValue !== ctrl.$modelValue) { - ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; + function cachedToggleClass(className, switchValue) { + if (switchValue && !classCache[className]) { + $animate.addClass($element, className); + classCache[className] = true; + } else if (!switchValue && classCache[className]) { + $animate.removeClass($element, className); + classCache[className] = false; + } + } - var formatters = ctrl.$formatters, - idx = formatters.length; + function toggleValidationCss(validationErrorKey, isValid) { + validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; - var viewValue = modelValue; - while (idx--) { - viewValue = formatters[idx](viewValue); - } - if (ctrl.$viewValue !== viewValue) { - ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; - ctrl.$render(); + cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true); + cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false); + } +} - ctrl.$$runValidators(undefined, modelValue, viewValue, noop); +function isObjectEmpty(obj) { + if (obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; } } + } + return true; +} - return modelValue; - }); -}]; +/** + * @ngdoc directive + * @name ngNonBindable + * @restrict AC + * @priority 1000 + * + * @description + * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current + * DOM element. This is useful if the element contains what appears to be Angular directives and + * bindings but which should be ignored by Angular. This could be the case if you have a site that + * displays snippets of code, for instance. + * + * @element ANY + * + * @example + * In this example there are two locations where a simple interpolation binding (`{{}}`) is present, + * but the one wrapped in `ngNonBindable` is left alone. + * + * @example + <example> + <file name="index.html"> + <div>Normal: {{1 + 2}}</div> + <div ng-non-bindable>Ignored: {{1 + 2}}</div> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-non-bindable', function() { + expect(element(by.binding('1 + 2')).getText()).toContain('3'); + expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/); + }); + </file> + </example> + */ +var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); +/* global jqLiteRemove */ + +var ngOptionsMinErr = minErr('ngOptions'); /** * @ngdoc directive - * @name ngModel - * - * @element input - * @priority 1 + * @name ngOptions + * @restrict A * * @description - * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a - * property on the scope using {@link ngModel.NgModelController NgModelController}, - * which is created and exposed by this directive. * - * `ngModel` is responsible for: + * The `ngOptions` attribute can be used to dynamically generate a list of `<option>` + * elements for the `<select>` element using the array or object obtained by evaluating the + * `ngOptions` comprehension expression. * - * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` - * require. - * - Providing validation behavior (i.e. required, number, email, url). - * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors). - * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations. - * - Registering the control with its parent {@link ng.directive:form form}. + * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a + * similar result. However, `ngOptions` provides some benefits such as reducing memory and + * increasing speed by not creating a new scope for each repeated instance, as well as providing + * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the + * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound + * to a non-string value. This is because an option element can only be bound to string values at + * present. * - * Note: `ngModel` will try to bind to the property given by evaluating the expression on the - * current scope. If the property doesn't already exist on this scope, it will be created - * implicitly and added to the scope. + * When an item in the `<select>` menu is selected, the array element or object property + * represented by the selected option will be bound to the model identified by the `ngModel` + * directive. * - * For best practices on using `ngModel`, see: + * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can + * be nested into the `<select>` element. This element will then represent the `null` or "not selected" + * option. See example below for demonstration. * - * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) + * ## Complex Models (objects or collections) * - * For basic examples, how to use `ngModel`, see: + * **Note:** By default, `ngModel` watches the model by reference, not value. This is important when + * binding any input directive to a model that is an object or a collection. * - * - {@link ng.directive:input input} - * - {@link input[text] text} - * - {@link input[checkbox] checkbox} - * - {@link input[radio] radio} - * - {@link input[number] number} - * - {@link input[email] email} - * - {@link input[url] url} - * - {@link input[date] date} - * - {@link input[datetime-local] datetime-local} - * - {@link input[time] time} - * - {@link input[month] month} - * - {@link input[week] week} - * - {@link ng.directive:select select} - * - {@link ng.directive:textarea textarea} + * Since this is a common situation for `ngOptions` the directive additionally watches the model using + * `$watchCollection` when the select has the `multiple` attribute or when there is a `track by` clause in + * the options expression. This allows ngOptions to trigger a re-rendering of the options even if the actual + * object/collection has not changed identity but only a property on the object or an item in the collection + * changes. * - * # CSS classes - * The following CSS classes are added and removed on the associated input/select/textarea element - * depending on the validity of the model. + * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection + * if the model is an array). This means that changing a property deeper inside the object/collection that the + * first level will not trigger a re-rendering. * - * - `ng-valid`: the model is valid - * - `ng-invalid`: the model is invalid - * - `ng-valid-[key]`: for each valid key added by `$setValidity` - * - `ng-invalid-[key]`: for each invalid key added by `$setValidity` - * - `ng-pristine`: the control hasn't been interacted with yet - * - `ng-dirty`: the control has been interacted with - * - `ng-touched`: the control has been blurred - * - `ng-untouched`: the control hasn't been blurred - * - `ng-pending`: any `$asyncValidators` are unfulfilled * - * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * ## `select` **`as`** * - * ## Animation Hooks + * Using `select` **`as`** will bind the result of the `select` expression to the model, but + * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources) + * or property name (for object data sources) of the value within the collection. If a **`track by`** expression + * is used, the result of that expression will be set as the value of the `option` and `select` elements. * - * Animations within models are triggered when any of the associated CSS classes are added and removed - * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`, - * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself. - * The animations that are triggered within ngModel are similar to how they work in ngClass and - * animations can be hooked into using CSS transitions, keyframes as well as JS animations. * - * The following example shows a simple way to utilize CSS transitions to style an input element - * that has been rendered as invalid after it has been validated: + * ### `select` **`as`** and **`track by`** * - * <pre> - * //be sure to include ngAnimate as a module to hook into more - * //advanced animations - * .my-input { - * transition:0.5s linear all; - * background: white; - * } - * .my-input.ng-invalid { - * background: red; - * color:white; - * } - * </pre> + * <div class="alert alert-warning"> + * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together. + * </div> * - * @example - * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample"> - <file name="index.html"> - <script> - angular.module('inputExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.val = '1'; - }]); - </script> - <style> - .my-input { - -webkit-transition:all linear 0.5s; - transition:all linear 0.5s; - background: transparent; - } - .my-input.ng-invalid { - color:white; - background: red; - } - </style> - Update input to see transitions when valid/invalid. - Integer is a valid value. - <form name="testForm" ng-controller="ExampleController"> - <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" /> - </form> - </file> - * </example> + * Consider the following example: * - * ## Binding to a getter/setter + * ```html + * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"> + * ``` * - * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a - * function that returns a representation of the model when called with zero arguments, and sets - * the internal state of a model when called with an argument. It's sometimes useful to use this - * for models that have an internal representation that's different than what the model exposes - * to the view. + * ```js + * $scope.values = [{ + * id: 1, + * label: 'aLabel', + * subItem: { name: 'aSubItem' } + * }, { + * id: 2, + * label: 'bLabel', + * subItem: { name: 'bSubItem' } + * }]; * - * <div class="alert alert-success"> - * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more - * frequently than other parts of your code. - * </div> + * $scope.selected = { name: 'aSubItem' }; + * ``` * - * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that - * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to - * a `<form>`, which will enable this behavior for all `<input>`s within it. See - * {@link ng.directive:ngModelOptions `ngModelOptions`} for more. + * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element + * of the data source (to `item` in this example). To calculate whether an element is selected, we do the + * following: * - * The following example shows how to use `ngModel` with a getter/setter: + * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]` + * 2. Apply **`track by`** to the already selected value in `ngModel`. + * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected + * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to + * a wrong object, the selected element can't be found, `<select>` is always reset to the "not + * selected" option. + * + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required The control is considered valid only if value is entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {comprehension_expression=} ngOptions in one of the following forms: + * + * * for array data sources: + * * `label` **`for`** `value` **`in`** `array` + * * `select` **`as`** `label` **`for`** `value` **`in`** `array` + * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` + * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` + * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` + * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` + * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr` + * (for including a filter with `track by`) + * * for object data sources: + * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object` + * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object` + * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object` + * * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object` + * * `select` **`as`** `label` **`group by`** `group` + * **`for` `(`**`key`**`,`** `value`**`) in`** `object` + * * `select` **`as`** `label` **`disable when`** `disable` + * **`for` `(`**`key`**`,`** `value`**`) in`** `object` + * + * Where: + * + * * `array` / `object`: an expression which evaluates to an array / object to iterate over. + * * `value`: local variable which will refer to each item in the `array` or each property value + * of `object` during iteration. + * * `key`: local variable which will refer to a property name in `object` during iteration. + * * `label`: The result of this expression will be the label for `<option>` element. The + * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`). + * * `select`: The result of this expression will be bound to the model of the parent `<select>` + * element. If not specified, `select` expression will default to `value`. + * * `group`: The result of this expression will be used to group options using the `<optgroup>` + * DOM element. + * * `disable`: The result of this expression will be used to disable the rendered `<option>` + * element. Return `true` to disable. + * * `trackexpr`: Used when working with an array of objects. The result of this expression will be + * used to identify the objects in the array. The `trackexpr` will most likely refer to the + * `value` variable (e.g. `value.propertyName`). With this the selection is preserved + * even when the options are recreated (e.g. reloaded from the server). * * @example - * <example name="ngModel-getter-setter" module="getterSetterExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ getterSetter: true }" /> - </form> - <pre>user.name = <span ng-bind="user.name()"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('getterSetterExample', []) - .controller('ExampleController', ['$scope', function($scope) { - var _name = 'Brian'; - $scope.user = { - name: function(newName) { - if (angular.isDefined(newName)) { - _name = newName; - } - return _name; - } - }; - }]); - </file> - * </example> + <example module="selectExample"> + <file name="index.html"> + <script> + angular.module('selectExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.colors = [ + {name:'black', shade:'dark'}, + {name:'white', shade:'light', notAnOption: true}, + {name:'red', shade:'dark'}, + {name:'blue', shade:'dark', notAnOption: true}, + {name:'yellow', shade:'light', notAnOption: false} + ]; + $scope.myColor = $scope.colors[2]; // red + }]); + </script> + <div ng-controller="ExampleController"> + <ul> + <li ng-repeat="color in colors"> + <label>Name: <input ng-model="color.name"></label> + <label><input type="checkbox" ng-model="color.notAnOption"> Disabled?</label> + <button ng-click="colors.splice($index, 1)" aria-label="Remove">X</button> + </li> + <li> + <button ng-click="colors.push({})">add</button> + </li> + </ul> + <hr/> + <label>Color (null not allowed): + <select ng-model="myColor" ng-options="color.name for color in colors"></select> + </label><br/> + <label>Color (null allowed): + <span class="nullable"> + <select ng-model="myColor" ng-options="color.name for color in colors"> + <option value="">-- choose color --</option> + </select> + </span></label><br/> + + <label>Color grouped by shade: + <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors"> + </select> + </label><br/> + + <label>Color grouped by shade, with some disabled: + <select ng-model="myColor" + ng-options="color.name group by color.shade disable when color.notAnOption for color in colors"> + </select> + </label><br/> + + + + Select <button ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</button>. + <br/> + <hr/> + Currently selected: {{ {selected_color:myColor} }} + <div style="border:solid 1px black; height:20px" + ng-style="{'background-color':myColor.name}"> + </div> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-options', function() { + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red'); + element.all(by.model('myColor')).first().click(); + element.all(by.css('select[ng-model="myColor"] option')).first().click(); + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black'); + element(by.css('.nullable select[ng-model="myColor"]')).click(); + element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click(); + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null'); + }); + </file> + </example> */ -var ngModelDirective = ['$rootScope', function($rootScope) { + +// jshint maxlen: false +// //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999 +var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/; + // 1: value expression (valueFn) + // 2: label expression (displayFn) + // 3: group by expression (groupByFn) + // 4: disable when expression (disableWhenFn) + // 5: array item variable name + // 6: object item key variable name + // 7: object item value variable name + // 8: collection expression + // 9: track by expression +// jshint maxlen: 100 + + +var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { + + function parseOptionsExpression(optionsExp, selectElement, scope) { + + var match = optionsExp.match(NG_OPTIONS_REGEXP); + if (!(match)) { + throw ngOptionsMinErr('iexp', + "Expected expression in form of " + + "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + + " but got '{0}'. Element: {1}", + optionsExp, startingTag(selectElement)); + } + + // Extract the parts from the ngOptions expression + + // The variable name for the value of the item in the collection + var valueName = match[5] || match[7]; + // The variable name for the key of the item in the collection + var keyName = match[6]; + + // An expression that generates the viewValue for an option if there is a label expression + var selectAs = / as /.test(match[0]) && match[1]; + // An expression that is used to track the id of each object in the options collection + var trackBy = match[9]; + // An expression that generates the viewValue for an option if there is no label expression + var valueFn = $parse(match[2] ? match[1] : valueName); + var selectAsFn = selectAs && $parse(selectAs); + var viewValueFn = selectAsFn || valueFn; + var trackByFn = trackBy && $parse(trackBy); + + // Get the value by which we are going to track the option + // if we have a trackFn then use that (passing scope and locals) + // otherwise just hash the given viewValue + var getTrackByValueFn = trackBy ? + function(value, locals) { return trackByFn(scope, locals); } : + function getHashOfValue(value) { return hashKey(value); }; + var getTrackByValue = function(value, key) { + return getTrackByValueFn(value, getLocals(value, key)); + }; + + var displayFn = $parse(match[2] || match[1]); + var groupByFn = $parse(match[3] || ''); + var disableWhenFn = $parse(match[4] || ''); + var valuesFn = $parse(match[8]); + + var locals = {}; + var getLocals = keyName ? function(value, key) { + locals[keyName] = key; + locals[valueName] = value; + return locals; + } : function(value) { + locals[valueName] = value; + return locals; + }; + + + function Option(selectValue, viewValue, label, group, disabled) { + this.selectValue = selectValue; + this.viewValue = viewValue; + this.label = label; + this.group = group; + this.disabled = disabled; + } + + function getOptionValuesKeys(optionValues) { + var optionValuesKeys; + + if (!keyName && isArrayLike(optionValues)) { + optionValuesKeys = optionValues; + } else { + // if object, extract keys, in enumeration order, unsorted + optionValuesKeys = []; + for (var itemKey in optionValues) { + if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') { + optionValuesKeys.push(itemKey); + } + } + } + return optionValuesKeys; + } + + return { + trackBy: trackBy, + getTrackByValue: getTrackByValue, + getWatchables: $parse(valuesFn, function(optionValues) { + // Create a collection of things that we would like to watch (watchedArray) + // so that they can all be watched using a single $watchCollection + // that only runs the handler once if anything changes + var watchedArray = []; + optionValues = optionValues || []; + + var optionValuesKeys = getOptionValuesKeys(optionValues); + var optionValuesLength = optionValuesKeys.length; + for (var index = 0; index < optionValuesLength; index++) { + var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index]; + var value = optionValues[key]; + + var locals = getLocals(optionValues[key], key); + var selectValue = getTrackByValueFn(optionValues[key], locals); + watchedArray.push(selectValue); + + // Only need to watch the displayFn if there is a specific label expression + if (match[2] || match[1]) { + var label = displayFn(scope, locals); + watchedArray.push(label); + } + + // Only need to watch the disableWhenFn if there is a specific disable expression + if (match[4]) { + var disableWhen = disableWhenFn(scope, locals); + watchedArray.push(disableWhen); + } + } + return watchedArray; + }), + + getOptions: function() { + + var optionItems = []; + var selectValueMap = {}; + + // The option values were already computed in the `getWatchables` fn, + // which must have been called to trigger `getOptions` + var optionValues = valuesFn(scope) || []; + var optionValuesKeys = getOptionValuesKeys(optionValues); + var optionValuesLength = optionValuesKeys.length; + + for (var index = 0; index < optionValuesLength; index++) { + var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index]; + var value = optionValues[key]; + var locals = getLocals(value, key); + var viewValue = viewValueFn(scope, locals); + var selectValue = getTrackByValueFn(viewValue, locals); + var label = displayFn(scope, locals); + var group = groupByFn(scope, locals); + var disabled = disableWhenFn(scope, locals); + var optionItem = new Option(selectValue, viewValue, label, group, disabled); + + optionItems.push(optionItem); + selectValueMap[selectValue] = optionItem; + } + + return { + items: optionItems, + selectValueMap: selectValueMap, + getOptionFromViewValue: function(value) { + return selectValueMap[getTrackByValue(value)]; + }, + getViewValueFromOption: function(option) { + // If the viewValue could be an object that may be mutated by the application, + // we need to make a copy and not return the reference to the value on the option. + return trackBy ? angular.copy(option.viewValue) : option.viewValue; + } + }; + } + }; + } + + + // we can't just jqLite('<option>') since jqLite is not smart enough + // to create it in <select> and IE barfs otherwise. + var optionTemplate = document.createElement('option'), + optGroupTemplate = document.createElement('optgroup'); + return { restrict: 'A', - require: ['ngModel', '^?form', '^?ngModelOptions'], - controller: NgModelController, - // Prelink needs to run before any input directive - // so that we can set the NgModelOptions in NgModelController - // before anyone else uses it. - priority: 1, - compile: function ngModelCompile(element) { - // Setup initial state of the control - element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); + terminal: true, + require: ['select', '?ngModel'], + link: function(scope, selectElement, attr, ctrls) { - return { - pre: function ngModelPreLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0], - formCtrl = ctrls[1] || nullFormCtrl; + // if ngModel is not defined, we don't need to do anything + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; - modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options); + var selectCtrl = ctrls[0]; + var multiple = attr.multiple; - // notify others, especially parent forms - formCtrl.$addControl(modelCtrl); + // The emptyOption allows the application developer to provide their own custom "empty" + // option when the viewValue does not match any of the option values. + var emptyOption; + for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) { + if (children[i].value === '') { + emptyOption = children.eq(i); + break; + } + } - attr.$observe('name', function(newValue) { - if (modelCtrl.$name !== newValue) { - formCtrl.$$renameControl(modelCtrl, newValue); - } - }); + var providedEmptyOption = !!emptyOption; - scope.$on('$destroy', function() { - formCtrl.$removeControl(modelCtrl); - }); - }, - post: function ngModelPostLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0]; - if (modelCtrl.$options && modelCtrl.$options.updateOn) { - element.on(modelCtrl.$options.updateOn, function(ev) { - modelCtrl.$$debounceViewValueCommit(ev && ev.type); - }); - } + var unknownOption = jqLite(optionTemplate.cloneNode(false)); + unknownOption.val('?'); - element.on('blur', function(ev) { - if (modelCtrl.$touched) return; + var options; + var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope); - if ($rootScope.$$phase) { - scope.$evalAsync(modelCtrl.$setTouched); + + var renderEmptyOption = function() { + if (!providedEmptyOption) { + selectElement.prepend(emptyOption); + } + selectElement.val(''); + emptyOption.prop('selected', true); // needed for IE + emptyOption.attr('selected', true); + }; + + var removeEmptyOption = function() { + if (!providedEmptyOption) { + emptyOption.remove(); + } + }; + + + var renderUnknownOption = function() { + selectElement.prepend(unknownOption); + selectElement.val('?'); + unknownOption.prop('selected', true); // needed for IE + unknownOption.attr('selected', true); + }; + + var removeUnknownOption = function() { + unknownOption.remove(); + }; + + + // Update the controller methods for multiple selectable options + if (!multiple) { + + selectCtrl.writeValue = function writeNgOptionsValue(value) { + var option = options.getOptionFromViewValue(value); + + if (option && !option.disabled) { + if (selectElement[0].value !== option.selectValue) { + removeUnknownOption(); + removeEmptyOption(); + + selectElement[0].value = option.selectValue; + option.element.selected = true; + option.element.setAttribute('selected', 'selected'); + } + } else { + if (value === null || providedEmptyOption) { + removeUnknownOption(); + renderEmptyOption(); } else { - scope.$apply(modelCtrl.$setTouched); + removeEmptyOption(); + renderUnknownOption(); } - }); + } + }; + + selectCtrl.readValue = function readNgOptionsValue() { + + var selectedOption = options.selectValueMap[selectElement.val()]; + + if (selectedOption && !selectedOption.disabled) { + removeEmptyOption(); + removeUnknownOption(); + return options.getViewValueFromOption(selectedOption); + } + return null; + }; + + // If we are using `track by` then we must watch the tracked value on the model + // since ngModel only watches for object identity change + if (ngOptions.trackBy) { + scope.$watch( + function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); }, + function() { ngModelCtrl.$render(); } + ); } - }; - } - }; -}]; -var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; + } else { -/** - * @ngdoc directive - * @name ngModelOptions - * - * @description - * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of - * events that will trigger a model update and/or a debouncing delay so that the actual update only - * takes place when a timer expires; this timer will be reset after another change takes place. - * - * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might - * be different than the value in the actual model. This means that if you update the model you - * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in - * order to make sure it is synchronized with the model and that any debounced action is canceled. - * - * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`} - * method is by making sure the input is placed inside a form that has a `name` attribute. This is - * important because `form` controllers are published to the related scope under the name in their - * `name` attribute. - * - * Any pending changes will take place immediately when an enclosing form is submitted via the - * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` - * to have access to the updated model. - * - * `ngModelOptions` has an effect on the element it's declared on and its descendants. - * - * @param {Object} ngModelOptions options to apply to the current model. Valid keys are: - * - `updateOn`: string specifying which event should the input be bound to. You can set several - * events using an space delimited list. There is a special event called `default` that - * matches the default events belonging of the control. - * - `debounce`: integer value which contains the debounce model update value in milliseconds. A - * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a - * custom value for each event. For example: - * `ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"` - * - `allowInvalid`: boolean value which indicates that the model can be set with values that did - * not validate correctly instead of the default behavior of setting the model to undefined. - * - `getterSetter`: boolean value which determines whether or not to treat functions bound to - `ngModel` as getters/setters. - * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for - * `<input type="date">`, `<input type="time">`, ... . Right now, the only supported value is `'UTC'`, - * otherwise the default timezone of the browser will be used. - * - * @example + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; - The following example shows how to override immediate updates. Changes on the inputs within the - form will update the model only when the control loses focus (blur event). If `escape` key is - pressed while the input field is focused, the value is reset to the value in the current model. - <example name="ngModelOptions-directive-blur" module="optionsExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ updateOn: 'blur' }" - ng-keyup="cancel($event)" /><br /> - - Other data: - <input type="text" ng-model="user.data" /><br /> - </form> - <pre>user.name = <span ng-bind="user.name"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('optionsExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.user = { name: 'say', data: '' }; + selectCtrl.writeValue = function writeNgOptionsMultiple(value) { + options.items.forEach(function(option) { + option.element.selected = false; + }); + + if (value) { + value.forEach(function(item) { + var option = options.getOptionFromViewValue(item); + if (option && !option.disabled) option.element.selected = true; + }); + } + }; + + + selectCtrl.readValue = function readNgOptionsMultiple() { + var selectedValues = selectElement.val() || [], + selections = []; + + forEach(selectedValues, function(value) { + var option = options.selectValueMap[value]; + if (!option.disabled) selections.push(options.getViewValueFromOption(option)); + }); + + return selections; + }; - $scope.cancel = function(e) { - if (e.keyCode == 27) { - $scope.userForm.userName.$rollbackViewValue(); + // If we are using `track by` then we must watch these tracked values on the model + // since ngModel only watches for object identity change + if (ngOptions.trackBy) { + + scope.$watchCollection(function() { + if (isArray(ngModelCtrl.$viewValue)) { + return ngModelCtrl.$viewValue.map(function(value) { + return ngOptions.getTrackByValue(value); + }); } - }; - }]); - </file> - <file name="protractor.js" type="protractor"> - var model = element(by.binding('user.name')); - var input = element(by.model('user.name')); - var other = element(by.model('user.data')); + }, function() { + ngModelCtrl.$render(); + }); - it('should allow custom events', function() { - input.sendKeys(' hello'); - input.click(); - expect(model.getText()).toEqual('say'); - other.click(); - expect(model.getText()).toEqual('say hello'); - }); + } + } - it('should $rollbackViewValue when model changes', function() { - input.sendKeys(' hello'); - expect(input.getAttribute('value')).toEqual('say hello'); - input.sendKeys(protractor.Key.ESCAPE); - expect(input.getAttribute('value')).toEqual('say'); - other.click(); - expect(model.getText()).toEqual('say'); - }); - </file> - </example> - This one shows how to debounce model changes. Model will be updated only 1 sec after last change. - If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty. + if (providedEmptyOption) { - <example name="ngModelOptions-directive-debounce" module="optionsExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ debounce: 1000 }" /> - <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button><br /> - </form> - <pre>user.name = <span ng-bind="user.name"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('optionsExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.user = { name: 'say' }; - }]); - </file> - </example> + // we need to remove it before calling selectElement.empty() because otherwise IE will + // remove the label from the element. wtf? + emptyOption.remove(); - This one shows how to bind to getter/setters: + // compile the element since there might be bindings in it + $compile(emptyOption)(scope); - <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ getterSetter: true }" /> - </form> - <pre>user.name = <span ng-bind="user.name()"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('getterSetterExample', []) - .controller('ExampleController', ['$scope', function($scope) { - var _name = 'Brian'; - $scope.user = { - name: function(newName) { - return angular.isDefined(newName) ? (_name = newName) : _name; - } - }; - }]); - </file> - </example> - */ -var ngModelOptionsDirective = function() { - return { - restrict: 'A', - controller: ['$scope', '$attrs', function($scope, $attrs) { - var that = this; - this.$options = $scope.$eval($attrs.ngModelOptions); - // Allow adding/overriding bound events - if (this.$options.updateOn !== undefined) { - this.$options.updateOnDefault = false; - // extract "default" pseudo-event from list of events that can trigger a model update - this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() { - that.$options.updateOnDefault = true; - return ' '; - })); + // remove the class, which is added automatically because we recompile the element and it + // becomes the compilation root + emptyOption.removeClass('ng-scope'); } else { - this.$options.updateOnDefault = true; + emptyOption = jqLite(optionTemplate.cloneNode(false)); } - }] - }; -}; + // We need to do this here to ensure that the options object is defined + // when we first hit it in writeNgOptionsValue + updateOptions(); + // We will re-render the option elements if the option values or labels change + scope.$watchCollection(ngOptions.getWatchables, updateOptions); -// helper methods -function addSetValidityMethod(context) { - var ctrl = context.ctrl, - $element = context.$element, - classCache = {}, - set = context.set, - unset = context.unset, - parentForm = context.parentForm, - $animate = context.$animate; + // ------------------------------------------------------------------ // - classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS)); - ctrl.$setValidity = setValidity; + function updateOptionElement(option, element) { + option.element = element; + element.disabled = option.disabled; + if (option.value !== element.value) element.value = option.selectValue; + if (option.label !== element.label) { + element.label = option.label; + element.textContent = option.label; + } + } - function setValidity(validationErrorKey, state, controller) { - if (state === undefined) { - createAndSet('$pending', validationErrorKey, controller); - } else { - unsetAndCleanup('$pending', validationErrorKey, controller); - } - if (!isBoolean(state)) { - unset(ctrl.$error, validationErrorKey, controller); - unset(ctrl.$$success, validationErrorKey, controller); - } else { - if (state) { - unset(ctrl.$error, validationErrorKey, controller); - set(ctrl.$$success, validationErrorKey, controller); - } else { - set(ctrl.$error, validationErrorKey, controller); - unset(ctrl.$$success, validationErrorKey, controller); + function addOrReuseElement(parent, current, type, templateElement) { + var element; + // Check whether we can reuse the next element + if (current && lowercase(current.nodeName) === type) { + // The next element is the right type so reuse it + element = current; + } else { + // The next element is not the right type so create a new one + element = templateElement.cloneNode(false); + if (!current) { + // There are no more elements so just append it to the select + parent.appendChild(element); + } else { + // The next element is not a group so insert the new one + parent.insertBefore(element, current); + } + } + return element; } - } - if (ctrl.$pending) { - cachedToggleClass(PENDING_CLASS, true); - ctrl.$valid = ctrl.$invalid = undefined; - toggleValidationCss('', null); - } else { - cachedToggleClass(PENDING_CLASS, false); - ctrl.$valid = isObjectEmpty(ctrl.$error); - ctrl.$invalid = !ctrl.$valid; - toggleValidationCss('', ctrl.$valid); - } - // re-read the state as the set/unset methods could have - // combined state in ctrl.$error[validationError] (used for forms), - // where setting/unsetting only increments/decrements the value, - // and does not replace it. - var combinedState; - if (ctrl.$pending && ctrl.$pending[validationErrorKey]) { - combinedState = undefined; - } else if (ctrl.$error[validationErrorKey]) { - combinedState = false; - } else if (ctrl.$$success[validationErrorKey]) { - combinedState = true; - } else { - combinedState = null; - } - toggleValidationCss(validationErrorKey, combinedState); - parentForm.$setValidity(validationErrorKey, combinedState, ctrl); - } + function removeExcessElements(current) { + var next; + while (current) { + next = current.nextSibling; + jqLiteRemove(current); + current = next; + } + } - function createAndSet(name, value, controller) { - if (!ctrl[name]) { - ctrl[name] = {}; - } - set(ctrl[name], value, controller); - } - function unsetAndCleanup(name, value, controller) { - if (ctrl[name]) { - unset(ctrl[name], value, controller); - } - if (isObjectEmpty(ctrl[name])) { - ctrl[name] = undefined; - } - } + function skipEmptyAndUnknownOptions(current) { + var emptyOption_ = emptyOption && emptyOption[0]; + var unknownOption_ = unknownOption && unknownOption[0]; - function cachedToggleClass(className, switchValue) { - if (switchValue && !classCache[className]) { - $animate.addClass($element, className); - classCache[className] = true; - } else if (!switchValue && classCache[className]) { - $animate.removeClass($element, className); - classCache[className] = false; - } - } + if (emptyOption_ || unknownOption_) { + while (current && + (current === emptyOption_ || + current === unknownOption_)) { + current = current.nextSibling; + } + } + return current; + } - function toggleValidationCss(validationErrorKey, isValid) { - validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; - cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true); - cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false); - } -} + function updateOptions() { -function isObjectEmpty(obj) { - if (obj) { - for (var prop in obj) { - return false; - } - } - return true; -} + var previousValue = options && selectCtrl.readValue(); -/** - * @ngdoc directive - * @name ngNonBindable - * @restrict AC - * @priority 1000 - * - * @description - * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current - * DOM element. This is useful if the element contains what appears to be Angular directives and - * bindings but which should be ignored by Angular. This could be the case if you have a site that - * displays snippets of code, for instance. - * - * @element ANY - * - * @example - * In this example there are two locations where a simple interpolation binding (`{{}}`) is present, - * but the one wrapped in `ngNonBindable` is left alone. - * - * @example - <example> - <file name="index.html"> - <div>Normal: {{1 + 2}}</div> - <div ng-non-bindable>Ignored: {{1 + 2}}</div> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-non-bindable', function() { - expect(element(by.binding('1 + 2')).getText()).toContain('3'); - expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/); - }); - </file> - </example> - */ -var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); + options = ngOptions.getOptions(); + + var groupMap = {}; + var currentElement = selectElement[0].firstChild; + + // Ensure that the empty option is always there if it was explicitly provided + if (providedEmptyOption) { + selectElement.prepend(emptyOption); + } + + currentElement = skipEmptyAndUnknownOptions(currentElement); + + options.items.forEach(function updateOption(option) { + var group; + var groupElement; + var optionElement; + + if (option.group) { + + // This option is to live in a group + // See if we have already created this group + group = groupMap[option.group]; + + if (!group) { + + // We have not already created this group + groupElement = addOrReuseElement(selectElement[0], + currentElement, + 'optgroup', + optGroupTemplate); + // Move to the next element + currentElement = groupElement.nextSibling; + + // Update the label on the group element + groupElement.label = option.group; + + // Store it for use later + group = groupMap[option.group] = { + groupElement: groupElement, + currentOptionElement: groupElement.firstChild + }; + + } + + // So now we have a group for this option we add the option to the group + optionElement = addOrReuseElement(group.groupElement, + group.currentOptionElement, + 'option', + optionTemplate); + updateOptionElement(option, optionElement); + // Move to the next element + group.currentOptionElement = optionElement.nextSibling; + + } else { + + // This option is not in a group + optionElement = addOrReuseElement(selectElement[0], + currentElement, + 'option', + optionTemplate); + updateOptionElement(option, optionElement); + // Move to the next element + currentElement = optionElement.nextSibling; + } + }); + + + // Now remove all excess options and group + Object.keys(groupMap).forEach(function(key) { + removeExcessElements(groupMap[key].currentOptionElement); + }); + removeExcessElements(currentElement); + + ngModelCtrl.$render(); + + // Check to see if the value has changed due to the update to the options + if (!ngModelCtrl.$isEmpty(previousValue)) { + var nextValue = selectCtrl.readValue(); + if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) { + ngModelCtrl.$setViewValue(nextValue); + ngModelCtrl.$render(); + } + } + + } + + } + }; +}]; /** * @ngdoc directive @@ -23888,6 +26501,9 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder * for <span ng-non-bindable>{{numberExpression}}</span>. * + * If no rule is defined for a category, then an empty string is displayed and a warning is generated. + * Note that some locales define more categories than `one` and `other`. For example, fr-fr defines `few` and `many`. + * * # Configuring ngPluralize with offset * The `offset` attribute allows further customization of pluralized text, which can result in * a better user experience. For example, instead of the message "4 people are viewing this document", @@ -23934,9 +26550,9 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); }]); </script> <div ng-controller="ExampleController"> - Person 1:<input type="text" ng-model="person1" value="Igor" /><br/> - Person 2:<input type="text" ng-model="person2" value="Misko" /><br/> - Number of People:<input type="text" ng-model="personCount" value="1" /><br/> + <label>Person 1:<input type="text" ng-model="person1" value="Igor" /></label><br/> + <label>Person 2:<input type="text" ng-model="person2" value="Misko" /></label><br/> + <label>Number of People:<input type="text" ng-model="personCount" value="1" /></label><br/> <!--- Example with simple pluralization rules for en locale ---> Without Offset: @@ -24006,12 +26622,11 @@ var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); </file> </example> */ -var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) { +var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) { var BRACE = /{}/g, IS_WHEN = /^when(Minus)?(.+)$/; return { - restrict: 'EA', link: function(scope, element, attr) { var numberExp = attr.count, whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs @@ -24048,9 +26663,18 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp // If both `count` and `lastCount` are NaN, we don't need to re-register a watch. // In JS `NaN !== NaN`, so we have to exlicitly check. - if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) { + if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) { watchRemover(); - watchRemover = scope.$watch(whensExpFns[count], updateElementText); + var whenExpFn = whensExpFns[count]; + if (isUndefined(whenExpFn)) { + if (newVal != null) { + $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp); + } + watchRemover = noop; + updateElementText(); + } else { + watchRemover = scope.$watch(whenExpFn, updateElementText); + } lastCount = count; } }); @@ -24065,6 +26689,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp /** * @ngdoc directive * @name ngRepeat + * @multiElement * * @description * The `ngRepeat` directive instantiates a template once per item from a collection. Each template @@ -24085,6 +26710,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}. * This may be useful when, for instance, nesting ngRepeats. * + * * # Iterating over object properties * * It is possible to get `ngRepeat` to iterate over the properties of an object using the following @@ -24094,19 +26720,78 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp * <div ng-repeat="(key, value) in myObj"> ... </div> * ``` * - * You need to be aware that the JavaScript specification does not define what order - * it will return the keys for an object. In order to have a guaranteed deterministic order - * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**. + * You need to be aware that the JavaScript specification does not define the order of keys + * returned for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive + * used to sort the keys alphabetically.) + * + * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser + * when running `for key in myObj`. It seems that browsers generally follow the strategy of providing + * keys in the order in which they were defined, although there are exceptions when keys are deleted + * and reinstated. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues * * If this is not desired, the recommended workaround is to convert your object into an array * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter) * or implement a `$watch` on the object yourself. * - * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the - * strategy of providing keys in the order in which they were defined, although there are exceptions - * when keys are deleted and reinstated. * + * # Tracking and Duplicates + * + * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM: + * + * * When an item is added, a new instance of the template is added to the DOM. + * * When an item is removed, its template instance is removed from the DOM. + * * When items are reordered, their respective templates are reordered in the DOM. + * + * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when + * there are duplicates, it is not possible to maintain a one-to-one mapping between collection + * items and DOM elements. + * + * If you do need to repeat duplicate items, you can substitute the default tracking behavior + * with your own using the `track by` expression. + * + * For example, you may track items by the index of each item in the collection, using the + * special scope property `$index`: + * ```html + * <div ng-repeat="n in [42, 42, 43, 43] track by $index"> + * {{n}} + * </div> + * ``` + * + * You may use arbitrary expressions in `track by`, including references to custom functions + * on the scope: + * ```html + * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)"> + * {{n}} + * </div> + * ``` + * + * If you are working with objects that have an identifier property, you can track + * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat` + * will not have to rebuild the DOM elements for items it has already rendered, even if the + * JavaScript objects in the collection have been substituted for new ones: + * ```html + * <div ng-repeat="model in collection track by model.id"> + * {{model.name}} + * </div> + * ``` + * + * When no `track by` expression is provided, it is equivalent to tracking by the built-in + * `$id` function, which tracks items by their identity: + * ```html + * <div ng-repeat="obj in collection track by $id(obj)"> + * {{obj.prop}} + * </div> + * ``` + * + * <div class="alert alert-warning"> + * **Note:** `track by` must always be the last expression: + * </div> + * ``` + * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id"> + * {{model.name}} + * </div> + * ``` * * # Special repeat start and end points * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending @@ -24175,12 +26860,13 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp * * For example: `(name, age) in {'adam':10, 'amalie':12}`. * - * * `variable in expression track by tracking_expression` – You can also provide an optional tracking function - * which can be used to associate the objects in the collection with the DOM elements. If no tracking function - * is specified the ng-repeat associates elements by identity in the collection. It is an error to have - * more than one tracking function to resolve to the same key. (This would mean that two distinct objects are - * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression, - * before specifying a tracking expression. + * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression + * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression + * is specified, ng-repeat associates elements by identity. It is an error to have + * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are + * mapped to the same DOM element, which is not possible.) + * + * Note that the tracking expression must come last, after any filters, and the alias expression. * * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements * will be associated by item identity in the array. @@ -24204,6 +26890,11 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after * the items have been processed through the filter. * + * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end + * (and not as operator, inside an expression). + * + * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` . + * * @example * This example initializes the scope to a list of names and * then uses `ngRepeat` to display every person: @@ -24222,7 +26913,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp {name:'Samantha', age:60, gender:'girl'} ]"> I have {{friends.length}} friends. They are: - <input type="search" ng-model="q" placeholder="filter friends..." /> + <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" /> <ul class="example-animate-container"> <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results"> [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. @@ -24420,14 +27111,13 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { trackByIdFn = trackByIdExpFn || trackByIdArrayFn; } else { trackByIdFn = trackByIdExpFn || trackByIdObjFn; - // if object, extract keys, sort them and use to determine order of iteration over obj props + // if object, extract keys, in enumeration order, unsorted collectionKeys = []; for (var itemKey in collection) { - if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') { + if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') { collectionKeys.push(itemKey); } } - collectionKeys.sort(); } collectionLength = collectionKeys.length; @@ -24529,6 +27219,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; /** * @ngdoc directive * @name ngShow + * @multiElement * * @description * The `ngShow` directive shows or hides the given HTML element based on the expression @@ -24622,7 +27313,7 @@ var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; * @example <example module="ngAnimate" deps="angular-animate.js" animations="true"> <file name="index.html"> - Click me: <input type="checkbox" ng-model="checked"><br/> + Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngHide"><br/> <div> Show: <div class="check-element animate-show" ng-show="checked"> @@ -24704,6 +27395,7 @@ var ngShowDirective = ['$animate', function($animate) { /** * @ngdoc directive * @name ngHide + * @multiElement * * @description * The `ngHide` directive shows or hides the given HTML element based on the expression @@ -24787,7 +27479,7 @@ var ngShowDirective = ['$animate', function($animate) { * @example <example module="ngAnimate" deps="angular-animate.js" animations="true"> <file name="index.html"> - Click me: <input type="checkbox" ng-model="checked"><br/> + Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow"><br/> <div> Show: <div class="check-element animate-hide" ng-show="checked"> @@ -24906,12 +27598,12 @@ var ngHideDirective = ['$animate', function($animate) { </example> */ var ngStyleDirective = ngDirective(function(scope, element, attr) { - scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { + scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { if (oldStyles && (newStyles !== oldStyles)) { forEach(oldStyles, function(val, style) { element.css(style, '');}); } if (newStyles) element.css(newStyles); - }); + }, true); }); /** @@ -24957,7 +27649,7 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) { * * @scope * @priority 1200 - * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>. + * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>. * On child elements add: * * * `ngSwitchWhen`: the case statement to match against. If match then this @@ -24974,7 +27666,7 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) { <div ng-controller="ExampleController"> <select ng-model="selection" ng-options="item for item in items"> </select> - <tt>selection={{selection}}</tt> + <code>selection={{selection}}</code> <hr/> <div class="animate-switch-container" ng-switch on="selection"> @@ -25044,7 +27736,6 @@ var ngStyleDirective = ngDirective(function(scope, element, attr) { */ var ngSwitchDirective = ['$animate', function($animate) { return { - restrict: 'EA', require: 'ngSwitch', // asks for $scope to fool the BC controller module @@ -25153,8 +27844,8 @@ var ngSwitchDefaultDirective = ngDirective({ }]); </script> <div ng-controller="ExampleController"> - <input ng-model="title"> <br/> - <textarea ng-model="text"></textarea> <br/> + <input ng-model="title" aria-label="title"> <br/> + <textarea ng-model="text" aria-label="text"></textarea> <br/> <pane title="{{title}}">{{text}}</pane> </div> </file> @@ -25192,791 +27883,325 @@ var ngTranscludeDirective = ngDirective({ }); /** - * @ngdoc directive - * @name script - * @restrict E - * - * @description - * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the - * template can be used by {@link ng.directive:ngInclude `ngInclude`}, - * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the - * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be - * assigned through the element's `id`, which can then be used as a directive's `templateUrl`. - * - * @param {string} type Must be set to `'text/ng-template'`. - * @param {string} id Cache name of the template. - * - * @example - <example> - <file name="index.html"> - <script type="text/ng-template" id="/tpl.html"> - Content of the template. - </script> - - <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a> - <div id="tpl-content" ng-include src="currentTpl"></div> - </file> - <file name="protractor.js" type="protractor"> - it('should load template defined inside script tag', function() { - element(by.css('#tpl-link')).click(); - expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); - }); - </file> - </example> - */ -var scriptDirective = ['$templateCache', function($templateCache) { - return { - restrict: 'E', - terminal: true, - compile: function(element, attr) { - if (attr.type == 'text/ng-template') { - var templateUrl = attr.id, - text = element[0].text; - - $templateCache.put(templateUrl, text); - } - } - }; -}]; - -var ngOptionsMinErr = minErr('ngOptions'); -/** - * @ngdoc directive - * @name select - * @restrict E - * - * @description - * HTML `SELECT` element with angular data-binding. - * - * # `ngOptions` - * - * The `ngOptions` attribute can be used to dynamically generate a list of `<option>` - * elements for the `<select>` element using the array or object obtained by evaluating the - * `ngOptions` comprehension expression. - * - * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a - * similar result. However, `ngOptions` provides some benefits such as reducing memory and - * increasing speed by not creating a new scope for each repeated instance, as well as providing - * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the - * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound - * to a non-string value. This is because an option element can only be bound to string values at - * present. - * - * When an item in the `<select>` menu is selected, the array element or object property - * represented by the selected option will be bound to the model identified by the `ngModel` - * directive. - * - * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can - * be nested into the `<select>` element. This element will then represent the `null` or "not selected" - * option. See example below for demonstration. - * - * <div class="alert alert-warning"> - * **Note:** `ngModel` compares by reference, not value. This is important when binding to an - * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). - * </div> - * - * ## `select` **`as`** - * - * Using `select` **`as`** will bind the result of the `select` expression to the model, but - * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources) - * or property name (for object data sources) of the value within the collection. If a **`track by`** expression - * is used, the result of that expression will be set as the value of the `option` and `select` elements. - * - * - * ### `select` **`as`** and **`track by`** - * - * <div class="alert alert-warning"> - * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together. - * </div> - * - * Consider the following example: - * - * ```html - * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"> - * ``` - * - * ```js - * $scope.values = [{ - * id: 1, - * label: 'aLabel', - * subItem: { name: 'aSubItem' } - * }, { - * id: 2, - * label: 'bLabel', - * subItem: { name: 'bSubItem' } - * }]; - * - * $scope.selected = { name: 'aSubItem' }; - * ``` - * - * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element - * of the data source (to `item` in this example). To calculate whether an element is selected, we do the - * following: - * - * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]` - * 2. Apply **`track by`** to the already selected value in `ngModel`. - * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected - * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to - * a wrong object, the selected element can't be found, `<select>` is always reset to the "not - * selected" option. - * - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required The control is considered valid only if value is entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {comprehension_expression=} ngOptions in one of the following forms: - * - * * for array data sources: - * * `label` **`for`** `value` **`in`** `array` - * * `select` **`as`** `label` **`for`** `value` **`in`** `array` - * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` - * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` - * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr` - * (for including a filter with `track by`) - * * for object data sources: - * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object` - * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object` - * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object` - * * `select` **`as`** `label` **`group by`** `group` - * **`for` `(`**`key`**`,`** `value`**`) in`** `object` - * - * Where: - * - * * `array` / `object`: an expression which evaluates to an array / object to iterate over. - * * `value`: local variable which will refer to each item in the `array` or each property value - * of `object` during iteration. - * * `key`: local variable which will refer to a property name in `object` during iteration. - * * `label`: The result of this expression will be the label for `<option>` element. The - * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`). - * * `select`: The result of this expression will be bound to the model of the parent `<select>` - * element. If not specified, `select` expression will default to `value`. - * * `group`: The result of this expression will be used to group options using the `<optgroup>` - * DOM element. - * * `trackexpr`: Used when working with an array of objects. The result of this expression will be - * used to identify the objects in the array. The `trackexpr` will most likely refer to the - * `value` variable (e.g. `value.propertyName`). With this the selection is preserved - * even when the options are recreated (e.g. reloaded from the server). - * - * @example - <example module="selectExample"> - <file name="index.html"> - <script> - angular.module('selectExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.colors = [ - {name:'black', shade:'dark'}, - {name:'white', shade:'light'}, - {name:'red', shade:'dark'}, - {name:'blue', shade:'dark'}, - {name:'yellow', shade:'light'} - ]; - $scope.myColor = $scope.colors[2]; // red - }]); - </script> - <div ng-controller="ExampleController"> - <ul> - <li ng-repeat="color in colors"> - Name: <input ng-model="color.name"> - [<a href ng-click="colors.splice($index, 1)">X</a>] - </li> - <li> - [<a href ng-click="colors.push({})">add</a>] - </li> - </ul> - <hr/> - Color (null not allowed): - <select ng-model="myColor" ng-options="color.name for color in colors"></select><br> - - Color (null allowed): - <span class="nullable"> - <select ng-model="myColor" ng-options="color.name for color in colors"> - <option value="">-- choose color --</option> - </select> - </span><br/> - - Color grouped by shade: - <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors"> - </select><br/> - - - Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br> - <hr/> - Currently selected: {{ {selected_color:myColor} }} - <div style="border:solid 1px black; height:20px" - ng-style="{'background-color':myColor.name}"> - </div> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-options', function() { - expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red'); - element.all(by.model('myColor')).first().click(); - element.all(by.css('select[ng-model="myColor"] option')).first().click(); - expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black'); - element(by.css('.nullable select[ng-model="myColor"]')).click(); - element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click(); - expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null'); - }); - </file> - </example> - */ - -var ngOptionsDirective = valueFn({ - restrict: 'A', - terminal: true -}); - -// jshint maxlen: false -var selectDirective = ['$compile', '$parse', function($compile, $parse) { - //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888 - var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/, - nullModelCtrl = {$setViewValue: noop}; -// jshint maxlen: 100 + * @ngdoc directive + * @name script + * @restrict E + * + * @description + * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the + * template can be used by {@link ng.directive:ngInclude `ngInclude`}, + * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the + * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be + * assigned through the element's `id`, which can then be used as a directive's `templateUrl`. + * + * @param {string} type Must be set to `'text/ng-template'`. + * @param {string} id Cache name of the template. + * + * @example + <example> + <file name="index.html"> + <script type="text/ng-template" id="/tpl.html"> + Content of the template. + </script> + <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a> + <div id="tpl-content" ng-include src="currentTpl"></div> + </file> + <file name="protractor.js" type="protractor"> + it('should load template defined inside script tag', function() { + element(by.css('#tpl-link')).click(); + expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); + }); + </file> + </example> + */ +var scriptDirective = ['$templateCache', function($templateCache) { return { restrict: 'E', - require: ['select', '?ngModel'], - controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) { - var self = this, - optionsMap = {}, - ngModelCtrl = nullModelCtrl, - nullOption, - unknownOption; - - - self.databound = $attrs.ngModel; + terminal: true, + compile: function(element, attr) { + if (attr.type == 'text/ng-template') { + var templateUrl = attr.id, + text = element[0].text; + $templateCache.put(templateUrl, text); + } + } + }; +}]; - self.init = function(ngModelCtrl_, nullOption_, unknownOption_) { - ngModelCtrl = ngModelCtrl_; - nullOption = nullOption_; - unknownOption = unknownOption_; - }; +var noopNgModelController = { $setViewValue: noop, $render: noop }; +/** + * @ngdoc type + * @name select.SelectController + * @description + * The controller for the `<select>` directive. This provides support for reading + * and writing the selected value(s) of the control and also coordinates dynamically + * added `<option>` elements, perhaps by an `ngRepeat` directive. + */ +var SelectController = + ['$element', '$scope', '$attrs', function($element, $scope, $attrs) { - self.addOption = function(value, element) { - assertNotHasOwnProperty(value, '"option value"'); - optionsMap[value] = true; + var self = this, + optionsMap = new HashMap(); + + // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors + self.ngModelCtrl = noopNgModelController; + + // The "unknown" option is one that is prepended to the list if the viewValue + // does not match any of the options. When it is rendered the value of the unknown + // option is '? XXX ?' where XXX is the hashKey of the value that is not known. + // + // We can't just jqLite('<option>') since jqLite is not smart enough + // to create it in <select> and IE barfs otherwise. + self.unknownOption = jqLite(document.createElement('option')); + self.renderUnknownOption = function(val) { + var unknownVal = '? ' + hashKey(val) + ' ?'; + self.unknownOption.val(unknownVal); + $element.prepend(self.unknownOption); + $element.val(unknownVal); + }; - if (ngModelCtrl.$viewValue == value) { - $element.val(value); - if (unknownOption.parent()) unknownOption.remove(); - } - // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 - // Adding an <option selected="selected"> element to a <select required="required"> should - // automatically select the new element - if (element && element[0].hasAttribute('selected')) { - element[0].selected = true; - } - }; + $scope.$on('$destroy', function() { + // disable unknown option so that we don't do work when the whole select is being destroyed + self.renderUnknownOption = noop; + }); + self.removeUnknownOption = function() { + if (self.unknownOption.parent()) self.unknownOption.remove(); + }; - self.removeOption = function(value) { - if (this.hasOption(value)) { - delete optionsMap[value]; - if (ngModelCtrl.$viewValue === value) { - this.renderUnknownOption(value); - } - } - }; + // Read the value of the select control, the implementation of this changes depending + // upon whether the select can have multiple values and whether ngOptions is at work. + self.readValue = function readSingleValue() { + self.removeUnknownOption(); + return $element.val(); + }; - self.renderUnknownOption = function(val) { - var unknownVal = '? ' + hashKey(val) + ' ?'; - unknownOption.val(unknownVal); - $element.prepend(unknownOption); - $element.val(unknownVal); - unknownOption.prop('selected', true); // needed for IE - }; + // Write the value to the select control, the implementation of this changes depending + // upon whether the select can have multiple values and whether ngOptions is at work. + self.writeValue = function writeSingleValue(value) { + if (self.hasOption(value)) { + self.removeUnknownOption(); + $element.val(value); + if (value === '') self.emptyOption.prop('selected', true); // to make IE9 happy + } else { + if (value == null && self.emptyOption) { + self.removeUnknownOption(); + $element.val(''); + } else { + self.renderUnknownOption(value); + } + } + }; - self.hasOption = function(value) { - return optionsMap.hasOwnProperty(value); - }; - $scope.$on('$destroy', function() { - // disable unknown option so that we don't do work when the whole select is being destroyed - self.renderUnknownOption = noop; - }); - }], + // Tell the select control that an option, with the given value, has been added + self.addOption = function(value, element) { + assertNotHasOwnProperty(value, '"option value"'); + if (value === '') { + self.emptyOption = element; + } + var count = optionsMap.get(value) || 0; + optionsMap.put(value, count + 1); + }; - link: function(scope, element, attr, ctrls) { - // if ngModel is not defined, we don't need to do anything - if (!ctrls[1]) return; - - var selectCtrl = ctrls[0], - ngModelCtrl = ctrls[1], - multiple = attr.multiple, - optionsExp = attr.ngOptions, - nullOption = false, // if false, user will not be able to select it (used by ngOptions) - emptyOption, - renderScheduled = false, - // we can't just jqLite('<option>') since jqLite is not smart enough - // to create it in <select> and IE barfs otherwise. - optionTemplate = jqLite(document.createElement('option')), - optGroupTemplate =jqLite(document.createElement('optgroup')), - unknownOption = optionTemplate.clone(); - - // find "null" option - for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) { - if (children[i].value === '') { - emptyOption = nullOption = children.eq(i); - break; + // Tell the select control that an option, with the given value, has been removed + self.removeOption = function(value) { + var count = optionsMap.get(value); + if (count) { + if (count === 1) { + optionsMap.remove(value); + if (value === '') { + self.emptyOption = undefined; } + } else { + optionsMap.put(value, count - 1); } + } + }; - selectCtrl.init(ngModelCtrl, nullOption, unknownOption); + // Check whether the select control has an option matching the given value + self.hasOption = function(value) { + return !!optionsMap.get(value); + }; +}]; - // required validator - if (multiple) { - ngModelCtrl.$isEmpty = function(value) { - return !value || value.length === 0; - }; - } +/** + * @ngdoc directive + * @name select + * @restrict E + * + * @description + * HTML `SELECT` element with angular data-binding. + * + * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions + * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits such as reducing + * memory and increasing speed by not creating a new scope for each repeated instance, as well as providing + * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the + * comprehension expression. + * + * When an item in the `<select>` menu is selected, the array element or object property + * represented by the selected option will be bound to the model identified by the `ngModel` + * directive. + * + * If the viewValue contains a value that doesn't match any of the options then the control + * will automatically add an "unknown" option, which it then removes when this is resolved. + * + * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can + * be nested into the `<select>` element. This element will then represent the `null` or "not selected" + * option. See example below for demonstration. + * + * <div class="alert alert-info"> + * The value of a `select` directive used without `ngOptions` is always a string. + * When the model needs to be bound to a non-string value, you must either explictly convert it + * using a directive (see example below) or use `ngOptions` to specify the set of options. + * This is because an option element can only be bound to string values at present. + * </div> + * + * ### Example (binding `select` to a non-string value) + * + * <example name="select-with-non-string-options" module="nonStringSelect"> + * <file name="index.html"> + * <select ng-model="model.id" convert-to-number> + * <option value="0">Zero</option> + * <option value="1">One</option> + * <option value="2">Two</option> + * </select> + * {{ model }} + * </file> + * <file name="app.js"> + * angular.module('nonStringSelect', []) + * .run(function($rootScope) { + * $rootScope.model = { id: 2 }; + * }) + * .directive('convertToNumber', function() { + * return { + * require: 'ngModel', + * link: function(scope, element, attrs, ngModel) { + * ngModel.$parsers.push(function(val) { + * return parseInt(val, 10); + * }); + * ngModel.$formatters.push(function(val) { + * return '' + val; + * }); + * } + * }; + * }); + * </file> + * <file name="protractor.js" type="protractor"> + * it('should initialize to model', function() { + * var select = element(by.css('select')); + * expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two'); + * }); + * </file> + * </example> + * + */ +var selectDirective = function() { - if (optionsExp) setupAsOptions(scope, element, ngModelCtrl); - else if (multiple) setupAsMultiple(scope, element, ngModelCtrl); - else setupAsSingle(scope, element, ngModelCtrl, selectCtrl); + return { + restrict: 'E', + require: ['select', '?ngModel'], + controller: SelectController, + link: function(scope, element, attr, ctrls) { + // if ngModel is not defined, we don't need to do anything + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; - //////////////////////////// + var selectCtrl = ctrls[0]; + selectCtrl.ngModelCtrl = ngModelCtrl; + // We delegate rendering to the `writeValue` method, which can be changed + // if the select can have multiple selected values or if the options are being + // generated by `ngOptions` + ngModelCtrl.$render = function() { + selectCtrl.writeValue(ngModelCtrl.$viewValue); + }; - function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) { - ngModelCtrl.$render = function() { - var viewValue = ngModelCtrl.$viewValue; + // When the selected item(s) changes we delegate getting the value of the select control + // to the `readValue` method, which can be changed if the select can have multiple + // selected values or if the options are being generated by `ngOptions` + element.on('change', function() { + scope.$apply(function() { + ngModelCtrl.$setViewValue(selectCtrl.readValue()); + }); + }); - if (selectCtrl.hasOption(viewValue)) { - if (unknownOption.parent()) unknownOption.remove(); - selectElement.val(viewValue); - if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy - } else { - if (isUndefined(viewValue) && emptyOption) { - selectElement.val(''); - } else { - selectCtrl.renderUnknownOption(viewValue); + // If the select allows multiple values then we need to modify how we read and write + // values from and to the control; also what it means for the value to be empty and + // we have to add an extra watch since ngModel doesn't work well with arrays - it + // doesn't trigger rendering if only an item in the array changes. + if (attr.multiple) { + + // Read value now needs to check each option to see if it is selected + selectCtrl.readValue = function readMultipleValue() { + var array = []; + forEach(element.find('option'), function(option) { + if (option.selected) { + array.push(option.value); } - } - }; - - selectElement.on('change', function() { - scope.$apply(function() { - if (unknownOption.parent()) unknownOption.remove(); - ngModelCtrl.$setViewValue(selectElement.val()); }); - }); - } + return array; + }; - function setupAsMultiple(scope, selectElement, ctrl) { - var lastView; - ctrl.$render = function() { - var items = new HashMap(ctrl.$viewValue); - forEach(selectElement.find('option'), function(option) { + // Write value now needs to set the selected property of each matching option + selectCtrl.writeValue = function writeMultipleValue(value) { + var items = new HashMap(value); + forEach(element.find('option'), function(option) { option.selected = isDefined(items.get(option.value)); }); }; // we have to do it on each watch since ngModel watches reference, but // we need to work of an array, so we need to see if anything was inserted/removed + var lastView, lastViewRef = NaN; scope.$watch(function selectMultipleWatch() { - if (!equals(lastView, ctrl.$viewValue)) { - lastView = shallowCopy(ctrl.$viewValue); - ctrl.$render(); + if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { + lastView = shallowCopy(ngModelCtrl.$viewValue); + ngModelCtrl.$render(); } + lastViewRef = ngModelCtrl.$viewValue; }); - selectElement.on('change', function() { - scope.$apply(function() { - var array = []; - forEach(selectElement.find('option'), function(option) { - if (option.selected) { - array.push(option.value); - } - }); - ctrl.$setViewValue(array); - }); - }); - } - - function setupAsOptions(scope, selectElement, ctrl) { - var match; - - if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) { - throw ngOptionsMinErr('iexp', - "Expected expression in form of " + - "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + - " but got '{0}'. Element: {1}", - optionsExp, startingTag(selectElement)); - } - - var displayFn = $parse(match[2] || match[1]), - valueName = match[4] || match[6], - selectAs = / as /.test(match[0]) && match[1], - selectAsFn = selectAs ? $parse(selectAs) : null, - keyName = match[5], - groupByFn = $parse(match[3] || ''), - valueFn = $parse(match[2] ? match[1] : valueName), - valuesFn = $parse(match[7]), - track = match[8], - trackFn = track ? $parse(match[8]) : null, - trackKeysCache = {}, - // This is an array of array of existing option groups in DOM. - // We try to reuse these if possible - // - optionGroupsCache[0] is the options with no option group - // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element - optionGroupsCache = [[{element: selectElement, label:''}]], - //re-usable object to represent option's locals - locals = {}; - - if (nullOption) { - // compile the element since there might be bindings in it - $compile(nullOption)(scope); - - // remove the class, which is added automatically because we recompile the element and it - // becomes the compilation root - nullOption.removeClass('ng-scope'); - - // we need to remove it before calling selectElement.empty() because otherwise IE will - // remove the label from the element. wtf? - nullOption.remove(); - } - - // clear contents, we'll add what's needed based on the model - selectElement.empty(); - - selectElement.on('change', selectionChanged); - - ctrl.$render = render; - - scope.$watchCollection(valuesFn, scheduleRendering); - scope.$watchCollection(getLabels, scheduleRendering); - - if (multiple) { - scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering); - } - - // ------------------------------------------------------------------ // - - function callExpression(exprFn, key, value) { - locals[valueName] = value; - if (keyName) locals[keyName] = key; - return exprFn(scope, locals); - } - - function selectionChanged() { - scope.$apply(function() { - var collection = valuesFn(scope) || []; - var viewValue; - if (multiple) { - viewValue = []; - forEach(selectElement.val(), function(selectedKey) { - selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey; - viewValue.push(getViewValue(selectedKey, collection[selectedKey])); - }); - } else { - var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val(); - viewValue = getViewValue(selectedKey, collection[selectedKey]); - } - ctrl.$setViewValue(viewValue); - render(); - }); - } - - function getViewValue(key, value) { - if (key === '?') { - return undefined; - } else if (key === '') { - return null; - } else { - var viewValueFn = selectAsFn ? selectAsFn : valueFn; - return callExpression(viewValueFn, key, value); - } - } - - function getLabels() { - var values = valuesFn(scope); - var toDisplay; - if (values && isArray(values)) { - toDisplay = new Array(values.length); - for (var i = 0, ii = values.length; i < ii; i++) { - toDisplay[i] = callExpression(displayFn, i, values[i]); - } - return toDisplay; - } else if (values) { - // TODO: Add a test for this case - toDisplay = {}; - for (var prop in values) { - if (values.hasOwnProperty(prop)) { - toDisplay[prop] = callExpression(displayFn, prop, values[prop]); - } - } - } - return toDisplay; - } - - function createIsSelectedFn(viewValue) { - var selectedSet; - if (multiple) { - if (trackFn && isArray(viewValue)) { - - selectedSet = new HashMap([]); - for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) { - // tracking by key - selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true); - } - } else { - selectedSet = new HashMap(viewValue); - } - } else if (trackFn) { - viewValue = callExpression(trackFn, null, viewValue); - } - - return function isSelected(key, value) { - var compareValueFn; - if (trackFn) { - compareValueFn = trackFn; - } else if (selectAsFn) { - compareValueFn = selectAsFn; - } else { - compareValueFn = valueFn; - } - - if (multiple) { - return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value))); - } else { - return viewValue === callExpression(compareValueFn, key, value); - } - }; - } - - function scheduleRendering() { - if (!renderScheduled) { - scope.$$postDigest(render); - renderScheduled = true; - } - } - - /** - * A new labelMap is created with each render. - * This function is called for each existing option with added=false, - * and each new option with added=true. - * - Labels that are passed to this method twice, - * (once with added=true and once with added=false) will end up with a value of 0, and - * will cause no change to happen to the corresponding option. - * - Labels that are passed to this method only once with added=false will end up with a - * value of -1 and will eventually be passed to selectCtrl.removeOption() - * - Labels that are passed to this method only once with added=true will end up with a - * value of 1 and will eventually be passed to selectCtrl.addOption() - */ - function updateLabelMap(labelMap, label, added) { - labelMap[label] = labelMap[label] || 0; - labelMap[label] += (added ? 1 : -1); - } - - function render() { - renderScheduled = false; - - // Temporary location for the option groups before we render them - var optionGroups = {'':[]}, - optionGroupNames = [''], - optionGroupName, - optionGroup, - option, - existingParent, existingOptions, existingOption, - viewValue = ctrl.$viewValue, - values = valuesFn(scope) || [], - keys = keyName ? sortedKeys(values) : values, - key, - value, - groupLength, length, - groupIndex, index, - labelMap = {}, - selected, - isSelected = createIsSelectedFn(viewValue), - anySelected = false, - lastElement, - element, - label, - optionId; - - trackKeysCache = {}; - - // We now build up the list of options we need (we merge later) - for (index = 0; length = keys.length, index < length; index++) { - key = index; - if (keyName) { - key = keys[index]; - if (key.charAt(0) === '$') continue; - } - value = values[key]; - - optionGroupName = callExpression(groupByFn, key, value) || ''; - if (!(optionGroup = optionGroups[optionGroupName])) { - optionGroup = optionGroups[optionGroupName] = []; - optionGroupNames.push(optionGroupName); - } - - selected = isSelected(key, value); - anySelected = anySelected || selected; - - label = callExpression(displayFn, key, value); // what will be seen by the user - - // doing displayFn(scope, locals) || '' overwrites zero values - label = isDefined(label) ? label : ''; - optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index); - if (trackFn) { - trackKeysCache[optionId] = key; - } - - optionGroup.push({ - // either the index into array or key from object - id: optionId, - label: label, - selected: selected // determine if we should be selected - }); - } - if (!multiple) { - if (nullOption || viewValue === null) { - // insert null option if we have a placeholder, or the model is null - optionGroups[''].unshift({id:'', label:'', selected:!anySelected}); - } else if (!anySelected) { - // option could not be found, we have to insert the undefined item - optionGroups[''].unshift({id:'?', label:'', selected:true}); - } - } - - // Now we need to update the list of DOM nodes to match the optionGroups we computed above - for (groupIndex = 0, groupLength = optionGroupNames.length; - groupIndex < groupLength; - groupIndex++) { - // current option group name or '' if no group - optionGroupName = optionGroupNames[groupIndex]; - - // list of options for that group. (first item has the parent) - optionGroup = optionGroups[optionGroupName]; - - if (optionGroupsCache.length <= groupIndex) { - // we need to grow the optionGroups - existingParent = { - element: optGroupTemplate.clone().attr('label', optionGroupName), - label: optionGroup.label - }; - existingOptions = [existingParent]; - optionGroupsCache.push(existingOptions); - selectElement.append(existingParent.element); - } else { - existingOptions = optionGroupsCache[groupIndex]; - existingParent = existingOptions[0]; // either SELECT (no group) or OPTGROUP element - - // update the OPTGROUP label if not the same. - if (existingParent.label != optionGroupName) { - existingParent.element.attr('label', existingParent.label = optionGroupName); - } - } - - lastElement = null; // start at the beginning - for (index = 0, length = optionGroup.length; index < length; index++) { - option = optionGroup[index]; - if ((existingOption = existingOptions[index + 1])) { - // reuse elements - lastElement = existingOption.element; - if (existingOption.label !== option.label) { - updateLabelMap(labelMap, existingOption.label, false); - updateLabelMap(labelMap, option.label, true); - lastElement.text(existingOption.label = option.label); - lastElement.prop('label', existingOption.label); - } - if (existingOption.id !== option.id) { - lastElement.val(existingOption.id = option.id); - } - // lastElement.prop('selected') provided by jQuery has side-effects - if (lastElement[0].selected !== option.selected) { - lastElement.prop('selected', (existingOption.selected = option.selected)); - if (msie) { - // See #7692 - // The selected item wouldn't visually update on IE without this. - // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well - lastElement.prop('selected', existingOption.selected); - } - } - } else { - // grow elements - - // if it's a null option - if (option.id === '' && nullOption) { - // put back the pre-compiled element - element = nullOption; - } else { - // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but - // in this version of jQuery on some browser the .text() returns a string - // rather then the element. - (element = optionTemplate.clone()) - .val(option.id) - .prop('selected', option.selected) - .attr('selected', option.selected) - .prop('label', option.label) - .text(option.label); - } + // If we are a multiple select then value is now a collection + // so the meaning of $isEmpty changes + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; - existingOptions.push(existingOption = { - element: element, - label: option.label, - id: option.id, - selected: option.selected - }); - updateLabelMap(labelMap, option.label, true); - if (lastElement) { - lastElement.after(element); - } else { - existingParent.element.append(element); - } - lastElement = element; - } - } - // remove any excessive OPTIONs in a group - index++; // increment since the existingOptions[0] is parent element not OPTION - while (existingOptions.length > index) { - option = existingOptions.pop(); - updateLabelMap(labelMap, option.label, false); - option.element.remove(); - } - } - // remove any excessive OPTGROUPs from select - while (optionGroupsCache.length > groupIndex) { - // remove all the labels in the option group - optionGroup = optionGroupsCache.pop(); - for (index = 1; index < optionGroup.length; ++index) { - updateLabelMap(labelMap, optionGroup[index].label, false); - } - optionGroup[0].element.remove(); - } - forEach(labelMap, function(count, label) { - if (count > 0) { - selectCtrl.addOption(label); - } else if (count < 0) { - selectCtrl.removeOption(label); - } - }); - } } } }; -}]; +}; + +// The option directive is purely designed to communicate the existence (or lack of) +// of dynamically created (and destroyed) option elements to their containing select +// directive via its controller. var optionDirective = ['$interpolate', function($interpolate) { - var nullSelectCtrl = { - addOption: noop, - removeOption: noop - }; + + function chromeHack(optionElement) { + // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 + // Adding an <option selected="selected"> element to a <select required="required"> should + // automatically select the new element + if (optionElement[0].hasAttribute('selected')) { + optionElement[0].selected = true; + } + } return { restrict: 'E', priority: 100, compile: function(element, attr) { + + // If the value attribute is not defined then we fall back to the + // text content of the option element, which may be interpolated if (isUndefined(attr.value)) { var interpolateFn = $interpolate(element.text(), true); if (!interpolateFn) { @@ -25985,30 +28210,39 @@ var optionDirective = ['$interpolate', function($interpolate) { } return function(scope, element, attr) { + + // This is an optimization over using ^^ since we don't want to have to search + // all the way to the root of the DOM for every single option element var selectCtrlName = '$selectController', parent = element.parent(), selectCtrl = parent.data(selectCtrlName) || parent.parent().data(selectCtrlName); // in case we are in optgroup - if (!selectCtrl || !selectCtrl.databound) { - selectCtrl = nullSelectCtrl; - } + // Only update trigger option updates if this is an option within a `select` + // that also has `ngModel` attached + if (selectCtrl && selectCtrl.ngModelCtrl) { - if (interpolateFn) { - scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) { - attr.$set('value', newVal); - if (oldVal !== newVal) { - selectCtrl.removeOption(oldVal); - } - selectCtrl.addOption(newVal, element); + if (interpolateFn) { + scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) { + attr.$set('value', newVal); + if (oldVal !== newVal) { + selectCtrl.removeOption(oldVal); + } + selectCtrl.addOption(newVal, element); + selectCtrl.ngModelCtrl.$render(); + chromeHack(element); + }); + } else { + selectCtrl.addOption(attr.value, element); + selectCtrl.ngModelCtrl.$render(); + chromeHack(element); + } + + element.on('$destroy', function() { + selectCtrl.removeOption(attr.value); + selectCtrl.ngModelCtrl.$render(); }); - } else { - selectCtrl.addOption(attr.value, element); } - - element.on('$destroy', function() { - selectCtrl.removeOption(attr.value); - }); }; } }; @@ -26079,7 +28313,7 @@ var maxlengthDirective = function() { var maxlength = -1; attr.$observe('maxlength', function(value) { - var intVal = int(value); + var intVal = toInt(value); maxlength = isNaN(intVal) ? -1 : intVal; ctrl.$validate(); }); @@ -26099,7 +28333,7 @@ var minlengthDirective = function() { var minlength = 0; attr.$observe('minlength', function(value) { - minlength = int(value) || 0; + minlength = toInt(value) || 0; ctrl.$validate(); }); ctrl.$validators.minlength = function(modelValue, viewValue) { @@ -26127,4 +28361,4 @@ var minlengthDirective = function() { })(window, document); -!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>'); +!window.angular.$$csp() && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); \ No newline at end of file diff --git a/www/lib/ionic/js/angular/angular.min.js b/www/lib/ionic/js/angular/angular.min.js index 67400e255a13bcbad116c3ae7c014aa4af7a7c35..2c28ef96f261392e1126ca9f316a9e75e6f3d6ff 100644 --- a/www/lib/ionic/js/angular/angular.min.js +++ b/www/lib/ionic/js/angular/angular.min.js @@ -1,250 +1,290 @@ /* - AngularJS v1.3.13 - (c) 2010-2014 Google, Inc. http://angularjs.org + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org License: MIT */ -(function(M,Y,t){'use strict';function S(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.3.13/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ta(b){if(null==b||Ua(b))return!1;var a=b.length;return b.nodeType=== -oa&&a?!0:F(b)||H(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function s(b,a,c){var d,e;if(b)if(G(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(H(b)||Ta(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==s)b.forEach(a,c,b);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d,b);return b}function Ed(b,a,c){for(var d=Object.keys(b).sort(),e=0;e<d.length;e++)a.call(c, -b[d[e]],d[e]);return d}function lc(b){return function(a,c){b(c,a)}}function Fd(){return++ob}function mc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function x(b){for(var a=b.$$hashKey,c=1,d=arguments.length;c<d;c++){var e=arguments[c];if(e)for(var f=Object.keys(e),g=0,h=f.length;g<h;g++){var l=f[g];b[l]=e[l]}}mc(b,a);return b}function ba(b){return parseInt(b,10)}function Pb(b,a){return x(Object.create(b),a)}function z(){}function pa(b){return b}function ea(b){return function(){return b}}function B(b){return"undefined"=== -typeof b}function y(b){return"undefined"!==typeof b}function I(b){return null!==b&&"object"===typeof b}function F(b){return"string"===typeof b}function V(b){return"number"===typeof b}function qa(b){return"[object Date]"===Da.call(b)}function G(b){return"function"===typeof b}function pb(b){return"[object RegExp]"===Da.call(b)}function Ua(b){return b&&b.window===b}function Va(b){return b&&b.$evalAsync&&b.$watch}function Wa(b){return"boolean"===typeof b}function nc(b){return!(!b||!(b.nodeName||b.prop&& -b.attr&&b.find))}function Gd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function ua(b){return Q(b.nodeName||b[0]&&b[0].nodeName)}function Xa(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return a}function Ea(b,a,c,d){if(Ua(b)||Va(b))throw Ka("cpws");if(a){if(b===a)throw Ka("cpi");c=c||[];d=d||[];if(I(b)){var e=c.indexOf(b);if(-1!==e)return d[e];c.push(b);d.push(a)}if(H(b))for(var f=a.length=0;f<b.length;f++)e=Ea(b[f],null,c,d),I(b[f])&&(c.push(b[f]),d.push(e)),a.push(e); -else{var g=a.$$hashKey;H(a)?a.length=0:s(a,function(b,c){delete a[c]});for(f in b)b.hasOwnProperty(f)&&(e=Ea(b[f],null,c,d),I(b[f])&&(c.push(b[f]),d.push(e)),a[f]=e);mc(a,g)}}else if(a=b)H(b)?a=Ea(b,[],c,d):qa(b)?a=new Date(b.getTime()):pb(b)?(a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex):I(b)&&(e=Object.create(Object.getPrototypeOf(b)),a=Ea(b,e,c,d));return a}function ra(b,a){if(H(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(I(b))for(c in a=a||{}, -b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ga(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(H(b)){if(!H(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ga(b[d],a[d]))return!1;return!0}}else{if(qa(b))return qa(a)?ga(b.getTime(),a.getTime()):!1;if(pb(b)&&pb(a))return b.toString()==a.toString();if(Va(b)||Va(a)||Ua(b)||Ua(a)||H(a))return!1;c={};for(d in b)if("$"!==d.charAt(0)&&!G(b[d])){if(!ga(b[d], -a[d]))return!1;c[d]=!0}for(d in a)if(!c.hasOwnProperty(d)&&"$"!==d.charAt(0)&&a[d]!==t&&!G(a[d]))return!1;return!0}return!1}function Ya(b,a,c){return b.concat(Za.call(a,c))}function oc(b,a){var c=2<arguments.length?Za.call(arguments,2):[];return!G(a)||a instanceof RegExp?a:c.length?function(){return arguments.length?a.apply(b,Ya(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Hd(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)&&"$"===b.charAt(1)? -c=t:Ua(a)?c="$WINDOW":a&&Y===a?c="$DOCUMENT":Va(a)&&(c="$SCOPE");return c}function $a(b,a){if("undefined"===typeof b)return t;V(a)||(a=a?2:null);return JSON.stringify(b,Hd,a)}function pc(b){return F(b)?JSON.parse(b):b}function va(b){b=D(b).clone();try{b.empty()}catch(a){}var c=D("<div>").append(b).html();try{return b[0].nodeType===qb?Q(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+Q(b)})}catch(d){return Q(c)}}function qc(b){try{return decodeURIComponent(b)}catch(a){}}function rc(b){var a= -{},c,d;s((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,"%20").split("="),d=qc(c[0]),y(d)&&(b=y(c[1])?qc(c[1]):!0,sc.call(a,d)?H(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];s(b,function(b,d){H(b)?s(b,function(b){a.push(Fa(d,!0)+(!0===b?"":"="+Fa(b,!0)))}):a.push(Fa(d,!0)+(!0===b?"":"="+Fa(b,!0)))});return a.length?a.join("&"):""}function rb(b){return Fa(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Fa(b,a){return encodeURIComponent(b).replace(/%40/gi, -"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Id(b,a){var c,d,e=sb.length;b=D(b);for(d=0;d<e;++d)if(c=sb[d]+a,F(c=b.attr(c)))return c;return null}function Jd(b,a){var c,d,e={};s(sb,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});s(sb,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Id(c,"strict-di"), -a(c,d?[d]:[],e))}function tc(b,a,c){I(c)||(c={});c=x({strictDi:!1},c);var d=function(){b=D(b);if(b.injector()){var d=b[0]===Y?"document":va(b);throw Ka("btstrpd",d.replace(/</,"<").replace(/>/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=ab(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector", -d);c(b)(a)})}]);return d},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;M&&e.test(M.name)&&(c.debugInfoEnabled=!0,M.name=M.name.replace(e,""));if(M&&!f.test(M.name))return d();M.name=M.name.replace(f,"");ca.resumeBootstrap=function(b){s(b,function(b){a.push(b)});return d()};G(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function Kd(){M.name="NG_ENABLE_DEBUG_INFO!"+M.name;M.location.reload()}function Ld(b){b=ca.element(b).injector();if(!b)throw Ka("test");return b.get("$$testability")} -function uc(b,a){a=a||"_";return b.replace(Md,function(b,d){return(d?a:"")+b.toLowerCase()})}function Nd(){var b;vc||((sa=M.jQuery)&&sa.fn.on?(D=sa,x(sa.fn,{scope:La.scope,isolateScope:La.isolateScope,controller:La.controller,injector:La.injector,inheritedData:La.inheritedData}),b=sa.cleanData,sa.cleanData=function(a){var c;if(Rb)Rb=!1;else for(var d=0,e;null!=(e=a[d]);d++)(c=sa._data(e,"events"))&&c.$destroy&&sa(e).triggerHandler("$destroy");b(a)}):D=R,ca.element=D,vc=!0)}function Sb(b,a,c){if(!b)throw Ka("areq", -a||"?",c||"required");return b}function tb(b,a,c){c&&H(b)&&(b=b[b.length-1]);Sb(G(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ma(b,a){if("hasOwnProperty"===b)throw Ka("badname",a);}function wc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&G(b)?oc(e,b):b}function ub(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!==b);return D(c)}function ha(){return Object.create(null)} -function Od(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=S("$injector"),d=S("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||S;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(c,d,e,f){f||(f=b);return function(){f[e||"push"]([c,d,arguments]);return u}}if(!g)throw c("nomod",f);var b=[],d=[],e=[],q=a("$injector","invoke","push",d),u={_invokeQueue:b,_configBlocks:d, -_runBlocks:e,requires:g,name:f,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:q,run:function(a){e.push(a);return this}};h&&q(h);return u})}})}function Pd(b){x(b,{bootstrap:tc,copy:Ea,extend:x,equals:ga, -element:D,forEach:s,injector:ab,noop:z,bind:oc,toJson:$a,fromJson:pc,identity:pa,isUndefined:B,isDefined:y,isString:F,isFunction:G,isObject:I,isNumber:V,isElement:nc,isArray:H,version:Qd,isDate:qa,lowercase:Q,uppercase:vb,callbacks:{counter:0},getTestability:Ld,$$minErr:S,$$csp:bb,reloadWithDebugInfo:Kd});cb=Od(M);try{cb("ngLocale")}catch(a){cb("ngLocale",[]).provider("$locale",Rd)}cb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:Sd});a.provider("$compile",xc).directive({a:Td, -input:yc,textarea:yc,form:Ud,script:Vd,select:Wd,style:Xd,option:Yd,ngBind:Zd,ngBindHtml:$d,ngBindTemplate:ae,ngClass:be,ngClassEven:ce,ngClassOdd:de,ngCloak:ee,ngController:fe,ngForm:ge,ngHide:he,ngIf:ie,ngInclude:je,ngInit:ke,ngNonBindable:le,ngPluralize:me,ngRepeat:ne,ngShow:oe,ngStyle:pe,ngSwitch:qe,ngSwitchWhen:re,ngSwitchDefault:se,ngOptions:te,ngTransclude:ue,ngModel:ve,ngList:we,ngChange:xe,pattern:zc,ngPattern:zc,required:Ac,ngRequired:Ac,minlength:Bc,ngMinlength:Bc,maxlength:Cc,ngMaxlength:Cc, -ngValue:ye,ngModelOptions:ze}).directive({ngInclude:Ae}).directive(wb).directive(Dc);a.provider({$anchorScroll:Be,$animate:Ce,$browser:De,$cacheFactory:Ee,$controller:Fe,$document:Ge,$exceptionHandler:He,$filter:Ec,$interpolate:Ie,$interval:Je,$http:Ke,$httpBackend:Le,$location:Me,$log:Ne,$parse:Oe,$rootScope:Pe,$q:Qe,$$q:Re,$sce:Se,$sceDelegate:Te,$sniffer:Ue,$templateCache:Ve,$templateRequest:We,$$testability:Xe,$timeout:Ye,$window:Ze,$$rAF:$e,$$asyncCallback:af,$$jqLite:bf})}])}function db(b){return b.replace(cf, -function(a,b,d,e){return e?d.toUpperCase():d}).replace(df,"Moz$1")}function Fc(b){b=b.nodeType;return b===oa||!b||9===b}function Gc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Tb.test(b)){c=c||e.appendChild(a.createElement("div"));d=(ef.exec(b)||["",""])[1].toLowerCase();d=ia[d]||ia._default;c.innerHTML=d[1]+b.replace(ff,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=Ya(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";s(f,function(a){e.appendChild(a)}); -return e}function R(b){if(b instanceof R)return b;var a;F(b)&&(b=U(b),a=!0);if(!(this instanceof R)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new R(b)}if(a){a=Y;var c;b=(c=gf.exec(b))?[a.createElement(c[1])]:(c=Gc(b,a))?c.childNodes:[]}Hc(this,b)}function Vb(b){return b.cloneNode(!0)}function xb(b,a){a||yb(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)yb(c[d])}function Ic(b,a,c,d){if(y(d))throw Ub("offargs");var e=(d=zb(b))&&d.events,f=d&&d.handle;if(f)if(a)s(a.split(" "), -function(a){if(y(c)){var d=e[a];Xa(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a,f,!1),delete e[a]}function yb(b,a){var c=b.ng339,d=c&&Ab[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Ic(b)),delete Ab[c],b.ng339=t))}function zb(b,a){var c=b.ng339,c=c&&Ab[c];a&&!c&&(b.ng339=c=++hf,c=Ab[c]={events:{},data:{},handle:t});return c}function Wb(b,a,c){if(Fc(b)){var d=y(c),e=!d&&a&&!I(a), -f=!a;b=(b=zb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];x(b,a)}}}function Bb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function Cb(b,a){a&&b.setAttribute&&s(a.split(" "),function(a){b.setAttribute("class",U((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+U(a)+" "," ")))})}function Db(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," "); -s(a.split(" "),function(a){a=U(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",U(c))}}function Hc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c=a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Jc(b,a){return Eb(b,"$"+(a||"ngController")+"Controller")}function Eb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=H(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=D.data(b,a[d]))!==t)return c;b=b.parentNode|| -11===b.nodeType&&b.host}}function Kc(b){for(xb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Lc(b,a){a||xb(b);var c=b.parentNode;c&&c.removeChild(b)}function jf(b,a){a=a||M;if("complete"===a.document.readyState)a.setTimeout(b);else D(a).on("load",b)}function Mc(b,a){var c=Fb[a.toLowerCase()];return c&&Nc[ua(b)]&&c}function kf(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Oc[a]}function lf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f= -a[e||c.type],g=f?f.length:0;if(g){if(B(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=ra(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function bf(){this.$get=function(){return x(R,{hasClass:function(b,a){b.attr&&(b=b[0]); -return Bb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return Db(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return Cb(b,a)}})}}function Na(b,a){var c=b&&b.$$hashKey;if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Fd)():c+":"+b}function eb(b,a){if(a){var c=0;this.nextUid=function(){return++c}}s(b,this.put,this)}function mf(b){return(b=b.toString().replace(Pc,"").match(Qc))?"function("+(b[1]||"").replace(/[\s\r\n]+/, -" ")+")":"fn"}function ab(b,a){function c(a){return function(b,c){if(I(b))s(b,lc(a));else return a(b,c)}}function d(a,b){Ma(a,"service");if(G(b)||H(b))b=q.instantiate(b);if(!b.$get)throw Ga("pget",a);return n[a+"Provider"]=b}function e(a,b){return function(){var c=r.invoke(b,this);if(B(c))throw Ga("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;s(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=q.get(e[0]);f[e[1]].apply(f, -e[2])}}if(!m.get(a)){m.put(a,!0);try{F(a)?(c=cb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):G(a)?b.push(q.invoke(a)):H(a)?b.push(q.invoke(a)):tb(a,"module")}catch(e){throw H(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ga("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Ga("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a), -b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var h=[],k=ab.$$annotate(b,a,g),l,q,n;q=0;for(l=k.length;q<l;q++){n=k[q];if("string"!==typeof n)throw Ga("itkn",n);h.push(f&&f.hasOwnProperty(n)?f[n]:d(n,g))}H(b)&&(b=b[l]);return b.apply(c,h)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((H(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return I(a)||G(a)?a:d},get:d,annotate:ab.$$annotate,has:function(a){return n.hasOwnProperty(a+ -"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],m=new eb([],!0),n={$provide:{provider:c(d),factory:c(f),service:c(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ea(b),!1)}),constant:c(function(a,b){Ma(a,"constant");n[a]=b;u[a]=b}),decorator:function(a,b){var c=q.get(a+"Provider"),d=c.$get;c.$get=function(){var a=r.invoke(d,c);return r.invoke(b,null,{$delegate:a})}}}},q=n.$injector=h(n,function(a,b){ca.isString(b)&&k.push(b); -throw Ga("unpr",k.join(" <- "));}),u={},r=u.$injector=h(u,function(a,b){var c=q.get(a+"Provider",b);return r.invoke(c.$get,c,t,a)});s(g(b),function(a){r.invoke(a||z)});return r}function Be(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ua(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;G(c)?c=c():nc(c)?(c=c[0],c="fixed"!== -a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):V(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0,0)}function g(){var a=c.hash(),b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||jf(function(){d.$evalAsync(g)})});return g}]}function af(){this.$get=["$$rAF","$timeout",function(b,a){return b.supported?function(a){return b(a)}: -function(b){return a(b,0,!1)}}]}function nf(b,a,c,d){function e(a){try{a.apply(null,Za.call(arguments,1))}finally{if(v--,0===v)for(;w.length;)try{w.pop()()}catch(b){c.error(b)}}}function f(a,b){(function N(){s(L,function(a){a()});C=b(N,a)})()}function g(){h();l()}function h(){A=b.history.state;A=B(A)?null:A;ga(A,J)&&(A=J);J=A}function l(){if(E!==m.url()||O!==A)E=m.url(),O=A,s(W,function(a){a(m.url(),A)})}function k(a){try{return decodeURIComponent(a)}catch(b){return a}}var m=this,n=a[0],q=b.location, -u=b.history,r=b.setTimeout,P=b.clearTimeout,p={};m.isMock=!1;var v=0,w=[];m.$$completeOutstandingRequest=e;m.$$incOutstandingRequestCount=function(){v++};m.notifyWhenNoOutstandingRequests=function(a){s(L,function(a){a()});0===v?a():w.push(a)};var L=[],C;m.addPollFn=function(a){B(C)&&f(100,r);L.push(a);return a};var A,O,E=q.href,T=a.find("base"),X=null;h();O=A;m.url=function(a,c,e){B(e)&&(e=null);q!==b.location&&(q=b.location);u!==b.history&&(u=b.history);if(a){var f=O===e;if(E===a&&(!d.history||f))return m; -var g=E&&Ha(E)===Ha(a);E=a;O=e;!d.history||g&&f?(g||(X=a),c?q.replace(a):g?(c=q,e=a.indexOf("#"),a=-1===e?"":a.substr(e+1),c.hash=a):q.href=a):(u[c?"replaceState":"pushState"](e,"",a),h(),O=A);return m}return X||q.href.replace(/%27/g,"'")};m.state=function(){return A};var W=[],wa=!1,J=null;m.onUrlChange=function(a){if(!wa){if(d.history)D(b).on("popstate",g);D(b).on("hashchange",g);wa=!0}W.push(a);return a};m.$$checkUrlChange=l;m.baseHref=function(){var a=T.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/, -""):""};var fa={},y="",da=m.baseHref();m.cookies=function(a,b){var d,e,f,g;if(a)b===t?n.cookie=encodeURIComponent(a)+"=;path="+da+";expires=Thu, 01 Jan 1970 00:00:00 GMT":F(b)&&(d=(n.cookie=encodeURIComponent(a)+"="+encodeURIComponent(b)+";path="+da).length+1,4096<d&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"));else{if(n.cookie!==y)for(y=n.cookie,d=y.split("; "),fa={},f=0;f<d.length;f++)e=d[f],g=e.indexOf("="),0<g&&(a=k(e.substring(0,g)), -fa[a]===t&&(fa[a]=k(e.substring(g+1))));return fa}};m.defer=function(a,b){var c;v++;c=r(function(){delete p[c];e(a)},b||0);p[c]=!0;return c};m.defer.cancel=function(a){return p[a]?(delete p[a],P(a),e(z),!0):!1}}function De(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new nf(b,d,a,c)}]}function Ee(){this.$get=function(){function b(b,d){function e(a){a!=n&&(q?q==a&&(q=a.n):q=a,f(a.n,a.p),f(a,n),n=a,n.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw S("$cacheFactory")("iid", -b);var g=0,h=x({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,m={},n=null,q=null;return a[b]={put:function(a,b){if(k<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}if(!B(b))return a in l||g++,l[a]=b,g>k&&this.remove(q.key),b},get:function(a){if(k<Number.MAX_VALUE){var b=m[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=m[a];if(!b)return;b==n&&(n=b.p);b==q&&(q=b.n);f(b.n,b.p);delete m[a]}delete l[a];g--},removeAll:function(){l={};g=0;m={};n=q=null},destroy:function(){m= -h=l=null;delete a[b]},info:function(){return x({},h,{size:g})}}}var a={};b.info=function(){var b={};s(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function Ve(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function xc(b,a){function c(a,b){var c=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,d={};s(a,function(a,e){var f=a.match(c);if(!f)throw ja("iscp",b,e,a);d[e]={mode:f[1][0],collection:"*"===f[2],optional:"?"===f[3],attrName:f[4]||e}});return d}var d= -{},e=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,f=/(([\w\-]+)(?:\:([^;]+))?;?)/,g=Gd("ngSrc,ngSrcset,src,srcset"),h=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,l=/^(on[a-z]+|formaction)$/;this.directive=function n(a,e){Ma(a,"directive");F(a)?(Sb(e,"directiveFactory"),d.hasOwnProperty(a)||(d[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,e){var f=[];s(d[a],function(d,g){try{var h=b.invoke(d);G(h)?h={compile:ea(h)}:!h.compile&&h.link&&(h.compile=ea(h.link));h.priority=h.priority||0;h.index= -g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";I(h.scope)&&(h.$$isolateBindings=c(h.scope,h.name));f.push(h)}catch(l){e(l)}});return f}])),d[a].push(e)):s(a,lc(n));return this};this.aHrefSanitizationWhitelist=function(b){return y(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};var k=!0;this.debugInfoEnabled= -function(a){return y(a)?(k=a,this):k};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,r,P,p,v,w,L,C,A){function O(a,b){try{a.addClass(b)}catch(c){}}function E(a,b,c,d,e){a instanceof D||(a=D(a));s(a,function(b,c){b.nodeType==qb&&b.nodeValue.match(/\S+/)&&(a[c]=D(b).wrap("<span></span>").parent()[0])});var f=T(a,b,a,c,d,e);E.$$addScopeClass(a);var g=null;return function(b,c, -d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ua(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?D(Xb(g,D("<div>").append(a).html())):c?La.clone.call(a):a;if(h)for(var l in h)d.data("$"+l+"Controller",h[l].instance);E.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function T(a,b,c,d,e,f){function g(a,c,d,e){var f,l,k,q,n,p,w;if(r)for(w= -Array(c.length),q=0;q<h.length;q+=3)f=h[q],w[f]=c[f];else w=c;q=0;for(n=h.length;q<n;)l=w[h[q++]],c=h[q++],f=h[q++],c?(c.scope?(k=a.$new(),E.$$addScopeInfo(D(l),k)):k=a,p=c.transcludeOnThisElement?X(a,c.transclude,e,c.elementTranscludeOnThisElement):!c.templateOnThisElement&&e?e:!e&&b?X(a,b):null,c(f,k,l,d,p)):f&&f(a,l.childNodes,t,e)}for(var h=[],l,k,q,n,r,p=0;p<a.length;p++){l=new Yb;k=W(a[p],[],l,0===p?d:t,e);(f=k.length?fa(k,a[p],l,b,c,null,[],[],f):null)&&f.scope&&E.$$addScopeClass(l.$$element); -l=f&&f.terminal||!(q=a[p].childNodes)||!q.length?null:T(q,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||l)h.push(p,f,l),n=!0,r=r||f;f=null}return n?g:null}function X(a,b,c,d){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function W(a,b,c,d,g){var h=c.$attr,l;switch(a.nodeType){case oa:da(b,ya(ua(a)),"E",d,g);for(var k,q,n,r=a.attributes,p=0,w=r&&r.length;p< -w;p++){var P=!1,L=!1;k=r[p];l=k.name;q=U(k.value);k=ya(l);if(n=gb.test(k))l=l.replace(Sc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var u=k.replace(/(Start|End)$/,"");B(u)&&k===u+"Start"&&(P=l,L=l.substr(0,l.length-5)+"end",l=l.substr(0,l.length-6));k=ya(l.toLowerCase());h[k]=l;if(n||!c.hasOwnProperty(k))c[k]=q,Mc(a,k)&&(c[k]=!0);Pa(a,b,q,k,n);da(b,k,"A",d,g,P,L)}a=a.className;I(a)&&(a=a.animVal);if(F(a)&&""!==a)for(;l=f.exec(a);)k=ya(l[2]),da(b,k,"C",d,g)&&(c[k]=U(l[3])), -a=a.substr(l.index+l[0].length);break;case qb:M(b,a.nodeValue);break;case 8:try{if(l=e.exec(a.nodeValue))k=ya(l[1]),da(b,k,"M",d,g)&&(c[k]=U(l[2]))}catch(v){}}b.sort(N);return b}function wa(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ja("uterdir",b,c);a.nodeType==oa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return D(d)}function J(a,b,c){return function(d,e,f,g,h){e=wa(e[0],b,c);return a(d,e,f,g,h)}}function fa(a, -d,e,f,g,l,k,n,r){function w(a,b,c,d){if(a){c&&(a=J(a,c,d));a.require=K.require;a.directiveName=x;if(T===K||K.$$isolateScope)a=Z(a,{isolateScope:!0});k.push(a)}if(b){c&&(b=J(b,c,d));b.require=K.require;b.directiveName=x;if(T===K||K.$$isolateScope)b=Z(b,{isolateScope:!0});n.push(b)}}function L(a,b,c,d){var e,f="data",g=!1,l=c,k;if(F(b)){k=b.match(h);b=b.substring(k[0].length);k[3]&&(k[1]?k[3]=null:k[1]=k[3]);"^"===k[1]?f="inheritedData":"^^"===k[1]&&(f="inheritedData",l=c.parent());"?"===k[2]&&(g=!0); -e=null;d&&"data"===f&&(e=d[b])&&(e=e.instance);e=e||l[f]("$"+b+"Controller");if(!e&&!g)throw ja("ctreq",b,a);return e||null}H(b)&&(e=[],s(b,function(b){e.push(L(a,b,c,d))}));return e}function v(a,c,f,g,h){function l(a,b,c){var d;Va(a)||(c=b,b=a,a=t);z&&(d=O);c||(c=z?W.parent():W);return h(a,b,d,c,wa)}var r,w,u,A,O,fb,W,J;d===f?(J=e,W=e.$$element):(W=D(f),J=new Yb(W,e));T&&(A=c.$new(!0));h&&(fb=l,fb.$$boundTransclude=h);C&&(X={},O={},s(C,function(a){var b={$scope:a===T||a.$$isolateScope?A:c,$element:W, -$attrs:J,$transclude:fb};u=a.controller;"@"==u&&(u=J[a.name]);b=p(u,b,!0,a.controllerAs);O[a.name]=b;z||W.data("$"+a.name+"Controller",b.instance);X[a.name]=b}));if(T){E.$$addScopeInfo(W,A,!0,!(ka&&(ka===T||ka===T.$$originalDirective)));E.$$addScopeClass(W,!0);g=X&&X[T.name];var xa=A;g&&g.identifier&&!0===T.bindToController&&(xa=g.instance);s(A.$$isolateBindings=T.$$isolateBindings,function(a,d){var e=a.attrName,f=a.optional,g,h,l,k;switch(a.mode){case "@":J.$observe(e,function(a){xa[d]=a});J.$$observers[e].$$scope= -c;J[e]&&(xa[d]=b(J[e])(c));break;case "=":if(f&&!J[e])break;h=P(J[e]);k=h.literal?ga:function(a,b){return a===b||a!==a&&b!==b};l=h.assign||function(){g=xa[d]=h(c);throw ja("nonassign",J[e],T.name);};g=xa[d]=h(c);f=function(a){k(a,xa[d])||(k(a,g)?l(c,a=xa[d]):xa[d]=a);return g=a};f.$stateful=!0;f=a.collection?c.$watchCollection(J[e],f):c.$watch(P(J[e],f),null,h.literal);A.$on("$destroy",f);break;case "&":h=P(J[e]),xa[d]=function(a){return h(c,a)}}})}X&&(s(X,function(a){a()}),X=null);g=0;for(r=k.length;g< -r;g++)w=k[g],$(w,w.isolateScope?A:c,W,J,w.require&&L(w.directiveName,w.require,W,O),fb);var wa=c;T&&(T.template||null===T.templateUrl)&&(wa=A);a&&a(wa,f.childNodes,t,h);for(g=n.length-1;0<=g;g--)w=n[g],$(w,w.isolateScope?A:c,W,J,w.require&&L(w.directiveName,w.require,W,O),fb)}r=r||{};for(var A=-Number.MAX_VALUE,O,C=r.controllerDirectives,X,T=r.newIsolateScopeDirective,ka=r.templateDirective,fa=r.nonTlbTranscludeDirective,da=!1,B=!1,z=r.hasElementTranscludeDirective,aa=e.$$element=D(d),K,x,N,Aa=f, -Q,M=0,R=a.length;M<R;M++){K=a[M];var Pa=K.$$start,gb=K.$$end;Pa&&(aa=wa(d,Pa,gb));N=t;if(A>K.priority)break;if(N=K.scope)K.templateUrl||(I(N)?(Oa("new/isolated scope",T||O,K,aa),T=K):Oa("new/isolated scope",T,K,aa)),O=O||K;x=K.name;!K.templateUrl&&K.controller&&(N=K.controller,C=C||{},Oa("'"+x+"' controller",C[x],K,aa),C[x]=K);if(N=K.transclude)da=!0,K.$$tlb||(Oa("transclusion",fa,K,aa),fa=K),"element"==N?(z=!0,A=K.priority,N=aa,aa=e.$$element=D(Y.createComment(" "+x+": "+e[x]+" ")),d=aa[0],V(g,Za.call(N, -0),d),Aa=E(N,f,A,l&&l.name,{nonTlbTranscludeDirective:fa})):(N=D(Vb(d)).contents(),aa.empty(),Aa=E(N,f));if(K.template)if(B=!0,Oa("template",ka,K,aa),ka=K,N=G(K.template)?K.template(aa,e):K.template,N=Tc(N),K.replace){l=K;N=Tb.test(N)?Uc(Xb(K.templateNamespace,U(N))):[];d=N[0];if(1!=N.length||d.nodeType!==oa)throw ja("tplrt",x,"");V(g,aa,d);R={$attr:{}};N=W(d,[],R);var ba=a.splice(M+1,a.length-(M+1));T&&y(N);a=a.concat(N).concat(ba);Rc(e,R);R=a.length}else aa.html(N);if(K.templateUrl)B=!0,Oa("template", -ka,K,aa),ka=K,K.replace&&(l=K),v=S(a.splice(M,a.length-M),aa,e,g,da&&Aa,k,n,{controllerDirectives:C,newIsolateScopeDirective:T,templateDirective:ka,nonTlbTranscludeDirective:fa}),R=a.length;else if(K.compile)try{Q=K.compile(aa,e,Aa),G(Q)?w(null,Q,Pa,gb):Q&&w(Q.pre,Q.post,Pa,gb)}catch(of){c(of,va(aa))}K.terminal&&(v.terminal=!0,A=Math.max(A,K.priority))}v.scope=O&&!0===O.scope;v.transcludeOnThisElement=da;v.elementTranscludeOnThisElement=z;v.templateOnThisElement=B;v.transclude=Aa;r.hasElementTranscludeDirective= -z;return v}function y(a){for(var b=0,c=a.length;b<c;b++)a[b]=Pb(a[b],{$$isolateScope:!0})}function da(b,e,f,g,h,l,k){if(e===h)return null;h=null;if(d.hasOwnProperty(e)){var q;e=a.get(e+"Directive");for(var r=0,p=e.length;r<p;r++)try{q=e[r],(g===t||g>q.priority)&&-1!=q.restrict.indexOf(f)&&(l&&(q=Pb(q,{$$start:l,$$end:k})),b.push(q),h=q)}catch(w){c(w)}}return h}function B(b){if(d.hasOwnProperty(b))for(var c=a.get(b+"Directive"),e=0,f=c.length;e<f;e++)if(b=c[e],b.multiElement)return!0;return!1}function Rc(a, -b){var c=b.$attr,d=a.$attr,e=a.$$element;s(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});s(b,function(b,f){"class"==f?(O(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function S(a,b,c,d,e,f,g,h){var l=[],k,q,n=b[0],p=a.shift(),w=Pb(p,{templateUrl:null,transclude:null,replace:null,$$originalDirective:p}), -P=G(p.templateUrl)?p.templateUrl(b,c):p.templateUrl,u=p.templateNamespace;b.empty();r(L.getTrustedResourceUrl(P)).then(function(r){var L,v;r=Tc(r);if(p.replace){r=Tb.test(r)?Uc(Xb(u,U(r))):[];L=r[0];if(1!=r.length||L.nodeType!==oa)throw ja("tplrt",p.name,P);r={$attr:{}};V(d,b,L);var A=W(L,[],r);I(p.scope)&&y(A);a=A.concat(a);Rc(c,r)}else L=n,b.html(r);a.unshift(w);k=fa(a,L,c,e,b,p,f,g,h);s(d,function(a,c){a==L&&(d[c]=b[0])});for(q=T(b[0].childNodes,e);l.length;){r=l.shift();v=l.shift();var C=l.shift(), -E=l.shift(),A=b[0];if(!r.$$destroyed){if(v!==n){var J=v.className;h.hasElementTranscludeDirective&&p.replace||(A=Vb(L));V(C,D(v),A);O(D(A),J)}v=k.transcludeOnThisElement?X(r,k.transclude,E):E;k(q,r,A,d,v)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(k.transcludeOnThisElement&&(a=X(b,k.transclude,e)),k(q,b,c,d,a)))}}function N(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function Oa(a,b,c,d){if(b)throw ja("multidir", -b.name,c.name,a,va(d));}function M(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&E.$$addBindingClass(a);return function(a,c){var e=c.parent();b||E.$$addBindingClass(e);E.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Xb(a,b){a=Q(a||"html");switch(a){case "svg":case "math":var c=Y.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"== -b)return L.HTML;var c=ua(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return L.RESOURCE_URL}function Pa(a,c,d,e,f){var h=R(a,e);f=g[e]||f;var k=b(d,!0,h,f);if(k){if("multiple"===e&&"select"===ua(a))throw ja("selmulti",va(a));c.push({priority:100,compile:function(){return{pre:function(a,c,g){c=g.$$observers||(g.$$observers={});if(l.test(e))throw ja("nodomevents");var n=g[e];n!==d&&(k=n&&b(n,!0,h,f),d=n);k&&(g[e]=k(a),(c[e]||(c[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope|| -a).$watch(k,function(a,b){"class"===e&&a!=b?g.$updateClass(a,b):g.$set(e,a)}))}}}})}}function V(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var l=a.length;g<l;g++,h++)h<l?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=Y.createDocumentFragment();a.appendChild(d);D(c).data(D(d).data());sa?(Rb=!0,sa.cleanData([d])):delete D.cache[d[D.expando]];d=1;for(e=b.length;d<e;d++)f=b[d],D(f).remove(), -a.appendChild(f),delete b[d];b[0]=c;b.length=1}function Z(a,b){return x(function(){return a.apply(null,arguments)},a,b)}function $(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,va(d))}}var Yb=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a};Yb.prototype={$normalize:ya,$addClass:function(a){a&&0<a.length&&C.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&C.removeClass(this.$$element,a)},$updateClass:function(a, -b){var c=Vc(a,b);c&&c.length&&C.addClass(this.$$element,c);(c=Vc(b,a))&&c.length&&C.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Mc(f,a),h=kf(f,a),f=a;g?(this.$$element.prop(a,b),e=g):h&&(this[h]=b,f=h);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=uc(a,"-"));g=ua(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=A(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",h=U(b),l=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,l=/\s/.test(h)? -l:/(,)/,h=h.split(l),l=Math.floor(h.length/2),k=0;k<l;k++)var q=2*k,g=g+A(U(h[q]),!0),g=g+(" "+U(h[q+1]));h=U(h[2*k]).split(/\s/);g+=A(U(h[0]),!0);2===h.length&&(g+=" "+U(h[1]));this[a]=b=g}!1!==d&&(null===b||b===t?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&s(a[f],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ha()),e=d[a]||(d[a]=[]);e.push(b);v.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])}); -return function(){Xa(e,b)}}};var Aa=b.startSymbol(),ka=b.endSymbol(),Tc="{{"==Aa||"}}"==ka?pa:function(a){return a.replace(/\{\{/g,Aa).replace(/}}/g,ka)},gb=/^ngAttr[A-Z]/;E.$$addBindingInfo=k?function(a,b){var c=a.data("$binding")||[];H(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:z;E.$$addBindingClass=k?function(a){O(a,"ng-binding")}:z;E.$$addScopeInfo=k?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:z;E.$$addScopeClass=k?function(a,b){O(a,b?"ng-isolate-scope": -"ng-scope")}:z;return E}]}function ya(b){return db(b.replace(Sc,""))}function Vc(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function Uc(b){b=D(b);var a=b.length;if(1>=a)return b;for(;a--;)8===b[a].nodeType&&pf.call(b,a,1);return b}function Fe(){var b={},a=!1,c=/^(\S+)(\s+as\s+(\w+))?$/;this.register=function(a,c){Ma(a,"controller");I(a)?x(b,a):b[a]=c};this.allowGlobals=function(){a= -!0};this.$get=["$injector","$window",function(d,e){function f(a,b,c,d){if(!a||!I(a.$scope))throw S("$controller")("noscp",d,b);a.$scope[b]=c}return function(g,h,l,k){var m,n,q;l=!0===l;k&&F(k)&&(q=k);if(F(g)){k=g.match(c);if(!k)throw qf("ctrlfmt",g);n=k[1];q=q||k[3];g=b.hasOwnProperty(n)?b[n]:wc(h.$scope,n,!0)||(a?wc(e,n,!0):t);tb(g,n,!0)}if(l)return l=(H(g)?g[g.length-1]:g).prototype,m=Object.create(l||null),q&&f(h,q,m,n||g.name),x(function(){d.invoke(g,m,h,n);return m},{instance:m,identifier:q}); -m=d.instantiate(g,h,n);q&&f(h,q,m,n||g.name);return m}}]}function Ge(){this.$get=["$window",function(b){return D(b.document)}]}function He(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b,a){if(F(b)){var c=b.replace(rf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(Wc))||(d=(d=c.match(sf))&&tf[d[0]].test(c));d&&(b=pc(c))}}return b}function Xc(b){var a=ha(),c,d,e;if(!b)return a;s(b.split("\n"),function(b){e=b.indexOf(":");c=Q(U(b.substr(0, -e)));d=U(b.substr(e+1));c&&(a[c]=a[c]?a[c]+", "+d:d)});return a}function Yc(b){var a=I(b)?b:t;return function(c){a||(a=Xc(b));return c?(c=a[Q(c)],void 0===c&&(c=null),c):a}}function Zc(b,a,c,d){if(G(d))return d(b,a,c);s(d,function(d){b=d(b,a,c)});return b}function Ke(){var b=this.defaults={transformResponse:[Zb],transformRequest:[function(a){return I(a)&&"[object File]"!==Da.call(a)&&"[object Blob]"!==Da.call(a)&&"[object FormData]"!==Da.call(a)?$a(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"}, -post:ra($b),put:ra($b),patch:ra($b)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},a=!1;this.useApplyAsync=function(b){return y(b)?(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=x({},a);b.data=a.data?Zc(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a){var b,c={};s(a,function(a,d){G(a)?(b= -a(),null!=b&&(c[d]=b)):c[d]=a});return c}if(!ca.isObject(a))throw S("$http")("badreq",a);var e=x({method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse},a);e.headers=function(a){var c=b.headers,e=x({},a.headers),f,g,c=x({},c.common,c[Q(a.method)]);a:for(f in c){a=Q(f);for(g in e)if(Q(g)===a)continue a;e[f]=c[f]}return d(e)}(a);e.method=vb(e.method);var f=[function(a){var d=a.headers,e=Zc(a.data,Yc(d),t,a.transformRequest);B(e)&&s(d,function(a,b){"content-type"===Q(b)&& -delete d[b]});B(a.withCredentials)&&!B(b.withCredentials)&&(a.withCredentials=b.withCredentials);return m(a,e).then(c,c)},t],g=h.when(e);for(s(u,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var l=f.shift(),g=g.then(a,l)}g.success=function(a){g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){g.then(null,function(b){a(b.data,b.status,b.headers,e)}); -return g};return g}function m(c,f){function l(b,c,d,e){function f(){m(c,b,d,e)}O&&(200<=b&&300>b?O.put(X,[b,c,Xc(d),e]):O.remove(X));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function m(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?C.resolve:C.reject)({data:a,status:b,headers:Yc(d),config:c,statusText:e})}function w(a){m(a.data,a.status,ra(a.headers()),a.statusText)}function u(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var C=h.defer(),A=C.promise,O,E,s=c.headers,X=n(c.url, -c.params);k.pendingRequests.push(c);A.then(u,u);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(O=I(c.cache)?c.cache:I(b.cache)?b.cache:q);O&&(E=O.get(X),y(E)?E&&G(E.then)?E.then(w,w):H(E)?m(E[1],E[0],ra(E[2]),E[3]):m(E,200,{},"OK"):O.put(X,A));B(E)&&((E=$c(c.url)?e.cookies()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(s[c.xsrfHeaderName||b.xsrfHeaderName]=E),d(c.method,X,f,l,s,c.timeout,c.withCredentials,c.responseType));return A}function n(a,b){if(!b)return a;var c=[];Ed(b, -function(a,b){null===a||B(a)||(H(a)||(a=[a]),s(a,function(a){I(a)&&(a=qa(a)?a.toISOString():$a(a));c.push(Fa(b)+"="+Fa(a))}))});0<c.length&&(a+=(-1==a.indexOf("?")?"?":"&")+c.join("&"));return a}var q=f("$http"),u=[];s(c,function(a){u.unshift(F(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){s(arguments,function(a){k[a]=function(b,c){return k(x(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){s(arguments,function(a){k[a]=function(b,c,d){return k(x(d||{},{method:a, -url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function uf(){return new M.XMLHttpRequest}function Le(){this.$get=["$browser","$window","$document",function(b,a,c){return vf(b,uf,b.defer,a.angular.callbacks,c[0])}]}function vf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m,!1);f.removeEventListener("error",m,!1);e.body.removeChild(f);f=null;var g=-1,u="unknown";a&&("load"!== -a.type||d[b].called||(a={type:"error"}),u=a.type,g="error"===a.type?404:200);c&&c(g,u)};f.addEventListener("load",m,!1);f.addEventListener("error",m,!1);e.body.appendChild(f);return m}return function(e,h,l,k,m,n,q,u){function r(){v&&v();w&&w.abort()}function P(a,d,e,f,g){C!==t&&c.cancel(C);v=w=null;a(d,e,f,g);b.$$completeOutstandingRequest(z)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==Q(e)){var p="_"+(d.counter++).toString(36);d[p]=function(a){d[p].data=a;d[p].called=!0};var v=f(h.replace("JSON_CALLBACK", -"angular.callbacks."+p),p,function(a,b){P(k,a,d[p].data,"",b);d[p]=z})}else{var w=a();w.open(e,h,!0);s(m,function(a,b){y(a)&&w.setRequestHeader(b,a)});w.onload=function(){var a=w.statusText||"",b="response"in w?w.response:w.responseText,c=1223===w.status?204:w.status;0===c&&(c=b?200:"file"==Ba(h).protocol?404:0);P(k,c,b,w.getAllResponseHeaders(),a)};e=function(){P(k,-1,null,null,"")};w.onerror=e;w.onabort=e;q&&(w.withCredentials=!0);if(u)try{w.responseType=u}catch(L){if("json"!==u)throw L;}w.send(l|| -null)}if(0<n)var C=c(r,n);else n&&G(n.then)&&n.then(r)}}function Ie(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(f,g,u,r){function P(c){return c.replace(k,b).replace(m,a)}function p(a){try{var b=a;a=u?e.getTrusted(u,b):e.valueOf(b);var c;if(r&&!y(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;case "number":a= -""+a;break;default:a=$a(a)}c=a}return c}catch(g){c=ac("interr",f,g.toString()),d(c)}}r=!!r;for(var v,w,L=0,C=[],A=[],O=f.length,E=[],s=[];L<O;)if(-1!=(v=f.indexOf(b,L))&&-1!=(w=f.indexOf(a,v+h)))L!==v&&E.push(P(f.substring(L,v))),L=f.substring(v+h,w),C.push(L),A.push(c(L,p)),L=w+l,s.push(E.length),E.push("");else{L!==O&&E.push(P(f.substring(L)));break}if(u&&1<E.length)throw ac("noconcat",f);if(!g||C.length){var X=function(a){for(var b=0,c=C.length;b<c;b++){if(r&&B(a[b]))return;E[s[b]]=a[b]}return E.join("")}; -return x(function(a){var b=0,c=C.length,e=Array(c);try{for(;b<c;b++)e[b]=A[b](a);return X(e)}catch(g){a=ac("interr",f,g.toString()),d(a)}},{exp:f,expressions:C,$$watchDelegate:function(a,b,c){var d;return a.$watchGroup(A,function(c,e){var f=X(c);G(b)&&b.call(this,f,c!==e?d:f,a);d=f},c)}})}}var h=b.length,l=a.length,k=new RegExp(b.replace(/./g,f),"g"),m=new RegExp(a.replace(/./g,f),"g");g.startSymbol=function(){return b};g.endSymbol=function(){return a};return g}]}function Je(){this.$get=["$rootScope", -"$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var m=a.setInterval,n=a.clearInterval,q=0,u=y(k)&&!k,r=(u?d:c).defer(),P=r.promise;l=y(l)?l:0;P.then(null,null,e);P.$$intervalId=m(function(){r.notify(q++);0<l&&q>=l&&(r.resolve(q),n(P.$$intervalId),delete f[P.$$intervalId]);u||b.$apply()},h);f[P.$$intervalId]=r;return P}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]} -function Rd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "), -DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=rb(b[a]);return b.join("/")}function ad(b,a){var c=Ba(b);a.$$protocol= -c.protocol;a.$$host=c.hostname;a.$$port=ba(c.port)||wf[c.protocol]||null}function bd(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=rc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function za(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ha(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Gb(b){return b.replace(/(#.+)|#$/, -"$1")}function cc(b){return b.substr(0,Ha(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);ad(b,this);this.$$parse=function(a){var b=za(c,a);if(!F(b))throw Hb("ipthprfx",a,c);bd(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+rb(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)), -!0;var f,g;(f=za(b,d))!==t?(g=f,g=(f=za(a,f))!==t?c+(za("/",f)||f):b+g):(f=za(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);ad(b,this);this.$$parse=function(d){d=za(b,d)||za(c,d);var e;"#"===d.charAt(0)?(e=za(a,d),B(e)&&(e=d)):e=this.$$html5?d:"";bd(e,this);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash? -"#"+rb(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ha(b)==Ha(a)?(this.$$parse(a),!0):!1}}function cd(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ha(d)?f=d:(g=za(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash?"#"+rb(this.$$hash): -"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Ib(b){return function(){return this[b]}}function dd(b,a){return function(c){if(B(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Me(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return y(a)?(b=a,this):b};this.html5Mode=function(b){return Wa(b)?(a.enabled=b,this):I(b)?(Wa(b.enabled)&&(a.enabled=b.enabled),Wa(b.requireBase)&&(a.requireBase=b.requireBase),Wa(b.rewriteLinks)&& -(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,m;m=d.baseHref();var n=d.url(),q;if(a.enabled){if(!m&&a.requireBase)throw Hb("nobase");q=n.substring(0,n.indexOf("/",n.indexOf("//")+2))+(m||"/");m=e.history?dc:cd}else q= -Ha(n),m=ec;k=new m(q,"#"+b);k.$$parseLinkUrl(n,n);k.$$state=d.state();var u=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=D(b.target);"a"!==ua(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");I(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);u.test(h)||!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h, -l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Gb(k.absUrl())!=Gb(n)&&d.url(k.absUrl(),!0);var r=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(r=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=Gb(d.url()),b=Gb(k.absUrl()),f=d.state(),g=k.$$replace, -q=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(r||q)r=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(q&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function Ne(){var b=!0,a=this;this.debugEnabled=function(a){return y(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)? -"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||z;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];s(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function ta(b,a){if("__defineGetter__"=== -b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw la("isecfld",a);return b}function ma(b,a){if(b){if(b.constructor===b)throw la("isecfn",a);if(b.window===b)throw la("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw la("isecdom",a);if(b===Object)throw la("isecobj",a);}return b}function fc(b){return b.constant}function hb(b,a,c,d,e){ma(b,e);ma(a,e);c=c.split(".");for(var f,g=0;1<c.length;g++){f=ta(c.shift(),e);var h=0===g&&a&&a[f]|| -b[f];h||(h={},b[f]=h);b=ma(h,e)}f=ta(c.shift(),e);ma(b[f],e);return b[f]=d}function Qa(b){return"constructor"==b}function ed(b,a,c,d,e,f,g){ta(b,f);ta(a,f);ta(c,f);ta(d,f);ta(e,f);var h=function(a){return ma(a,f)},l=g||Qa(b)?h:pa,k=g||Qa(a)?h:pa,m=g||Qa(c)?h:pa,n=g||Qa(d)?h:pa,q=g||Qa(e)?h:pa;return function(f,g){var h=g&&g.hasOwnProperty(b)?g:f;if(null==h)return h;h=l(h[b]);if(!a)return h;if(null==h)return t;h=k(h[a]);if(!c)return h;if(null==h)return t;h=m(h[c]);if(!d)return h;if(null==h)return t; -h=n(h[d]);return e?null==h?t:h=q(h[e]):h}}function xf(b,a){return function(c,d){return b(c,d,ma,a)}}function yf(b,a,c){var d=a.expensiveChecks,e=d?zf:Af,f=e[b];if(f)return f;var g=b.split("."),h=g.length;if(a.csp)f=6>h?ed(g[0],g[1],g[2],g[3],g[4],c,d):function(a,b){var e=0,f;do f=ed(g[e++],g[e++],g[e++],g[e++],g[e++],c,d)(a,b),b=t,a=f;while(e<h);return f};else{var l="";d&&(l+="s = eso(s, fe);\nl = eso(l, fe);\n");var k=d;s(g,function(a,b){ta(a,c);var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+ -"."+a;if(d||Qa(a))e="eso("+e+", fe)",k=!0;l+="if(s == null) return undefined;\ns="+e+";\n"});l+="return s;";a=new Function("s","l","eso","fe",l);a.toString=ea(l);k&&(a=xf(a,c));f=a}f.sharedGetter=!0;f.assign=function(a,c,d){return hb(a,d,b,c,b)};return e[b]=f}function gc(b){return G(b.valueOf)?b.valueOf():Bf.call(b)}function Oe(){var b=ha(),a=ha();this.$get=["$filter","$sniffer",function(c,d){function e(a){var b=a;a.sharedGetter&&(b=function(b,c){return a(b,c)},b.literal=a.literal,b.constant=a.constant, -b.assign=a.assign);return b}function f(a,b){for(var c=0,d=a.length;c<d;c++){var e=a[c];e.constant||(e.inputs?f(e.inputs,b):-1===b.indexOf(e)&&b.push(e))}return b}function g(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=gc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function h(a,b,c,d){var e=d.$$inputs||(d.$$inputs=f(d.inputs,[])),h;if(1===e.length){var l=g,e=e[0];return a.$watch(function(a){var b=e(a);g(b,l)||(h=d(a),l=b&&gc(b));return h},b,c)}for(var k=[],q=0,n=e.length;q<n;q++)k[q]= -g;return a.$watch(function(a){for(var b=!1,c=0,f=e.length;c<f;c++){var l=e[c](a);if(b||(b=!g(l,k[c])))k[c]=l&&gc(l)}b&&(h=d(a));return h},b,c)}function l(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;G(b)&&b.apply(this,arguments);y(a)&&d.$$postDigest(function(){y(f)&&e()})},c)}function k(a,b,c,d){function e(a){var b=!0;s(a,function(a){y(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;G(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&& -f()})},c)}function m(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){G(b)&&b.apply(this,arguments);e()},c)}function n(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==k&&c!==l?function(c,d){var e=a(c,d);return b(e,c,d)}:function(c,d){var e=a(c,d),f=b(e,c,d);return y(e)?f:e};a.$$watchDelegate&&a.$$watchDelegate!==h?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=h,c.inputs=[a]);return c}var q={csp:d.csp,expensiveChecks:!1},u={csp:d.csp,expensiveChecks:!0}; -return function(d,f,g){var v,w,L;switch(typeof d){case "string":L=d=d.trim();var C=g?a:b;v=C[L];v||(":"===d.charAt(0)&&":"===d.charAt(1)&&(w=!0,d=d.substring(2)),g=g?u:q,v=new hc(g),v=(new ib(v,c,g)).parse(d),v.constant?v.$$watchDelegate=m:w?(v=e(v),v.$$watchDelegate=v.literal?k:l):v.inputs&&(v.$$watchDelegate=h),C[L]=v);return n(v,f);case "function":return n(d,f);default:return n(z,f)}}}]}function Qe(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return fd(function(a){b.$evalAsync(a)}, -a)}]}function Re(){this.$get=["$browser","$exceptionHandler",function(b,a){return fd(function(a){b.defer(a)},a)}]}function fd(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&&c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=t;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status]; -try{G(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),a(h)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=S("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending||[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a, -b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(I(b)||G(b))d=b&&b.then;G(d)?(this.promise.$$state.status=-1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status|| -this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(G(b)?b(c):c)}catch(h){a(h)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{G(c)&&(d=c())}catch(e){return l(e,!1)}return d&&G(d.then)? -d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},m=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},n=function u(a){if(!G(a))throw h("norslvr",a);if(!(this instanceof u))return new u(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};n.defer=function(){return new g};n.reject=function(a){var b=new g;b.reject(a);return b.promise};n.when=m;n.all=function(a){var b=new g,c=0,d=H(a)?[]:{};s(a,function(a,e){c++;m(a).then(function(a){d.hasOwnProperty(e)|| -(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return n}function $e(){this.$get=["$window","$timeout",function(b,a){var c=b.requestAnimationFrame||b.webkitRequestAnimationFrame,d=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,e=!!c,f=e?function(a){var b=c(a);return function(){d(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};f.supported=e;return f}]}function Pe(){var b= -10,a=S("$rootScope"),c=null,d=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(e,f,g,h){function l(){this.$id=++ob;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$isolateBindings=null}function k(b){if(r.$$phase)throw a("inprog",r.$$phase);r.$$phase=b}function m(a, -b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function n(){}function q(){for(;v.length;)try{v.shift()()}catch(a){f(a)}d=null}function u(){null===d&&(d=h.defer(function(){r.$apply(q)}))}l.prototype={constructor:l,$new:function(a,b){function c(){d.$$destroyed=!0}var d;b=b||this;a?(d=new l,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=function(){this.$$watchers=this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners= -{};this.$$listenerCount={};this.$id=++ob;this.$$ChildScope=null},this.$$ChildScope.prototype=this),d=new this.$$ChildScope);d.$parent=b;d.$$prevSibling=b.$$childTail;b.$$childHead?(b.$$childTail.$$nextSibling=d,b.$$childTail=d):b.$$childHead=b.$$childTail=d;(a||b!=this)&&d.$on("$destroy",c);return d},$watch:function(a,b,d){var e=g(a);if(e.$$watchDelegate)return e.$$watchDelegate(this,b,d,e);var f=this.$$watchers,h={fn:b,last:n,get:e,exp:a,eq:!!d};c=null;G(b)||(h.fn=z);f||(f=this.$$watchers=[]);f.unshift(h); -return function(){Xa(f,h);c=null}},$watchGroup:function(a,b){function c(){h=!1;l?(l=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,l=!0;if(!a.length){var k=!0;g.$evalAsync(function(){k&&b(e,e,g)});return function(){k=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});s(a,function(a,b){var l=g.$watch(a,function(a,f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(l)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a, -b){function c(a){e=a;var b,d,g,h;if(!B(e)){if(I(e))if(Ta(e))for(f!==q&&(f=q,u=f.length=0,k++),a=e.length,u!==a&&(k++,f.length=u=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(k++,f[b]=g);else{f!==m&&(f=m={},u=0,k++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(k++,f[b]=g)):(u++,f[b]=g,k++));if(u>a)for(b in k++,f)e.hasOwnProperty(b)||(u--,delete f[b])}else f!==e&&(f=e,k++);return k}}c.$stateful=!0;var d=this,e,f,h,l=1<b.length,k=0,n=g(a,c),q=[],m= -{},p=!0,u=0;return this.$watch(n,function(){p?(p=!1,b(e,e,d)):b(e,h,d);if(l)if(I(e))if(Ta(e)){h=Array(e.length);for(var a=0;a<e.length;a++)h[a]=e[a]}else for(a in h={},e)sc.call(e,a)&&(h[a]=e[a]);else h=e})},$digest:function(){var e,g,l,m,u,v,s=b,t,W=[],y,J;k("$digest");h.$$checkUrlChange();this===r&&null!==d&&(h.defer.cancel(d),q());c=null;do{v=!1;for(t=this;P.length;){try{J=P.shift(),J.scope.$eval(J.expression,J.locals)}catch(D){f(D)}c=null}a:do{if(m=t.$$watchers)for(u=m.length;u--;)try{if(e=m[u])if((g= -e.get(t))!==(l=e.last)&&!(e.eq?ga(g,l):"number"===typeof g&&"number"===typeof l&&isNaN(g)&&isNaN(l)))v=!0,c=e,e.last=e.eq?Ea(g,null):g,e.fn(g,l===n?g:l,t),5>s&&(y=4-s,W[y]||(W[y]=[]),W[y].push({msg:G(e.exp)?"fn: "+(e.exp.name||e.exp.toString()):e.exp,newVal:g,oldVal:l}));else if(e===c){v=!1;break a}}catch(B){f(B)}if(!(m=t.$$childHead||t!==this&&t.$$nextSibling))for(;t!==this&&!(m=t.$$nextSibling);)t=t.$parent}while(t=m);if((v||P.length)&&!s--)throw r.$$phase=null,a("infdig",b,W);}while(v||P.length); -for(r.$$phase=null;p.length;)try{p.shift()()}catch(da){f(da)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(this!==r){for(var b in this.$$listenerCount)m(this,this.$$listenerCount[b],b);a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling); -this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=z;this.$on=this.$watch=this.$watchGroup=function(){return z};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){r.$$phase||P.length||h.defer(function(){P.length&&r.$digest()});P.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){p.push(a)},$apply:function(a){try{return k("$apply"), -this.$eval(a)}catch(b){f(b)}finally{r.$$phase=null;try{r.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&v.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,m(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e, -stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},l=Ya([h],arguments,1),k,m;do{d=e.$$listeners[a]||c;h.currentScope=e;k=0;for(m=d.length;k<m;k++)if(d[k])try{d[k].apply(null,l)}catch(n){f(n)}else d.splice(k,1),k--,m--;if(g)return h.currentScope=null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e; -for(var g=Ya([e],arguments,1),h,l;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(l=d.length;h<l;h++)if(d[h])try{d[h].apply(null,g)}catch(k){f(k)}else d.splice(h,1),h--,l--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var r=new l,P=r.$$asyncQueue=[],p=r.$$postDigestQueue=[],v=r.$$applyAsyncQueue=[];return r}]}function Sd(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/; -this.aHrefSanitizationWhitelist=function(a){return y(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Ba(c).href;return""===f||f.match(e)?c:"unsafe:"+f}}}function Cf(b){if("self"===b)return b;if(F(b)){if(-1<b.indexOf("***"))throw Ca("iwcard",b);b=gd(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(pb(b))return new RegExp("^"+b.source+"$");throw Ca("imatcher");}function hd(b){var a= -[];y(b)&&s(b,function(b){a.push(Cf(b))});return a}function Te(){this.SCE_CONTEXTS=na;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=hd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&&(a=hd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?$c(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()}; -b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw Ca("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[na.HTML]=e(g);h[na.CSS]=e(g);h[na.URL]=e(g);h[na.JS]=e(g);h[na.RESOURCE_URL]=e(h[na.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Ca("icontext",a,b);if(null===b||b===t||""===b)return b;if("string"!==typeof b)throw Ca("itype",a);return new c(b)},getTrusted:function(c,e){if(null=== -e||e===t||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(c===na.RESOURCE_URL){var g=Ba(e.toString()),n,q,u=!1;n=0;for(q=b.length;n<q;n++)if(d(b[n],g)){u=!0;break}if(u)for(n=0,q=a.length;n<q;n++)if(d(a[n],g)){u=!1;break}if(u)return e;throw Ca("insecurl",e.toString());}if(c===na.HTML)return f(e);throw Ca("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function Se(){var b=!0;this.enabled=function(a){arguments.length&& -(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&8>Ra)throw Ca("iequirks");var d=ra(na);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=pa);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;s(na,function(a,b){var c=Q(b);d[db("parse_as_"+c)]=function(b){return e(a, -b)};d[db("get_trusted_"+c)]=function(b){return f(a,b)};d[db("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function Ue(){this.$get=["$window","$document",function(b,a){var c={},d=ba((/android (\d+)/.exec(Q((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,m=!1;if(l){for(var n in l)if(k=h.exec(n)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit"); -k=!!("transition"in l||g+"Transition"in l);m=!!("animation"in l||g+"Animation"in l);!d||k&&m||(k=F(f.body.style.webkitTransition),m=F(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=Ra)return!1;if(B(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:bb(),vendorPrefix:g,transitions:k,animations:m,android:d}}]}function We(){this.$get=["$templateCache","$http","$q",function(b,a,c){function d(e,f){d.totalPendingRequests++; -var g=a.defaults&&a.defaults.transformResponse;H(g)?g=g.filter(function(a){return a!==Zb}):g===Zb&&(g=null);return a.get(e,{cache:b,transformResponse:g}).finally(function(){d.totalPendingRequests--}).then(function(a){return a.data},function(a){if(!f)throw ja("tpload",e);return c.reject(a)})}d.totalPendingRequests=0;return d}]}function Xe(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];s(a,function(a){var d= -ca.element(a).data("$binding");d&&s(d,function(d){c?(new RegExp("(^|\\s)"+gd(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function Ye(){this.$get= -["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){var m=y(k)&&!k,n=(m?d:c).defer(),q=n.promise;l=a.defer(function(){try{n.resolve(f())}catch(a){n.reject(a),e(a)}finally{delete g[q.$$timeoutId]}m||b.$apply()},l);q.$$timeoutId=l;g[l]=n;return q}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Ba(b){Ra&&(Z.setAttribute("href",b),b=Z.href); -Z.setAttribute("href",b);return{href:Z.href,protocol:Z.protocol?Z.protocol.replace(/:$/,""):"",host:Z.host,search:Z.search?Z.search.replace(/^\?/,""):"",hash:Z.hash?Z.hash.replace(/^#/,""):"",hostname:Z.hostname,port:Z.port,pathname:"/"===Z.pathname.charAt(0)?Z.pathname:"/"+Z.pathname}}function $c(b){b=F(b)?Ba(b):b;return b.protocol===id.protocol&&b.host===id.host}function Ze(){this.$get=ea(M)}function Ec(b){function a(c,d){if(I(c)){var e={};s(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+ -"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",jd);a("date",kd);a("filter",Df);a("json",Ef);a("limitTo",Ff);a("lowercase",Gf);a("number",ld);a("orderBy",md);a("uppercase",Hf)}function Df(){return function(b,a,c){if(!H(b))return b;var d;switch(typeof a){case "function":break;case "boolean":case "number":case "string":d=!0;case "object":a=If(a,c,d);break;default:return b}return b.filter(a)}}function If(b,a,c){var d=I(b)&&"$"in -b;!0===a?a=ga:G(a)||(a=function(a,b){if(I(a)||I(b))return!1;a=Q(""+a);b=Q(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!I(e)?Ia(e,b.$,a,!1):Ia(e,b,a,c)}}function Ia(b,a,c,d,e){var f=typeof b,g=typeof a;if("string"===g&&"!"===a.charAt(0))return!Ia(b,a.substring(1),c,d);if(H(b))return b.some(function(b){return Ia(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==h.charAt(0)&&Ia(b[h],a,c,!0))return!0;return e?!1:Ia(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!G(e)&& -(f="$"===h,!Ia(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function jd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){B(d)&&(d=a.CURRENCY_SYM);B(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:nd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function ld(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==b?b:nd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function nd(b,a,c,d,e){if(!isFinite(b)||I(b))return"";var f= -0>b;b=Math.abs(b);var g=b+"",h="",l=[],k=!1;if(-1!==g.indexOf("e")){var m=g.match(/([\d\.]+)e(-?)(\d+)/);m&&"-"==m[2]&&m[3]>e+1?b=0:(h=g,k=!0)}if(k)0<e&&1>b&&(h=b.toFixed(e),b=parseFloat(h));else{g=(g.split(od)[1]||"").length;B(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(od),k=g[0],g=g[1]||"",n=0,q=a.lgSize,u=a.gSize;if(k.length>=q+u)for(n=k.length-q,m=0;m<n;m++)0===(n-m)%u&&0!==m&&(h+=c),h+=k.charAt(m);for(m=n;m<k.length;m++)0=== -(k.length-m)%q&&0!==m&&(h+=c),h+=k.charAt(m);for(;g.length<e;)g+="0";e&&"0"!==e&&(h+=d+g.substr(0,e))}0===b&&(f=!1);l.push(f?a.negPre:a.posPre,h,f?a.negSuf:a.posSuf);return l.join("")}function Jb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function $(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=c;0===e&&-12==c&&(e=12);return Jb(e,a,d)}}function Kb(b,a){return function(c,d){var e=c["get"+b](),f=vb(a?"SHORT"+b:b);return d[f][e]}} -function pd(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function qd(b){return function(a){var c=pd(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Jb(a,b)}}function kd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=ba(b[9]+b[10]),g=ba(b[9]+b[11]));h.call(a,ba(b[1]),ba(b[2])-1,ba(b[3]));f=ba(b[4]||0)-f; -g=ba(b[5]||0)-g;h=ba(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;F(c)&&(c=Jf.test(c)?ba(c):a(c));V(c)&&(c=new Date(c));if(!qa(c))return c;for(;e;)(k=Kf.exec(e))?(h=Ya(h,k,1),e=h.pop()):(h.push(e),e=null);f&&"UTC"===f&&(c=new Date(c.getTime()),c.setMinutes(c.getMinutes()+ -c.getTimezoneOffset()));s(h,function(a){l=Lf[a];g+=l?l(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Ef(){return function(b,a){B(a)&&(a=2);return $a(b,a)}}function Ff(){return function(b,a){V(b)&&(b=b.toString());return H(b)||F(b)?(a=Infinity===Math.abs(Number(a))?Number(a):ba(a))?0<a?b.slice(0,a):b.slice(a):F(b)?"":[]:b}}function md(b){return function(a,c,d){function e(a,b){return b?function(b,c){return a(c,b)}:a}function f(a){switch(typeof a){case "number":case "boolean":case "string":return!0; -default:return!1}}function g(a){return null===a?"null":"function"===typeof a.valueOf&&(a=a.valueOf(),f(a))||"function"===typeof a.toString&&(a=a.toString(),f(a))?a:""}function h(a,b){var c=typeof a,d=typeof b;c===d&&"object"===c&&(a=g(a),b=g(b));return c===d?("string"===c&&(a=a.toLowerCase(),b=b.toLowerCase()),a===b?0:a<b?-1:1):c<d?-1:1}if(!Ta(a))return a;c=H(c)?c:[c];0===c.length&&(c=["+"]);c=c.map(function(a){var c=!1,d=a||pa;if(F(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))c="-"==a.charAt(0),a=a.substring(1); -if(""===a)return e(h,c);d=b(a);if(d.constant){var f=d();return e(function(a,b){return h(a[f],b[f])},c)}}return e(function(a,b){return h(d(a),d(b))},c)});return Za.call(a).sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(0!==e)return e}return 0},d))}}function Ja(b){G(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ea(b)}function rd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Lb;f.$error={};f.$$success={};f.$pending=t;f.$name=e(a.name||a.ngForm|| -"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){s(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){s(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ma(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];s(f.$pending,function(b,c){f.$setValidity(c, -null,a)});s(f.$error,function(b,c){f.$setValidity(c,null,a)});s(f.$$success,function(b,c){f.$setValidity(c,null,a)});Xa(g,a)};sd({ctrl:this,$element:b,set:function(a,b,c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(Xa(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Sa);d.addClass(b,Mb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Sa,Mb+" ng-submitted");f.$dirty=!1;f.$pristine= -!0;f.$submitted=!1;s(g,function(a){a.$setPristine()})};f.$setUntouched=function(){s(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b,"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function ic(b){b.$formatters.push(function(a){return b.$isEmpty(a)?a:a.toString()})}function jb(b,a,c,d,e,f){var g=Q(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e= -a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=U(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}};if(e.hasEvent("input"))a.on("input",l);else{var k,m=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",m)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}} -function Nb(b,a){return function(c,d){var e,f;if(qa(c))return c;if(F(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(Mf.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},s(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0, -1E3*f.sss||0)}return NaN}}function kb(b,a,c,d){return function(e,f,g,h,l,k,m){function n(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function q(a){return y(a)?qa(a)?a:c(a):t}td(e,f,g,h);jb(e,f,g,h,l,k);var u=h&&h.$options&&h.$options.timezone,r;h.$$parserName=b;h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,r),"UTC"===u&&b.setMinutes(b.getMinutes()-b.getTimezoneOffset()),b):t});h.$formatters.push(function(a){if(a&&!qa(a))throw Ob("datefmt",a);if(n(a)){if((r=a)&&"UTC"=== -u){var b=6E4*r.getTimezoneOffset();r=new Date(r.getTime()+b)}return m("date")(a,d,u)}r=null;return""});if(y(g.min)||g.ngMin){var s;h.$validators.min=function(a){return!n(a)||B(s)||c(a)>=s};g.$observe("min",function(a){s=q(a);h.$validate()})}if(y(g.max)||g.ngMax){var p;h.$validators.max=function(a){return!n(a)||B(p)||c(a)<=p};g.$observe("max",function(a){p=q(a);h.$validate()})}}}function td(b,a,c,d){(d.$$hasNativeValidators=I(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{}; -return c.badInput&&!c.typeMismatch?t:b})}function ud(b,a,c,d,e){if(y(d)){b=b(d);if(!b.constant)throw S("ngModel")("constexpr",c,d);return b(a)}return e}function jc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],m=0;m<b.length;m++)if(e==b[m])continue a;c.push(e)}return c}function e(a){if(!H(a)){if(F(a))return a.split(" ");if(I(a)){var b=[];s(a,function(a,c){a&&(b=b.concat(c.split(" ")))});return b}}return a}return{restrict:"AC",link:function(f, -g,h){function l(a,b){var c=g.data("$classCounts")||{},d=[];s(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!m){var u=l(k,1);h.$addClass(u)}else if(!ga(b,m)){var r=e(m),u=d(k,r),k=d(r,k),u=l(u,1),k=l(k,-1);u&&u.length&&c.addClass(g,u);k&&k.length&&c.removeClass(g,k)}}m=ra(b)}var m;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index", -function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function sd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function c(b,c){b=b?"-"+uc(b,"-"):"";a(lb+b,!0===c);a(vd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[vd]=!(f[lb]=e.hasClass(lb));d.$setValidity=function(b,e,f){e===t?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&& -h(d.$pending,b,f),wd(d.$pending)&&(d.$pending=t));Wa(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(xd,!0),d.$valid=d.$invalid=t,c("",null)):(a(xd,!1),d.$valid=wd(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?t:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function wd(b){if(b)for(var a in b)return!1;return!0}var Nf=/^\/(.+)\/([a-z]*)$/,Q=function(b){return F(b)?b.toLowerCase(): -b},sc=Object.prototype.hasOwnProperty,vb=function(b){return F(b)?b.toUpperCase():b},Ra,D,sa,Za=[].slice,pf=[].splice,Of=[].push,Da=Object.prototype.toString,Ka=S("ng"),ca=M.angular||(M.angular={}),cb,ob=0;Ra=Y.documentMode;z.$inject=[];pa.$inject=[];var H=Array.isArray,U=function(b){return F(b)?b.trim():b},gd=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},bb=function(){if(y(bb.isActive_))return bb.isActive_;var b=!(!Y.querySelector("[ng-csp]")&&!Y.querySelector("[data-ng-csp]")); -if(!b)try{new Function("")}catch(a){b=!0}return bb.isActive_=b},sb=["ng-","data-ng-","ng:","x-ng-"],Md=/[A-Z]/g,vc=!1,Rb,oa=1,qb=3,Qd={full:"1.3.13",major:1,minor:3,dot:13,codeName:"meticulous-riffleshuffle"};R.expando="ng339";var Ab=R.cache={},hf=1;R._data=function(b){return this.cache[b[this.expando]]||{}};var cf=/([\:\-\_]+(.))/g,df=/^moz([A-Z])/,Pf={mouseleave:"mouseout",mouseenter:"mouseover"},Ub=S("jqLite"),gf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,ef=/<([\w:]+)/,ff=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, -ia={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ia.optgroup=ia.option;ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead;ia.th=ia.td;var La=R.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===Y.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),R(M).on("load",a))}, -toString:function(){var b=[];s(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?D(this[b]):D(this[this.length+b])},length:0,push:Of,sort:[].sort,splice:[].splice},Fb={};s("multiple selected checked disabled readOnly required open".split(" "),function(b){Fb[Q(b)]=b});var Nc={};s("input select option textarea button form details".split(" "),function(b){Nc[b]=!0});var Oc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"}; -s({data:Wb,removeData:yb},function(b,a){R[a]=b});s({data:Wb,inheritedData:Eb,scope:function(b){return D.data(b,"$scope")||Eb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return D.data(b,"$isolateScope")||D.data(b,"$isolateScopeNoTemplate")},controller:Jc,injector:function(b){return Eb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Bb,css:function(b,a,c){a=db(a);if(y(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=Q(a);if(Fb[d])if(y(c))c? -(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||z).specified?d:t;else if(y(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(y(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(B(b)){var d=a.nodeType;return d===oa||d===qb?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(B(a)){if(b.multiple&&"select"===ua(b)){var c=[];s(b.options,function(a){a.selected&& -c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(B(a))return b.innerHTML;xb(b,!0);b.innerHTML=a},empty:Kc},function(b,a){R.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Kc&&(2==b.length&&b!==Bb&&b!==Jc?a:d)===t){if(I(a)){for(e=0;e<g;e++)if(b===Wb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===t?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}}); -s({removeData:yb,on:function a(c,d,e,f){if(y(f))throw Ub("onargs");if(Fc(c)){var g=zb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=lf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"===d?a(c,Pf[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Ic,one:function(a,c,d){a=D(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c, -d)},replaceWith:function(a,c){var d,e=a.parentNode;xb(a);s(new R(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];s(a.childNodes,function(a){a.nodeType===oa&&c.push(a)});return c},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===oa||11===d){c=new R(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===oa){var d=a.firstChild;s(new R(c),function(c){a.insertBefore(c, -d)})}},wrap:function(a,c){c=D(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Lc,detach:function(a){Lc(a,!0)},after:function(a,c){var d=a,e=a.parentNode;c=new R(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h,d.nextSibling);d=h}},addClass:Db,removeClass:Cb,toggleClass:function(a,c,d){c&&s(c.split(" "),function(c){var f=d;B(f)&&(f=!Bb(a,c));(f?Db:Cb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling}, -find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Vb,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=zb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:z,type:g,target:a},c.type&&(e=x(e, -c)),c=ra(h),f=d?[e].concat(d):[e],s(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){R.prototype[c]=function(c,e,f){for(var g,h=0,l=this.length;h<l;h++)B(g)?(g=a(this[h],c,e,f),y(g)&&(g=D(g))):Hc(g,a(this[h],c,e,f));return y(g)?g:this};R.prototype.bind=R.prototype.on;R.prototype.unbind=R.prototype.off});eb.prototype={put:function(a,c){this[Na(a,this.nextUid)]=c},get:function(a){return this[Na(a,this.nextUid)]},remove:function(a){var c=this[a=Na(a,this.nextUid)];delete this[a]; -return c}};var Qc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,Qf=/,/,Rf=/^\s*(_?)(\S+?)\1\s*$/,Pc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ga=S("$injector");ab.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e=[];if(a.length){if(c)throw F(d)&&d||(d=a.name||mf(a)),Ga("strictdi",d);c=a.toString().replace(Pc,"");c=c.match(Qc);s(c[1].split(Qf),function(a){a.replace(Rf,function(a,c,d){e.push(d)})})}a.$inject=e}}else H(a)?(c=a.length-1,tb(a[c],"fn"),e=a.slice(0,c)):tb(a,"fn",!0);return e}; -var Sf=S("$animate"),Ce=["$provide",function(a){this.$$selectors={};this.register=function(c,d){var e=c+"-animation";if(c&&"."!=c.charAt(0))throw Sf("notcsel",c);this.$$selectors[c.substr(1)]=e;a.factory(e,d)};this.classNameFilter=function(a){1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null);return this.$$classNameFilter};this.$get=["$$q","$$asyncCallback","$rootScope",function(a,d,e){function f(d){var f,g=a.defer();g.promise.$$cancelFn=function(){f&&f()};e.$$postDigest(function(){f= -d(function(){g.resolve()})});return g.promise}function g(a,c){var d=[],e=[],f=ha();s((a.attr("class")||"").split(/\s+/),function(a){f[a]=!0});s(c,function(a,c){var g=f[c];!1===a&&g?e.push(c):!0!==a||g||d.push(c)});return 0<d.length+e.length&&[d.length?d:null,e.length?e:null]}function h(a,c,d){for(var e=0,f=c.length;e<f;++e)a[c[e]]=d}function l(){m||(m=a.defer(),d(function(){m.resolve();m=null}));return m.promise}function k(a,c){if(ca.isObject(c)){var d=x(c.from||{},c.to||{});a.css(d)}}var m;return{animate:function(a, -c,d){k(a,{from:c,to:d});return l()},enter:function(a,c,d,e){k(a,e);d?d.after(a):c.prepend(a);return l()},leave:function(a,c){a.remove();return l()},move:function(a,c,d,e){return this.enter(a,c,d,e)},addClass:function(a,c,d){return this.setClass(a,c,[],d)},$$addClassImmediately:function(a,c,d){a=D(a);c=F(c)?c:H(c)?c.join(" "):"";s(a,function(a){Db(a,c)});k(a,d);return l()},removeClass:function(a,c,d){return this.setClass(a,[],c,d)},$$removeClassImmediately:function(a,c,d){a=D(a);c=F(c)?c:H(c)?c.join(" "): -"";s(a,function(a){Cb(a,c)});k(a,d);return l()},setClass:function(a,c,d,e){var k=this,l=!1;a=D(a);var m=a.data("$$animateClasses");m?e&&m.options&&(m.options=ca.extend(m.options||{},e)):(m={classes:{},options:e},l=!0);e=m.classes;c=H(c)?c:c.split(" ");d=H(d)?d:d.split(" ");h(e,c,!0);h(e,d,!1);l&&(m.promise=f(function(c){var d=a.data("$$animateClasses");a.removeData("$$animateClasses");if(d){var e=g(a,d.classes);e&&k.$$setClassImmediately(a,e[0],e[1],d.options)}c()}),a.data("$$animateClasses",m)); -return m.promise},$$setClassImmediately:function(a,c,d,e){c&&this.$$addClassImmediately(a,c);d&&this.$$removeClassImmediately(a,d);k(a,e);return l()},enabled:z,cancel:z}}]}],ja=S("$compile");xc.$inject=["$provide","$$sanitizeUriProvider"];var Sc=/^((?:x|data)[\:\-_])/i,qf=S("$controller"),Wc="application/json",$b={"Content-Type":Wc+";charset=utf-8"},sf=/^\[|^\{(?!\{)/,tf={"[":/]$/,"{":/}$/},rf=/^\)\]\}',?\n/,ac=S("$interpolate"),Tf=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,wf={http:80,https:443,ftp:21},Hb= -S("$location"),Uf={$$html5:!1,$$replace:!1,absUrl:Ib("$$absUrl"),url:function(a){if(B(a))return this.$$url;var c=Tf.exec(a);(c[1]||""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Ib("$$protocol"),host:Ib("$$host"),port:Ib("$$port"),path:dd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(F(a)||V(a))a= -a.toString(),this.$$search=rc(a);else if(I(a))a=Ea(a,{}),s(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Hb("isrcharg");break;default:B(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:dd("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};s([cd,ec,dc],function(a){a.prototype=Object.create(Uf);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==dc||!this.$$html5)throw Hb("nostate"); -this.$$state=B(c)?null:c;return this}});var la=S("$parse"),Vf=Function.prototype.call,Wf=Function.prototype.apply,Xf=Function.prototype.bind,mb=ha();s({"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:function(){}},function(a,c){a.constant=a.literal=a.sharedGetter=!0;mb[c]=a});mb["this"]=function(a){return a};mb["this"].sharedGetter=!0;var nb=x(ha(),{"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return y(d)?y(e)?d+e:d:y(e)?e:t},"-":function(a,c,d,e){d=d(a, -c);e=e(a,c);return(y(d)?d:0)-(y(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"===":function(a,c,d,e){return d(a,c)===e(a,c)},"!==":function(a,c,d,e){return d(a,c)!==e(a,c)},"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a, -c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"!":function(a,c,d){return!d(a,c)},"=":!0,"|":!0}),Yf={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},hc=function(a){this.options=a};hc.prototype={constructor:hc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber(); -else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var c=a+this.peek(),d=c+this.peek(2),e=nb[c],f=nb[d];nb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+ -a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=y(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw la("lexerr",a,c,this.text); -},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=Q(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var e=this.peek();if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a= -this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&!this.isNumber(c))break;this.index++}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+= -4,d+=String.fromCharCode(parseInt(f,16))):d+=Yf[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===a){this.index++;this.tokens.push({index:c,text:e,constant:!0,value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var ib=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d};ib.ZERO=x(function(){return 0},{sharedGetter:!0,constant:!0});ib.prototype={constructor:ib,parse:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.statements();0!==this.tokens.length&&this.throwError("is an unexpected token", -this.tokens[0]);a.literal=!!a.literal;a.constant=!!a.constant;return a},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.peek().identifier&&this.peek().text in mb?a=mb[this.consume().text]:this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var c,d;c=this.expect("(","[",".");)"("===c.text?(a=this.functionCall(a, -d),d=null):"["===c.text?(d=a,a=this.objectIndex(a)):"."===c.text?(d=a,a=this.fieldAccess(a)):this.throwError("IMPOSSIBLE");return a},throwError:function(a,c){throw la("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},peekToken:function(){if(0===this.tokens.length)throw la("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];var g=a.text;if(g===c||g===d||g===e||g=== -f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},consume:function(a){if(0===this.tokens.length)throw la("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},unaryFn:function(a,c){var d=nb[a];return x(function(a,f){return d(a,f,c)},{constant:c.constant,inputs:[c]})},binaryFn:function(a,c,d,e){var f=nb[c];return x(function(c,e){return f(c,e,a,d)},{constant:a.constant&& -d.constant,inputs:!e&&[a,d]})},identifier:function(){for(var a=this.consume().text;this.peek(".")&&this.peekAhead(1).identifier&&!this.peekAhead(2,"(");)a+=this.consume().text+this.consume().text;return yf(a,this.options,this.text)},constant:function(){var a=this.consume().value;return x(function(){return a},{constant:!0,literal:!0})},statements:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.filterChain()),!this.expect(";"))return 1===a.length?a[0]:function(c, -d){for(var e,f=0,g=a.length;f<g;f++)e=a[f](c,d);return e}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},filter:function(a){var c=this.$filter(this.consume().text),d,e;if(this.peek(":"))for(d=[],e=[];this.expect(":");)d.push(this.expression());var f=[a].concat(d||[]);return x(function(f,h){var l=a(f,h);if(e){e[0]=l;for(l=d.length;l--;)e[l+1]=d[l](f,h);return c.apply(t,e)}return c(l)},{constant:!c.$stateful&&f.every(fc),inputs:!c.$stateful&&f})},expression:function(){return this.assignment()}, -assignment:function(){var a=this.ternary(),c,d;return(d=this.expect("="))?(a.assign||this.throwError("implies assignment but ["+this.text.substring(0,d.index)+"] can not be assigned to",d),c=this.ternary(),x(function(d,f){return a.assign(d,c(d,f),f)},{inputs:[a,c]})):a},ternary:function(){var a=this.logicalOR(),c;if(this.expect("?")&&(c=this.assignment(),this.consume(":"))){var d=this.assignment();return x(function(e,f){return a(e,f)?c(e,f):d(e,f)},{constant:a.constant&&c.constant&&d.constant})}return a}, -logicalOR:function(){for(var a=this.logicalAND(),c;c=this.expect("||");)a=this.binaryFn(a,c.text,this.logicalAND(),!0);return a},logicalAND:function(){for(var a=this.equality(),c;c=this.expect("&&");)a=this.binaryFn(a,c.text,this.equality(),!0);return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a=this.binaryFn(a,c.text,this.relational());return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a=this.binaryFn(a,c.text, -this.additive());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.text,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.text,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(ib.ZERO,a.text,this.unary()):(a=this.expect("!"))?this.unaryFn(a.text,this.unary()):this.primary()},fieldAccess:function(a){var c= -this.identifier();return x(function(d,e,f){d=f||a(d,e);return null==d?t:c(d)},{assign:function(d,e,f){var g=a(d,f);g||a.assign(d,g={},f);return c.assign(g,e)}})},objectIndex:function(a){var c=this.text,d=this.expression();this.consume("]");return x(function(e,f){var g=a(e,f),h=d(e,f);ta(h,c);return g?ma(g[h],c):t},{assign:function(e,f,g){var h=ta(d(e,g),c),l=ma(a(e,g),c);l||a.assign(e,l={},g);return l[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression()); -while(this.expect(","))}this.consume(")");var e=this.text,f=d.length?[]:null;return function(g,h){var l=c?c(g,h):y(c)?t:g,k=a(g,h,l)||z;if(f)for(var m=d.length;m--;)f[m]=ma(d[m](g,h),e);ma(l,e);if(k){if(k.constructor===k)throw la("isecfn",e);if(k===Vf||k===Wf||k===Xf)throw la("isecff",e);}l=k.apply?k.apply(l,f):k(f[0],f[1],f[2],f[3],f[4]);f&&(f.length=0);return ma(l,e)}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(",")) -}this.consume("]");return x(function(c,d){for(var e=[],f=0,g=a.length;f<g;f++)e.push(a[f](c,d));return e},{literal:!0,constant:a.every(fc),inputs:a})},object:function(){var a=[],c=[];if("}"!==this.peekToken().text){do{if(this.peek("}"))break;var d=this.consume();d.constant?a.push(d.value):d.identifier?a.push(d.text):this.throwError("invalid key",d);this.consume(":");c.push(this.expression())}while(this.expect(","))}this.consume("}");return x(function(d,f){for(var g={},h=0,l=c.length;h<l;h++)g[a[h]]= -c[h](d,f);return g},{literal:!0,constant:c.every(fc),inputs:c})}};var Af=ha(),zf=ha(),Bf=Object.prototype.valueOf,Ca=S("$sce"),na={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ja=S("$compile"),Z=Y.createElement("a"),id=Ba(M.location.href);Ec.$inject=["$provide"];jd.$inject=["$locale"];ld.$inject=["$locale"];var od=".",Lf={yyyy:$("FullYear",4),yy:$("FullYear",2,0,!0),y:$("FullYear",1),MMMM:Kb("Month"),MMM:Kb("Month",!0),MM:$("Month",2,1),M:$("Month",1,1),dd:$("Date",2),d:$("Date", -1),HH:$("Hours",2),H:$("Hours",1),hh:$("Hours",2,-12),h:$("Hours",1,-12),mm:$("Minutes",2),m:$("Minutes",1),ss:$("Seconds",2),s:$("Seconds",1),sss:$("Milliseconds",3),EEEE:Kb("Day"),EEE:Kb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Jb(Math[0<a?"floor":"ceil"](a/60),2)+Jb(Math.abs(a%60),2))},ww:qd(2),w:qd(1)},Kf=/((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,Jf=/^\-?\d+$/; -kd.$inject=["$locale"];var Gf=ea(Q),Hf=ea(vb);md.$inject=["$parse"];var Td=ea({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===Da.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),wb={};s(Fb,function(a,c){if("multiple"!=a){var d=ya("ng-"+c);wb[d]=function(){return{restrict:"A",priority:100,link:function(a,f,g){a.$watch(g[d],function(a){g.$set(c, -!!a)})}}}}});s(Oc,function(a,c){wb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(Nf))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});s(["src","srcset","href"],function(a){var c=ya("ng-"+a);wb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===Da.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",g=null);f.$observe(c, -function(c){c?(f.$set(h,c),Ra&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Lb={$addControl:z,$$renameControl:function(a,c){a.$name=c},$removeControl:z,$setValidity:z,$setDirty:z,$setPristine:z,$setSubmitted:z};rd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var yd=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:rd,compile:function(a){a.addClass(Sa).addClass(lb);return{pre:function(a,d,g,h){if(!("action"in g)){var l=function(c){a.$apply(function(){h.$commitViewValue(); -h.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",l,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",l,!1)},0,!1)})}var k=h.$$parentForm,m=h.$name;m&&(hb(a,null,m,h,m),g.$observe(g.name?"name":"ngForm",function(c){m!==c&&(hb(a,null,m,t,m),m=c,hb(a,null,m,h,m),k.$$renameControl(h,m))}));d.on("$destroy",function(){k.$removeControl(h);m&&hb(a,null,m,t,m);x(h,Lb)})}}}}}]},Ud=yd(),ge=yd(!0),Mf=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/, -Zf=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,$f=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,ag=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,zd=/^(\d{4})-(\d{2})-(\d{2})$/,Ad=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,kc=/^(\d{4})-W(\d\d)$/,Bd=/^(\d{4})-(\d\d)$/,Cd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Dd={text:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);ic(e)},date:kb("date",zd,Nb(zd,["yyyy", -"MM","dd"]),"yyyy-MM-dd"),"datetime-local":kb("datetimelocal",Ad,Nb(Ad,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:kb("time",Cd,Nb(Cd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:kb("week",kc,function(a,c){if(qa(a))return a;if(F(a)){kc.lastIndex=0;var d=kc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=pd(e),f=7*(f-1);c&&(d=c.getHours(),g=c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:kb("month", -Bd,Nb(Bd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){td(a,c,d,e);jb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:ag.test(a)?parseFloat(a):t});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Ob("numfmt",a);a=a.toString()}return a});if(d.min||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||B(h)||a>=h};d.$observe("min",function(a){y(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(d.max|| -d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||B(l)||a<=l};d.$observe("max",function(a){y(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);ic(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||Zf.test(d)}},email:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);ic(e);e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||$f.test(d)}},radio:function(a,c, -d,e){B(d.name)&&c.attr("name",++ob);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=ud(l,a,"ngTrueValue",d.ngTrueValue,!0),m=ud(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ga(a, -k)});e.$parsers.push(function(a){return a?k:m})},hidden:z,button:z,submit:z,reset:z,file:z},yc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Dd[Q(h.type)]||Dd.text)(f,g,h,l[0],c,a,d,e)}}}}],bg=/^(true|false|\d+)$/,ye=function(){return{restrict:"A",priority:100,compile:function(a,c){return bg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value", -a)})}}}},Zd=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],ae=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===t?"":a})}}}}],$d=["$sce", -"$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],xe=ea({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),be=jc("",!0),de=jc("Odd",0),ce=jc("Even",1),ee=Ja({compile:function(a,c){c.$set("ngCloak", -t);a.removeClass("ng-cloak")}}),fe=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Dc={},cg={blur:!0,focus:!0};s("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ya("ng-"+a);Dc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})}; -cg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ie=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=Y.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=ub(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],je=["$templateRequest","$anchorScroll", -"$animate","$sce",function(a,c,d,e){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(f,g){var h=g.ngInclude||g.src,l=g.onload||"",k=g.autoscroll;return function(f,g,q,s,r){var t=0,p,v,w,L=function(){v&&(v.remove(),v=null);p&&(p.$destroy(),p=null);w&&(d.leave(w).then(function(){v=null}),v=w,w=null)};f.$watch(e.parseAsResourceUrl(h),function(e){var h=function(){!y(k)||k&&!f.$eval(k)||c()},q=++t;e?(a(e,!0).then(function(a){if(q===t){var c=f.$new(); -s.template=a;a=r(c,function(a){L();d.enter(a,null,g).then(h)});p=c;w=a;p.$emit("$includeContentLoaded",e);f.$eval(l)}},function(){q===t&&(L(),f.$emit("$includeContentError",e))}),f.$emit("$includeContentRequested",e)):(L(),s.template=null)})}}}}],Ae=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Gc(f.template,Y).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}], -ke=Ja({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),we=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?U(f):f;e.$parsers.push(function(a){if(!B(a)){var c=[];a&&s(a.split(h),function(a){a&&c.push(g?U(a):a)});return c}});e.$formatters.push(function(a){return H(a)?a.join(f):t});e.$isEmpty=function(a){return!a||!a.length}}}},lb="ng-valid",vd="ng-invalid",Sa="ng-pristine", -Mb="ng-dirty",xd="ng-pending",Ob=new S("ngModel"),dg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,m){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success= -{};this.$pending=t;this.$name=m(d.name||"",!1)(a);var n=f(d.ngModel),q=n.assign,u=n,r=q,P=null,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");u=function(a){var d=n(a);G(d)&&(d=c(a));return d};r=function(a,c){G(n(a))?g(a,{$$$p:p.$modelValue}):q(a,p.$modelValue)}}else if(!n.assign)throw Ob("nonassign",d.ngModel,va(e));};this.$render=z;this.$isEmpty=function(a){return B(a)||""===a||null===a||a!==a};var v=e.inheritedData("$formController")|| -Lb,w=0;sd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:v,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Mb);g.addClass(e,Sa)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Sa);g.addClass(e,Mb);v.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched", -"ng-untouched")};this.$rollbackViewValue=function(){h.cancel(P);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(p.$error[p.$$parserName||"parse"]?!1:t,a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:t,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators=function(a,c,d,e){function f(){var a= -!0;s(p.$validators,function(e,f){var g=e(c,d);a=a&&g;h(f,g)});return a?!0:(s(p.$asyncValidators,function(a,c){h(c,null)}),!1)}function g(){var a=[],e=!0;s(p.$asyncValidators,function(f,g){var l=f(c,d);if(!l||!G(l.then))throw Ob("$asyncValidators",l);h(g,t);a.push(l.then(function(){h(g,!0)},function(a){e=!1;h(g,!1)}))});a.length?k.all(a).then(function(){l(e)},z):l(!0)}function h(a,c){m===w&&p.$setValidity(a,c)}function l(a){m===w&&e(a)}w++;var m=w;(function(a){var c=p.$$parserName||"parse";if(a=== -t)h(c,null);else if(h(c,a),!a)return s(p.$validators,function(a,c){h(c,null)}),s(p.$asyncValidators,function(a,c){h(c,null)}),!1;return!0})(a)?f()?g():l(!1):l(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(P);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue,d=B(c)?t:!0;if(d)for(var e=0;e<p.$parsers.length;e++)if(c= -p.$parsers[e](c),B(c)){d=!1;break}V(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=u(a));var f=p.$modelValue,g=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=c;g&&(p.$modelValue=c,p.$modelValue!==f&&p.$$writeModelToScope());p.$$runValidators(d,c,p.$$lastCommittedViewValue,function(a){g||(p.$modelValue=a?c:t,p.$modelValue!==f&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){r(a,p.$modelValue);s(p.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};this.$setViewValue= -function(a,c){p.$viewValue=a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=p.$options;e&&y(e.debounce)&&(e=e.debounce,V(e)?d=e:V(e[c])?d=e[c]:V(e["default"])&&(d=e["default"]));h.cancel(P);d?P=h(function(){p.$commitViewValue()},d):l.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var c=u(a);if(c!==p.$modelValue){p.$modelValue=p.$$rawModelValue=c;for(var d=p.$formatters,e=d.length, -f=c;e--;)f=d[e](f);p.$viewValue!==f&&(p.$viewValue=p.$$lastCommittedViewValue=f,p.$render(),p.$$runValidators(t,c,f,z))}return c})}],ve=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:dg,priority:1,compile:function(c){c.addClass(Sa).addClass("ng-untouched").addClass(lb);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Lb;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name",function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy", -function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],eg=/(\s+|^)default(\s+|$)/,ze=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=a.$eval(c.ngModelOptions);this.$options.updateOn!==t?(this.$options.updateOnDefault= -!1,this.$options.updateOn=U(this.$options.updateOn.replace(eg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},le=Ja({terminal:!0,priority:1E3}),me=["$locale","$interpolate",function(a,c){var d=/{}/g,e=/^when(Minus)?(.+)$/;return{restrict:"EA",link:function(f,g,h){function l(a){g.text(a||"")}var k=h.count,m=h.$attr.when&&g.attr(h.$attr.when),n=h.offset||0,q=f.$eval(m)||{},u={},m=c.startSymbol(),r=c.endSymbol(),t=m+k+"-"+n+r,p=ca.noop,v;s(h,function(a,c){var d= -e.exec(c);d&&(d=(d[1]?"-":"")+Q(d[2]),q[d]=g.attr(h.$attr[c]))});s(q,function(a,e){u[e]=c(a.replace(d,t))});f.$watch(k,function(c){c=parseFloat(c);var d=isNaN(c);d||c in q||(c=a.pluralCat(c-n));c===v||d&&isNaN(v)||(p(),p=f.$watch(u[c],l),v=c)})}}}],ne=["$parse","$animate",function(a,c){var d=S("ngRepeat"),e=function(a,c,d,e,k,m,n){a[d]=e;k&&(a[k]=m);a.$index=c;a.$first=0===c;a.$last=c===n-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element", -priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=Y.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var m=k[1],n=k[2],q=k[3],u=k[4],k=m.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!k)throw d("iidexp",m);var r=k[3]||k[1],y=k[2];if(q&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(q)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(q)))throw d("badident", -q);var p,v,w,B,z={$id:Na};u?p=a(u):(w=function(a,c){return Na(c)},B=function(a){return a});return function(a,f,g,k,m){p&&(v=function(c,d,e){y&&(z[y]=c);z[r]=d;z.$index=e;return p(a,z)});var u=ha();a.$watchCollection(n,function(g){var k,p,n=f[0],E,z=ha(),x,T,N,G,H,C,I;q&&(a[q]=g);if(Ta(g))H=g,p=v||w;else{p=v||B;H=[];for(I in g)g.hasOwnProperty(I)&&"$"!=I.charAt(0)&&H.push(I);H.sort()}x=H.length;I=Array(x);for(k=0;k<x;k++)if(T=g===H?k:H[k],N=g[T],G=p(T,N,k),u[G])C=u[G],delete u[G],z[G]=C,I[k]=C;else{if(z[G])throw s(I, -function(a){a&&a.scope&&(u[a.id]=a)}),d("dupes",h,G,N);I[k]={id:G,scope:t,clone:t};z[G]=!0}for(E in u){C=u[E];G=ub(C.clone);c.leave(G);if(G[0].parentNode)for(k=0,p=G.length;k<p;k++)G[k].$$NG_REMOVED=!0;C.scope.$destroy()}for(k=0;k<x;k++)if(T=g===H?k:H[k],N=g[T],C=I[k],C.scope){E=n;do E=E.nextSibling;while(E&&E.$$NG_REMOVED);C.clone[0]!=E&&c.move(ub(C.clone),null,D(n));n=C.clone[C.clone.length-1];e(C.scope,k,r,N,y,T,x)}else m(function(a,d){C.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a, -null,D(n));n=f;C.clone=a;z[C.id]=C;e(C.scope,k,r,N,y,T,x)});u=z})}}}}],oe=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],he=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],pe=Ja(function(a,c,d){a.$watchCollection(d.ngStyle, -function(a,d){d&&a!==d&&s(d,function(a,d){c.css(d,"")});a&&c.css(a)})}),qe=["$animate",function(a){return{restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],m=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch||e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=0;for(e=k.length;d<e;++d){var r=ub(h[d].clone);k[d].$destroy();(l[d]=a.leave(r)).then(m(l,d))}h.length=0;k.length=0;(g= -f.cases["!"+c]||f.cases["?"])&&s(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=Y.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],re=Ja({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,element:c})}}),se=Ja({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0, -link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),ue=Ja({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw S("ngTransclude")("orphan",va(c));f(function(a){c.empty();c.append(a)})}}),Vd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],fg=S("ngOptions"),te=ea({restrict:"A",terminal:!0}),Wd=["$compile","$parse",function(a,c){var d=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/, -e={$setViewValue:z};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope","$attrs",function(a,c,d){var l=this,k={},m=e,n;l.databound=d.ngModel;l.init=function(a,c,d){m=a;n=d};l.addOption=function(c,d){Ma(c,'"option value"');k[c]=!0;m.$viewValue==c&&(a.val(c),n.parent()&&n.remove());d&&d[0].hasAttribute("selected")&&(d[0].selected=!0)};l.removeOption=function(a){this.hasOption(a)&&(delete k[a],m.$viewValue===a&&this.renderUnknownOption(a))};l.renderUnknownOption=function(c){c= -"? "+Na(c)+" ?";n.val(c);a.prepend(n);a.val(c);n.prop("selected",!0)};l.hasOption=function(a){return k.hasOwnProperty(a)};c.$on("$destroy",function(){l.renderUnknownOption=z})}],link:function(e,g,h,l){function k(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(C.parent()&&C.remove(),c.val(a),""===a&&p.prop("selected",!0)):B(a)&&p?c.val(""):e.renderUnknownOption(a)};c.on("change",function(){a.$apply(function(){C.parent()&&C.remove();d.$setViewValue(c.val())})})}function m(a,c,d){var e; -d.$render=function(){var a=new eb(d.$viewValue);s(c.find("option"),function(c){c.selected=y(a.get(c.value))})};a.$watch(function(){ga(e,d.$viewValue)||(e=ra(d.$viewValue),d.$render())});c.on("change",function(){a.$apply(function(){var a=[];s(c.find("option"),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function n(e,f,g){function h(a,c,d){S[x]=d;D&&(S[D]=c);return a(e,S)}function k(a){var c;if(u)if(M&&H(a)){c=new eb([]);for(var d=0;d<a.length;d++)c.put(h(M,null,a[d]),!0)}else c= -new eb(a);else M&&(a=h(M,null,a));return function(d,e){var f;f=M?M:B?B:F;return u?y(c.remove(h(f,d,e))):a===h(f,d,e)}}function l(){v||(e.$$postDigest(p),v=!0)}function m(a,c,d){a[c]=a[c]||0;a[c]+=d?1:-1}function p(){v=!1;var a={"":[]},c=[""],d,l,n,r,t;n=g.$viewValue;r=O(e)||[];var B=D?Object.keys(r).sort():r,x,A,H,F,N={};t=k(n);var J=!1,U,V;Q={};for(F=0;H=B.length,F<H;F++){x=F;if(D&&(x=B[F],"$"===x.charAt(0)))continue;A=r[x];d=h(I,x,A)||"";(l=a[d])||(l=a[d]=[],c.push(d));d=t(x,A);J=J||d;A=h(C,x,A); -A=y(A)?A:"";V=M?M(e,S):D?B[F]:F;M&&(Q[V]=x);l.push({id:V,label:A,selected:d})}u||(z||null===n?a[""].unshift({id:"",label:"",selected:!J}):J||a[""].unshift({id:"?",label:"",selected:!0}));x=0;for(B=c.length;x<B;x++){d=c[x];l=a[d];R.length<=x?(n={element:G.clone().attr("label",d),label:l.label},r=[n],R.push(r),f.append(n.element)):(r=R[x],n=r[0],n.label!=d&&n.element.attr("label",n.label=d));J=null;F=0;for(H=l.length;F<H;F++)d=l[F],(t=r[F+1])?(J=t.element,t.label!==d.label&&(m(N,t.label,!1),m(N,d.label, -!0),J.text(t.label=d.label),J.prop("label",t.label)),t.id!==d.id&&J.val(t.id=d.id),J[0].selected!==d.selected&&(J.prop("selected",t.selected=d.selected),Ra&&J.prop("selected",t.selected))):(""===d.id&&z?U=z:(U=w.clone()).val(d.id).prop("selected",d.selected).attr("selected",d.selected).prop("label",d.label).text(d.label),r.push(t={element:U,label:d.label,id:d.id,selected:d.selected}),m(N,d.label,!0),J?J.after(U):n.element.append(U),J=U);for(F++;r.length>F;)d=r.pop(),m(N,d.label,!1),d.element.remove()}for(;R.length> -x;){l=R.pop();for(F=1;F<l.length;++F)m(N,l[F].label,!1);l[0].element.remove()}s(N,function(a,c){0<a?q.addOption(c):0>a&&q.removeOption(c)})}var n;if(!(n=r.match(d)))throw fg("iexp",r,va(f));var C=c(n[2]||n[1]),x=n[4]||n[6],A=/ as /.test(n[0])&&n[1],B=A?c(A):null,D=n[5],I=c(n[3]||""),F=c(n[2]?n[1]:x),O=c(n[7]),M=n[8]?c(n[8]):null,Q={},R=[[{element:f,label:""}]],S={};z&&(a(z)(e),z.removeClass("ng-scope"),z.remove());f.empty();f.on("change",function(){e.$apply(function(){var a=O(e)||[],c;if(u)c=[],s(f.val(), -function(d){d=M?Q[d]:d;c.push("?"===d?t:""===d?null:h(B?B:F,d,a[d]))});else{var d=M?Q[f.val()]:f.val();c="?"===d?t:""===d?null:h(B?B:F,d,a[d])}g.$setViewValue(c);p()})});g.$render=p;e.$watchCollection(O,l);e.$watchCollection(function(){var a=O(e),c;if(a&&H(a)){c=Array(a.length);for(var d=0,f=a.length;d<f;d++)c[d]=h(C,d,a[d])}else if(a)for(d in c={},a)a.hasOwnProperty(d)&&(c[d]=h(C,d,a[d]));return c},l);u&&e.$watchCollection(function(){return g.$modelValue},l)}if(l[1]){var q=l[0];l=l[1];var u=h.multiple, -r=h.ngOptions,z=!1,p,v=!1,w=D(Y.createElement("option")),G=D(Y.createElement("optgroup")),C=w.clone();h=0;for(var A=g.children(),x=A.length;h<x;h++)if(""===A[h].value){p=z=A.eq(h);break}q.init(l,z,C);u&&(l.$isEmpty=function(a){return!a||0===a.length});r?n(e,g,l):u?m(e,g,l):k(e,g,l,q)}}}}],Yd=["$interpolate",function(a){var c={addOption:z,removeOption:z};return{restrict:"E",priority:100,compile:function(d,e){if(B(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k= -d.parent(),m=k.data("$selectController")||k.parent().data("$selectController");m&&m.databound||(m=c);f?a.$watch(f,function(a,c){e.$set("value",a);c!==a&&m.removeOption(c);m.addOption(a,d)}):m.addOption(e.value,d);d.on("$destroy",function(){m.removeOption(e.value)})}}}}],Xd=ea({restrict:"E",terminal:!1}),Ac=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}}, -zc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){F(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw S("ngPattern")("noregexp",g,a,va(c));f=a||t;e.$validate()});e.$validators.pattern=function(a){return e.$isEmpty(a)||B(f)||f.test(a)}}}}},Cc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=ba(a);f=isNaN(a)?-1:a;e.$validate()}); -e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Bc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=ba(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};M.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(Nd(),Pd(ca),D(Y).ready(function(){Jd(Y,tc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document).find("head").prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>'); +(function(O,U,t){'use strict';function J(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.3/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ea(b){if(null==b||Wa(b))return!1;var a="length"in Object(b)&&b.length; +return b.nodeType===qa&&a?!0:L(b)||G(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function m(b,a,c){var d,e;if(b)if(z(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(G(b)||Ea(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==m)b.forEach(a,c,b);else if(nc(b))for(d in b)a.call(c,b[d],d,b);else if("function"===typeof b.hasOwnProperty)for(d in b)b.hasOwnProperty(d)&& +a.call(c,b[d],d,b);else for(d in b)Xa.call(b,d)&&a.call(c,b[d],d,b);return b}function oc(b,a,c){for(var d=Object.keys(b).sort(),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function pc(b){return function(a,c){b(c,a)}}function Ud(){return++nb}function qc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function Nb(b,a,c){for(var d=b.$$hashKey,e=0,f=a.length;e<f;++e){var g=a[e];if(H(g)||z(g))for(var h=Object.keys(g),l=0,k=h.length;l<k;l++){var n=h[l],r=g[n];c&&H(r)?aa(r)?b[n]=new Date(r.valueOf()):(H(b[n])|| +(b[n]=G(r)?[]:{}),Nb(b[n],[r],!0)):b[n]=r}}qc(b,d);return b}function P(b){return Nb(b,za.call(arguments,1),!1)}function Vd(b){return Nb(b,za.call(arguments,1),!0)}function W(b){return parseInt(b,10)}function Ob(b,a){return P(Object.create(b),a)}function v(){}function Ya(b){return b}function ra(b){return function(){return b}}function rc(b){return z(b.toString)&&b.toString!==Object.prototype.toString}function A(b){return"undefined"===typeof b}function w(b){return"undefined"!==typeof b}function H(b){return null!== +b&&"object"===typeof b}function nc(b){return null!==b&&"object"===typeof b&&!sc(b)}function L(b){return"string"===typeof b}function V(b){return"number"===typeof b}function aa(b){return"[object Date]"===sa.call(b)}function z(b){return"function"===typeof b}function Za(b){return"[object RegExp]"===sa.call(b)}function Wa(b){return b&&b.window===b}function $a(b){return b&&b.$evalAsync&&b.$watch}function ab(b){return"boolean"===typeof b}function tc(b){return!(!b||!(b.nodeName||b.prop&&b.attr&&b.find))} +function Wd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function ta(b){return M(b.nodeName||b[0]&&b[0].nodeName)}function bb(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return c}function fa(b,a,c,d){if(Wa(b)||$a(b))throw Fa("cpws");if(uc.test(sa.call(a)))throw Fa("cpta");if(a){if(b===a)throw Fa("cpi");c=c||[];d=d||[];H(b)&&(c.push(b),d.push(a));var e;if(G(b))for(e=a.length=0;e<b.length;e++)a.push(fa(b[e],null,c,d));else{var f=a.$$hashKey;G(a)?a.length=0:m(a,function(b, +c){delete a[c]});if(nc(b))for(e in b)a[e]=fa(b[e],null,c,d);else if(b&&"function"===typeof b.hasOwnProperty)for(e in b)b.hasOwnProperty(e)&&(a[e]=fa(b[e],null,c,d));else for(e in b)Xa.call(b,e)&&(a[e]=fa(b[e],null,c,d));qc(a,f)}}else if(a=b,H(b)){if(c&&-1!==(f=c.indexOf(b)))return d[f];if(G(b))return fa(b,[],c,d);if(uc.test(sa.call(b)))a=new b.constructor(b);else if(aa(b))a=new Date(b.getTime());else if(Za(b))a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex;else return e= +Object.create(sc(b)),fa(b,e,c,d);d&&(c.push(b),d.push(a))}return a}function ia(b,a){if(G(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(H(b))for(c in a=a||{},b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ka(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(G(b)){if(!G(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ka(b[d],a[d]))return!1;return!0}}else{if(aa(b))return aa(a)? +ka(b.getTime(),a.getTime()):!1;if(Za(b))return Za(a)?b.toString()==a.toString():!1;if($a(b)||$a(a)||Wa(b)||Wa(a)||G(a)||aa(a)||Za(a))return!1;c=ga();for(d in b)if("$"!==d.charAt(0)&&!z(b[d])){if(!ka(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!(d in c||"$"===d.charAt(0)||a[d]===t||z(a[d])))return!1;return!0}return!1}function cb(b,a,c){return b.concat(za.call(a,c))}function vc(b,a){var c=2<arguments.length?za.call(arguments,2):[];return!z(a)||a instanceof RegExp?a:c.length?function(){return arguments.length? +a.apply(b,cb(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Xd(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)&&"$"===b.charAt(1)?c=t:Wa(a)?c="$WINDOW":a&&U===a?c="$DOCUMENT":$a(a)&&(c="$SCOPE");return c}function db(b,a){if("undefined"===typeof b)return t;V(a)||(a=a?2:null);return JSON.stringify(b,Xd,a)}function wc(b){return L(b)?JSON.parse(b):b}function xc(b,a){var c=Date.parse("Jan 01, 1970 00:00:00 "+b)/6E4;return isNaN(c)?a:c}function Pb(b, +a,c){c=c?-1:1;var d=xc(a,b.getTimezoneOffset());a=b;b=c*(d-b.getTimezoneOffset());a=new Date(a.getTime());a.setMinutes(a.getMinutes()+b);return a}function ua(b){b=y(b).clone();try{b.empty()}catch(a){}var c=y("<div>").append(b).html();try{return b[0].nodeType===Na?M(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+M(b)})}catch(d){return M(c)}}function yc(b){try{return decodeURIComponent(b)}catch(a){}}function zc(b){var a={},c,d;m((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g, +"%20").split("="),d=yc(c[0]),w(d)&&(b=w(c[1])?yc(c[1]):!0,Xa.call(a,d)?G(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];m(b,function(b,d){G(b)?m(b,function(b){a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))}):a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))});return a.length?a.join("&"):""}function ob(b){return ma(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ma(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g, +"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Yd(b,a){var c,d,e=Oa.length;for(d=0;d<e;++d)if(c=Oa[d]+a,L(c=b.getAttribute(c)))return c;return null}function Zd(b,a){var c,d,e={};m(Oa,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});m(Oa,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Yd(c,"strict-di"),a(c,d?[d]:[],e))}function Ac(b,a,c){H(c)|| +(c={});c=P({strictDi:!1},c);var d=function(){b=y(b);if(b.injector()){var d=b[0]===U?"document":ua(b);throw Fa("btstrpd",d.replace(/</,"<").replace(/>/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=eb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e= +/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;O&&e.test(O.name)&&(c.debugInfoEnabled=!0,O.name=O.name.replace(e,""));if(O&&!f.test(O.name))return d();O.name=O.name.replace(f,"");ca.resumeBootstrap=function(b){m(b,function(b){a.push(b)});return d()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function $d(){O.name="NG_ENABLE_DEBUG_INFO!"+O.name;O.location.reload()}function ae(b){b=ca.element(b).injector();if(!b)throw Fa("test");return b.get("$$testability")}function Bc(b,a){a=a|| +"_";return b.replace(be,function(b,d){return(d?a:"")+b.toLowerCase()})}function ce(){var b;if(!Cc){var a=pb();la=O.jQuery;w(a)&&(la=null===a?t:O[a]);la&&la.fn.on?(y=la,P(la.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),b=la.cleanData,la.cleanData=function(a){var d;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d=la._data(f,"events"))&&d.$destroy&&la(f).triggerHandler("$destroy");b(a)}):y=Q;ca.element=y;Cc=!0}}function Sb(b, +a,c){if(!b)throw Fa("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&G(b)&&(b=b[b.length-1]);Sb(z(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ra(b,a){if("hasOwnProperty"===b)throw Fa("badname",a);}function Dc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&z(b)?vc(e,b):b}function qb(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!== +b);return y(c)}function ga(){return Object.create(null)}function de(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=J("$injector"),d=J("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||J;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(b,c,e,f){f||(f=d);return function(){f[e||"push"]([b,c,arguments]);return C}}function b(a,c){return function(b,e){e&&z(e)&& +(e.$$moduleName=f);d.push([a,c,arguments]);return C}}if(!g)throw c("nomod",f);var d=[],e=[],s=[],x=a("$injector","invoke","push",e),C={_invokeQueue:d,_configBlocks:e,_runBlocks:s,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator"),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider", +"register"),directive:b("$compileProvider","directive"),config:x,run:function(a){s.push(a);return this}};h&&x(h);return C})}})}function ee(b){P(b,{bootstrap:Ac,copy:fa,extend:P,merge:Vd,equals:ka,element:y,forEach:m,injector:eb,noop:v,bind:vc,toJson:db,fromJson:wc,identity:Ya,isUndefined:A,isDefined:w,isString:L,isFunction:z,isObject:H,isNumber:V,isElement:tc,isArray:G,version:fe,isDate:aa,lowercase:M,uppercase:rb,callbacks:{counter:0},getTestability:ae,$$minErr:J,$$csp:fb,reloadWithDebugInfo:$d}); +gb=de(O);try{gb("ngLocale")}catch(a){gb("ngLocale",[]).provider("$locale",ge)}gb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:he});a.provider("$compile",Ec).directive({a:ie,input:Fc,textarea:Fc,form:je,script:ke,select:le,style:me,option:ne,ngBind:oe,ngBindHtml:pe,ngBindTemplate:qe,ngClass:re,ngClassEven:se,ngClassOdd:te,ngCloak:ue,ngController:ve,ngForm:we,ngHide:xe,ngIf:ye,ngInclude:ze,ngInit:Ae,ngNonBindable:Be,ngPluralize:Ce,ngRepeat:De,ngShow:Ee,ngStyle:Fe,ngSwitch:Ge, +ngSwitchWhen:He,ngSwitchDefault:Ie,ngOptions:Je,ngTransclude:Ke,ngModel:Le,ngList:Me,ngChange:Ne,pattern:Gc,ngPattern:Gc,required:Hc,ngRequired:Hc,minlength:Ic,ngMinlength:Ic,maxlength:Jc,ngMaxlength:Jc,ngValue:Oe,ngModelOptions:Pe}).directive({ngInclude:Qe}).directive(sb).directive(Kc);a.provider({$anchorScroll:Re,$animate:Se,$$animateQueue:Te,$$AnimateRunner:Ue,$browser:Ve,$cacheFactory:We,$controller:Xe,$document:Ye,$exceptionHandler:Ze,$filter:Lc,$interpolate:$e,$interval:af,$http:bf,$httpParamSerializer:cf, +$httpParamSerializerJQLike:df,$httpBackend:ef,$location:ff,$log:gf,$parse:hf,$rootScope:jf,$q:kf,$$q:lf,$sce:mf,$sceDelegate:nf,$sniffer:of,$templateCache:pf,$templateRequest:qf,$$testability:rf,$timeout:sf,$window:tf,$$rAF:uf,$$jqLite:vf,$$HashMap:wf,$$cookieReader:xf})}])}function hb(b){return b.replace(yf,function(a,b,d,e){return e?d.toUpperCase():d}).replace(zf,"Moz$1")}function Mc(b){b=b.nodeType;return b===qa||!b||9===b}function Nc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Tb.test(b)){c= +c||e.appendChild(a.createElement("div"));d=(Af.exec(b)||["",""])[1].toLowerCase();d=na[d]||na._default;c.innerHTML=d[1]+b.replace(Bf,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=cb(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";m(f,function(a){e.appendChild(a)});return e}function Q(b){if(b instanceof Q)return b;var a;L(b)&&(b=R(b),a=!0);if(!(this instanceof Q)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new Q(b)}if(a){a=U; +var c;b=(c=Cf.exec(b))?[a.createElement(c[1])]:(c=Nc(b,a))?c.childNodes:[]}Oc(this,b)}function Vb(b){return b.cloneNode(!0)}function tb(b,a){a||ub(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)ub(c[d])}function Pc(b,a,c,d){if(w(d))throw Ub("offargs");var e=(d=vb(b))&&d.events,f=d&&d.handle;if(f)if(a)m(a.split(" "),function(a){if(w(c)){var d=e[a];bb(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a, +f,!1),delete e[a]}function ub(b,a){var c=b.ng339,d=c&&ib[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Pc(b)),delete ib[c],b.ng339=t))}function vb(b,a){var c=b.ng339,c=c&&ib[c];a&&!c&&(b.ng339=c=++Df,c=ib[c]={events:{},data:{},handle:t});return c}function Wb(b,a,c){if(Mc(b)){var d=w(c),e=!d&&a&&!H(a),f=!a;b=(b=vb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];P(b,a)}}}function wb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+ +" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function xb(b,a){a&&b.setAttribute&&m(a.split(" "),function(a){b.setAttribute("class",R((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+R(a)+" "," ")))})}function yb(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");m(a.split(" "),function(a){a=R(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",R(c))}}function Oc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c= +a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Qc(b,a){return zb(b,"$"+(a||"ngController")+"Controller")}function zb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=G(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=y.data(b,a[d]))!==t)return c;b=b.parentNode||11===b.nodeType&&b.host}}function Rc(b){for(tb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Xb(b,a){a||tb(b);var c=b.parentNode;c&&c.removeChild(b)}function Ef(b, +a){a=a||O;if("complete"===a.document.readyState)a.setTimeout(b);else y(a).on("load",b)}function Sc(b,a){var c=Ab[a.toLowerCase()];return c&&Tc[ta(b)]&&c}function Ff(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Uc[a]}function Gf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=a[e||c.type],g=f?f.length:0;if(g){if(A(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped= +!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=ia(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function vf(){this.$get=function(){return P(Q,{hasClass:function(b,a){b.attr&&(b=b[0]);return wb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return yb(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return xb(b,a)}})}}function Ga(b,a){var c=b&&b.$$hashKey; +if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Ud)():c+":"+b}function Sa(b,a){if(a){var c=0;this.nextUid=function(){return++c}}m(b,this.put,this)}function Hf(b){return(b=b.toString().replace(Vc,"").match(Wc))?"function("+(b[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function eb(b,a){function c(a){return function(b,c){if(H(b))m(b,pc(a));else return a(b,c)}}function d(a,b){Ra(a,"service");if(z(b)||G(b))b=s.instantiate(b); +if(!b.$get)throw Ha("pget",a);return r[a+"Provider"]=b}function e(a,b){return function(){var c=C.invoke(b,this);if(A(c))throw Ha("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;m(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=s.get(e[0]);f[e[1]].apply(f,e[2])}}if(!n.get(a)){n.put(a,!0);try{L(a)?(c=gb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(s.invoke(a)):G(a)? +b.push(s.invoke(a)):Qa(a,"module")}catch(e){throw G(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ha("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Ha("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a),b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var h=[],k=eb.$$annotate(b, +a,g),l,s,n;s=0;for(l=k.length;s<l;s++){n=k[s];if("string"!==typeof n)throw Ha("itkn",n);h.push(f&&f.hasOwnProperty(n)?f[n]:d(n,g))}G(b)&&(b=b[l]);return b.apply(c,h)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((G(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return H(a)||z(a)?a:d},get:d,annotate:eb.$$annotate,has:function(a){return r.hasOwnProperty(a+"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],n=new Sa([],!0),r={$provide:{provider:c(d),factory:c(f),service:c(function(a, +b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ra(b),!1)}),constant:c(function(a,b){Ra(a,"constant");r[a]=b;x[a]=b}),decorator:function(a,b){var c=s.get(a+"Provider"),d=c.$get;c.$get=function(){var a=C.invoke(d,c);return C.invoke(b,null,{$delegate:a})}}}},s=r.$injector=h(r,function(a,b){ca.isString(b)&&k.push(b);throw Ha("unpr",k.join(" <- "));}),x={},C=x.$injector=h(x,function(a,b){var c=s.get(a+"Provider",b);return C.invoke(c.$get,c,t,a)});m(g(b), +function(a){a&&C.invoke(a)});return C}function Re(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ta(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():tc(c)?(c=c[0],c="fixed"!==a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):V(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0, +0)}function g(a){a=L(a)?a:c.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||Ef(function(){d.$evalAsync(g)})});return g}]}function jb(b,a){if(!b&&!a)return"";if(!b)return a;if(!a)return b;G(b)&&(b=b.join(" "));G(a)&&(a=a.join(" "));return b+" "+a}function If(b){L(b)&&(b=b.split(" "));var a=ga();m(b,function(b){b.length&&(a[b]=!0)});return a}function Ia(b){return H(b)? +b:{}}function Jf(b,a,c,d){function e(a){try{a.apply(null,za.call(arguments,1))}finally{if(C--,0===C)for(;F.length;)try{F.pop()()}catch(b){c.error(b)}}}function f(){g();h()}function g(){a:{try{u=n.state;break a}catch(a){}u=void 0}u=A(u)?null:u;ka(u,D)&&(u=D);D=u}function h(){if(K!==l.url()||p!==u)K=l.url(),p=u,m(B,function(a){a(l.url(),u)})}var l=this,k=b.location,n=b.history,r=b.setTimeout,s=b.clearTimeout,x={};l.isMock=!1;var C=0,F=[];l.$$completeOutstandingRequest=e;l.$$incOutstandingRequestCount= +function(){C++};l.notifyWhenNoOutstandingRequests=function(a){0===C?a():F.push(a)};var u,p,K=k.href,q=a.find("base"),I=null;g();p=u;l.url=function(a,c,e){A(e)&&(e=null);k!==b.location&&(k=b.location);n!==b.history&&(n=b.history);if(a){var f=p===e;if(K===a&&(!d.history||f))return l;var h=K&&Ja(K)===Ja(a);K=a;p=e;if(!d.history||h&&f){if(!h||I)I=a;c?k.replace(a):h?(c=k,e=a.indexOf("#"),a=-1===e?"":a.substr(e),c.hash=a):k.href=a}else n[c?"replaceState":"pushState"](e,"",a),g(),p=u;return l}return I|| +k.href.replace(/%27/g,"'")};l.state=function(){return u};var B=[],N=!1,D=null;l.onUrlChange=function(a){if(!N){if(d.history)y(b).on("popstate",f);y(b).on("hashchange",f);N=!0}B.push(a);return a};l.$$applicationDestroyed=function(){y(b).off("hashchange popstate",f)};l.$$checkUrlChange=h;l.baseHref=function(){var a=q.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};l.defer=function(a,b){var c;C++;c=r(function(){delete x[c];e(a)},b||0);x[c]=!0;return c};l.defer.cancel=function(a){return x[a]? +(delete x[a],s(a),e(v),!0):!1}}function Ve(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new Jf(b,d,a,c)}]}function We(){this.$get=function(){function b(b,d){function e(a){a!=r&&(s?s==a&&(s=a.n):s=a,f(a.n,a.p),f(a,r),r=a,r.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw J("$cacheFactory")("iid",b);var g=0,h=P({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,n={},r=null,s=null;return a[b]={put:function(a,b){if(!A(b)){if(k<Number.MAX_VALUE){var c= +n[a]||(n[a]={key:a});e(c)}a in l||g++;l[a]=b;g>k&&this.remove(s.key);return b}},get:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;b==r&&(r=b.p);b==s&&(s=b.n);f(b.n,b.p);delete n[a]}delete l[a];g--},removeAll:function(){l={};g=0;n={};r=s=null},destroy:function(){n=h=l=null;delete a[b]},info:function(){return P({},h,{size:g})}}}var a={};b.info=function(){var b={};m(a,function(a,e){b[e]=a.info()});return b}; +b.get=function(b){return a[b]};return b}}function pf(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Ec(b,a){function c(a,b,c){var d=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,e={};m(a,function(a,f){var g=a.match(d);if(!g)throw ea("iscp",b,f,a,c?"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f}});return e}function d(a){var b=a.charAt(0);if(!b||b!==M(b))throw ea("baddir",a);if(a!==a.trim())throw ea("baddir", +a);}var e={},f=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,g=/(([\w\-]+)(?:\:([^;]+))?;?)/,h=Wd("ngSrc,ngSrcset,src,srcset"),l=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,k=/^(on[a-z]+|formaction)$/;this.directive=function s(a,f){Ra(a,"directive");L(a)?(d(a),Sb(f,"directiveFactory"),e.hasOwnProperty(a)||(e[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,d){var f=[];m(e[a],function(e,g){try{var h=b.invoke(e);z(h)?h={compile:ra(h)}:!h.compile&&h.link&&(h.compile=ra(h.link));h.priority=h.priority|| +0;h.index=g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";var k=h,l=h,s=h.name,n={isolateScope:null,bindToController:null};H(l.scope)&&(!0===l.bindToController?(n.bindToController=c(l.scope,s,!0),n.isolateScope={}):n.isolateScope=c(l.scope,s,!1));H(l.bindToController)&&(n.bindToController=c(l.bindToController,s,!0));if(H(n.bindToController)){var C=l.controller,$=l.controllerAs;if(!C)throw ea("noctrl",s);var ha;a:if($&&L($))ha=$;else{if(L(C)){var m=Xc.exec(C); +if(m){ha=m[3];break a}}ha=void 0}if(!ha)throw ea("noident",s);}var q=k.$$bindings=n;H(q.isolateScope)&&(h.$$isolateBindings=q.isolateScope);h.$$moduleName=e.$$moduleName;f.push(h)}catch(t){d(t)}});return f}])),e[a].push(f)):m(a,pc(s));return this};this.aHrefSanitizationWhitelist=function(b){return w(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()}; +var n=!0;this.debugInfoEnabled=function(a){return w(a)?(n=a,this):n};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,d,u,p,K,q,I,B,N){function D(a,b){try{a.addClass(b)}catch(c){}}function Z(a,b,c,d,e){a instanceof y||(a=y(a));m(a,function(b,c){b.nodeType==Na&&b.nodeValue.match(/\S+/)&&(a[c]=y(b).wrap("<span></span>").parent()[0])});var f=S(a,b,a,c,d,e);Z.$$addScopeClass(a); +var g=null;return function(b,c,d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?y(Yb(g,y("<div>").append(a).html())):c?Pa.clone.call(a):a;if(h)for(var k in h)d.data("$"+k+"Controller",h[k].instance);Z.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function S(a,b,c,d,e,f){function g(a, +c,d,e){var f,k,l,s,n,B,C;if(p)for(C=Array(c.length),s=0;s<h.length;s+=3)f=h[s],C[f]=c[f];else C=c;s=0;for(n=h.length;s<n;)if(k=C[h[s++]],c=h[s++],f=h[s++],c){if(c.scope){if(l=a.$new(),Z.$$addScopeInfo(y(k),l),B=c.$$destroyBindings)c.$$destroyBindings=null,l.$on("$destroyed",B)}else l=a;B=c.transcludeOnThisElement?$(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?$(a,b):null;c(f,l,k,d,B,c)}else f&&f(a,k.childNodes,t,e)}for(var h=[],k,l,s,n,p,B=0;B<a.length;B++){k=new aa;l=ha(a[B],[],k,0===B? +d:t,e);(f=l.length?E(l,a[B],k,b,c,null,[],[],f):null)&&f.scope&&Z.$$addScopeClass(k.$$element);k=f&&f.terminal||!(s=a[B].childNodes)||!s.length?null:S(s,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(B,f,k),n=!0,p=p||f;f=null}return n?g:null}function $(a,b,c){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function ha(a,b,c,d,e){var h=c.$attr,k;switch(a.nodeType){case qa:w(b, +wa(ta(a)),"E",d,e);for(var l,s,n,p=a.attributes,B=0,C=p&&p.length;B<C;B++){var x=!1,S=!1;l=p[B];k=l.name;s=R(l.value);l=wa(k);if(n=ia.test(l))k=k.replace(Zc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var F=l.replace(/(Start|End)$/,"");A(F)&&l===F+"Start"&&(x=k,S=k.substr(0,k.length-5)+"end",k=k.substr(0,k.length-6));l=wa(k.toLowerCase());h[l]=k;if(n||!c.hasOwnProperty(l))c[l]=s,Sc(a,l)&&(c[l]=!0);V(a,b,s,l,n);w(b,l,"A",d,e,x,S)}a=a.className;H(a)&&(a=a.animVal);if(L(a)&& +""!==a)for(;k=g.exec(a);)l=wa(k[2]),w(b,l,"C",d,e)&&(c[l]=R(k[3])),a=a.substr(k.index+k[0].length);break;case Na:if(11===Ua)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===Na;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);xa(b,a.nodeValue);break;case 8:try{if(k=f.exec(a.nodeValue))l=wa(k[1]),w(b,l,"M",d,e)&&(c[l]=R(k[2]))}catch($){}}b.sort(Aa);return b}function va(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ea("uterdir",b,c); +a.nodeType==qa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return y(d)}function Yc(a,b,c){return function(d,e,f,g,h){e=va(e[0],b,c);return a(d,e,f,g,h)}}function E(a,b,d,e,f,g,h,k,s){function n(a,b,c,d){if(a){c&&(a=Yc(a,c,d));a.require=E.require;a.directiveName=w;if(u===E||E.$$isolateScope)a=X(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=Yc(b,c,d));b.require=E.require;b.directiveName=w;if(u===E||E.$$isolateScope)b=X(b,{isolateScope:!0});k.push(b)}} +function B(a,b,c,d){var e;if(L(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;e||(d="$"+b+"Controller",e=g?c.inheritedData(d):c.data(d));if(!e&&!f)throw ea("ctreq",b,a);}else if(G(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=B(a,b[g],c,d);return e||null}function x(a,b,c,d,e,f){var g=ga(),h;for(h in d){var k=d[h],l={$scope:k===u||k.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},s=k.controller;"@"==s&&(s=b[k.name]);l=p(s, +l,!0,k.controllerAs);g[k.name]=l;q||a.data("$"+k.name+"Controller",l.instance)}return g}function S(a,c,e,f,g,l){function s(a,b,c){var d;$a(a)||(c=b,b=a,a=t);q&&(d=m);c||(c=q?ja.parent():ja);return g(a,b,d,c,va)}var n,p,C,F,m,ha,ja;b===e?(f=d,ja=d.$$element):(ja=y(e),f=new aa(ja,d));u&&(F=c.$new(!0));g&&(ha=s,ha.$$boundTransclude=g);N&&(m=x(ja,f,ha,N,F,c));u&&(Z.$$addScopeInfo(ja,F,!0,!(D&&(D===u||D===u.$$originalDirective))),Z.$$addScopeClass(ja,!0),F.$$isolateBindings=u.$$isolateBindings,W(c,f,F, +F.$$isolateBindings,u,F));if(m){var K=u||$,I;K&&m[K.name]&&(p=K.$$bindings.bindToController,(C=m[K.name])&&C.identifier&&p&&(I=C,l.$$destroyBindings=W(c,f,C.instance,p,K)));for(n in m){C=m[n];var E=C();E!==C.instance&&(C.instance=E,ja.data("$"+n+"Controller",E),C===I&&(l.$$destroyBindings(),l.$$destroyBindings=W(c,f,E,p,K)))}}n=0;for(l=h.length;n<l;n++)p=h[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha);var va=c;u&&(u.template||null===u.templateUrl)&&(va=F);a&&a(va, +e.childNodes,t,g);for(n=k.length-1;0<=n;n--)p=k[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha)}s=s||{};for(var F=-Number.MAX_VALUE,$=s.newScopeDirective,N=s.controllerDirectives,u=s.newIsolateScopeDirective,D=s.templateDirective,m=s.nonTlbTranscludeDirective,K=!1,I=!1,q=s.hasElementTranscludeDirective,ba=d.$$element=y(b),E,w,v,A=e,Aa,xa=0,Ta=a.length;xa<Ta;xa++){E=a[xa];var M=E.$$start,P=E.$$end;M&&(ba=va(b,M,P));v=t;if(F>E.priority)break;if(v=E.scope)E.templateUrl|| +(H(v)?(O("new/isolated scope",u||$,E,ba),u=E):O("new/isolated scope",u,E,ba)),$=$||E;w=E.name;!E.templateUrl&&E.controller&&(v=E.controller,N=N||ga(),O("'"+w+"' controller",N[w],E,ba),N[w]=E);if(v=E.transclude)K=!0,E.$$tlb||(O("transclusion",m,E,ba),m=E),"element"==v?(q=!0,F=E.priority,v=ba,ba=d.$$element=y(U.createComment(" "+w+": "+d[w]+" ")),b=ba[0],T(f,za.call(v,0),b),A=Z(v,e,F,g&&g.name,{nonTlbTranscludeDirective:m})):(v=y(Vb(b)).contents(),ba.empty(),A=Z(v,e));if(E.template)if(I=!0,O("template", +D,E,ba),D=E,v=z(E.template)?E.template(ba,d):E.template,v=fa(v),E.replace){g=E;v=Tb.test(v)?$c(Yb(E.templateNamespace,R(v))):[];b=v[0];if(1!=v.length||b.nodeType!==qa)throw ea("tplrt",w,"");T(f,ba,b);Ta={$attr:{}};v=ha(b,[],Ta);var Q=a.splice(xa+1,a.length-(xa+1));u&&ad(v);a=a.concat(v).concat(Q);J(d,Ta);Ta=a.length}else ba.html(v);if(E.templateUrl)I=!0,O("template",D,E,ba),D=E,E.replace&&(g=E),S=Lf(a.splice(xa,a.length-xa),ba,d,f,K&&A,h,k,{controllerDirectives:N,newScopeDirective:$!==E&&$,newIsolateScopeDirective:u, +templateDirective:D,nonTlbTranscludeDirective:m}),Ta=a.length;else if(E.compile)try{Aa=E.compile(ba,d,A),z(Aa)?n(null,Aa,M,P):Aa&&n(Aa.pre,Aa.post,M,P)}catch(Kf){c(Kf,ua(ba))}E.terminal&&(S.terminal=!0,F=Math.max(F,E.priority))}S.scope=$&&!0===$.scope;S.transcludeOnThisElement=K;S.templateOnThisElement=I;S.transclude=A;s.hasElementTranscludeDirective=q;return S}function ad(a){for(var b=0,c=a.length;b<c;b++)a[b]=Ob(a[b],{$$isolateScope:!0})}function w(b,d,f,g,h,k,l){if(d===h)return null;h=null;if(e.hasOwnProperty(d)){var n; +d=a.get(d+"Directive");for(var p=0,B=d.length;p<B;p++)try{n=d[p],(g===t||g>n.priority)&&-1!=n.restrict.indexOf(f)&&(k&&(n=Ob(n,{$$start:k,$$end:l})),b.push(n),h=n)}catch(x){c(x)}}return h}function A(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d<f;d++)if(b=c[d],b.multiElement)return!0;return!1}function J(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;m(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});m(b,function(b,f){"class"== +f?(D(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function Lf(a,b,c,e,f,g,h,k){var l=[],s,n,p=b[0],B=a.shift(),C=Ob(B,{templateUrl:null,transclude:null,replace:null,$$originalDirective:B}),x=z(B.templateUrl)?B.templateUrl(b,c):B.templateUrl,N=B.templateNamespace;b.empty();d(x).then(function(d){var F,u;d=fa(d);if(B.replace){d=Tb.test(d)?$c(Yb(N,R(d))): +[];F=d[0];if(1!=d.length||F.nodeType!==qa)throw ea("tplrt",B.name,x);d={$attr:{}};T(e,b,F);var K=ha(F,[],d);H(B.scope)&&ad(K);a=K.concat(a);J(c,d)}else F=p,b.html(d);a.unshift(C);s=E(a,F,c,f,b,B,g,h,k);m(e,function(a,c){a==F&&(e[c]=b[0])});for(n=S(b[0].childNodes,f);l.length;){d=l.shift();u=l.shift();var I=l.shift(),va=l.shift(),K=b[0];if(!d.$$destroyed){if(u!==p){var Z=u.className;k.hasElementTranscludeDirective&&B.replace||(K=Vb(F));T(I,y(u),K);D(y(K),Z)}u=s.transcludeOnThisElement?$(d,s.transclude, +va):va;s(n,d,K,e,u,s)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(s.transcludeOnThisElement&&(a=$(b,s.transclude,e)),s(n,b,c,d,a,s)))}}function Aa(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function O(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ea("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,ua(d));}function xa(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a= +a.parent();var b=!!a.length;b&&Z.$$addBindingClass(a);return function(a,c){var e=c.parent();b||Z.$$addBindingClass(e);Z.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Yb(a,b){a=M(a||"html");switch(a){case "svg":case "math":var c=U.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function Q(a,b){if("srcdoc"==b)return I.HTML;var c=ta(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b|| +"ngSrc"==b))return I.RESOURCE_URL}function V(a,c,d,e,f){var g=Q(a,e);f=h[e]||f;var l=b(d,!0,g,f);if(l){if("multiple"===e&&"select"===ta(a))throw ea("selmulti",ua(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers={});if(k.test(e))throw ea("nodomevents");var s=h[e];s!==d&&(l=s&&b(s,!0,g,f),d=s);l&&(h[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e, +a)}))}}}})}}function T(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=U.createDocumentFragment();a.appendChild(d);y.hasData(d)&&(y(c).data(y(d).data()),la?(Rb=!0,la.cleanData([d])):delete y.cache[d[y.expando]]);d=1;for(e=b.length;d<e;d++)f=b[d],y(f).remove(),a.appendChild(f),delete b[d];b[0]=c;b.length=1}function X(a, +b){return P(function(){return a.apply(null,arguments)},a,b)}function Y(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,ua(d))}}function W(a,c,d,e,f,g){var h;m(e,function(e,g){var k=e.attrName,l=e.optional,s=e.mode,n,p,B,C;Xa.call(c,k)||(c[k]=t);switch(s){case "@":c[k]||l||(d[g]=t);c.$observe(k,function(a){d[g]=a});c.$$observers[k].$$scope=a;c[k]&&(d[g]=b(c[k])(a));break;case "=":if(l&&!c[k])break;p=u(c[k]);C=p.literal?ka:function(a,b){return a===b||a!==a&&b!==b};B=p.assign||function(){n=d[g]=p(a);throw ea("nonassign", +c[k],f.name);};n=d[g]=p(a);l=function(b){C(b,d[g])||(C(b,n)?B(a,b=d[g]):d[g]=b);return n=b};l.$stateful=!0;l=e.collection?a.$watchCollection(c[k],l):a.$watch(u(c[k],l),null,p.literal);h=h||[];h.push(l);break;case "&":p=u(c[k]);if(p===v&&l)break;d[g]=function(b){return p(a,b)}}});e=h?function(){for(var a=0,b=h.length;a<b;++a)h[a]()}:v;return g&&e!==v?(g.$on("$destroy",e),v):e}var aa=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element= +a};aa.prototype={$normalize:wa,$addClass:function(a){a&&0<a.length&&B.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&B.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=bd(a,b);c&&c.length&&B.addClass(this.$$element,c);(c=bd(b,a))&&c.length&&B.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Sc(f,a),h=Ff(f,a),f=a;g?(this.$$element.prop(a,b),e=g):h&&(this[h]=b,f=h);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Bc(a, +"-"));g=ta(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=N(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",h=R(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(h)?k:/(,)/,h=h.split(k),k=Math.floor(h.length/2),l=0;l<k;l++)var s=2*l,g=g+N(R(h[s]),!0),g=g+(" "+R(h[s+1]));h=R(h[2*l]).split(/\s/);g+=N(R(h[0]),!0);2===h.length&&(g+=" "+R(h[1]));this[a]=b=g}!1!==d&&(null===b||b===t?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&m(a[f], +function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ga()),e=d[a]||(d[a]=[]);e.push(b);K.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])});return function(){bb(e,b)}}};var ca=b.startSymbol(),da=b.endSymbol(),fa="{{"==ca||"}}"==da?Ya:function(a){return a.replace(/\{\{/g,ca).replace(/}}/g,da)},ia=/^ngAttr[A-Z]/;Z.$$addBindingInfo=n?function(a,b){var c=a.data("$binding")||[];G(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:v;Z.$$addBindingClass= +n?function(a){D(a,"ng-binding")}:v;Z.$$addScopeInfo=n?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:v;Z.$$addScopeClass=n?function(a,b){D(a,b?"ng-isolate-scope":"ng-scope")}:v;return Z}]}function wa(b){return hb(b.replace(Zc,""))}function bd(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function $c(b){b=y(b);var a=b.length;if(1>=a)return b;for(;a--;)8=== +b[a].nodeType&&Mf.call(b,a,1);return b}function Xe(){var b={},a=!1;this.register=function(a,d){Ra(a,"controller");H(a)?P(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!H(a.$scope))throw J("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,l){var k,n,r;h=!0===h;l&&L(l)&&(r=l);if(L(f)){l=f.match(Xc);if(!l)throw Nf("ctrlfmt",f);n=l[1];r=r||l[3];f=b.hasOwnProperty(n)?b[n]:Dc(g.$scope,n,!0)||(a?Dc(d,n,!0):t);Qa(f, +n,!0)}if(h)return h=(G(f)?f[f.length-1]:f).prototype,k=Object.create(h||null),r&&e(g,r,k,n||f.name),P(function(){var a=c.invoke(f,k,g,n);a!==k&&(H(a)||z(a))&&(k=a,r&&e(g,r,k,n||f.name));return k},{instance:k,identifier:r});k=c.instantiate(f,g,n);r&&e(g,r,k,n||f.name);return k}}]}function Ye(){this.$get=["$window",function(b){return y(b.document)}]}function Ze(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b){return H(b)?aa(b)?b.toISOString():db(b):b} +function cf(){this.$get=function(){return function(b){if(!b)return"";var a=[];oc(b,function(b,d){null===b||A(b)||(G(b)?m(b,function(b,c){a.push(ma(d)+"="+ma(Zb(b)))}):a.push(ma(d)+"="+ma(Zb(b))))});return a.join("&")}}}function df(){this.$get=function(){return function(b){function a(b,e,f){null===b||A(b)||(G(b)?m(b,function(b){a(b,e+"[]")}):H(b)&&!aa(b)?oc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(ma(e)+"="+ma(Zb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function $b(b, +a){if(L(b)){var c=b.replace(Of,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(cd))||(d=(d=c.match(Pf))&&Qf[d[0]].test(c));d&&(b=wc(c))}}return b}function dd(b){var a=ga(),c;L(b)?m(b.split("\n"),function(b){c=b.indexOf(":");var e=M(R(b.substr(0,c)));b=R(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):H(b)&&m(b,function(b,c){var f=M(c),g=R(b);f&&(a[f]=a[f]?a[f]+", "+g:g)});return a}function ed(b){var a;return function(c){a||(a=dd(b));return c?(c=a[M(c)],void 0===c&&(c=null),c):a}}function fd(b, +a,c,d){if(z(d))return d(b,a,c);m(d,function(d){b=d(b,a,c)});return b}function bf(){var b=this.defaults={transformResponse:[$b],transformRequest:[function(a){return H(a)&&"[object File]"!==sa.call(a)&&"[object Blob]"!==sa.call(a)&&"[object FormData]"!==sa.call(a)?db(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ac),put:ia(ac),patch:ia(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return w(b)? +(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=P({},a);b.data=a.data?fd(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a,b){var c,e={};m(a,function(a,d){z(a)?(c=a(b),null!=c&&(e[d]=c)):e[d]=a});return e}if(!ca.isObject(a))throw J("$http")("badreq",a);var e=P({method:"get",transformRequest:b.transformRequest, +transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);e.headers=function(a){var c=b.headers,e=P({},a.headers),f,g,h,c=P({},c.common,c[M(a.method)]);a:for(f in c){g=M(f);for(h in e)if(M(h)===g)continue a;e[f]=c[f]}return d(e,ia(a))}(a);e.method=rb(e.method);e.paramSerializer=L(e.paramSerializer)?l.get(e.paramSerializer):e.paramSerializer;var f=[function(a){var d=a.headers,e=fd(a.data,ed(d),t,a.transformRequest);A(e)&&m(d,function(a,b){"content-type"===M(b)&&delete d[b]});A(a.withCredentials)&& +!A(b.withCredentials)&&(a.withCredentials=b.withCredentials);return n(a,e).then(c,c)},t],g=h.when(e);for(m(x,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),g=g.then(a,k)}g.success=function(a){Qa(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){Qa(a,"fn");g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g} +function n(c,f){function l(b,c,d,e){function f(){n(c,b,d,e)}N&&(200<=b&&300>b?N.put(S,[b,c,dd(d),e]):N.remove(S));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function n(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:ed(d),config:c,statusText:e})}function x(a){n(a.data,a.status,ia(a.headers()),a.statusText)}function m(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),B=I.promise,N,D,q=c.headers,S=r(c.url,c.paramSerializer(c.params)); +k.pendingRequests.push(c);B.then(m,m);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(N=H(c.cache)?c.cache:H(b.cache)?b.cache:s);N&&(D=N.get(S),w(D)?D&&z(D.then)?D.then(x,x):G(D)?n(D[1],D[0],ia(D[2]),D[3]):n(D,200,{},"OK"):N.put(S,B));A(D)&&((D=gd(c.url)?e()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(q[c.xsrfHeaderName||b.xsrfHeaderName]=D),d(c.method,S,f,l,q,c.timeout,c.withCredentials,c.responseType));return B}function r(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b); +return a}var s=f("$http");b.paramSerializer=L(b.paramSerializer)?l.get(b.paramSerializer):b.paramSerializer;var x=[];m(c,function(a){x.unshift(L(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){m(arguments,function(a){k[a]=function(b,c){return k(P({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){m(arguments,function(a){k[a]=function(b,c,d){return k(P({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function Rf(){return new O.XMLHttpRequest} +function ef(){this.$get=["$browser","$window","$document",function(b,a,c){return Sf(b,Rf,b.defer,a.angular.callbacks,c[0])}]}function Sf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),n=null;f.type="text/javascript";f.src=a;f.async=!0;n=function(a){f.removeEventListener("load",n,!1);f.removeEventListener("error",n,!1);e.body.removeChild(f);f=null;var g=-1,x="unknown";a&&("load"!==a.type||d[b].called||(a={type:"error"}),x=a.type,g="error"===a.type?404:200);c&&c(g,x)};f.addEventListener("load", +n,!1);f.addEventListener("error",n,!1);e.body.appendChild(f);return n}return function(e,h,l,k,n,r,s,x){function C(){p&&p();K&&K.abort()}function F(a,d,e,f,g){I!==t&&c.cancel(I);p=K=null;a(d,e,f,g);b.$$completeOutstandingRequest(v)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==M(e)){var u="_"+(d.counter++).toString(36);d[u]=function(a){d[u].data=a;d[u].called=!0};var p=f(h.replace("JSON_CALLBACK","angular.callbacks."+u),u,function(a,b){F(k,a,d[u].data,"",b);d[u]=v})}else{var K=a();K.open(e, +h,!0);m(n,function(a,b){w(a)&&K.setRequestHeader(b,a)});K.onload=function(){var a=K.statusText||"",b="response"in K?K.response:K.responseText,c=1223===K.status?204:K.status;0===c&&(c=b?200:"file"==Ba(h).protocol?404:0);F(k,c,b,K.getAllResponseHeaders(),a)};e=function(){F(k,-1,null,null,"")};K.onerror=e;K.onabort=e;s&&(K.withCredentials=!0);if(x)try{K.responseType=x}catch(q){if("json"!==x)throw q;}K.send(l)}if(0<r)var I=c(C,r);else r&&z(r.then)&&r.then(C)}}function $e(){var b="{{",a="}}";this.startSymbol= +function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(n,b).replace(r,a)}function h(f,h,n,r){function u(a){try{var b=a;a=n?e.getTrusted(n,b):e.valueOf(b);var c;if(r&&!w(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=db(a)}c=a}return c}catch(g){d(Ka.interr(f,g))}}r=!!r;for(var p,m,q=0,I= +[],B=[],N=f.length,D=[],t=[];q<N;)if(-1!=(p=f.indexOf(b,q))&&-1!=(m=f.indexOf(a,p+l)))q!==p&&D.push(g(f.substring(q,p))),q=f.substring(p+l,m),I.push(q),B.push(c(q,u)),q=m+k,t.push(D.length),D.push("");else{q!==N&&D.push(g(f.substring(q)));break}n&&1<D.length&&Ka.throwNoconcat(f);if(!h||I.length){var S=function(a){for(var b=0,c=I.length;b<c;b++){if(r&&A(a[b]))return;D[t[b]]=a[b]}return D.join("")};return P(function(a){var b=0,c=I.length,e=Array(c);try{for(;b<c;b++)e[b]=B[b](a);return S(e)}catch(g){d(Ka.interr(f, +g))}},{exp:f,expressions:I,$$watchDelegate:function(a,b){var c;return a.$watchGroup(B,function(d,e){var f=S(d);z(b)&&b.call(this,f,d!==e?c:f,a);c=f})}})}}var l=b.length,k=a.length,n=new RegExp(b.replace(/./g,f),"g"),r=new RegExp(a.replace(/./g,f),"g");h.startSymbol=function(){return b};h.endSymbol=function(){return a};return h}]}function af(){this.$get=["$rootScope","$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var n=4<arguments.length,r=n?za.call(arguments,4):[],s=a.setInterval,x=a.clearInterval, +C=0,F=w(k)&&!k,u=(F?d:c).defer(),p=u.promise;l=w(l)?l:0;p.then(null,null,n?function(){e.apply(null,r)}:e);p.$$intervalId=s(function(){u.notify(C++);0<l&&C>=l&&(u.resolve(C),x(p.$$intervalId),delete f[p.$$intervalId]);F||b.$apply()},h);f[p.$$intervalId]=u;return p}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function ge(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".", +GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), +SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=ob(b[a]);return b.join("/")}function hd(b,a){var c=Ba(b);a.$$protocol=c.protocol; +a.$$host=c.hostname;a.$$port=W(c.port)||Tf[c.protocol]||null}function id(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=zc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ya(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ja(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Bb(b){return b.replace(/(#.+)|#$/, +"$1")}function cc(b){return b.substr(0,Ja(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);hd(b,this);this.$$parse=function(a){var b=ya(c,a);if(!L(b))throw Cb("ipthprfx",a,c);id(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)), +!0;var f,g;(f=ya(b,d))!==t?(g=f,g=(f=ya(a,f))!==t?c+(ya("/",f)||f):b+g):(f=ya(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);hd(b,this);this.$$parse=function(d){var e=ya(b,d)||ya(c,d),f;A(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",A(e)&&(b=d,this.replace())):(f=ya(a,e),A(f)&&(f=e));id(f,this);d=this.$$path;var e=b,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(d=(f=g.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose= +function(){var c=Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ja(b)==Ja(a)?(this.$$parse(a),!0):!1}}function jd(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ja(d)?f=d:(g=ya(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c= +Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Db(b){return function(){return this[b]}}function kd(b,a){return function(c){if(A(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ff(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return w(a)?(b=a,this):b};this.html5Mode=function(b){return ab(b)?(a.enabled=b,this):H(b)?(ab(b.enabled)&&(a.enabled=b.enabled), +ab(b.requireBase)&&(a.requireBase=b.requireBase),ab(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var r=d.url(),s;if(a.enabled){if(!n&&a.requireBase)throw Cb("nobase");s=r.substring(0, +r.indexOf("/",r.indexOf("//")+2))+(n||"/");n=e.history?dc:jd}else s=Ja(r),n=ec;k=new n(s,"#"+b);k.$$parseLinkUrl(r,r);k.$$state=d.state();var x=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=y(b.target);"a"!==ta(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);x.test(h)|| +!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Bb(k.absUrl())!=Bb(r)&&d.url(k.absUrl(),!0);var C=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(C=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a= +Bb(d.url()),b=Bb(k.absUrl()),f=d.state(),g=k.$$replace,n=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(C||n)C=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(n&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function gf(){var b=!0,a=this;this.debugEnabled=function(a){return w(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&& +(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||v;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];m(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]} +function Ca(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw da("isecfld",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b.window===b)throw da("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw da("isecdom",a);if(b===Object)throw da("isecobj",a);}return b}function ld(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b===Uf||b===Vf||b===Wf)throw da("isecff",a); +}}function Xf(b,a){return"undefined"!==typeof b?b:a}function md(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function T(b,a){var c,d;switch(b.type){case q.Program:c=!0;m(b.body,function(b){T(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case q.Literal:b.constant=!0;b.toWatch=[];break;case q.UnaryExpression:T(b.argument,a);b.constant=b.argument.constant;b.toWatch=b.argument.toWatch;break;case q.BinaryExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&& +b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch);break;case q.LogicalExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case q.ConditionalExpression:T(b.test,a);T(b.alternate,a);T(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case q.Identifier:b.constant=!1;b.toWatch=[b];break;case q.MemberExpression:T(b.object,a);b.computed&&T(b.property,a); +b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch=[b];break;case q.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];m(b.arguments,function(b){T(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case q.AssignmentExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=[b];break;case q.ArrayExpression:c=!0;d=[];m(b.elements,function(b){T(b,a);c= +c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=d;break;case q.ObjectExpression:c=!0;d=[];m(b.properties,function(b){T(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case q.ThisExpression:b.constant=!1,b.toWatch=[]}}function nd(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:t}}function od(b){return b.type===q.Identifier||b.type===q.MemberExpression}function pd(b){if(1=== +b.body.length&&od(b.body[0].expression))return{type:q.AssignmentExpression,left:b.body[0].expression,right:{type:q.NGValueParameter},operator:"="}}function qd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===q.Literal||b.body[0].expression.type===q.ArrayExpression||b.body[0].expression.type===q.ObjectExpression)}function rd(b,a){this.astBuilder=b;this.$filter=a}function sd(b,a){this.astBuilder=b;this.$filter=a}function Eb(b,a,c,d){oa(b,d);a=a.split(".");for(var e,f=0;1< +a.length;f++){e=Ca(a.shift(),d);var g=oa(b[e],d);g||(g={},b[e]=g);b=g}e=Ca(a.shift(),d);oa(b[e],d);return b[e]=c}function Fb(b){return"constructor"==b}function fc(b){return z(b.valueOf)?b.valueOf():Yf.call(b)}function hf(){var b=ga(),a=ga();this.$get=["$filter","$sniffer",function(c,d){function e(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=fc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function f(a,b,c,d,f){var g=d.inputs,h;if(1===g.length){var k=e,g=g[0];return a.$watch(function(a){var b= +g(a);e(b,k)||(h=d(a,t,t,[b]),k=b&&fc(b));return h},b,c,f)}for(var l=[],n=[],r=0,m=g.length;r<m;r++)l[r]=e,n[r]=null;return a.$watch(function(a){for(var b=!1,c=0,f=g.length;c<f;c++){var k=g[c](a);if(b||(b=!e(k,l[c])))n[c]=k,l[c]=k&&fc(k)}b&&(h=d(a,t,t,n));return h},b,c,f)}function g(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);w(a)&&d.$$postDigest(function(){w(f)&&e()})},c)}function h(a,b,c,d){function e(a){var b=!0;m(a,function(a){w(a)|| +(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function l(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){z(b)&&b.apply(this,arguments);e()},c)}function k(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==h&&c!==g?function(c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}:function(c,d,e,f){e=a(c,d,e,f);c=b(e,c,d);return w(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!== +f?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=f,c.inputs=a.inputs?a.inputs:[a]);return c}var n={csp:d.csp,expensiveChecks:!1},r={csp:d.csp,expensiveChecks:!0};return function(d,e,C){var m,u,p;switch(typeof d){case "string":p=d=d.trim();var q=C?a:b;m=q[p];m||(":"===d.charAt(0)&&":"===d.charAt(1)&&(u=!0,d=d.substring(2)),C=C?r:n,m=new gc(C),m=(new hc(m,c,C)).parse(d),m.constant?m.$$watchDelegate=l:u?m.$$watchDelegate=m.literal?h:g:m.inputs&&(m.$$watchDelegate=f),q[p]=m);return k(m, +e);case "function":return k(d,e);default:return v}}}]}function kf(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return td(function(a){b.$evalAsync(a)},a)}]}function lf(){this.$get=["$browser","$exceptionHandler",function(b,a){return td(function(a){b.defer(a)},a)}]}function td(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&& +c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=t;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status];try{z(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),a(h)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=J("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending|| +[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(H(b)||z(b))d=b&&b.then;z(d)?(this.promise.$$state.status= +-1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(z(b)? +b(c):c)}catch(h){a(h)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return l(e,!1)}return d&&z(d.then)?d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},n=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},r=function x(a){if(!z(a))throw h("norslvr",a);if(!(this instanceof x))return new x(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise}; +r.defer=function(){return new g};r.reject=function(a){var b=new g;b.reject(a);return b.promise};r.when=n;r.resolve=n;r.all=function(a){var b=new g,c=0,d=G(a)?[]:{};m(a,function(a,e){c++;n(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return r}function uf(){this.$get=["$window","$timeout",function(b,a){function c(){for(var a=0;a<n.length;a++){var b=n[a];b&&(n[a]=null,b())}k=n.length=0}function d(a){var b= +n.length;k++;n.push(a);0===b&&(l=h(c));return function(){0<=b&&(b=n[b]=null,0===--k&&l&&(l(),l=null,n.length=0))}}var e=b.requestAnimationFrame||b.webkitRequestAnimationFrame,f=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,g=!!e,h=g?function(a){var b=e(a);return function(){f(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};d.supported=g;var l,k=0,n=[];return d}]}function jf(){function b(a){function b(){this.$$watchers=this.$$nextSibling= +this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++nb;this.$$ChildScope=null}b.prototype=a;return b}var a=10,c=J("$rootScope"),d=null,e=null;this.digestTtl=function(b){arguments.length&&(a=b);return a};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(f,g,h,l){function k(a){a.currentScope.$$destroyed=!0}function n(){this.$id=++nb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead= +this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function r(a){if(p.$$phase)throw c("inprog",p.$$phase);p.$$phase=a}function s(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function x(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function q(){}function F(){for(;I.length;)try{I.shift()()}catch(a){g(a)}e=null}function u(){null===e&&(e= +l.defer(function(){p.$apply(F)}))}n.prototype={constructor:n,$new:function(a,c){var d;c=c||this;a?(d=new n,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=b(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(a||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,c,e){var f=h(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,c,f,a);var g=this,k=g.$$watchers,l= +{fn:b,last:q,get:f,exp:e||a,eq:!!c};d=null;z(b)||(l.fn=v);k||(k=g.$$watchers=[]);k.unshift(l);s(this,1);return function(){0<=bb(k,l)&&s(g,-1);d=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&b(e,e,g)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});m(a,function(a,b){var k=g.$watch(a,function(a, +f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!A(e)){if(H(e))if(Ea(e))for(f!==r&&(f=r,m=f.length=0,l++),a=e.length,m!==a&&(l++,f.length=m=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==s&&(f=s={},m=0,l++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(m++,f[b]=g,l++));if(m>a)for(b in l++,f)e.hasOwnProperty(b)|| +(m--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,g,k=1<b.length,l=0,n=h(a,c),r=[],s={},p=!0,m=0;return this.$watch(n,function(){p?(p=!1,b(e,e,d)):b(e,g,d);if(k)if(H(e))if(Ea(e)){g=Array(e.length);for(var a=0;a<e.length;a++)g[a]=e[a]}else for(a in g={},e)Xa.call(e,a)&&(g[a]=e[a]);else g=e})},$digest:function(){var b,f,h,k,n,s,m=a,x,u=[],E,I;r("$digest");l.$$checkUrlChange();this===p&&null!==e&&(l.defer.cancel(e),F());d=null;do{s=!1;for(x=this;t.length;){try{I=t.shift(), +I.scope.$eval(I.expression,I.locals)}catch(v){g(v)}d=null}a:do{if(k=x.$$watchers)for(n=k.length;n--;)try{if(b=k[n])if((f=b.get(x))!==(h=b.last)&&!(b.eq?ka(f,h):"number"===typeof f&&"number"===typeof h&&isNaN(f)&&isNaN(h)))s=!0,d=b,b.last=b.eq?fa(f,null):f,b.fn(f,h===q?f:h,x),5>m&&(E=4-m,u[E]||(u[E]=[]),u[E].push({msg:z(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){s=!1;break a}}catch(A){g(A)}if(!(k=x.$$watchersCount&&x.$$childHead||x!==this&&x.$$nextSibling))for(;x!== +this&&!(k=x.$$nextSibling);)x=x.$parent}while(x=k);if((s||t.length)&&!m--)throw p.$$phase=null,c("infdig",a,u);}while(s||t.length);for(p.$$phase=null;w.length;)try{w.shift()()}catch(y){g(y)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===p&&l.$$applicationDestroyed();s(this,-this.$$watchersCount);for(var b in this.$$listenerCount)x(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail== +this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=v;this.$on=this.$watch=this.$watchGroup=function(){return v};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return h(a)(this,b)}, +$evalAsync:function(a,b){p.$$phase||t.length||l.defer(function(){t.length&&p.$digest()});t.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){w.push(a)},$apply:function(a){try{return r("$apply"),this.$eval(a)}catch(b){g(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&I.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]|| +(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,x(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=cb([h],arguments,1),l,n;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(n=d.length;l<n;l++)if(d[l])try{d[l].apply(null,k)}catch(r){g(r)}else d.splice(l,1),l--,n--;if(f)return h.currentScope= +null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var f=cb([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,f)}catch(l){g(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d= +c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var p=new n,t=p.$$asyncQueue=[],w=p.$$postDigestQueue=[],I=p.$$applyAsyncQueue=[];return p}]}function he(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(a){return w(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Ba(c).href;return""===f||f.match(e)?c:"unsafe:"+ +f}}}function Zf(b){if("self"===b)return b;if(L(b)){if(-1<b.indexOf("***"))throw Da("iwcard",b);b=ud(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(Za(b))return new RegExp("^"+b.source+"$");throw Da("imatcher");}function vd(b){var a=[];w(b)&&m(b,function(b){a.push(Zf(b))});return a}function nf(){this.SCE_CONTEXTS=pa;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=vd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&& +(a=vd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?gd(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw Da("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[pa.HTML]=e(g);h[pa.CSS]=e(g);h[pa.URL]= +e(g);h[pa.JS]=e(g);h[pa.RESOURCE_URL]=e(h[pa.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Da("icontext",a,b);if(null===b||b===t||""===b)return b;if("string"!==typeof b)throw Da("itype",a);return new c(b)},getTrusted:function(c,e){if(null===e||e===t||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(c===pa.RESOURCE_URL){var g=Ba(e.toString()),r,s,m=!1;r=0;for(s=b.length;r<s;r++)if(d(b[r],g)){m=!0;break}if(m)for(r= +0,s=a.length;r<s;r++)if(d(a[r],g)){m=!1;break}if(m)return e;throw Da("insecurl",e.toString());}if(c===pa.HTML)return f(e);throw Da("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function mf(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&8>Ua)throw Da("iequirks");var d=ia(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs= +d.getTrusted=function(a,b){return b},d.valueOf=Ya);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;m(pa,function(a,b){var c=M(b);d[hb("parse_as_"+c)]=function(b){return e(a,b)};d[hb("get_trusted_"+c)]=function(b){return f(a,b)};d[hb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function of(){this.$get=["$window","$document",function(b,a){var c={},d=W((/android (\d+)/.exec(M((b.navigator|| +{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var r in l)if(k=h.exec(r)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);n=!!("animation"in l||g+"Animation"in l);!d||k&&n||(k=L(l.webkitTransition),n=L(l.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"=== +a&&11>=Ua)return!1;if(A(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:fb(),vendorPrefix:g,transitions:k,animations:n,android:d}}]}function qf(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,g){e.totalPendingRequests++;L(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var h=a.defaults&&a.defaults.transformResponse;G(h)?h=h.filter(function(a){return a!==$b}):h===$b&&(h=null);return a.get(f,{cache:b,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(a){b.put(f, +a.data);return a.data},function(a){if(!g)throw ea("tpload",f,a.status,a.statusText);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function rf(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];m(a,function(a){var d=ca.element(a).data("$binding");d&&m(d,function(d){c?(new RegExp("(^|\\s)"+ud(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a, +b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function sf(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){z(f)||(k=l,l=f,f=v);var n=za.call(arguments,3),r=w(k)&&!k,s=(r?d:c).defer(), +m=s.promise,q;q=a.defer(function(){try{s.resolve(f.apply(null,n))}catch(a){s.reject(a),e(a)}finally{delete g[m.$$timeoutId]}r||b.$apply()},l);m.$$timeoutId=q;g[q]=s;return m}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Ba(b){Ua&&(X.setAttribute("href",b),b=X.href);X.setAttribute("href",b);return{href:X.href,protocol:X.protocol?X.protocol.replace(/:$/,""):"",host:X.host, +search:X.search?X.search.replace(/^\?/,""):"",hash:X.hash?X.hash.replace(/^#/,""):"",hostname:X.hostname,port:X.port,pathname:"/"===X.pathname.charAt(0)?X.pathname:"/"+X.pathname}}function gd(b){b=L(b)?Ba(b):b;return b.protocol===wd.protocol&&b.host===wd.host}function tf(){this.$get=ra(O)}function xd(b){function a(a){try{return decodeURIComponent(a)}catch(b){return a}}var c=b[0]||{},d={},e="";return function(){var b,g,h,l,k;b=c.cookie||"";if(b!==e)for(e=b,b=e.split("; "),d={},h=0;h<b.length;h++)g= +b[h],l=g.indexOf("="),0<l&&(k=a(g.substring(0,l)),d[k]===t&&(d[k]=a(g.substring(l+1))));return d}}function xf(){this.$get=xd}function Lc(b){function a(c,d){if(H(c)){var e={};m(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",yd);a("date",zd);a("filter",$f);a("json",ag);a("limitTo",bg);a("lowercase",cg);a("number",Ad);a("orderBy",Bd);a("uppercase",dg)}function $f(){return function(b, +a,c){if(!Ea(b)){if(null==b)return b;throw J("filter")("notarray",b);}var d;switch(ic(a)){case "function":break;case "boolean":case "null":case "number":case "string":d=!0;case "object":a=eg(a,c,d);break;default:return b}return Array.prototype.filter.call(b,a)}}function eg(b,a,c){var d=H(b)&&"$"in b;!0===a?a=ka:z(a)||(a=function(a,b){if(A(a))return!1;if(null===a||null===b)return a===b;if(H(b)||H(a)&&!rc(a))return!1;a=M(""+a);b=M(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!H(e)?La(e, +b.$,a,!1):La(e,b,a,c)}}function La(b,a,c,d,e){var f=ic(b),g=ic(a);if("string"===g&&"!"===a.charAt(0))return!La(b,a.substring(1),c,d);if(G(b))return b.some(function(b){return La(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==h.charAt(0)&&La(b[h],a,c,!0))return!0;return e?!1:La(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!z(e)&&!A(e)&&(f="$"===h,!La(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function ic(b){return null=== +b?"null":typeof b}function yd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){A(d)&&(d=a.CURRENCY_SYM);A(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:Cd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function Ad(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==b?b:Cd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Cd(b,a,c,d,e){if(H(b))return"";var f=0>b;b=Math.abs(b);var g=Infinity===b;if(!g&&!isFinite(b))return"";var h=b+"",l="",k=!1,n=[];g&&(l="\u221e"); +if(!g&&-1!==h.indexOf("e")){var r=h.match(/([\d\.]+)e(-?)(\d+)/);r&&"-"==r[2]&&r[3]>e+1?b=0:(l=h,k=!0)}if(g||k)0<e&&1>b&&(l=b.toFixed(e),b=parseFloat(l));else{g=(h.split(Dd)[1]||"").length;A(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(Dd),h=g[0],g=g[1]||"",r=0,s=a.lgSize,m=a.gSize;if(h.length>=s+m)for(r=h.length-s,k=0;k<r;k++)0===(r-k)%m&&0!==k&&(l+=c),l+=h.charAt(k);for(k=r;k<h.length;k++)0===(h.length-k)%s&&0!==k&& +(l+=c),l+=h.charAt(k);for(;g.length<e;)g+="0";e&&"0"!==e&&(l+=d+g.substr(0,e))}0===b&&(f=!1);n.push(f?a.negPre:a.posPre,l,f?a.negSuf:a.posSuf);return n.join("")}function Gb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function Y(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c,d){var e=c["get"+b](),f=rb(a?"SHORT"+b:b);return d[f][e]}}function Ed(b){var a= +(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Fd(b){return function(a){var c=Ed(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function jc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function zd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=W(b[9]+b[10]),g=W(b[9]+b[11]));h.call(a,W(b[1]), +W(b[2])-1,W(b[3]));f=W(b[4]||0)-f;g=W(b[5]||0)-g;h=W(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;L(c)&&(c=fg.test(c)?W(c):a(c));V(c)&&(c=new Date(c));if(!aa(c)||!isFinite(c.getTime()))return c;for(;e;)(k=gg.exec(e))?(h=cb(h,k,1),e=h.pop()):(h.push(e),e=null);var n=c.getTimezoneOffset(); +f&&(n=xc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));m(h,function(a){l=hg[a];g+=l?l(c,b.DATETIME_FORMATS,n):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function ag(){return function(b,a){A(a)&&(a=2);return db(b,a)}}function bg(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):W(a);if(isNaN(a))return b;V(b)&&(b=b.toString());if(!G(b)&&!L(b))return b;c=!c||isNaN(c)?0:W(c);c=0>c&&c>=-b.length?b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0, +c+a),c)}}function Bd(b){function a(a,c){c=c?-1:1;return a.map(function(a){var d=1,h=Ya;if(z(a))h=a;else if(L(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))d="-"==a.charAt(0)?-1:1,a=a.substring(1);if(""!==a&&(h=b(a),h.constant))var l=h(),h=function(a){return a[l]}}return{get:h,descending:d*c}})}function c(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}return function(b,e,f){if(!Ea(b))return b;G(e)||(e=[e]);0===e.length&&(e=["+"]);var g=a(e,f);b=Array.prototype.map.call(b, +function(a,b){return{value:a,predicateValues:g.map(function(d){var e=d.get(a);d=typeof e;if(null===e)d="string",e="null";else if("string"===d)e=e.toLowerCase();else if("object"===d)a:{if("function"===typeof e.valueOf&&(e=e.valueOf(),c(e)))break a;if(rc(e)&&(e=e.toString(),c(e)))break a;e=b}return{value:e,type:d}})}});b.sort(function(a,b){for(var c=0,d=0,e=g.length;d<e;++d){var c=a.predicateValues[d],f=b.predicateValues[d],m=0;c.type===f.type?c.value!==f.value&&(m=c.value<f.value?-1:1):m=c.type<f.type? +-1:1;if(c=m*g[d].descending)break}return c});return b=b.map(function(a){return a.value})}}function Ma(b){z(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ra(b)}function Gd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Ib;f.$error={};f.$$success={};f.$pending=t;f.$name=e(a.name||a.ngForm||"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){m(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue= +function(){m(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ra(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];m(f.$pending,function(b,c){f.$setValidity(c,null,a)});m(f.$error,function(b,c){f.$setValidity(c,null,a)});m(f.$$success,function(b,c){f.$setValidity(c,null,a)});bb(g,a)};Hd({ctrl:this,$element:b,set:function(a,b, +c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(bb(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Va);d.addClass(b,Jb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Va,Jb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;m(g,function(a){a.$setPristine()})};f.$setUntouched=function(){m(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b, +"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function kc(b){b.$formatters.push(function(a){return b.$isEmpty(a)?a:a.toString()})}function kb(b,a,c,d,e,f){var g=M(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e=a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=R(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}}; +if(e.hasEvent("input"))a.on("input",l);else{var k,n=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Kb(b,a){return function(c,d){var e,f;if(aa(c))return c;if(L(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1)); +if(ig.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},m(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function lb(b,a,c,d){return function(e,f,g,h,l,k,n){function r(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function s(a){return w(a)? +aa(a)?a:c(a):t}Id(e,f,g,h);kb(e,f,g,h,l,k);var m=h&&h.$options&&h.$options.timezone,q;h.$$parserName=b;h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,q),m&&(b=Pb(b,m)),b):t});h.$formatters.push(function(a){if(a&&!aa(a))throw Lb("datefmt",a);if(r(a))return(q=a)&&m&&(q=Pb(q,m,!0)),n("date")(a,d,m);q=null;return""});if(w(g.min)||g.ngMin){var F;h.$validators.min=function(a){return!r(a)||A(F)||c(a)>=F};g.$observe("min",function(a){F=s(a);h.$validate()})}if(w(g.max)||g.ngMax){var u; +h.$validators.max=function(a){return!r(a)||A(u)||c(a)<=u};g.$observe("max",function(a){u=s(a);h.$validate()})}}}function Id(b,a,c,d){(d.$$hasNativeValidators=H(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?t:b})}function Jd(b,a,c,d,e){if(w(d)){b=b(d);if(!b.constant)throw J("ngModel")("constexpr",c,d);return b(a)}return e}function lc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e= +a[d],n=0;n<b.length;n++)if(e==b[n])continue a;c.push(e)}return c}function e(a){var b=[];return G(a)?(m(a,function(a){b=b.concat(e(a))}),b):L(a)?a.split(" "):H(a)?(m(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",link:function(f,g,h){function l(a,b){var c=g.data("$classCounts")||ga(),d=[];m(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!n){var m= +l(k,1);h.$addClass(m)}else if(!ka(b,n)){var q=e(n),m=d(k,q),k=d(q,k),m=l(m,1),k=l(k,-1);m&&m.length&&c.addClass(g,m);k&&k.length&&c.removeClass(g,k)}}n=ia(b)}var n;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function Hd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)} +function c(b,c){b=b?"-"+Bc(b,"-"):"";a(mb+b,!0===c);a(Kd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[Kd]=!(f[mb]=e.hasClass(mb));d.$setValidity=function(b,e,f){e===t?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&&h(d.$pending,b,f),Ld(d.$pending)&&(d.$pending=t));ab(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(Md,!0),d.$valid=d.$invalid=t,c("",null)):(a(Md, +!1),d.$valid=Ld(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?t:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function Ld(b){if(b)for(var a in b)if(b.hasOwnProperty(a))return!1;return!0}var jg=/^\/(.+)\/([a-z]*)$/,M=function(b){return L(b)?b.toLowerCase():b},Xa=Object.prototype.hasOwnProperty,rb=function(b){return L(b)?b.toUpperCase():b},Ua,y,la,za=[].slice,Mf=[].splice,kg=[].push,sa=Object.prototype.toString,sc=Object.getPrototypeOf,Fa=J("ng"),ca= +O.angular||(O.angular={}),gb,nb=0;Ua=U.documentMode;v.$inject=[];Ya.$inject=[];var G=Array.isArray,uc=/^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/,R=function(b){return L(b)?b.trim():b},ud=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},fb=function(){if(w(fb.isActive_))return fb.isActive_;var b=!(!U.querySelector("[ng-csp]")&&!U.querySelector("[data-ng-csp]"));if(!b)try{new Function("")}catch(a){b=!0}return fb.isActive_= +b},pb=function(){if(w(pb.name_))return pb.name_;var b,a,c=Oa.length,d,e;for(a=0;a<c;++a)if(d=Oa[a],b=U.querySelector("["+d.replace(":","\\:")+"jq]")){e=b.getAttribute(d+"jq");break}return pb.name_=e},Oa=["ng-","data-ng-","ng:","x-ng-"],be=/[A-Z]/g,Cc=!1,Rb,qa=1,Na=3,fe={full:"1.4.3",major:1,minor:4,dot:3,codeName:"foam-acceleration"};Q.expando="ng339";var ib=Q.cache={},Df=1;Q._data=function(b){return this.cache[b[this.expando]]||{}};var yf=/([\:\-\_]+(.))/g,zf=/^moz([A-Z])/,lg={mouseleave:"mouseout", +mouseenter:"mouseover"},Ub=J("jqLite"),Cf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,Af=/<([\w:]+)/,Bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,na={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};na.optgroup=na.option;na.tbody=na.tfoot=na.colgroup=na.caption=na.thead; +na.th=na.td;var Pa=Q.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===U.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),Q(O).on("load",a))},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?y(this[b]):y(this[this.length+b])},length:0,push:kg,sort:[].sort,splice:[].splice},Ab={};m("multiple selected checked disabled readOnly required open".split(" "),function(b){Ab[M(b)]=b});var Tc={};m("input select option textarea button form details".split(" "), +function(b){Tc[b]=!0});var Uc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};m({data:Wb,removeData:ub,hasData:function(b){for(var a in ib[b.ng339])return!0;return!1}},function(b,a){Q[a]=b});m({data:Wb,inheritedData:zb,scope:function(b){return y.data(b,"$scope")||zb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return y.data(b,"$isolateScope")||y.data(b,"$isolateScopeNoTemplate")},controller:Qc,injector:function(b){return zb(b, +"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:wb,css:function(b,a,c){a=hb(a);if(w(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==Na&&2!==d&&8!==d)if(d=M(a),Ab[d])if(w(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||v).specified?d:t;else if(w(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(w(c))b[a]=c;else return b[a]}, +text:function(){function b(a,b){if(A(b)){var d=a.nodeType;return d===qa||d===Na?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(A(a)){if(b.multiple&&"select"===ta(b)){var c=[];m(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(A(a))return b.innerHTML;tb(b,!0);b.innerHTML=a},empty:Rc},function(b,a){Q.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Rc&&(2==b.length&&b!==wb&&b!==Qc? +a:d)===t){if(H(a)){for(e=0;e<g;e++)if(b===Wb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===t?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}});m({removeData:ub,on:function a(c,d,e,f){if(w(f))throw Ub("onargs");if(Mc(c)){var g=vb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=Gf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"=== +d?a(c,lg[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Pc,one:function(a,c,d){a=y(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c,d)},replaceWith:function(a,c){var d,e=a.parentNode;tb(a);m(new Q(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];m(a.childNodes,function(a){a.nodeType===qa&&c.push(a)});return c},contents:function(a){return a.contentDocument|| +a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===qa||11===d){c=new Q(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===qa){var d=a.firstChild;m(new Q(c),function(c){a.insertBefore(c,d)})}},wrap:function(a,c){c=y(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Xb,detach:function(a){Xb(a,!0)},after:function(a,c){var d=a,e=a.parentNode;c=new Q(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h, +d.nextSibling);d=h}},addClass:yb,removeClass:xb,toggleClass:function(a,c,d){c&&m(c.split(" "),function(c){var f=d;A(f)&&(f=!wb(a,c));(f?yb:xb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Vb,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=vb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0=== +this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:v,type:g,target:a},c.type&&(e=P(e,c)),c=ia(h),f=d?[e].concat(d):[e],m(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){Q.prototype[c]=function(c,e,f){for(var g,h=0,l=this.length;h<l;h++)A(g)?(g=a(this[h],c,e,f),w(g)&&(g=y(g))):Oc(g,a(this[h],c,e,f));return w(g)?g:this};Q.prototype.bind= +Q.prototype.on;Q.prototype.unbind=Q.prototype.off});Sa.prototype={put:function(a,c){this[Ga(a,this.nextUid)]=c},get:function(a){return this[Ga(a,this.nextUid)]},remove:function(a){var c=this[a=Ga(a,this.nextUid)];delete this[a];return c}};var wf=[function(){this.$get=[function(){return Sa}]}],Wc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,mg=/,/,ng=/^\s*(_?)(\S+?)\1\s*$/,Vc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ha=J("$injector");eb.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e= +[];if(a.length){if(c)throw L(d)&&d||(d=a.name||Hf(a)),Ha("strictdi",d);c=a.toString().replace(Vc,"");c=c.match(Wc);m(c[1].split(mg),function(a){a.replace(ng,function(a,c,d){e.push(d)})})}a.$inject=e}}else G(a)?(c=a.length-1,Qa(a[c],"fn"),e=a.slice(0,c)):Qa(a,"fn",!0);return e};var Nd=J("$animate"),Ue=function(){this.$get=["$q","$$rAF",function(a,c){function d(){}d.all=v;d.chain=v;d.prototype={end:v,cancel:v,resume:v,pause:v,complete:v,then:function(d,f){return a(function(a){c(function(){a()})}).then(d, +f)}};return d}]},Te=function(){var a=new Sa,c=[];this.$get=["$$AnimateRunner","$rootScope",function(d,e){function f(d,f,l){var k=a.get(d);k||(a.put(d,k={}),c.push(d));f&&m(f.split(" "),function(a){a&&(k[a]=!0)});l&&m(l.split(" "),function(a){a&&(k[a]=!1)});1<c.length||e.$$postDigest(function(){m(c,function(c){var d=a.get(c);if(d){var e=If(c.attr("class")),f="",g="";m(d,function(a,c){a!==!!e[c]&&(a?f+=(f.length?" ":"")+c:g+=(g.length?" ":"")+c)});m(c,function(a){f&&yb(a,f);g&&xb(a,g)});a.remove(c)}}); +c.length=0})}return{enabled:v,on:v,off:v,pin:v,push:function(a,c,e,k){k&&k();e=e||{};e.from&&a.css(e.from);e.to&&a.css(e.to);(e.addClass||e.removeClass)&&f(a,e.addClass,e.removeClass);return new d}}}]},Se=["$provide",function(a){var c=this;this.$$registeredAnimations=Object.create(null);this.register=function(d,e){if(d&&"."!==d.charAt(0))throw Nd("notcsel",d);var f=d+"-animation";c.$$registeredAnimations[d.substr(1)]=f;a.factory(f,e)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter= +a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Nd("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function c(a,d,e){if(e){var l;a:{for(l=0;l<e.length;l++){var k=e[l];if(1===k.nodeType){l=k;break a}}l=void 0}!l||l.parentNode||l.previousElementSibling||(e=null)}e?e.after(a):d.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(f,g,h,l){g= +g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"enter",Ia(l))},move:function(f,g,h,l){g=g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"move",Ia(l))},leave:function(c,e){return a.push(c,"leave",Ia(e),function(){c.remove()})},addClass:function(c,e,h){h=Ia(h);h.addClass=jb(h.addclass,e);return a.push(c,"addClass",h)},removeClass:function(c,e,h){h=Ia(h);h.removeClass=jb(h.removeClass,e);return a.push(c,"removeClass",h)},setClass:function(c,e,h,l){l=Ia(l);l.addClass=jb(l.addClass, +e);l.removeClass=jb(l.removeClass,h);return a.push(c,"setClass",l)},animate:function(c,e,h,l,k){k=Ia(k);k.from=k.from?P(k.from,e):e;k.to=k.to?P(k.to,h):h;k.tempClasses=jb(k.tempClasses,l||"ng-inline-animate");return a.push(c,"animate",k)}}}]}],ea=J("$compile");Ec.$inject=["$provide","$$sanitizeUriProvider"];var Zc=/^((?:x|data)[\:\-_])/i,Nf=J("$controller"),Xc=/^(\S+)(\s+as\s+(\w+))?$/,cd="application/json",ac={"Content-Type":cd+";charset=utf-8"},Pf=/^\[|^\{(?!\{)/,Qf={"[":/]$/,"{":/}$/},Of=/^\)\]\}',?\n/, +Ka=ca.$interpolateMinErr=J("$interpolate");Ka.throwNoconcat=function(a){throw Ka("noconcat",a);};Ka.interr=function(a,c){return Ka("interr",a,c.toString())};var og=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,Tf={http:80,https:443,ftp:21},Cb=J("$location"),pg={$$html5:!1,$$replace:!1,absUrl:Db("$$absUrl"),url:function(a){if(A(a))return this.$$url;var c=og.exec(a);(c[1]||""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Db("$$protocol"), +host:Db("$$host"),port:Db("$$port"),path:kd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(L(a)||V(a))a=a.toString(),this.$$search=zc(a);else if(H(a))a=fa(a,{}),m(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Cb("isrcharg");break;default:A(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:kd("$$hash",function(a){return null!== +a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};m([jd,ec,dc],function(a){a.prototype=Object.create(pg);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==dc||!this.$$html5)throw Cb("nostate");this.$$state=A(c)?null:c;return this}});var da=J("$parse"),Uf=Function.prototype.call,Vf=Function.prototype.apply,Wf=Function.prototype.bind,Mb=ga();m("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Mb[a]=!0});var qg={n:"\n",f:"\f",r:"\r", +t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++; +else{var c=a+this.peek(),d=c+this.peek(2),e=Mb[c],f=Mb[d];Mb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a|| +"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=w(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw da("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=M(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var e=this.peek(); +if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&!this.isNumber(c))break;this.index++}this.tokens.push({index:a, +text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+=4,d+=String.fromCharCode(parseInt(f,16))):d+=qg[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===a){this.index++;this.tokens.push({index:c,text:e,constant:!0, +value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var q=function(a,c){this.lexer=a;this.options=c};q.Program="Program";q.ExpressionStatement="ExpressionStatement";q.AssignmentExpression="AssignmentExpression";q.ConditionalExpression="ConditionalExpression";q.LogicalExpression="LogicalExpression";q.BinaryExpression="BinaryExpression";q.UnaryExpression="UnaryExpression";q.CallExpression="CallExpression";q.MemberExpression="MemberExpression";q.Identifier="Identifier";q.Literal= +"Literal";q.ArrayExpression="ArrayExpression";q.Property="Property";q.ObjectExpression="ObjectExpression";q.ThisExpression="ThisExpression";q.NGValueParameter="NGValueParameter";q.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:q.Program, +body:a}},expressionStatement:function(){return{type:q.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:q.AssignmentExpression,left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),c,d;return this.expect("?")&&(c=this.expression(),this.consume(":"))? +(d=this.expression(),{type:q.ConditionalExpression,test:a,alternate:c,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:q.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:q.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a={type:q.BinaryExpression, +operator:c.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:q.BinaryExpression,operator:c.text, +left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:q.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=fa(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant(): +this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:q.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===c.text?(a={type:q.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===c.text?a={type:q.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:q.CallExpression,callee:this.identifier(), +arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:q.Identifier,name:a.text}},constant:function(){return{type:q.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break; +a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:q.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;c={type:q.Property,kind:"init"};this.peek().constant?c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:q.ObjectExpression,properties:a}}, +throwError:function(a,c){throw da("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw da("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw da("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a]; +var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:q.Literal,value:!0},"false":{type:q.Literal,value:!1},"null":{type:q.Literal,value:null},undefined:{type:q.Literal,value:t},"this":{type:q.ThisExpression}}};rd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[], +body:[],own:{}},inputs:[]};T(e,d.$filter);var f="",g;this.stage="assign";if(g=pd(e))this.state.computing="assign",f=this.nextId(),this.recurse(g,f),f="fn.assign="+this.generateFunction("assign","s,v,l");g=nd(e.body);d.stage="inputs";m(g,function(a,c){var e="fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+ +"var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","ifDefined","plus","text",f))(this.$filter,Ca,oa,ld,Xf,md,a);this.state=this.stage=t;f.literal=qd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;m(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")}, +generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],c=this;m(this.state.filters,function(d,e){a.push(d+"=$filter("+c.escape(e)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,g){var h,l,k=this,n,r;e=e||v;if(!g&&w(a.watchId))c=c||this.nextId(),this.if_("i", +this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case q.Program:m(a.body,function(c,d){k.recurse(c.expression,t,t,function(a){l=a});d!==a.body.length-1?k.current().body.push(l,";"):k.return_(l)});break;case q.Literal:r=this.escape(a.value);this.assign(c,r);e(r);break;case q.UnaryExpression:this.recurse(a.argument,t,t,function(a){l=a});r=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,r);e(r);break;case q.BinaryExpression:this.recurse(a.left, +t,t,function(a){h=a});this.recurse(a.right,t,t,function(a){l=a});r="+"===a.operator?this.plus(h,l):"-"===a.operator?this.ifDefined(h,0)+a.operator+this.ifDefined(l,0):"("+h+")"+a.operator+"("+l+")";this.assign(c,r);e(r);break;case q.LogicalExpression:c=c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case q.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c); +break;case q.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Ca(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l", +a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case q.MemberExpression:h=d&&(d.context=this.nextId())||this.nextId();c=c||this.nextId();k.recurse(a.object,h,t,function(){k.if_(k.notNull(h),function(){if(a.computed)l=k.nextId(),k.recurse(a.property,l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(h,l)),k.lazyAssign(k.computedMember(h,l),"{}")),r=k.ensureSafeObject(k.computedMember(h,l)),k.assign(c,r),d&&(d.computed=!0,d.name=l);else{Ca(a.property.name); +f&&1!==f&&k.if_(k.not(k.nonComputedMember(h,a.property.name)),k.lazyAssign(k.nonComputedMember(h,a.property.name),"{}"));r=k.nonComputedMember(h,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))r=k.ensureSafeObject(r);k.assign(c,r);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(c,"undefined")});e(c)},!!f);break;case q.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),n=[],m(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);n.push(c)}),r=l+ +"("+n.join(",")+")",k.assign(c,r),e(c)):(l=k.nextId(),h={},n=[],k.recurse(a.callee,l,h,function(){k.if_(k.notNull(l),function(){k.addEnsureSafeFunction(l);m(a.arguments,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(k.ensureSafeObject(a))})});h.name?(k.state.expensiveChecks||k.addEnsureSafeObject(h.context),r=k.member(h.context,h.name,h.computed)+"("+n.join(",")+")"):r=l+"("+n.join(",")+")";r=k.ensureSafeObject(r);k.assign(c,r)},function(){k.assign(c,"undefined")});e(c)}));break;case q.AssignmentExpression:l= +this.nextId();h={};if(!od(a.left))throw da("lval");this.recurse(a.left,t,h,function(){k.if_(k.notNull(h.context),function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(h.context,h.name,h.computed));r=k.member(h.context,h.name,h.computed)+a.operator+l;k.assign(c,r);e(c||r)})},1);break;case q.ArrayExpression:n=[];m(a.elements,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(a)})});r="["+n.join(",")+"]";this.assign(c,r);e(r);break;case q.ObjectExpression:n=[];m(a.properties,function(a){k.recurse(a.value, +k.nextId(),t,function(c){n.push(k.escape(a.key.type===q.Identifier?a.key.name:""+a.key.value)+":"+c)})});r="{"+n.join(",")+"}";this.assign(c,r);e(r);break;case q.ThisExpression:this.assign(c,"s");e("s");break;case q.NGValueParameter:this.assign(c,"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)|| +(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+a+","+c+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+ +"."+c},computedMember:function(a,c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+ +a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},lazyRecurse:function(a,c,d,e,f,g){var h=this;return function(){h.recurse(a,c,d,e,f,g)}},lazyAssign:function(a,c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(L(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true"; +if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw da("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}};sd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;T(e,d.$filter);var f,g;if(f=pd(e))g=this.recurse(f);f=nd(e.body);var h;f&&(h=[],m(f,function(a,c){var e=d.recurse(a); +a.input=e;h.push(e);a.watchId=c}));var l=[];m(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;m(l,function(e){d=e(a,c)});return d};g&&(f.assign=function(a,c,d){return g(a,d,c)});h&&(f.inputs=h);f.literal=qd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,g=this,h;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case q.Literal:return this.value(a.value,c);case q.UnaryExpression:return f= +this.recurse(a.argument),this["unary"+a.operator](f,c);case q.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.LogicalExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case q.Identifier:return Ca(a.name,g.expression),g.identifier(a.name,g.expensiveChecks||Fb(a.name), +c,d,g.expression);case q.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Ca(a.property.name,g.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed?this.computedMember(e,f,c,d,g.expression):this.nonComputedMember(e,f,g.expensiveChecks,c,d,g.expression);case q.CallExpression:return h=[],m(a.arguments,function(a){h.push(g.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,g){for(var m= +[],q=0;q<h.length;++q)m.push(h[q](a,d,e,g));a=f.apply(t,m,g);return c?{context:t,name:t,value:a}:a}:function(a,d,e,r){var m=f(a,d,e,r),q;if(null!=m.value){oa(m.context,g.expression);ld(m.value,g.expression);q=[];for(var t=0;t<h.length;++t)q.push(oa(h[t](a,d,e,r),g.expression));q=oa(m.value.apply(m.context,q),g.expression)}return c?{value:q}:q};case q.AssignmentExpression:return e=this.recurse(a.left,!0,1),f=this.recurse(a.right),function(a,d,h,r){var m=e(a,d,h,r);a=f(a,d,h,r);oa(m.value,g.expression); +m.context[m.name]=a;return c?{value:a}:a};case q.ArrayExpression:return h=[],m(a.elements,function(a){h.push(g.recurse(a))}),function(a,d,e,f){for(var g=[],m=0;m<h.length;++m)g.push(h[m](a,d,e,f));return c?{value:g}:g};case q.ObjectExpression:return h=[],m(a.properties,function(a){h.push({key:a.key.type===q.Identifier?a.key.name:""+a.key.value,value:g.recurse(a.value)})}),function(a,d,e,f){for(var g={},m=0;m<h.length;++m)g[h[m].key]=h[m].value(a,d,e,f);return c?{value:g}:g};case q.ThisExpression:return function(a){return c? +{value:a}:a};case q.NGValueParameter:return function(a,d,e,f){return c?{value:e}:e}}},"unary+":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?+d:0;return c?{value:d}:d}},"unary-":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?-d:0;return c?{value:d}:d}},"unary!":function(a,c){return function(d,e,f,g){d=!a(d,e,f,g);return c?{value:d}:d}},"binary+":function(a,c,d){return function(e,f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=md(l,e);return d?{value:l}:l}},"binary-":function(a,c,d){return function(e, +f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=(w(l)?l:0)-(w(e)?e:0);return d?{value:l}:l}},"binary*":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)*c(e,f,g,h);return d?{value:e}:e}},"binary/":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)/c(e,f,g,h);return d?{value:e}:e}},"binary%":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)%c(e,f,g,h);return d?{value:e}:e}},"binary===":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)===c(e,f,g,h);return d?{value:e}:e}},"binary!==":function(a, +c,d){return function(e,f,g,h){e=a(e,f,g,h)!==c(e,f,g,h);return d?{value:e}:e}},"binary==":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)==c(e,f,g,h);return d?{value:e}:e}},"binary!=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)!=c(e,f,g,h);return d?{value:e}:e}},"binary<":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)<c(e,f,g,h);return d?{value:e}:e}},"binary>":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>c(e,f,g,h);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e, +f,g,h){e=a(e,f,g,h)<=c(e,f,g,h);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>=c(e,f,g,h);return d?{value:e}:e}},"binary&&":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)&&c(e,f,g,h);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)||c(e,f,g,h);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,g,h,l){f=a(f,g,h,l)?c(f,g,h,l):d(f,g,h,l);return e?{value:f}:f}},value:function(a,c){return function(){return c? +{context:t,name:t,value:a}:a}},identifier:function(a,c,d,e,f){return function(g,h,l,k){g=h&&a in h?h:g;e&&1!==e&&g&&!g[a]&&(g[a]={});h=g?g[a]:t;c&&oa(h,f);return d?{context:g,name:a,value:h}:h}},computedMember:function(a,c,d,e,f){return function(g,h,l,k){var n=a(g,h,l,k),m,s;null!=n&&(m=c(g,h,l,k),Ca(m,f),e&&1!==e&&n&&!n[m]&&(n[m]={}),s=n[m],oa(s,f));return d?{context:n,name:m,value:s}:s}},nonComputedMember:function(a,c,d,e,f,g){return function(h,l,k,n){h=a(h,l,k,n);f&&1!==f&&h&&!h[c]&&(h[c]={}); +l=null!=h?h[c]:t;(d||Fb(c))&&oa(l,g);return e?{context:h,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,g){return g?g[c]:a(d,e,f)}}};var hc=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d;this.ast=new q(this.lexer);this.astCompiler=d.csp?new sd(this.ast,c):new rd(this.ast,c)};hc.prototype={constructor:hc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};ga();ga();var Yf=Object.prototype.valueOf,Da=J("$sce"),pa={HTML:"html",CSS:"css",URL:"url", +RESOURCE_URL:"resourceUrl",JS:"js"},ea=J("$compile"),X=U.createElement("a"),wd=Ba(O.location.href);xd.$inject=["$document"];Lc.$inject=["$provide"];yd.$inject=["$locale"];Ad.$inject=["$locale"];var Dd=".",hg={yyyy:Y("FullYear",4),yy:Y("FullYear",2,0,!0),y:Y("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:Y("Month",2,1),M:Y("Month",1,1),dd:Y("Date",2),d:Y("Date",1),HH:Y("Hours",2),H:Y("Hours",1),hh:Y("Hours",2,-12),h:Y("Hours",1,-12),mm:Y("Minutes",2),m:Y("Minutes",1),ss:Y("Seconds",2),s:Y("Seconds", +1),sss:Y("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a,c,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0<a?"floor":"ceil"](a/60),2)+Gb(Math.abs(a%60),2))},ww:Fd(2),w:Fd(1),G:jc,GG:jc,GGG:jc,GGGG:function(a,c){return 0>=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},gg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,fg=/^\-?\d+$/;zd.$inject=["$locale"];var cg=ra(M),dg=ra(rb);Bd.$inject= +["$parse"];var ie=ra({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===sa.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),sb={};m(Ab,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=wa("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});sb[e]=function(){return{restrict:"A", +priority:100,link:f}}}});m(Uc,function(a,c){sb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(jg))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});m(["src","srcset","href"],function(a){var c=wa("ng-"+a);sb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===sa.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href", +g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ua&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Ib={$addControl:v,$$renameControl:function(a,c){a.$name=c},$removeControl:v,$setValidity:v,$setDirty:v,$setPristine:v,$setSubmitted:v};Gd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Od=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Gd,compile:function(d,e){d.addClass(Va).addClass(mb);var f=e.name?"name":a&&e.ngForm?"ngForm": +!1;return{pre:function(a,d,e,k){if(!("action"in e)){var n=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",n,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",n,!1)},0,!1)})}var m=k.$$parentForm;f&&(Eb(a,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(Eb(a,k.$name,t,k.$name),m.$$renameControl(k,c),Eb(a,k.$name,k,k.$name))}));d.on("$destroy",function(){m.$removeControl(k);f&&Eb(a,e[f],t, +k.$name);P(k,Ib)})}}}}}]},je=Od(),we=Od(!0),ig=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,rg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,sg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,tg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Pd=/^(\d{4})-(\d{2})-(\d{2})$/,Qd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Rd=/^(\d{4})-(\d\d)$/, +Sd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Td={text:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e)},date:lb("date",Pd,Kb(Pd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":lb("datetimelocal",Qd,Kb(Qd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:lb("time",Sd,Kb(Sd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:lb("week",mc,function(a,c){if(aa(a))return a;if(L(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=Ed(e),f=7*(f-1);c&&(d=c.getHours(),g= +c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:lb("month",Rd,Kb(Rd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){Id(a,c,d,e);kb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:tg.test(a)?parseFloat(a):t});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Lb("numfmt",a);a=a.toString()}return a});if(w(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)|| +A(h)||a>=h};d.$observe("min",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(w(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||A(l)||a<=l};d.$observe("max",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||rg.test(d)}},email:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e); +e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||sg.test(d)}},radio:function(a,c,d,e){A(d.name)&&c.attr("name",++nb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=Jd(l,a,"ngTrueValue",d.ngTrueValue,!0),n=Jd(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&& +a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a,k)});e.$parsers.push(function(a){return a?k:n})},hidden:v,button:v,submit:v,reset:v,file:v},Fc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Td[M(h.type)]||Td.text)(f,g,h,l[0],c,a,d,e)}}}}],ug=/^(true|false|\d+)$/,Oe=function(){return{restrict:"A",priority:100,compile:function(a, +c){return ug.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},oe=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],qe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate)); +c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===t?"":a})}}}}],pe=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],Ne=ra({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}), +re=lc("",!0),te=lc("Odd",0),se=lc("Even",1),ue=Ma({compile:function(a,c){c.$set("ngCloak",t);a.removeClass("ng-cloak")}}),ve=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Kc={},vg={blur:!0,focus:!0};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=wa("ng-"+a);Kc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h= +d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};vg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ye=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=U.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k= +qb(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],ze=["$templateRequest","$anchorScroll","$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(e,f){var g=f.ngInclude||f.src,h=f.onload||"",l=f.autoscroll;return function(e,f,m,s,q){var t=0,F,u,p,v=function(){u&&(u.remove(),u=null);F&&(F.$destroy(),F=null);p&&(d.leave(p).then(function(){u=null}),u=p,p=null)};e.$watch(g,function(g){var m=function(){!w(l)||l&&!e.$eval(l)|| +c()},r=++t;g?(a(g,!0).then(function(a){if(r===t){var c=e.$new();s.template=a;a=q(c,function(a){v();d.enter(a,null,f).then(m)});F=c;p=a;F.$emit("$includeContentLoaded",g);e.$eval(h)}},function(){r===t&&(v(),e.$emit("$includeContentError",g))}),e.$emit("$includeContentRequested",g)):(v(),s.template=null)})}}}}],Qe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Nc(f.template,U).childNodes)(c,function(a){d.append(a)}, +{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],Ae=Ma({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Me=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?R(f):f;e.$parsers.push(function(a){if(!A(a)){var c=[];a&&m(a.split(h),function(a){a&&c.push(g?R(a):a)});return c}});e.$formatters.push(function(a){return G(a)?a.join(f):t});e.$isEmpty=function(a){return!a|| +!a.length}}}},mb="ng-valid",Kd="ng-invalid",Va="ng-pristine",Jb="ng-dirty",Md="ng-pending",Lb=new J("ngModel"),wg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty= +!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=t;this.$name=n(d.name||"",!1)(a);var r=f(d.ngModel),s=r.assign,q=r,C=s,F=null,u,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");q=function(a){var d=r(a);z(d)&&(d=c(a));return d};C=function(a,c){z(r(a))?g(a,{$$$p:p.$modelValue}):s(a,p.$modelValue)}}else if(!r.assign)throw Lb("nonassign",d.ngModel,ua(e));};this.$render=v;this.$isEmpty=function(a){return A(a)|| +""===a||null===a||a!==a};var K=e.inheritedData("$formController")||Ib,y=0;Hd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:K,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Jb);g.addClass(e,Va)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Va);g.addClass(e,Jb);K.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched= +function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(F);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:t,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators= +function(a,c,d){function e(){var d=!0;m(p.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(m(p.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;m(p.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!z(k.then))throw Lb("$asyncValidators",k);g(h,t);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},v):h(!0)}function g(a,c){l===y&&p.$setValidity(a,c)}function h(a){l===y&&d(a)}y++;var l=y;(function(){var a= +p.$$parserName||"parse";if(u===t)g(a,null);else return u||(m(p.$validators,function(a,c){g(c,null)}),m(p.$asyncValidators,function(a,c){g(c,null)})),g(a,u),u;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(F);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue;if(u=A(c)?t:!0)for(var d= +0;d<p.$parsers.length;d++)if(c=p.$parsers[d](c),A(c)){u=!1;break}V(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=q(a));var e=p.$modelValue,f=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=c;f&&(p.$modelValue=c,p.$modelValue!==e&&p.$$writeModelToScope());p.$$runValidators(c,p.$$lastCommittedViewValue,function(a){f||(p.$modelValue=a?c:t,p.$modelValue!==e&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){C(a,p.$modelValue);m(p.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})}; +this.$setViewValue=function(a,c){p.$viewValue=a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=p.$options;e&&w(e.debounce)&&(e=e.debounce,V(e)?d=e:V(e[c])?d=e[c]:V(e["default"])&&(d=e["default"]));h.cancel(F);d?F=h(function(){p.$commitViewValue()},d):l.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var c=q(a);if(c!==p.$modelValue&&(p.$modelValue===p.$modelValue||c===c)){p.$modelValue= +p.$$rawModelValue=c;u=t;for(var d=p.$formatters,e=d.length,f=c;e--;)f=d[e](f);p.$viewValue!==f&&(p.$viewValue=p.$$lastCommittedViewValue=f,p.$render(),p.$$runValidators(c,f,v))}return c})}],Le=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:wg,priority:1,compile:function(c){c.addClass(Va).addClass("ng-untouched").addClass(mb);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Ib;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name", +function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy",function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],xg=/(\s+|^)default(\s+|$)/,Pe=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=fa(a.$eval(c.ngModelOptions)); +this.$options.updateOn!==t?(this.$options.updateOnDefault=!1,this.$options.updateOn=R(this.$options.updateOn.replace(xg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},Be=Ma({terminal:!0,priority:1E3}),yg=J("ngOptions"),zg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/, +Je=["$compile","$parse",function(a,c){function d(a,d,e){function f(a,c,d,e,g){this.selectValue=a;this.viewValue=c;this.label=d;this.group=e;this.disabled=g}function n(a){var c;if(!q&&Ea(a))c=a;else{c=[];for(var d in a)a.hasOwnProperty(d)&&"$"!==d.charAt(0)&&c.push(d)}return c}var m=a.match(zg);if(!m)throw yg("iexp",a,ua(d));var s=m[5]||m[7],q=m[6];a=/ as /.test(m[0])&&m[1];var t=m[9];d=c(m[2]?m[1]:s);var v=a&&c(a)||d,u=t&&c(t),p=t?function(a,c){return u(e,c)}:function(a){return Ga(a)},w=function(a, +c){return p(a,z(a,c))},y=c(m[2]||m[1]),A=c(m[3]||""),B=c(m[4]||""),N=c(m[8]),D={},z=q?function(a,c){D[q]=c;D[s]=a;return D}:function(a){D[s]=a;return D};return{trackBy:t,getTrackByValue:w,getWatchables:c(N,function(a){var c=[];a=a||[];for(var d=n(a),f=d.length,g=0;g<f;g++){var h=a===d?g:d[g],k=z(a[h],h),h=p(a[h],k);c.push(h);if(m[2]||m[1])h=y(e,k),c.push(h);m[4]&&(k=B(e,k),c.push(k))}return c}),getOptions:function(){for(var a=[],c={},d=N(e)||[],g=n(d),h=g.length,m=0;m<h;m++){var r=d===g?m:g[m],s= +z(d[r],r),q=v(e,s),r=p(q,s),u=y(e,s),x=A(e,s),s=B(e,s),q=new f(r,q,u,x,s);a.push(q);c[r]=q}return{items:a,selectValueMap:c,getOptionFromViewValue:function(a){return c[w(a)]},getViewValueFromOption:function(a){return t?ca.copy(a.viewValue):a.viewValue}}}}}var e=U.createElement("option"),f=U.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","?ngModel"],link:function(c,h,l,k){function n(a,c){a.element=c;c.disabled=a.disabled;a.value!==c.value&&(c.value=a.selectValue);a.label!== +c.label&&(c.label=a.label,c.textContent=a.label)}function r(a,c,d,e){c&&M(c.nodeName)===d?d=c:(d=e.cloneNode(!1),c?a.insertBefore(d,c):a.appendChild(d));return d}function s(a){for(var c;a;)c=a.nextSibling,Xb(a),a=c}function q(a){var c=p&&p[0],d=N&&N[0];if(c||d)for(;a&&(a===c||a===d);)a=a.nextSibling;return a}function t(){var a=D&&u.readValue();D=z.getOptions();var c={},d=h[0].firstChild;B&&h.prepend(p);d=q(d);D.items.forEach(function(a){var g,k;a.group?(g=c[a.group],g||(g=r(h[0],d,"optgroup",f),d= +g.nextSibling,g.label=a.group,g=c[a.group]={groupElement:g,currentOptionElement:g.firstChild}),k=r(g.groupElement,g.currentOptionElement,"option",e),n(a,k),g.currentOptionElement=k.nextSibling):(k=r(h[0],d,"option",e),n(a,k),d=k.nextSibling)});Object.keys(c).forEach(function(a){s(c[a].currentOptionElement)});s(d);v.$render();if(!v.$isEmpty(a)){var g=u.readValue();(z.trackBy?ka(a,g):a===g)||(v.$setViewValue(g),v.$render())}}var v=k[1];if(v){var u=k[0];k=l.multiple;for(var p,w=0,A=h.children(),I=A.length;w< +I;w++)if(""===A[w].value){p=A.eq(w);break}var B=!!p,N=y(e.cloneNode(!1));N.val("?");var D,z=d(l.ngOptions,h,c);k?(v.$isEmpty=function(a){return!a||0===a.length},u.writeValue=function(a){D.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){(a=D.getOptionFromViewValue(a))&&!a.disabled&&(a.element.selected=!0)})},u.readValue=function(){var a=h.val()||[],c=[];m(a,function(a){a=D.selectValueMap[a];a.disabled||c.push(D.getViewValueFromOption(a))});return c},z.trackBy&&c.$watchCollection(function(){if(G(v.$viewValue))return v.$viewValue.map(function(a){return z.getTrackByValue(a)})}, +function(){v.$render()})):(u.writeValue=function(a){var c=D.getOptionFromViewValue(a);c&&!c.disabled?h[0].value!==c.selectValue&&(N.remove(),B||p.remove(),h[0].value=c.selectValue,c.element.selected=!0,c.element.setAttribute("selected","selected")):null===a||B?(N.remove(),B||h.prepend(p),h.val(""),p.prop("selected",!0),p.attr("selected",!0)):(B||p.remove(),h.prepend(N),h.val("?"),N.prop("selected",!0),N.attr("selected",!0))},u.readValue=function(){var a=D.selectValueMap[h.val()];return a&&!a.disabled? +(B||p.remove(),N.remove(),D.getViewValueFromOption(a)):null},z.trackBy&&c.$watch(function(){return z.getTrackByValue(v.$viewValue)},function(){v.$render()}));B?(p.remove(),a(p)(c),p.removeClass("ng-scope")):p=y(e.cloneNode(!1));t();c.$watchCollection(z.getWatchables,t)}}}}],Ce=["$locale","$interpolate","$log",function(a,c,d){var e=/{}/g,f=/^when(Minus)?(.+)$/;return{link:function(g,h,l){function k(a){h.text(a||"")}var n=l.count,r=l.$attr.when&&h.attr(l.$attr.when),s=l.offset||0,q=g.$eval(r)||{},t= +{},w=c.startSymbol(),u=c.endSymbol(),p=w+n+"-"+s+u,y=ca.noop,z;m(l,function(a,c){var d=f.exec(c);d&&(d=(d[1]?"-":"")+M(d[2]),q[d]=h.attr(l.$attr[c]))});m(q,function(a,d){t[d]=c(a.replace(e,p))});g.$watch(n,function(c){var e=parseFloat(c),f=isNaN(e);f||e in q||(e=a.pluralCat(e-s));e===z||f&&V(z)&&isNaN(z)||(y(),f=t[e],A(f)?(null!=c&&d.debug("ngPluralize: no rule defined for '"+e+"' in "+r),y=v,k()):y=g.$watch(f,k),z=e)})}}}],De=["$parse","$animate",function(a,c){var d=J("ngRepeat"),e=function(a,c, +d,e,k,m,r){a[d]=e;k&&(a[k]=m);a.$index=c;a.$first=0===c;a.$last=c===r-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=U.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var n=k[1],r=k[2],s=k[3],q=k[4],k=n.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); +if(!k)throw d("iidexp",n);var v=k[3]||k[1],w=k[2];if(s&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(s)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(s)))throw d("badident",s);var u,p,z,A,I={$id:Ga};q?u=a(q):(z=function(a,c){return Ga(c)},A=function(a){return a});return function(a,f,g,k,n){u&&(p=function(c,d,e){w&&(I[w]=c);I[v]=d;I.$index=e;return u(a,I)});var q=ga();a.$watchCollection(r,function(g){var k,r,u=f[0],x,D=ga(),I,H,L,G,M,J,O;s&&(a[s]=g);if(Ea(g))M= +g,r=p||z;else for(O in r=p||A,M=[],g)g.hasOwnProperty(O)&&"$"!==O.charAt(0)&&M.push(O);I=M.length;O=Array(I);for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],G=r(H,L,k),q[G])J=q[G],delete q[G],D[G]=J,O[k]=J;else{if(D[G])throw m(O,function(a){a&&a.scope&&(q[a.id]=a)}),d("dupes",h,G,L);O[k]={id:G,scope:t,clone:t};D[G]=!0}for(x in q){J=q[x];G=qb(J.clone);c.leave(G);if(G[0].parentNode)for(k=0,r=G.length;k<r;k++)G[k].$$NG_REMOVED=!0;J.scope.$destroy()}for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],J=O[k],J.scope){x= +u;do x=x.nextSibling;while(x&&x.$$NG_REMOVED);J.clone[0]!=x&&c.move(qb(J.clone),null,y(u));u=J.clone[J.clone.length-1];e(J.scope,k,v,L,w,H,I)}else n(function(a,d){J.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a,null,y(u));u=f;J.clone=a;D[J.id]=J;e(J.scope,k,v,L,w,H,I)});q=D})}}}}],Ee=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],xe=["$animate", +function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Fe=Ma(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&m(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Ge=["$animate",function(a){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],n=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch|| +e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=0;for(e=k.length;d<e;++d){var q=qb(h[d].clone);k[d].$destroy();(l[d]=a.leave(q)).then(n(l,d))}h.length=0;k.length=0;(g=f.cases["!"+c]||f.cases["?"])&&m(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=U.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],He=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e, +f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,element:c})}}),Ie=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),Ke=Ma({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw J("ngTransclude")("orphan",ua(c));f(function(a){c.empty();c.append(a)})}}),ke=["$templateCache",function(a){return{restrict:"E",terminal:!0, +compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],Ag={$setViewValue:v,$render:v},Bg=["$element","$scope","$attrs",function(a,c,d){var e=this,f=new Sa;e.ngModelCtrl=Ag;e.unknownOption=y(U.createElement("option"));e.renderUnknownOption=function(c){c="? "+Ga(c)+" ?";e.unknownOption.val(c);a.prepend(e.unknownOption);a.val(c)};c.$on("$destroy",function(){e.renderUnknownOption=v});e.removeUnknownOption=function(){e.unknownOption.parent()&&e.unknownOption.remove()};e.readValue= +function(){e.removeUnknownOption();return a.val()};e.writeValue=function(c){e.hasOption(c)?(e.removeUnknownOption(),a.val(c),""===c&&e.emptyOption.prop("selected",!0)):null==c&&e.emptyOption?(e.removeUnknownOption(),a.val("")):e.renderUnknownOption(c)};e.addOption=function(a,c){Ra(a,'"option value"');""===a&&(e.emptyOption=c);var d=f.get(a)||0;f.put(a,d+1)};e.removeOption=function(a){var c=f.get(a);c&&(1===c?(f.remove(a),""===a&&(e.emptyOption=t)):f.put(a,c-1))};e.hasOption=function(a){return!!f.get(a)}}], +le=function(){return{restrict:"E",require:["select","?ngModel"],controller:Bg,link:function(a,c,d,e){var f=e[1];if(f){var g=e[0];g.ngModelCtrl=f;f.$render=function(){g.writeValue(f.$viewValue)};c.on("change",function(){a.$apply(function(){f.$setViewValue(g.readValue())})});if(d.multiple){g.readValue=function(){var a=[];m(c.find("option"),function(c){c.selected&&a.push(c.value)});return a};g.writeValue=function(a){var d=new Sa(a);m(c.find("option"),function(a){a.selected=w(d.get(a.value))})};var h, +l=NaN;a.$watch(function(){l!==f.$viewValue||ka(h,f.$viewValue)||(h=ia(f.$viewValue),f.$render());l=f.$viewValue});f.$isEmpty=function(a){return!a||0===a.length}}}}}},ne=["$interpolate",function(a){function c(a){a[0].hasAttribute("selected")&&(a[0].selected=!0)}return{restrict:"E",priority:100,compile:function(d,e){if(A(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),m=k.data("$selectController")||k.parent().data("$selectController");m&&m.ngModelCtrl&& +(f?a.$watch(f,function(a,f){e.$set("value",a);f!==a&&m.removeOption(f);m.addOption(a,d);m.ngModelCtrl.$render();c(d)}):(m.addOption(e.value,d),m.ngModelCtrl.$render(),c(d)),d.on("$destroy",function(){m.removeOption(e.value);m.ngModelCtrl.$render()}))}}}}],me=ra({restrict:"E",terminal:!1}),Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}}, +Gc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){L(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw J("ngPattern")("noregexp",g,a,ua(c));f=a||t;e.$validate()});e.$validators.pattern=function(a){return e.$isEmpty(a)||A(f)||f.test(a)}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=W(a);f=isNaN(a)?-1:a;e.$validate()}); +e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Ic=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=W(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};O.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(ce(),ee(ca),y(U).ready(function(){Zd(U,Ac)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); //# sourceMappingURL=angular.min.js.map diff --git a/www/lib/ionic/js/ionic-angular.js b/www/lib/ionic/js/ionic-angular.js index a47cd62791c9fa504be96a08016a3e8debc1c4c0..4146ce2c56c4d6a14b0cfdf4cfcf0dc5cbfdd03d 100644 --- a/www/lib/ionic/js/ionic-angular.js +++ b/www/lib/ionic/js/ionic-angular.js @@ -1,8 +1,8 @@ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -14,7 +14,7 @@ (function() { /* eslint no-unused-vars:0 */ -var IonicModule = angular.module('ionic', ['ngAnimate', 'ngSanitize', 'ui.router']), +var IonicModule = angular.module('ionic', ['ngAnimate', 'ngSanitize', 'ui.router', 'ngIOS9UIWebViewPatch']), extend = angular.extend, forEach = angular.forEach, isDefined = angular.isDefined, @@ -170,7 +170,7 @@ function($rootScope, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicP element.remove(); // scope.cancel.$scope is defined near the bottom scope.cancel.$scope = sheetEl = null; - (done || noop)(); + (done || noop)(opts.buttons); }); }; @@ -305,10 +305,14 @@ jqLite.prototype.removeClass = function(cssClasses) { * For example, if `retain` is called three times, the backdrop will be shown until `release` * is called three times. * + * **Notes:** + * - The backdrop service will broadcast 'backdrop.shown' and 'backdrop.hidden' events from the root scope, + * this is useful for alerting native components not in html. + * * @usage * * ```js - * function MyController($scope, $ionicBackdrop, $timeout) { + * function MyController($scope, $ionicBackdrop, $timeout, $rootScope) { * //Show a backdrop for one second * $scope.action = function() { * $ionicBackdrop.retain(); @@ -316,13 +320,24 @@ jqLite.prototype.removeClass = function(cssClasses) { * $ionicBackdrop.release(); * }, 1000); * }; + * + * // Execute action on backdrop disappearing + * $scope.$on('backdrop.hidden', function() { + * // Execute action + * }); + * + * // Execute action on backdrop appearing + * $scope.$on('backdrop.shown', function() { + * // Execute action + * }); + * * } * ``` */ IonicModule .factory('$ionicBackdrop', [ - '$document', '$timeout', '$$rAF', -function($document, $timeout, $$rAF) { + '$document', '$timeout', '$$rAF', '$rootScope', +function($document, $timeout, $$rAF, $rootScope) { var el = jqLite('<div class="backdrop">'); var backdropHolds = 0; @@ -354,6 +369,7 @@ function($document, $timeout, $$rAF) { backdropHolds++; if (backdropHolds === 1) { el.addClass('visible'); + $rootScope.$broadcast('backdrop.shown'); $$rAF(function() { // If we're still at >0 backdropHolds after async... if (backdropHolds >= 1) el.addClass('active'); @@ -363,6 +379,7 @@ function($document, $timeout, $$rAF) { function release() { if (backdropHolds === 1) { el.removeClass('active'); + $rootScope.$broadcast('backdrop.hidden'); $timeout(function() { // If we're still at 0 backdropHolds after async... if (backdropHolds === 0) el.removeClass('visible'); @@ -446,7 +463,7 @@ IonicModule return { /** * @ngdoc method - * @name $ionicBody#add + * @name $ionicBody#addClass * @description Add a class to the document's body element. * @param {string} class Each argument will be added to the body element. * @returns {$ionicBody} The $ionicBody service so methods can be chained. @@ -1251,11 +1268,12 @@ function($rootScope, $state, $location, $window, $timeout, $ionicViewSwitcher, $ /** * @ngdoc method * @name $ionicHistory#clearCache + * @return promise * @description Removes all cached views within every {@link ionic.directive:ionNavView}. * This both removes the view element from the DOM, and destroy it's scope. */ clearCache: function(stateIds) { - $timeout(function() { + return $timeout(function() { $ionicNavViewDelegate._instances.forEach(function(instance) { instance.clearCache(stateIds); }); @@ -1544,9 +1562,9 @@ function($rootScope, $state, $location, $document, $ionicPlatform, $ionicHistory /** * @ngdoc method * @name $ionicConfigProvider#scrolling.jsScrolling - * @description Whether to use JS or Native scrolling. Defaults to JS scrolling. Setting this to - * `false` has the same effect as setting each `ion-content` to have `overflow-scroll='true'`. - * @param {boolean} value Defaults to `true` + * @description Whether to use JS or Native scrolling. Defaults to native scrolling. Setting this to + * `true` has the same effect as setting each `ion-content` to have `overflow-scroll='false'`. + * @param {boolean} value Defaults to `false` as of Ionic 1.2 * @returns {boolean} */ @@ -1821,8 +1839,11 @@ IonicModule tabs: { style: 'striped', position: 'top' - } + }, + scrolling: { + jsScrolling: false + } }); // Windows Phone @@ -2104,8 +2125,8 @@ IonicModule // http://blogs.msdn.com/b/msdn_answers/archive/2015/02/10/ // running-cordova-apps-on-windows-and-windows-phone-8-1-using-ionic-angularjs-and-other-frameworks.aspx .config(['$compileProvider', function($compileProvider) { - $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|tel|ftp|mailto|file|ghttps?|ms-appx|x-wmapp0):/); - $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|x-wmapp0):|data:image\//); + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|sms|tel|geo|ftp|mailto|file|ghttps?|ms-appx-web|ms-appx|x-wmapp0):/); + $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|ms-appx-web|x-wmapp0):|data:image\//); }]); @@ -2192,7 +2213,9 @@ function($ionicLoadingConfig, $ionicBody, $ionicTemplateLoader, $ionicBackdrop, * @ngdoc method * @name $ionicLoading#show * @description Shows a loading indicator. If the indicator is already shown, - * it will set the options given and keep the indicator shown. + * it will set the options given and keep the indicator shown. Note: While this + * function still returns an $ionicLoading instance for backwards compatiblity, + * its use has been deprecated. * @param {object} opts The options for the loading indicator. Available properties: * - `{string=}` `template` The html content of the indicator. * - `{string=}` `templateUrl` The url of an html template to load as the content of the indicator. @@ -2287,12 +2310,15 @@ function($ionicLoadingConfig, $ionicBody, $ionicTemplateLoader, $ionicBackdrop, } self.element.removeClass('active'); $ionicBody.removeClass('loading-active'); - setTimeout(function() { + self.element.removeClass('visible'); + ionic.requestAnimationFrame(function() { !self.isShown && self.element.removeClass('visible'); - }, 200); + }); } $timeout.cancel(self.durationTimeout); self.isShown = false; + var loading = self.element.children(); + loading.html(""); }; return self; @@ -2529,10 +2555,18 @@ function($rootScope, $ionicBody, $compile, $timeout, $ionicPlatform, $ionicTempl self.scope.$parent && self.scope.$parent.$broadcast(self.viewType + '.shown', self); self.el.classList.add('active'); self.scope.$broadcast('$ionicHeader.align'); + self.scope.$broadcast('$ionicFooter.align'); }, 20); return $timeout(function() { if (!self._isShown) return; + self.$el.on('touchmove', function(e) { + //Don't allow scrolling while open by dragging on backdrop + var isInScroll = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'scroll'); + if (!isInScroll) { + e.preventDefault(); + } + }); //After animating in, allow hide on backdrop click self.$el.on('click', function(e) { if (self.backdropClickToClose && e.target === self.el && stack.isHighest(self)) { @@ -2805,7 +2839,7 @@ IonicModule }) .provider('$ionicPlatform', function() { return { - $get: ['$q', function($q) { + $get: ['$q', '$ionicScrollDelegate', function($q, $ionicScrollDelegate) { var self = { /** @@ -2956,6 +2990,11 @@ IonicModule return q.promise; } }; + + window.addEventListener('statusTap', function() { + $ionicScrollDelegate.scrollTop(true); + }); + return self; }] }; @@ -3168,7 +3207,7 @@ function($ionicModal, $ionicPosition, $document, $window) { * controller (ionicPopover is built on top of $ionicPopover). */ fromTemplate: function(templateString, options) { - return $ionicModal.fromTemplate(templateString, ionic.Utils.extend(POPOVER_OPTIONS, options || {})); + return $ionicModal.fromTemplate(templateString, ionic.Utils.extend({}, POPOVER_OPTIONS, options)); }, /** * @ngdoc method @@ -3179,7 +3218,7 @@ function($ionicModal, $ionicPosition, $document, $window) { * an {@link ionic.controller:ionicPopover} controller (ionicPopover is built on top of $ionicPopover). */ fromTemplateUrl: function(url, options) { - return $ionicModal.fromTemplateUrl(url, ionic.Utils.extend(POPOVER_OPTIONS, options || {})); + return $ionicModal.fromTemplateUrl(url, ionic.Utils.extend({}, POPOVER_OPTIONS, options)); } }; @@ -3230,7 +3269,7 @@ var POPUP_TPL = * * // Triggered on a button click, or some other target * $scope.showPopup = function() { - * $scope.data = {} + * $scope.data = {}; * * // An elaborate, custom popup * var myPopup = $ionicPopup.show({ @@ -3254,19 +3293,23 @@ var POPUP_TPL = * } * ] * }); + * * myPopup.then(function(res) { * console.log('Tapped!', res); * }); + * * $timeout(function() { * myPopup.close(); //close the popup after 3 seconds for some reason * }, 3000); * }; + * * // A confirm dialog * $scope.showConfirm = function() { * var confirmPopup = $ionicPopup.confirm({ * title: 'Consume Ice Cream', * template: 'Are you sure you want to eat this ice cream?' * }); + * * confirmPopup.then(function(res) { * if(res) { * console.log('You are sure'); @@ -3282,6 +3325,7 @@ var POPUP_TPL = * title: 'Don\'t eat that!', * template: 'It might taste good' * }); + * * alertPopup.then(function(res) { * console.log('Thank you for not eating my delicious ice cream cone'); * }); @@ -3438,8 +3482,10 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB * cssClass: '', // String, The custom CSS class name * subTitle: '', // String (optional). The sub-title of the popup. * template: '', // String (optional). The html template to place in the popup body. - * templateUrl: '', // String (optional). The URL of an html template to place in the popup body. + * templateUrl: '', // String (optional). The URL of an html template to place in the popup body. * inputType: // String (default: 'text'). The type of input to use + * defaultText: // String (default: ''). The initial value placed into the input. + * maxLength: // Integer (default: null). Specify a maxlength attribute for the input. * inputPlaceholder: // String (default: ''). A placeholder to use for the input. * cancelText: // String (default: 'Cancel'. The text of the Cancel button. * cancelType: // String (default: 'button-default'). The type of the Cancel button. @@ -3483,7 +3529,7 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB subTitle: options.subTitle, cssClass: options.cssClass, $buttonTapped: function(button, event) { - var result = (button.onTap || noop)(event); + var result = (button.onTap || noop).apply(self, [event]); event = event.originalEvent || event; //jquery events if (!event.defaultPrevented) { @@ -3533,7 +3579,7 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB }; self.remove = function() { - if (self.removed || !$ionicModal.stack.isHighest(self)) return; + if (self.removed) return; self.hide(function() { self.element.remove(); @@ -3556,8 +3602,8 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB var showDelay = 0; if (popupStack.length > 0) { - popupStack[popupStack.length - 1].hide(); showDelay = config.stackPushDelay; + $timeout(popupStack[popupStack.length - 1].hide, showDelay, false); } else { //Add popup-open & backdrop if this is first popup $ionicBody.addClass('popup-open'); @@ -3590,6 +3636,8 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB popupStack.splice(index, 1); } + popup.remove(); + if (popupStack.length > 0) { popupStack[popupStack.length - 1].show(); } else { @@ -3605,7 +3653,6 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB ($ionicPopup._backButtonActionDone || noop)(); } - popup.remove(); return result; }); @@ -3650,14 +3697,21 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB function showPrompt(opts) { var scope = $rootScope.$new(true); scope.data = {}; + scope.data.fieldtype = opts.inputType ? opts.inputType : 'text'; + scope.data.response = opts.defaultText ? opts.defaultText : ''; + scope.data.placeholder = opts.inputPlaceholder ? opts.inputPlaceholder : ''; + scope.data.maxlength = opts.maxLength ? parseInt(opts.maxLength) : ''; var text = ''; if (opts.template && /<[a-z][\s\S]*>/i.test(opts.template) === false) { text = '<span>' + opts.template + '</span>'; delete opts.template; } return showPopup(extend({ - template: text + '<input ng-model="data.response" type="' + (opts.inputType || 'text') + - '" placeholder="' + (opts.inputPlaceholder || '') + '">', + template: text + '<input ng-model="data.response" ' + + 'type="{{ data.fieldtype }}"' + + 'maxlength="{{ data.maxlength }}"' + + 'placeholder="{{ data.placeholder }}"' + + '>', scope: scope, buttons: [{ text: opts.cancelText || 'Cancel', @@ -3906,7 +3960,7 @@ IonicModule * @name $ionicScrollDelegate#freezeScroll * @description Does not allow this scroll view to scroll either x or y. * @param {boolean=} shouldFreeze Should this scroll view be prevented from scrolling or not. - * @returns {object} If the scroll view is being prevented from scrolling or not. + * @returns {boolean} If the scroll view is being prevented from scrolling or not. */ 'freezeScroll', /** @@ -4216,7 +4270,16 @@ IonicModule * @name $ionicTabsDelegate#selectedIndex * @returns `number` The index of the selected tab, or -1. */ - 'selectedIndex' + 'selectedIndex', + /** + * @ngdoc method + * @name $ionicTabsDelegate#showBar + * @description + * Set/get whether the {@link ionic.directive:ionTabs} is shown + * @param {boolean} show Whether to show the bar. + * @returns {boolean} Whether the bar is shown. + */ + 'showBar' /** * @ngdoc method * @name $ionicTabsDelegate#$getByHandle @@ -4229,7 +4292,6 @@ IonicModule */ ])); - // closure to keep things neat (function() { var templatesToCache = []; @@ -4650,8 +4712,9 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe if (renderStart && renderEnd) { // CSS "auto" transitioned, not manually transitioned // wait a frame so the styles apply before auto transitioning - $timeout(onReflow, 16); - + $timeout(function() { + ionic.requestAnimationFrame(onReflow); + }); } else if (!renderEnd) { // just the start of a manual transition // but it will not render the end of the transition @@ -4716,10 +4779,6 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe $timeout.cancel(enteringEle.data(DATA_FALLBACK_TIMER)); leavingEle && $timeout.cancel(leavingEle.data(DATA_FALLBACK_TIMER)); - // emit that the views have finished transitioning - // each parent nav-view will update which views are active and cached - switcher.emit('after', enteringData, leavingData); - // resolve that this one transition (there could be many w/ nested views) deferred && deferred.resolve(navViewCtrl); @@ -4727,6 +4786,10 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe // transition promises should be added to the services array of promises if (transitionId === transitionCounter) { $q.all(transitionPromises).then(ionicViewSwitcher.transitionEnd); + + // emit that the views have finished transitioning + // each parent nav-view will update which views are active and cached + switcher.emit('after', enteringData, leavingData); switcher.cleanup(enteringData); } @@ -4735,6 +4798,7 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe instance.triggerTransitionEnd(); }); + // remove any references that could cause memory issues nextTransition = nextDirection = enteringView = leavingView = enteringEle = leavingEle = null; } @@ -4950,6 +5014,82 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe }]); +/** + * ================== angular-ios9-uiwebview.patch.js v1.1.1 ================== + * + * This patch works around iOS9 UIWebView regression that causes infinite digest + * errors in Angular. + * + * The patch can be applied to Angular 1.2.0 – 1.4.5. Newer versions of Angular + * have the workaround baked in. + * + * To apply this patch load/bundle this file with your application and add a + * dependency on the "ngIOS9UIWebViewPatch" module to your main app module. + * + * For example: + * + * ``` + * angular.module('myApp', ['ngRoute'])` + * ``` + * + * becomes + * + * ``` + * angular.module('myApp', ['ngRoute', 'ngIOS9UIWebViewPatch']) + * ``` + * + * + * More info: + * - https://openradar.appspot.com/22186109 + * - https://github.com/angular/angular.js/issues/12241 + * - https://github.com/driftyco/ionic/issues/4082 + * + * + * @license AngularJS + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ + +angular.module('ngIOS9UIWebViewPatch', ['ng']).config(['$provide', function($provide) { + 'use strict'; + + $provide.decorator('$browser', ['$delegate', '$window', function($delegate, $window) { + + if (isIOS9UIWebView($window.navigator.userAgent)) { + return applyIOS9Shim($delegate); + } + + return $delegate; + + function isIOS9UIWebView(userAgent) { + return /(iPhone|iPad|iPod).* OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent); + } + + function applyIOS9Shim(browser) { + var pendingLocationUrl = null; + var originalUrlFn = browser.url; + + browser.url = function() { + if (arguments.length) { + pendingLocationUrl = arguments[0]; + return originalUrlFn.apply(browser, arguments); + } + + return pendingLocationUrl || originalUrlFn.apply(browser, arguments); + }; + + window.addEventListener('popstate', clearPendingLocationUrl, false); + window.addEventListener('hashchange', clearPendingLocationUrl, false); + + function clearPendingLocationUrl() { + pendingLocationUrl = null; + } + + return browser; + } + }]); +}]); + /** * @private * Parts of Ionic requires that $scope data is attached to the element. @@ -4979,7 +5119,7 @@ function($provide) { //found nearest to body's scrollTop is set to scroll to an element //with that ID. $location.hash = function(value) { - if (isDefined(value)) { + if (isDefined(value) && value.length > 0) { $timeout(function() { var scroll = document.querySelector('.scroll-content'); if (scroll) { @@ -5472,13 +5612,15 @@ function($scope, $attrs, $element, $timeout) { }; var computedStyle = window.getComputedStyle(self.scrollEl) || {}; return { - left: computedStyle.overflowX === 'scroll' || - computedStyle.overflowX === 'auto' || - self.scrollEl.style['overflow-x'] === 'scroll' ? + left: maxValues.left && + (computedStyle.overflowX === 'scroll' || + computedStyle.overflowX === 'auto' || + self.scrollEl.style['overflow-x'] === 'scroll') ? calculateMaxValue(maxValues.left) : -1, - top: computedStyle.overflowY === 'scroll' || - computedStyle.overflowY === 'auto' || - self.scrollEl.style['overflow-y'] === 'scroll' ? + top: maxValues.top && + (computedStyle.overflowY === 'scroll' || + computedStyle.overflowY === 'auto' || + self.scrollEl.style['overflow-y'] === 'scroll' ) ? calculateMaxValue(maxValues.top) : -1 }; }; @@ -5510,18 +5652,20 @@ function($scope, $attrs, $element, $timeout) { * method to control specific ionList instances. * * @usage - * - * ````html + * ```html + * {% raw %} * <ion-content ng-controller="MyCtrl"> * <button class="button" ng-click="showDeleteButtons()"></button> * <ion-list> * <ion-item ng-repeat="i in items"> - * {% raw %}Hello, {{i}}!{% endraw %} + * Hello, {{i}}! * <ion-delete-button class="ion-minus-circled"></ion-delete-button> * </ion-item> * </ion-list> * </ion-content> + * {% endraw %} * ``` + * ```js * function MyCtrl($scope, $ionicListDelegate) { * $scope.showDeleteButtons = function() { @@ -6395,6 +6539,9 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate, if (viewLocals && viewLocals.$$controller) { viewLocals.$scope = viewScope; var controller = $controller(viewLocals.$$controller, viewLocals); + if (viewLocals.$$controllerAs) { + viewScope[viewLocals.$$controllerAs] = controller; + } $element.children().data('$ngControllerController', controller); } @@ -6673,13 +6820,31 @@ IonicModule $onPulling: '&onPulling' }); + function handleMousedown(e) { + e.touches = e.touches || [{ + screenX: e.screenX, + screenY: e.screenY + }]; + // Mouse needs this + startY = Math.floor(e.touches[0].screenY); + } + + function handleTouchstart(e) { + e.touches = e.touches || [{ + screenX: e.screenX, + screenY: e.screenY + }]; + + startY = e.touches[0].screenY; + } + function handleTouchend() { + // reset Y + startY = null; // if this wasn't an overscroll, get out immediately if (!canOverscroll && !isDragging) { return; } - // reset Y - startY = null; // the user has overscrolled but went back to native scrolling if (!isDragging) { dragOffset = 0; @@ -6703,23 +6868,35 @@ IonicModule } function handleTouchmove(e) { + e.touches = e.touches || [{ + screenX: e.screenX, + screenY: e.screenY + }]; + + // Force mouse events to have had a down event first + if (!startY && e.type == 'mousemove') { + return; + } + // if multitouch or regular scroll event, get out immediately if (!canOverscroll || e.touches.length > 1) { return; } //if this is a new drag, keep track of where we start if (startY === null) { - startY = parseInt(e.touches[0].screenY, 10); + startY = e.touches[0].screenY; } + deltaY = e.touches[0].screenY - startY; + + // how far have we dragged so far? // kitkat fix for touchcancel events http://updates.html5rocks.com/2014/05/A-More-Compatible-Smoother-Touch - if (ionic.Platform.isAndroid() && ionic.Platform.version() === 4.4 && scrollParent.scrollTop === 0) { + // Only do this if we're not on crosswalk + if (ionic.Platform.isAndroid() && ionic.Platform.version() === 4.4 && !ionic.Platform.isCrosswalk() && scrollParent.scrollTop === 0 && deltaY > 0) { isDragging = true; e.preventDefault(); } - // how far have we dragged so far? - deltaY = parseInt(e.touches[0].screenY, 10) - startY; // if we've dragged up and back down in to native scroll territory if (deltaY - dragOffset <= 0 || scrollParent.scrollTop !== 0) { @@ -6730,7 +6907,7 @@ IonicModule } if (isDragging) { - nativescroll(scrollParent, parseInt(deltaY - dragOffset, 10) * -1); + nativescroll(scrollParent, deltaY - dragOffset * -1); } // if we're not at overscroll 0 yet, 0 out @@ -6755,7 +6932,7 @@ IonicModule isDragging = true; // overscroll according to the user's drag so far - overscroll(parseInt((deltaY - dragOffset) / 3, 10)); + overscroll((deltaY - dragOffset) / 3); // update the icon accordingly if (!activated && lastOverscroll > ptrThreshold) { @@ -6851,7 +7028,7 @@ IonicModule // fraction based on the easing method easedT = easeOutCubic(time); - overscroll(parseInt((easedT * (Y - from)) + from, 10)); + overscroll(Math.floor((easedT * (Y - from)) + from)); if (time < 1) { ionic.requestAnimationFrame(scroll); @@ -6872,6 +7049,21 @@ IonicModule } + var touchStartEvent, touchMoveEvent, touchEndEvent; + if (window.navigator.pointerEnabled) { + touchStartEvent = 'pointerdown'; + touchMoveEvent = 'pointermove'; + touchEndEvent = 'pointerup'; + } else if (window.navigator.msPointerEnabled) { + touchStartEvent = 'MSPointerDown'; + touchMoveEvent = 'MSPointerMove'; + touchEndEvent = 'MSPointerUp'; + } else { + touchStartEvent = 'touchstart'; + touchMoveEvent = 'touchmove'; + touchEndEvent = 'touchend'; + } + self.init = function() { scrollParent = $element.parent().parent()[0]; scrollChild = $element.parent()[0]; @@ -6881,8 +7073,13 @@ IonicModule throw new Error('Refresher must be immediate child of ion-content or ion-scroll'); } - ionic.on('touchmove', handleTouchmove, scrollChild); - ionic.on('touchend', handleTouchend, scrollChild); + + ionic.on(touchStartEvent, handleTouchstart, scrollChild); + ionic.on(touchMoveEvent, handleTouchmove, scrollChild); + ionic.on(touchEndEvent, handleTouchend, scrollChild); + ionic.on('mousedown', handleMousedown, scrollChild); + ionic.on('mousemove', handleTouchmove, scrollChild); + ionic.on('mouseup', handleTouchend, scrollChild); ionic.on('scroll', handleScroll, scrollParent); // cleanup when done @@ -6890,8 +7087,12 @@ IonicModule }; function destroy() { - ionic.off('touchmove', handleTouchmove, scrollChild); - ionic.off('touchend', handleTouchend, scrollChild); + ionic.off(touchStartEvent, handleTouchstart, scrollChild); + ionic.off(touchMoveEvent, handleTouchmove, scrollChild); + ionic.off(touchEndEvent, handleTouchend, scrollChild); + ionic.off('mousedown', handleMousedown, scrollChild); + ionic.off('mousemove', handleTouchmove, scrollChild); + ionic.off('mouseup', handleTouchend, scrollChild); ionic.off('scroll', handleScroll, scrollParent); scrollParent = null; scrollChild = null; @@ -6927,7 +7128,13 @@ IonicModule function start() { // startCallback $element[0].classList.add('refreshing'); - $scope.$onRefresh(); + var q = $scope.$onRefresh(); + + if (q && q.then) { + q['finally'](function() { + $scope.$broadcast('scroll.refreshComplete'); + }); + } } function show() { @@ -7008,7 +7215,7 @@ function($scope, if (!isDefined(scrollViewOptions.bouncing)) { ionic.Platform.ready(function() { - if (scrollView.options) { + if (scrollView && scrollView.options) { scrollView.options.bouncing = true; if (ionic.Platform.isAndroid()) { // No bouncing by default on Android @@ -7062,12 +7269,18 @@ function($scope, self.scrollTop = function(shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.scrollTo(0, 0, !!shouldAnimate); }); }; self.scrollBottom = function(shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } var max = scrollView.getScrollMax(); scrollView.scrollTo(max.left, max.top, !!shouldAnimate); }); @@ -7075,30 +7288,45 @@ function($scope, self.scrollTo = function(left, top, shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.scrollTo(left, top, !!shouldAnimate); }); }; self.zoomTo = function(zoom, shouldAnimate, originLeft, originTop) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.zoomTo(zoom, !!shouldAnimate, originLeft, originTop); }); }; self.zoomBy = function(zoom, shouldAnimate, originLeft, originTop) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.zoomBy(zoom, !!shouldAnimate, originLeft, originTop); }); }; self.scrollBy = function(left, top, shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.scrollBy(left, top, !!shouldAnimate); }); }; self.anchorScroll = function(shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } var hash = $location.hash(); var elm = hash && $document[0].getElementById(hash); if (!(hash && elm)) { @@ -7117,6 +7345,7 @@ function($scope, }; self.freezeScroll = scrollView.freeze; + self.freezeScrollShut = scrollView.freezeShut; self.freezeAllScrolls = function(shouldFreeze) { for (var i = 0; i < $ionicScrollDelegate._instances.length; i++) { @@ -7298,9 +7527,10 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io // equal 0, otherwise remove the class from the body element $ionicBody.enableClass((percentage !== 0), 'menu-open'); - freezeAllScrolls(false); + self.content.setCanScroll(percentage == 0); }; + /* function freezeAllScrolls(shouldFreeze) { if (shouldFreeze && !self.isScrollFreeze) { $ionicScrollDelegate.freezeAllScrolls(shouldFreeze); @@ -7310,6 +7540,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io } self.isScrollFreeze = shouldFreeze; } + */ /** * Open the menu the given pixel amount. @@ -7442,14 +7673,15 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io self.close(); isAsideExposed = shouldExposeAside; - if (self.left && self.left.isEnabled) { + if ((self.left && self.left.isEnabled) && (self.right && self.right.isEnabled)) { + self.content.setMarginLeftAndRight(isAsideExposed ? self.left.width : 0, isAsideExposed ? self.right.width : 0); + } else if (self.left && self.left.isEnabled) { // set the left marget width if it should be exposed // otherwise set false so there's no left margin self.content.setMarginLeft(isAsideExposed ? self.left.width : 0); } else if (self.right && self.right.isEnabled) { self.content.setMarginRight(isAsideExposed ? self.right.width : 0); } - self.$scope.$emit('$ionicExposeAside', isAsideExposed); }; @@ -7459,8 +7691,6 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io // End a drag with the given event self._endDrag = function(e) { - freezeAllScrolls(false); - if (isAsideExposed) return; if (isDragging) { @@ -7498,7 +7728,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io if (isDragging) { self.openAmount(offsetX + (lastX - startX)); - freezeAllScrolls(true); + //self.content.setCanScroll(false); } }; @@ -7537,7 +7767,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io var menuEnabled = enableMenuWithBackViews ? true : !backView; if (!menuEnabled) { var currentView = $ionicHistory.currentView() || {}; - return backView.historyId !== currentView.historyId; + return (dragIsWithinBounds && (backView.historyId !== currentView.historyId)); } return ($scope.dragContent || self.isOpen()) && @@ -7577,12 +7807,10 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io deregisterBackButtonAction(); self.$scope = null; if (self.content) { + self.content.setCanScroll(true); self.content.element = null; self.content = null; } - - // ensure scrolls are unfrozen - freezeAllScrolls(false); }); self.initialize({ @@ -7928,6 +8156,10 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io var animations = { android: function(ele) { + var self = this; + + this.stop = false; + var rIndex = 0; var rotateCircle = 0; var startTime; @@ -7935,6 +8167,8 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io var circleEle = ele.querySelector('circle'); function run() { + if (self.stop) return; + var v = easeInOutCubic(Date.now() - startTime, 650); var scaleX = 1; var translateX = 0; @@ -7970,6 +8204,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io return function() { startTime = Date.now(); run(); + return self; }; } @@ -7990,7 +8225,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io '$attrs', '$ionicConfig', function($element, $attrs, $ionicConfig) { - var spinnerName; + var spinnerName, anim; this.init = function() { spinnerName = $attrs.icon || $ionicConfig.spinner.icon(); @@ -8013,7 +8248,11 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io }; this.start = function() { - animations[spinnerName] && animations[spinnerName]($element[0])(); + animations[spinnerName] && (anim = animations[spinnerName]($element[0])()); + }; + + this.stop = function() { + animations[spinnerName] && (anim.stop = true); }; }]); @@ -8058,6 +8297,7 @@ function($scope, $element, $ionicHistory) { var selectedTab = null; var previousSelectedTab = null; var selectedTabIndex; + var isVisible = true; self.tabs = []; self.selectedIndex = function() { @@ -8164,6 +8404,17 @@ function($scope, $element, $ionicHistory) { return false; }; + self.showBar = function(show) { + if (arguments.length) { + if (show) { + $element.removeClass('tabs-item-hide'); + } else { + $element.addClass('tabs-item-hide'); + } + isVisible = !!show; + } + return isVisible; + }; }]); IonicModule @@ -8330,7 +8581,7 @@ IonicModule '<div class="action-sheet" ng-class="{\'action-sheet-has-icons\': $actionSheetHasIcon}">' + '<div class="action-sheet-group action-sheet-options">' + '<div class="action-sheet-title" ng-if="titleText" ng-bind-html="titleText"></div>' + - '<button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-repeat="b in buttons" ng-bind-html="b.text"></button>' + + '<button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-class="b.className" ng-repeat="b in buttons" ng-bind-html="b.text"></button>' + '<button class="button destructive action-sheet-destructive" ng-if="destructiveText" ng-click="destructiveButtonClicked()" ng-bind-html="destructiveText"></button>' + '</div>' + '<div class="action-sheet-group action-sheet-cancel" ng-if="cancelText">' + @@ -8457,7 +8708,7 @@ IonicModule * <ion-scroll direction="x" class="available-scroller"> * <div class="photo" collection-repeat="photo in main.photos" * item-height="250" item-width="photo.width + 30"> - * <img ng-src="{{photo.src}}"> + * <img ng-src="{% raw %}{{photo.src}}{% endraw %}"> * </div> * </ion-scroll> * </ion-content> @@ -8739,17 +8990,15 @@ function CollectionRepeatDirective($ionicCollectionManager, $parse, $window, $$r // If it's a constant, it's either a percent or just a constant pixel number. if (isConstant) { - var intValue = parseInt(parsedValue()); - // For percents, store the percent getter on .getValue() if (attrValue.indexOf('%') > -1) { - var decimalValue = intValue / 100; + var decimalValue = parseFloat(parsedValue()) / 100; dimensionData.getValue = dimensionData === heightData ? function() { return Math.floor(decimalValue * scrollView.__clientHeight); } : function() { return Math.floor(decimalValue * scrollView.__clientWidth); }; } else { // For static constants, just store the static constant. - dimensionData.value = intValue; + dimensionData.value = parseInt(parsedValue()); } } else { @@ -8758,14 +9007,14 @@ function CollectionRepeatDirective($ionicCollectionManager, $parse, $window, $$r function heightGetter(scope, locals) { var result = parsedValue(scope, locals); if (result.charAt && result.charAt(result.length - 1) === '%') { - return Math.floor(parseInt(result) / 100 * scrollView.__clientHeight); + return Math.floor(parseFloat(result) / 100 * scrollView.__clientHeight); } return parseInt(result); } : function widthGetter(scope, locals) { var result = parsedValue(scope, locals); if (result.charAt && result.charAt(result.length - 1) === '%') { - return Math.floor(parseInt(result) / 100 * scrollView.__clientWidth); + return Math.floor(parseFloat(result) / 100 * scrollView.__clientWidth); } return parseInt(result); }; @@ -9424,7 +9673,7 @@ function RepeatManagerFactory($rootScope, $window, $$rAF) { * @param {string=} direction Which way to scroll. 'x' or 'y' or 'xy'. Default 'y'. * @param {boolean=} locking Whether to lock scrolling in one direction at a time. Useful to set to false when zoomed in or scrolling in two directions. Default true. * @param {boolean=} padding Whether to add padding to the content. - * of the content. Defaults to true on iOS, false on Android. + * Defaults to true on iOS, false on Android. * @param {boolean=} scroll Whether to allow scrolling of content. Defaults to true. * @param {boolean=} overflow-scroll Whether to use overflow-scrolling instead of * Ionic scroll. See {@link ionic.provider:$ionicConfigProvider} to set this as the global default. @@ -9466,13 +9715,12 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { element.addClass('scroll-content-false'); } - var nativeScrolling = attr.overflowScroll === "true" || !$ionicConfig.scrolling.jsScrolling(); + var nativeScrolling = attr.overflowScroll !== "false" && (attr.overflowScroll === "true" || !$ionicConfig.scrolling.jsScrolling()); // collection-repeat requires JS scrolling if (nativeScrolling) { nativeScrolling = !element[0].querySelector('[collection-repeat]'); } - return { pre: prelink }; function prelink($scope, $element, $attr) { var parentScope = $scope.$parent; @@ -9555,6 +9803,8 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { scrollViewOptions: scrollViewOptions }); + $scope.scrollCtrl = scrollCtrl; + $scope.$on('$destroy', function() { if (scrollViewOptions) { scrollViewOptions.scrollingComplete = noop; @@ -9603,7 +9853,6 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { * the most common use-case. However, for added flexibility, any valid media query could be added * as the value, such as `(min-width:600px)` or even multiple queries such as * `(min-width:750px) and (max-width:1200px)`. - * @usage * ```html * <ion-side-menus> @@ -9619,12 +9868,21 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { * For a complete side menu example, see the * {@link ionic.directive:ionSideMenus} documentation. */ + IonicModule.directive('exposeAsideWhen', ['$window', function($window) { return { restrict: 'A', require: '^ionSideMenus', link: function($scope, $element, $attr, sideMenuCtrl) { + // Setup a match media query listener that triggers a ui change only when a change + // in media matching status occurs + var mq = $attr.exposeAsideWhen == 'large' ? '(min-width:768px)' : $attr.exposeAsideWhen; + var mql = $window.matchMedia(mq); + mql.addListener(function() { + onResize(); + }); + function checkAsideExpose() { var mq = $attr.exposeAsideWhen == 'large' ? '(min-width:768px)' : $attr.exposeAsideWhen; sideMenuCtrl.exposeAside($window.matchMedia(mq).matches); @@ -9641,18 +9899,10 @@ IonicModule.directive('exposeAsideWhen', ['$window', function($window) { }, 300, false); $scope.$evalAsync(checkAsideExpose); - - ionic.on('resize', onResize, $window); - - $scope.$on('$destroy', function() { - ionic.off('resize', onResize, $window); - }); - } }; }]); - var GESTURE_DIRECTIVES = 'onHold onTap onDoubleTap onTouch onRelease onDragStart onDrag onDragEnd onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeDown onSwipeLeft'.split(' '); GESTURE_DIRECTIVES.forEach(function(name) { @@ -9959,7 +10209,7 @@ function gestureDirective(directiveName) { IonicModule -.directive('ionHeaderBar', tapScrollToTopDirective()) +//.directive('ionHeaderBar', tapScrollToTopDirective()) /** * @ngdoc directive @@ -10036,7 +10286,7 @@ IonicModule */ .directive('ionFooterBar', headerFooterBarDirective(false)); -function tapScrollToTopDirective() { +function tapScrollToTopDirective() { //eslint-disable-line no-unused-vars return ['$ionicScrollDelegate', function($ionicScrollDelegate) { return { restrict: 'E', @@ -10123,6 +10373,12 @@ function headerFooterBarDirective(isHeader) { $scope.$watch('$hasTabs', function(val) { $element.toggleClass('has-tabs', !!val); }); + ctrl.align(); + $scope.$on('$ionicFooter.align', function() { + ionic.requestAnimationFrame(function() { + ctrl.align(); + }); + }); } } } @@ -10240,6 +10496,137 @@ IonicModule }; }]); +/** +* @ngdoc directive +* @name ionInput +* @parent ionic.directive:ionList +* @module ionic +* @restrict E +* Creates a text input group that can easily be focused +* +* @usage +* +* ```html +* <ion-list> +* <ion-input> +* <input type="text" placeholder="First Name"> +* <ion-input> +* +* <ion-input> +* <ion-label>Username</ion-label> +* <input type="text"> +* </ion-input> +* </ion-list> +* ``` +*/ + +var labelIds = -1; + +IonicModule +.directive('ionInput', [function() { + return { + restrict: 'E', + controller: ['$scope', '$element', function($scope, $element) { + this.$scope = $scope; + this.$element = $element; + + this.setInputAriaLabeledBy = function(id) { + var inputs = $element[0].querySelectorAll('input,textarea'); + inputs.length && inputs[0].setAttribute('aria-labelledby', id); + }; + + this.focus = function() { + var inputs = $element[0].querySelectorAll('input,textarea'); + inputs.length && inputs[0].focus(); + }; + }] + }; +}]); + +/** +* @ngdoc directive +* @name ionLabel +* @parent ionic.directive:ionList +* @module ionic +* @restrict E +* +* New in Ionic 1.2. It is strongly recommended that you use `<ion-label>` in place +* of any `<label>` elements for maximum cross-browser support and performance. +* +* Creates a label for a form input. +* +* @usage +* +* ```html +* <ion-list> +* <ion-input> +* <ion-label>Username</ion-label> +* <input type="text"> +* </ion-input> +* </ion-list> +* ``` +*/ +IonicModule +.directive('ionLabel', [function() { + return { + restrict: 'E', + require: '?^ionInput', + compile: function() { + + return function link($scope, $element, $attrs, ionInputCtrl) { + var element = $element[0]; + + $element.addClass('input-label'); + + $element.attr('aria-label', $element.text()); + var id = element.id || '_label-' + ++labelIds; + + if (!element.id) { + $element.attr('id', id); + } + + if (ionInputCtrl) { + + ionInputCtrl.setInputAriaLabeledBy(id); + + $element.on('click', function() { + ionInputCtrl.focus(); + }); + } + }; + } + }; +}]); + +/** + * Input label adds accessibility to <span class="input-label">. + */ +IonicModule +.directive('inputLabel', [function() { + return { + restrict: 'C', + require: '?^ionInput', + compile: function() { + + return function link($scope, $element, $attrs, ionInputCtrl) { + var element = $element[0]; + + $element.attr('aria-label', $element.text()); + var id = element.id || '_label-' + ++labelIds; + + if (!element.id) { + $element.attr('id', id); + } + + if (ionInputCtrl) { + ionInputCtrl.setInputAriaLabeledBy(id); + } + + }; + } + }; +}]); + /** * @ngdoc directive * @name ionItem @@ -10448,7 +10835,7 @@ var ITEM_TPL_OPTION_BUTTONS = * @description * Creates an option button inside a list item, that is visible when the item is swiped * to the left by the user. Swiped open option buttons can be hidden with -* {@link ionic.service:$ionicListDelegate#closeOptionButtons $ionicListDelegate#closeOptionButtons}. +* {@link ionic.service:$ionicListDelegate#closeOptionButtons $ionicListDelegate.closeOptionButtons}. * * Can be assigned any button class. * @@ -10629,7 +11016,7 @@ IonicModule } //for testing - var keyboardHeight = e.keyboardHeight || e.detail.keyboardHeight; + var keyboardHeight = e.keyboardHeight || (e.detail && e.detail.keyboardHeight); element.css('bottom', keyboardHeight + "px"); scrollCtrl = element.controller('$ionicScroll'); if (scrollCtrl) { @@ -10881,9 +11268,21 @@ function($timeout) { * ```html * <a menu-close href="#/home" class="item">Home</a> * ``` + * + * Note that if your destination state uses a resolve and that resolve asynchronously + * takes longer than a standard transition (300ms), you'll need to set the + * `nextViewOptions` manually as your resolve completes. + * + * ```js + * $ionicHistory.nextViewOptions({ + * historyRoot: true, + * disableAnimate: true, + * expire: 300 + * }); + * ``` */ IonicModule -.directive('menuClose', ['$ionicHistory', function($ionicHistory) { +.directive('menuClose', ['$ionicHistory', '$timeout', function($ionicHistory, $timeout) { return { restrict: 'AC', link: function($scope, $element) { @@ -10895,6 +11294,15 @@ IonicModule disableAnimate: true, expire: 300 }); + // if no transition in 300ms, reset nextViewOptions + // the expire should take care of it, but will be cancelled in some + // cases. This directive is an exception to the rules of history.js + $timeout( function() { + $ionicHistory.nextViewOptions({ + historyRoot: false, + disableAnimate: false + }); + }, 300); sideMenuCtrl.close(); } }); @@ -11459,7 +11867,7 @@ IonicModule * }); * }); * ``` - * Then on app start, $stateProvider will look at the url, see it matches the index state, + * Then on app start, $stateProvider will look at the url, see if it matches the index state, * and then try to load home.html into the `<ion-nav-view>`. * * Pages are loaded by the URLs given. One simple way to create templates in Angular is to put @@ -11717,7 +12125,7 @@ IonicModule * @description * The radio directive is no different than the HTML radio input, except it's styled differently. * - * Radio behaves like any [AngularJS radio](http://docs.angularjs.org/api/ng/input/input[radio]). + * Radio behaves like [AngularJS radio](http://docs.angularjs.org/api/ng/input/input[radio]). * * @usage * ```html @@ -11745,13 +12153,16 @@ IonicModule template: '<label class="item item-radio">' + '<input type="radio" name="radio-group">' + - '<div class="item-content disable-pointer-events" ng-transclude></div>' + - '<i class="radio-icon disable-pointer-events icon ion-checkmark"></i>' + + '<div class="radio-content">' + + '<div class="item-content disable-pointer-events" ng-transclude></div>' + + '<i class="radio-icon disable-pointer-events icon ion-checkmark"></i>' + + '</div>' + '</label>', compile: function(element, attr) { if (attr.icon) { - element.children().eq(2).removeClass('ion-checkmark').addClass(attr.icon); + var iconElm = element.find('i'); + iconElm.removeClass('ion-checkmark').addClass(attr.icon); } var input = element.find('input'); @@ -11938,12 +12349,13 @@ IonicModule '$timeout', '$controller', '$ionicBind', -function($timeout, $controller, $ionicBind) { + '$ionicConfig', +function($timeout, $controller, $ionicBind, $ionicConfig) { return { restrict: 'E', scope: true, controller: function() {}, - compile: function(element) { + compile: function(element, attr) { element.addClass('scroll-view ionic-scroll'); //We cannot transclude here because it breaks element.data() inheritance on compile @@ -11951,6 +12363,8 @@ function($timeout, $controller, $ionicBind) { innerElement.append(element.contents()); element.append(innerElement); + var nativeScrolling = attr.overflowScroll !== "false" && (attr.overflowScroll === "true" || !$ionicConfig.scrolling.jsScrolling()); + return { pre: prelink }; function prelink($scope, $element, $attr) { $ionicBind($scope, $attr, { @@ -11978,6 +12392,12 @@ function($timeout, $controller, $ionicBind) { if (!$scope.direction) { $scope.direction = 'y'; } var isPaging = $scope.$eval($scope.paging) === true; + if (nativeScrolling) { + $element.addClass('overflow-scroll'); + } + + $element.addClass('scroll-' + $scope.direction); + var scrollViewOptions = { el: $element[0], delegateHandle: $attr.delegateHandle, @@ -11991,8 +12411,10 @@ function($timeout, $controller, $ionicBind) { zooming: $scope.$eval($scope.zooming) === true, maxZoom: $scope.$eval($scope.maxZoom) || 3, minZoom: $scope.$eval($scope.minZoom) || 0.5, - preventDefault: true + preventDefault: true, + nativeScrolling: nativeScrolling }; + if (isPaging) { scrollViewOptions.speedMultiplier = 0.8; scrollViewOptions.bouncing = false; @@ -12203,6 +12625,22 @@ function($timeout, $ionicGesture, $window) { element: element[0], onDrag: function() {}, endDrag: function() {}, + setCanScroll: function(canScroll) { + var c = $element[0].querySelector('.scroll'); + + if (!c) { + return; + } + + var content = angular.element(c.parentElement); + if (!content) { + return; + } + + // freeze our scroll container if we have one + var scrollScope = content.scope(); + scrollScope.scrollCtrl && scrollScope.scrollCtrl.freezeScrollShut(!canScroll); + }, getTranslateX: function() { return $scope.sideMenuContentTranslateX || 0; }, @@ -12237,6 +12675,24 @@ function($timeout, $ionicGesture, $window) { // reset incase left gets grabby $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(0,0,0)'; }), + setMarginLeftAndRight: ionic.animationFrameThrottle(function(amountLeft, amountRight) { + amountLeft = amountLeft && parseInt(amountLeft, 10) || 0; + amountRight = amountRight && parseInt(amountRight, 10) || 0; + + var amount = amountLeft + amountRight; + + if (amount > 0) { + $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(' + amountLeft + 'px,0,0)'; + $element[0].style.width = ($window.innerWidth - amount) + 'px'; + content.offsetX = amountLeft; + } else { + $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(0,0,0)'; + $element[0].style.width = ''; + content.offsetX = 0; + } + // reset incase left gets grabby + //$element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(0,0,0)'; + }), enableAnimation: function() { $scope.animationEnabled = true; $element[0].classList.add('menu-animated'); @@ -12252,9 +12708,7 @@ function($timeout, $ionicGesture, $window) { // add gesture handlers var gestureOpts = { stop_browser_behavior: false }; - if (ionic.DomUtil.getParentOrSelfWithClass($element[0], 'overflow-scroll')) { - gestureOpts.prevent_default_directions = ['left', 'right']; - } + gestureOpts.prevent_default_directions = ['left', 'right']; var contentTapGesture = $ionicGesture.on('tap', onContentTap, $element, gestureOpts); var dragRightGesture = $ionicGesture.on('dragright', onDragX, $element, gestureOpts); var dragLeftGesture = $ionicGesture.on('dragleft', onDragX, $element, gestureOpts); @@ -12326,21 +12780,18 @@ IonicModule * * ```html * <ion-side-menus> - * <!-- Center content --> - * <ion-side-menu-content ng-controller="ContentController"> - * </ion-side-menu-content> - * * <!-- Left menu --> * <ion-side-menu side="left"> * </ion-side-menu> * + * <ion-side-menu-content> + * <!-- Main content, usually <ion-nav-view> --> + * </ion-side-menu-content> + * * <!-- Right menu --> * <ion-side-menu side="right"> * </ion-side-menu> * - * <ion-side-menu-content> - * <!-- Main content, usually <ion-nav-view> --> - * </ion-side-menu-content> * </ion-side-menus> * ``` * ```js @@ -12398,6 +12849,8 @@ IonicModule * @ngdoc directive * @name ionSlideBox * @module ionic + * @deprecated will be removed in the next Ionic release in favor of the new ion-slides component. + * Don't depend on the internal behavior of this widget. * @delegate ionic.service:$ionicSlideBoxDelegate * @restrict E * @description @@ -12428,16 +12881,17 @@ IonicModule * @param {boolean=} show-pager Whether a pager should be shown for this slide box. Accepts expressions via `show-pager="{{shouldShow()}}"`. Defaults to true. * @param {expression=} pager-click Expression to call when a pager is clicked (if show-pager is true). Is passed the 'index' variable. * @param {expression=} on-slide-changed Expression called whenever the slide is changed. Is passed an '$index' variable. - * @param {expression=} active-slide Model to bind the current slide to. + * @param {expression=} active-slide Model to bind the current slide index to. */ IonicModule .directive('ionSlideBox', [ + '$animate', '$timeout', '$compile', '$ionicSlideBoxDelegate', '$ionicHistory', '$ionicScrollDelegate', -function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScrollDelegate) { +function($animate, $timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScrollDelegate) { return { restrict: 'E', replace: true, @@ -12450,12 +12904,14 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll pagerClick: '&', disableScroll: '@', onSlideChanged: '&', - activeSlide: '=?' + activeSlide: '=?', + bounce: '@' }, controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) { var _this = this; var continuous = $scope.$eval($scope.doesContinue) === true; + var bouncing = ($scope.$eval($scope.bounce) !== false); //Default to true var shouldAutoPlay = isDefined($attrs.autoPlay) ? !!$scope.autoPlay : false; var slideInterval = shouldAutoPlay ? $scope.$eval($scope.slideInterval) || 4000 : 0; @@ -12464,6 +12920,7 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll auto: slideInterval, continuous: continuous, startSlide: $scope.activeSlide, + bouncing: bouncing, slidesChanged: function() { $scope.currentSlide = slider.currentIndex(); @@ -12534,7 +12991,6 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll }; this.onPagerClick = function(index) { - void 0; $scope.pagerClick({index: index}); }; @@ -12548,6 +13004,9 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll '</div>', link: function($scope, $element, $attr) { + // Disable ngAnimate for slidebox and its children + $animate.enabled(false, $element); + // if showPager is undefined, show the pager if (!isDefined($attr.showPager)) { $scope.showPager = true; @@ -12555,6 +13014,7 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll } $attr.$observe('showPager', function(show) { + if (show === undefined) return; show = $scope.$eval(show); getPager().toggleClass('hide', !show); }); @@ -12575,7 +13035,7 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll .directive('ionSlide', function() { return { restrict: 'E', - require: '^ionSlideBox', + require: '?^ionSlideBox', compile: function(element) { element.addClass('slider-slide'); } @@ -12617,6 +13077,132 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll }); + +/** + * @ngdoc directive + * @name ionSlides + * @module ionic + * @delegate ionic.service:$ionicSlideBoxDelegate + * @restrict E + * @description + * The Slides component is a powerful multi-page container where each page can be swiped or dragged between. + * + * Note: this is a new version of the Ionic Slide Box based on the [Swiper](http://www.idangero.us/swiper/#.Vmc1J-ODFBc) widget from + * [idangerous](http://www.idangero.us/). + * + *  + * + * @usage + * ```html + * <ion-slides on-slide-changed="slideHasChanged($index)"> + * <ion-slide-page> + * <div class="box blue"><h1>BLUE</h1></div> + * </ion-slide-page> + * <ion-slide-page> + * <div class="box yellow"><h1>YELLOW</h1></div> + * </ion-slide-page> + * <ion-slide-page> + * <div class="box pink"><h1>PINK</h1></div> + * </ion-slide-page> + * </ion-slides> + * ``` + * + * @param {string=} delegate-handle The handle used to identify this slideBox + * with {@link ionic.service:$ionicSlideBoxDelegate}. + * @param {object=} options to pass to the widget. See the full ist here: [http://www.idangero.us/swiper/api/](http://www.idangero.us/swiper/api/) + */ +IonicModule +.directive('ionSlides', [ + '$animate', + '$timeout', + '$compile', +function($animate, $timeout, $compile) { + return { + restrict: 'E', + transclude: true, + scope: { + options: '=', + slider: '=' + }, + template: '<div class="swiper-container">' + + '<div class="swiper-wrapper" ng-transclude>' + + '</div>' + + '<div ng-hide="!showPager" class="swiper-pagination"></div>' + + '</div>', + controller: ['$scope', '$element', function($scope, $element) { + var _this = this; + + this.update = function() { + $timeout(function() { + if (!_this.__slider) { + return; + } + + _this.__slider.update(); + if (_this._options.loop) { + _this.__slider.createLoop(); + } + + // Don't allow pager to show with > 10 slides + if (_this.__slider.slides.length > 10) { + $scope.showPager = false; + } + }); + }; + + this.rapidUpdate = ionic.debounce(function() { + _this.update(); + }, 50); + + this.getSlider = function() { + return _this.__slider; + }; + + var options = $scope.options || {}; + + var newOptions = angular.extend({ + pagination: '.swiper-pagination', + paginationClickable: true, + lazyLoading: true, + preloadImages: false + }, options); + + this._options = newOptions; + + $timeout(function() { + var slider = new ionic.views.Swiper($element.children()[0], newOptions, $scope, $compile); + + _this.__slider = slider; + $scope.slider = _this.__slider; + + $scope.$on('$destroy', function() { + slider.destroy(); + }); + }); + + }], + + + link: function($scope) { + $scope.showPager = true; + // Disable ngAnimate for slidebox and its children + //$animate.enabled(false, $element); + } + }; +}]) +.directive('ionSlidePage', [function() { + return { + restrict: 'E', + require: '?^ionSlides', + transclude: true, + replace: true, + template: '<div class="swiper-slide" ng-transclude></div>', + link: function($scope, $element, $attr, ionSlidesCtrl) { + ionSlidesCtrl.rapidUpdate(); + } + }; +}]); + /** * @ngdoc directive * @name ionSpinner @@ -12807,6 +13393,10 @@ IonicModule link: function($scope, $element, $attrs, ctrl) { var spinnerName = ctrl.init(); $element.addClass('spinner spinner-' + spinnerName); + + $element.on('$destroy', function onDestroy() { + ctrl.stop(); + }); } }; }); @@ -13106,7 +13696,7 @@ IonicModule * * @usage * ```html - * <ion-tabs class="tabs-positive tabs-icon-only"> + * <ion-tabs class="tabs-positive tabs-icon-top"> * * <ion-tab title="Home" icon-on="ion-ios-filing" icon-off="ion-ios-filing-outline"> * <!-- Tab 1 content --> @@ -13199,6 +13789,34 @@ function($ionicTabsDelegate, $ionicConfig) { }; }]); +/** +* @ngdoc directive +* @name ionTitle +* @module ionic +* @restrict E +* +* Used for titles in header and nav bars. New in 1.2 +* +* Identical to <div class="title"> but with future compatibility for Ionic 2 +* +* @usage +* +* ```html +* <ion-nav-bar> +* <ion-title>Hello</ion-title> +* <ion-nav-bar> +* ``` +*/ +IonicModule +.directive('ionTitle', [function() { + return { + restrict: 'E', + compile: function(element) { + element.addClass('title'); + } + }; +}]); + /** * @ngdoc directive * @name ionToggle diff --git a/www/lib/ionic/js/ionic-angular.min.js b/www/lib/ionic/js/ionic-angular.min.js index f4f5a3ecdf073e906465ea5b491c9ad617519e70..c913df7c7364dc19e80e6239e5fa4b38974b8e91 100644 --- a/www/lib/ionic/js/ionic-angular.min.js +++ b/www/lib/ionic/js/ionic-angular.min.js @@ -1,8 +1,8 @@ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -12,7 +12,7 @@ * */ -!function(){function e(e,t,n,i,o,r){function a(i,a,c,s,l){function d(){N.resizeRequiresRefresh(w.__clientWidth,w.__clientHeight)&&g()}function f(){var e;return e={dataLength:0,width:0,height:0,resizeRequiresRefresh:function(t,n){var i=e.dataLength&&t&&n&&(t!==e.width||n!==e.height);return e.width=t,e.height=n,!!i},dataChangeRequiresRefresh:function(t){var n=t.length>0||t.length<e.dataLength;return e.dataLength=t.length,!!n}}}function h(){return T||(T=new e({afterItemsNode:M[0],containerNode:y,heightData:A,widthData:E,forceRefreshImages:!(!u(c.forceRefreshImages)||"false"===c.forceRefreshImages),keyExpression:B,renderBuffer:_,scope:i,scrollView:s.scrollView,transclude:l}))}function p(){var e=angular.element(w.__content.querySelector(".collection-repeat-after-container"));if(!e.length){var t=!1,n=[].filter.call(w.__content.childNodes,function(e){return ionic.DomUtil.contains(e,y)?(t=!0,!1):t});e=angular.element('<span class="collection-repeat-after-container">'),w.options.scrollingX&&e.addClass("horizontal"),e.append(n),w.__content.appendChild(e[0])}return e}function v(){R?m(R,A):A.computed=!0,L?m(L,E):E.computed=!0}function g(){var e=P.length>0;if(e&&(A.computed||E.computed)&&$(),e&&A.computed){if(A.value=V.height,!A.value)throw new Error('collection-repeat tried to compute the height of repeated elements "'+k+'", but was unable to. Please provide the "item-height" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!A.dynamic&&A.getValue&&(A.value=A.getValue());if(e&&E.computed){if(E.value=V.width,!E.value)throw new Error('collection-repeat tried to compute the width of repeated elements "'+k+'", but was unable to. Please provide the "item-width" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!E.dynamic&&E.getValue&&(E.value=E.getValue());h().refreshLayout()}function m(e,n){if(e){var i;try{i=t(e)}catch(o){e.trim().match(/\d+(px|%)$/)&&(e='"'+e+'"'),i=t(e)}var r=e.replace(/(\'|\"|px|%)/g,"").trim(),a=r.length&&!/([a-zA-Z]|\$|:|\?)/.test(r);if(n.attrValue=e,a){var c=parseInt(i());if(e.indexOf("%")>-1){var s=c/100;n.getValue=n===A?function(){return Math.floor(s*w.__clientHeight)}:function(){return Math.floor(s*w.__clientWidth)}}else n.value=c}else n.dynamic=!0,n.getValue=n===A?function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseInt(n)/100*w.__clientHeight):parseInt(n)}:function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseInt(n)/100*w.__clientWidth):parseInt(n)}}}function $(){H||l(O=i.$new(),function(e){e[0].removeAttribute("collection-repeat"),H=e[0]}),O[B]=(x(i)||[])[0],o.$$phase||O.$digest(),y.appendChild(H);var e=n.getComputedStyle(H);V.width=parseInt(e.width),V.height=parseInt(e.height),y.removeChild(H)}var w=s.scrollView,b=a[0],y=angular.element('<div class="collection-repeat-container">')[0];if(b.parentNode.replaceChild(y,b),w.options.scrollingX&&w.options.scrollingY)throw new Error("collection-repeat expected a parent x or y scrollView, not an xy scrollView.");var k=c.collectionRepeat,C=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!C)throw new Error("collection-repeat expected expression in form of '_item_ in _collection_[ track by _id_]' but got '"+c.collectionRepeat+"'.");var T,B=C[1],I=C[2],x=t(I),A={},E={},V={},P=[],D=c.itemRenderBuffer||c.collectionBufferSize,_=angular.isDefined(D)?parseInt(D):S,R=c.itemHeight||c.collectionItemHeight,L=c.itemWidth||c.collectionItemWidth,M=p(),N=f();v(),s.$element.on("scroll-resize",g),angular.element(n).on("resize",d);var z=o.$on("$ionicExposeAside",ionic.animationFrameThrottle(function(){s.scrollView.resize(),d()}));r(g,0,!1),i.$watchCollection(x,function(e){if(P=e||(e=[]),!angular.isArray(e))throw new Error("collection-repeat expected an array for '"+I+"', but got a "+typeof value);i.$$postDigest(function(){h().setData(P),N.dataChangeRequiresRefresh(P)&&g()})}),i.$on("$destroy",function(){angular.element(n).off("resize",d),z(),s.$element&&s.$element.off("scroll-resize",g),H&&H.parentNode&&H.parentNode.removeChild(H),O&&O.$destroy(),O=H=null,T&&T.destroy(),T=null});var H,O}return{restrict:"A",priority:1e3,transclude:"element",$$tlb:!0,require:"^^$ionicScroll",link:a}}function t(e,t,n){var i={primaryPos:0,secondaryPos:0,primarySize:0,secondarySize:0,rowPrimarySize:0};return function(o){function r(){return a(!0)}function a(t){if(!a.destroyed){var n,o,r,l,u,d=ee.getScrollValue(),f=d+ee.scrollPrimarySize;ee.updateRenderRange(d,f),W=Math.max(0,W-T),F=Math.min(A.length-1,F+T);for(n in Z)(W>n||n>F)&&(r=Z[n],delete Z[n],j.push(r),r.isShown=!1);for(n=W;F>=n;n++)n>=A.length||Z[n]&&!t||(r=Z[n]||(Z[n]=j.length?j.pop():G.length?G.shift():new s),K.push(r),r.isShown=!0,u=r.scope,u.$index=n,u[C]=A[n],u.$first=0===n,u.$last=n===A.length-1,u.$middle=!(u.$first||u.$last),u.$odd=!(u.$even=0===(1&n)),u.$$disconnected&&ionic.Utils.reconnectScope(r.scope),l=ee.getDimensions(n),(r.secondaryPos!==l.secondaryPos||r.primaryPos!==l.primaryPos)&&(r.node.style[ionic.CSS.TRANSFORM]=H.replace(N,r.primaryPos=l.primaryPos).replace(z,r.secondaryPos=l.secondaryPos)),(r.secondarySize!==l.secondarySize||r.primarySize!==l.primarySize)&&(r.node.style.cssText=r.node.style.cssText.replace(y,O.replace(N,(r.primarySize=l.primarySize)+1).replace(z,r.secondarySize=l.secondarySize))));for(F===A.length-1&&(l=ee.getDimensions(A.length-1)||i,m.style[ionic.CSS.TRANSFORM]=H.replace(N,l.primaryPos+l.primarySize).replace(z,0));j.length;)r=j.pop(),r.scope.$broadcast("$collectionRepeatLeave"),ionic.Utils.disconnectScope(r.scope),G.push(r),r.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",r.primaryPos=r.secondaryPos=null;if(w)for(n=0,o=K.length;o>n&&(r=K[n]);n++)if(r.images)for(var h,p=0,v=r.images.length;v>p&&(h=r.images[p]);p++){var g=h.src;h.src=b,h.src=g}if(t)for(var $=e.$$phase;K.length;)r=K.pop(),$||r.scope.$digest();else c()}}function c(){var t;c.running||(c.running=!0,n(function(){for(var n=e.$$phase;K.length;)t=K.pop(),t.isShown&&(n||t.scope.$digest());c.running=!1}))}function s(){var e=this;this.scope=B.$new(),this.id="item"+J++,x(this.scope,function(t){e.element=t,e.element.data("$$collectionRepeatItem",e),e.node=t[0],e.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",e.node.style.cssText+=" height: 0px; width: 0px;",ionic.Utils.disconnectScope(e.scope),$.appendChild(e.node),e.images=t[0].getElementsByTagName("img")})}function l(){this.getItemPrimarySize=P,this.getItemSecondarySize=_,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollTop-q,I.__maxScrollTop-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientHeight,this.scrollSecondarySize=I.__clientWidth,this.estimatedPrimarySize=v,this.estimatedSecondarySize=g,this.estimatedItemsAcross=L&&Math.floor(I.__clientWidth/g)||1}}function u(){this.getItemPrimarySize=_,this.getItemSecondarySize=P,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollLeft-q,I.__maxScrollLeft-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientWidth,this.scrollSecondarySize=I.__clientHeight,this.estimatedPrimarySize=g,this.estimatedSecondarySize=v,this.estimatedItemsAcross=L&&Math.floor(I.__clientHeight/v)||1}}function d(){this.getEstimatedSecondaryPos=function(e){return e%this.estimatedItemsAcross*this.estimatedSecondarySize},this.getEstimatedPrimaryPos=function(e){return Math.floor(e/this.estimatedItemsAcross)*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)*this.estimatedItemsAcross}}function f(){this.getEstimatedSecondaryPos=function(){return 0},this.getEstimatedPrimaryPos=function(e){return e*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)}}function h(){this.getContentSize=function(){return this.getEstimatedPrimaryPos(A.length-1)+this.estimatedPrimarySize+q+U};var e={};this.getDimensions=function(t){return e.primaryPos=this.getEstimatedPrimaryPos(t),e.secondaryPos=this.getEstimatedSecondaryPos(t),e.primarySize=this.estimatedPrimarySize,e.secondarySize=this.estimatedSecondarySize,e},this.updateRenderRange=function(e,t){W=Math.max(0,this.getEstimatedIndex(e)),F=Math.min(A.length-1,this.getEstimatedIndex(t)+this.estimatedItemsAcross-1),Y=Math.max(0,this.getEstimatedPrimaryPos(W)),X=this.getEstimatedPrimaryPos(F)+this.estimatedPrimarySize}}function p(){function e(e){var t,r,a;for(t=Math.max(0,n);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.primarySize=o.getItemPrimarySize(t,A[t]),a.secondarySize=o.scrollSecondarySize,a.primaryPos=r.primaryPos+r.primarySize,a.secondaryPos=0}function t(e){var t,r,a;for(t=Math.max(n,0);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.secondarySize=Math.min(o.getItemSecondarySize(t,A[t]),o.scrollSecondarySize),a.secondaryPos=r.secondaryPos+r.secondarySize,0===t||a.secondaryPos+a.secondarySize>o.scrollSecondarySize?(a.secondaryPos=0,a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos+r.rowPrimarySize,a.rowStartIndex=t,a.rowPrimarySize=a.primarySize):(a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos,a.rowStartIndex=r.rowStartIndex,c[a.rowStartIndex].rowPrimarySize=a.rowPrimarySize=Math.max(c[a.rowStartIndex].rowPrimarySize,a.primarySize),a.rowPrimarySize=Math.max(a.primarySize,a.rowPrimarySize))}var n,o=this,r=ionic.debounce(Q,25,!0),a=L?t:e,c=[];this.getContentSize=function(){var e=c[n]||i;return(e.primaryPos+e.primarySize||0)+this.getEstimatedPrimaryPos(A.length-n-1)+q+U},this.onDestroy=function(){c.length=0},this.onRefreshData=function(){var e,t;for(e=c.length,t=A.length;t>e;e++)c.push({});n=-1},this.onRefreshLayout=function(){n=-1},this.getDimensions=function(e){return e=Math.min(e,A.length-1),e>n&&(e>.9*A.length?(a(A.length-1),n=A.length-1,Q()):(a(e),n=e,r())),c[e]};var s=-1,l=-1;this.updateRenderRange=function(e,t){var n,i,o;if(this.getDimensions(2*this.getEstimatedIndex(t)),-1===s||0===e)n=0;else if(e>=l)for(n=s,i=A.length;i>n&&!((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>=e);n++);else for(n=s;n>=0;n--)if((o=this.getDimensions(n))&&o.primaryPos<=e){n=L?o.rowStartIndex:n;break}W=Math.min(Math.max(0,n),A.length-1),Y=-1!==W?this.getDimensions(W).primaryPos:-1;var r;for(n=W+1,i=A.length;i>n;n++)if((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>t){if(L)for(r=o;i-1>n&&(o=this.getDimensions(n+1)).primaryPos===r.primaryPos;)n++;break}F=Math.min(n,A.length-1),X=-1!==F?(o=this.getDimensions(F)).primaryPos+(o.rowPrimarySize||o.primarySize):-1,l=e,s=W}}var v,g,m=o.afterItemsNode,$=o.containerNode,w=o.forceRefreshImages,S=o.heightData,k=o.widthData,C=o.keyExpression,T=o.renderBuffer,B=o.scope,I=o.scrollView,x=o.transclude,A=[],E={},V=S.getValue||function(){return S.value},P=function(e,t){return E[C]=t,E.$index=e,V(B,E)},D=k.getValue||function(){return k.value},_=function(e,t){return E[C]=t,E.$index=e,D(B,E)},R=!!I.options.scrollingY,L=R?k.dynamic||k.value!==I.__clientWidth:S.dynamic||S.value!==I.__clientHeight,M=!S.dynamic&&!k.dynamic,N="PRIMARY",z="SECONDARY",H=R?"translate3d(SECONDARYpx,PRIMARYpx,0)":"translate3d(PRIMARYpx,SECONDARYpx,0)",O=R?"height: PRIMARYpx; width: SECONDARYpx;":"height: SECONDARYpx; width: PRIMARYpx;",q=0,U=0,W=-1,F=-1,X=-1,Y=-1,G=[],j=[],K=[],Z={},J=0,Q=R?function(){I.setDimensions(null,null,null,ee.getContentSize(),!0)}:function(){I.setDimensions(null,null,ee.getContentSize(),null,!0)},ee=R?new l:new u;(L?d:f).call(ee),(M?h:p).call(ee);var te=R?"getContentHeight":"getContentWidth",ne=I.options[te];I.options[te]=angular.bind(ee,ee.getContentSize),I.__$callback=I.__callback,I.__callback=function(e,t,n,i){var o=ee.getScrollValue();(-1===W||o+ee.scrollPrimarySize>X||Y>o)&&a(),I.__$callback(e,t,n,i)};var ie=!1,oe=!1;this.refreshLayout=function(){A.length?(v=P(0,A[0]),g=_(0,A[0])):(v=100,g=100);var e=getComputedStyle(m)||{},n=m.firstElementChild&&getComputedStyle(m.firstElementChild)||{},i=m.lastElementChild&&getComputedStyle(m.lastElementChild)||{};U=(parseInt(e[R?"height":"width"])||0)+(n&&parseInt(n[R?"marginTop":"marginLeft"])||0)+(i&&parseInt(i[R?"marginBottom":"marginRight"])||0),q=0;var o=$;do q+=o[R?"offsetTop":"offsetLeft"];while(ionic.DomUtil.contains(I.__content,o=o.offsetParent));var a=$.previousElementSibling,c=a?t.getComputedStyle(a):{},l=parseInt(c[R?"marginBottom":"marginRight"]||0);if($.style[ionic.CSS.TRANSFORM]=H.replace(N,-l).replace(z,0),q-=l,I.__clientHeight&&I.__clientWidth||(I.__clientWidth=I.__container.clientWidth,I.__clientHeight=I.__container.clientHeight),(ee.onRefreshLayout||angular.noop)(),ee.refreshDirection(),Q(),!ie)for(var u=Math.max(20,3*T),d=0;u>d;d++)G.push(new s);ie=!0,ie&&oe&&((I.__scrollLeft>I.__maxScrollLeft||I.__scrollTop>I.__maxScrollTop)&&I.resize(),r(!0))},this.setData=function(e){A=e,(ee.onRefreshData||angular.noop)(),oe=!0},this.destroy=function(){a.destroyed=!0,G.forEach(function(e){e.scope.$destroy(),e.scope=e.element=e.node=e.images=null}),G.length=K.length=j.length=0,Z={},I.options[te]=ne,I.__callback=I.__$callback,I.resize(),(ee.onDestroy||angular.noop)()}}}function n(e){return["$ionicGesture","$parse",function(t,n){var i=e.substr(2).toLowerCase();return function(o,r,a){var c=n(a[e]),s=function(e){o.$apply(function(){c(o,{$event:e})})},l=t.on(i,s,r);o.$on("$destroy",function(){t.off(l,i,s)})}}]}function i(){return["$ionicScrollDelegate",function(e){return{restrict:"E",link:function(t,n,i){function o(t){for(var i=3,o=t.target;i--&&o;){if(o.classList.contains("button")||o.tagName.match(/input|textarea|select/i)||o.isContentEditable)return;o=o.parentNode}var r=t.gesture&&t.gesture.touches[0]||t.detail.touches[0],a=n[0].getBoundingClientRect();ionic.DomUtil.rectContains(r.pageX,r.pageY,a.left,a.top-20,a.left+a.width,a.top+a.height)&&e.scrollTop(!0)}"true"!=i.noTapScroll&&(ionic.on("tap",o,n[0]),t.$on("$destroy",function(){ionic.off("tap",o,n[0])}))}}}]}function o(e){return["$document","$timeout",function(t,n){return{restrict:"E",controller:"$ionicHeaderBar",compile:function(i){function o(t,n,i,o){e?(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subheader");t.$hasHeader=n&&!i,t.$hasSubheader=n&&i,t.$emit("$ionicSubheader",t.$hasSubheader)}),t.$on("$destroy",function(){delete t.$hasHeader,delete t.$hasSubheader}),o.align(),t.$on("$ionicHeader.align",function(){ionic.requestAnimationFrame(function(){o.align()})})):(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subfooter");t.$hasFooter=n&&!i,t.$hasSubfooter=n&&i}),t.$on("$destroy",function(){delete t.$hasFooter,delete t.$hasSubfooter}),t.$watch("$hasTabs",function(e){n.toggleClass("has-tabs",!!e)}))}return i.addClass(e?"bar bar-header":"bar bar-footer"),n(function(){e&&t[0].getElementsByClassName("tabs-top").length&&i.addClass("has-tabs-top")}),{pre:o}}}}]}function r(e){return e.clientHeight}function a(e){e.stopPropagation()}var c=angular.module("ionic",["ngAnimate","ngSanitize","ui.router"]),s=angular.extend,l=angular.forEach,u=angular.isDefined,d=angular.isNumber,f=angular.isString,h=angular.element,p=angular.noop;c.factory("$ionicActionSheet",["$rootScope","$compile","$animate","$timeout","$ionicTemplateLoader","$ionicPlatform","$ionicBody","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c){function l(o){function l(e){e&&/icon/.test(e)&&(u.$actionSheetHasIcon=!0)}var u=e.$new(!0);s(u,{cancel:p,destructiveButtonClicked:p,buttonClicked:p,$deregisterBackButton:p,buttons:[],cancelOnStateChange:!0},o||{});for(var d=0;d<u.buttons.length;d++)l(u.buttons[d].text);l(u.cancelText),l(u.destructiveText);var f=u.element=t('<ion-action-sheet ng-class="cssClass" buttons="buttons"></ion-action-sheet>')(u),v=h(f[0].querySelector(".action-sheet-wrapper")),g=u.cancelOnStateChange?e.$on("$stateChangeSuccess",function(){u.cancel()}):p;return u.removeSheet=function(e){u.removed||(u.removed=!0,v.removeClass("action-sheet-up"),i(function(){a.removeClass("action-sheet-open")},400),u.$deregisterBackButton(),g(),n.removeClass(f,"active").then(function(){u.$destroy(),f.remove(),u.cancel.$scope=v=null,(e||p)()}))},u.showSheet=function(e){u.removed||(a.append(f).addClass("action-sheet-open"),n.addClass(f,"active").then(function(){u.removed||(e||p)()}),i(function(){u.removed||v.addClass("action-sheet-up")},20,!1))},u.$deregisterBackButton=r.registerBackButtonAction(function(){i(u.cancel)},c.actionSheet),u.cancel=function(){u.removeSheet(o.cancel)},u.buttonClicked=function(e){o.buttonClicked(e,o.buttons[e])===!0&&u.removeSheet()},u.destructiveButtonClicked=function(){o.destructiveButtonClicked()===!0&&u.removeSheet()},u.showSheet(),u.cancel.$scope=u,u.cancel}return{show:l}}]),h.prototype.addClass=function(e){var t,n,i,o,r,a;if(e&&"ng-scope"!=e&&"ng-isolate-scope"!=e)for(t=0;t<this.length;t++)if(o=this[t],o.setAttribute)if(e.indexOf(" ")<0&&o.classList.add)o.classList.add(e);else{for(a=(" "+(o.getAttribute("class")||"")+" ").replace(/[\n\t]/g," "),r=e.split(" "),n=0;n<r.length;n++)i=r[n].trim(),-1===a.indexOf(" "+i+" ")&&(a+=i+" ");o.setAttribute("class",a.trim())}return this},h.prototype.removeClass=function(e){var t,n,i,o,r;if(e)for(t=0;t<this.length;t++)if(r=this[t],r.getAttribute)if(e.indexOf(" ")<0&&r.classList.remove)r.classList.remove(e);else for(i=e.split(" "),n=0;n<i.length;n++)o=i[n],r.setAttribute("class",(" "+(r.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+o.trim()+" "," ").trim());return this},c.factory("$ionicBackdrop",["$document","$timeout","$$rAF",function(e,t,n){function i(){c++,1===c&&(a.addClass("visible"),n(function(){c>=1&&a.addClass("active")}))}function o(){1===c&&(a.removeClass("active"),t(function(){0===c&&a.removeClass("visible")},400,!1)),c=Math.max(0,c-1)}function r(){return a}var a=h('<div class="backdrop">'),c=0;return e[0].body.appendChild(a[0]),{retain:i,release:o,getElement:r,_element:a}}]),c.factory("$ionicBind",["$parse","$interpolate",function(e,t){var n=/^\s*([@=&])(\??)\s*(\w*)\s*$/;return function(i,o,r){l(r||{},function(r,a){var c,s,l=r.match(n)||[],u=l[3]||a,d=l[1];switch(d){case"@":if(!o[u])return;o.$observe(u,function(e){i[a]=e}),o[u]&&(i[a]=t(o[u])(i));break;case"=":if(!o[u])return;s=i.$watch(o[u],function(e){i[a]=e}),i.$on("$destroy",s);break;case"&":if(o[u]&&o[u].match(RegExp(a+"(.*?)")))throw new Error('& expression binding "'+a+'" looks like it will recursively call "'+o[u]+'" and cause a stack overflow! Please choose a different scopeName.');c=e(o[u]),i[a]=function(e){return c(i,e)}}})}}]),c.factory("$ionicBody",["$document",function(e){return{addClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.add(arguments[t]);return this},removeClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.remove(arguments[t]);return this},enableClass:function(e){var t=Array.prototype.slice.call(arguments).slice(1);return e?this.addClass.apply(this,t):this.removeClass.apply(this,t),this},append:function(t){return e[0].body.appendChild(t.length?t[0]:t),this},get:function(){return e[0].body}}}]),c.factory("$ionicClickBlock",["$document","$ionicBody","$timeout",function(e,t,n){function i(e){e.preventDefault(),e.stopPropagation()}function o(){s&&(a?a.classList.remove(l):(a=e[0].createElement("div"),a.className="click-block",t.append(a),a.addEventListener("touchstart",i),a.addEventListener("mousedown",i)),s=!1)}function r(){a&&a.classList.add(l)}var a,c,s,l="click-block-hide";return{show:function(e){s=!0,n.cancel(c),c=n(this.hide,e||310,!1),o()},hide:function(){s=!1,n.cancel(c),r()}}}]),c.factory("$ionicGesture",[function(){return{on:function(e,t,n,i){return window.ionic.onGesture(e,t,n[0],i)},off:function(e,t,n){return window.ionic.offGesture(e,t,n)}}}]),c.factory("$ionicHistory",["$rootScope","$state","$location","$window","$timeout","$ionicViewSwitcher","$ionicNavViewDelegate",function(e,t,n,i,o,r,a){function c(e){return e?L.views[e]:null}function l(e){return e?c(e.backViewId):null}function d(e){return e?c(e.forwardViewId):null}function f(e){return e?L.histories[e]:null}function h(e){var t=p(e);return L.histories[t.historyId]||(L.histories[t.historyId]={historyId:t.historyId,parentHistoryId:p(t.scope.$parent).historyId,stack:[],cursor:-1}),f(t.historyId)}function p(t){for(var n=t;n;){if(n.hasOwnProperty("$historyId"))return{historyId:n.$historyId,scope:n};n=n.$parent}return{historyId:"root",scope:e}}function v(e){L.currentView=c(e),L.backView=l(L.currentView),L.forwardView=d(L.currentView)}function g(){var e;if(t&&t.current&&t.current.name){if(e=t.current.name,t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&t.params[n]&&(e+="_"+n+"="+t.params[n]);return e}return ionic.Utils.nextUid()}function m(){var e;if(t&&t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&(e=e||{},e[n]=t.params[n]);return e}function $(e){return e&&e.length&&/ion-side-menus|ion-tabs/i.test(e[0].tagName)}function w(e,t){return t&&t.$$state&&t.$$state.self.canSwipeBack===!1?!1:e&&"false"===e.attr("can-swipe-back")?!1:!0}var b,y,S,k,C,T="initialView",B="newView",I="moveBack",x="moveForward",A="back",E="forward",V="enter",P="exit",D="swap",_="none",R=0,L={histories:{root:{historyId:"root",parentHistoryId:null,stack:[],cursor:-1}},views:{},backView:null,forwardView:null,currentView:null},M=function(){};return M.prototype.initialize=function(e){if(e){for(var t in e)this[t]=e[t];return this}return null},M.prototype.go=function(){if(this.stateName)return t.go(this.stateName,this.stateParams);if(this.url&&this.url!==n.url()){if(L.backView===this)return i.history.go(-1);if(L.forwardView===this)return i.history.go(1);n.url(this.url)}return null},M.prototype.destroy=function(){this.scope&&(this.scope.$destroy&&this.scope.$destroy(),this.scope=null)},{register:function(e,t){var i,a,s,u=g(),d=h(e),$=L.currentView,M=L.backView,N=L.forwardView,z=null,H=null,O=_,q=d.historyId,U=n.url();if(b!==u&&(b=u,R++),C)z=C.viewId,H=C.action,O=C.direction,C=null;else if(M&&M.stateId===u)z=M.viewId,q=M.historyId,H=I,M.historyId===$.historyId?O=A:$&&(O=P,i=f(M.historyId),i&&i.parentHistoryId===$.historyId?O=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(O=D)));else if(N&&N.stateId===u)z=N.viewId,q=N.historyId,H=x,N.historyId===$.historyId?O=E:$&&(O=P,$.historyId===d.parentHistoryId?O=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(O=D))),i=p(e),N.historyId&&i.scope&&(i.scope.$historyId=N.historyId,q=N.historyId);else if($&&$.historyId!==q&&d.cursor>-1&&d.stack.length>0&&d.cursor<d.stack.length&&d.stack[d.cursor].stateId===u){var W=d.stack[d.cursor];z=W.viewId,q=W.historyId,H=I,O=D,i=f($.historyId),i&&i.parentHistoryId===q?O=P:(i=f(q),i&&i.parentHistoryId===$.historyId&&(O=V)),i=c(W.backViewId),i&&W.historyId!==i.historyId&&(d.stack[d.cursor].backViewId=$.viewId)}else{if(s=r.createViewEle(t),this.isAbstractEle(s,t))return{action:"abstractView",direction:_,ele:s};if(z=ionic.Utils.nextUid(),$){if($.forwardViewId=z,H=B,N&&$.stateId!==N.stateId&&$.historyId===N.historyId&&(i=f(N.historyId))){for(a=i.stack.length-1;a>=N.index;a--){var F=i.stack[a];F&&F.destroy&&F.destroy(),i.stack.splice(a)}q=N.historyId}d.historyId===$.historyId?O=E:$.historyId!==d.historyId&&(O=V,i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId?O=D:(i=f(i.parentHistoryId),i&&i.historyId===d.historyId&&(O=P)))}else H=T;2>R&&(O=_),L.views[z]=this.createView({viewId:z,index:d.stack.length,historyId:d.historyId,backViewId:$&&$.viewId?$.viewId:null,forwardViewId:null,stateId:u,stateName:this.currentStateName(),stateParams:m(),url:U,canSwipeBack:w(s,t)}),d.stack.push(L.views[z])}if(S&&S(),o.cancel(k),y){if(y.disableAnimate&&(O=_),y.disableBack&&(L.views[z].backViewId=null),y.historyRoot){for(a=0;a<d.stack.length;a++)d.stack[a].viewId===z?(d.stack[a].index=0,d.stack[a].backViewId=d.stack[a].forwardViewId=null):delete L.views[d.stack[a].viewId];d.stack=[L.views[z]]}y=null}if(v(z),L.backView&&q==L.backView.historyId&&u==L.backView.stateId&&U==L.backView.url)for(a=0;a<d.stack.length;a++)if(d.stack[a].viewId==z){H="dupNav",O=_,a>0&&(d.stack[a-1].forwardViewId=null),L.forwardView=null,L.currentView.index=L.backView.index,L.currentView.backViewId=L.backView.backViewId,L.backView=l(L.backView),d.stack.splice(a,1);break}return d.cursor=L.currentView.index,{viewId:z,action:H,direction:O,historyId:q,enableBack:this.enabledBack(L.currentView),isHistoryRoot:0===L.currentView.index,ele:s}},registerHistory:function(e){e.$historyId=ionic.Utils.nextUid()},createView:function(e){var t=new M;return t.initialize(e)},getViewById:c,viewHistory:function(){return L},currentView:function(e){return arguments.length&&(L.currentView=e),L.currentView},currentHistoryId:function(){return L.currentView?L.currentView.historyId:null},currentTitle:function(e){return L.currentView?(arguments.length&&(L.currentView.title=e),L.currentView.title):void 0},backView:function(e){return arguments.length&&(L.backView=e),L.backView},backTitle:function(e){var t=e&&c(e.backViewId)||L.backView;return t&&t.title},forwardView:function(e){return arguments.length&&(L.forwardView=e),L.forwardView},currentStateName:function(){return t&&t.current?t.current.name:null},isCurrentStateNavView:function(e){return!!(t&&t.current&&t.current.views&&t.current.views[e])},goToHistoryRoot:function(e){if(e){var t=f(e);if(t&&t.stack.length){if(L.currentView&&L.currentView.viewId===t.stack[0].viewId)return;C={viewId:t.stack[0].viewId,action:I,direction:A},t.stack[0].go()}}},goBack:function(e){if(u(e)&&-1!==e){if(e>-1)return;var t=L.histories[this.currentHistoryId()],n=t.cursor+e+1;1>n&&(n=1),t.cursor=n,v(t.stack[n].viewId);for(var i=n-1,r=[],a=c(t.stack[i].forwardViewId);a&&(r.push(a.stateId||a.viewId),i++,!(i>=t.stack.length));)a=c(t.stack[i].forwardViewId);var s=this;r.length&&o(function(){s.clearCache(r)},600)}L.backView&&L.backView.go()},enabledBack:function(e){var t=l(e);return!(!t||t.historyId!==e.historyId)},clearHistory:function(){var e=L.histories,t=L.currentView;if(e)for(var n in e)e[n].stack&&(e[n].stack=[],e[n].cursor=-1),t&&t.historyId===n?(t.backViewId=t.forwardViewId=null,e[n].stack.push(t)):e[n].destroy&&e[n].destroy();for(var i in L.views)i!==t.viewId&&delete L.views[i];t&&v(t.viewId)},clearCache:function(e){o(function(){a._instances.forEach(function(t){t.clearCache(e)})})},nextViewOptions:function(t){return S&&S(),arguments.length&&(o.cancel(k),null===t?y=t:(y=y||{},s(y,t),y.expire&&(S=e.$on("$stateChangeSuccess",function(){k=o(function(){y=null},y.expire)})))),y},isAbstractEle:function(e,t){return t&&t.$$state&&t.$$state.self["abstract"]?!0:!(!e||!$(e)&&!$(e.children()))},isActiveScope:function(e){if(!e)return!1;for(var t,n=e,i=this.currentHistoryId();n;){if(n.$$disconnected)return!1;if(!t&&n.hasOwnProperty("$historyId")&&(t=!0),i){if(n.hasOwnProperty("$historyId")&&i==n.$historyId)return!0;if(n.hasOwnProperty("$activeHistoryId")&&i==n.$activeHistoryId){if(n.hasOwnProperty("$historyId"))return!0;if(!t)return!0}}t&&n.hasOwnProperty("$activeHistoryId")&&(t=!1),n=n.$parent}return i?"root"==i:!0}}}]).run(["$rootScope","$state","$location","$document","$ionicPlatform","$ionicHistory","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a){function c(e){var t=r.backView();return t?t.go():ionic.Platform.exitApp(),e.preventDefault(),!1}e.$on("$ionicView.beforeEnter",function(){ionic.keyboard&&ionic.keyboard.hide&&ionic.keyboard.hide()}),e.$on("$ionicHistory.change",function(e,i){if(!i)return null;var o=r.viewHistory(),a=i.historyId?o.histories[i.historyId]:null;if(a&&a.cursor>-1&&a.cursor<a.stack.length){var c=a.stack[a.cursor];return c.go(i)}!i.url&&i.uiSref&&(i.url=t.href(i.uiSref)),i.url&&(0===i.url.indexOf("#")&&(i.url=i.url.replace("#","")),i.url!==n.url()&&n.url(i.url))}),e.$ionicGoBack=function(e){r.goBack(e)},e.$on("$ionicView.afterEnter",function(e,t){t&&t.title&&(i[0].title=t.title)}),o.registerBackButtonAction(c,a.view)}]),c.provider("$ionicConfig",function(){function e(e,i){a.platform[e]=i,o.platform[e]={},t(a,a.platform[e]),n(a.platform[e],o.platform[e],"")}function t(e,n){for(var i in e)i!=r&&e.hasOwnProperty(i)&&(angular.isObject(e[i])?(u(n[i])||(n[i]={}),t(e[i],n[i])):u(n[i])||(n[i]=null))}function n(e,t,o){l(e,function(c,s){angular.isObject(e[s])?(t[s]={},n(e[s],t[s],o+"."+s)):t[s]=function(n){if(arguments.length)return e[s]=n,t;if(e[s]==r){var c=i(a.platform,ionic.Platform.platform()+o+"."+s);return c||c===!1?c:i(a.platform,"default"+o+"."+s)}return e[s]}})}function i(e,t){t=t.split(".");for(var n=0;n<t.length;n++){if(!e||!u(e[t[n]]))return null;e=e[t[n]]}return e}var o=this;o.platform={};var r="platform",a={views:{maxCache:r,forwardCache:r,transition:r,swipeBackEnabled:r,swipeBackHitWidth:r},navBar:{alignTitle:r,positionPrimaryButtons:r,positionSecondaryButtons:r,transition:r},backButton:{icon:r,text:r,previousTitleText:r},form:{checkbox:r,toggle:r},scrolling:{jsScrolling:r},spinner:{icon:r},tabs:{style:r,position:r},templates:{maxPrefetch:r},platform:{}};n(a,o,""),e("default",{views:{maxCache:10,forwardCache:!1,transition:"ios",swipeBackEnabled:!0,swipeBackHitWidth:45},navBar:{alignTitle:"center",positionPrimaryButtons:"left",positionSecondaryButtons:"right",transition:"view"},backButton:{icon:"ion-ios-arrow-back",text:"Back",previousTitleText:!0},form:{checkbox:"circle",toggle:"large"},scrolling:{jsScrolling:!0},spinner:{icon:"ios"},tabs:{style:"standard",position:"bottom"},templates:{maxPrefetch:30}}),e("ios",{}),e("android",{views:{transition:"android",swipeBackEnabled:!1},navBar:{alignTitle:"left",positionPrimaryButtons:"right",positionSecondaryButtons:"right"},backButton:{icon:"ion-android-arrow-back",text:!1,previousTitleText:!1},form:{checkbox:"square",toggle:"small"},spinner:{icon:"android"},tabs:{style:"striped",position:"top"}}),e("windowsphone",{spinner:{icon:"android"}}),o.transitions={views:{},navBar:{}},o.transitions.views.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,o.opacity=t,i>-1&&(o.boxShadow="0 0 10px rgba(0,0,0,"+(r.shouldAnimate?.45*i:.3)+")"),o[ionic.CSS.TRANSFORM]="translate3d("+n+"%,0,0)",ionic.DomUtil.cachedStyles(e,o)}var r={run:function(i){"forward"==n?(o(e,1,99*(1-i),1-i),o(t,1-.1*i,-33*i,-1)):"back"==n?(o(e,1-.1*(1-i),-33*(1-i),-1),o(t,1,100*i,1-i)):(o(e,1,0,-1),o(t,0,0,-1))},shouldAnimate:i&&("forward"==n||"back"==n)};return r},o.transitions.navBar.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=c.shouldAnimate?"":"0ms",o.opacity=1===t?"":t,e.setCss("buttons-left",o),e.setCss("buttons-right",o),e.setCss("back-button",o),o[ionic.CSS.TRANSFORM]="translate3d("+i+"px,0,0)",e.setCss("back-text",o),o[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e.setCss("title",o)}function r(e,t,n){if(e&&t){var i=(e.titleTextX()+e.titleWidth())*(1-n),r=t&&(t.titleTextX()-e.backButtonTextLeft())*(1-n)||0;o(e,n,i,r)}}function a(e,t,n){if(e&&t){var i=(-(e.titleTextX()-t.backButtonTextLeft())-e.titleLeftRight())*n;o(e,1-n,i,0)}}var c={run:function(n){var i=e.controller(),o=t&&t.controller();"back"==c.direction?(a(i,o,1-n),r(o,i,1-n)):(r(i,o,n),a(o,i,n))},direction:n,shouldAnimate:i&&("forward"==n||"back"==n)};return c},o.transitions.views.android=function(e,t,n,i){function o(e,t){var n={};n[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,n[ionic.CSS.TRANSFORM]="translate3d("+t+"%,0,0)",ionic.DomUtil.cachedStyles(e,n)}i=i&&("forward"==n||"back"==n);var r={run:function(i){"forward"==n?(o(e,99*(1-i)),o(t,-100*i)):"back"==n?(o(e,-100*(1-i)),o(t,100*i)):(o(e,0),o(t,0))},shouldAnimate:i};return r},o.transitions.navBar.android=function(e,t,n,i){function o(e,t){if(e){var n={};n.opacity=1===t?"":t,e.setCss("buttons-left",n),e.setCss("buttons-right",n),e.setCss("back-button",n),e.setCss("back-text",n),e.setCss("title",n)}}return{run:function(n){o(e.controller(),n),o(t&&t.controller(),1-n)},shouldAnimate:i&&("forward"==n||"back"==n)}},o.transitions.views.none=function(e,t){return{run:function(n){o.transitions.views.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.transitions.navBar.none=function(e,t){return{run:function(n){o.transitions.navBar.ios(e,t,!1,!1).run(n), -o.transitions.navBar.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.setPlatformConfig=e,o.$get=function(){return o}}).config(["$compileProvider",function(e){e.aHrefSanitizationWhitelist(/^\s*(https?|tel|ftp|mailto|file|ghttps?|ms-appx|x-wmapp0):/),e.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|x-wmapp0):|data:image\//)}]);var v='<div class="loading-container"><div class="loading"></div></div>',g="$ionicLoading instance.hide() has been deprecated. Use $ionicLoading.hide().",m="$ionicLoading instance.show() has been deprecated. Use $ionicLoading.show().",$="$ionicLoading instance.setContent() has been deprecated. Use $ionicLoading.show({ template: 'my content' }).";c.constant("$ionicLoadingConfig",{template:"<ion-spinner></ion-spinner>"}).factory("$ionicLoading",["$ionicLoadingConfig","$ionicBody","$ionicTemplateLoader","$ionicBackdrop","$timeout","$q","$log","$compile","$ionicPlatform","$rootScope","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c,l,u,d){function f(){return b||(b=n.compile({template:v,appendTo:t.get()}).then(function(e){return e.show=function(a){var s=a.templateUrl?n.load(a.templateUrl):r.when(a.template||a.content||"");e.scope=a.scope||e.scope,e.isShown||(e.hasBackdrop=!a.noBackdrop&&a.showBackdrop!==!1,e.hasBackdrop&&(i.retain(),i.getElement().addClass("backdrop-loading"))),a.duration&&(o.cancel(e.durationTimeout),e.durationTimeout=o(angular.bind(e,e.hide),+a.duration)),y(),y=l.registerBackButtonAction(p,d.loading),s.then(function(n){if(n){var i=e.element.children();i.html(n),c(i.contents())(e.scope)}e.isShown&&(e.element.addClass("visible"),ionic.requestAnimationFrame(function(){e.isShown&&(e.element.addClass("active"),t.addClass("loading-active"))}))}),e.isShown=!0},e.hide=function(){y(),e.isShown&&(e.hasBackdrop&&(i.release(),i.getElement().removeClass("backdrop-loading")),e.element.removeClass("active"),t.removeClass("loading-active"),setTimeout(function(){!e.isShown&&e.element.removeClass("visible")},200)),o.cancel(e.durationTimeout),e.isShown=!1},e})),b}function h(t){t=s({},e||{},t||{});var n=t.delay||t.showDelay||0;return S(),k(),t.hideOnStateChange&&(S=u.$on("$stateChangeSuccess",w),k=u.$on("$stateChangeError",w)),o.cancel(C),C=o(p,n),C.then(f).then(function(e){return e.show(t)}),{hide:function(){return a.error(g),w.apply(this,arguments)},show:function(){return a.error(m),h.apply(this,arguments)},setContent:function(e){return a.error($),f().then(function(t){t.show({template:e})})}}}function w(){S(),k(),o.cancel(C),f().then(function(e){e.hide()})}var b,y=p,S=p,k=p,C=r.when();return{show:h,hide:w,_getLoader:f}}]),c.factory("$ionicModal",["$rootScope","$ionicBody","$compile","$timeout","$ionicPlatform","$ionicTemplateLoader","$$q","$log","$ionicClickBlock","$window","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c,l,u,d){var f=ionic.views.Modal.inherit({initialize:function(e){ionic.views.Modal.prototype.initialize.call(this,e),this.animation=e.animation||"slide-in-up"},show:function(e){var n=this;if(n.scope.$$destroyed)return c.error("Cannot call "+n.viewType+".show() after remove(). Please create a new "+n.viewType+" instance."),a.when();l.show(600),m.add(n);var r=h(n.modalEl);n.el.classList.remove("hide"),i(function(){n._isShown&&t.addClass(n.viewType+"-open")},400,!1),n.el.parentElement||(r.addClass(n.animation),t.append(n.el));var s=r.data("$$ionicScrollController");return s&&s.resize(),e&&n.positionView&&(n.positionView(e,r),n._onWindowResize=function(){n._isShown&&n.positionView(e,r)},ionic.on("resize",n._onWindowResize,window)),r.addClass("ng-enter active").removeClass("ng-leave ng-leave-active"),n._isShown=!0,n._deregisterBackButton=o.registerBackButtonAction(n.hardwareBackButtonClose?angular.bind(n,n.hide):p,d.modal),ionic.views.Modal.prototype.show.call(n),i(function(){n._isShown&&(r.addClass("ng-enter-active"),ionic.trigger("resize"),n.scope.$parent&&n.scope.$parent.$broadcast(n.viewType+".shown",n),n.el.classList.add("active"),n.scope.$broadcast("$ionicHeader.align"))},20),i(function(){n._isShown&&n.$el.on("click",function(e){n.backdropClickToClose&&e.target===n.el&&m.isHighest(n)&&n.hide()})},400)},hide:function(){var e=this,n=h(e.modalEl);return l.show(600),m.remove(e),e.el.classList.remove("active"),n.addClass("ng-leave"),i(function(){e._isShown||n.addClass("ng-leave-active").removeClass("ng-enter ng-enter-active active")},20,!1),e.$el.off("click"),e._isShown=!1,e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".hidden",e),e._deregisterBackButton&&e._deregisterBackButton(),ionic.views.Modal.prototype.hide.call(e),e.positionView&&ionic.off("resize",e._onWindowResize,window),i(function(){t.removeClass(e.viewType+"-open"),e.el.classList.add("hide")},e.hideDelay||320)},remove:function(){var e=this;return e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".removed",e),e.hide().then(function(){e.scope.$destroy(),e.$el.remove()})},isShown:function(){return!!this._isShown}}),v=function(t,i){var o=i.scope&&i.scope.$new()||e.$new(!0);i.viewType=i.viewType||"modal",s(o,{$hasHeader:!1,$hasSubheader:!1,$hasFooter:!1,$hasSubfooter:!1,$hasTabs:!1,$hasTabsTop:!1});var r=n("<ion-"+i.viewType+">"+t+"</ion-"+i.viewType+">")(o);i.$el=r,i.el=r[0],i.modalEl=i.el.querySelector("."+i.viewType);var a=new f(i);return a.scope=o,i.scope||(o[i.viewType]=a),a},g=[],m={add:function(e){g.push(e)},remove:function(e){var t=g.indexOf(e);t>-1&&t<g.length&&g.splice(t,1)},isHighest:function(e){var t=g.indexOf(e);return t>-1&&t===g.length-1}};return{fromTemplate:function(e,t){var n=v(e,t||{});return n},fromTemplateUrl:function(e,t,n){var i;return angular.isFunction(t)&&(i=t,t=n),r.load(e).then(function(e){var n=v(e,t||{});return i&&i(n),n})},stack:m}}]),c.service("$ionicNavBarDelegate",ionic.DelegateService(["align","showBackButton","showBar","title","changeTitle","setTitle","getTitle","back","getPreviousTitle"])),c.service("$ionicNavViewDelegate",ionic.DelegateService(["clearCache"])),c.constant("IONIC_BACK_PRIORITY",{view:100,sideMenu:150,modal:200,actionSheet:300,popup:400,loading:500}).provider("$ionicPlatform",function(){return{$get:["$q",function(e){var t={onHardwareBackButton:function(e){ionic.Platform.ready(function(){document.addEventListener("backbutton",e,!1)})},offHardwareBackButton:function(e){ionic.Platform.ready(function(){document.removeEventListener("backbutton",e)})},$backButtonActions:{},registerBackButtonAction:function(e,n,i){t._hasBackButtonHandler||(t.$backButtonActions={},t.onHardwareBackButton(t.hardwareBackButtonClick),t._hasBackButtonHandler=!0);var o={id:i?i:ionic.Utils.nextUid(),priority:n?n:0,fn:e};return t.$backButtonActions[o.id]=o,function(){delete t.$backButtonActions[o.id]}},hardwareBackButtonClick:function(e){var n,i;for(i in t.$backButtonActions)(!n||t.$backButtonActions[i].priority>=n.priority)&&(n=t.$backButtonActions[i]);return n?(n.fn(e),n):void 0},is:function(e){return ionic.Platform.is(e)},on:function(e,t){return ionic.Platform.ready(function(){document.addEventListener(e,t,!1)}),function(){ionic.Platform.ready(function(){document.removeEventListener(e,t)})}},ready:function(t){var n=e.defer();return ionic.Platform.ready(function(){n.resolve(),t&&t()}),n.promise}};return t}]}}),c.factory("$ionicPopover",["$ionicModal","$ionicPosition","$document","$window",function(e,t,n,i){function o(e,n){var o=h(e.target||e),a=t.offset(o),c=n.prop("offsetWidth"),s=n.prop("offsetHeight"),l=i.innerWidth,u=i.innerHeight,d={left:a.left+a.width/2-c/2},f=h(n[0].querySelector(".popover-arrow"));d.left<r?d.left=r:d.left+c+r>l&&(d.left=l-c-r),a.top+a.height+s>u&&a.top-s>0?(d.top=a.top-s,n.addClass("popover-bottom")):(d.top=a.top+a.height,n.removeClass("popover-bottom")),f.css({left:a.left+a.width/2-f.prop("offsetWidth")/2-d.left+"px"}),n.css({top:d.top+"px",left:d.left+"px",marginLeft:"0",opacity:"1"})}var r=6,a={viewType:"popover",hideDelay:1,animation:"none",positionView:o};return{fromTemplate:function(t,n){return e.fromTemplate(t,ionic.Utils.extend(a,n||{}))},fromTemplateUrl:function(t,n){return e.fromTemplateUrl(t,ionic.Utils.extend(a,n||{}))}}}]);var w='<div class="popup-container" ng-class="cssClass"><div class="popup"><div class="popup-head"><h3 class="popup-title" ng-bind-html="title"></h3><h5 class="popup-sub-title" ng-bind-html="subTitle" ng-if="subTitle"></h5></div><div class="popup-body"></div><div class="popup-buttons" ng-show="buttons.length"><button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button></div></div></div>';c.factory("$ionicPopup",["$ionicTemplateLoader","$ionicBackdrop","$q","$timeout","$rootScope","$ionicBody","$compile","$ionicPlatform","$ionicModal","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c,l,u){function d(t){t=s({scope:null,title:"",buttons:[]},t||{});var c={};return c.scope=(t.scope||o).$new(),c.element=h(w),c.responseDeferred=n.defer(),r.get().appendChild(c.element[0]),a(c.element)(c.scope),s(c.scope,{title:t.title,buttons:t.buttons,subTitle:t.subTitle,cssClass:t.cssClass,$buttonTapped:function(e,t){var n=(e.onTap||p)(t);t=t.originalEvent||t,t.defaultPrevented||c.responseDeferred.resolve(n)}}),n.when(t.templateUrl?e.load(t.templateUrl):t.template||t.content||"").then(function(e){var t=h(c.element[0].querySelector(".popup-body"));e?(t.html(e),a(t.contents())(c.scope)):t.remove()}),c.show=function(){c.isShown||c.removed||(l.stack.add(c),c.isShown=!0,ionic.requestAnimationFrame(function(){c.isShown&&(c.element.removeClass("popup-hidden"),c.element.addClass("popup-showing active"),g(c.element))}))},c.hide=function(e){return e=e||p,c.isShown?(l.stack.remove(c),c.isShown=!1,c.element.removeClass("active"),c.element.addClass("popup-hidden"),void i(e,250,!1)):e()},c.remove=function(){!c.removed&&l.stack.isHighest(c)&&(c.hide(function(){c.element.remove(),c.scope.$destroy()}),c.removed=!0)},c}function f(){var e=S[S.length-1];e&&e.responseDeferred.resolve()}function v(e){function n(){S.push(o),i(o.show,a,!1),o.responseDeferred.promise.then(function(e){var n=S.indexOf(o);return-1!==n&&S.splice(n,1),S.length>0?S[S.length-1].show():(t.release(),i(function(){S.length||r.removeClass("popup-open")},400,!1),(k._backButtonActionDone||p)()),o.remove(),e})}var o=k._createPopup(e),a=0;return S.length>0?(S[S.length-1].hide(),a=y.stackPushDelay):(r.addClass("popup-open"),t.retain(),k._backButtonActionDone=c.registerBackButtonAction(f,u.popup)),o.responseDeferred.promise.close=function(e){o.removed||o.responseDeferred.resolve(e)},o.responseDeferred.notify({close:o.responseDeferred.close}),n(),o.responseDeferred.promise}function g(e){var t=e[0].querySelector("[autofocus]");t&&t.focus()}function m(e){return v(s({buttons:[{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function $(e){return v(s({buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){return!1}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function b(e){var t=o.$new(!0);t.data={};var n="";return e.template&&/<[a-z][\s\S]*>/i.test(e.template)===!1&&(n="<span>"+e.template+"</span>",delete e.template),v(s({template:n+'<input ng-model="data.response" type="'+(e.inputType||"text")+'" placeholder="'+(e.inputPlaceholder||"")+'">',scope:t,buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return t.data.response||""}}]},e||{}))}var y={stackPushDelay:75},S=[],k={show:v,alert:m,confirm:$,prompt:b,_createPopup:d,_popupStack:S};return k}]),c.factory("$ionicPosition",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function i(e){return"static"===(n(e,"position")||"static")}var o=function(t){for(var n=e[0],o=t.offsetParent||n;o&&o!==n&&i(o);)o=o.offsetParent;return o||n};return{position:function(t){var n=this.offset(t),i={top:0,left:0},r=o(t[0]);r!=e[0]&&(i=this.offset(h(r)),i.top+=r.clientTop-r.scrollTop,i.left+=r.clientLeft-r.scrollLeft);var a=t[0].getBoundingClientRect();return{width:a.width||t.prop("offsetWidth"),height:a.height||t.prop("offsetHeight"),top:n.top-i.top,left:n.left-i.left}},offset:function(n){var i=n[0].getBoundingClientRect();return{width:i.width||n.prop("offsetWidth"),height:i.height||n.prop("offsetHeight"),top:i.top+(t.pageYOffset||e[0].documentElement.scrollTop),left:i.left+(t.pageXOffset||e[0].documentElement.scrollLeft)}}}}]),c.service("$ionicScrollDelegate",ionic.DelegateService(["resize","scrollTop","scrollBottom","scrollTo","scrollBy","zoomTo","zoomBy","getScrollPosition","anchorScroll","freezeScroll","freezeAllScrolls","getScrollView"])),c.service("$ionicSideMenuDelegate",ionic.DelegateService(["toggleLeft","toggleRight","getOpenRatio","isOpen","isOpenLeft","isOpenRight","canDragContent","edgeDragThreshold"])),c.service("$ionicSlideBoxDelegate",ionic.DelegateService(["update","slide","select","enableSlide","previous","next","stop","autoPlay","start","currentIndex","selected","slidesCount","count","loop"])),c.service("$ionicTabsDelegate",ionic.DelegateService(["select","selectedIndex"])),function(){var e=[];c.factory("$ionicTemplateCache",["$http","$templateCache","$timeout",function(t,n,i){function o(e){return"undefined"==typeof e?r():(f(e)&&(e=[e]),l(e,function(e){c.push(e)}),void(a&&r()))}function r(){var e;if(o._runCount++,a=!0,0!==c.length){for(var s=0;4>s&&(e=c.pop());)f(e)&&t.get(e,{cache:n}),s++;c.length&&i(r,1e3)}}var a,c=e;return o._runCount=0,o}]).config(["$stateProvider","$ionicConfigProvider",function(t,n){var i=t.state;t.state=function(o,r){if("object"==typeof r){var a=r.prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch();if(a&&f(r.templateUrl)&&e.push(r.templateUrl),angular.isObject(r.views))for(var c in r.views)a=r.views[c].prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch(),a&&f(r.views[c].templateUrl)&&e.push(r.views[c].templateUrl)}return i.call(t,o,r)}}]).run(["$ionicTemplateCache",function(e){e()}])}(),c.factory("$ionicTemplateLoader",["$compile","$controller","$http","$q","$rootScope","$templateCache",function(e,t,n,i,o,r){function a(e){return n.get(e,{cache:r}).then(function(e){return e.data&&e.data.trim()})}function c(n){n=s({template:"",templateUrl:"",scope:null,controller:null,locals:{},appendTo:null},n||{});var r=n.templateUrl?this.load(n.templateUrl):i.when(n.template);return r.then(function(i){var r,a=n.scope||o.$new(),c=h("<div>").html(i).contents();return n.controller&&(r=t(n.controller,s(n.locals,{$scope:a})),c.children().data("$ngControllerController",r)),n.appendTo&&h(n.appendTo).append(c),e(c)(a),{element:c,scope:a}})}return{load:a,compile:c}}]),c.factory("$ionicViewService",["$ionicHistory","$log",function(e,t){function n(e,n){t.warn("$ionicViewService"+e+" is deprecated, please use $ionicHistory"+n+" instead: http://ionicframework.com/docs/nightly/api/service/$ionicHistory/")}n("","");var i={getCurrentView:"currentView",getBackView:"backView",getForwardView:"forwardView",getCurrentStateName:"currentStateName",nextViewOptions:"nextViewOptions",clearHistory:"clearHistory"};return l(i,function(t,o){i[o]=function(){return n("."+o,"."+t),e[t].apply(this,arguments)}}),i}]),c.factory("$ionicViewSwitcher",["$timeout","$document","$q","$ionicClickBlock","$ionicConfig","$ionicNavBarDelegate",function(e,t,n,i,o,r){function a(e,t){return c(e)["abstract"]?c(e).name:t?t.stateId||t.viewId:ionic.Utils.nextUid()}function c(e){return e&&e.$$state&&e.$$state.self||{}}function d(e,t,n,i){var r=c(e),a=g||V(t,"view-transition")||r.viewTransition||o.views.transition()||"ios",l=o.navBar.transition();return n=m||V(t,"view-direction")||r.viewDirection||n||"none",s(f(i),{transition:a,navBarTransition:"view"===l?a:l,direction:n,shouldAnimate:"none"!==a&&"none"!==n})}function f(e){return e=e||{},{viewId:e.viewId,historyId:e.historyId,stateId:e.stateId,stateName:e.stateName,stateParams:e.stateParams}}function p(e,t){return arguments.length>1?void V(e,T,t):V(e,T)}function v(e){if(e&&e.length){var t=e.scope();t&&(t.$emit("$ionicView.unloaded",e.data(C)),t.$destroy()),e.remove()}}var g,m,$="webkitTransitionEnd transitionend",w="$noCache",b="$destroyEle",y="$eleId",S="$accessed",k="$fallbackTimer",C="$viewData",T="nav-view",B="active",I="cached",x="stage",A=0;ionic.transition=ionic.transition||{},ionic.transition.isActive=!1;var E,V=ionic.DomUtil.cachedAttr,P=[],D=1100,_={create:function(t,l,h,T,E,R){var L,M,N,z=++A,H={init:function(e,t){_.isTransitioning(!0),H.loadViewElements(e),H.render(e,function(){t&&t()})},loadViewElements:function(e){var n,i,o,r=t.getViewElements(),c=a(l,h),s=t.activeEleId();for(n=0,i=r.length;i>n&&(o=r.eq(n),o.data(y)===c?o.data(w)?(o.data(y,c+ionic.Utils.nextUid()),o.data(b,!0)):L=o:u(s)&&o.data(y)===s&&(M=o),!L||!M);n++);N=!!L,N||(L=e.ele||_.createViewEle(l),L.data(y,c)),R&&t.activeEleId(c),e.ele=null},render:function(e,n){if(N)ionic.Utils.reconnectScope(L.scope());else{p(L,x);var i=d(l,L,e.direction,h),r=o.transitions.views[i.transition]||o.transitions.views.none;r(L,null,i.direction,!0).run(0),L.data(C,{viewId:i.viewId,historyId:i.historyId,stateName:i.stateName,stateParams:i.stateParams}),(c(l).cache===!1||"false"===c(l).cache||"false"==L.attr("cache-view")||0===o.views.maxCache())&&L.data(w,!0);var a=t.appendViewElement(L,l);delete i.direction,delete i.transition,a.$emit("$ionicView.loaded",i)}L.data(S,Date.now()),n&&n()},transition:function(a,c,u){function v(){p(L,W.shouldAnimate?"entering":B),p(M,W.shouldAnimate?"leaving":I),W.run(1),r._instances.forEach(function(e){e.triggerTransitionStart(z)}),W.shouldAnimate||b()}function w(e){e.target===this&&b()}function b(){b.x||(b.x=!0,L.off($,w),e.cancel(L.data(k)),M&&e.cancel(M.data(k)),H.emit("after",O,q),C&&C.resolve(t),z===A&&(n.all(P).then(_.transitionEnd),H.cleanup(O)),r._instances.forEach(function(e){e.triggerTransitionEnd()}),g=m=h=T=L=M=null)}function y(e){e.target===this&&S()}function S(){p(L,I),p(M,B),L.off($,y),e.cancel(L.data(k)),_.transitionEnd([t])}var C,O=d(l,L,a,h),q=s(s({},O),f(T));O.transitionId=q.transitionId=z,O.fromCache=!!N,O.enableBack=!!c,O.renderStart=E,O.renderEnd=R,V(L.parent(),"nav-view-transition",O.transition),V(L.parent(),"nav-view-direction",O.direction),e.cancel(L.data(k));var U=o.transitions.views[O.transition]||o.transitions.views.none,W=U(L,M,O.direction,O.shouldAnimate&&u&&R);if(W.shouldAnimate&&(L.on($,w),L.data(k,e(b,D)),i.show(D)),E&&(H.emit("before",O,q),p(L,x),W.run(0)),R&&(C=n.defer(),P.push(C.promise)),E&&R)e(v,16);else{if(!R)return p(L,"entering"),p(M,"leaving"),{run:W.run,cancel:function(t){t?(L.on($,y),L.data(k,e(S,D)),i.show(D)):S(),W.shouldAnimate=t,W.run(0),W=null}};R&&v()}},emit:function(e,t,n){var i=L.scope(),o=M&&M.scope();"after"==e&&(i&&i.$emit("$ionicView.enter",t),o?o.$emit("$ionicView.leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView.leave",n)),i&&i.$emit("$ionicView."+e+"Enter",t),o?o.$emit("$ionicView."+e+"Leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView."+e+"Leave",n)},cleanup:function(e){M&&"back"==e.direction&&!o.views.forwardCache()&&v(M);var n,i,r,a=t.getViewElements(),c=a.length,s=c-1>o.views.maxCache(),l=Date.now();for(n=0;c>n;n++)i=a.eq(n),s&&i.data(S)<l?(l=i.data(S),r=a.eq(n)):i.data(b)&&p(i)!=B&&v(i);v(r),L.data(w)&&L.data(b,!0)},enteringEle:function(){return L},leavingEle:function(){return M}};return H},transitionEnd:function(e){l(e,function(e){e.transitionEnd()}),_.isTransitioning(!1),i.hide(),P=[]},nextTransition:function(e){g=e},nextDirection:function(e){m=e},isTransitioning:function(t){return arguments.length&&(ionic.transition.isActive=!!t,e.cancel(E),t&&(E=e(function(){_.isTransitioning(!1)},999))),ionic.transition.isActive},createViewEle:function(e){var n=t[0].createElement("div");return e&&e.$template&&(n.innerHTML=e.$template,1===n.children.length)?(n.children[0].classList.add("pane"),h(n.children[0])):(n.className="pane",h(n))},viewEleIsActive:function(e,t){p(e,t?B:I)},getTransitionData:d,navViewAttr:p,destroyViewEle:v};return _}]),c.config(["$provide",function(e){e.decorator("$compile",["$delegate",function(e){return e.$$addScopeInfo=function(e,t,n,i){var o=n?i?"$isolateScopeNoTemplate":"$isolateScope":"$scope";e.data(o,t)},e}])}]),c.config(["$provide",function(e){function t(e,t){return e.__hash=e.hash,e.hash=function(n){return u(n)&&t(function(){var e=document.querySelector(".scroll-content");e&&(e.scrollTop=0)},0,!1),e.__hash(n)},e}e.decorator("$location",["$delegate","$timeout",t])}]),c.controller("$ionicHeaderBar",["$scope","$element","$attrs","$q","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r){function a(e){return C[e]||(C[e]=t[0].querySelector("."+e)),C[e]}var c="title",s="back-text",l="back-button",u="default-title",d="previous-title",f="hide",h=this,p="",v="",g=0,m=0,$="",w=!1,b=!0,y=!0,S=!1,k=0;h.beforeEnter=function(t){e.$broadcast("$ionicView.beforeEnter",t)},h.title=function(e){return arguments.length&&e!==p&&(a(c).innerHTML=e,p=e,k=0),p},h.enableBack=function(e,t){return arguments.length&&(w=e,t||h.updateBackButton()),w},h.showBack=function(e,t){return arguments.length&&(b=e,t||h.updateBackButton()),b},h.showNavBack=function(e){y=e,h.updateBackButton()},h.updateBackButton=function(){var e;(b&&y&&w)!==S&&(S=b&&y&&w,e=a(l),e&&e.classList[S?"remove":"add"](f)),w&&(e=e||a(l),e&&(h.backButtonIcon!==o.backButton.icon()&&(e=a(l+" .icon"),e&&(h.backButtonIcon=o.backButton.icon(),e.className="icon "+h.backButtonIcon)),h.backButtonText!==o.backButton.text()&&(e=a(l+" .back-text"),e&&(e.textContent=h.backButtonText=o.backButton.text()))))},h.titleTextWidth=function(){if(!k){var e=ionic.DomUtil.getTextBounds(a(c));k=Math.min(e&&e.width||30)}return k},h.titleWidth=function(){var e=h.titleTextWidth(),t=a(c).offsetWidth;return e>t&&(e=t+(g-m-5)),e},h.titleTextX=function(){return t[0].offsetWidth/2-h.titleWidth()/2},h.titleLeftRight=function(){return g-m},h.backButtonTextLeft=function(){for(var e=0,t=a(s);t;)e+=t.offsetLeft,t=t.parentElement;return e},h.resetBackButton=function(e){if(o.backButton.previousTitleText()){var t=a(d);if(t){t.classList.remove(f);var n=e&&r.getViewById(e.viewId),i=r.backTitle(n);i!==v&&(v=t.innerHTML=i)}var c=a(u);c&&c.classList.remove(f)}},h.align=function(e){var i=a(c);e=e||n.alignTitle||o.navBar.alignTitle();var r=h.calcWidths(e,!1);if(b&&v&&o.backButton.previousTitleText()){var s=h.calcWidths(e,!0),l=t[0].offsetWidth-s.titleLeft-s.titleRight;h.titleTextWidth()<=l&&(r=s)}return h.updatePositions(i,r.titleLeft,r.titleRight,r.buttonsLeft,r.buttonsRight,r.css,r.showPrevTitle)},h.calcWidths=function(e,n){var i,o,r,h,p,v,g,m,$,w=a(c),y=a(l),S=t[0].childNodes,k=0,C=0,T=0,B=0,I="",x=0;for(i=0;i<S.length;i++){if(p=S[i],g=0,1==p.nodeType){if(p===w){$=!0;continue}if(p.classList.contains(f))continue;if(b&&p===y){for(o=0;o<p.childNodes.length;o++)if(h=p.childNodes[o],1==h.nodeType)if(h.classList.contains(s))for(r=0;r<h.children.length;r++)if(v=h.children[r],n){if(v.classList.contains(u))continue;x+=v.offsetWidth}else{if(v.classList.contains(d))continue;x+=v.offsetWidth}else x+=h.offsetWidth;else 3==h.nodeType&&h.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(h),x+=m&&m.width||0);g=x||p.offsetWidth}else g=p.offsetWidth}else 3==p.nodeType&&p.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(p),g=m&&m.width||0);$?C+=g:k+=g}if("left"==e)I="title-left",k&&(T=k+15),C&&(B=C+15);else if("right"==e)I="title-right",k&&(T=k+15),C&&(B=C+15);else{var A=Math.max(k,C)+10;A>10&&(T=B=A)}return{backButtonWidth:x,buttonsLeft:k,buttonsRight:C,titleLeft:T,titleRight:B,showPrevTitle:n,css:I}},h.updatePositions=function(e,n,r,c,s,l,p){var v=i.defer();if(e&&(n!==g&&(e.style.left=n?n+"px":"",g=n),r!==m&&(e.style.right=r?r+"px":"",m=r),l!==$&&(l&&e.classList.add(l),$&&e.classList.remove($),$=l)),o.backButton.previousTitleText()){var w=a(d),b=a(u);w&&w.classList[p?"remove":"add"](f),b&&b.classList[p?"add":"remove"](f)}return ionic.requestAnimationFrame(function(){if(e&&e.offsetWidth+10<e.scrollWidth){var n=s+5,i=t[0].offsetWidth-g-h.titleTextWidth()-20;r=n>i?n:i,r!==m&&(e.style.right=r+"px",m=r)}v.resolve()}),v.promise},h.setCss=function(e,t){ionic.DomUtil.cachedStyles(a(e),t)};var C={};e.$on("$destroy",function(){for(var e in C)C[e]=null})}]),c.controller("$ionInfiniteScroll",["$scope","$attrs","$element","$timeout",function(e,t,n,i){function o(){ionic.requestAnimationFrame(function(){n[0].classList.add("active")}),s.isLoading=!0,e.$parent&&e.$parent.$apply(t.onInfinite||"")}function r(){ionic.requestAnimationFrame(function(){n[0].classList.remove("active")}),i(function(){s.jsScrolling&&s.scrollView.resize(),(s.jsScrolling&&s.scrollView.__container&&s.scrollView.__container.offsetHeight>0||!s.jsScrolling)&&s.checkBounds()},30,!1),s.isLoading=!1}function a(){if(!s.isLoading){var e={};if(s.jsScrolling){e=s.getJSMaxScroll();var t=s.scrollView.getValues();(-1!==e.left&&t.left>=e.left||-1!==e.top&&t.top>=e.top)&&o()}else e=s.getNativeMaxScroll(),(-1!==e.left&&s.scrollEl.scrollLeft>=e.left-s.scrollEl.clientWidth||-1!==e.top&&s.scrollEl.scrollTop>=e.top-s.scrollEl.clientHeight)&&o()}}function c(e){var n=(t.distance||"2.5%").trim(),i=-1!==n.indexOf("%");return i?e*(1-parseFloat(n)/100):e-parseFloat(n)}var s=this;s.isLoading=!1,e.icon=function(){return u(t.icon)?t.icon:"ion-load-d"},e.spinner=function(){return u(t.spinner)?t.spinner:""},e.$on("scroll.infiniteScrollComplete",function(){r()}),e.$on("$destroy",function(){s.scrollCtrl&&s.scrollCtrl.$element&&s.scrollCtrl.$element.off("scroll",s.checkBounds),s.scrollEl&&s.scrollEl.removeEventListener&&s.scrollEl.removeEventListener("scroll",s.checkBounds)}),s.checkBounds=ionic.Utils.throttle(a,300),s.getJSMaxScroll=function(){var e=s.scrollView.getScrollMax();return{left:s.scrollView.options.scrollingX?c(e.left):-1,top:s.scrollView.options.scrollingY?c(e.top):-1}},s.getNativeMaxScroll=function(){var e={left:s.scrollEl.scrollWidth,top:s.scrollEl.scrollHeight},t=window.getComputedStyle(s.scrollEl)||{};return{left:"scroll"===t.overflowX||"auto"===t.overflowX||"scroll"===s.scrollEl.style["overflow-x"]?c(e.left):-1,top:"scroll"===t.overflowY||"auto"===t.overflowY||"scroll"===s.scrollEl.style["overflow-y"]?c(e.top):-1}},s.__finishInfiniteScroll=r}]),c.service("$ionicListDelegate",ionic.DelegateService(["showReorder","showDelete","canSwipeItems","closeOptionButtons"])).controller("$ionicList",["$scope","$attrs","$ionicListDelegate","$ionicHistory",function(e,t,n,i){var o=this,r=!0,a=!1,c=!1,s=n._registerInstance(o,t.delegateHandle,function(){return i.isActiveScope(e)});e.$on("$destroy",s),o.showReorder=function(e){return arguments.length&&(a=!!e),a},o.showDelete=function(e){return arguments.length&&(c=!!e),c},o.canSwipeItems=function(e){return arguments.length&&(r=!!e),r},o.closeOptionButtons=function(){o.listView&&o.listView.clearDragEffects()}}]),c.controller("$ionicNavBar",["$scope","$element","$attrs","$compile","$timeout","$ionicNavBarDelegate","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r,a,c){function s(e,t){var n=console.warn||console.log;n&&n.call(console,"navBarController."+e+" is deprecated, please use "+t+" instead")}function d(e){return x[e]?h(x[e]):void 0}function f(){for(var e=0;e<I.length;e++)if(I[e].isActive)return I[e]}function p(){for(var e=0;e<I.length;e++)if(!I[e].isActive)return I[e]}function v(e,t){e&&ionic.DomUtil.cachedAttr(e.containerEle(),"nav-bar",t)}function g(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}var m,$,w,b="hide",y="$ionNavBarController",S="primaryButtons",k="secondaryButtons",C="backButton",T="primaryButtons secondaryButtons leftButtons rightButtons title".split(" "),B=this,I=[],x={},A=!0;t.parent().data(y,B);var E=n.delegateHandle||"navBar"+ionic.Utils.nextUid(),V=r._registerInstance(B,E);B.init=function(){t.addClass("nav-bar-container"),ionic.DomUtil.cachedAttr(t,"nav-bar-transition",a.views.transition()),B.createHeaderBar(!1),B.createHeaderBar(!0),e.$emit("ionNavBar.init",E)},B.createHeaderBar=function(o){function r(e,t){e&&("title"===t?g.append(e):"rightButtons"==t||t==k&&"left"!=a.navBar.positionSecondaryButtons()||t==S&&"right"==a.navBar.positionPrimaryButtons()?(v||(v=h('<div class="buttons buttons-right">'),f.append(v)),t==k?v.append(e):v.prepend(e)):(p||(p=h('<div class="buttons buttons-left">'),m[C]?m[C].after(p):f.prepend(p)),t==k?p.append(e):p.prepend(e)))}var c=h('<div class="nav-bar-block">');ionic.DomUtil.cachedAttr(c,"nav-bar",o?"active":"cached");var s=n.alignTitle||a.navBar.alignTitle(),f=h("<ion-header-bar>").addClass(n["class"]).attr("align-title",s);u(n.noTapScroll)&&f.attr("no-tap-scroll",n.noTapScroll);var p,v,g=h('<div class="title title-'+s+'">'),m={},$={};m[C]=d(C),m[C]&&f.append(m[C]),f.append(g),l(T,function(e){m[e]=d(e),r(m[e],e)});for(var w=0;w<f[0].children.length;w++)f[0].children[w].classList.add("header-item");c.append(f),t.append(i(c)(e.$new()));var y=f.data("$ionHeaderBarController");y.backButtonIcon=a.backButton.icon(),y.backButtonText=a.backButton.text();var B={isActive:o,title:function(e){y.title(e)},setItem:function(e,t){B.removeItem(t),e?("title"===t&&B.title(""),r(e,t),m[t]&&m[t].addClass(b),$[t]=e):m[t]&&m[t].removeClass(b)},removeItem:function(e){$[e]&&($[e].scope().$destroy(),$[e].remove(),$[e]=null)},containerEle:function(){return c},headerBarEle:function(){return f},afterLeave:function(){l(T,function(e){B.removeItem(e)}),y.resetBackButton()},controller:function(){return y},destroy:function(){l(T,function(e){B.removeItem(e)}),c.scope().$destroy();for(var e in m)m[e]&&(m[e].removeData(),m[e]=null);p&&p.removeData(),v&&v.removeData(),g.removeData(),f.removeData(),c.remove(),c=f=g=p=v=null}};return I.push(B),B},B.navElement=function(e,t){return u(t)&&(x[e]=t),x[e]},B.update=function(e){var t=!e.hasHeaderBar&&e.showNavBar;e.transition=a.views.transition(),t||(e.direction="none"),B.enable(t);var n=B.isInitialized?p():f(),i=B.isInitialized?f():null,o=n.controller();o.enableBack(e.enableBack,!0),o.showBack(e.showBack,!0),o.updateBackButton(),B.title(e.title,n),B.showBar(t),e.navBarItems&&l(T,function(t){n.setItem(e.navBarItems[t],t)}),B.transition(n,i,e),B.isInitialized=!0,g("")},B.transition=function(n,i,r){function c(){for(var e=0;e<I.length;e++)I[e].isActive=!1;n.isActive=!0,v(n,"active"),v(i,"cached"),B.activeTransition=d=$=null}var s=n.controller(),l=a.transitions.navBar[r.navBarTransition]||a.transitions.navBar.none,u=r.transitionId;s.beforeEnter(r);var d=l(n,i,r.direction,r.shouldAnimate&&B.isInitialized);ionic.DomUtil.cachedAttr(t,"nav-bar-transition",r.navBarTransition),ionic.DomUtil.cachedAttr(t,"nav-bar-direction",r.direction),d.shouldAnimate&&r.renderEnd?v(n,"stage"):(v(n,"entering"),v(i,"leaving")),s.resetBackButton(r),d.run(0),B.activeTransition={run:function(e){d.shouldAnimate=!1,d.direction="back",d.run(e)},cancel:function(t,o,r){g(o),v(i,"active"),v(n,"cached"),d.shouldAnimate=t,d.run(0),B.activeTransition=d=null;var a;r.showBar!==B.showBar()&&B.showBar(r.showBar),r.showBackButton!==B.showBackButton()&&B.showBackButton(r.showBackButton),a&&e.$apply()},complete:function(e,t){g(t),d.shouldAnimate=e,d.run(1),$=c}},o(s.align,16),(m=function(){w===u&&(v(n,"entering"),v(i,"leaving"),d.run(1),$=function(){w!=u&&d.shouldAnimate||c()},m=null)})()},B.triggerTransitionStart=function(e){w=e,m&&m()},B.triggerTransitionEnd=function(){$&&$()},B.showBar=function(t){return arguments.length&&(B.visibleBar(t),e.$parent.$hasHeader=!!t),!!e.$parent.$hasHeader},B.visibleBar=function(e){e&&!A?(t.removeClass(b),B.align()):!e&&A&&t.addClass(b),A=e},B.enable=function(e){B.visibleBar(e);for(var t=0;t<r._instances.length;t++)r._instances[t]!==B&&r._instances[t].visibleBar(!1)},B.showBackButton=function(t){if(arguments.length){for(var n=0;n<I.length;n++)I[n].controller().showNavBack(!!t);e.$isBackButtonShown=!!t}return e.$isBackButtonShown},B.showActiveBackButton=function(e){var t=f();return t?arguments.length?t.controller().showBack(e):t.controller().showBack():void 0},B.title=function(t,n){return u(t)&&(t=t||"",n=n||f(),n&&n.title(t), -e.$title=t,c.currentTitle(t)),e.$title},B.align=function(e,t){t=t||f(),t&&t.controller().align(e)},B.hasTabsTop=function(e){t[e?"addClass":"removeClass"]("nav-bar-tabs-top")},B.hasBarSubheader=function(e){t[e?"addClass":"removeClass"]("nav-bar-has-subheader")},B.changeTitle=function(e){s("changeTitle(val)","title(val)"),B.title(e)},B.setTitle=function(e){s("setTitle(val)","title(val)"),B.title(e)},B.getTitle=function(){return s("getTitle()","title()"),B.title()},B.back=function(){s("back()","$ionicHistory.goBack()"),c.goBack()},B.getPreviousTitle=function(){s("getPreviousTitle()","$ionicHistory.backTitle()"),c.goBack()},e.$on("$destroy",function(){e.$parent.$hasHeader=!1,t.parent().removeData(y);for(var n=0;n<I.length;n++)I[n].destroy();t.remove(),t=I=null,V()})}]),c.controller("$ionicNavView",["$scope","$element","$attrs","$compile","$controller","$ionicNavBarDelegate","$ionicNavViewDelegate","$ionicHistory","$ionicViewSwitcher","$ionicConfig","$ionicScrollDelegate",function(e,t,n,i,o,r,a,c,l,u,d){function f(e,n){for(var i,o,r=t.children(),a=0,c=r.length;c>a;a++)if(i=r.eq(a),A(i)==T){o=i.scope(),o&&o.$emit(e.name.replace("Tabs","View"),n);break}}function h(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}function p(e,t){var n=g();n&&n.hasTabsTop(t)}function v(e,t){var n=g();n&&n.hasBarSubheader(t)}function g(){if($)for(var e=0;e<r._instances.length;e++)if(r._instances[e].$$delegateHandle==$)return r._instances[e];return t.inheritedData("$ionNavBarController")}var m,$,w,b,y,S="$eleId",k="$destroyEle",C="$noCache",T="active",B="cached",I=this,x=!1,A=l.navViewAttr;I.scope=e,I.element=t,I.init=function(){var i=n.name||"",o=t.parent().inheritedData("$uiView"),r=o&&o.state?o.state.name:"";i.indexOf("@")<0&&(i=i+"@"+r);var c={name:i,state:null};t.data("$uiView",c);var s=a._registerInstance(I,n.delegateHandle);return e.$on("$destroy",function(){s(),I.isSwipeFreeze&&d.freezeAllScrolls(!1)}),e.$on("$ionicHistory.deselect",I.cacheCleanup),e.$on("$ionicTabs.top",p),e.$on("$ionicSubheader",v),e.$on("$ionicTabs.beforeLeave",f),e.$on("$ionicTabs.afterLeave",f),e.$on("$ionicTabs.leave",f),ionic.Platform.ready(function(){ionic.Platform.isWebView()&&u.views.swipeBackEnabled()&&I.initSwipeBack()}),c},I.register=function(t){var n=s({},c.currentView()),i=c.register(e,t);I.update(i);var o=c.getViewById(i.viewId)||{},r=b!==i.viewId;I.render(i,t,o,n,r,!0)},I.update=function(e){x=!0,m=e.direction;var n=t.parent().inheritedData("$ionNavViewController");n&&(n.isPrimary(!1),("enter"===m||"exit"===m)&&(n.direction(m),"enter"===m&&(m="none")))},I.render=function(e,t,n,i,o,r){var a=l.create(I,t,n,i,o,r);a.init(e,function(){a.transition(I.direction(),e.enableBack,!y),b=y=null})},I.beforeEnter=function(e){if(x){$=e.navBarDelegate;var t=g();t&&t.update(e),h("")}},I.activeEleId=function(e){return arguments.length&&(w=e),w},I.transitionEnd=function(){var e,n,i,o=t.children();for(e=0,n=o.length;n>e;e++)i=o.eq(e),i.data(S)===w?A(i,T):("leaving"===A(i)||A(i)===T||A(i)===B)&&(i.data(k)||i.data(C)?l.destroyViewEle(i):(A(i,B),ionic.Utils.disconnectScope(i.scope())));h(""),I.isSwipeFreeze&&d.freezeAllScrolls(!1)},I.cacheCleanup=function(){for(var e=t.children(),n=0,i=e.length;i>n;n++)e.eq(n).data(k)&&l.destroyViewEle(e.eq(n))},I.clearCache=function(e){var n,i,o,r,a,c,s=t.children();for(o=0,r=s.length;r>o;o++)if(n=s.eq(o),e)for(c=n.data(S),a=0;a<e.length;a++)c===e[a]&&l.destroyViewEle(n);else A(n)==B?l.destroyViewEle(n):A(n)==T&&(i=n.scope(),i&&i.$broadcast("$ionicView.clearCache"))},I.getViewElements=function(){return t.children()},I.appendViewElement=function(n,r){var a=i(n);t.append(n);var c=e.$new();if(r&&r.$$controller){r.$scope=c;var s=o(r.$$controller,r);t.children().data("$ngControllerController",s)}return a(c),c},I.title=function(e){var t=g();t&&t.title(e)},I.enableBackButton=function(e){var t=g();t&&t.enableBackButton(e)},I.showBackButton=function(e){var t=g();return t?arguments.length?t.showActiveBackButton(e):t.showActiveBackButton():!0},I.showBar=function(e){var t=g();return t?arguments.length?t.showBar(e):t.showBar():!0},I.isPrimary=function(e){return arguments.length&&(x=e),x},I.direction=function(e){return arguments.length&&(m=e),m},I.initSwipeBack=function(){function n(e){if(x&&(S=r(e),!(S>C))){p=c.backView();var n=c.currentView();if(p&&p.historyId===n.historyId&&n.canSwipeBack!==!1){w||(w=window.innerWidth),I.isSwipeFreeze=d.freezeAllScrolls(!0);var a={direction:"back"};k=[],T={showBar:I.showBar(),showBackButton:I.showBackButton()};var u=l.create(I,a,p,n,!0,!1);u.loadViewElements(a),u.render(a),s=u.transition("back",c.enabledBack(p),!0),f=g(),m=ionic.onGesture("drag",i,t[0]),$=ionic.onGesture("release",o,t[0])}}}function i(e){if(x&&s){var t=r(e);if(k.push({t:Date.now(),x:t}),t>=w-15)o(e);else{var n=Math.min(Math.max(a(t),0),1);s.run(n),f&&f.activeTransition&&f.activeTransition.run(n)}}}function o(e){if(x&&s&&k&&k.length>1){for(var t=Date.now(),n=r(e),c=k[k.length-1],l=k.length-2;l>=0&&!(t-c.t>200);l--)c=k[l];var u=n>=k[k.length-2].x,v=a(n),g=Math.abs(c.x-n)/(t-c.t);if(b=p.viewId,y=.03>v||v>.97,u&&(v>.5||g>.1)){var S=g>.5||.05>g||n>w-45?"fast":"slow";h(y?"":S),p.go(),f&&f.activeTransition&&f.activeTransition.complete(!y,S)}else h(y?"":"fast"),b=null,s.cancel(!y),f&&f.activeTransition&&f.activeTransition.cancel(!y,"fast",T),y=null}ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),w=s=k=null,I.isSwipeFreeze=d.freezeAllScrolls(!1)}function r(e){return ionic.tap.pointerCoord(e.gesture.srcEvent).x}function a(e){return(e-S)/w}var s,f,p,v,m,$,w,S,k,C=u.views.swipeBackHitWidth(),T={};v=ionic.onGesture("dragstart",n,t[0]),e.$on("$destroy",function(){ionic.offGesture(v,"dragstart",n),ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),I.element=s=f=null})}}]),c.controller("$ionicRefresher",["$scope","$attrs","$element","$ionicBind","$timeout",function(e,t,n,i,o){function r(){(P||k)&&(E=null,k?(k=!1,T=0,B>I?(g(),f(I,A)):(f(0,A,v),C=!1)):(T=0,C=!1,d(!1)))}function a(e){if(P&&!(e.touches.length>1)){if(null===E&&(E=parseInt(e.touches[0].screenY,10)),ionic.Platform.isAndroid()&&4.4===ionic.Platform.version()&&0===b.scrollTop&&(k=!0,e.preventDefault()),V=parseInt(e.touches[0].screenY,10)-E,0>=V-T||0!==b.scrollTop)return C&&(C=!1,d(!1)),k&&l(b,-1*parseInt(V-T,10)),void(0!==B&&s(0));V>0&&0===b.scrollTop&&!C&&(T=V),e.preventDefault(),C||(C=!0,d(!0)),k=!0,s(parseInt((V-T)/3,10)),!x&&B>I?(x=!0,ionic.requestAnimationFrame(p)):x&&I>B&&(x=!1,ionic.requestAnimationFrame(v))}}function c(e){P=0===e.target.scrollTop||k}function s(e){y.style[ionic.CSS.TRANSFORM]="translateY("+e+"px)",B=e}function l(e,t){e.scrollTop=t;var n=document.createEvent("UIEvents");n.initUIEvent("scroll",!0,!0,window,1),e.dispatchEvent(n)}function d(e){ionic.requestAnimationFrame(e?function(){y.classList.add("overscroll"),m()}:function(){y.classList.remove("overscroll"),$(),v()})}function f(e,t,n){function i(e){return--e*e*e+1}function o(){var c=Date.now(),l=Math.min(1,(c-r)/t),u=i(l);s(parseInt(u*(e-a)+a,10)),1>l?ionic.requestAnimationFrame(o):(5>e&&e>-5&&(C=!1,d(!1)),n&&n())}var r=Date.now(),a=B;return a===e?void n():void ionic.requestAnimationFrame(o)}function h(){ionic.off("touchmove",a,y),ionic.off("touchend",r,y),ionic.off("scroll",c,b),b=null,y=null}function p(){n[0].classList.add("active"),e.$onPulling()}function v(){o(function(){n.removeClass("active refreshing refreshing-tail"),x&&(x=!1)},150)}function g(){n[0].classList.add("refreshing"),e.$onRefresh()}function m(){n[0].classList.remove("invisible")}function $(){n[0].classList.add("invisible")}function w(){n[0].classList.add("refreshing-tail")}var b,y,S=this,k=!1,C=!1,T=0,B=0,I=60,x=!1,A=500,E=null,V=null,P=!0;u(t.pullingIcon)||t.$set("pullingIcon","ion-android-arrow-down"),e.showSpinner=!u(t.refreshingIcon)&&"none"!=t.spinner,e.showIcon=u(t.refreshingIcon),i(e,t,{pullingIcon:"@",pullingText:"@",refreshingIcon:"@",refreshingText:"@",spinner:"@",disablePullingRotation:"@",$onRefresh:"&onRefresh",$onPulling:"&onPulling"}),e.$on("scroll.refreshComplete",function(){o(function(){ionic.requestAnimationFrame(w),f(0,A,v),o(function(){C&&(C=!1,d(!1))},A)},A)}),S.init=function(){if(b=n.parent().parent()[0],y=n.parent()[0],!(b&&b.classList.contains("ionic-scroll")&&y&&y.classList.contains("scroll")))throw new Error("Refresher must be immediate child of ion-content or ion-scroll");ionic.on("touchmove",a,y),ionic.on("touchend",r,y),ionic.on("scroll",c,b),e.$on("$destroy",h)},S.getRefresherDomMethods=function(){return{activate:p,deactivate:v,start:g,show:m,hide:$,tail:w}},S.__handleTouchmove=a,S.__getScrollChild=function(){return y},S.__getScrollParent=function(){return b}}]),c.controller("$ionicScroll",["$scope","scrollViewOptions","$timeout","$window","$location","$document","$ionicScrollDelegate","$ionicHistory",function(e,t,n,i,o,r,a,c){var s=this;s.__timeout=n,s._scrollViewOptions=t,s.isNative=function(){return!!t.nativeScrolling};var l,d=s.element=t.el,f=s.$element=h(d);l=s.isNative()?s.scrollView=new ionic.views.ScrollNative(t):s.scrollView=new ionic.views.Scroll(t),(f.parent().length?f.parent():f).data("$$ionicScrollController",s);var p=a._registerInstance(s,t.delegateHandle,function(){return c.isActiveScope(e)});u(t.bouncing)||ionic.Platform.ready(function(){l.options&&(l.options.bouncing=!0,ionic.Platform.isAndroid()&&(l.options.bouncing=!1,l.options.deceleration=.95))});var v=angular.bind(l,l.resize);angular.element(i).on("resize",v);var g=function(t){var n=(t.originalEvent||t).detail||{};e.$onScroll&&e.$onScroll({event:t,scrollTop:n.scrollTop||0,scrollLeft:n.scrollLeft||0})};f.on("scroll",g),e.$on("$destroy",function(){p(),l&&l.__cleanup&&l.__cleanup(),angular.element(i).off("resize",v),f.off("scroll",g),l=s.scrollView=t=s._scrollViewOptions=t.el=s._scrollViewOptions.el=f=s.$element=d=null}),n(function(){l&&l.run&&l.run()}),s.getScrollView=function(){return l},s.getScrollPosition=function(){return l.getValues()},s.resize=function(){return n(v,0,!1).then(function(){f&&f.triggerHandler("scroll-resize")})},s.scrollTop=function(e){s.resize().then(function(){l.scrollTo(0,0,!!e)})},s.scrollBottom=function(e){s.resize().then(function(){var t=l.getScrollMax();l.scrollTo(t.left,t.top,!!e)})},s.scrollTo=function(e,t,n){s.resize().then(function(){l.scrollTo(e,t,!!n)})},s.zoomTo=function(e,t,n,i){s.resize().then(function(){l.zoomTo(e,!!t,n,i)})},s.zoomBy=function(e,t,n,i){s.resize().then(function(){l.zoomBy(e,!!t,n,i)})},s.scrollBy=function(e,t,n){s.resize().then(function(){l.scrollBy(e,t,!!n)})},s.anchorScroll=function(e){s.resize().then(function(){var t=o.hash(),n=t&&r[0].getElementById(t);if(!t||!n)return void l.scrollTo(0,0,!!e);var i=n,a=0,c=0;do null!==i&&(a+=i.offsetLeft),null!==i&&(c+=i.offsetTop),i=i.offsetParent;while(i.attributes!=s.element.attributes&&i.offsetParent);l.scrollTo(a,c,!!e)})},s.freezeScroll=l.freeze,s.freezeAllScrolls=function(e){for(var t=0;t<a._instances.length;t++)a._instances[t].freezeScroll(e)},s._setRefresher=function(e,t,n){s.refresher=t;var i=s.refresher.clientHeight||60;l.activatePullToRefresh(i,n)}}]),c.controller("$ionicSideMenus",["$scope","$attrs","$ionicSideMenuDelegate","$ionicPlatform","$ionicBody","$ionicHistory","$ionicScrollDelegate","IONIC_BACK_PRIORITY","$rootScope",function(e,t,n,i,o,r,a,c,s){function l(e){e&&!w.isScrollFreeze?a.freezeAllScrolls(e):!e&&w.isScrollFreeze&&a.freezeAllScrolls(!1),w.isScrollFreeze=e}var u,f,h,v,g,m,$,w=this,b=!0;w.$scope=e,w.initialize=function(e){w.left=e.left,w.right=e.right,w.setContent(e.content),w.dragThresholdX=e.dragThresholdX||10,r.registerHistory(w.$scope)},w.setContent=function(e){e&&(w.content=e,w.content.onDrag=function(e){w._handleDrag(e)},w.content.endDrag=function(e){w._endDrag(e)})},w.isOpenLeft=function(){return w.getOpenAmount()>0},w.isOpenRight=function(){return w.getOpenAmount()<0},w.toggleLeft=function(e){if(!$&&w.left.isEnabled){var t=w.getOpenAmount();0===arguments.length&&(e=0>=t),w.content.enableAnimation(),e?(w.openPercentage(100),s.$emit("$ionicSideMenuOpen","left")):(w.openPercentage(0),s.$emit("$ionicSideMenuClose","left"))}},w.toggleRight=function(e){if(!$&&w.right.isEnabled){var t=w.getOpenAmount();0===arguments.length&&(e=t>=0),w.content.enableAnimation(),e?(w.openPercentage(-100),s.$emit("$ionicSideMenuOpen","right")):(w.openPercentage(0),s.$emit("$ionicSideMenuClose","right"))}},w.toggle=function(e){"right"==e?w.toggleRight():w.toggleLeft()},w.close=function(){w.openPercentage(0),s.$emit("$ionicSideMenuClose","left"),s.$emit("$ionicSideMenuClose","right")},w.getOpenAmount=function(){return w.content&&w.content.getTranslateX()||0},w.getOpenRatio=function(){var e=w.getOpenAmount();return e>=0?e/w.left.width:e/w.right.width},w.isOpen=function(){return 0!==w.getOpenAmount()},w.getOpenPercentage=function(){return 100*w.getOpenRatio()},w.openPercentage=function(e){var t=e/100;w.left&&e>=0?w.openAmount(w.left.width*t):w.right&&0>e&&w.openAmount(w.right.width*t),o.enableClass(0!==e,"menu-open"),l(!1)},w.openAmount=function(e){var t=w.left&&w.left.width||0,n=w.right&&w.right.width||0;return(w.left&&w.left.isEnabled||!(e>0))&&(w.right&&w.right.isEnabled||!(0>e))?f&&e>t?void w.content.setTranslateX(t):u&&-n>e?void w.content.setTranslateX(-n):(w.content.setTranslateX(e),void(e>=0?(f=!0,u=!1,e>0&&(w.right&&w.right.pushDown&&w.right.pushDown(),w.left&&w.left.bringUp&&w.left.bringUp())):(u=!0,f=!1,w.right&&w.right.bringUp&&w.right.bringUp(),w.left&&w.left.pushDown&&w.left.pushDown()))):void w.content.setTranslateX(0)},w.snapToRest=function(e){w.content.enableAnimation(),h=!1;var t=w.getOpenRatio();if(0===t)return void w.openPercentage(0);var n=.3,i=e.gesture.velocityX,o=e.gesture.direction;w.openPercentage(t>0&&.5>t&&"right"==o&&n>i?0:t>.5&&"left"==o&&n>i?100:0>t&&t>-.5&&"left"==o&&n>i?0:.5>t&&"right"==o&&n>i?-100:"right"==o&&t>=0&&(t>=.5||i>n)?100:"left"==o&&0>=t&&(-.5>=t||i>n)?-100:0)},w.enableMenuWithBackViews=function(e){return arguments.length&&(b=!!e),b},w.isAsideExposed=function(){return!!$},w.exposeAside=function(e){(w.left&&w.left.isEnabled||w.right&&w.right.isEnabled)&&(w.close(),$=e,w.left&&w.left.isEnabled?w.content.setMarginLeft($?w.left.width:0):w.right&&w.right.isEnabled&&w.content.setMarginRight($?w.right.width:0),w.$scope.$emit("$ionicExposeAside",$))},w.activeAsideResizing=function(e){o.enableClass(e,"aside-resizing")},w._endDrag=function(e){l(!1),$||(h&&w.snapToRest(e),v=null,g=null,m=null)},w._handleDrag=function(t){!$&&e.dragContent&&(v?g=t.gesture.touches[0].pageX:(v=t.gesture.touches[0].pageX,g=v),!h&&Math.abs(g-v)>w.dragThresholdX&&(v=g,h=!0,w.content.disableAnimation(),m=w.getOpenAmount()),h&&(w.openAmount(m+(g-v)),l(!0)))},w.canDragContent=function(t){return arguments.length&&(e.dragContent=!!t),e.dragContent},w.edgeThreshold=25,w.edgeThresholdEnabled=!1,w.edgeDragThreshold=function(e){return arguments.length&&(d(e)&&e>0?(w.edgeThreshold=e,w.edgeThresholdEnabled=!0):w.edgeThresholdEnabled=!!e),w.edgeThresholdEnabled},w.isDraggableTarget=function(t){var n=w.edgeThresholdEnabled&&!w.isOpen(),i=t.gesture.startEvent&&t.gesture.startEvent.center&&t.gesture.startEvent.center.pageX,o=!n||i<=w.edgeThreshold||i>=w.content.element.offsetWidth-w.edgeThreshold,a=r.backView(),c=b?!0:!a;if(!c){var s=r.currentView()||{};return a.historyId!==s.historyId}return(e.dragContent||w.isOpen())&&o&&!t.gesture.srcEvent.defaultPrevented&&c&&!t.target.tagName.match(/input|textarea|select|object|embed/i)&&!t.target.isContentEditable&&!(t.target.dataset?t.target.dataset.preventScroll:"true"==t.target.getAttribute("data-prevent-scroll"))},e.sideMenuContentTranslateX=0;var y=p,S=angular.bind(w,w.close);e.$watch(function(){return 0!==w.getOpenAmount()},function(e){y(),e&&(y=i.registerBackButtonAction(S,c.sideMenu))});var k=n._registerInstance(w,t.delegateHandle,function(){return r.isActiveScope(e)});e.$on("$destroy",function(){k(),y(),w.$scope=null,w.content&&(w.content.element=null,w.content=null),l(!1)}),w.initialize({left:{width:275},right:{width:275}})}]),function(e){function t(e,i,o,r){var a,c,s,l=document.createElement(f[e]||e);for(a in i)if(angular.isArray(i[a]))for(c=0;c<i[a].length;c++)if(i[a][c].fn)for(s=0;s<i[a][c].t;s++)t(a,i[a][c].fn(s,r),l,r);else t(a,i[a][c],l,r);else n(l,a,i[a]);o.appendChild(l)}function n(e,t,n){e.setAttribute(f[t]||t,n)}function i(e,t){var n=e.split(";"),i=n.slice(t),o=n.slice(0,n.length-i.length);return n=i.concat(o).reverse(),n.join(";")+";"+n[0]}function o(e,t){return e/=t/2,1>e?.5*e*e*e:(e-=2,.5*(e*e*e+2))}var r="translate(32,32)",a="stroke-opacity",s="round",l="indefinite",u="750ms",d="none",f={a:"animate",an:"attributeName",at:"animateTransform",c:"circle",da:"stroke-dasharray",os:"stroke-dashoffset",f:"fill",lc:"stroke-linecap",rc:"repeatCount",sw:"stroke-width",t:"transform",v:"values"},h={v:"0,32,32;360,32,32",an:"transform",type:"rotate",rc:l,dur:u},p={sw:4,lc:s,line:[{fn:function(e,t){return{y1:"ios"==t?17:12,y2:"ios"==t?29:20,t:r+" rotate("+(30*e+(6>e?180:-180))+")",a:[{fn:function(){return{an:a,dur:u,v:i("0;.1;.15;.25;.35;.45;.55;.65;.7;.85;1",e),rc:l}},t:1}]}},t:12}]},v={android:{c:[{sw:6,da:128,os:82,r:26,cx:32,cy:32,f:d}]},ios:p,"ios-small":p,bubbles:{sw:0,c:[{fn:function(e){return{cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,a:[{fn:function(){return{an:"r",dur:u,v:i("1;2;3;4;5;6;7;8",e),rc:l}},t:1}]}},t:8}]},circles:{c:[{fn:function(e){return{r:5,cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".3;.3;.3;.4;.7;.85;.9;1",e),rc:l}},t:1}]}},t:8}]},crescent:{c:[{sw:4,da:128,os:82,r:26,cx:32,cy:32,f:d,at:[h]}]},dots:{c:[{fn:function(e){return{cx:16+16*e,cy:32,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".5;.6;.8;1;.8;.6;.5",e),rc:l}},t:1},{fn:function(){return{an:"r",dur:u,v:i("4;5;6;5;4;3;3",e),rc:l}},t:1}]}},t:3}]},lines:{sw:7,lc:s,line:[{fn:function(e){return{x1:10+14*e,x2:10+14*e,a:[{fn:function(){return{an:"y1",dur:u,v:i("16;18;28;18;16",e),rc:l}},t:1},{fn:function(){return{an:"y2",dur:u,v:i("48;44;36;46;48",e),rc:l}},t:1},{fn:function(){return{an:a,dur:u,v:i("1;.8;.5;.4;1",e),rc:l}},t:1}]}},t:4}]},ripple:{f:d,"fill-rule":"evenodd",sw:3,circle:[{fn:function(e){return{cx:32,cy:32,a:[{fn:function(){return{an:"r",begin:-1*e+"s",dur:"2s",v:"0;24",keyTimes:"0;1",keySplines:"0.1,0.2,0.3,1",calcMode:"spline",rc:l}},t:1},{fn:function(){return{an:a,begin:-1*e+"s",dur:"2s",v:".2;1;.2;0",rc:l}},t:1}]}},t:2}]},spiral:{defs:[{linearGradient:[{id:"sGD",gradientUnits:"userSpaceOnUse",x1:55,y1:46,x2:2,y2:46,stop:[{offset:.1,"class":"stop1"},{offset:1,"class":"stop2"}]}]}],g:[{sw:4,lc:s,f:d,path:[{stroke:"url(#sGD)",d:"M4,32 c0,15,12,28,28,28c8,0,16-4,21-9"},{d:"M60,32 C60,16,47.464,4,32,4S4,16,4,32"}],at:[h]}]}},g={android:function(t){function i(){var t=o(Date.now()-r,650),u=1,d=0,f=188-58*t,h=182-182*t;a%2&&(u=-1,d=-64,f=128- -58*t,h=182*t);var p=[0,-101,-90,-11,-180,79,-270,-191][a];n(l,"da",Math.max(Math.min(f,188),128)),n(l,"os",Math.max(Math.min(h,182),0)),n(l,"t","scale("+u+",1) translate("+d+",0) rotate("+p+",32,32)"),c+=4.1,c>359&&(c=0),n(s,"t","rotate("+c+",32,32)"),t>=1&&(a++,a>7&&(a=0),r=Date.now()),e.requestAnimationFrame(i)}var r,a=0,c=0,s=t.querySelector("g"),l=t.querySelector("circle");return function(){r=Date.now(),i()}}};c.controller("$ionicSpinner",["$element","$attrs","$ionicConfig",function(e,n,i){var o;this.init=function(){o=n.icon||i.spinner.icon();var r=document.createElement("div");return t("svg",{viewBox:"0 0 64 64",g:[v[o]]},r,o),e.html(r.innerHTML),this.start(),o},this.start=function(){g[o]&&g[o](e[0])()}}])}(ionic),c.controller("$ionicTab",["$scope","$ionicHistory","$attrs","$location","$state",function(e,t,n,i,o){this.$scope=e,this.hrefMatchesState=function(){return n.href&&0===i.path().indexOf(n.href.replace(/^#/,"").replace(/\/$/,""))},this.srefMatchesState=function(){return n.uiSref&&o.includes(n.uiSref.split("(")[0])},this.navNameMatchesState=function(){return this.navViewName&&t.isCurrentStateNavView(this.navViewName)},this.tabMatchesState=function(){return this.hrefMatchesState()||this.srefMatchesState()||this.navNameMatchesState()}}]),c.controller("$ionicTabs",["$scope","$element","$ionicHistory",function(e,t,n){var i,o=this,r=null,a=null;o.tabs=[],o.selectedIndex=function(){return o.tabs.indexOf(r)},o.selectedTab=function(){return r},o.previousSelectedTab=function(){return a},o.add=function(e){n.registerHistory(e),o.tabs.push(e)},o.remove=function(e){var t=o.tabs.indexOf(e);if(-1!==t){if(e.$tabSelected)if(o.deselect(e),1===o.tabs.length);else{var n=t===o.tabs.length-1?t-1:t+1;o.select(o.tabs[n])}o.tabs.splice(t,1)}},o.deselect=function(e){e.$tabSelected&&(a=r,r=i=null,e.$tabSelected=!1,(e.onDeselect||p)(),e.$broadcast&&e.$broadcast("$ionicHistory.deselect"))},o.select=function(t,a){var c;if(d(t)){if(c=t,c>=o.tabs.length)return;t=o.tabs[c]}else c=o.tabs.indexOf(t);1===arguments.length&&(a=!(!t.navViewName&&!t.uiSref)),r&&r.$historyId==t.$historyId?a&&n.goToHistoryRoot(t.$historyId):i!==c&&(l(o.tabs,function(e){o.deselect(e)}),r=t,i=c,o.$scope&&o.$scope.$parent&&(o.$scope.$parent.$activeHistoryId=t.$historyId),t.$tabSelected=!0,(t.onSelect||p)(),a&&e.$emit("$ionicHistory.change",{type:"tab",tabIndex:c,historyId:t.$historyId,navViewName:t.navViewName,hasNavView:!!t.navViewName,title:t.title,url:t.href,uiSref:t.uiSref}))},o.hasActiveScope=function(){for(var e=0;e<o.tabs.length;e++)if(n.isActiveScope(o.tabs[e]))return!0;return!1}}]),c.controller("$ionicView",["$scope","$element","$attrs","$compile","$rootScope",function(e,t,n,i,o){function r(){var t=u(n.viewTitle)&&"viewTitle"||u(n.title)&&"title";t&&(a(n[t]),$.push(n.$observe(t,a))),u(n.hideBackButton)&&$.push(e.$watch(n.hideBackButton,function(e){f.showBackButton(!e)})),u(n.hideNavBar)&&$.push(e.$watch(n.hideNavBar,function(e){f.showBar(!e)}))}function a(e){u(e)&&e!==v&&(v=e,f.title(v))}function c(){for(var e=0;e<$.length;e++)$[e]();$=[]}function l(t){return t?i(t)(e.$new()):void 0}function d(t){return!!e.$eval(n[t])}var f,h,p,v,g=this,m={},$=[],w=e.$on("ionNavBar.init",function(e,t){e.stopPropagation(),h=t});g.init=function(){w();var n=t.inheritedData("$ionModalController");f=t.inheritedData("$ionNavViewController"),f&&!n&&(e.$on("$ionicView.beforeEnter",g.beforeEnter),e.$on("$ionicView.afterEnter",r),e.$on("$ionicView.beforeLeave",c))},g.beforeEnter=function(t,i){if(i&&!i.viewNotified){i.viewNotified=!0,o.$$phase||e.$digest(),v=u(n.viewTitle)?n.viewTitle:n.title;var r={};for(var a in m)r[a]=l(m[a]);f.beforeEnter(s(i,{title:v,showBack:!d("hideBackButton"),navBarItems:r,navBarDelegate:h||null,showNavBar:!d("hideNavBar"),hasHeaderBar:!!p})),c()}},g.navElement=function(e,t){m[e]=t}}]),c.directive("ionActionSheet",["$document",function(e){return{restrict:"E",scope:!0,replace:!0,link:function(t,n){var i=function(e){27==e.which&&(t.cancel(),t.$apply())},o=function(e){e.target==n[0]&&(t.cancel(),t.$apply())};t.$on("$destroy",function(){n.remove(),e.unbind("keyup",i)}),e.bind("keyup",i),n.bind("click",o)},template:'<div class="action-sheet-backdrop"><div class="action-sheet-wrapper"><div class="action-sheet" ng-class="{\'action-sheet-has-icons\': $actionSheetHasIcon}"><div class="action-sheet-group action-sheet-options"><div class="action-sheet-title" ng-if="titleText" ng-bind-html="titleText"></div><button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-repeat="b in buttons" ng-bind-html="b.text"></button><button class="button destructive action-sheet-destructive" ng-if="destructiveText" ng-click="destructiveButtonClicked()" ng-bind-html="destructiveText"></button></div><div class="action-sheet-group action-sheet-cancel" ng-if="cancelText"><button class="button" ng-click="cancel()" ng-bind-html="cancelText"></button></div></div></div></div>'}}]),c.directive("ionCheckbox",["$ionicConfig",function(e){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-checkbox"><div class="checkbox checkbox-input-hidden disable-pointer-events"><input type="checkbox"><i class="checkbox-icon"></i></div><div class="item-content disable-pointer-events" ng-transclude></div></label>',compile:function(t,n){var i=t.find("input");l({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){u(e)&&i.attr(t,e)});var o=t[0].querySelector(".checkbox");o.classList.add("checkbox-"+e.form.checkbox())}}}]),c.directive("collectionRepeat",e).factory("$ionicCollectionManager",t);var b="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",y=/height:.*?px;\s*width:.*?px/,S=3;e.$inject=["$ionicCollectionManager","$parse","$window","$$rAF","$rootScope","$timeout"],t.$inject=["$rootScope","$window","$$rAF"],c.directive("ionContent",["$timeout","$controller","$ionicBind","$ionicConfig",function(e,t,n,i){return{restrict:"E",require:"^?ionNavView",scope:!0,priority:800,compile:function(e,o){function r(e,i,r){function l(){e.$onScrollComplete({scrollTop:c.scrollView.__scrollTop,scrollLeft:c.scrollView.__scrollLeft})}var d=e.$parent;if(e.$watch(function(){return(d.$hasHeader?" has-header":"")+(d.$hasSubheader?" has-subheader":"")+(d.$hasFooter?" has-footer":"")+(d.$hasSubfooter?" has-subfooter":"")+(d.$hasTabs?" has-tabs":"")+(d.$hasTabsTop?" has-tabs-top":"")},function(e,t){i.removeClass(t),i.addClass(e)}),e.$hasHeader=e.$hasSubheader=e.$hasFooter=e.$hasSubfooter=e.$hasTabs=e.$hasTabsTop=!1,n(e,r,{$onScroll:"&onScroll",$onScrollComplete:"&onScrollComplete",hasBouncing:"@",padding:"@",direction:"@",scrollbarX:"@",scrollbarY:"@",startX:"@",startY:"@",scrollEventInterval:"@"}),e.direction=e.direction||"y",u(r.padding)&&e.$watch(r.padding,function(e){(a||i).toggleClass("padding",!!e)}),"false"===r.scroll);else{var f={};s?(i.addClass("overflow-scroll"),f={el:i[0],delegateHandle:o.delegateHandle,startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,nativeScrolling:!0}):f={el:i[0],delegateHandle:o.delegateHandle,locking:"true"===(o.locking||"true"),bouncing:e.$eval(e.hasBouncing),startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,scrollEventInterval:parseInt(e.scrollEventInterval,10)||10,scrollingComplete:l},c=t("$ionicScroll",{$scope:e,scrollViewOptions:f}),e.$on("$destroy",function(){f&&(f.scrollingComplete=p,delete f.el),a=null,i=null,o.$$element=null})}}var a,c;e.addClass("scroll-content ionic-scroll"),"false"!=o.scroll?(a=h('<div class="scroll"></div>'),a.append(e.contents()),e.append(a)):e.addClass("scroll-content-false");var s="true"===o.overflowScroll||!i.scrolling.jsScrolling();return s&&(s=!e[0].querySelector("[collection-repeat]")),{pre:r}}}}]),c.directive("exposeAsideWhen",["$window",function(e){return{restrict:"A",require:"^ionSideMenus",link:function(t,n,i,o){function r(){var t="large"==i.exposeAsideWhen?"(min-width:768px)":i.exposeAsideWhen;o.exposeAside(e.matchMedia(t).matches),o.activeAsideResizing(!1)}function a(){o.activeAsideResizing(!0),c()}var c=ionic.debounce(function(){t.$apply(r)},300,!1);t.$evalAsync(r),ionic.on("resize",a,e),t.$on("$destroy",function(){ionic.off("resize",a,e)})}}}]);var k="onHold onTap onDoubleTap onTouch onRelease onDragStart onDrag onDragEnd onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeDown onSwipeLeft".split(" ");k.forEach(function(e){c.directive(e,n(e))}),c.directive("ionHeaderBar",i()).directive("ionHeaderBar",o(!0)).directive("ionFooterBar",o(!1)),c.directive("ionInfiniteScroll",["$timeout",function(e){return{restrict:"E",require:["?^$ionicScroll","ionInfiniteScroll"],template:function(e,t){return t.icon?'<i class="icon {{icon()}} icon-refreshing {{scrollingType}}"></i>':'<ion-spinner icon="{{spinner()}}"></ion-spinner>'},scope:!0,controller:"$ionInfiniteScroll",link:function(t,n,i,o){var r=o[1],a=r.scrollCtrl=o[0],c=r.jsScrolling=!a.isNative();if(c)r.scrollView=a.scrollView,t.scrollingType="js-scrolling",a.$element.on("scroll",r.checkBounds);else{var s=ionic.DomUtil.getParentOrSelfWithClass(n[0].parentNode,"overflow-scroll");if(r.scrollEl=s,!s)throw"Infinite scroll must be used inside a scrollable div";r.scrollEl.addEventListener("scroll",r.checkBounds)}var l=u(i.immediateCheck)?t.$eval(i.immediateCheck):!0;l&&e(function(){r.checkBounds()})}}}]),c.directive("ionItem",["$$rAF",function(e){return{restrict:"E",controller:["$scope","$element",function(e,t){this.$scope=e,this.$element=t}],scope:!0,compile:function(t,n){var i=u(n.href)||u(n.ngHref)||u(n.uiSref),o=i||/ion-(delete|option|reorder)-button/i.test(t.html());if(o){var r=h(i?"<a></a>":"<div></div>");r.addClass("item-content"),(u(n.href)||u(n.ngHref))&&(r.attr("ng-href","{{$href()}}"),u(n.target)&&r.attr("target","{{$target()}}")),r.append(t.contents()),t.addClass("item item-complex").append(r)}else t.addClass("item");return function(t,n,i){t.$href=function(){return i.href||i.ngHref},t.$target=function(){return i.target};var o=n[0].querySelector(".item-content");o&&t.$on("$collectionRepeatLeave",function(){o&&o.$$ionicOptionsOpen&&(o.style[ionic.CSS.TRANSFORM]="",o.style[ionic.CSS.TRANSITION]="none",e(function(){o.style[ionic.CSS.TRANSITION]=""}),o.$$ionicOptionsOpen=!1)})}}}}]);var C='<div class="item-left-edit item-delete enable-pointer-events"></div>';c.directive("ionDeleteButton",function(){function e(e){e.stopPropagation()}return{restrict:"E",require:["^^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),function(t,n,i,o){function r(){c=c||n.controller("ionList"),c&&c.showDelete()&&s.addClass("visible active")}var a=o[0],c=o[1],s=h(C);s.append(n),a.$element.append(s).addClass("item-left-editable"),n.on("click",e),r(),t.$on("$ionic.reconnectScope",r)}}}}),c.directive("itemFloatingLabel",function(){return{restrict:"C",link:function(e,t){var n=t[0],i=n.querySelector("input, textarea"),o=n.querySelector(".input-label");if(i&&o){var r=function(){i.value?o.classList.add("has-input"):o.classList.remove("has-input")};i.addEventListener("input",r);var a=h(i).controller("ngModel");a&&(a.$render=function(){i.value=a.$viewValue||"",r()}),e.$on("$destroy",function(){i.removeEventListener("input",r)})}}}});var T='<div class="item-options invisible"></div>';c.directive("ionOptionButton",[function(){function e(e){e.stopPropagation()}return{restrict:"E",require:"^ionItem",priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button",!0),function(t,n,i,o){o.optionsContainer||(o.optionsContainer=h(T),o.$element.append(o.optionsContainer)),o.optionsContainer.append(n),o.$element.addClass("item-right-editable"),n.on("click",e)}}}}]);var B='<div data-prevent-scroll="true" class="item-right-edit item-reorder enable-pointer-events"></div>';c.directive("ionReorderButton",["$parse",function(e){return{restrict:"E",require:["^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),t[0].setAttribute("data-prevent-scroll",!0),function(t,n,i,o){var r=o[0],a=o[1],c=e(i.onReorder);t.$onReorder=function(e,n){c(t,{$fromIndex:e,$toIndex:n})},i.ngClick||i.onClick||i.onclick||(n[0].onclick=function(e){return e.stopPropagation(),!1});var s=h(B);s.append(n),r.$element.append(s).addClass("item-right-editable"),a&&a.showReorder()&&s.addClass("visible active")}}}}]),c.directive("keyboardAttach",function(){return function(e,t){function n(e){if(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen){var n=e.keyboardHeight||e.detail.keyboardHeight;t.css("bottom",n+"px"),o=t.controller("$ionicScroll"),o&&(o.scrollView.__container.style.bottom=n+r(t[0])+"px")}}function i(){(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen)&&(t.css("bottom",""),o&&(o.scrollView.__container.style.bottom=""))}ionic.on("native.keyboardshow",n,window), -ionic.on("native.keyboardhide",i,window),ionic.on("native.showkeyboard",n,window),ionic.on("native.hidekeyboard",i,window);var o;e.$on("$destroy",function(){ionic.off("native.keyboardshow",n,window),ionic.off("native.keyboardhide",i,window),ionic.off("native.showkeyboard",n,window),ionic.off("native.hidekeyboard",i,window)})}}),c.directive("ionList",["$timeout",function(e){return{restrict:"E",require:["ionList","^?$ionicScroll"],controller:"$ionicList",compile:function(t,n){var i=h('<div class="list">').append(t.contents()).addClass(n.type);return t.append(i),function(t,i,o,r){function a(){function o(e,t){t()&&e.addClass("visible")||e.removeClass("active"),ionic.requestAnimationFrame(function(){t()&&e.addClass("active")||e.removeClass("visible")})}var r=c.listView=new ionic.views.ListView({el:i[0],listEl:i.children()[0],scrollEl:s&&s.element,scrollView:s&&s.scrollView,onReorder:function(t,n,i){var o=h(t).scope();o&&o.$onReorder&&e(function(){o.$onReorder(n,i)})},canSwipe:function(){return c.canSwipeItems()}});t.$on("$destroy",function(){r&&(r.deregister&&r.deregister(),r=null)}),u(n.canSwipe)&&t.$watch("!!("+n.canSwipe+")",function(e){c.canSwipeItems(e)}),u(n.showDelete)&&t.$watch("!!("+n.showDelete+")",function(e){c.showDelete(e)}),u(n.showReorder)&&t.$watch("!!("+n.showReorder+")",function(e){c.showReorder(e)}),t.$watch(function(){return c.showDelete()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-left-editing",e),i.toggleClass("disable-pointer-events",e);var n=h(i[0].getElementsByClassName("item-delete"));o(n,c.showDelete)}}),t.$watch(function(){return c.showReorder()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-right-editing",e),i.toggleClass("disable-pointer-events",e);var n=h(i[0].getElementsByClassName("item-reorder"));o(n,c.showReorder)}})}var c=r[0],s=r[1];e(a)}}}}]),c.directive("menuClose",["$ionicHistory",function(e){return{restrict:"AC",link:function(t,n){n.bind("click",function(){var t=n.inheritedData("$ionSideMenusController");t&&(e.nextViewOptions({historyRoot:!0,disableAnimate:!0,expire:300}),t.close())})}}}]),c.directive("menuToggle",function(){return{restrict:"AC",link:function(e,t,n){e.$on("$ionicView.beforeEnter",function(e,n){if(n.enableBack){var i=t.inheritedData("$ionSideMenusController");i.enableMenuWithBackViews()||t.addClass("hide")}else t.removeClass("hide")}),t.bind("click",function(){var e=t.inheritedData("$ionSideMenusController");e&&e.toggle(n.menuToggle)})}}}),c.directive("ionModal",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="modal-backdrop"><div class="modal-backdrop-bg"></div><div class="modal-wrapper" ng-transclude></div></div>'}}]),c.directive("ionModalView",function(){return{restrict:"E",compile:function(e){e.addClass("modal")}}}),c.directive("ionNavBackButton",["$ionicConfig","$document",function(e,t){return{restrict:"E",require:"^ionNavBar",compile:function(n,i){function o(e){return/ion-|icon/.test(e.className)}var r=t[0].createElement("button");for(var a in i.$attr)r.setAttribute(i.$attr[a],i[a]);i.ngClick||r.setAttribute("ng-click","$ionicGoBack()"),r.className="button back-button hide buttons "+(n.attr("class")||""),r.innerHTML=n.html()||"";for(var c,s,l,u,d=o(n[0]),f=0;f<n[0].childNodes.length;f++)c=n[0].childNodes[f],1===c.nodeType?o(c)?d=!0:c.classList.contains("default-title")?l=!0:c.classList.contains("previous-title")&&(u=!0):s||3!==c.nodeType||(s=!!c.nodeValue.trim());var h=e.backButton.icon();if(!d&&h&&"none"!==h&&(r.innerHTML='<i class="icon '+h+'"></i> '+r.innerHTML,r.className+=" button-clear"),!s){var p=t[0].createElement("span");p.className="back-text",!l&&e.backButton.text()&&(p.innerHTML+='<span class="default-title">'+e.backButton.text()+"</span>"),!u&&e.backButton.previousTitleText()&&(p.innerHTML+='<span class="previous-title"></span>'),r.appendChild(p)}return n.attr("class","hide"),n.empty(),{pre:function(e,t,n,i){i.navElement("backButton",r.outerHTML),r=null}}}}}]),c.directive("ionNavBar",function(){return{restrict:"E",controller:"$ionicNavBar",scope:!0,link:function(e,t,n,i){i.init()}}}),c.directive("ionNavButtons",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="left";/^primary|secondary|right$/i.test(n.side||"")&&(i=n.side.toLowerCase());var o=e[0].createElement("span");o.className=i+"-buttons",o.innerHTML=t.html();var r=i+"Buttons";return t.attr("class","hide"),t.empty(),{pre:function(e,t,n,i){var a=t.parent().data("$ionViewController");a?a.navElement(r,o.outerHTML):i.navElement(r,o.outerHTML),o=null}}}}}]),c.directive("navDirection",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextDirection(i.navDirection)})}}}]),c.directive("ionNavTitle",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="title",o=e[0].createElement("span");for(var r in n.$attr)o.setAttribute(n.$attr[r],n[r]);return o.classList.add("nav-bar-title"),o.innerHTML=t.html(),t.attr("class","hide"),t.empty(),{pre:function(e,t,n,r){var a=t.parent().data("$ionViewController");a?a.navElement(i,o.outerHTML):r.navElement(i,o.outerHTML),o=null}}}}}]),c.directive("navTransition",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextTransition(i.navTransition)})}}}]),c.directive("ionNavView",["$state","$ionicConfig",function(e,t){return{restrict:"E",terminal:!0,priority:2e3,transclude:!0,controller:"$ionicNavView",compile:function(n,i,o){return n.addClass("view-container"),ionic.DomUtil.cachedAttr(n,"nav-view-transition",t.views.transition()),function(t,n,i,r){function a(t){var n=e.$current&&e.$current.locals[s.name];n&&(t||n!==c)&&(c=n,s.state=n.$$state,r.register(n))}var c;o(t,function(e){n.append(e)});var s=r.init();t.$on("$stateChangeSuccess",function(){a(!1)}),t.$on("$viewContentLoading",function(){a(!1)}),a(!0)}}}}]),c.config(["$provide",function(e){e.decorator("ngClickDirective",["$delegate",function(e){return e.shift(),e}])}]).factory("$ionicNgClick",["$parse",function(e){return function(t,n,i){var o=angular.isFunction(i)?i:e(i);n.on("click",function(e){t.$apply(function(){o(t,{$event:e})})}),n.onclick=p}}]).directive("ngClick",["$ionicNgClick",function(e){return function(t,n,i){e(t,n,i.ngClick)}}]).directive("ionStopEvent",function(){return{restrict:"A",link:function(e,t,n){t.bind(n.ionStopEvent,a)}}}),c.directive("ionPane",function(){return{restrict:"E",link:function(e,t){t.addClass("pane")}}}),c.directive("ionPopover",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="popover-backdrop"><div class="popover-wrapper" ng-transclude></div></div>'}}]),c.directive("ionPopoverView",function(){return{restrict:"E",compile:function(e){e.append(h('<div class="popover-arrow">')),e.addClass("popover")}}}),c.directive("ionRadio",function(){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-radio"><input type="radio" name="radio-group"><div class="item-content disable-pointer-events" ng-transclude></div><i class="radio-icon disable-pointer-events icon ion-checkmark"></i></label>',compile:function(e,t){t.icon&&e.children().eq(2).removeClass("ion-checkmark").addClass(t.icon);var n=e.find("input");return l({name:t.name,value:t.value,disabled:t.disabled,"ng-value":t.ngValue,"ng-model":t.ngModel,"ng-disabled":t.ngDisabled,"ng-change":t.ngChange,"ng-required":t.ngRequired,required:t.required},function(e,t){u(e)&&n.attr(t,e)}),function(e,t,n){e.getValue=function(){return e.ngValue||n.value}}}}}),c.directive("ionRefresher",[function(){return{restrict:"E",replace:!0,require:["?^$ionicScroll","ionRefresher"],controller:"$ionicRefresher",template:'<div class="scroll-refresher invisible" collection-repeat-ignore><div class="ionic-refresher-content" ng-class="{\'ionic-refresher-with-text\': pullingText || refreshingText}"><div class="icon-pulling" ng-class="{\'pulling-rotation-disabled\':disablePullingRotation}"><i class="icon {{pullingIcon}}"></i></div><div class="text-pulling" ng-bind-html="pullingText"></div><div class="icon-refreshing"><ion-spinner ng-if="showSpinner" icon="{{spinner}}"></ion-spinner><i ng-if="showIcon" class="icon {{refreshingIcon}}"></i></div><div class="text-refreshing" ng-bind-html="refreshingText"></div></div></div>',link:function(e,t,n,i){var o=i[0],r=i[1];!o||o.isNative()?r.init():(t[0].classList.add("js-scrolling"),o._setRefresher(e,t[0],r.getRefresherDomMethods()),e.$on("scroll.refreshComplete",function(){e.$evalAsync(function(){o.scrollView.finishPullToRefresh()})}))}}}]),c.directive("ionScroll",["$timeout","$controller","$ionicBind",function(e,t,n){return{restrict:"E",scope:!0,controller:function(){},compile:function(e){function i(e,i,r){n(e,r,{direction:"@",paging:"@",$onScroll:"&onScroll",scroll:"@",scrollbarX:"@",scrollbarY:"@",zooming:"@",minZoom:"@",maxZoom:"@"}),e.direction=e.direction||"y",u(r.padding)&&e.$watch(r.padding,function(e){o.toggleClass("padding",!!e)}),e.$eval(e.paging)===!0&&o.addClass("scroll-paging"),e.direction||(e.direction="y");var a=e.$eval(e.paging)===!0,c={el:i[0],delegateHandle:r.delegateHandle,locking:"true"===(r.locking||"true"),bouncing:e.$eval(r.hasBouncing),paging:a,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,zooming:e.$eval(e.zooming)===!0,maxZoom:e.$eval(e.maxZoom)||3,minZoom:e.$eval(e.minZoom)||.5,preventDefault:!0};a&&(c.speedMultiplier=.8,c.bouncing=!1),t("$ionicScroll",{$scope:e,scrollViewOptions:c})}e.addClass("scroll-view ionic-scroll");var o=h('<div class="scroll"></div>');return o.append(e.contents()),e.append(o),{pre:i}}}}]),c.directive("ionSideMenu",function(){return{restrict:"E",require:"^ionSideMenus",scope:!0,compile:function(e,t){return angular.isUndefined(t.isEnabled)&&t.$set("isEnabled","true"),angular.isUndefined(t.width)&&t.$set("width","275"),e.addClass("menu menu-"+t.side),function(e,n,i,o){e.side=i.side||"left";var r=o[e.side]=new ionic.views.SideMenu({width:t.width,el:n[0],isEnabled:!0});e.$watch(i.width,function(e){var t=+e;t&&t==e&&r.setWidth(+e)}),e.$watch(i.isEnabled,function(e){r.setIsEnabled(!!e)})}}}}),c.directive("ionSideMenuContent",["$timeout","$ionicGesture","$window",function(e,t,n){return{restrict:"EA",require:"^ionSideMenus",scope:!0,compile:function(i,o){function r(r,a,c,s){function l(e){0!==s.getOpenAmount()?(s.close(),e.gesture.srcEvent.preventDefault(),v=null,g=null):v||(v=ionic.tap.pointerCoord(e.gesture.srcEvent))}function d(e){s.isDraggableTarget(e)&&"x"==p(e)&&(s._handleDrag(e),e.gesture.srcEvent.preventDefault())}function f(e){"x"==p(e)&&e.gesture.srcEvent.preventDefault()}function h(e){s._endDrag(e),v=null,g=null}function p(e){if(g)return g;if(e&&e.gesture){if(v){var t=ionic.tap.pointerCoord(e.gesture.srcEvent),n=Math.abs(t.x-v.x),i=Math.abs(t.y-v.y),o=i>n?"y":"x";return Math.max(n,i)>30&&(g=o),o}v=ionic.tap.pointerCoord(e.gesture.srcEvent)}return"y"}var v=null,g=null;u(o.dragContent)?r.$watch(o.dragContent,function(e){s.canDragContent(e)}):s.canDragContent(!0),u(o.edgeDragThreshold)&&r.$watch(o.edgeDragThreshold,function(e){s.edgeDragThreshold(e)});var m={element:i[0],onDrag:function(){},endDrag:function(){},getTranslateX:function(){return r.sideMenuContentTranslateX||0},setTranslateX:ionic.animationFrameThrottle(function(t){var n=m.offsetX+t;a[0].style[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e(function(){r.sideMenuContentTranslateX=t})}),setMarginLeft:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style[ionic.CSS.TRANSFORM]="translate3d("+e+"px,0,0)",a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)",a[0].style.width="",m.offsetX=0)}),setMarginRight:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style.width="",m.offsetX=0),a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)"}),enableAnimation:function(){r.animationEnabled=!0,a[0].classList.add("menu-animated")},disableAnimation:function(){r.animationEnabled=!1,a[0].classList.remove("menu-animated")},offsetX:0};s.setContent(m);var $={stop_browser_behavior:!1};ionic.DomUtil.getParentOrSelfWithClass(a[0],"overflow-scroll")&&($.prevent_default_directions=["left","right"]);var w=t.on("tap",l,a,$),b=t.on("dragright",d,a,$),y=t.on("dragleft",d,a,$),S=t.on("dragup",f,a,$),k=t.on("dragdown",f,a,$),C=t.on("release",h,a,$);r.$on("$destroy",function(){m&&(m.element=null,m=null),t.off(y,"dragleft",d),t.off(b,"dragright",d),t.off(S,"dragup",f),t.off(k,"dragdown",f),t.off(C,"release",h),t.off(w,"tap",l)})}return i.addClass("menu-content pane"),{pre:r}}}}]),c.directive("ionSideMenus",["$ionicBody",function(e){return{restrict:"ECA",controller:"$ionicSideMenus",compile:function(t,n){function i(t,n,i,o){o.enableMenuWithBackViews(t.$eval(i.enableMenuWithBackViews)),t.$on("$ionicExposeAside",function(n,i){t.$exposeAside||(t.$exposeAside={}),t.$exposeAside.active=i,e.enableClass(i,"aside-open")}),t.$on("$ionicView.beforeEnter",function(e,n){n.historyId&&(t.$activeHistoryId=n.historyId)}),t.$on("$destroy",function(){e.removeClass("menu-open","aside-open")})}return n.$set("class",(n["class"]||"")+" view"),{pre:i}}}}]),c.directive("ionSlideBox",["$timeout","$compile","$ionicSlideBoxDelegate","$ionicHistory","$ionicScrollDelegate",function(e,t,n,i,o){return{restrict:"E",replace:!0,transclude:!0,scope:{autoPlay:"=",doesContinue:"@",slideInterval:"@",showPager:"@",pagerClick:"&",disableScroll:"@",onSlideChanged:"&",activeSlide:"=?"},controller:["$scope","$element","$attrs",function(t,r,a){function c(e){e&&!s.isScrollFreeze?o.freezeAllScrolls(e):!e&&s.isScrollFreeze&&o.freezeAllScrolls(!1),s.isScrollFreeze=e}var s=this,l=t.$eval(t.doesContinue)===!0,d=u(a.autoPlay)?!!t.autoPlay:!1,f=d?t.$eval(t.slideInterval)||4e3:0,h=new ionic.views.Slider({el:r[0],auto:f,continuous:l,startSlide:t.activeSlide,slidesChanged:function(){t.currentSlide=h.currentIndex(),e(function(){})},callback:function(n){t.currentSlide=n,t.onSlideChanged({index:t.currentSlide,$index:t.currentSlide}),t.$parent.$broadcast("slideBox.slideChanged",n),t.activeSlide=n,e(function(){})},onDrag:function(){c(!0)},onDragEnd:function(){c(!1)}});h.enableSlide(t.$eval(a.disableScroll)!==!0),t.$watch("activeSlide",function(e){u(e)&&h.slide(e)}),t.$on("slideBox.nextSlide",function(){h.next()}),t.$on("slideBox.prevSlide",function(){h.prev()}),t.$on("slideBox.setSlide",function(e,t){h.slide(t)}),this.__slider=h;var p=n._registerInstance(h,a.delegateHandle,function(){return i.isActiveScope(t)});t.$on("$destroy",function(){p(),h.kill()}),this.slidesCount=function(){return h.slidesCount()},this.onPagerClick=function(e){t.pagerClick({index:e})},e(function(){h.load()})}],template:'<div class="slider"><div class="slider-slides" ng-transclude></div></div>',link:function(e,n,i){function o(){if(!r){var i=e.$new();r=h("<ion-pager></ion-pager>"),n.append(r),r=t(r)(i)}return r}u(i.showPager)||(e.showPager=!0,o().toggleClass("hide",!1)),i.$observe("showPager",function(t){t=e.$eval(t),o().toggleClass("hide",!t)});var r}}}]).directive("ionSlide",function(){return{restrict:"E",require:"^ionSlideBox",compile:function(e){e.addClass("slider-slide")}}}).directive("ionPager",function(){return{restrict:"E",replace:!0,require:"^ionSlideBox",template:'<div class="slider-pager"><span class="slider-pager-page" ng-repeat="slide in numSlides() track by $index" ng-class="{active: $index == currentSlide}" ng-click="pagerClick($index)"><i class="icon ion-record"></i></span></div>',link:function(e,t,n,i){var o=function(e){for(var n=t[0].children,i=n.length,o=0;i>o;o++)o==e?n[o].classList.add("active"):n[o].classList.remove("active")};e.pagerClick=function(e){i.onPagerClick(e)},e.numSlides=function(){return new Array(i.slidesCount())},e.$watch("currentSlide",function(e){o(e)})}}}),c.directive("ionSpinner",function(){return{restrict:"E",controller:"$ionicSpinner",link:function(e,t,n,i){var o=i.init();t.addClass("spinner spinner-"+o)}}}),c.directive("ionTab",["$compile","$ionicConfig","$ionicBind","$ionicViewSwitcher",function(e,t,n,i){function o(e,t){return u(t)?" "+e+'="'+t+'"':""}return{restrict:"E",require:["^ionTabs","ionTab"],controller:"$ionicTab",scope:!0,compile:function(r,a){for(var c="<ion-tab-nav"+o("ng-click",a.ngClick)+o("title",a.title)+o("icon",a.icon)+o("icon-on",a.iconOn)+o("icon-off",a.iconOff)+o("badge",a.badge)+o("badge-style",a.badgeStyle)+o("hidden",a.hidden)+o("disabled",a.disabled)+o("class",a["class"])+"></ion-tab-nav>",s=document.createElement("div"),l=0;l<r[0].children.length;l++)s.appendChild(r[0].children[l].cloneNode(!0));var u=s.childElementCount;r.empty();var d,f;return u&&("ION-NAV-VIEW"===s.children[0].tagName&&(d=s.children[0].getAttribute("name"),s.children[0].classList.add("view-container"),f=!0),1===u&&(s=s.children[0]),f||s.classList.add("pane"),s.classList.add("tab-content")),function(o,r,a,l){function f(){w.tabMatchesState()&&$.select(o,!1)}function p(n){n&&u?(b||(g=o.$new(),m=h(s),i.viewEleIsActive(m,!0),$.$element.append(m),e(m)(g),b=!0),i.viewEleIsActive(m,!0)):b&&m&&(t.views.maxCache()>0?i.viewEleIsActive(m,!1):v())}function v(){g&&g.$destroy(),b&&m&&m.remove(),s.innerHTML="",b=g=m=null}var g,m,$=l[0],w=l[1],b=!1;o.$tabSelected=!1,n(o,a,{onSelect:"&",onDeselect:"&",title:"@",uiSref:"@",href:"@"}),$.add(o),o.$on("$destroy",function(){o.$tabsDestroy||$.remove(o),y.isolateScope().$destroy(),y.remove(),y=s=m=null}),r[0].removeAttribute("title"),d&&(w.navViewName=o.navViewName=d),o.$on("$stateChangeSuccess",f),f();var y=h(c);y.data("$ionTabsController",$),y.data("$ionTabController",w),$.$tabsElement.append(e(y)(o)),o.$watch("$tabSelected",p),o.$on("$ionicView.afterEnter",function(){i.viewEleIsActive(m,o.$tabSelected)}),o.$on("$ionicView.clearCache",function(){o.$tabSelected||v()})}}}}]),c.directive("ionTabNav",[function(){return{restrict:"E",replace:!0,require:["^ionTabs","^ionTab"],template:"<a ng-class=\"{'tab-item-active': isTabActive(), 'has-badge':badge, 'tab-hidden':isHidden()}\" "+' ng-disabled="disabled()" class="tab-item"><span class="badge {{badgeStyle}}" ng-if="badge">{{badge}}</span><i class="icon {{getIconOn()}}" ng-if="getIconOn() && isTabActive()"></i><i class="icon {{getIconOff()}}" ng-if="getIconOff() && !isTabActive()"></i><span class="tab-title" ng-bind-html="title"></span></a>',scope:{title:"@",icon:"@",iconOn:"@",iconOff:"@",badge:"=",hidden:"@",disabled:"&",badgeStyle:"@","class":"@"},link:function(e,t,n,i){var o=i[0],r=i[1];t[0].removeAttribute("title"),e.selectTab=function(e){e.preventDefault(),o.select(r.$scope,!0)},n.ngClick||t.on("click",function(t){e.$apply(function(){e.selectTab(t)})}),e.isHidden=function(){return"true"===n.hidden||n.hidden===!0?!0:!1},e.getIconOn=function(){return e.iconOn||e.icon},e.getIconOff=function(){return e.iconOff||e.icon},e.isTabActive=function(){return o.selectedTab()===r.$scope}}}}]),c.directive("ionTabs",["$ionicTabsDelegate","$ionicConfig",function(e,t){return{restrict:"E",scope:!0,controller:"$ionicTabs",compile:function(n){function i(t,n,i,o){function a(e,t){e.stopPropagation();var n=o.previousSelectedTab();n&&n.$broadcast(e.name.replace("NavView","Tabs"),t)}var c=e._registerInstance(o,i.delegateHandle,o.hasActiveScope);o.$scope=t,o.$element=n,o.$tabsElement=h(n[0].querySelector(".tabs")),t.$watch(function(){return n[0].className},function(e){var n=-1!==e.indexOf("tabs-top"),i=-1!==e.indexOf("tabs-item-hide");t.$hasTabs=!n&&!i,t.$hasTabsTop=n&&!i,t.$emit("$ionicTabs.top",t.$hasTabsTop)}),t.$on("$ionicNavView.beforeLeave",a),t.$on("$ionicNavView.afterLeave",a),t.$on("$ionicNavView.leave",a),t.$on("$destroy",function(){t.$tabsDestroy=!0,c(),o.$tabsElement=o.$element=o.$scope=r=null,delete t.$hasTabs,delete t.$hasTabsTop})}function o(e,t,n,i){i.selectedTab()||i.select(0)}var r=h('<div class="tab-nav tabs">');return r.append(n.contents()),n.append(r).addClass("tabs-"+t.tabs.position()+" tabs-"+t.tabs.style()),{pre:i,post:o}}}}]),c.directive("ionToggle",["$timeout","$ionicConfig",function(e,t){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<div class="item item-toggle"><div ng-transclude></div><label class="toggle"><input type="checkbox"><div class="track"><div class="handle"></div></div></label></div>',compile:function(e,n){var i=e.find("input");return l({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){u(e)&&i.attr(t,e)}),n.toggleClass&&e[0].getElementsByTagName("label")[0].classList.add(n.toggleClass),e.addClass("toggle-"+t.form.toggle()),function(e,t){var n=t[0].getElementsByTagName("label")[0],i=n.children[0],o=n.children[1],r=o.children[0],a=h(i).controller("ngModel");e.toggle=new ionic.views.Toggle({el:n,track:o,checkbox:i,handle:r,onChange:function(){a&&(a.$setViewValue(i.checked),e.$apply())}}),e.$on("$destroy",function(){e.toggle.destroy()})}}}}]),c.directive("ionView",function(){return{restrict:"EA",priority:1e3,controller:"$ionicView",compile:function(e){return e.addClass("pane"),e[0].removeAttribute("title"),function(e,t,n,i){i.init()}}}})}(); \ No newline at end of file +!function(){function e(e,t,n,i,o,r){function a(i,a,c,s,u){function d(){N.resizeRequiresRefresh(w.__clientWidth,w.__clientHeight)&&g()}function f(){var e;return e={dataLength:0,width:0,height:0,resizeRequiresRefresh:function(t,n){var i=e.dataLength&&t&&n&&(t!==e.width||n!==e.height);return e.width=t,e.height=n,!!i},dataChangeRequiresRefresh:function(t){var n=t.length>0||t.length<e.dataLength;return e.dataLength=t.length,!!n}}}function h(){return T||(T=new e({afterItemsNode:M[0],containerNode:S,heightData:A,widthData:E,forceRefreshImages:!(!l(c.forceRefreshImages)||"false"===c.forceRefreshImages),keyExpression:B,renderBuffer:D,scope:i,scrollView:s.scrollView,transclude:u}))}function p(){var e=angular.element(w.__content.querySelector(".collection-repeat-after-container"));if(!e.length){var t=!1,n=[].filter.call(w.__content.childNodes,function(e){return ionic.DomUtil.contains(e,S)?(t=!0,!1):t});e=angular.element('<span class="collection-repeat-after-container">'),w.options.scrollingX&&e.addClass("horizontal"),e.append(n),w.__content.appendChild(e[0])}return e}function v(){L?m(L,A):A.computed=!0,R?m(R,E):E.computed=!0}function g(){var e=P.length>0;if(e&&(A.computed||E.computed)&&$(),e&&A.computed){if(A.value=V.height,!A.value)throw new Error('collection-repeat tried to compute the height of repeated elements "'+k+'", but was unable to. Please provide the "item-height" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!A.dynamic&&A.getValue&&(A.value=A.getValue());if(e&&E.computed){if(E.value=V.width,!E.value)throw new Error('collection-repeat tried to compute the width of repeated elements "'+k+'", but was unable to. Please provide the "item-width" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!E.dynamic&&E.getValue&&(E.value=E.getValue());h().refreshLayout()}function m(e,n){if(e){var i;try{i=t(e)}catch(o){e.trim().match(/\d+(px|%)$/)&&(e='"'+e+'"'),i=t(e)}var r=e.replace(/(\'|\"|px|%)/g,"").trim(),a=r.length&&!/([a-zA-Z]|\$|:|\?)/.test(r);if(n.attrValue=e,a)if(e.indexOf("%")>-1){var c=parseFloat(i())/100;n.getValue=n===A?function(){return Math.floor(c*w.__clientHeight)}:function(){return Math.floor(c*w.__clientWidth)}}else n.value=parseInt(i());else n.dynamic=!0,n.getValue=n===A?function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseFloat(n)/100*w.__clientHeight):parseInt(n)}:function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseFloat(n)/100*w.__clientWidth):parseInt(n)}}}function $(){O||u(H=i.$new(),function(e){e[0].removeAttribute("collection-repeat"),O=e[0]}),H[B]=(x(i)||[])[0],o.$$phase||H.$digest(),S.appendChild(O);var e=n.getComputedStyle(O);V.width=parseInt(e.width),V.height=parseInt(e.height),S.removeChild(O)}var w=s.scrollView,b=a[0],S=angular.element('<div class="collection-repeat-container">')[0];if(b.parentNode.replaceChild(S,b),w.options.scrollingX&&w.options.scrollingY)throw new Error("collection-repeat expected a parent x or y scrollView, not an xy scrollView.");var k=c.collectionRepeat,C=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!C)throw new Error("collection-repeat expected expression in form of '_item_ in _collection_[ track by _id_]' but got '"+c.collectionRepeat+"'.");var T,B=C[1],I=C[2],x=t(I),A={},E={},V={},P=[],_=c.itemRenderBuffer||c.collectionBufferSize,D=angular.isDefined(_)?parseInt(_):y,L=c.itemHeight||c.collectionItemHeight,R=c.itemWidth||c.collectionItemWidth,M=p(),N=f();v(),s.$element.on("scroll-resize",g),angular.element(n).on("resize",d);var z=o.$on("$ionicExposeAside",ionic.animationFrameThrottle(function(){s.scrollView.resize(),d()}));r(g,0,!1),i.$watchCollection(x,function(e){if(P=e||(e=[]),!angular.isArray(e))throw new Error("collection-repeat expected an array for '"+I+"', but got a "+typeof value);i.$$postDigest(function(){h().setData(P),N.dataChangeRequiresRefresh(P)&&g()})}),i.$on("$destroy",function(){angular.element(n).off("resize",d),z(),s.$element&&s.$element.off("scroll-resize",g),O&&O.parentNode&&O.parentNode.removeChild(O),H&&H.$destroy(),H=O=null,T&&T.destroy(),T=null});var O,H}return{restrict:"A",priority:1e3,transclude:"element",$$tlb:!0,require:"^^$ionicScroll",link:a}}function t(e,t,n){var i={primaryPos:0,secondaryPos:0,primarySize:0,secondarySize:0,rowPrimarySize:0};return function(o){function r(){return a(!0)}function a(t){if(!a.destroyed){var n,o,r,l,u,d=ee.getScrollValue(),f=d+ee.scrollPrimarySize;ee.updateRenderRange(d,f),F=Math.max(0,F-T),W=Math.min(A.length-1,W+T);for(n in Z)(F>n||n>W)&&(r=Z[n],delete Z[n],G.push(r),r.isShown=!1);for(n=F;W>=n;n++)n>=A.length||Z[n]&&!t||(r=Z[n]||(Z[n]=G.length?G.pop():j.length?j.shift():new s),K.push(r),r.isShown=!0,u=r.scope,u.$index=n,u[C]=A[n],u.$first=0===n,u.$last=n===A.length-1,u.$middle=!(u.$first||u.$last),u.$odd=!(u.$even=0===(1&n)),u.$$disconnected&&ionic.Utils.reconnectScope(r.scope),l=ee.getDimensions(n),(r.secondaryPos!==l.secondaryPos||r.primaryPos!==l.primaryPos)&&(r.node.style[ionic.CSS.TRANSFORM]=O.replace(N,r.primaryPos=l.primaryPos).replace(z,r.secondaryPos=l.secondaryPos)),(r.secondarySize!==l.secondarySize||r.primarySize!==l.primarySize)&&(r.node.style.cssText=r.node.style.cssText.replace(b,H.replace(N,(r.primarySize=l.primarySize)+1).replace(z,r.secondarySize=l.secondarySize))));for(W===A.length-1&&(l=ee.getDimensions(A.length-1)||i,m.style[ionic.CSS.TRANSFORM]=O.replace(N,l.primaryPos+l.primarySize).replace(z,0));G.length;)r=G.pop(),r.scope.$broadcast("$collectionRepeatLeave"),ionic.Utils.disconnectScope(r.scope),j.push(r),r.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",r.primaryPos=r.secondaryPos=null;if(y)for(n=0,o=K.length;o>n&&(r=K[n]);n++)if(r.images)for(var h,p=0,v=r.images.length;v>p&&(h=r.images[p]);p++){var g=h.src;h.src=w,h.src=g}if(t)for(var $=e.$$phase;K.length;)r=K.pop(),$||r.scope.$digest();else c()}}function c(){var t;c.running||(c.running=!0,n(function(){for(var n=e.$$phase;K.length;)t=K.pop(),t.isShown&&(n||t.scope.$digest());c.running=!1}))}function s(){var e=this;this.scope=B.$new(),this.id="item"+J++,x(this.scope,function(t){e.element=t,e.element.data("$$collectionRepeatItem",e),e.node=t[0],e.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",e.node.style.cssText+=" height: 0px; width: 0px;",ionic.Utils.disconnectScope(e.scope),$.appendChild(e.node),e.images=t[0].getElementsByTagName("img")})}function l(){this.getItemPrimarySize=P,this.getItemSecondarySize=D,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollTop-q,I.__maxScrollTop-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientHeight,this.scrollSecondarySize=I.__clientWidth,this.estimatedPrimarySize=v,this.estimatedSecondarySize=g,this.estimatedItemsAcross=R&&Math.floor(I.__clientWidth/g)||1}}function u(){this.getItemPrimarySize=D,this.getItemSecondarySize=P,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollLeft-q,I.__maxScrollLeft-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientWidth,this.scrollSecondarySize=I.__clientHeight,this.estimatedPrimarySize=g,this.estimatedSecondarySize=v,this.estimatedItemsAcross=R&&Math.floor(I.__clientHeight/v)||1}}function d(){this.getEstimatedSecondaryPos=function(e){return e%this.estimatedItemsAcross*this.estimatedSecondarySize},this.getEstimatedPrimaryPos=function(e){return Math.floor(e/this.estimatedItemsAcross)*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)*this.estimatedItemsAcross}}function f(){this.getEstimatedSecondaryPos=function(){return 0},this.getEstimatedPrimaryPos=function(e){return e*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)}}function h(){this.getContentSize=function(){return this.getEstimatedPrimaryPos(A.length-1)+this.estimatedPrimarySize+q+U};var e={};this.getDimensions=function(t){return e.primaryPos=this.getEstimatedPrimaryPos(t),e.secondaryPos=this.getEstimatedSecondaryPos(t),e.primarySize=this.estimatedPrimarySize,e.secondarySize=this.estimatedSecondarySize,e},this.updateRenderRange=function(e,t){F=Math.max(0,this.getEstimatedIndex(e)),W=Math.min(A.length-1,this.getEstimatedIndex(t)+this.estimatedItemsAcross-1),Y=Math.max(0,this.getEstimatedPrimaryPos(F)),X=this.getEstimatedPrimaryPos(W)+this.estimatedPrimarySize}}function p(){function e(e){var t,r,a;for(t=Math.max(0,n);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.primarySize=o.getItemPrimarySize(t,A[t]),a.secondarySize=o.scrollSecondarySize,a.primaryPos=r.primaryPos+r.primarySize,a.secondaryPos=0}function t(e){var t,r,a;for(t=Math.max(n,0);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.secondarySize=Math.min(o.getItemSecondarySize(t,A[t]),o.scrollSecondarySize),a.secondaryPos=r.secondaryPos+r.secondarySize,0===t||a.secondaryPos+a.secondarySize>o.scrollSecondarySize?(a.secondaryPos=0,a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos+r.rowPrimarySize,a.rowStartIndex=t,a.rowPrimarySize=a.primarySize):(a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos,a.rowStartIndex=r.rowStartIndex,c[a.rowStartIndex].rowPrimarySize=a.rowPrimarySize=Math.max(c[a.rowStartIndex].rowPrimarySize,a.primarySize),a.rowPrimarySize=Math.max(a.primarySize,a.rowPrimarySize))}var n,o=this,r=ionic.debounce(Q,25,!0),a=R?t:e,c=[];this.getContentSize=function(){var e=c[n]||i;return(e.primaryPos+e.primarySize||0)+this.getEstimatedPrimaryPos(A.length-n-1)+q+U},this.onDestroy=function(){c.length=0},this.onRefreshData=function(){var e,t;for(e=c.length,t=A.length;t>e;e++)c.push({});n=-1},this.onRefreshLayout=function(){n=-1},this.getDimensions=function(e){return e=Math.min(e,A.length-1),e>n&&(e>.9*A.length?(a(A.length-1),n=A.length-1,Q()):(a(e),n=e,r())),c[e]};var s=-1,l=-1;this.updateRenderRange=function(e,t){var n,i,o;if(this.getDimensions(2*this.getEstimatedIndex(t)),-1===s||0===e)n=0;else if(e>=l)for(n=s,i=A.length;i>n&&!((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>=e);n++);else for(n=s;n>=0;n--)if((o=this.getDimensions(n))&&o.primaryPos<=e){n=R?o.rowStartIndex:n;break}F=Math.min(Math.max(0,n),A.length-1),Y=-1!==F?this.getDimensions(F).primaryPos:-1;var r;for(n=F+1,i=A.length;i>n;n++)if((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>t){if(R)for(r=o;i-1>n&&(o=this.getDimensions(n+1)).primaryPos===r.primaryPos;)n++;break}W=Math.min(n,A.length-1),X=-1!==W?(o=this.getDimensions(W)).primaryPos+(o.rowPrimarySize||o.primarySize):-1,l=e,s=F}}var v,g,m=o.afterItemsNode,$=o.containerNode,y=o.forceRefreshImages,S=o.heightData,k=o.widthData,C=o.keyExpression,T=o.renderBuffer,B=o.scope,I=o.scrollView,x=o.transclude,A=[],E={},V=S.getValue||function(){return S.value},P=function(e,t){return E[C]=t,E.$index=e,V(B,E)},_=k.getValue||function(){return k.value},D=function(e,t){return E[C]=t,E.$index=e,_(B,E)},L=!!I.options.scrollingY,R=L?k.dynamic||k.value!==I.__clientWidth:S.dynamic||S.value!==I.__clientHeight,M=!S.dynamic&&!k.dynamic,N="PRIMARY",z="SECONDARY",O=L?"translate3d(SECONDARYpx,PRIMARYpx,0)":"translate3d(PRIMARYpx,SECONDARYpx,0)",H=L?"height: PRIMARYpx; width: SECONDARYpx;":"height: SECONDARYpx; width: PRIMARYpx;",q=0,U=0,F=-1,W=-1,X=-1,Y=-1,j=[],G=[],K=[],Z={},J=0,Q=L?function(){I.setDimensions(null,null,null,ee.getContentSize(),!0)}:function(){I.setDimensions(null,null,ee.getContentSize(),null,!0)},ee=L?new l:new u;(R?d:f).call(ee),(M?h:p).call(ee);var te=L?"getContentHeight":"getContentWidth",ne=I.options[te];I.options[te]=angular.bind(ee,ee.getContentSize),I.__$callback=I.__callback,I.__callback=function(e,t,n,i){var o=ee.getScrollValue();(-1===F||o+ee.scrollPrimarySize>X||Y>o)&&a(),I.__$callback(e,t,n,i)};var ie=!1,oe=!1;this.refreshLayout=function(){A.length?(v=P(0,A[0]),g=D(0,A[0])):(v=100,g=100);var e=getComputedStyle(m)||{},n=m.firstElementChild&&getComputedStyle(m.firstElementChild)||{},i=m.lastElementChild&&getComputedStyle(m.lastElementChild)||{};U=(parseInt(e[L?"height":"width"])||0)+(n&&parseInt(n[L?"marginTop":"marginLeft"])||0)+(i&&parseInt(i[L?"marginBottom":"marginRight"])||0),q=0;var o=$;do q+=o[L?"offsetTop":"offsetLeft"];while(ionic.DomUtil.contains(I.__content,o=o.offsetParent));var a=$.previousElementSibling,c=a?t.getComputedStyle(a):{},l=parseInt(c[L?"marginBottom":"marginRight"]||0);if($.style[ionic.CSS.TRANSFORM]=O.replace(N,-l).replace(z,0),q-=l,I.__clientHeight&&I.__clientWidth||(I.__clientWidth=I.__container.clientWidth,I.__clientHeight=I.__container.clientHeight),(ee.onRefreshLayout||angular.noop)(),ee.refreshDirection(),Q(),!ie)for(var u=Math.max(20,3*T),d=0;u>d;d++)j.push(new s);ie=!0,ie&&oe&&((I.__scrollLeft>I.__maxScrollLeft||I.__scrollTop>I.__maxScrollTop)&&I.resize(),r(!0))},this.setData=function(e){A=e,(ee.onRefreshData||angular.noop)(),oe=!0},this.destroy=function(){a.destroyed=!0,j.forEach(function(e){e.scope.$destroy(),e.scope=e.element=e.node=e.images=null}),j.length=K.length=G.length=0,Z={},I.options[te]=ne,I.__callback=I.__$callback,I.resize(),(ee.onDestroy||angular.noop)()}}}function n(e){return["$ionicGesture","$parse",function(t,n){var i=e.substr(2).toLowerCase();return function(o,r,a){var c=n(a[e]),s=function(e){o.$apply(function(){c(o,{$event:e})})},l=t.on(i,s,r);o.$on("$destroy",function(){t.off(l,i,s)})}}]}function i(e){return["$document","$timeout",function(t,n){return{restrict:"E",controller:"$ionicHeaderBar",compile:function(i){function o(t,n,i,o){e?(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subheader");t.$hasHeader=n&&!i,t.$hasSubheader=n&&i,t.$emit("$ionicSubheader",t.$hasSubheader)}),t.$on("$destroy",function(){delete t.$hasHeader,delete t.$hasSubheader}),o.align(),t.$on("$ionicHeader.align",function(){ionic.requestAnimationFrame(function(){o.align()})})):(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subfooter");t.$hasFooter=n&&!i,t.$hasSubfooter=n&&i}),t.$on("$destroy",function(){delete t.$hasFooter,delete t.$hasSubfooter}),t.$watch("$hasTabs",function(e){n.toggleClass("has-tabs",!!e)}),o.align(),t.$on("$ionicFooter.align",function(){ionic.requestAnimationFrame(function(){o.align()})}))}return i.addClass(e?"bar bar-header":"bar bar-footer"),n(function(){e&&t[0].getElementsByClassName("tabs-top").length&&i.addClass("has-tabs-top")}),{pre:o}}}}]}function o(e){return e.clientHeight}function r(e){e.stopPropagation()}var a=angular.module("ionic",["ngAnimate","ngSanitize","ui.router","ngIOS9UIWebViewPatch"]),c=angular.extend,s=angular.forEach,l=angular.isDefined,u=angular.isNumber,d=angular.isString,f=angular.element,h=angular.noop;a.factory("$ionicActionSheet",["$rootScope","$compile","$animate","$timeout","$ionicTemplateLoader","$ionicPlatform","$ionicBody","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s){function l(o){function l(e){e&&/icon/.test(e)&&(u.$actionSheetHasIcon=!0)}var u=e.$new(!0);c(u,{cancel:h,destructiveButtonClicked:h,buttonClicked:h,$deregisterBackButton:h,buttons:[],cancelOnStateChange:!0},o||{});for(var d=0;d<u.buttons.length;d++)l(u.buttons[d].text);l(u.cancelText),l(u.destructiveText);var p=u.element=t('<ion-action-sheet ng-class="cssClass" buttons="buttons"></ion-action-sheet>')(u),v=f(p[0].querySelector(".action-sheet-wrapper")),g=u.cancelOnStateChange?e.$on("$stateChangeSuccess",function(){u.cancel()}):h;return u.removeSheet=function(e){u.removed||(u.removed=!0,v.removeClass("action-sheet-up"),i(function(){a.removeClass("action-sheet-open")},400),u.$deregisterBackButton(),g(),n.removeClass(p,"active").then(function(){u.$destroy(),p.remove(),u.cancel.$scope=v=null,(e||h)(o.buttons)}))},u.showSheet=function(e){u.removed||(a.append(p).addClass("action-sheet-open"),n.addClass(p,"active").then(function(){u.removed||(e||h)()}),i(function(){u.removed||v.addClass("action-sheet-up")},20,!1))},u.$deregisterBackButton=r.registerBackButtonAction(function(){i(u.cancel)},s.actionSheet),u.cancel=function(){u.removeSheet(o.cancel)},u.buttonClicked=function(e){o.buttonClicked(e,o.buttons[e])===!0&&u.removeSheet()},u.destructiveButtonClicked=function(){o.destructiveButtonClicked()===!0&&u.removeSheet()},u.showSheet(),u.cancel.$scope=u,u.cancel}return{show:l}}]),f.prototype.addClass=function(e){var t,n,i,o,r,a;if(e&&"ng-scope"!=e&&"ng-isolate-scope"!=e)for(t=0;t<this.length;t++)if(o=this[t],o.setAttribute)if(e.indexOf(" ")<0&&o.classList.add)o.classList.add(e);else{for(a=(" "+(o.getAttribute("class")||"")+" ").replace(/[\n\t]/g," "),r=e.split(" "),n=0;n<r.length;n++)i=r[n].trim(),-1===a.indexOf(" "+i+" ")&&(a+=i+" ");o.setAttribute("class",a.trim())}return this},f.prototype.removeClass=function(e){var t,n,i,o,r;if(e)for(t=0;t<this.length;t++)if(r=this[t],r.getAttribute)if(e.indexOf(" ")<0&&r.classList.remove)r.classList.remove(e);else for(i=e.split(" "),n=0;n<i.length;n++)o=i[n],r.setAttribute("class",(" "+(r.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+o.trim()+" "," ").trim());return this},a.factory("$ionicBackdrop",["$document","$timeout","$$rAF","$rootScope",function(e,t,n,i){function o(){s++,1===s&&(c.addClass("visible"),i.$broadcast("backdrop.shown"),n(function(){s>=1&&c.addClass("active")}))}function r(){1===s&&(c.removeClass("active"),i.$broadcast("backdrop.hidden"),t(function(){0===s&&c.removeClass("visible")},400,!1)),s=Math.max(0,s-1)}function a(){return c}var c=f('<div class="backdrop">'),s=0;return e[0].body.appendChild(c[0]),{retain:o,release:r,getElement:a,_element:c}}]),a.factory("$ionicBind",["$parse","$interpolate",function(e,t){var n=/^\s*([@=&])(\??)\s*(\w*)\s*$/;return function(i,o,r){s(r||{},function(r,a){var c,s,l=r.match(n)||[],u=l[3]||a,d=l[1];switch(d){case"@":if(!o[u])return;o.$observe(u,function(e){i[a]=e}),o[u]&&(i[a]=t(o[u])(i));break;case"=":if(!o[u])return;s=i.$watch(o[u],function(e){i[a]=e}),i.$on("$destroy",s);break;case"&":if(o[u]&&o[u].match(RegExp(a+"(.*?)")))throw new Error('& expression binding "'+a+'" looks like it will recursively call "'+o[u]+'" and cause a stack overflow! Please choose a different scopeName.');c=e(o[u]),i[a]=function(e){return c(i,e)}}})}}]),a.factory("$ionicBody",["$document",function(e){return{addClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.add(arguments[t]);return this},removeClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.remove(arguments[t]);return this},enableClass:function(e){var t=Array.prototype.slice.call(arguments).slice(1);return e?this.addClass.apply(this,t):this.removeClass.apply(this,t),this},append:function(t){return e[0].body.appendChild(t.length?t[0]:t),this},get:function(){return e[0].body}}}]),a.factory("$ionicClickBlock",["$document","$ionicBody","$timeout",function(e,t,n){function i(e){e.preventDefault(),e.stopPropagation()}function o(){s&&(a?a.classList.remove(l):(a=e[0].createElement("div"),a.className="click-block",t.append(a),a.addEventListener("touchstart",i),a.addEventListener("mousedown",i)),s=!1)}function r(){a&&a.classList.add(l)}var a,c,s,l="click-block-hide";return{show:function(e){s=!0,n.cancel(c),c=n(this.hide,e||310,!1),o()},hide:function(){s=!1,n.cancel(c),r()}}}]),a.factory("$ionicGesture",[function(){return{on:function(e,t,n,i){return window.ionic.onGesture(e,t,n[0],i)},off:function(e,t,n){return window.ionic.offGesture(e,t,n)}}}]),a.factory("$ionicHistory",["$rootScope","$state","$location","$window","$timeout","$ionicViewSwitcher","$ionicNavViewDelegate",function(e,t,n,i,o,r,a){function s(e){return e?R.views[e]:null}function u(e){return e?s(e.backViewId):null}function d(e){return e?s(e.forwardViewId):null}function f(e){return e?R.histories[e]:null}function h(e){var t=p(e);return R.histories[t.historyId]||(R.histories[t.historyId]={historyId:t.historyId,parentHistoryId:p(t.scope.$parent).historyId,stack:[],cursor:-1}),f(t.historyId)}function p(t){for(var n=t;n;){if(n.hasOwnProperty("$historyId"))return{historyId:n.$historyId,scope:n};n=n.$parent}return{historyId:"root",scope:e}}function v(e){R.currentView=s(e),R.backView=u(R.currentView),R.forwardView=d(R.currentView)}function g(){var e;if(t&&t.current&&t.current.name){if(e=t.current.name,t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&t.params[n]&&(e+="_"+n+"="+t.params[n]);return e}return ionic.Utils.nextUid()}function m(){var e;if(t&&t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&(e=e||{},e[n]=t.params[n]);return e}function $(e){return e&&e.length&&/ion-side-menus|ion-tabs/i.test(e[0].tagName)}function w(e,t){return t&&t.$$state&&t.$$state.self.canSwipeBack===!1?!1:e&&"false"===e.attr("can-swipe-back")?!1:!0}var b,y,S,k,C,T="initialView",B="newView",I="moveBack",x="moveForward",A="back",E="forward",V="enter",P="exit",_="swap",D="none",L=0,R={histories:{root:{historyId:"root",parentHistoryId:null,stack:[],cursor:-1}},views:{},backView:null,forwardView:null,currentView:null},M=function(){};return M.prototype.initialize=function(e){if(e){for(var t in e)this[t]=e[t];return this}return null},M.prototype.go=function(){if(this.stateName)return t.go(this.stateName,this.stateParams);if(this.url&&this.url!==n.url()){if(R.backView===this)return i.history.go(-1);if(R.forwardView===this)return i.history.go(1);n.url(this.url)}return null},M.prototype.destroy=function(){this.scope&&(this.scope.$destroy&&this.scope.$destroy(),this.scope=null)},{register:function(e,t){var i,a,c,l=g(),d=h(e),$=R.currentView,M=R.backView,N=R.forwardView,z=null,O=null,H=D,q=d.historyId,U=n.url();if(b!==l&&(b=l,L++),C)z=C.viewId,O=C.action,H=C.direction,C=null;else if(M&&M.stateId===l)z=M.viewId,q=M.historyId,O=I,M.historyId===$.historyId?H=A:$&&(H=P,i=f(M.historyId),i&&i.parentHistoryId===$.historyId?H=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(H=_)));else if(N&&N.stateId===l)z=N.viewId,q=N.historyId,O=x,N.historyId===$.historyId?H=E:$&&(H=P,$.historyId===d.parentHistoryId?H=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(H=_))),i=p(e),N.historyId&&i.scope&&(i.scope.$historyId=N.historyId,q=N.historyId);else if($&&$.historyId!==q&&d.cursor>-1&&d.stack.length>0&&d.cursor<d.stack.length&&d.stack[d.cursor].stateId===l){var F=d.stack[d.cursor];z=F.viewId,q=F.historyId,O=I,H=_,i=f($.historyId),i&&i.parentHistoryId===q?H=P:(i=f(q),i&&i.parentHistoryId===$.historyId&&(H=V)),i=s(F.backViewId),i&&F.historyId!==i.historyId&&(d.stack[d.cursor].backViewId=$.viewId)}else{if(c=r.createViewEle(t),this.isAbstractEle(c,t))return{action:"abstractView",direction:D,ele:c};if(z=ionic.Utils.nextUid(),$){if($.forwardViewId=z,O=B,N&&$.stateId!==N.stateId&&$.historyId===N.historyId&&(i=f(N.historyId))){for(a=i.stack.length-1;a>=N.index;a--){var W=i.stack[a];W&&W.destroy&&W.destroy(),i.stack.splice(a)}q=N.historyId}d.historyId===$.historyId?H=E:$.historyId!==d.historyId&&(H=V,i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId?H=_:(i=f(i.parentHistoryId),i&&i.historyId===d.historyId&&(H=P)))}else O=T;2>L&&(H=D),R.views[z]=this.createView({viewId:z,index:d.stack.length,historyId:d.historyId,backViewId:$&&$.viewId?$.viewId:null,forwardViewId:null,stateId:l,stateName:this.currentStateName(),stateParams:m(),url:U,canSwipeBack:w(c,t)}),d.stack.push(R.views[z])}if(S&&S(),o.cancel(k),y){if(y.disableAnimate&&(H=D),y.disableBack&&(R.views[z].backViewId=null),y.historyRoot){for(a=0;a<d.stack.length;a++)d.stack[a].viewId===z?(d.stack[a].index=0,d.stack[a].backViewId=d.stack[a].forwardViewId=null):delete R.views[d.stack[a].viewId];d.stack=[R.views[z]]}y=null}if(v(z),R.backView&&q==R.backView.historyId&&l==R.backView.stateId&&U==R.backView.url)for(a=0;a<d.stack.length;a++)if(d.stack[a].viewId==z){O="dupNav",H=D,a>0&&(d.stack[a-1].forwardViewId=null),R.forwardView=null,R.currentView.index=R.backView.index,R.currentView.backViewId=R.backView.backViewId,R.backView=u(R.backView),d.stack.splice(a,1);break}return d.cursor=R.currentView.index,{viewId:z,action:O,direction:H,historyId:q,enableBack:this.enabledBack(R.currentView),isHistoryRoot:0===R.currentView.index,ele:c}},registerHistory:function(e){e.$historyId=ionic.Utils.nextUid()},createView:function(e){var t=new M;return t.initialize(e)},getViewById:s,viewHistory:function(){return R},currentView:function(e){return arguments.length&&(R.currentView=e),R.currentView},currentHistoryId:function(){return R.currentView?R.currentView.historyId:null},currentTitle:function(e){return R.currentView?(arguments.length&&(R.currentView.title=e),R.currentView.title):void 0},backView:function(e){return arguments.length&&(R.backView=e),R.backView},backTitle:function(e){var t=e&&s(e.backViewId)||R.backView;return t&&t.title},forwardView:function(e){return arguments.length&&(R.forwardView=e),R.forwardView},currentStateName:function(){return t&&t.current?t.current.name:null},isCurrentStateNavView:function(e){return!!(t&&t.current&&t.current.views&&t.current.views[e])},goToHistoryRoot:function(e){if(e){var t=f(e);if(t&&t.stack.length){if(R.currentView&&R.currentView.viewId===t.stack[0].viewId)return;C={viewId:t.stack[0].viewId,action:I,direction:A},t.stack[0].go()}}},goBack:function(e){if(l(e)&&-1!==e){if(e>-1)return;var t=R.histories[this.currentHistoryId()],n=t.cursor+e+1;1>n&&(n=1),t.cursor=n,v(t.stack[n].viewId);for(var i=n-1,r=[],a=s(t.stack[i].forwardViewId);a&&(r.push(a.stateId||a.viewId),i++,!(i>=t.stack.length));)a=s(t.stack[i].forwardViewId);var c=this;r.length&&o(function(){c.clearCache(r)},600)}R.backView&&R.backView.go()},enabledBack:function(e){var t=u(e);return!(!t||t.historyId!==e.historyId)},clearHistory:function(){var e=R.histories,t=R.currentView;if(e)for(var n in e)e[n].stack&&(e[n].stack=[],e[n].cursor=-1),t&&t.historyId===n?(t.backViewId=t.forwardViewId=null,e[n].stack.push(t)):e[n].destroy&&e[n].destroy();for(var i in R.views)i!==t.viewId&&delete R.views[i];t&&v(t.viewId)},clearCache:function(e){return o(function(){a._instances.forEach(function(t){t.clearCache(e)})})},nextViewOptions:function(t){return S&&S(),arguments.length&&(o.cancel(k),null===t?y=t:(y=y||{},c(y,t),y.expire&&(S=e.$on("$stateChangeSuccess",function(){k=o(function(){y=null},y.expire)})))),y},isAbstractEle:function(e,t){return t&&t.$$state&&t.$$state.self["abstract"]?!0:!(!e||!$(e)&&!$(e.children()))},isActiveScope:function(e){if(!e)return!1;for(var t,n=e,i=this.currentHistoryId();n;){if(n.$$disconnected)return!1;if(!t&&n.hasOwnProperty("$historyId")&&(t=!0),i){if(n.hasOwnProperty("$historyId")&&i==n.$historyId)return!0;if(n.hasOwnProperty("$activeHistoryId")&&i==n.$activeHistoryId){if(n.hasOwnProperty("$historyId"))return!0;if(!t)return!0}}t&&n.hasOwnProperty("$activeHistoryId")&&(t=!1),n=n.$parent}return i?"root"==i:!0}}}]).run(["$rootScope","$state","$location","$document","$ionicPlatform","$ionicHistory","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a){function c(e){var t=r.backView();return t?t.go():ionic.Platform.exitApp(),e.preventDefault(),!1}e.$on("$ionicView.beforeEnter",function(){ionic.keyboard&&ionic.keyboard.hide&&ionic.keyboard.hide()}),e.$on("$ionicHistory.change",function(e,i){if(!i)return null;var o=r.viewHistory(),a=i.historyId?o.histories[i.historyId]:null;if(a&&a.cursor>-1&&a.cursor<a.stack.length){var c=a.stack[a.cursor];return c.go(i)}!i.url&&i.uiSref&&(i.url=t.href(i.uiSref)),i.url&&(0===i.url.indexOf("#")&&(i.url=i.url.replace("#","")),i.url!==n.url()&&n.url(i.url))}),e.$ionicGoBack=function(e){r.goBack(e)},e.$on("$ionicView.afterEnter",function(e,t){t&&t.title&&(i[0].title=t.title)}),o.registerBackButtonAction(c,a.view)}]),a.provider("$ionicConfig",function(){function e(e,i){a.platform[e]=i,o.platform[e]={},t(a,a.platform[e]),n(a.platform[e],o.platform[e],"")}function t(e,n){for(var i in e)i!=r&&e.hasOwnProperty(i)&&(angular.isObject(e[i])?(l(n[i])||(n[i]={}),t(e[i],n[i])):l(n[i])||(n[i]=null))}function n(e,t,o){s(e,function(c,s){angular.isObject(e[s])?(t[s]={},n(e[s],t[s],o+"."+s)):t[s]=function(n){if(arguments.length)return e[s]=n,t;if(e[s]==r){var c=i(a.platform,ionic.Platform.platform()+o+"."+s);return c||c===!1?c:i(a.platform,"default"+o+"."+s)}return e[s]}})}function i(e,t){t=t.split(".");for(var n=0;n<t.length;n++){if(!e||!l(e[t[n]]))return null;e=e[t[n]]}return e}var o=this;o.platform={};var r="platform",a={views:{maxCache:r,forwardCache:r,transition:r,swipeBackEnabled:r,swipeBackHitWidth:r},navBar:{alignTitle:r,positionPrimaryButtons:r,positionSecondaryButtons:r,transition:r},backButton:{icon:r,text:r,previousTitleText:r},form:{checkbox:r,toggle:r},scrolling:{jsScrolling:r},spinner:{icon:r},tabs:{style:r,position:r},templates:{maxPrefetch:r},platform:{}};n(a,o,""),e("default",{views:{maxCache:10,forwardCache:!1,transition:"ios",swipeBackEnabled:!0,swipeBackHitWidth:45},navBar:{alignTitle:"center",positionPrimaryButtons:"left",positionSecondaryButtons:"right",transition:"view"},backButton:{icon:"ion-ios-arrow-back",text:"Back",previousTitleText:!0},form:{checkbox:"circle",toggle:"large"},scrolling:{jsScrolling:!0},spinner:{icon:"ios"},tabs:{style:"standard",position:"bottom"},templates:{maxPrefetch:30}}),e("ios",{}),e("android",{views:{transition:"android",swipeBackEnabled:!1},navBar:{alignTitle:"left",positionPrimaryButtons:"right",positionSecondaryButtons:"right"},backButton:{icon:"ion-android-arrow-back",text:!1,previousTitleText:!1},form:{checkbox:"square",toggle:"small"},spinner:{icon:"android"},tabs:{style:"striped",position:"top"},scrolling:{jsScrolling:!1}}),e("windowsphone",{spinner:{icon:"android"}}),o.transitions={views:{},navBar:{}},o.transitions.views.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,o.opacity=t,i>-1&&(o.boxShadow="0 0 10px rgba(0,0,0,"+(r.shouldAnimate?.45*i:.3)+")"),o[ionic.CSS.TRANSFORM]="translate3d("+n+"%,0,0)",ionic.DomUtil.cachedStyles(e,o)}var r={run:function(i){"forward"==n?(o(e,1,99*(1-i),1-i),o(t,1-.1*i,-33*i,-1)):"back"==n?(o(e,1-.1*(1-i),-33*(1-i),-1),o(t,1,100*i,1-i)):(o(e,1,0,-1),o(t,0,0,-1))},shouldAnimate:i&&("forward"==n||"back"==n)};return r},o.transitions.navBar.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=c.shouldAnimate?"":"0ms",o.opacity=1===t?"":t,e.setCss("buttons-left",o),e.setCss("buttons-right",o),e.setCss("back-button",o),o[ionic.CSS.TRANSFORM]="translate3d("+i+"px,0,0)",e.setCss("back-text",o),o[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e.setCss("title",o)}function r(e,t,n){if(e&&t){var i=(e.titleTextX()+e.titleWidth())*(1-n),r=t&&(t.titleTextX()-e.backButtonTextLeft())*(1-n)||0;o(e,n,i,r)}}function a(e,t,n){if(e&&t){var i=(-(e.titleTextX()-t.backButtonTextLeft())-e.titleLeftRight())*n;o(e,1-n,i,0)}}var c={run:function(n){var i=e.controller(),o=t&&t.controller();"back"==c.direction?(a(i,o,1-n),r(o,i,1-n)):(r(i,o,n),a(o,i,n))},direction:n,shouldAnimate:i&&("forward"==n||"back"==n)};return c},o.transitions.views.android=function(e,t,n,i){function o(e,t){var n={};n[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,n[ionic.CSS.TRANSFORM]="translate3d("+t+"%,0,0)",ionic.DomUtil.cachedStyles(e,n)}i=i&&("forward"==n||"back"==n);var r={run:function(i){"forward"==n?(o(e,99*(1-i)),o(t,-100*i)):"back"==n?(o(e,-100*(1-i)),o(t,100*i)):(o(e,0),o(t,0))},shouldAnimate:i};return r},o.transitions.navBar.android=function(e,t,n,i){function o(e,t){if(e){var n={};n.opacity=1===t?"":t,e.setCss("buttons-left",n),e.setCss("buttons-right",n),e.setCss("back-button",n),e.setCss("back-text",n),e.setCss("title",n)}}return{run:function(n){o(e.controller(),n),o(t&&t.controller(),1-n)},shouldAnimate:i&&("forward"==n||"back"==n)}},o.transitions.views.none=function(e,t){return{run:function(n){o.transitions.views.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.transitions.navBar.none=function(e,t){return{run:function(n){o.transitions.navBar.ios(e,t,!1,!1).run(n),o.transitions.navBar.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.setPlatformConfig=e,o.$get=function(){return o}}).config(["$compileProvider",function(e){e.aHrefSanitizationWhitelist(/^\s*(https?|sms|tel|geo|ftp|mailto|file|ghttps?|ms-appx-web|ms-appx|x-wmapp0):/),e.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|ms-appx-web|x-wmapp0):|data:image\//); +}]);var p='<div class="loading-container"><div class="loading"></div></div>',v="$ionicLoading instance.hide() has been deprecated. Use $ionicLoading.hide().",g="$ionicLoading instance.show() has been deprecated. Use $ionicLoading.show().",m="$ionicLoading instance.setContent() has been deprecated. Use $ionicLoading.show({ template: 'my content' }).";a.constant("$ionicLoadingConfig",{template:"<ion-spinner></ion-spinner>"}).factory("$ionicLoading",["$ionicLoadingConfig","$ionicBody","$ionicTemplateLoader","$ionicBackdrop","$timeout","$q","$log","$compile","$ionicPlatform","$rootScope","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s,l,u,d){function f(){return b||(b=n.compile({template:p,appendTo:t.get()}).then(function(e){return e.show=function(a){var c=a.templateUrl?n.load(a.templateUrl):r.when(a.template||a.content||"");e.scope=a.scope||e.scope,e.isShown||(e.hasBackdrop=!a.noBackdrop&&a.showBackdrop!==!1,e.hasBackdrop&&(i.retain(),i.getElement().addClass("backdrop-loading"))),a.duration&&(o.cancel(e.durationTimeout),e.durationTimeout=o(angular.bind(e,e.hide),+a.duration)),y(),y=l.registerBackButtonAction(h,d.loading),c.then(function(n){if(n){var i=e.element.children();i.html(n),s(i.contents())(e.scope)}e.isShown&&(e.element.addClass("visible"),ionic.requestAnimationFrame(function(){e.isShown&&(e.element.addClass("active"),t.addClass("loading-active"))}))}),e.isShown=!0},e.hide=function(){y(),e.isShown&&(e.hasBackdrop&&(i.release(),i.getElement().removeClass("backdrop-loading")),e.element.removeClass("active"),t.removeClass("loading-active"),e.element.removeClass("visible"),ionic.requestAnimationFrame(function(){!e.isShown&&e.element.removeClass("visible")})),o.cancel(e.durationTimeout),e.isShown=!1;var n=e.element.children();n.html("")},e})),b}function $(t){t=c({},e||{},t||{});var n=t.delay||t.showDelay||0;return S(),k(),t.hideOnStateChange&&(S=u.$on("$stateChangeSuccess",w),k=u.$on("$stateChangeError",w)),o.cancel(C),C=o(h,n),C.then(f).then(function(e){return e.show(t)}),{hide:function(){return a.error(v),w.apply(this,arguments)},show:function(){return a.error(g),$.apply(this,arguments)},setContent:function(e){return a.error(m),f().then(function(t){t.show({template:e})})}}}function w(){S(),k(),o.cancel(C),f().then(function(e){e.hide()})}var b,y=h,S=h,k=h,C=r.when();return{show:$,hide:w,_getLoader:f}}]),a.factory("$ionicModal",["$rootScope","$ionicBody","$compile","$timeout","$ionicPlatform","$ionicTemplateLoader","$$q","$log","$ionicClickBlock","$window","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s,l,u,d){var p=ionic.views.Modal.inherit({initialize:function(e){ionic.views.Modal.prototype.initialize.call(this,e),this.animation=e.animation||"slide-in-up"},show:function(e){var n=this;if(n.scope.$$destroyed)return s.error("Cannot call "+n.viewType+".show() after remove(). Please create a new "+n.viewType+" instance."),a.when();l.show(600),m.add(n);var r=f(n.modalEl);n.el.classList.remove("hide"),i(function(){n._isShown&&t.addClass(n.viewType+"-open")},400,!1),n.el.parentElement||(r.addClass(n.animation),t.append(n.el));var c=r.data("$$ionicScrollController");return c&&c.resize(),e&&n.positionView&&(n.positionView(e,r),n._onWindowResize=function(){n._isShown&&n.positionView(e,r)},ionic.on("resize",n._onWindowResize,window)),r.addClass("ng-enter active").removeClass("ng-leave ng-leave-active"),n._isShown=!0,n._deregisterBackButton=o.registerBackButtonAction(n.hardwareBackButtonClose?angular.bind(n,n.hide):h,d.modal),ionic.views.Modal.prototype.show.call(n),i(function(){n._isShown&&(r.addClass("ng-enter-active"),ionic.trigger("resize"),n.scope.$parent&&n.scope.$parent.$broadcast(n.viewType+".shown",n),n.el.classList.add("active"),n.scope.$broadcast("$ionicHeader.align"),n.scope.$broadcast("$ionicFooter.align"))},20),i(function(){n._isShown&&(n.$el.on("touchmove",function(e){var t=ionic.DomUtil.getParentOrSelfWithClass(e.target,"scroll");t||e.preventDefault()}),n.$el.on("click",function(e){n.backdropClickToClose&&e.target===n.el&&m.isHighest(n)&&n.hide()}))},400)},hide:function(){var e=this,n=f(e.modalEl);return l.show(600),m.remove(e),e.el.classList.remove("active"),n.addClass("ng-leave"),i(function(){e._isShown||n.addClass("ng-leave-active").removeClass("ng-enter ng-enter-active active")},20,!1),e.$el.off("click"),e._isShown=!1,e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".hidden",e),e._deregisterBackButton&&e._deregisterBackButton(),ionic.views.Modal.prototype.hide.call(e),e.positionView&&ionic.off("resize",e._onWindowResize,window),i(function(){t.removeClass(e.viewType+"-open"),e.el.classList.add("hide")},e.hideDelay||320)},remove:function(){var e=this;return e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".removed",e),e.hide().then(function(){e.scope.$destroy(),e.$el.remove()})},isShown:function(){return!!this._isShown}}),v=function(t,i){var o=i.scope&&i.scope.$new()||e.$new(!0);i.viewType=i.viewType||"modal",c(o,{$hasHeader:!1,$hasSubheader:!1,$hasFooter:!1,$hasSubfooter:!1,$hasTabs:!1,$hasTabsTop:!1});var r=n("<ion-"+i.viewType+">"+t+"</ion-"+i.viewType+">")(o);i.$el=r,i.el=r[0],i.modalEl=i.el.querySelector("."+i.viewType);var a=new p(i);return a.scope=o,i.scope||(o[i.viewType]=a),a},g=[],m={add:function(e){g.push(e)},remove:function(e){var t=g.indexOf(e);t>-1&&t<g.length&&g.splice(t,1)},isHighest:function(e){var t=g.indexOf(e);return t>-1&&t===g.length-1}};return{fromTemplate:function(e,t){var n=v(e,t||{});return n},fromTemplateUrl:function(e,t,n){var i;return angular.isFunction(t)&&(i=t,t=n),r.load(e).then(function(e){var n=v(e,t||{});return i&&i(n),n})},stack:m}}]),a.service("$ionicNavBarDelegate",ionic.DelegateService(["align","showBackButton","showBar","title","changeTitle","setTitle","getTitle","back","getPreviousTitle"])),a.service("$ionicNavViewDelegate",ionic.DelegateService(["clearCache"])),a.constant("IONIC_BACK_PRIORITY",{view:100,sideMenu:150,modal:200,actionSheet:300,popup:400,loading:500}).provider("$ionicPlatform",function(){return{$get:["$q","$ionicScrollDelegate",function(e,t){var n={onHardwareBackButton:function(e){ionic.Platform.ready(function(){document.addEventListener("backbutton",e,!1)})},offHardwareBackButton:function(e){ionic.Platform.ready(function(){document.removeEventListener("backbutton",e)})},$backButtonActions:{},registerBackButtonAction:function(e,t,i){n._hasBackButtonHandler||(n.$backButtonActions={},n.onHardwareBackButton(n.hardwareBackButtonClick),n._hasBackButtonHandler=!0);var o={id:i?i:ionic.Utils.nextUid(),priority:t?t:0,fn:e};return n.$backButtonActions[o.id]=o,function(){delete n.$backButtonActions[o.id]}},hardwareBackButtonClick:function(e){var t,i;for(i in n.$backButtonActions)(!t||n.$backButtonActions[i].priority>=t.priority)&&(t=n.$backButtonActions[i]);return t?(t.fn(e),t):void 0},is:function(e){return ionic.Platform.is(e)},on:function(e,t){return ionic.Platform.ready(function(){document.addEventListener(e,t,!1)}),function(){ionic.Platform.ready(function(){document.removeEventListener(e,t)})}},ready:function(t){var n=e.defer();return ionic.Platform.ready(function(){n.resolve(),t&&t()}),n.promise}};return window.addEventListener("statusTap",function(){t.scrollTop(!0)}),n}]}}),a.factory("$ionicPopover",["$ionicModal","$ionicPosition","$document","$window",function(e,t,n,i){function o(e,n){var o=f(e.target||e),a=t.offset(o),c=n.prop("offsetWidth"),s=n.prop("offsetHeight"),l=i.innerWidth,u=i.innerHeight,d={left:a.left+a.width/2-c/2},h=f(n[0].querySelector(".popover-arrow"));d.left<r?d.left=r:d.left+c+r>l&&(d.left=l-c-r),a.top+a.height+s>u&&a.top-s>0?(d.top=a.top-s,n.addClass("popover-bottom")):(d.top=a.top+a.height,n.removeClass("popover-bottom")),h.css({left:a.left+a.width/2-h.prop("offsetWidth")/2-d.left+"px"}),n.css({top:d.top+"px",left:d.left+"px",marginLeft:"0",opacity:"1"})}var r=6,a={viewType:"popover",hideDelay:1,animation:"none",positionView:o};return{fromTemplate:function(t,n){return e.fromTemplate(t,ionic.Utils.extend({},a,n))},fromTemplateUrl:function(t,n){return e.fromTemplateUrl(t,ionic.Utils.extend({},a,n))}}}]);var $='<div class="popup-container" ng-class="cssClass"><div class="popup"><div class="popup-head"><h3 class="popup-title" ng-bind-html="title"></h3><h5 class="popup-sub-title" ng-bind-html="subTitle" ng-if="subTitle"></h5></div><div class="popup-body"></div><div class="popup-buttons" ng-show="buttons.length"><button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button></div></div></div>';a.factory("$ionicPopup",["$ionicTemplateLoader","$ionicBackdrop","$q","$timeout","$rootScope","$ionicBody","$compile","$ionicPlatform","$ionicModal","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s,l,u){function d(t){t=c({scope:null,title:"",buttons:[]},t||{});var s={};return s.scope=(t.scope||o).$new(),s.element=f($),s.responseDeferred=n.defer(),r.get().appendChild(s.element[0]),a(s.element)(s.scope),c(s.scope,{title:t.title,buttons:t.buttons,subTitle:t.subTitle,cssClass:t.cssClass,$buttonTapped:function(e,t){var n=(e.onTap||h).apply(s,[t]);t=t.originalEvent||t,t.defaultPrevented||s.responseDeferred.resolve(n)}}),n.when(t.templateUrl?e.load(t.templateUrl):t.template||t.content||"").then(function(e){var t=f(s.element[0].querySelector(".popup-body"));e?(t.html(e),a(t.contents())(s.scope)):t.remove()}),s.show=function(){s.isShown||s.removed||(l.stack.add(s),s.isShown=!0,ionic.requestAnimationFrame(function(){s.isShown&&(s.element.removeClass("popup-hidden"),s.element.addClass("popup-showing active"),g(s.element))}))},s.hide=function(e){return e=e||h,s.isShown?(l.stack.remove(s),s.isShown=!1,s.element.removeClass("active"),s.element.addClass("popup-hidden"),void i(e,250,!1)):e()},s.remove=function(){s.removed||(s.hide(function(){s.element.remove(),s.scope.$destroy()}),s.removed=!0)},s}function p(){var e=S[S.length-1];e&&e.responseDeferred.resolve()}function v(e){function n(){S.push(o),i(o.show,a,!1),o.responseDeferred.promise.then(function(e){var n=S.indexOf(o);return-1!==n&&S.splice(n,1),o.remove(),S.length>0?S[S.length-1].show():(t.release(),i(function(){S.length||r.removeClass("popup-open")},400,!1),(k._backButtonActionDone||h)()),e})}var o=k._createPopup(e),a=0;return S.length>0?(a=y.stackPushDelay,i(S[S.length-1].hide,a,!1)):(r.addClass("popup-open"),t.retain(),k._backButtonActionDone=s.registerBackButtonAction(p,u.popup)),o.responseDeferred.promise.close=function(e){o.removed||o.responseDeferred.resolve(e)},o.responseDeferred.notify({close:o.responseDeferred.close}),n(),o.responseDeferred.promise}function g(e){var t=e[0].querySelector("[autofocus]");t&&t.focus()}function m(e){return v(c({buttons:[{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function w(e){return v(c({buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){return!1}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function b(e){var t=o.$new(!0);t.data={},t.data.fieldtype=e.inputType?e.inputType:"text",t.data.response=e.defaultText?e.defaultText:"",t.data.placeholder=e.inputPlaceholder?e.inputPlaceholder:"",t.data.maxlength=e.maxLength?parseInt(e.maxLength):"";var n="";return e.template&&/<[a-z][\s\S]*>/i.test(e.template)===!1&&(n="<span>"+e.template+"</span>",delete e.template),v(c({template:n+'<input ng-model="data.response" type="{{ data.fieldtype }}"maxlength="{{ data.maxlength }}"placeholder="{{ data.placeholder }}">',scope:t,buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return t.data.response||""}}]},e||{}))}var y={stackPushDelay:75},S=[],k={show:v,alert:m,confirm:w,prompt:b,_createPopup:d,_popupStack:S};return k}]),a.factory("$ionicPosition",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function i(e){return"static"===(n(e,"position")||"static")}var o=function(t){for(var n=e[0],o=t.offsetParent||n;o&&o!==n&&i(o);)o=o.offsetParent;return o||n};return{position:function(t){var n=this.offset(t),i={top:0,left:0},r=o(t[0]);r!=e[0]&&(i=this.offset(f(r)),i.top+=r.clientTop-r.scrollTop,i.left+=r.clientLeft-r.scrollLeft);var a=t[0].getBoundingClientRect();return{width:a.width||t.prop("offsetWidth"),height:a.height||t.prop("offsetHeight"),top:n.top-i.top,left:n.left-i.left}},offset:function(n){var i=n[0].getBoundingClientRect();return{width:i.width||n.prop("offsetWidth"),height:i.height||n.prop("offsetHeight"),top:i.top+(t.pageYOffset||e[0].documentElement.scrollTop),left:i.left+(t.pageXOffset||e[0].documentElement.scrollLeft)}}}}]),a.service("$ionicScrollDelegate",ionic.DelegateService(["resize","scrollTop","scrollBottom","scrollTo","scrollBy","zoomTo","zoomBy","getScrollPosition","anchorScroll","freezeScroll","freezeAllScrolls","getScrollView"])),a.service("$ionicSideMenuDelegate",ionic.DelegateService(["toggleLeft","toggleRight","getOpenRatio","isOpen","isOpenLeft","isOpenRight","canDragContent","edgeDragThreshold"])),a.service("$ionicSlideBoxDelegate",ionic.DelegateService(["update","slide","select","enableSlide","previous","next","stop","autoPlay","start","currentIndex","selected","slidesCount","count","loop"])),a.service("$ionicTabsDelegate",ionic.DelegateService(["select","selectedIndex","showBar"])),function(){var e=[];a.factory("$ionicTemplateCache",["$http","$templateCache","$timeout",function(t,n,i){function o(e){return"undefined"==typeof e?r():(d(e)&&(e=[e]),s(e,function(e){c.push(e)}),void(a&&r()))}function r(){var e;if(o._runCount++,a=!0,0!==c.length){for(var s=0;4>s&&(e=c.pop());)d(e)&&t.get(e,{cache:n}),s++;c.length&&i(r,1e3)}}var a,c=e;return o._runCount=0,o}]).config(["$stateProvider","$ionicConfigProvider",function(t,n){var i=t.state;t.state=function(o,r){if("object"==typeof r){var a=r.prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch();if(a&&d(r.templateUrl)&&e.push(r.templateUrl),angular.isObject(r.views))for(var c in r.views)a=r.views[c].prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch(),a&&d(r.views[c].templateUrl)&&e.push(r.views[c].templateUrl)}return i.call(t,o,r)}}]).run(["$ionicTemplateCache",function(e){e()}])}(),a.factory("$ionicTemplateLoader",["$compile","$controller","$http","$q","$rootScope","$templateCache",function(e,t,n,i,o,r){function a(e){return n.get(e,{cache:r}).then(function(e){return e.data&&e.data.trim()})}function s(n){n=c({template:"",templateUrl:"",scope:null,controller:null,locals:{},appendTo:null},n||{});var r=n.templateUrl?this.load(n.templateUrl):i.when(n.template);return r.then(function(i){var r,a=n.scope||o.$new(),s=f("<div>").html(i).contents();return n.controller&&(r=t(n.controller,c(n.locals,{$scope:a})),s.children().data("$ngControllerController",r)),n.appendTo&&f(n.appendTo).append(s),e(s)(a),{element:s,scope:a}})}return{load:a,compile:s}}]),a.factory("$ionicViewService",["$ionicHistory","$log",function(e,t){function n(e,n){t.warn("$ionicViewService"+e+" is deprecated, please use $ionicHistory"+n+" instead: http://ionicframework.com/docs/nightly/api/service/$ionicHistory/")}n("","");var i={getCurrentView:"currentView",getBackView:"backView",getForwardView:"forwardView",getCurrentStateName:"currentStateName",nextViewOptions:"nextViewOptions",clearHistory:"clearHistory"};return s(i,function(t,o){i[o]=function(){return n("."+o,"."+t),e[t].apply(this,arguments)}}),i}]),a.factory("$ionicViewSwitcher",["$timeout","$document","$q","$ionicClickBlock","$ionicConfig","$ionicNavBarDelegate",function(e,t,n,i,o,r){function a(e,t){return u(e)["abstract"]?u(e).name:t?t.stateId||t.viewId:ionic.Utils.nextUid()}function u(e){return e&&e.$$state&&e.$$state.self||{}}function d(e,t,n,i){var r=u(e),a=g||V(t,"view-transition")||r.viewTransition||o.views.transition()||"ios",s=o.navBar.transition();return n=m||V(t,"view-direction")||r.viewDirection||n||"none",c(h(i),{transition:a,navBarTransition:"view"===s?a:s,direction:n,shouldAnimate:"none"!==a&&"none"!==n})}function h(e){return e=e||{},{viewId:e.viewId,historyId:e.historyId,stateId:e.stateId,stateName:e.stateName,stateParams:e.stateParams}}function p(e,t){return arguments.length>1?void V(e,T,t):V(e,T)}function v(e){if(e&&e.length){var t=e.scope();t&&(t.$emit("$ionicView.unloaded",e.data(C)),t.$destroy()),e.remove()}}var g,m,$="webkitTransitionEnd transitionend",w="$noCache",b="$destroyEle",y="$eleId",S="$accessed",k="$fallbackTimer",C="$viewData",T="nav-view",B="active",I="cached",x="stage",A=0;ionic.transition=ionic.transition||{},ionic.transition.isActive=!1;var E,V=ionic.DomUtil.cachedAttr,P=[],_=1100,D={create:function(t,s,f,T,E,L){var R,M,N,z=++A,O={init:function(e,t){D.isTransitioning(!0),O.loadViewElements(e),O.render(e,function(){t&&t()})},loadViewElements:function(e){var n,i,o,r=t.getViewElements(),c=a(s,f),u=t.activeEleId();for(n=0,i=r.length;i>n&&(o=r.eq(n),o.data(y)===c?o.data(w)?(o.data(y,c+ionic.Utils.nextUid()),o.data(b,!0)):R=o:l(u)&&o.data(y)===u&&(M=o),!R||!M);n++);N=!!R,N||(R=e.ele||D.createViewEle(s),R.data(y,c)),L&&t.activeEleId(c),e.ele=null},render:function(e,n){if(N)ionic.Utils.reconnectScope(R.scope());else{p(R,x);var i=d(s,R,e.direction,f),r=o.transitions.views[i.transition]||o.transitions.views.none;r(R,null,i.direction,!0).run(0),R.data(C,{viewId:i.viewId,historyId:i.historyId,stateName:i.stateName,stateParams:i.stateParams}),(u(s).cache===!1||"false"===u(s).cache||"false"==R.attr("cache-view")||0===o.views.maxCache())&&R.data(w,!0);var a=t.appendViewElement(R,s);delete i.direction,delete i.transition,a.$emit("$ionicView.loaded",i)}R.data(S,Date.now()),n&&n()},transition:function(a,l,u){function v(){p(R,F.shouldAnimate?"entering":B),p(M,F.shouldAnimate?"leaving":I),F.run(1),r._instances.forEach(function(e){e.triggerTransitionStart(z)}),F.shouldAnimate||b()}function w(e){e.target===this&&b()}function b(){b.x||(b.x=!0,R.off($,w),e.cancel(R.data(k)),M&&e.cancel(M.data(k)),C&&C.resolve(t),z===A&&(n.all(P).then(D.transitionEnd),O.emit("after",H,q),O.cleanup(H)),r._instances.forEach(function(e){e.triggerTransitionEnd()}),g=m=f=T=R=M=null)}function y(e){e.target===this&&S()}function S(){p(R,I),p(M,B),R.off($,y),e.cancel(R.data(k)),D.transitionEnd([t])}var C,H=d(s,R,a,f),q=c(c({},H),h(T));H.transitionId=q.transitionId=z,H.fromCache=!!N,H.enableBack=!!l,H.renderStart=E,H.renderEnd=L,V(R.parent(),"nav-view-transition",H.transition),V(R.parent(),"nav-view-direction",H.direction),e.cancel(R.data(k));var U=o.transitions.views[H.transition]||o.transitions.views.none,F=U(R,M,H.direction,H.shouldAnimate&&u&&L);if(F.shouldAnimate&&(R.on($,w),R.data(k,e(b,_)),i.show(_)),E&&(O.emit("before",H,q),p(R,x),F.run(0)),L&&(C=n.defer(),P.push(C.promise)),E&&L)e(function(){ionic.requestAnimationFrame(v)});else{if(!L)return p(R,"entering"),p(M,"leaving"),{run:F.run,cancel:function(t){t?(R.on($,y),R.data(k,e(S,_)),i.show(_)):S(),F.shouldAnimate=t,F.run(0),F=null}};L&&v()}},emit:function(e,t,n){var i=R.scope(),o=M&&M.scope();"after"==e&&(i&&i.$emit("$ionicView.enter",t),o?o.$emit("$ionicView.leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView.leave",n)),i&&i.$emit("$ionicView."+e+"Enter",t),o?o.$emit("$ionicView."+e+"Leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView."+e+"Leave",n)},cleanup:function(e){M&&"back"==e.direction&&!o.views.forwardCache()&&v(M);var n,i,r,a=t.getViewElements(),c=a.length,s=c-1>o.views.maxCache(),l=Date.now();for(n=0;c>n;n++)i=a.eq(n),s&&i.data(S)<l?(l=i.data(S),r=a.eq(n)):i.data(b)&&p(i)!=B&&v(i);v(r),R.data(w)&&R.data(b,!0)},enteringEle:function(){return R},leavingEle:function(){return M}};return O},transitionEnd:function(e){s(e,function(e){e.transitionEnd()}),D.isTransitioning(!1),i.hide(),P=[]},nextTransition:function(e){g=e},nextDirection:function(e){m=e},isTransitioning:function(t){return arguments.length&&(ionic.transition.isActive=!!t,e.cancel(E),t&&(E=e(function(){D.isTransitioning(!1)},999))),ionic.transition.isActive},createViewEle:function(e){var n=t[0].createElement("div");return e&&e.$template&&(n.innerHTML=e.$template,1===n.children.length)?(n.children[0].classList.add("pane"),f(n.children[0])):(n.className="pane",f(n))},viewEleIsActive:function(e,t){p(e,t?B:I)},getTransitionData:d,navViewAttr:p,destroyViewEle:v};return D}]),angular.module("ngIOS9UIWebViewPatch",["ng"]).config(["$provide",function(e){"use strict";e.decorator("$browser",["$delegate","$window",function(e,t){function n(e){return/(iPhone|iPad|iPod).* OS 9_\d/.test(e)&&!/Version\/9\./.test(e)}function i(e){function t(){n=null}var n=null,i=e.url;return e.url=function(){return arguments.length?(n=arguments[0],i.apply(e,arguments)):n||i.apply(e,arguments)},window.addEventListener("popstate",t,!1),window.addEventListener("hashchange",t,!1),e}return n(t.navigator.userAgent)?i(e):e}])}]),a.config(["$provide",function(e){e.decorator("$compile",["$delegate",function(e){return e.$$addScopeInfo=function(e,t,n,i){var o=n?i?"$isolateScopeNoTemplate":"$isolateScope":"$scope";e.data(o,t)},e}])}]),a.config(["$provide",function(e){function t(e,t){return e.__hash=e.hash,e.hash=function(n){return l(n)&&n.length>0&&t(function(){var e=document.querySelector(".scroll-content");e&&(e.scrollTop=0)},0,!1),e.__hash(n)},e}e.decorator("$location",["$delegate","$timeout",t])}]),a.controller("$ionicHeaderBar",["$scope","$element","$attrs","$q","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r){function a(e){return C[e]||(C[e]=t[0].querySelector("."+e)),C[e]}var c="title",s="back-text",l="back-button",u="default-title",d="previous-title",f="hide",h=this,p="",v="",g=0,m=0,$="",w=!1,b=!0,y=!0,S=!1,k=0;h.beforeEnter=function(t){e.$broadcast("$ionicView.beforeEnter",t)},h.title=function(e){return arguments.length&&e!==p&&(a(c).innerHTML=e,p=e,k=0),p},h.enableBack=function(e,t){return arguments.length&&(w=e,t||h.updateBackButton()),w},h.showBack=function(e,t){return arguments.length&&(b=e,t||h.updateBackButton()),b},h.showNavBack=function(e){y=e,h.updateBackButton()},h.updateBackButton=function(){var e;(b&&y&&w)!==S&&(S=b&&y&&w,e=a(l),e&&e.classList[S?"remove":"add"](f)),w&&(e=e||a(l),e&&(h.backButtonIcon!==o.backButton.icon()&&(e=a(l+" .icon"),e&&(h.backButtonIcon=o.backButton.icon(),e.className="icon "+h.backButtonIcon)),h.backButtonText!==o.backButton.text()&&(e=a(l+" .back-text"),e&&(e.textContent=h.backButtonText=o.backButton.text()))))},h.titleTextWidth=function(){if(!k){var e=ionic.DomUtil.getTextBounds(a(c));k=Math.min(e&&e.width||30)}return k},h.titleWidth=function(){var e=h.titleTextWidth(),t=a(c).offsetWidth;return e>t&&(e=t+(g-m-5)),e},h.titleTextX=function(){return t[0].offsetWidth/2-h.titleWidth()/2},h.titleLeftRight=function(){return g-m},h.backButtonTextLeft=function(){for(var e=0,t=a(s);t;)e+=t.offsetLeft,t=t.parentElement;return e},h.resetBackButton=function(e){if(o.backButton.previousTitleText()){var t=a(d);if(t){t.classList.remove(f);var n=e&&r.getViewById(e.viewId),i=r.backTitle(n);i!==v&&(v=t.innerHTML=i)}var c=a(u);c&&c.classList.remove(f)}},h.align=function(e){var i=a(c);e=e||n.alignTitle||o.navBar.alignTitle();var r=h.calcWidths(e,!1);if(b&&v&&o.backButton.previousTitleText()){var s=h.calcWidths(e,!0),l=t[0].offsetWidth-s.titleLeft-s.titleRight;h.titleTextWidth()<=l&&(r=s)}return h.updatePositions(i,r.titleLeft,r.titleRight,r.buttonsLeft,r.buttonsRight,r.css,r.showPrevTitle)},h.calcWidths=function(e,n){var i,o,r,h,p,v,g,m,$,w=a(c),y=a(l),S=t[0].childNodes,k=0,C=0,T=0,B=0,I="",x=0;for(i=0;i<S.length;i++){if(p=S[i],g=0,1==p.nodeType){if(p===w){$=!0;continue}if(p.classList.contains(f))continue;if(b&&p===y){for(o=0;o<p.childNodes.length;o++)if(h=p.childNodes[o],1==h.nodeType)if(h.classList.contains(s))for(r=0;r<h.children.length;r++)if(v=h.children[r],n){if(v.classList.contains(u))continue;x+=v.offsetWidth}else{if(v.classList.contains(d))continue;x+=v.offsetWidth}else x+=h.offsetWidth;else 3==h.nodeType&&h.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(h),x+=m&&m.width||0);g=x||p.offsetWidth}else g=p.offsetWidth}else 3==p.nodeType&&p.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(p),g=m&&m.width||0);$?C+=g:k+=g}if("left"==e)I="title-left",k&&(T=k+15),C&&(B=C+15);else if("right"==e)I="title-right",k&&(T=k+15),C&&(B=C+15);else{var A=Math.max(k,C)+10;A>10&&(T=B=A)}return{backButtonWidth:x,buttonsLeft:k,buttonsRight:C,titleLeft:T,titleRight:B,showPrevTitle:n,css:I}},h.updatePositions=function(e,n,r,c,s,l,p){var v=i.defer();if(e&&(n!==g&&(e.style.left=n?n+"px":"",g=n),r!==m&&(e.style.right=r?r+"px":"",m=r),l!==$&&(l&&e.classList.add(l),$&&e.classList.remove($),$=l)),o.backButton.previousTitleText()){var w=a(d),b=a(u);w&&w.classList[p?"remove":"add"](f),b&&b.classList[p?"add":"remove"](f)}return ionic.requestAnimationFrame(function(){if(e&&e.offsetWidth+10<e.scrollWidth){var n=s+5,i=t[0].offsetWidth-g-h.titleTextWidth()-20;r=n>i?n:i,r!==m&&(e.style.right=r+"px",m=r)}v.resolve()}),v.promise},h.setCss=function(e,t){ionic.DomUtil.cachedStyles(a(e),t)};var C={};e.$on("$destroy",function(){for(var e in C)C[e]=null})}]),a.controller("$ionInfiniteScroll",["$scope","$attrs","$element","$timeout",function(e,t,n,i){function o(){ionic.requestAnimationFrame(function(){n[0].classList.add("active")}),s.isLoading=!0,e.$parent&&e.$parent.$apply(t.onInfinite||"")}function r(){ionic.requestAnimationFrame(function(){n[0].classList.remove("active")}),i(function(){s.jsScrolling&&s.scrollView.resize(),(s.jsScrolling&&s.scrollView.__container&&s.scrollView.__container.offsetHeight>0||!s.jsScrolling)&&s.checkBounds()},30,!1),s.isLoading=!1}function a(){if(!s.isLoading){var e={};if(s.jsScrolling){e=s.getJSMaxScroll();var t=s.scrollView.getValues();(-1!==e.left&&t.left>=e.left||-1!==e.top&&t.top>=e.top)&&o()}else e=s.getNativeMaxScroll(),(-1!==e.left&&s.scrollEl.scrollLeft>=e.left-s.scrollEl.clientWidth||-1!==e.top&&s.scrollEl.scrollTop>=e.top-s.scrollEl.clientHeight)&&o()}}function c(e){var n=(t.distance||"2.5%").trim(),i=-1!==n.indexOf("%");return i?e*(1-parseFloat(n)/100):e-parseFloat(n)}var s=this;s.isLoading=!1,e.icon=function(){return l(t.icon)?t.icon:"ion-load-d"},e.spinner=function(){return l(t.spinner)?t.spinner:""},e.$on("scroll.infiniteScrollComplete",function(){r()}),e.$on("$destroy",function(){s.scrollCtrl&&s.scrollCtrl.$element&&s.scrollCtrl.$element.off("scroll",s.checkBounds),s.scrollEl&&s.scrollEl.removeEventListener&&s.scrollEl.removeEventListener("scroll",s.checkBounds)}),s.checkBounds=ionic.Utils.throttle(a,300),s.getJSMaxScroll=function(){var e=s.scrollView.getScrollMax();return{left:s.scrollView.options.scrollingX?c(e.left):-1,top:s.scrollView.options.scrollingY?c(e.top):-1}},s.getNativeMaxScroll=function(){var e={left:s.scrollEl.scrollWidth,top:s.scrollEl.scrollHeight},t=window.getComputedStyle(s.scrollEl)||{};return{left:!e.left||"scroll"!==t.overflowX&&"auto"!==t.overflowX&&"scroll"!==s.scrollEl.style["overflow-x"]?-1:c(e.left),top:!e.top||"scroll"!==t.overflowY&&"auto"!==t.overflowY&&"scroll"!==s.scrollEl.style["overflow-y"]?-1:c(e.top)}},s.__finishInfiniteScroll=r}]),a.service("$ionicListDelegate",ionic.DelegateService(["showReorder","showDelete","canSwipeItems","closeOptionButtons"])).controller("$ionicList",["$scope","$attrs","$ionicListDelegate","$ionicHistory",function(e,t,n,i){var o=this,r=!0,a=!1,c=!1,s=n._registerInstance(o,t.delegateHandle,function(){return i.isActiveScope(e)});e.$on("$destroy",s),o.showReorder=function(e){return arguments.length&&(a=!!e),a},o.showDelete=function(e){return arguments.length&&(c=!!e),c},o.canSwipeItems=function(e){return arguments.length&&(r=!!e),r},o.closeOptionButtons=function(){o.listView&&o.listView.clearDragEffects()}}]),a.controller("$ionicNavBar",["$scope","$element","$attrs","$compile","$timeout","$ionicNavBarDelegate","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r,a,c){function u(e,t){var n=console.warn||console.log;n&&n.call(console,"navBarController."+e+" is deprecated, please use "+t+" instead")}function d(e){return x[e]?f(x[e]):void 0}function h(){for(var e=0;e<I.length;e++)if(I[e].isActive)return I[e]}function p(){for(var e=0;e<I.length;e++)if(!I[e].isActive)return I[e]}function v(e,t){e&&ionic.DomUtil.cachedAttr(e.containerEle(),"nav-bar",t)}function g(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}var m,$,w,b="hide",y="$ionNavBarController",S="primaryButtons",k="secondaryButtons",C="backButton",T="primaryButtons secondaryButtons leftButtons rightButtons title".split(" "),B=this,I=[],x={},A=!0;t.parent().data(y,B);var E=n.delegateHandle||"navBar"+ionic.Utils.nextUid(),V=r._registerInstance(B,E);B.init=function(){t.addClass("nav-bar-container"),ionic.DomUtil.cachedAttr(t,"nav-bar-transition",a.views.transition()),B.createHeaderBar(!1),B.createHeaderBar(!0),e.$emit("ionNavBar.init",E)},B.createHeaderBar=function(o){function r(e,t){e&&("title"===t?g.append(e):"rightButtons"==t||t==k&&"left"!=a.navBar.positionSecondaryButtons()||t==S&&"right"==a.navBar.positionPrimaryButtons()?(v||(v=f('<div class="buttons buttons-right">'),h.append(v)),t==k?v.append(e):v.prepend(e)):(p||(p=f('<div class="buttons buttons-left">'),m[C]?m[C].after(p):h.prepend(p)),t==k?p.append(e):p.prepend(e)))}var c=f('<div class="nav-bar-block">');ionic.DomUtil.cachedAttr(c,"nav-bar",o?"active":"cached");var u=n.alignTitle||a.navBar.alignTitle(),h=f("<ion-header-bar>").addClass(n["class"]).attr("align-title",u);l(n.noTapScroll)&&h.attr("no-tap-scroll",n.noTapScroll);var p,v,g=f('<div class="title title-'+u+'">'),m={},$={};m[C]=d(C),m[C]&&h.append(m[C]),h.append(g),s(T,function(e){m[e]=d(e),r(m[e],e)});for(var w=0;w<h[0].children.length;w++)h[0].children[w].classList.add("header-item");c.append(h),t.append(i(c)(e.$new()));var y=h.data("$ionHeaderBarController");y.backButtonIcon=a.backButton.icon(),y.backButtonText=a.backButton.text();var B={isActive:o,title:function(e){y.title(e)},setItem:function(e,t){B.removeItem(t),e?("title"===t&&B.title(""),r(e,t),m[t]&&m[t].addClass(b),$[t]=e):m[t]&&m[t].removeClass(b)},removeItem:function(e){$[e]&&($[e].scope().$destroy(),$[e].remove(),$[e]=null)},containerEle:function(){return c},headerBarEle:function(){return h},afterLeave:function(){s(T,function(e){B.removeItem(e)}),y.resetBackButton()},controller:function(){return y},destroy:function(){s(T,function(e){B.removeItem(e)}),c.scope().$destroy();for(var e in m)m[e]&&(m[e].removeData(),m[e]=null);p&&p.removeData(),v&&v.removeData(),g.removeData(),h.removeData(),c.remove(),c=h=g=p=v=null}};return I.push(B),B},B.navElement=function(e,t){return l(t)&&(x[e]=t),x[e]},B.update=function(e){var t=!e.hasHeaderBar&&e.showNavBar;e.transition=a.views.transition(),t||(e.direction="none"),B.enable(t);var n=B.isInitialized?p():h(),i=B.isInitialized?h():null,o=n.controller();o.enableBack(e.enableBack,!0),o.showBack(e.showBack,!0),o.updateBackButton(),B.title(e.title,n),B.showBar(t),e.navBarItems&&s(T,function(t){n.setItem(e.navBarItems[t],t)}),B.transition(n,i,e),B.isInitialized=!0,g("")},B.transition=function(n,i,r){function c(){for(var e=0;e<I.length;e++)I[e].isActive=!1;n.isActive=!0,v(n,"active"),v(i,"cached"),B.activeTransition=d=$=null}var s=n.controller(),l=a.transitions.navBar[r.navBarTransition]||a.transitions.navBar.none,u=r.transitionId;s.beforeEnter(r);var d=l(n,i,r.direction,r.shouldAnimate&&B.isInitialized);ionic.DomUtil.cachedAttr(t,"nav-bar-transition",r.navBarTransition),ionic.DomUtil.cachedAttr(t,"nav-bar-direction",r.direction),d.shouldAnimate&&r.renderEnd?v(n,"stage"):(v(n,"entering"),v(i,"leaving")),s.resetBackButton(r),d.run(0),B.activeTransition={run:function(e){d.shouldAnimate=!1,d.direction="back",d.run(e)},cancel:function(t,o,r){g(o),v(i,"active"),v(n,"cached"),d.shouldAnimate=t,d.run(0),B.activeTransition=d=null;var a;r.showBar!==B.showBar()&&B.showBar(r.showBar),r.showBackButton!==B.showBackButton()&&B.showBackButton(r.showBackButton),a&&e.$apply()},complete:function(e,t){g(t),d.shouldAnimate=e,d.run(1),$=c}},o(s.align,16),(m=function(){w===u&&(v(n,"entering"),v(i,"leaving"),d.run(1),$=function(){w!=u&&d.shouldAnimate||c(); +},m=null)})()},B.triggerTransitionStart=function(e){w=e,m&&m()},B.triggerTransitionEnd=function(){$&&$()},B.showBar=function(t){return arguments.length&&(B.visibleBar(t),e.$parent.$hasHeader=!!t),!!e.$parent.$hasHeader},B.visibleBar=function(e){e&&!A?(t.removeClass(b),B.align()):!e&&A&&t.addClass(b),A=e},B.enable=function(e){B.visibleBar(e);for(var t=0;t<r._instances.length;t++)r._instances[t]!==B&&r._instances[t].visibleBar(!1)},B.showBackButton=function(t){if(arguments.length){for(var n=0;n<I.length;n++)I[n].controller().showNavBack(!!t);e.$isBackButtonShown=!!t}return e.$isBackButtonShown},B.showActiveBackButton=function(e){var t=h();return t?arguments.length?t.controller().showBack(e):t.controller().showBack():void 0},B.title=function(t,n){return l(t)&&(t=t||"",n=n||h(),n&&n.title(t),e.$title=t,c.currentTitle(t)),e.$title},B.align=function(e,t){t=t||h(),t&&t.controller().align(e)},B.hasTabsTop=function(e){t[e?"addClass":"removeClass"]("nav-bar-tabs-top")},B.hasBarSubheader=function(e){t[e?"addClass":"removeClass"]("nav-bar-has-subheader")},B.changeTitle=function(e){u("changeTitle(val)","title(val)"),B.title(e)},B.setTitle=function(e){u("setTitle(val)","title(val)"),B.title(e)},B.getTitle=function(){return u("getTitle()","title()"),B.title()},B.back=function(){u("back()","$ionicHistory.goBack()"),c.goBack()},B.getPreviousTitle=function(){u("getPreviousTitle()","$ionicHistory.backTitle()"),c.goBack()},e.$on("$destroy",function(){e.$parent.$hasHeader=!1,t.parent().removeData(y);for(var n=0;n<I.length;n++)I[n].destroy();t.remove(),t=I=null,V()})}]),a.controller("$ionicNavView",["$scope","$element","$attrs","$compile","$controller","$ionicNavBarDelegate","$ionicNavViewDelegate","$ionicHistory","$ionicViewSwitcher","$ionicConfig","$ionicScrollDelegate",function(e,t,n,i,o,r,a,s,l,u,d){function f(e,n){for(var i,o,r=t.children(),a=0,c=r.length;c>a;a++)if(i=r.eq(a),A(i)==T){o=i.scope(),o&&o.$emit(e.name.replace("Tabs","View"),n);break}}function h(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}function p(e,t){var n=g();n&&n.hasTabsTop(t)}function v(e,t){var n=g();n&&n.hasBarSubheader(t)}function g(){if($)for(var e=0;e<r._instances.length;e++)if(r._instances[e].$$delegateHandle==$)return r._instances[e];return t.inheritedData("$ionNavBarController")}var m,$,w,b,y,S="$eleId",k="$destroyEle",C="$noCache",T="active",B="cached",I=this,x=!1,A=l.navViewAttr;I.scope=e,I.element=t,I.init=function(){var i=n.name||"",o=t.parent().inheritedData("$uiView"),r=o&&o.state?o.state.name:"";i.indexOf("@")<0&&(i=i+"@"+r);var c={name:i,state:null};t.data("$uiView",c);var s=a._registerInstance(I,n.delegateHandle);return e.$on("$destroy",function(){s(),I.isSwipeFreeze&&d.freezeAllScrolls(!1)}),e.$on("$ionicHistory.deselect",I.cacheCleanup),e.$on("$ionicTabs.top",p),e.$on("$ionicSubheader",v),e.$on("$ionicTabs.beforeLeave",f),e.$on("$ionicTabs.afterLeave",f),e.$on("$ionicTabs.leave",f),ionic.Platform.ready(function(){ionic.Platform.isWebView()&&u.views.swipeBackEnabled()&&I.initSwipeBack()}),c},I.register=function(t){var n=c({},s.currentView()),i=s.register(e,t);I.update(i);var o=s.getViewById(i.viewId)||{},r=b!==i.viewId;I.render(i,t,o,n,r,!0)},I.update=function(e){x=!0,m=e.direction;var n=t.parent().inheritedData("$ionNavViewController");n&&(n.isPrimary(!1),("enter"===m||"exit"===m)&&(n.direction(m),"enter"===m&&(m="none")))},I.render=function(e,t,n,i,o,r){var a=l.create(I,t,n,i,o,r);a.init(e,function(){a.transition(I.direction(),e.enableBack,!y),b=y=null})},I.beforeEnter=function(e){if(x){$=e.navBarDelegate;var t=g();t&&t.update(e),h("")}},I.activeEleId=function(e){return arguments.length&&(w=e),w},I.transitionEnd=function(){var e,n,i,o=t.children();for(e=0,n=o.length;n>e;e++)i=o.eq(e),i.data(S)===w?A(i,T):("leaving"===A(i)||A(i)===T||A(i)===B)&&(i.data(k)||i.data(C)?l.destroyViewEle(i):(A(i,B),ionic.Utils.disconnectScope(i.scope())));h(""),I.isSwipeFreeze&&d.freezeAllScrolls(!1)},I.cacheCleanup=function(){for(var e=t.children(),n=0,i=e.length;i>n;n++)e.eq(n).data(k)&&l.destroyViewEle(e.eq(n))},I.clearCache=function(e){var n,i,o,r,a,c,s=t.children();for(o=0,r=s.length;r>o;o++)if(n=s.eq(o),e)for(c=n.data(S),a=0;a<e.length;a++)c===e[a]&&l.destroyViewEle(n);else A(n)==B?l.destroyViewEle(n):A(n)==T&&(i=n.scope(),i&&i.$broadcast("$ionicView.clearCache"))},I.getViewElements=function(){return t.children()},I.appendViewElement=function(n,r){var a=i(n);t.append(n);var c=e.$new();if(r&&r.$$controller){r.$scope=c;var s=o(r.$$controller,r);r.$$controllerAs&&(c[r.$$controllerAs]=s),t.children().data("$ngControllerController",s)}return a(c),c},I.title=function(e){var t=g();t&&t.title(e)},I.enableBackButton=function(e){var t=g();t&&t.enableBackButton(e)},I.showBackButton=function(e){var t=g();return t?arguments.length?t.showActiveBackButton(e):t.showActiveBackButton():!0},I.showBar=function(e){var t=g();return t?arguments.length?t.showBar(e):t.showBar():!0},I.isPrimary=function(e){return arguments.length&&(x=e),x},I.direction=function(e){return arguments.length&&(m=e),m},I.initSwipeBack=function(){function n(e){if(x&&(S=r(e),!(S>C))){p=s.backView();var n=s.currentView();if(p&&p.historyId===n.historyId&&n.canSwipeBack!==!1){w||(w=window.innerWidth),I.isSwipeFreeze=d.freezeAllScrolls(!0);var a={direction:"back"};k=[],T={showBar:I.showBar(),showBackButton:I.showBackButton()};var u=l.create(I,a,p,n,!0,!1);u.loadViewElements(a),u.render(a),c=u.transition("back",s.enabledBack(p),!0),f=g(),m=ionic.onGesture("drag",i,t[0]),$=ionic.onGesture("release",o,t[0])}}}function i(e){if(x&&c){var t=r(e);if(k.push({t:Date.now(),x:t}),t>=w-15)o(e);else{var n=Math.min(Math.max(a(t),0),1);c.run(n),f&&f.activeTransition&&f.activeTransition.run(n)}}}function o(e){if(x&&c&&k&&k.length>1){for(var t=Date.now(),n=r(e),s=k[k.length-1],l=k.length-2;l>=0&&!(t-s.t>200);l--)s=k[l];var u=n>=k[k.length-2].x,v=a(n),g=Math.abs(s.x-n)/(t-s.t);if(b=p.viewId,y=.03>v||v>.97,u&&(v>.5||g>.1)){var S=g>.5||.05>g||n>w-45?"fast":"slow";h(y?"":S),p.go(),f&&f.activeTransition&&f.activeTransition.complete(!y,S)}else h(y?"":"fast"),b=null,c.cancel(!y),f&&f.activeTransition&&f.activeTransition.cancel(!y,"fast",T),y=null}ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),w=c=k=null,I.isSwipeFreeze=d.freezeAllScrolls(!1)}function r(e){return ionic.tap.pointerCoord(e.gesture.srcEvent).x}function a(e){return(e-S)/w}var c,f,p,v,m,$,w,S,k,C=u.views.swipeBackHitWidth(),T={};v=ionic.onGesture("dragstart",n,t[0]),e.$on("$destroy",function(){ionic.offGesture(v,"dragstart",n),ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),I.element=c=f=null})}}]),a.controller("$ionicRefresher",["$scope","$attrs","$element","$ionicBind","$timeout",function(e,t,n,i,o){function r(e){e.touches=e.touches||[{screenX:e.screenX,screenY:e.screenY}],P=Math.floor(e.touches[0].screenY)}function a(e){e.touches=e.touches||[{screenX:e.screenX,screenY:e.screenY}],P=e.touches[0].screenY}function c(){P=null,(D||T)&&(T?(T=!1,I=0,x>A?($(),p(A,V)):(p(0,V,m),B=!1)):(I=0,B=!1,h(!1)))}function s(e){if(e.touches=e.touches||[{screenX:e.screenX,screenY:e.screenY}],(P||"mousemove"!=e.type)&&D&&!(e.touches.length>1)){if(null===P&&(P=e.touches[0].screenY),_=e.touches[0].screenY-P,ionic.Platform.isAndroid()&&4.4===ionic.Platform.version()&&!ionic.Platform.isCrosswalk()&&0===S.scrollTop&&_>0&&(T=!0,e.preventDefault()),0>=_-I||0!==S.scrollTop)return B&&(B=!1,h(!1)),T&&f(S,_- -1*I),void(0!==x&&d(0));_>0&&0===S.scrollTop&&!B&&(I=_),e.preventDefault(),B||(B=!0,h(!0)),T=!0,d((_-I)/3),!E&&x>A?(E=!0,ionic.requestAnimationFrame(g)):E&&A>x&&(E=!1,ionic.requestAnimationFrame(m))}}function u(e){D=0===e.target.scrollTop||T}function d(e){k.style[ionic.CSS.TRANSFORM]="translateY("+e+"px)",x=e}function f(e,t){e.scrollTop=t;var n=document.createEvent("UIEvents");n.initUIEvent("scroll",!0,!0,window,1),e.dispatchEvent(n)}function h(e){e?ionic.requestAnimationFrame(function(){k.classList.add("overscroll"),w()}):ionic.requestAnimationFrame(function(){k.classList.remove("overscroll"),b(),m()})}function p(e,t,n){function i(e){return--e*e*e+1}function o(){var c=Date.now(),s=Math.min(1,(c-r)/t),l=i(s);d(Math.floor(l*(e-a)+a)),1>s?ionic.requestAnimationFrame(o):(5>e&&e>-5&&(B=!1,h(!1)),n&&n())}var r=Date.now(),a=x;return a===e?void n():void ionic.requestAnimationFrame(o)}function v(){ionic.off(L,a,k),ionic.off(R,s,k),ionic.off(M,c,k),ionic.off("mousedown",r,k),ionic.off("mousemove",s,k),ionic.off("mouseup",c,k),ionic.off("scroll",u,S),S=null,k=null}function g(){n[0].classList.add("active"),e.$onPulling()}function m(){o(function(){n.removeClass("active refreshing refreshing-tail"),E&&(E=!1)},150)}function $(){n[0].classList.add("refreshing");var t=e.$onRefresh();t&&t.then&&t["finally"](function(){e.$broadcast("scroll.refreshComplete")})}function w(){n[0].classList.remove("invisible")}function b(){n[0].classList.add("invisible")}function y(){n[0].classList.add("refreshing-tail")}var S,k,C=this,T=!1,B=!1,I=0,x=0,A=60,E=!1,V=500,P=null,_=null,D=!0;l(t.pullingIcon)||t.$set("pullingIcon","ion-android-arrow-down"),e.showSpinner=!l(t.refreshingIcon)&&"none"!=t.spinner,e.showIcon=l(t.refreshingIcon),i(e,t,{pullingIcon:"@",pullingText:"@",refreshingIcon:"@",refreshingText:"@",spinner:"@",disablePullingRotation:"@",$onRefresh:"&onRefresh",$onPulling:"&onPulling"}),e.$on("scroll.refreshComplete",function(){o(function(){ionic.requestAnimationFrame(y),p(0,V,m),o(function(){B&&(B=!1,h(!1))},V)},V)});var L,R,M;window.navigator.pointerEnabled?(L="pointerdown",R="pointermove",M="pointerup"):window.navigator.msPointerEnabled?(L="MSPointerDown",R="MSPointerMove",M="MSPointerUp"):(L="touchstart",R="touchmove",M="touchend"),C.init=function(){if(S=n.parent().parent()[0],k=n.parent()[0],!(S&&S.classList.contains("ionic-scroll")&&k&&k.classList.contains("scroll")))throw new Error("Refresher must be immediate child of ion-content or ion-scroll");ionic.on(L,a,k),ionic.on(R,s,k),ionic.on(M,c,k),ionic.on("mousedown",r,k),ionic.on("mousemove",s,k),ionic.on("mouseup",c,k),ionic.on("scroll",u,S),e.$on("$destroy",v)},C.getRefresherDomMethods=function(){return{activate:g,deactivate:m,start:$,show:w,hide:b,tail:y}},C.__handleTouchmove=s,C.__getScrollChild=function(){return k},C.__getScrollParent=function(){return S}}]),a.controller("$ionicScroll",["$scope","scrollViewOptions","$timeout","$window","$location","$document","$ionicScrollDelegate","$ionicHistory",function(e,t,n,i,o,r,a,c){var s=this;s.__timeout=n,s._scrollViewOptions=t,s.isNative=function(){return!!t.nativeScrolling};var u,d=s.element=t.el,h=s.$element=f(d);u=s.isNative()?s.scrollView=new ionic.views.ScrollNative(t):s.scrollView=new ionic.views.Scroll(t),(h.parent().length?h.parent():h).data("$$ionicScrollController",s);var p=a._registerInstance(s,t.delegateHandle,function(){return c.isActiveScope(e)});l(t.bouncing)||ionic.Platform.ready(function(){u&&u.options&&(u.options.bouncing=!0,ionic.Platform.isAndroid()&&(u.options.bouncing=!1,u.options.deceleration=.95))});var v=angular.bind(u,u.resize);angular.element(i).on("resize",v);var g=function(t){var n=(t.originalEvent||t).detail||{};e.$onScroll&&e.$onScroll({event:t,scrollTop:n.scrollTop||0,scrollLeft:n.scrollLeft||0})};h.on("scroll",g),e.$on("$destroy",function(){p(),u&&u.__cleanup&&u.__cleanup(),angular.element(i).off("resize",v),h.off("scroll",g),u=s.scrollView=t=s._scrollViewOptions=t.el=s._scrollViewOptions.el=h=s.$element=d=null}),n(function(){u&&u.run&&u.run()}),s.getScrollView=function(){return u},s.getScrollPosition=function(){return u.getValues()},s.resize=function(){return n(v,0,!1).then(function(){h&&h.triggerHandler("scroll-resize")})},s.scrollTop=function(e){s.resize().then(function(){u&&u.scrollTo(0,0,!!e)})},s.scrollBottom=function(e){s.resize().then(function(){if(u){var t=u.getScrollMax();u.scrollTo(t.left,t.top,!!e)}})},s.scrollTo=function(e,t,n){s.resize().then(function(){u&&u.scrollTo(e,t,!!n)})},s.zoomTo=function(e,t,n,i){s.resize().then(function(){u&&u.zoomTo(e,!!t,n,i)})},s.zoomBy=function(e,t,n,i){s.resize().then(function(){u&&u.zoomBy(e,!!t,n,i)})},s.scrollBy=function(e,t,n){s.resize().then(function(){u&&u.scrollBy(e,t,!!n)})},s.anchorScroll=function(e){s.resize().then(function(){if(u){var t=o.hash(),n=t&&r[0].getElementById(t);if(!t||!n)return void u.scrollTo(0,0,!!e);var i=n,a=0,c=0;do null!==i&&(a+=i.offsetLeft),null!==i&&(c+=i.offsetTop),i=i.offsetParent;while(i.attributes!=s.element.attributes&&i.offsetParent);u.scrollTo(a,c,!!e)}})},s.freezeScroll=u.freeze,s.freezeScrollShut=u.freezeShut,s.freezeAllScrolls=function(e){for(var t=0;t<a._instances.length;t++)a._instances[t].freezeScroll(e)},s._setRefresher=function(e,t,n){s.refresher=t;var i=s.refresher.clientHeight||60;u.activatePullToRefresh(i,n)}}]),a.controller("$ionicSideMenus",["$scope","$attrs","$ionicSideMenuDelegate","$ionicPlatform","$ionicBody","$ionicHistory","$ionicScrollDelegate","IONIC_BACK_PRIORITY","$rootScope",function(e,t,n,i,o,r,a,c,s){var l,d,f,p,v,g,m,$=this,w=!0;$.$scope=e,$.initialize=function(e){$.left=e.left,$.right=e.right,$.setContent(e.content),$.dragThresholdX=e.dragThresholdX||10,r.registerHistory($.$scope)},$.setContent=function(e){e&&($.content=e,$.content.onDrag=function(e){$._handleDrag(e)},$.content.endDrag=function(e){$._endDrag(e)})},$.isOpenLeft=function(){return $.getOpenAmount()>0},$.isOpenRight=function(){return $.getOpenAmount()<0},$.toggleLeft=function(e){if(!m&&$.left.isEnabled){var t=$.getOpenAmount();0===arguments.length&&(e=0>=t),$.content.enableAnimation(),e?($.openPercentage(100),s.$emit("$ionicSideMenuOpen","left")):($.openPercentage(0),s.$emit("$ionicSideMenuClose","left"))}},$.toggleRight=function(e){if(!m&&$.right.isEnabled){var t=$.getOpenAmount();0===arguments.length&&(e=t>=0),$.content.enableAnimation(),e?($.openPercentage(-100),s.$emit("$ionicSideMenuOpen","right")):($.openPercentage(0),s.$emit("$ionicSideMenuClose","right"))}},$.toggle=function(e){"right"==e?$.toggleRight():$.toggleLeft()},$.close=function(){$.openPercentage(0),s.$emit("$ionicSideMenuClose","left"),s.$emit("$ionicSideMenuClose","right")},$.getOpenAmount=function(){return $.content&&$.content.getTranslateX()||0},$.getOpenRatio=function(){var e=$.getOpenAmount();return e>=0?e/$.left.width:e/$.right.width},$.isOpen=function(){return 0!==$.getOpenAmount()},$.getOpenPercentage=function(){return 100*$.getOpenRatio()},$.openPercentage=function(e){var t=e/100;$.left&&e>=0?$.openAmount($.left.width*t):$.right&&0>e&&$.openAmount($.right.width*t),o.enableClass(0!==e,"menu-open"),$.content.setCanScroll(0==e)},$.openAmount=function(e){var t=$.left&&$.left.width||0,n=$.right&&$.right.width||0;return($.left&&$.left.isEnabled||!(e>0))&&($.right&&$.right.isEnabled||!(0>e))?d&&e>t?void $.content.setTranslateX(t):l&&-n>e?void $.content.setTranslateX(-n):($.content.setTranslateX(e),void(e>=0?(d=!0,l=!1,e>0&&($.right&&$.right.pushDown&&$.right.pushDown(),$.left&&$.left.bringUp&&$.left.bringUp())):(l=!0,d=!1,$.right&&$.right.bringUp&&$.right.bringUp(),$.left&&$.left.pushDown&&$.left.pushDown()))):void $.content.setTranslateX(0)},$.snapToRest=function(e){$.content.enableAnimation(),f=!1;var t=$.getOpenRatio();if(0===t)return void $.openPercentage(0);var n=.3,i=e.gesture.velocityX,o=e.gesture.direction;t>0&&.5>t&&"right"==o&&n>i?$.openPercentage(0):t>.5&&"left"==o&&n>i?$.openPercentage(100):0>t&&t>-.5&&"left"==o&&n>i?$.openPercentage(0):.5>t&&"right"==o&&n>i?$.openPercentage(-100):"right"==o&&t>=0&&(t>=.5||i>n)?$.openPercentage(100):"left"==o&&0>=t&&(-.5>=t||i>n)?$.openPercentage(-100):$.openPercentage(0)},$.enableMenuWithBackViews=function(e){return arguments.length&&(w=!!e),w},$.isAsideExposed=function(){return!!m},$.exposeAside=function(e){($.left&&$.left.isEnabled||$.right&&$.right.isEnabled)&&($.close(),m=e,$.left&&$.left.isEnabled&&$.right&&$.right.isEnabled?$.content.setMarginLeftAndRight(m?$.left.width:0,m?$.right.width:0):$.left&&$.left.isEnabled?$.content.setMarginLeft(m?$.left.width:0):$.right&&$.right.isEnabled&&$.content.setMarginRight(m?$.right.width:0),$.$scope.$emit("$ionicExposeAside",m))},$.activeAsideResizing=function(e){o.enableClass(e,"aside-resizing")},$._endDrag=function(e){m||(f&&$.snapToRest(e),p=null,v=null,g=null)},$._handleDrag=function(t){!m&&e.dragContent&&(p?v=t.gesture.touches[0].pageX:(p=t.gesture.touches[0].pageX,v=p),!f&&Math.abs(v-p)>$.dragThresholdX&&(p=v,f=!0,$.content.disableAnimation(),g=$.getOpenAmount()),f&&$.openAmount(g+(v-p)))},$.canDragContent=function(t){return arguments.length&&(e.dragContent=!!t),e.dragContent},$.edgeThreshold=25,$.edgeThresholdEnabled=!1,$.edgeDragThreshold=function(e){return arguments.length&&(u(e)&&e>0?($.edgeThreshold=e,$.edgeThresholdEnabled=!0):$.edgeThresholdEnabled=!!e),$.edgeThresholdEnabled},$.isDraggableTarget=function(t){var n=$.edgeThresholdEnabled&&!$.isOpen(),i=t.gesture.startEvent&&t.gesture.startEvent.center&&t.gesture.startEvent.center.pageX,o=!n||i<=$.edgeThreshold||i>=$.content.element.offsetWidth-$.edgeThreshold,a=r.backView(),c=w?!0:!a;if(!c){var s=r.currentView()||{};return o&&a.historyId!==s.historyId}return(e.dragContent||$.isOpen())&&o&&!t.gesture.srcEvent.defaultPrevented&&c&&!t.target.tagName.match(/input|textarea|select|object|embed/i)&&!t.target.isContentEditable&&!(t.target.dataset?t.target.dataset.preventScroll:"true"==t.target.getAttribute("data-prevent-scroll"))},e.sideMenuContentTranslateX=0;var b=h,y=angular.bind($,$.close);e.$watch(function(){return 0!==$.getOpenAmount()},function(e){b(),e&&(b=i.registerBackButtonAction(y,c.sideMenu))});var S=n._registerInstance($,t.delegateHandle,function(){return r.isActiveScope(e)});e.$on("$destroy",function(){S(),b(),$.$scope=null,$.content&&($.content.setCanScroll(!0),$.content.element=null,$.content=null)}),$.initialize({left:{width:275},right:{width:275}})}]),function(e){function t(e,i,o,r){var a,c,s,l=document.createElement(f[e]||e);for(a in i)if(angular.isArray(i[a]))for(c=0;c<i[a].length;c++)if(i[a][c].fn)for(s=0;s<i[a][c].t;s++)t(a,i[a][c].fn(s,r),l,r);else t(a,i[a][c],l,r);else n(l,a,i[a]);o.appendChild(l)}function n(e,t,n){e.setAttribute(f[t]||t,n)}function i(e,t){var n=e.split(";"),i=n.slice(t),o=n.slice(0,n.length-i.length);return n=i.concat(o).reverse(),n.join(";")+";"+n[0]}function o(e,t){return e/=t/2,1>e?.5*e*e*e:(e-=2,.5*(e*e*e+2))}var r="translate(32,32)",c="stroke-opacity",s="round",l="indefinite",u="750ms",d="none",f={a:"animate",an:"attributeName",at:"animateTransform",c:"circle",da:"stroke-dasharray",os:"stroke-dashoffset",f:"fill",lc:"stroke-linecap",rc:"repeatCount",sw:"stroke-width",t:"transform",v:"values"},h={v:"0,32,32;360,32,32",an:"transform",type:"rotate",rc:l,dur:u},p={sw:4,lc:s,line:[{fn:function(e,t){return{y1:"ios"==t?17:12,y2:"ios"==t?29:20,t:r+" rotate("+(30*e+(6>e?180:-180))+")",a:[{fn:function(){return{an:c,dur:u,v:i("0;.1;.15;.25;.35;.45;.55;.65;.7;.85;1",e),rc:l}},t:1}]}},t:12}]},v={android:{c:[{sw:6,da:128,os:82,r:26,cx:32,cy:32,f:d}]},ios:p,"ios-small":p,bubbles:{sw:0,c:[{fn:function(e){return{cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,a:[{fn:function(){return{an:"r",dur:u,v:i("1;2;3;4;5;6;7;8",e),rc:l}},t:1}]}},t:8}]},circles:{c:[{fn:function(e){return{r:5,cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".3;.3;.3;.4;.7;.85;.9;1",e),rc:l}},t:1}]}},t:8}]},crescent:{c:[{sw:4,da:128,os:82,r:26,cx:32,cy:32,f:d,at:[h]}]},dots:{c:[{fn:function(e){return{cx:16+16*e,cy:32,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".5;.6;.8;1;.8;.6;.5",e),rc:l}},t:1},{fn:function(){return{an:"r",dur:u,v:i("4;5;6;5;4;3;3",e),rc:l}},t:1}]}},t:3}]},lines:{sw:7,lc:s,line:[{fn:function(e){return{x1:10+14*e,x2:10+14*e,a:[{fn:function(){return{an:"y1",dur:u,v:i("16;18;28;18;16",e),rc:l}},t:1},{fn:function(){return{an:"y2",dur:u,v:i("48;44;36;46;48",e),rc:l}},t:1},{fn:function(){return{an:c,dur:u,v:i("1;.8;.5;.4;1",e),rc:l}},t:1}]}},t:4}]},ripple:{f:d,"fill-rule":"evenodd",sw:3,circle:[{fn:function(e){return{cx:32,cy:32,a:[{fn:function(){return{an:"r",begin:-1*e+"s",dur:"2s",v:"0;24",keyTimes:"0;1",keySplines:"0.1,0.2,0.3,1",calcMode:"spline",rc:l}},t:1},{fn:function(){return{an:c,begin:-1*e+"s",dur:"2s",v:".2;1;.2;0",rc:l}},t:1}]}},t:2}]},spiral:{defs:[{linearGradient:[{id:"sGD",gradientUnits:"userSpaceOnUse",x1:55,y1:46,x2:2,y2:46,stop:[{offset:.1,"class":"stop1"},{offset:1,"class":"stop2"}]}]}],g:[{sw:4,lc:s,f:d,path:[{stroke:"url(#sGD)",d:"M4,32 c0,15,12,28,28,28c8,0,16-4,21-9"},{d:"M60,32 C60,16,47.464,4,32,4S4,16,4,32"}],at:[h]}]}},g={android:function(t){function i(){if(!r.stop){var t=o(Date.now()-a,650),d=1,f=0,h=188-58*t,p=182-182*t;c%2&&(d=-1,f=-64,h=128- -58*t,p=182*t);var v=[0,-101,-90,-11,-180,79,-270,-191][c];n(u,"da",Math.max(Math.min(h,188),128)),n(u,"os",Math.max(Math.min(p,182),0)),n(u,"t","scale("+d+",1) translate("+f+",0) rotate("+v+",32,32)"),s+=4.1,s>359&&(s=0),n(l,"t","rotate("+s+",32,32)"),t>=1&&(c++,c>7&&(c=0),a=Date.now()),e.requestAnimationFrame(i)}}var r=this;this.stop=!1;var a,c=0,s=0,l=t.querySelector("g"),u=t.querySelector("circle");return function(){return a=Date.now(),i(),r}}};a.controller("$ionicSpinner",["$element","$attrs","$ionicConfig",function(e,n,i){var o,r;this.init=function(){o=n.icon||i.spinner.icon();var r=document.createElement("div");return t("svg",{viewBox:"0 0 64 64",g:[v[o]]},r,o),e.html(r.innerHTML),this.start(),o},this.start=function(){g[o]&&(r=g[o](e[0])())},this.stop=function(){g[o]&&(r.stop=!0)}}])}(ionic),a.controller("$ionicTab",["$scope","$ionicHistory","$attrs","$location","$state",function(e,t,n,i,o){this.$scope=e,this.hrefMatchesState=function(){return n.href&&0===i.path().indexOf(n.href.replace(/^#/,"").replace(/\/$/,""))},this.srefMatchesState=function(){return n.uiSref&&o.includes(n.uiSref.split("(")[0])},this.navNameMatchesState=function(){return this.navViewName&&t.isCurrentStateNavView(this.navViewName)},this.tabMatchesState=function(){return this.hrefMatchesState()||this.srefMatchesState()||this.navNameMatchesState()}}]),a.controller("$ionicTabs",["$scope","$element","$ionicHistory",function(e,t,n){var i,o=this,r=null,a=null,c=!0;o.tabs=[],o.selectedIndex=function(){return o.tabs.indexOf(r)},o.selectedTab=function(){return r},o.previousSelectedTab=function(){return a},o.add=function(e){n.registerHistory(e),o.tabs.push(e)},o.remove=function(e){var t=o.tabs.indexOf(e);if(-1!==t){if(e.$tabSelected)if(o.deselect(e),1===o.tabs.length);else{var n=t===o.tabs.length-1?t-1:t+1;o.select(o.tabs[n])}o.tabs.splice(t,1)}},o.deselect=function(e){e.$tabSelected&&(a=r,r=i=null,e.$tabSelected=!1,(e.onDeselect||h)(),e.$broadcast&&e.$broadcast("$ionicHistory.deselect"))},o.select=function(t,a){var c;if(u(t)){if(c=t,c>=o.tabs.length)return;t=o.tabs[c]}else c=o.tabs.indexOf(t);1===arguments.length&&(a=!(!t.navViewName&&!t.uiSref)),r&&r.$historyId==t.$historyId?a&&n.goToHistoryRoot(t.$historyId):i!==c&&(s(o.tabs,function(e){o.deselect(e)}),r=t,i=c,o.$scope&&o.$scope.$parent&&(o.$scope.$parent.$activeHistoryId=t.$historyId),t.$tabSelected=!0,(t.onSelect||h)(),a&&e.$emit("$ionicHistory.change",{type:"tab",tabIndex:c,historyId:t.$historyId,navViewName:t.navViewName,hasNavView:!!t.navViewName,title:t.title,url:t.href,uiSref:t.uiSref}))},o.hasActiveScope=function(){for(var e=0;e<o.tabs.length;e++)if(n.isActiveScope(o.tabs[e]))return!0;return!1},o.showBar=function(e){return arguments.length&&(e?t.removeClass("tabs-item-hide"):t.addClass("tabs-item-hide"),c=!!e),c}}]),a.controller("$ionicView",["$scope","$element","$attrs","$compile","$rootScope",function(e,t,n,i,o){function r(){var t=l(n.viewTitle)&&"viewTitle"||l(n.title)&&"title";t&&(a(n[t]),$.push(n.$observe(t,a))),l(n.hideBackButton)&&$.push(e.$watch(n.hideBackButton,function(e){f.showBackButton(!e)})),l(n.hideNavBar)&&$.push(e.$watch(n.hideNavBar,function(e){f.showBar(!e)}))}function a(e){l(e)&&e!==v&&(v=e,f.title(v))}function s(){for(var e=0;e<$.length;e++)$[e]();$=[]}function u(t){return t?i(t)(e.$new()):void 0}function d(t){return!!e.$eval(n[t])}var f,h,p,v,g=this,m={},$=[],w=e.$on("ionNavBar.init",function(e,t){e.stopPropagation(),h=t});g.init=function(){w();var n=t.inheritedData("$ionModalController");f=t.inheritedData("$ionNavViewController"),f&&!n&&(e.$on("$ionicView.beforeEnter",g.beforeEnter),e.$on("$ionicView.afterEnter",r),e.$on("$ionicView.beforeLeave",s))},g.beforeEnter=function(t,i){if(i&&!i.viewNotified){i.viewNotified=!0,o.$$phase||e.$digest(),v=l(n.viewTitle)?n.viewTitle:n.title;var r={};for(var a in m)r[a]=u(m[a]);f.beforeEnter(c(i,{title:v,showBack:!d("hideBackButton"),navBarItems:r,navBarDelegate:h||null,showNavBar:!d("hideNavBar"),hasHeaderBar:!!p})),s()}},g.navElement=function(e,t){m[e]=t}}]),a.directive("ionActionSheet",["$document",function(e){return{restrict:"E",scope:!0,replace:!0,link:function(t,n){var i=function(e){27==e.which&&(t.cancel(),t.$apply())},o=function(e){e.target==n[0]&&(t.cancel(),t.$apply())};t.$on("$destroy",function(){n.remove(),e.unbind("keyup",i)}),e.bind("keyup",i),n.bind("click",o)},template:'<div class="action-sheet-backdrop"><div class="action-sheet-wrapper"><div class="action-sheet" ng-class="{\'action-sheet-has-icons\': $actionSheetHasIcon}"><div class="action-sheet-group action-sheet-options"><div class="action-sheet-title" ng-if="titleText" ng-bind-html="titleText"></div><button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-class="b.className" ng-repeat="b in buttons" ng-bind-html="b.text"></button><button class="button destructive action-sheet-destructive" ng-if="destructiveText" ng-click="destructiveButtonClicked()" ng-bind-html="destructiveText"></button></div><div class="action-sheet-group action-sheet-cancel" ng-if="cancelText"><button class="button" ng-click="cancel()" ng-bind-html="cancelText"></button></div></div></div></div>'}}]),a.directive("ionCheckbox",["$ionicConfig",function(e){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-checkbox"><div class="checkbox checkbox-input-hidden disable-pointer-events"><input type="checkbox"><i class="checkbox-icon"></i></div><div class="item-content disable-pointer-events" ng-transclude></div></label>',compile:function(t,n){var i=t.find("input");s({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){l(e)&&i.attr(t,e)});var o=t[0].querySelector(".checkbox");o.classList.add("checkbox-"+e.form.checkbox())}}}]),a.directive("collectionRepeat",e).factory("$ionicCollectionManager",t);var w="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",b=/height:.*?px;\s*width:.*?px/,y=3;e.$inject=["$ionicCollectionManager","$parse","$window","$$rAF","$rootScope","$timeout"],t.$inject=["$rootScope","$window","$$rAF"],a.directive("ionContent",["$timeout","$controller","$ionicBind","$ionicConfig",function(e,t,n,i){return{restrict:"E",require:"^?ionNavView",scope:!0,priority:800,compile:function(e,o){function r(e,i,r){function u(){e.$onScrollComplete({scrollTop:c.scrollView.__scrollTop,scrollLeft:c.scrollView.__scrollLeft})}var d=e.$parent;if(e.$watch(function(){return(d.$hasHeader?" has-header":"")+(d.$hasSubheader?" has-subheader":"")+(d.$hasFooter?" has-footer":"")+(d.$hasSubfooter?" has-subfooter":"")+(d.$hasTabs?" has-tabs":"")+(d.$hasTabsTop?" has-tabs-top":"")},function(e,t){i.removeClass(t),i.addClass(e)}),e.$hasHeader=e.$hasSubheader=e.$hasFooter=e.$hasSubfooter=e.$hasTabs=e.$hasTabsTop=!1,n(e,r,{$onScroll:"&onScroll",$onScrollComplete:"&onScrollComplete",hasBouncing:"@",padding:"@",direction:"@",scrollbarX:"@",scrollbarY:"@",startX:"@",startY:"@",scrollEventInterval:"@"}),e.direction=e.direction||"y",l(r.padding)&&e.$watch(r.padding,function(e){(a||i).toggleClass("padding",!!e)}),"false"===r.scroll);else{var f={};s?(i.addClass("overflow-scroll"),f={el:i[0],delegateHandle:o.delegateHandle,startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,nativeScrolling:!0}):f={el:i[0],delegateHandle:o.delegateHandle,locking:"true"===(o.locking||"true"),bouncing:e.$eval(e.hasBouncing),startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,scrollEventInterval:parseInt(e.scrollEventInterval,10)||10,scrollingComplete:u},c=t("$ionicScroll",{$scope:e,scrollViewOptions:f}),e.scrollCtrl=c,e.$on("$destroy",function(){f&&(f.scrollingComplete=h,delete f.el),a=null,i=null,o.$$element=null})}}var a,c;e.addClass("scroll-content ionic-scroll"),"false"!=o.scroll?(a=f('<div class="scroll"></div>'),a.append(e.contents()),e.append(a)):e.addClass("scroll-content-false");var s="false"!==o.overflowScroll&&("true"===o.overflowScroll||!i.scrolling.jsScrolling());return s&&(s=!e[0].querySelector("[collection-repeat]")),{pre:r}}}}]),a.directive("exposeAsideWhen",["$window",function(e){return{restrict:"A",require:"^ionSideMenus",link:function(t,n,i,o){function r(){var t="large"==i.exposeAsideWhen?"(min-width:768px)":i.exposeAsideWhen;o.exposeAside(e.matchMedia(t).matches),o.activeAsideResizing(!1)}function a(){o.activeAsideResizing(!0),l()}var c="large"==i.exposeAsideWhen?"(min-width:768px)":i.exposeAsideWhen,s=e.matchMedia(c);s.addListener(function(){a()});var l=ionic.debounce(function(){t.$apply(r)},300,!1);t.$evalAsync(r)}}}]);var S="onHold onTap onDoubleTap onTouch onRelease onDragStart onDrag onDragEnd onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeDown onSwipeLeft".split(" ");S.forEach(function(e){a.directive(e,n(e))}),a.directive("ionHeaderBar",i(!0)).directive("ionFooterBar",i(!1)),a.directive("ionInfiniteScroll",["$timeout",function(e){return{restrict:"E",require:["?^$ionicScroll","ionInfiniteScroll"],template:function(e,t){return t.icon?'<i class="icon {{icon()}} icon-refreshing {{scrollingType}}"></i>':'<ion-spinner icon="{{spinner()}}"></ion-spinner>'},scope:!0,controller:"$ionInfiniteScroll",link:function(t,n,i,o){var r=o[1],a=r.scrollCtrl=o[0],c=r.jsScrolling=!a.isNative();if(c)r.scrollView=a.scrollView,t.scrollingType="js-scrolling",a.$element.on("scroll",r.checkBounds);else{var s=ionic.DomUtil.getParentOrSelfWithClass(n[0].parentNode,"overflow-scroll");if(r.scrollEl=s,!s)throw"Infinite scroll must be used inside a scrollable div";r.scrollEl.addEventListener("scroll",r.checkBounds)}var u=l(i.immediateCheck)?t.$eval(i.immediateCheck):!0;u&&e(function(){r.checkBounds()})}}}]);var k=-1;a.directive("ionInput",[function(){return{restrict:"E",controller:["$scope","$element",function(e,t){this.$scope=e,this.$element=t,this.setInputAriaLabeledBy=function(e){var n=t[0].querySelectorAll("input,textarea");n.length&&n[0].setAttribute("aria-labelledby",e)},this.focus=function(){var e=t[0].querySelectorAll("input,textarea");e.length&&e[0].focus()}}]}}]),a.directive("ionLabel",[function(){return{restrict:"E",require:"?^ionInput",compile:function(){return function(e,t,n,i){var o=t[0];t.addClass("input-label"),t.attr("aria-label",t.text());var r=o.id||"_label-"+ ++k;o.id||t.attr("id",r),i&&(i.setInputAriaLabeledBy(r),t.on("click",function(){i.focus()}))}}}}]),a.directive("inputLabel",[function(){return{restrict:"C",require:"?^ionInput",compile:function(){return function(e,t,n,i){var o=t[0];t.attr("aria-label",t.text());var r=o.id||"_label-"+ ++k;o.id||t.attr("id",r),i&&i.setInputAriaLabeledBy(r)}}}}]),a.directive("ionItem",["$$rAF",function(e){return{restrict:"E",controller:["$scope","$element",function(e,t){this.$scope=e,this.$element=t}],scope:!0,compile:function(t,n){var i=l(n.href)||l(n.ngHref)||l(n.uiSref),o=i||/ion-(delete|option|reorder)-button/i.test(t.html());if(o){var r=f(i?"<a></a>":"<div></div>");r.addClass("item-content"),(l(n.href)||l(n.ngHref))&&(r.attr("ng-href","{{$href()}}"),l(n.target)&&r.attr("target","{{$target()}}")),r.append(t.contents()),t.addClass("item item-complex").append(r); +}else t.addClass("item");return function(t,n,i){t.$href=function(){return i.href||i.ngHref},t.$target=function(){return i.target};var o=n[0].querySelector(".item-content");o&&t.$on("$collectionRepeatLeave",function(){o&&o.$$ionicOptionsOpen&&(o.style[ionic.CSS.TRANSFORM]="",o.style[ionic.CSS.TRANSITION]="none",e(function(){o.style[ionic.CSS.TRANSITION]=""}),o.$$ionicOptionsOpen=!1)})}}}}]);var C='<div class="item-left-edit item-delete enable-pointer-events"></div>';a.directive("ionDeleteButton",function(){function e(e){e.stopPropagation()}return{restrict:"E",require:["^^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),function(t,n,i,o){function r(){c=c||n.controller("ionList"),c&&c.showDelete()&&s.addClass("visible active")}var a=o[0],c=o[1],s=f(C);s.append(n),a.$element.append(s).addClass("item-left-editable"),n.on("click",e),r(),t.$on("$ionic.reconnectScope",r)}}}}),a.directive("itemFloatingLabel",function(){return{restrict:"C",link:function(e,t){var n=t[0],i=n.querySelector("input, textarea"),o=n.querySelector(".input-label");if(i&&o){var r=function(){i.value?o.classList.add("has-input"):o.classList.remove("has-input")};i.addEventListener("input",r);var a=f(i).controller("ngModel");a&&(a.$render=function(){i.value=a.$viewValue||"",r()}),e.$on("$destroy",function(){i.removeEventListener("input",r)})}}}});var T='<div class="item-options invisible"></div>';a.directive("ionOptionButton",[function(){function e(e){e.stopPropagation()}return{restrict:"E",require:"^ionItem",priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button",!0),function(t,n,i,o){o.optionsContainer||(o.optionsContainer=f(T),o.$element.append(o.optionsContainer)),o.optionsContainer.append(n),o.$element.addClass("item-right-editable"),n.on("click",e)}}}}]);var B='<div data-prevent-scroll="true" class="item-right-edit item-reorder enable-pointer-events"></div>';a.directive("ionReorderButton",["$parse",function(e){return{restrict:"E",require:["^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),t[0].setAttribute("data-prevent-scroll",!0),function(t,n,i,o){var r=o[0],a=o[1],c=e(i.onReorder);t.$onReorder=function(e,n){c(t,{$fromIndex:e,$toIndex:n})},i.ngClick||i.onClick||i.onclick||(n[0].onclick=function(e){return e.stopPropagation(),!1});var s=f(B);s.append(n),r.$element.append(s).addClass("item-right-editable"),a&&a.showReorder()&&s.addClass("visible active")}}}}]),a.directive("keyboardAttach",function(){return function(e,t){function n(e){if(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen){var n=e.keyboardHeight||e.detail&&e.detail.keyboardHeight;t.css("bottom",n+"px"),r=t.controller("$ionicScroll"),r&&(r.scrollView.__container.style.bottom=n+o(t[0])+"px")}}function i(){(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen)&&(t.css("bottom",""),r&&(r.scrollView.__container.style.bottom=""))}ionic.on("native.keyboardshow",n,window),ionic.on("native.keyboardhide",i,window),ionic.on("native.showkeyboard",n,window),ionic.on("native.hidekeyboard",i,window);var r;e.$on("$destroy",function(){ionic.off("native.keyboardshow",n,window),ionic.off("native.keyboardhide",i,window),ionic.off("native.showkeyboard",n,window),ionic.off("native.hidekeyboard",i,window)})}}),a.directive("ionList",["$timeout",function(e){return{restrict:"E",require:["ionList","^?$ionicScroll"],controller:"$ionicList",compile:function(t,n){var i=f('<div class="list">').append(t.contents()).addClass(n.type);return t.append(i),function(t,i,o,r){function a(){function o(e,t){t()&&e.addClass("visible")||e.removeClass("active"),ionic.requestAnimationFrame(function(){t()&&e.addClass("active")||e.removeClass("visible")})}var r=c.listView=new ionic.views.ListView({el:i[0],listEl:i.children()[0],scrollEl:s&&s.element,scrollView:s&&s.scrollView,onReorder:function(t,n,i){var o=f(t).scope();o&&o.$onReorder&&e(function(){o.$onReorder(n,i)})},canSwipe:function(){return c.canSwipeItems()}});t.$on("$destroy",function(){r&&(r.deregister&&r.deregister(),r=null)}),l(n.canSwipe)&&t.$watch("!!("+n.canSwipe+")",function(e){c.canSwipeItems(e)}),l(n.showDelete)&&t.$watch("!!("+n.showDelete+")",function(e){c.showDelete(e)}),l(n.showReorder)&&t.$watch("!!("+n.showReorder+")",function(e){c.showReorder(e)}),t.$watch(function(){return c.showDelete()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-left-editing",e),i.toggleClass("disable-pointer-events",e);var n=f(i[0].getElementsByClassName("item-delete"));o(n,c.showDelete)}}),t.$watch(function(){return c.showReorder()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-right-editing",e),i.toggleClass("disable-pointer-events",e);var n=f(i[0].getElementsByClassName("item-reorder"));o(n,c.showReorder)}})}var c=r[0],s=r[1];e(a)}}}}]),a.directive("menuClose",["$ionicHistory","$timeout",function(e,t){return{restrict:"AC",link:function(n,i){i.bind("click",function(){var n=i.inheritedData("$ionSideMenusController");n&&(e.nextViewOptions({historyRoot:!0,disableAnimate:!0,expire:300}),t(function(){e.nextViewOptions({historyRoot:!1,disableAnimate:!1})},300),n.close())})}}}]),a.directive("menuToggle",function(){return{restrict:"AC",link:function(e,t,n){e.$on("$ionicView.beforeEnter",function(e,n){if(n.enableBack){var i=t.inheritedData("$ionSideMenusController");i.enableMenuWithBackViews()||t.addClass("hide")}else t.removeClass("hide")}),t.bind("click",function(){var e=t.inheritedData("$ionSideMenusController");e&&e.toggle(n.menuToggle)})}}}),a.directive("ionModal",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="modal-backdrop"><div class="modal-backdrop-bg"></div><div class="modal-wrapper" ng-transclude></div></div>'}}]),a.directive("ionModalView",function(){return{restrict:"E",compile:function(e){e.addClass("modal")}}}),a.directive("ionNavBackButton",["$ionicConfig","$document",function(e,t){return{restrict:"E",require:"^ionNavBar",compile:function(n,i){function o(e){return/ion-|icon/.test(e.className)}var r=t[0].createElement("button");for(var a in i.$attr)r.setAttribute(i.$attr[a],i[a]);i.ngClick||r.setAttribute("ng-click","$ionicGoBack()"),r.className="button back-button hide buttons "+(n.attr("class")||""),r.innerHTML=n.html()||"";for(var c,s,l,u,d=o(n[0]),f=0;f<n[0].childNodes.length;f++)c=n[0].childNodes[f],1===c.nodeType?o(c)?d=!0:c.classList.contains("default-title")?l=!0:c.classList.contains("previous-title")&&(u=!0):s||3!==c.nodeType||(s=!!c.nodeValue.trim());var h=e.backButton.icon();if(!d&&h&&"none"!==h&&(r.innerHTML='<i class="icon '+h+'"></i> '+r.innerHTML,r.className+=" button-clear"),!s){var p=t[0].createElement("span");p.className="back-text",!l&&e.backButton.text()&&(p.innerHTML+='<span class="default-title">'+e.backButton.text()+"</span>"),!u&&e.backButton.previousTitleText()&&(p.innerHTML+='<span class="previous-title"></span>'),r.appendChild(p)}return n.attr("class","hide"),n.empty(),{pre:function(e,t,n,i){i.navElement("backButton",r.outerHTML),r=null}}}}}]),a.directive("ionNavBar",function(){return{restrict:"E",controller:"$ionicNavBar",scope:!0,link:function(e,t,n,i){i.init()}}}),a.directive("ionNavButtons",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="left";/^primary|secondary|right$/i.test(n.side||"")&&(i=n.side.toLowerCase());var o=e[0].createElement("span");o.className=i+"-buttons",o.innerHTML=t.html();var r=i+"Buttons";return t.attr("class","hide"),t.empty(),{pre:function(e,t,n,i){var a=t.parent().data("$ionViewController");a?a.navElement(r,o.outerHTML):i.navElement(r,o.outerHTML),o=null}}}}}]),a.directive("navDirection",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextDirection(i.navDirection)})}}}]),a.directive("ionNavTitle",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="title",o=e[0].createElement("span");for(var r in n.$attr)o.setAttribute(n.$attr[r],n[r]);return o.classList.add("nav-bar-title"),o.innerHTML=t.html(),t.attr("class","hide"),t.empty(),{pre:function(e,t,n,r){var a=t.parent().data("$ionViewController");a?a.navElement(i,o.outerHTML):r.navElement(i,o.outerHTML),o=null}}}}}]),a.directive("navTransition",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextTransition(i.navTransition)})}}}]),a.directive("ionNavView",["$state","$ionicConfig",function(e,t){return{restrict:"E",terminal:!0,priority:2e3,transclude:!0,controller:"$ionicNavView",compile:function(n,i,o){return n.addClass("view-container"),ionic.DomUtil.cachedAttr(n,"nav-view-transition",t.views.transition()),function(t,n,i,r){function a(t){var n=e.$current&&e.$current.locals[s.name];n&&(t||n!==c)&&(c=n,s.state=n.$$state,r.register(n))}var c;o(t,function(e){n.append(e)});var s=r.init();t.$on("$stateChangeSuccess",function(){a(!1)}),t.$on("$viewContentLoading",function(){a(!1)}),a(!0)}}}}]),a.config(["$provide",function(e){e.decorator("ngClickDirective",["$delegate",function(e){return e.shift(),e}])}]).factory("$ionicNgClick",["$parse",function(e){return function(t,n,i){var o=angular.isFunction(i)?i:e(i);n.on("click",function(e){t.$apply(function(){o(t,{$event:e})})}),n.onclick=h}}]).directive("ngClick",["$ionicNgClick",function(e){return function(t,n,i){e(t,n,i.ngClick)}}]).directive("ionStopEvent",function(){return{restrict:"A",link:function(e,t,n){t.bind(n.ionStopEvent,r)}}}),a.directive("ionPane",function(){return{restrict:"E",link:function(e,t){t.addClass("pane")}}}),a.directive("ionPopover",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="popover-backdrop"><div class="popover-wrapper" ng-transclude></div></div>'}}]),a.directive("ionPopoverView",function(){return{restrict:"E",compile:function(e){e.append(f('<div class="popover-arrow">')),e.addClass("popover")}}}),a.directive("ionRadio",function(){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-radio"><input type="radio" name="radio-group"><div class="radio-content"><div class="item-content disable-pointer-events" ng-transclude></div><i class="radio-icon disable-pointer-events icon ion-checkmark"></i></div></label>',compile:function(e,t){if(t.icon){var n=e.find("i");n.removeClass("ion-checkmark").addClass(t.icon)}var i=e.find("input");return s({name:t.name,value:t.value,disabled:t.disabled,"ng-value":t.ngValue,"ng-model":t.ngModel,"ng-disabled":t.ngDisabled,"ng-change":t.ngChange,"ng-required":t.ngRequired,required:t.required},function(e,t){l(e)&&i.attr(t,e)}),function(e,t,n){e.getValue=function(){return e.ngValue||n.value}}}}}),a.directive("ionRefresher",[function(){return{restrict:"E",replace:!0,require:["?^$ionicScroll","ionRefresher"],controller:"$ionicRefresher",template:'<div class="scroll-refresher invisible" collection-repeat-ignore><div class="ionic-refresher-content" ng-class="{\'ionic-refresher-with-text\': pullingText || refreshingText}"><div class="icon-pulling" ng-class="{\'pulling-rotation-disabled\':disablePullingRotation}"><i class="icon {{pullingIcon}}"></i></div><div class="text-pulling" ng-bind-html="pullingText"></div><div class="icon-refreshing"><ion-spinner ng-if="showSpinner" icon="{{spinner}}"></ion-spinner><i ng-if="showIcon" class="icon {{refreshingIcon}}"></i></div><div class="text-refreshing" ng-bind-html="refreshingText"></div></div></div>',link:function(e,t,n,i){var o=i[0],r=i[1];!o||o.isNative()?r.init():(t[0].classList.add("js-scrolling"),o._setRefresher(e,t[0],r.getRefresherDomMethods()),e.$on("scroll.refreshComplete",function(){e.$evalAsync(function(){o.scrollView.finishPullToRefresh()})}))}}}]),a.directive("ionScroll",["$timeout","$controller","$ionicBind","$ionicConfig",function(e,t,n,i){return{restrict:"E",scope:!0,controller:function(){},compile:function(e,o){function r(e,i,o){n(e,o,{direction:"@",paging:"@",$onScroll:"&onScroll",scroll:"@",scrollbarX:"@",scrollbarY:"@",zooming:"@",minZoom:"@",maxZoom:"@"}),e.direction=e.direction||"y",l(o.padding)&&e.$watch(o.padding,function(e){a.toggleClass("padding",!!e)}),e.$eval(e.paging)===!0&&a.addClass("scroll-paging"),e.direction||(e.direction="y");var r=e.$eval(e.paging)===!0;c&&i.addClass("overflow-scroll"),i.addClass("scroll-"+e.direction);var s={el:i[0],delegateHandle:o.delegateHandle,locking:"true"===(o.locking||"true"),bouncing:e.$eval(o.hasBouncing),paging:r,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,zooming:e.$eval(e.zooming)===!0,maxZoom:e.$eval(e.maxZoom)||3,minZoom:e.$eval(e.minZoom)||.5,preventDefault:!0,nativeScrolling:c};r&&(s.speedMultiplier=.8,s.bouncing=!1),t("$ionicScroll",{$scope:e,scrollViewOptions:s})}e.addClass("scroll-view ionic-scroll");var a=f('<div class="scroll"></div>');a.append(e.contents()),e.append(a);var c="false"!==o.overflowScroll&&("true"===o.overflowScroll||!i.scrolling.jsScrolling());return{pre:r}}}}]),a.directive("ionSideMenu",function(){return{restrict:"E",require:"^ionSideMenus",scope:!0,compile:function(e,t){return angular.isUndefined(t.isEnabled)&&t.$set("isEnabled","true"),angular.isUndefined(t.width)&&t.$set("width","275"),e.addClass("menu menu-"+t.side),function(e,n,i,o){e.side=i.side||"left";var r=o[e.side]=new ionic.views.SideMenu({width:t.width,el:n[0],isEnabled:!0});e.$watch(i.width,function(e){var t=+e;t&&t==e&&r.setWidth(+e)}),e.$watch(i.isEnabled,function(e){r.setIsEnabled(!!e)})}}}}),a.directive("ionSideMenuContent",["$timeout","$ionicGesture","$window",function(e,t,n){return{restrict:"EA",require:"^ionSideMenus",scope:!0,compile:function(i,o){function r(r,a,c,s){function u(e){0!==s.getOpenAmount()?(s.close(),e.gesture.srcEvent.preventDefault(),v=null,g=null):v||(v=ionic.tap.pointerCoord(e.gesture.srcEvent))}function d(e){s.isDraggableTarget(e)&&"x"==p(e)&&(s._handleDrag(e),e.gesture.srcEvent.preventDefault())}function f(e){"x"==p(e)&&e.gesture.srcEvent.preventDefault()}function h(e){s._endDrag(e),v=null,g=null}function p(e){if(g)return g;if(e&&e.gesture){if(v){var t=ionic.tap.pointerCoord(e.gesture.srcEvent),n=Math.abs(t.x-v.x),i=Math.abs(t.y-v.y),o=i>n?"y":"x";return Math.max(n,i)>30&&(g=o),o}v=ionic.tap.pointerCoord(e.gesture.srcEvent)}return"y"}var v=null,g=null;l(o.dragContent)?r.$watch(o.dragContent,function(e){s.canDragContent(e)}):s.canDragContent(!0),l(o.edgeDragThreshold)&&r.$watch(o.edgeDragThreshold,function(e){s.edgeDragThreshold(e)});var m={element:i[0],onDrag:function(){},endDrag:function(){},setCanScroll:function(e){var t=a[0].querySelector(".scroll");if(t){var n=angular.element(t.parentElement);if(n){var i=n.scope();i.scrollCtrl&&i.scrollCtrl.freezeScrollShut(!e)}}},getTranslateX:function(){return r.sideMenuContentTranslateX||0},setTranslateX:ionic.animationFrameThrottle(function(t){var n=m.offsetX+t;a[0].style[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e(function(){r.sideMenuContentTranslateX=t})}),setMarginLeft:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style[ionic.CSS.TRANSFORM]="translate3d("+e+"px,0,0)",a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)",a[0].style.width="",m.offsetX=0)}),setMarginRight:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style.width="",m.offsetX=0),a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)"}),setMarginLeftAndRight:ionic.animationFrameThrottle(function(e,t){e=e&&parseInt(e,10)||0,t=t&&parseInt(t,10)||0;var i=e+t;i>0?(a[0].style[ionic.CSS.TRANSFORM]="translate3d("+e+"px,0,0)",a[0].style.width=n.innerWidth-i+"px",m.offsetX=e):(a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)",a[0].style.width="",m.offsetX=0)}),enableAnimation:function(){r.animationEnabled=!0,a[0].classList.add("menu-animated")},disableAnimation:function(){r.animationEnabled=!1,a[0].classList.remove("menu-animated")},offsetX:0};s.setContent(m);var $={stop_browser_behavior:!1};$.prevent_default_directions=["left","right"];var w=t.on("tap",u,a,$),b=t.on("dragright",d,a,$),y=t.on("dragleft",d,a,$),S=t.on("dragup",f,a,$),k=t.on("dragdown",f,a,$),C=t.on("release",h,a,$);r.$on("$destroy",function(){m&&(m.element=null,m=null),t.off(y,"dragleft",d),t.off(b,"dragright",d),t.off(S,"dragup",f),t.off(k,"dragdown",f),t.off(C,"release",h),t.off(w,"tap",u)})}return i.addClass("menu-content pane"),{pre:r}}}}]),a.directive("ionSideMenus",["$ionicBody",function(e){return{restrict:"ECA",controller:"$ionicSideMenus",compile:function(t,n){function i(t,n,i,o){o.enableMenuWithBackViews(t.$eval(i.enableMenuWithBackViews)),t.$on("$ionicExposeAside",function(n,i){t.$exposeAside||(t.$exposeAside={}),t.$exposeAside.active=i,e.enableClass(i,"aside-open")}),t.$on("$ionicView.beforeEnter",function(e,n){n.historyId&&(t.$activeHistoryId=n.historyId)}),t.$on("$destroy",function(){e.removeClass("menu-open","aside-open")})}return n.$set("class",(n["class"]||"")+" view"),{pre:i}}}}]),a.directive("ionSlideBox",["$animate","$timeout","$compile","$ionicSlideBoxDelegate","$ionicHistory","$ionicScrollDelegate",function(e,t,n,i,o,r){return{restrict:"E",replace:!0,transclude:!0,scope:{autoPlay:"=",doesContinue:"@",slideInterval:"@",showPager:"@",pagerClick:"&",disableScroll:"@",onSlideChanged:"&",activeSlide:"=?",bounce:"@"},controller:["$scope","$element","$attrs",function(e,n,a){function c(e){e&&!s.isScrollFreeze?r.freezeAllScrolls(e):!e&&s.isScrollFreeze&&r.freezeAllScrolls(!1),s.isScrollFreeze=e}var s=this,u=e.$eval(e.doesContinue)===!0,d=e.$eval(e.bounce)!==!1,f=l(a.autoPlay)?!!e.autoPlay:!1,h=f?e.$eval(e.slideInterval)||4e3:0,p=new ionic.views.Slider({el:n[0],auto:h,continuous:u,startSlide:e.activeSlide,bouncing:d,slidesChanged:function(){e.currentSlide=p.currentIndex(),t(function(){})},callback:function(n){e.currentSlide=n,e.onSlideChanged({index:e.currentSlide,$index:e.currentSlide}),e.$parent.$broadcast("slideBox.slideChanged",n),e.activeSlide=n,t(function(){})},onDrag:function(){c(!0)},onDragEnd:function(){c(!1)}});p.enableSlide(e.$eval(a.disableScroll)!==!0),e.$watch("activeSlide",function(e){l(e)&&p.slide(e)}),e.$on("slideBox.nextSlide",function(){p.next()}),e.$on("slideBox.prevSlide",function(){p.prev()}),e.$on("slideBox.setSlide",function(e,t){p.slide(t)}),this.__slider=p;var v=i._registerInstance(p,a.delegateHandle,function(){return o.isActiveScope(e)});e.$on("$destroy",function(){v(),p.kill()}),this.slidesCount=function(){return p.slidesCount()},this.onPagerClick=function(t){e.pagerClick({index:t})},t(function(){p.load()})}],template:'<div class="slider"><div class="slider-slides" ng-transclude></div></div>',link:function(t,i,o){function r(){if(!a){var e=t.$new();a=f("<ion-pager></ion-pager>"),i.append(a),a=n(a)(e)}return a}e.enabled(!1,i),l(o.showPager)||(t.showPager=!0,r().toggleClass("hide",!1)),o.$observe("showPager",function(e){void 0!==e&&(e=t.$eval(e),r().toggleClass("hide",!e))});var a}}}]).directive("ionSlide",function(){return{restrict:"E",require:"?^ionSlideBox",compile:function(e){e.addClass("slider-slide")}}}).directive("ionPager",function(){return{restrict:"E",replace:!0,require:"^ionSlideBox",template:'<div class="slider-pager"><span class="slider-pager-page" ng-repeat="slide in numSlides() track by $index" ng-class="{active: $index == currentSlide}" ng-click="pagerClick($index)"><i class="icon ion-record"></i></span></div>',link:function(e,t,n,i){var o=function(e){for(var n=t[0].children,i=n.length,o=0;i>o;o++)o==e?n[o].classList.add("active"):n[o].classList.remove("active")};e.pagerClick=function(e){i.onPagerClick(e)},e.numSlides=function(){return new Array(i.slidesCount())},e.$watch("currentSlide",function(e){o(e)})}}}),a.directive("ionSlides",["$animate","$timeout","$compile",function(e,t,n){return{restrict:"E",transclude:!0,scope:{options:"=",slider:"="},template:'<div class="swiper-container"><div class="swiper-wrapper" ng-transclude></div><div ng-hide="!showPager" class="swiper-pagination"></div></div>',controller:["$scope","$element",function(e,i){var o=this;this.update=function(){t(function(){o.__slider&&(o.__slider.update(),o._options.loop&&o.__slider.createLoop(),o.__slider.slides.length>10&&(e.showPager=!1))})},this.rapidUpdate=ionic.debounce(function(){o.update()},50),this.getSlider=function(){return o.__slider};var r=e.options||{},a=angular.extend({pagination:".swiper-pagination",paginationClickable:!0,lazyLoading:!0,preloadImages:!1},r);this._options=a,t(function(){var t=new ionic.views.Swiper(i.children()[0],a,e,n);o.__slider=t,e.slider=o.__slider,e.$on("$destroy",function(){t.destroy()})})}],link:function(e){e.showPager=!0}}}]).directive("ionSlidePage",[function(){return{restrict:"E",require:"?^ionSlides",transclude:!0,replace:!0,template:'<div class="swiper-slide" ng-transclude></div>',link:function(e,t,n,i){i.rapidUpdate()}}}]),a.directive("ionSpinner",function(){return{restrict:"E",controller:"$ionicSpinner",link:function(e,t,n,i){var o=i.init();t.addClass("spinner spinner-"+o),t.on("$destroy",function(){i.stop()})}}}),a.directive("ionTab",["$compile","$ionicConfig","$ionicBind","$ionicViewSwitcher",function(e,t,n,i){function o(e,t){return l(t)?" "+e+'="'+t+'"':""}return{restrict:"E",require:["^ionTabs","ionTab"],controller:"$ionicTab",scope:!0,compile:function(r,a){for(var c="<ion-tab-nav"+o("ng-click",a.ngClick)+o("title",a.title)+o("icon",a.icon)+o("icon-on",a.iconOn)+o("icon-off",a.iconOff)+o("badge",a.badge)+o("badge-style",a.badgeStyle)+o("hidden",a.hidden)+o("disabled",a.disabled)+o("class",a["class"])+"></ion-tab-nav>",s=document.createElement("div"),l=0;l<r[0].children.length;l++)s.appendChild(r[0].children[l].cloneNode(!0));var u=s.childElementCount;r.empty();var d,h;return u&&("ION-NAV-VIEW"===s.children[0].tagName&&(d=s.children[0].getAttribute("name"),s.children[0].classList.add("view-container"),h=!0),1===u&&(s=s.children[0]),h||s.classList.add("pane"),s.classList.add("tab-content")),function(o,r,a,l){function h(){w.tabMatchesState()&&$.select(o,!1)}function p(n){n&&u?(b||(g=o.$new(),m=f(s),i.viewEleIsActive(m,!0),$.$element.append(m),e(m)(g),b=!0),i.viewEleIsActive(m,!0)):b&&m&&(t.views.maxCache()>0?i.viewEleIsActive(m,!1):v())}function v(){g&&g.$destroy(),b&&m&&m.remove(),s.innerHTML="",b=g=m=null}var g,m,$=l[0],w=l[1],b=!1;o.$tabSelected=!1,n(o,a,{onSelect:"&",onDeselect:"&",title:"@",uiSref:"@",href:"@"}),$.add(o),o.$on("$destroy",function(){o.$tabsDestroy||$.remove(o),y.isolateScope().$destroy(),y.remove(),y=s=m=null}),r[0].removeAttribute("title"),d&&(w.navViewName=o.navViewName=d),o.$on("$stateChangeSuccess",h),h();var y=f(c);y.data("$ionTabsController",$),y.data("$ionTabController",w),$.$tabsElement.append(e(y)(o)),o.$watch("$tabSelected",p),o.$on("$ionicView.afterEnter",function(){i.viewEleIsActive(m,o.$tabSelected)}),o.$on("$ionicView.clearCache",function(){o.$tabSelected||v()})}}}}]),a.directive("ionTabNav",[function(){return{restrict:"E",replace:!0,require:["^ionTabs","^ionTab"],template:"<a ng-class=\"{'tab-item-active': isTabActive(), 'has-badge':badge, 'tab-hidden':isHidden()}\" "+' ng-disabled="disabled()" class="tab-item"><span class="badge {{badgeStyle}}" ng-if="badge">{{badge}}</span><i class="icon {{getIconOn()}}" ng-if="getIconOn() && isTabActive()"></i><i class="icon {{getIconOff()}}" ng-if="getIconOff() && !isTabActive()"></i><span class="tab-title" ng-bind-html="title"></span></a>',scope:{title:"@",icon:"@",iconOn:"@",iconOff:"@",badge:"=",hidden:"@",disabled:"&",badgeStyle:"@","class":"@"},link:function(e,t,n,i){var o=i[0],r=i[1];t[0].removeAttribute("title"),e.selectTab=function(e){e.preventDefault(),o.select(r.$scope,!0)},n.ngClick||t.on("click",function(t){e.$apply(function(){e.selectTab(t)})}),e.isHidden=function(){return"true"===n.hidden||n.hidden===!0?!0:!1},e.getIconOn=function(){return e.iconOn||e.icon},e.getIconOff=function(){return e.iconOff||e.icon},e.isTabActive=function(){return o.selectedTab()===r.$scope}}}}]),a.directive("ionTabs",["$ionicTabsDelegate","$ionicConfig",function(e,t){return{restrict:"E",scope:!0,controller:"$ionicTabs",compile:function(n){function i(t,n,i,o){function a(e,t){e.stopPropagation();var n=o.previousSelectedTab();n&&n.$broadcast(e.name.replace("NavView","Tabs"),t)}var c=e._registerInstance(o,i.delegateHandle,o.hasActiveScope);o.$scope=t,o.$element=n,o.$tabsElement=f(n[0].querySelector(".tabs")),t.$watch(function(){return n[0].className},function(e){var n=-1!==e.indexOf("tabs-top"),i=-1!==e.indexOf("tabs-item-hide");t.$hasTabs=!n&&!i,t.$hasTabsTop=n&&!i,t.$emit("$ionicTabs.top",t.$hasTabsTop)}),t.$on("$ionicNavView.beforeLeave",a),t.$on("$ionicNavView.afterLeave",a),t.$on("$ionicNavView.leave",a),t.$on("$destroy",function(){t.$tabsDestroy=!0,c(),o.$tabsElement=o.$element=o.$scope=r=null,delete t.$hasTabs,delete t.$hasTabsTop})}function o(e,t,n,i){i.selectedTab()||i.select(0)}var r=f('<div class="tab-nav tabs">');return r.append(n.contents()),n.append(r).addClass("tabs-"+t.tabs.position()+" tabs-"+t.tabs.style()),{pre:i,post:o}}}}]),a.directive("ionTitle",[function(){return{restrict:"E",compile:function(e){e.addClass("title")}}}]),a.directive("ionToggle",["$timeout","$ionicConfig",function(e,t){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<div class="item item-toggle"><div ng-transclude></div><label class="toggle"><input type="checkbox"><div class="track"><div class="handle"></div></div></label></div>',compile:function(e,n){var i=e.find("input");return s({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){l(e)&&i.attr(t,e)}),n.toggleClass&&e[0].getElementsByTagName("label")[0].classList.add(n.toggleClass),e.addClass("toggle-"+t.form.toggle()),function(e,t){var n=t[0].getElementsByTagName("label")[0],i=n.children[0],o=n.children[1],r=o.children[0],a=f(i).controller("ngModel");e.toggle=new ionic.views.Toggle({el:n,track:o,checkbox:i,handle:r,onChange:function(){a&&(a.$setViewValue(i.checked),e.$apply())}}),e.$on("$destroy",function(){e.toggle.destroy()})}}}}]),a.directive("ionView",function(){return{restrict:"EA",priority:1e3,controller:"$ionicView",compile:function(e){return e.addClass("pane"),e[0].removeAttribute("title"),function(e,t,n,i){i.init()}}}})}(); \ No newline at end of file diff --git a/www/lib/ionic/js/ionic.bundle.js b/www/lib/ionic/js/ionic.bundle.js index 67661ccdf0772330a0cd2ba97e620b04794b2570..1e84bd523e2f9db01283bc2ee47723c0752cb5d1 100644 --- a/www/lib/ionic/js/ionic.bundle.js +++ b/www/lib/ionic/js/ionic.bundle.js @@ -6,10 +6,10 @@ */ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -25,7 +25,7 @@ // build processes may have already created an ionic obj window.ionic = window.ionic || {}; window.ionic.views = {}; -window.ionic.version = '1.0.1'; +window.ionic.version = '1.2.4'; (function (ionic) { @@ -244,6 +244,17 @@ window.ionic.version = '1.0.1'; }; }, + getOffsetTop: function(el) { + var curtop = 0; + if (el.offsetParent) { + do { + curtop += el.offsetTop; + el = el.offsetParent; + } while (el) + return curtop; + } + }, + /** * @ngdoc method * @name ionic.DomUtil#ready @@ -1628,7 +1639,7 @@ window.ionic.version = '1.0.1'; index: 10, defaults: { hold_timeout: 500, - hold_threshold: 1 + hold_threshold: 9 }, timer: null, handler: function holdGesture(ev, inst) { @@ -1785,8 +1796,8 @@ window.ionic.version = '1.0.1'; } else if (!this.preventedFirstMove && ev.srcEvent.type == 'touchmove') { // Prevent gestures that are not intended for this event handler from firing subsequent times - if (inst.options.prevent_default_directions.length === 0 - || inst.options.prevent_default_directions.indexOf(ev.direction) != -1) { + if (inst.options.prevent_default_directions.length > 0 + && inst.options.prevent_default_directions.indexOf(ev.direction) != -1) { ev.srcEvent.preventDefault(); } this.preventedFirstMove = true; @@ -2036,6 +2047,8 @@ window.ionic.version = '1.0.1'; var IOS = 'ios'; var ANDROID = 'android'; var WINDOWS_PHONE = 'windowsphone'; + var EDGE = 'edge'; + var CROSSWALK = 'crosswalk'; var requestAnimationFrame = ionic.requestAnimationFrame; /** @@ -2255,6 +2268,18 @@ window.ionic.version = '1.0.1'; isWindowsPhone: function() { return self.is(WINDOWS_PHONE); }, + /** + * @ngdoc method + * @name ionic.Platform#isEdge + * @returns {boolean} Whether we are running on MS Edge/Windows 10 (inc. Phone) + */ + isEdge: function() { + return self.is(EDGE); + }, + + isCrosswalk: function() { + return self.is(CROSSWALK); + }, /** * @ngdoc method @@ -2275,12 +2300,14 @@ window.ionic.version = '1.0.1'; platformName = n.toLowerCase(); } else if (getParameterByName('ionicplatform')) { platformName = getParameterByName('ionicplatform'); + } else if (self.ua.indexOf('Edge') > -1) { + platformName = EDGE; + } else if (self.ua.indexOf('Windows Phone') > -1) { + platformName = WINDOWS_PHONE; } else if (self.ua.indexOf('Android') > 0) { platformName = ANDROID; } else if (/iPhone|iPad|iPod/.test(self.ua)) { platformName = IOS; - } else if (self.ua.indexOf('Windows Phone') > -1) { - platformName = WINDOWS_PHONE; } else { platformName = self.navigator.platform && navigator.platform.toLowerCase().split(' ')[0] || ''; } @@ -2327,7 +2354,12 @@ window.ionic.version = '1.0.1'; } }, - // Check if the platform is the one detected by cordova + /** + * @ngdoc method + * @name ionic.Platform#is + * @param {string} Platform name. + * @returns {boolean} Whether the platform name provided is detected. + */ is: function(type) { type = type.toLowerCase(); // check if it has an array of platforms @@ -2414,7 +2446,19 @@ window.ionic.version = '1.0.1'; var platformName = null, // just the name, like iOS or Android platformVersion = null, // a float of the major and minor, like 7.1 readyCallbacks = [], - windowLoadListenderAttached; + windowLoadListenderAttached, + platformReadyTimer = 2000; // How long to wait for platform ready before emitting a warning + + verifyPlatformReady(); + + // Warn the user if deviceready did not fire in a reasonable amount of time, and how to fix it. + function verifyPlatformReady() { + setTimeout(function() { + if(!self.isReady && self.isWebView()) { + void 0; + } + }, platformReadyTimer); + } // setup listeners to know when the device is ready to go function onWindowLoad() { @@ -2454,13 +2498,17 @@ window.ionic.version = '1.0.1'; }); } -})(this, document, ionic); +})(window, document, ionic); (function(document, ionic) { 'use strict'; // Ionic CSS polyfills ionic.CSS = {}; + ionic.CSS.TRANSITION = []; + ionic.CSS.TRANSFORM = []; + + ionic.EVENTS = {}; (function() { @@ -2484,6 +2532,9 @@ window.ionic.version = '1.0.1'; } } + // Fallback in case the keys don't exist at all + ionic.CSS.TRANSITION = ionic.CSS.TRANSITION || 'transition'; + // The only prefix we care about is webkit for transitions. var isWebkit = ionic.CSS.TRANSITION.indexOf('webkit') > -1; @@ -2494,6 +2545,30 @@ window.ionic.version = '1.0.1'; ionic.CSS.TRANSITIONEND = (isWebkit ? 'webkitTransitionEnd ' : '') + 'transitionend'; })(); + (function() { + var touchStartEvent = 'touchstart'; + var touchMoveEvent = 'touchmove'; + var touchEndEvent = 'touchend'; + var touchCancelEvent = 'touchcancel'; + + if (window.navigator.pointerEnabled) { + touchStartEvent = 'pointerdown'; + touchMoveEvent = 'pointermove'; + touchEndEvent = 'pointerup'; + touchCancelEvent = 'pointercancel'; + } else if (window.navigator.msPointerEnabled) { + touchStartEvent = 'MSPointerDown'; + touchMoveEvent = 'MSPointerMove'; + touchEndEvent = 'MSPointerUp'; + touchCancelEvent = 'MSPointerCancel'; + } + + ionic.EVENTS.touchstart = touchStartEvent; + ionic.EVENTS.touchmove = touchMoveEvent; + ionic.EVENTS.touchend = touchEndEvent; + ionic.EVENTS.touchcancel = touchCancelEvent; + })(); + // classList polyfill for them older Androids // https://gist.github.com/devongovett/1381839 if (!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') { @@ -2662,7 +2737,7 @@ ionic.tap = { if (window.navigator.pointerEnabled) { tapEventListener('pointerdown'); tapEventListener('pointerup'); - tapEventListener('pointcancel'); + tapEventListener('pointercancel'); tapTouchMoveListener = 'pointermove'; } else if (window.navigator.msPointerEnabled) { @@ -2712,6 +2787,11 @@ ionic.tap = { (ele.tagName == 'INPUT' && (/^(date|time|datetime-local|month|week)$/i).test(ele.type)); }, + isVideo: function(ele) { + return !!ele && + (ele.tagName == 'VIDEO'); + }, + isKeyboardElement: function(ele) { if ( !ionic.Platform.isIOS() || ionic.Platform.isIPad() ) { return ionic.tap.isTextInput(ele) && !ionic.tap.isDateInput(ele); @@ -2778,6 +2858,9 @@ ionic.tap = { }, requiresNativeClick: function(ele) { + if (ionic.Platform.isWindowsPhone() && (ele.tagName == 'A' || ele.tagName == 'BUTTON' || ele.hasAttribute('ng-click') || (ele.tagName == 'INPUT' && (ele.type == 'button' || ele.type == 'submit')))) { + return true; //Windows Phone edge case, prevent ng-click (and similar) events from firing twice on this platform + } if (!ele || ele.disabled || (/^(file|range)$/i).test(ele.type) || (/^(object|video)$/i).test(ele.tagName) || ionic.tap.isLabelContainingFileInput(ele)) { return true; } @@ -2796,7 +2879,7 @@ ionic.tap = { if (ele && ele.nodeType === 1) { var element = ele; while (element) { - if ((element.dataset ? element.dataset.tapDisabled : element.getAttribute('data-tap-disabled')) == 'true') { + if ((element.dataset ? element.dataset.tapDisabled : element.getAttribute && element.getAttribute('data-tap-disabled')) == 'true') { return true; } element = element.parentElement; @@ -2892,14 +2975,17 @@ function tapMouseDown(e) { if (e.isIonicTap || tapIgnoreEvent(e)) return null; if (tapEnabledTouchEvents) { - void 0; + //console.log('mousedown', 'stop event'); e.stopPropagation(); - if ((!ionic.tap.isTextInput(e.target) || tapLastTouchTarget !== e.target) && !(/^(select|option)$/i).test(e.target.tagName)) { + if (!ionic.Platform.isEdge() && (!ionic.tap.isTextInput(e.target) || tapLastTouchTarget !== e.target) && + !isSelectOrOption(e.target.tagName) && !ionic.tap.isVideo(e.target)) { // If you preventDefault on a text input then you cannot move its text caret/cursor. // Allow through only the text input default. However, without preventDefault on an // input the 300ms delay can change focus on inputs after the keyboard shows up. // The focusin event handles the chance of focus changing after the keyboard shows. + // Windows Phone - if you preventDefault on a video element then you cannot operate + // its native controls. e.preventDefault(); } @@ -2921,7 +3007,7 @@ function tapMouseUp(e) { return false; } - if (tapIgnoreEvent(e) || (/^(select|option)$/i).test(e.target.tagName)) return false; + if (tapIgnoreEvent(e) || isSelectOrOption(e.target.tagName)) return false; if (!tapHasPointerMoved(e)) { tapClick(e); @@ -2963,6 +3049,7 @@ function tapTouchStart(e) { var textInput = tapTargetElement(tapContainingElement(e.target)); if (textInput !== tapActiveEle) { // don't preventDefault on an already focused input or else iOS's text caret isn't usable + //console.log('Would prevent default here'); e.preventDefault(); } } @@ -2976,7 +3063,7 @@ function tapTouchEnd(e) { if (!tapHasPointerMoved(e)) { tapClick(e); - if ((/^(select|option)$/i).test(e.target.tagName)) { + if (isSelectOrOption(e.target.tagName)) { e.preventDefault(); } } @@ -3012,6 +3099,10 @@ function tapIgnoreEvent(e) { if (e.isTapHandled) return true; e.isTapHandled = true; + if(ionic.tap.isElementTapDisabled(e.target)) { + return true; + } + if (ionic.scroll.isScrolling && ionic.tap.containsOrIsTextInput(e.target)) { e.preventDefault(); return true; @@ -3033,7 +3124,7 @@ function tapHandleFocus(ele) { // already is the active element and has focus triggerFocusIn = true; - } else if ((/^(input|textarea)$/i).test(ele.tagName) || ele.isContentEditable) { + } else if ((/^(input|textarea|ion-label)$/i).test(ele.tagName) || ele.isContentEditable) { triggerFocusIn = true; ele.focus && ele.focus(); ele.value = ele.value; @@ -3056,7 +3147,7 @@ function tapHandleFocus(ele) { function tapFocusOutActive() { var ele = tapActiveElement(); if (ele && ((/^(input|textarea|select)$/i).test(ele.tagName) || ele.isContentEditable)) { - void 0; + //console.log('tapFocusOutActive', ele.tagName); ele.blur(); } tapActiveElement(null); @@ -3077,7 +3168,7 @@ function tapFocusIn(e) { // 2) There is an active element which is a text input // 3) A text input was just set to be focused on by a touch event // 4) A new focus has been set, however the target isn't the one the touch event wanted - void 0; + //console.log('focusin', 'tapTouchFocusedInput'); tapTouchFocusedInput.focus(); tapTouchFocusedInput = null; } @@ -3135,6 +3226,10 @@ function tapTargetElement(ele) { return ele; } +function isSelectOrOption(tagName){ + return (/^(select|option)$/i).test(tagName); +} + ionic.DomUtil.ready(function() { var ng = typeof angular !== 'undefined' ? angular : null; //do nothing for e2e tests @@ -3555,6 +3650,12 @@ var keyboardLandscapeViewportHeight = 0; */ var keyboardActiveElement; +/** + * The previously focused input used to reset keyboard after focusing on a + * new non-keyboard element + */ +var lastKeyboardActiveElement; + /** * The scroll view containing the currently focused input. */ @@ -3771,6 +3872,9 @@ function keyboardFocusIn(e) { e.target.readOnly || !ionic.tap.isKeyboardElement(e.target) || !(scrollView = ionic.DomUtil.getParentWithClass(e.target, SCROLL_CONTAINER_CSS))) { + if (keyboardActiveElement) { + lastKeyboardActiveElement = keyboardActiveElement; + } keyboardActiveElement = null; return; } @@ -4006,9 +4110,9 @@ function keyboardHide() { ionic.keyboard.isOpen = false; ionic.keyboard.isClosing = false; - if (keyboardActiveElement) { + if (keyboardActiveElement || lastKeyboardActiveElement) { ionic.trigger('resetScrollView', { - target: keyboardActiveElement + target: keyboardActiveElement || lastKeyboardActiveElement }, true); } @@ -4032,6 +4136,7 @@ function keyboardHide() { } keyboardActiveElement = null; + lastKeyboardActiveElement = null; } /** @@ -4619,7 +4724,7 @@ var zyngaCore = { effect: {} }; return id; } }; -})(this); +})(window); /* * Scroller @@ -4800,6 +4905,9 @@ ionic.views.Scroll = ionic.views.View.inherit({ return self.options.freeze; }; + // We can just use the standard freeze pop in our mouth + self.freezeShut = self.freeze; + self.setScrollStart = function() { ionic.scroll.isScrolling = Math.abs(ionic.scroll.lastTop - self.__scrollTop) > 1; clearTimeout(self.scrollTimer); @@ -5274,6 +5382,7 @@ ionic.views.Scroll = ionic.views.View.inherit({ document.addEventListener("touchmove", self.touchMove, false); document.addEventListener("touchend", self.touchEnd, false); document.addEventListener("touchcancel", self.touchEnd, false); + document.addEventListener("wheel", self.mouseWheel, false); } else if (window.navigator.pointerEnabled) { // Pointer Events @@ -6872,7 +6981,7 @@ ionic.scroll = { (function(ionic) { var NOOP = function() {}; - var depreciated = function(name) { + var deprecated = function(name) { void 0; }; ionic.views.ScrollNative = ionic.views.View.inherit({ @@ -6881,6 +6990,8 @@ ionic.scroll = { var self = this; self.__container = self.el = options.el; self.__content = options.el.firstElementChild; + // Whether scrolling is frozen or not + self.__frozen = false; self.isNative = true; self.__scrollTop = self.el.scrollTop; @@ -6890,6 +7001,16 @@ ionic.scroll = { self.__maxScrollTop = Math.max((self.__contentHeight) - self.__clientHeight, 0); self.__maxScrollLeft = Math.max((self.__contentWidth) - self.__clientWidth, 0); + if(options.startY >= 0 || options.startX >= 0) { + ionic.requestAnimationFrame(function() { + self.el.scrollTop = options.startY || 0; + self.el.scrollLeft = options.startX || 0; + + self.__scrollTop = self.el.scrollTop; + self.__scrollLeft = self.el.scrollLeft; + }); + } + self.options = { freeze: false, @@ -6922,16 +7043,22 @@ ionic.scroll = { }, 80); }; - self.freeze = NOOP; + self.freeze = function(shouldFreeze) { + self.__frozen = shouldFreeze; + }; + // A more powerful freeze pop that dominates all other freeze pops + self.freezeShut = function(shouldFreezeShut) { + self.__frozenShut = shouldFreezeShut; + }; self.__initEventHandlers(); }, /** Methods not used in native scrolling */ - __callback: function() { depreciated('__callback'); }, - zoomTo: function() { depreciated('zoomTo'); }, - zoomBy: function() { depreciated('zoomBy'); }, - activatePullToRefresh: function() { depreciated('activatePullToRefresh'); }, + __callback: function() { deprecated('__callback'); }, + zoomTo: function() { deprecated('zoomTo'); }, + zoomBy: function() { deprecated('zoomBy'); }, + activatePullToRefresh: function() { deprecated('activatePullToRefresh'); }, /** * Returns the scroll position and zooming values @@ -7071,6 +7198,19 @@ ionic.scroll = { self.resize(); return; } + + var oldOverflowX = self.el.style.overflowX; + var oldOverflowY = self.el.style.overflowY; + + clearTimeout(self.__scrollToCleanupTimeout); + self.__scrollToCleanupTimeout = setTimeout(function() { + self.el.style.overflowX = oldOverflowX; + self.el.style.overflowY = oldOverflowY; + }, 500); + + self.el.style.overflowY = 'hidden'; + self.el.style.overflowX = 'hidden'; + animateScroll(top, left); function animateScroll(Y, X) { @@ -7082,6 +7222,8 @@ ionic.scroll = { fromX = self.el.scrollLeft; if (fromY === Y && fromX === X) { + self.el.style.overflowX = oldOverflowX; + self.el.style.overflowY = oldOverflowY; self.resize(); return; /* Prevent scrolling to the Y point if already there */ } @@ -7112,6 +7254,8 @@ ionic.scroll = { } else { // done ionic.tap.removeClonedInputs(self.__container, self); + self.el.style.overflowX = oldOverflowX; + self.el.style.overflowY = oldOverflowY; self.resize(); } } @@ -7169,21 +7313,29 @@ ionic.scroll = { // save height when scroll view is shrunk so we don't need to reflow var scrollViewOffsetHeight; + var lastKeyboardHeight; + /** * Shrink the scroll view when the keyboard is up if necessary and if the * focused input is below the bottom of the shrunk scroll view, scroll it * into view. */ self.scrollChildIntoView = function(e) { - //console.log("scrollChildIntoView at: " + Date.now()); + var rect = container.getBoundingClientRect(); + if(!self.__originalContainerHeight) { + self.__originalContainerHeight = rect.height; + } // D - var scrollBottomOffsetToTop = container.getBoundingClientRect().bottom; + //var scrollBottomOffsetToTop = rect.bottom; // D - A - scrollViewOffsetHeight = container.offsetHeight; + scrollViewOffsetHeight = self.__originalContainerHeight; + //console.log('Scroll view offset height', scrollViewOffsetHeight); + //console.dir(container); var alreadyShrunk = self.isShrunkForKeyboard; var isModal = container.parentNode.classList.contains('modal'); + var isPopover = container.parentNode.classList.contains('popover'); // 680px is when the media query for 60% modal width kicks in var isInsetModal = isModal && window.innerWidth >= 680; @@ -7199,24 +7351,41 @@ ionic.scroll = { * All commented calculations relative to the top of the viewport (ie E * is the viewport height, not 0) */ - if (!alreadyShrunk) { + + + var changedKeyboardHeight = lastKeyboardHeight && (lastKeyboardHeight !== e.detail.keyboardHeight); + + if (!alreadyShrunk || changedKeyboardHeight) { // shrink scrollview so we can actually scroll if the input is hidden // if it isn't shrink so we can scroll to inputs under the keyboard // inset modals won't shrink on Android on their own when the keyboard appears - if ( ionic.Platform.isIOS() || ionic.Platform.isFullScreen || isInsetModal ) { + if ( !isPopover && (ionic.Platform.isIOS() || ionic.Platform.isFullScreen || isInsetModal) ) { // if there are things below the scroll view account for them and // subtract them from the keyboard height when resizing // E - D E D - var scrollBottomOffsetToBottom = e.detail.viewportHeight - scrollBottomOffsetToTop; + //var scrollBottomOffsetToBottom = e.detail.viewportHeight - scrollBottomOffsetToTop; // 0 or D - B if D > B E - B E - D - var keyboardOffset = Math.max(0, e.detail.keyboardHeight - scrollBottomOffsetToBottom); + //var keyboardOffset = e.detail.keyboardHeight - scrollBottomOffsetToBottom; ionic.requestAnimationFrame(function(){ // D - A or B - A if D > B D - A max(0, D - B) - scrollViewOffsetHeight = scrollViewOffsetHeight - keyboardOffset; + scrollViewOffsetHeight = Math.max(0, Math.min(self.__originalContainerHeight, self.__originalContainerHeight - (e.detail.keyboardHeight - 43)));//keyboardOffset >= 0 ? scrollViewOffsetHeight - keyboardOffset : scrollViewOffsetHeight + keyboardOffset; + + //console.log('Old container height', self.__originalContainerHeight, 'New container height', scrollViewOffsetHeight, 'Keyboard height', e.detail.keyboardHeight); + container.style.height = scrollViewOffsetHeight + "px"; + /* + if (ionic.Platform.isIOS()) { + // Force redraw to avoid disappearing content + var disp = container.style.display; + container.style.display = 'none'; + var trick = container.offsetHeight; + container.style.display = disp; + } + */ + container.classList.add('keyboard-up'); //update scroll view self.resize(); }); @@ -7225,6 +7394,8 @@ ionic.scroll = { self.isShrunkForKeyboard = true; } + lastKeyboardHeight = e.detail.keyboardHeight; + /* * _______ * |---A---| <- top of scroll view @@ -7241,26 +7412,42 @@ ionic.scroll = { if (e.detail.isElementUnderKeyboard) { ionic.requestAnimationFrame(function(){ + var pos = ionic.DomUtil.getOffsetTop(e.detail.target); + setTimeout(function() { + if (ionic.Platform.isIOS()) { + ionic.tap.cloneFocusedInput(container, self); + } + // Scroll the input into view, with a 100px buffer + self.scrollTo(0, pos - (rect.top + 100), true); + self.onScroll(); + }, 32); + + /* // update D if we shrunk if (self.isShrunkForKeyboard && !alreadyShrunk) { scrollBottomOffsetToTop = container.getBoundingClientRect().bottom; + console.log('Scroll bottom', scrollBottomOffsetToTop); } // middle of the scrollview, this is where we want to scroll to // (D - A) / 2 var scrollMidpointOffset = scrollViewOffsetHeight * 0.5; + console.log('Midpoint', scrollMidpointOffset); //console.log("container.offsetHeight: " + scrollViewOffsetHeight); // middle of the input we want to scroll into view // C var inputMidpoint = ((e.detail.elementBottom + e.detail.elementTop) / 2); + console.log('Input midpoint'); // distance from middle of input to the bottom of the scroll view // C - D C D var inputMidpointOffsetToScrollBottom = inputMidpoint - scrollBottomOffsetToTop; + console.log('Input midpoint offset', inputMidpointOffsetToScrollBottom); //C - D + (D - A)/2 C - D (D - A)/ 2 var scrollTop = inputMidpointOffsetToScrollBottom + scrollMidpointOffset; + console.log('Scroll top', scrollTop); if ( scrollTop > 0) { if (ionic.Platform.isIOS()) { @@ -7275,6 +7462,7 @@ ionic.scroll = { self.onScroll(); } } + */ }); } @@ -7288,16 +7476,46 @@ ionic.scroll = { if (self.isShrunkForKeyboard) { self.isShrunkForKeyboard = false; container.style.height = ""; + + /* + if (ionic.Platform.isIOS()) { + // Force redraw to avoid disappearing content + var disp = container.style.display; + container.style.display = 'none'; + var trick = container.offsetHeight; + container.style.display = disp; + } + */ + + self.__originalContainerHeight = container.getBoundingClientRect().height; + + if (ionic.Platform.isIOS()) { + ionic.requestAnimationFrame(function() { + container.classList.remove('keyboard-up'); + }); + } + } self.resize(); }; + self.handleTouchMove = function(e) { + if(self.__frozenShut) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + }; + container.addEventListener('scroll', self.onScroll); //Broadcasted when keyboard is shown on some platforms. //See js/utils/keyboard.js container.addEventListener('scrollChildIntoView', self.scrollChildIntoView); + container.addEventListener(ionic.EVENTS.touchstart, self.handleTouchMove); + container.addEventListener(ionic.EVENTS.touchmove, self.handleTouchMove); + // Listen on document because container may not have had the last // keyboardActiveElement, for example after closing a modal with a focused // input and returning to a previously resized scroll view in an ion-content. @@ -7316,6 +7534,9 @@ ionic.scroll = { container.removeEventListener('scrollChildIntoView', self.scrollChildIntoView); container.removeEventListener('resetScrollView', self.resetScrollView); + container.removeEventListener(ionic.EVENTS.touchstart, self.handleTouchMove); + container.removeEventListener(ionic.EVENTS.touchmove, self.handleTouchMove); + ionic.tap.removeClonedInputs(container, self); delete self.__container; @@ -7332,7 +7553,6 @@ ionic.scroll = { })(ionic); - (function(ionic) { 'use strict'; @@ -8073,6 +8293,25 @@ ionic.views.Slider = ionic.views.View.inherit({ initialize: function (options) { var slider = this; + var touchStartEvent, touchMoveEvent, touchEndEvent; + if (window.navigator.pointerEnabled) { + touchStartEvent = 'pointerdown'; + touchMoveEvent = 'pointermove'; + touchEndEvent = 'pointerup'; + } else if (window.navigator.msPointerEnabled) { + touchStartEvent = 'MSPointerDown'; + touchMoveEvent = 'MSPointerMove'; + touchEndEvent = 'MSPointerUp'; + } else { + touchStartEvent = 'touchstart'; + touchMoveEvent = 'touchmove'; + touchEndEvent = 'touchend'; + } + + var mouseStartEvent = 'mousedown'; + var mouseMoveEvent = 'mousemove'; + var mouseEndEvent = 'mouseup'; + // utilities var noop = function() {}; // simple no operation function var offloadFn = function(fn) { setTimeout(fn || noop, 0); }; // offload a functions execution @@ -8080,7 +8319,6 @@ ionic.views.Slider = ionic.views.View.inherit({ // check browser capabilities var browser = { addEventListener: !!window.addEventListener, - touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch, transitions: (function(temp) { var props = ['transitionProperty', 'WebkitTransition', 'MozTransition', 'OTransition', 'msTransition']; for ( var i in props ) if (temp.style[ props[i] ] !== undefined) return true; @@ -8184,6 +8422,11 @@ ionic.views.Slider = ionic.views.View.inherit({ // do nothing if already on requested slide if (index == to) return; + if (!slides) { + index = to; + return; + } + if (browser.transitions) { var direction = Math.abs(index - to) / (index - to); // 1: backward, -1: forward @@ -8311,7 +8554,7 @@ ionic.views.Slider = ionic.views.View.inherit({ var events = { handleEvent: function(event) { - if(event.type == 'mousedown' || event.type == 'mouseup' || event.type == 'mousemove') { + if(!event.touches && event.pageX && event.pageY) { event.touches = [{ pageX: event.pageX, pageY: event.pageY @@ -8319,12 +8562,12 @@ ionic.views.Slider = ionic.views.View.inherit({ } switch (event.type) { - case 'mousedown': this.start(event); break; - case 'touchstart': this.start(event); break; - case 'touchmove': this.touchmove(event); break; - case 'mousemove': this.touchmove(event); break; - case 'touchend': offloadFn(this.end(event)); break; - case 'mouseup': offloadFn(this.end(event)); break; + case touchStartEvent: this.start(event); break; + case mouseStartEvent: this.start(event); break; + case touchMoveEvent: this.touchmove(event); break; + case mouseMoveEvent: this.touchmove(event); break; + case touchEndEvent: offloadFn(this.end(event)); break; + case mouseEndEvent: offloadFn(this.end(event)); break; case 'webkitTransitionEnd': case 'msTransitionEnd': case 'oTransitionEnd': @@ -8338,6 +8581,11 @@ ionic.views.Slider = ionic.views.View.inherit({ }, start: function(event) { + // prevent to start if there is no valid event + if (!event.touches) { + return; + } + var touches = event.touches[0]; // measure start values @@ -8359,20 +8607,22 @@ ionic.views.Slider = ionic.views.View.inherit({ delta = {}; // attach touchmove and touchend listeners - if(browser.touch) { - element.addEventListener('touchmove', this, false); - element.addEventListener('touchend', this, false); - } else { - element.addEventListener('mousemove', this, false); - element.addEventListener('mouseup', this, false); - document.addEventListener('mouseup', this, false); - } + element.addEventListener(touchMoveEvent, this, false); + element.addEventListener(mouseMoveEvent, this, false); + + element.addEventListener(touchEndEvent, this, false); + element.addEventListener(mouseEndEvent, this, false); + + document.addEventListener(touchEndEvent, this, false); + document.addEventListener(mouseEndEvent, this, false); }, touchmove: function(event) { + // ensure there is a valid event // ensure swiping with one touch and not pinching // ensure sliding is enabled - if (event.touches.length > 1 || + if (!event.touches || + event.touches.length > 1 || event.scale && event.scale !== 1 || slider.slideIsDisabled) { return; @@ -8410,15 +8660,24 @@ ionic.views.Slider = ionic.views.View.inherit({ translate(circle(index + 1), delta.x + slidePos[circle(index + 1)], 0); } else { - - delta.x = - delta.x / - ( (!index && delta.x > 0 || // if first slide and sliding left - index == slides.length - 1 && // or if last slide and sliding right - delta.x < 0 // and if sliding at all - ) ? - ( Math.abs(delta.x) / width + 1 ) // determine resistance level - : 1 ); // no resistance if false + // If the slider bounces, do the bounce! + if(options.bouncing) { + delta.x = + delta.x / + ( (!index && delta.x > 0 || // if first slide and sliding left + index == slides.length - 1 && // or if last slide and sliding right + delta.x < 0 // and if sliding at all + ) ? + ( Math.abs(delta.x) / width + 1 ) // determine resistance level + : 1 ); // no resistance if false + } else { + if(width * index - delta.x < 0) { //We are trying scroll past left boundary + delta.x = Math.min(delta.x, width * index); //Set delta.x so we don't go past left screen + } + if(Math.abs(delta.x) > width * (slides.length - index - 1)){ //We are trying to scroll past right bondary + delta.x = Math.max( -width * (slides.length - index - 1), delta.x); //Set delta.x so we don't go past right screen + } + } // translate 1:1 translate(index - 1, delta.x + slidePos[index - 1], 0); @@ -8508,14 +8767,14 @@ ionic.views.Slider = ionic.views.View.inherit({ } // kill touchmove and touchend event listeners until touchstart called again - if(browser.touch) { - element.removeEventListener('touchmove', events, false); - element.removeEventListener('touchend', events, false); - } else { - element.removeEventListener('mousemove', events, false); - element.removeEventListener('mouseup', events, false); - document.removeEventListener('mouseup', events, false); - } + element.removeEventListener(touchMoveEvent, events, false); + element.removeEventListener(mouseMoveEvent, events, false); + + element.removeEventListener(touchEndEvent, events, false); + element.removeEventListener(mouseEndEvent, events, false); + + document.removeEventListener(touchEndEvent, events, false); + document.removeEventListener(mouseEndEvent, events, false); options.onDragEnd && options.onDragEnd(); }, @@ -8617,7 +8876,8 @@ ionic.views.Slider = ionic.views.View.inherit({ if (browser.addEventListener) { // remove current event listeners - element.removeEventListener('touchstart', events, false); + element.removeEventListener(touchStartEvent, events, false); + element.removeEventListener(mouseStartEvent, events, false); element.removeEventListener('webkitTransitionEnd', events, false); element.removeEventListener('msTransitionEnd', events, false); element.removeEventListener('oTransitionEnd', events, false); @@ -8645,11 +8905,8 @@ ionic.views.Slider = ionic.views.View.inherit({ if (browser.addEventListener) { // set touchstart event on element - if (browser.touch) { - element.addEventListener('touchstart', events, false); - } else { - element.addEventListener('mousedown', events, false); - } + element.addEventListener(touchStartEvent, events, false); + element.addEventListener(mouseStartEvent, events, false); if (browser.transitions) { element.addEventListener('webkitTransitionEnd', events, false); @@ -8674,8937 +8931,13854 @@ ionic.views.Slider = ionic.views.View.inherit({ })(ionic); -(function(ionic) { -'use strict'; - - ionic.views.Toggle = ionic.views.View.inherit({ - initialize: function(opts) { - var self = this; +/*eslint space-after-keywords: 0*/ + +/** + * Swiper 3.2.7 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/swiper/ + * + * Copyright 2015, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: December 7, 2015 + */ +(function () { + 'use strict'; + var $; + /*=========================== + Swiper + ===========================*/ + var Swiper = function (container, params, _scope, $compile) { + + if (!(this instanceof Swiper)) return new Swiper(container, params); + + var defaults = { + direction: 'horizontal', + touchEventsTarget: 'container', + initialSlide: 0, + speed: 300, + // autoplay + autoplay: false, + autoplayDisableOnInteraction: true, + // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView). + iOSEdgeSwipeDetection: false, + iOSEdgeSwipeThreshold: 20, + // Free mode + freeMode: false, + freeModeMomentum: true, + freeModeMomentumRatio: 1, + freeModeMomentumBounce: true, + freeModeMomentumBounceRatio: 1, + freeModeSticky: false, + freeModeMinimumVelocity: 0.02, + // Autoheight + autoHeight: false, + // Set wrapper width + setWrapperSize: false, + // Virtual Translate + virtualTranslate: false, + // Effects + effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' + coverflow: { + rotate: 50, + stretch: 0, + depth: 100, + modifier: 1, + slideShadows : true + }, + cube: { + slideShadows: true, + shadow: true, + shadowOffset: 20, + shadowScale: 0.94 + }, + fade: { + crossFade: false + }, + // Parallax + parallax: false, + // Scrollbar + scrollbar: null, + scrollbarHide: true, + scrollbarDraggable: false, + scrollbarSnapOnRelease: false, + // Keyboard Mousewheel + keyboardControl: false, + mousewheelControl: false, + mousewheelReleaseOnEdges: false, + mousewheelInvert: false, + mousewheelForceToAxis: false, + mousewheelSensitivity: 1, + // Hash Navigation + hashnav: false, + // Breakpoints + breakpoints: undefined, + // Slides grid + spaceBetween: 0, + slidesPerView: 1, + slidesPerColumn: 1, + slidesPerColumnFill: 'column', + slidesPerGroup: 1, + centeredSlides: false, + slidesOffsetBefore: 0, // in px + slidesOffsetAfter: 0, // in px + // Round length + roundLengths: false, + // Touches + touchRatio: 1, + touchAngle: 45, + simulateTouch: true, + shortSwipes: true, + longSwipes: true, + longSwipesRatio: 0.5, + longSwipesMs: 300, + followFinger: true, + onlyExternal: false, + threshold: 0, + touchMoveStopPropagation: true, + // Pagination + pagination: null, + paginationElement: 'span', + paginationClickable: false, + paginationHide: false, + paginationBulletRender: null, + // Resistance + resistance: true, + resistanceRatio: 0.85, + // Next/prev buttons + nextButton: null, + prevButton: null, + // Progress + watchSlidesProgress: false, + watchSlidesVisibility: false, + // Cursor + grabCursor: false, + // Clicks + preventClicks: true, + preventClicksPropagation: true, + slideToClickedSlide: false, + // Lazy Loading + lazyLoading: false, + lazyLoadingInPrevNext: false, + lazyLoadingOnTransitionStart: false, + // Images + preloadImages: true, + updateOnImagesReady: true, + // loop + loop: false, + loopAdditionalSlides: 0, + loopedSlides: null, + // Control + control: undefined, + controlInverse: false, + controlBy: 'slide', //or 'container' + // Swiping/no swiping + allowSwipeToPrev: true, + allowSwipeToNext: true, + swipeHandler: null, //'.swipe-handler', + noSwiping: true, + noSwipingClass: 'swiper-no-swiping', + // NS + slideClass: 'swiper-slide', + slideActiveClass: 'swiper-slide-active', + slideVisibleClass: 'swiper-slide-visible', + slideDuplicateClass: 'swiper-slide-duplicate', + slideNextClass: 'swiper-slide-next', + slidePrevClass: 'swiper-slide-prev', + wrapperClass: 'swiper-wrapper', + bulletClass: 'swiper-pagination-bullet', + bulletActiveClass: 'swiper-pagination-bullet-active', + buttonDisabledClass: 'swiper-button-disabled', + paginationHiddenClass: 'swiper-pagination-hidden', + // Observer + observer: false, + observeParents: false, + // Accessibility + a11y: false, + prevSlideMessage: 'Previous slide', + nextSlideMessage: 'Next slide', + firstSlideMessage: 'This is the first slide', + lastSlideMessage: 'This is the last slide', + paginationBulletMessage: 'Go to slide {{index}}', + // Callbacks + runCallbacksOnInit: true + /* + Callbacks: + onInit: function (swiper) + onDestroy: function (swiper) + onClick: function (swiper, e) + onTap: function (swiper, e) + onDoubleTap: function (swiper, e) + onSliderMove: function (swiper, e) + onSlideChangeStart: function (swiper) + onSlideChangeEnd: function (swiper) + onTransitionStart: function (swiper) + onTransitionEnd: function (swiper) + onImagesReady: function (swiper) + onProgress: function (swiper, progress) + onTouchStart: function (swiper, e) + onTouchMove: function (swiper, e) + onTouchMoveOpposite: function (swiper, e) + onTouchEnd: function (swiper, e) + onReachBeginning: function (swiper) + onReachEnd: function (swiper) + onSetTransition: function (swiper, duration) + onSetTranslate: function (swiper, translate) + onAutoplayStart: function (swiper) + onAutoplayStop: function (swiper), + onLazyImageLoad: function (swiper, slide, image) + onLazyImageReady: function (swiper, slide, image) + */ - this.el = opts.el; - this.checkbox = opts.checkbox; - this.track = opts.track; - this.handle = opts.handle; - this.openPercent = -1; - this.onChange = opts.onChange || function() {}; + }; + var initialVirtualTranslate = params && params.virtualTranslate; - this.triggerThreshold = opts.triggerThreshold || 20; + params = params || {}; + var originalParams = {}; + for (var param in params) { + if (typeof params[param] === 'object' && !(params[param].nodeType || params[param] === window || params[param] === document || (typeof Dom7 !== 'undefined' && params[param] instanceof Dom7) || (typeof jQuery !== 'undefined' && params[param] instanceof jQuery))) { + originalParams[param] = {}; + for (var deepParam in params[param]) { + originalParams[param][deepParam] = params[param][deepParam]; + } + } + else { + originalParams[param] = params[param]; + } + } + for (var def in defaults) { + if (typeof params[def] === 'undefined') { + params[def] = defaults[def]; + } + else if (typeof params[def] === 'object') { + for (var deepDef in defaults[def]) { + if (typeof params[def][deepDef] === 'undefined') { + params[def][deepDef] = defaults[def][deepDef]; + } + } + } + } - this.dragStartHandler = function(e) { - self.dragStart(e); - }; - this.dragHandler = function(e) { - self.drag(e); - }; - this.holdHandler = function(e) { - self.hold(e); - }; - this.releaseHandler = function(e) { - self.release(e); - }; + // Swiper + var s = this; - this.dragStartGesture = ionic.onGesture('dragstart', this.dragStartHandler, this.el); - this.dragGesture = ionic.onGesture('drag', this.dragHandler, this.el); - this.dragHoldGesture = ionic.onGesture('hold', this.holdHandler, this.el); - this.dragReleaseGesture = ionic.onGesture('release', this.releaseHandler, this.el); - }, + // Params + s.params = params; + s.originalParams = originalParams; - destroy: function() { - ionic.offGesture(this.dragStartGesture, 'dragstart', this.dragStartGesture); - ionic.offGesture(this.dragGesture, 'drag', this.dragGesture); - ionic.offGesture(this.dragHoldGesture, 'hold', this.holdHandler); - ionic.offGesture(this.dragReleaseGesture, 'release', this.releaseHandler); - }, + // Classname + s.classNames = []; + /*========================= + Dom Library and plugins + ===========================*/ + if (typeof $ !== 'undefined' && typeof Dom7 !== 'undefined'){ + $ = Dom7; + } + if (typeof $ === 'undefined') { + if (typeof Dom7 === 'undefined') { + $ = window.Dom7 || window.Zepto || window.jQuery; + } + else { + $ = Dom7; + } + if (!$) return; + } + // Export it to Swiper instance + s.$ = $; + + /*========================= + Breakpoints + ===========================*/ + s.currentBreakpoint = undefined; + s.getActiveBreakpoint = function () { + //Get breakpoint for window width + if (!s.params.breakpoints) return false; + var breakpoint = false; + var points = [], point; + for ( point in s.params.breakpoints ) { + if (s.params.breakpoints.hasOwnProperty(point)) { + points.push(point); + } + } + points.sort(function (a, b) { + return parseInt(a, 10) > parseInt(b, 10); + }); + for (var i = 0; i < points.length; i++) { + point = points[i]; + if (point >= window.innerWidth && !breakpoint) { + breakpoint = point; + } + } + return breakpoint || 'max'; + }; + s.setBreakpoint = function () { + //Set breakpoint for window width and update parameters + var breakpoint = s.getActiveBreakpoint(); + if (breakpoint && s.currentBreakpoint !== breakpoint) { + var breakPointsParams = breakpoint in s.params.breakpoints ? s.params.breakpoints[breakpoint] : s.originalParams; + for ( var param in breakPointsParams ) { + s.params[param] = breakPointsParams[param]; + } + s.currentBreakpoint = breakpoint; + } + }; + // Set breakpoint on load + if (s.params.breakpoints) { + s.setBreakpoint(); + } + + /*========================= + Preparation - Define Container, Wrapper and Pagination + ===========================*/ + s.container = $(container); + if (s.container.length === 0) return; + if (s.container.length > 1) { + s.container.each(function () { + new Swiper(this, params); + }); + return; + } - tap: function() { - if(this.el.getAttribute('disabled') !== 'disabled') { - this.val( !this.checkbox.checked ); - } - }, + // Save instance in container HTML Element and in data + s.container[0].swiper = s; + s.container.data('swiper', s); - dragStart: function(e) { - if(this.checkbox.disabled) return; + s.classNames.push('swiper-container-' + s.params.direction); - this._dragInfo = { - width: this.el.offsetWidth, - left: this.el.offsetLeft, - right: this.el.offsetLeft + this.el.offsetWidth, - triggerX: this.el.offsetWidth / 2, - initialState: this.checkbox.checked - }; + if (s.params.freeMode) { + s.classNames.push('swiper-container-free-mode'); + } + if (!s.support.flexbox) { + s.classNames.push('swiper-container-no-flexbox'); + s.params.slidesPerColumn = 1; + } + if (s.params.autoHeight) { + s.classNames.push('swiper-container-autoheight'); + } + // Enable slides progress when required + if (s.params.parallax || s.params.watchSlidesVisibility) { + s.params.watchSlidesProgress = true; + } + // Coverflow / 3D + if (['cube', 'coverflow'].indexOf(s.params.effect) >= 0) { + if (s.support.transforms3d) { + s.params.watchSlidesProgress = true; + s.classNames.push('swiper-container-3d'); + } + else { + s.params.effect = 'slide'; + } + } + if (s.params.effect !== 'slide') { + s.classNames.push('swiper-container-' + s.params.effect); + } + if (s.params.effect === 'cube') { + s.params.resistanceRatio = 0; + s.params.slidesPerView = 1; + s.params.slidesPerColumn = 1; + s.params.slidesPerGroup = 1; + s.params.centeredSlides = false; + s.params.spaceBetween = 0; + s.params.virtualTranslate = true; + s.params.setWrapperSize = false; + } + if (s.params.effect === 'fade') { + s.params.slidesPerView = 1; + s.params.slidesPerColumn = 1; + s.params.slidesPerGroup = 1; + s.params.watchSlidesProgress = true; + s.params.spaceBetween = 0; + if (typeof initialVirtualTranslate === 'undefined') { + s.params.virtualTranslate = true; + } + } - // Stop any parent dragging - e.gesture.srcEvent.preventDefault(); + // Grab Cursor + if (s.params.grabCursor && s.support.touch) { + s.params.grabCursor = false; + } - // Trigger hold styles - this.hold(e); - }, + // Wrapper + s.wrapper = s.container.children('.' + s.params.wrapperClass); - drag: function(e) { - var self = this; - if(!this._dragInfo) { return; } + // Pagination + if (s.params.pagination) { + s.paginationContainer = $(s.params.pagination); + if (s.params.paginationClickable) { + s.paginationContainer.addClass('swiper-pagination-clickable'); + } + } - // Stop any parent dragging - e.gesture.srcEvent.preventDefault(); + // Is Horizontal + function isH() { + return s.params.direction === 'horizontal'; + } - ionic.requestAnimationFrame(function () { - if (!self._dragInfo) { return; } + // RTL + s.rtl = isH() && (s.container[0].dir.toLowerCase() === 'rtl' || s.container.css('direction') === 'rtl'); + if (s.rtl) { + s.classNames.push('swiper-container-rtl'); + } - var px = e.gesture.touches[0].pageX - self._dragInfo.left; - var mx = self._dragInfo.width - self.triggerThreshold; + // Wrong RTL support + if (s.rtl) { + s.wrongRTL = s.wrapper.css('display') === '-webkit-box'; + } - // The initial state was on, so "tend towards" on - if(self._dragInfo.initialState) { - if(px < self.triggerThreshold) { - self.setOpenPercent(0); - } else if(px > self._dragInfo.triggerX) { - self.setOpenPercent(100); - } - } else { - // The initial state was off, so "tend towards" off - if(px < self._dragInfo.triggerX) { - self.setOpenPercent(0); - } else if(px > mx) { - self.setOpenPercent(100); - } + // Columns + if (s.params.slidesPerColumn > 1) { + s.classNames.push('swiper-container-multirow'); } - }); - }, - endDrag: function() { - this._dragInfo = null; - }, + // Check for Android + if (s.device.android) { + s.classNames.push('swiper-container-android'); + } - hold: function() { - this.el.classList.add('dragging'); - }, - release: function(e) { - this.el.classList.remove('dragging'); - this.endDrag(e); - }, + // Add classes + s.container.addClass(s.classNames.join(' ')); + // Translate + s.translate = 0; - setOpenPercent: function(openPercent) { - // only make a change if the new open percent has changed - if(this.openPercent < 0 || (openPercent < (this.openPercent - 3) || openPercent > (this.openPercent + 3) ) ) { - this.openPercent = openPercent; + // Progress + s.progress = 0; - if(openPercent === 0) { - this.val(false); - } else if(openPercent === 100) { - this.val(true); - } else { - var openPixel = Math.round( (openPercent / 100) * this.track.offsetWidth - (this.handle.offsetWidth) ); - openPixel = (openPixel < 1 ? 0 : openPixel); - this.handle.style[ionic.CSS.TRANSFORM] = 'translate3d(' + openPixel + 'px,0,0)'; - } - } - }, + // Velocity + s.velocity = 0; - val: function(value) { - if(value === true || value === false) { - if(this.handle.style[ionic.CSS.TRANSFORM] !== "") { - this.handle.style[ionic.CSS.TRANSFORM] = ""; - } - this.checkbox.checked = value; - this.openPercent = (value ? 100 : 0); - this.onChange && this.onChange(); - } - return this.checkbox.checked; - } + /*========================= + Locks, unlocks + ===========================*/ + s.lockSwipeToNext = function () { + s.params.allowSwipeToNext = false; + }; + s.lockSwipeToPrev = function () { + s.params.allowSwipeToPrev = false; + }; + s.lockSwipes = function () { + s.params.allowSwipeToNext = s.params.allowSwipeToPrev = false; + }; + s.unlockSwipeToNext = function () { + s.params.allowSwipeToNext = true; + }; + s.unlockSwipeToPrev = function () { + s.params.allowSwipeToPrev = true; + }; + s.unlockSwipes = function () { + s.params.allowSwipeToNext = s.params.allowSwipeToPrev = true; + }; - }); + /*========================= + Round helper + ===========================*/ + function round(a) { + return Math.floor(a); + } + /*========================= + Set grab cursor + ===========================*/ + if (s.params.grabCursor) { + s.container[0].style.cursor = 'move'; + s.container[0].style.cursor = '-webkit-grab'; + s.container[0].style.cursor = '-moz-grab'; + s.container[0].style.cursor = 'grab'; + } + /*========================= + Update on Images Ready + ===========================*/ + s.imagesToLoad = []; + s.imagesLoaded = 0; + + s.loadImage = function (imgElement, src, srcset, checkForComplete, callback) { + var image; + function onReady () { + if (callback) callback(); + } + if (!imgElement.complete || !checkForComplete) { + if (src) { + image = new window.Image(); + image.onload = onReady; + image.onerror = onReady; + if (srcset) { + image.srcset = srcset; + } + if (src) { + image.src = src; + } + } else { + onReady(); + } -})(ionic); + } else {//image already loaded... + onReady(); + } + }; + s.preloadImages = function () { + s.imagesToLoad = s.container.find('img'); + function _onReady() { + if (typeof s === 'undefined' || s === null) return; + if (s.imagesLoaded !== undefined) s.imagesLoaded++; + if (s.imagesLoaded === s.imagesToLoad.length) { + if (s.params.updateOnImagesReady) s.update(); + s.emit('onImagesReady', s); + } + } + for (var i = 0; i < s.imagesToLoad.length; i++) { + s.loadImage(s.imagesToLoad[i], (s.imagesToLoad[i].currentSrc || s.imagesToLoad[i].getAttribute('src')), (s.imagesToLoad[i].srcset || s.imagesToLoad[i].getAttribute('srcset')), true, _onReady); + } + }; -})(); -/*! - * ionic.bundle.js is a concatenation of: - * ionic.js, angular.js, angular-animate.js, - * angular-sanitize.js, angular-ui-router.js, - * and ionic-angular.js - */ + /*========================= + Autoplay + ===========================*/ + s.autoplayTimeoutId = undefined; + s.autoplaying = false; + s.autoplayPaused = false; + function autoplay() { + s.autoplayTimeoutId = setTimeout(function () { + if (s.params.loop) { + s.fixLoop(); + s._slideNext(); + } + else { + if (!s.isEnd) { + s._slideNext(); + } + else { + if (!params.autoplayStopOnLast) { + s._slideTo(0); + } + else { + s.stopAutoplay(); + } + } + } + }, s.params.autoplay); + } + s.startAutoplay = function () { + if (typeof s.autoplayTimeoutId !== 'undefined') return false; + if (!s.params.autoplay) return false; + if (s.autoplaying) return false; + s.autoplaying = true; + s.emit('onAutoplayStart', s); + autoplay(); + }; + s.stopAutoplay = function (internal) { + if (!s.autoplayTimeoutId) return; + if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId); + s.autoplaying = false; + s.autoplayTimeoutId = undefined; + s.emit('onAutoplayStop', s); + }; + s.pauseAutoplay = function (speed) { + if (s.autoplayPaused) return; + if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId); + s.autoplayPaused = true; + if (speed === 0) { + s.autoplayPaused = false; + autoplay(); + } + else { + s.wrapper.transitionEnd(function () { + if (!s) return; + s.autoplayPaused = false; + if (!s.autoplaying) { + s.stopAutoplay(); + } + else { + autoplay(); + } + }); + } + }; + /*========================= + Min/Max Translate + ===========================*/ + s.minTranslate = function () { + return (-s.snapGrid[0]); + }; + s.maxTranslate = function () { + return (-s.snapGrid[s.snapGrid.length - 1]); + }; + /*========================= + Slider/slides sizes + ===========================*/ + s.updateAutoHeight = function () { + // Update Height + var newHeight = s.slides.eq(s.activeIndex)[0].offsetHeight; + if (newHeight) s.wrapper.css('height', s.slides.eq(s.activeIndex)[0].offsetHeight + 'px'); + }; + s.updateContainerSize = function () { + var width, height; + if (typeof s.params.width !== 'undefined') { + width = s.params.width; + } + else { + width = s.container[0].clientWidth; + } + if (typeof s.params.height !== 'undefined') { + height = s.params.height; + } + else { + height = s.container[0].clientHeight; + } + if (width === 0 && isH() || height === 0 && !isH()) { + return; + } -/** - * @license AngularJS v1.3.13 - * (c) 2010-2014 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, document, undefined) {'use strict'; + //Subtract paddings + width = width - parseInt(s.container.css('padding-left'), 10) - parseInt(s.container.css('padding-right'), 10); + height = height - parseInt(s.container.css('padding-top'), 10) - parseInt(s.container.css('padding-bottom'), 10); -/** - * @description - * - * This object provides a utility for producing rich Error messages within - * Angular. It can be called as follows: - * - * var exampleMinErr = minErr('example'); - * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); - * - * The above creates an instance of minErr in the example namespace. The - * resulting error will have a namespaced error code of example.one. The - * resulting error will replace {0} with the value of foo, and {1} with the - * value of bar. The object is not restricted in the number of arguments it can - * take. - * - * If fewer arguments are specified than necessary for interpolation, the extra - * interpolation markers will be preserved in the final string. - * - * Since data will be parsed statically during a build step, some restrictions - * are applied with respect to how minErr instances are created and called. - * Instances should have names of the form namespaceMinErr for a minErr created - * using minErr('namespace') . Error codes, namespaces and template strings - * should all be static strings, not variables or general expressions. - * - * @param {string} module The namespace to use for the new minErr instance. - * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning - * error from returned function, for cases when a particular type of error is useful. - * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance - */ + // Store values + s.width = width; + s.height = height; + s.size = isH() ? s.width : s.height; + }; -function minErr(module, ErrorConstructor) { - ErrorConstructor = ErrorConstructor || Error; - return function() { - var code = arguments[0], - prefix = '[' + (module ? module + ':' : '') + code + '] ', - template = arguments[1], - templateArgs = arguments, + s.updateSlidesSize = function () { + s.slides = s.wrapper.children('.' + s.params.slideClass); + s.snapGrid = []; + s.slidesGrid = []; + s.slidesSizesGrid = []; + + var spaceBetween = s.params.spaceBetween, + slidePosition = -s.params.slidesOffsetBefore, + i, + prevSlideSize = 0, + index = 0; + if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { + spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * s.size; + } - message, i; + s.virtualSize = -spaceBetween; + // reset margins + if (s.rtl) s.slides.css({marginLeft: '', marginTop: ''}); + else s.slides.css({marginRight: '', marginBottom: ''}); - message = prefix + template.replace(/\{\d+\}/g, function(match) { - var index = +match.slice(1, -1), arg; + var slidesNumberEvenToRows; + if (s.params.slidesPerColumn > 1) { + if (Math.floor(s.slides.length / s.params.slidesPerColumn) === s.slides.length / s.params.slidesPerColumn) { + slidesNumberEvenToRows = s.slides.length; + } + else { + slidesNumberEvenToRows = Math.ceil(s.slides.length / s.params.slidesPerColumn) * s.params.slidesPerColumn; + } + if (s.params.slidesPerView !== 'auto' && s.params.slidesPerColumnFill === 'row') { + slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, s.params.slidesPerView * s.params.slidesPerColumn); + } + } - if (index + 2 < templateArgs.length) { - return toDebugString(templateArgs[index + 2]); - } - return match; - }); + // Calc slides + var slideSize; + var slidesPerColumn = s.params.slidesPerColumn; + var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn; + var numFullColumns = slidesPerRow - (s.params.slidesPerColumn * slidesPerRow - s.slides.length); + for (i = 0; i < s.slides.length; i++) { + slideSize = 0; + var slide = s.slides.eq(i); + if (s.params.slidesPerColumn > 1) { + // Set slides order + var newSlideOrderIndex; + var column, row; + if (s.params.slidesPerColumnFill === 'column') { + column = Math.floor(i / slidesPerColumn); + row = i - column * slidesPerColumn; + if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn-1)) { + if (++row >= slidesPerColumn) { + row = 0; + column++; + } + } + newSlideOrderIndex = column + row * slidesNumberEvenToRows / slidesPerColumn; + slide + .css({ + '-webkit-box-ordinal-group': newSlideOrderIndex, + '-moz-box-ordinal-group': newSlideOrderIndex, + '-ms-flex-order': newSlideOrderIndex, + '-webkit-order': newSlideOrderIndex, + 'order': newSlideOrderIndex + }); + } + else { + row = Math.floor(i / slidesPerRow); + column = i - row * slidesPerRow; + } + slide + .css({ + 'margin-top': (row !== 0 && s.params.spaceBetween) && (s.params.spaceBetween + 'px') + }) + .attr('data-swiper-column', column) + .attr('data-swiper-row', row); - message = message + '\nhttp://errors.angularjs.org/1.3.13/' + - (module ? module + '/' : '') + code; - for (i = 2; i < arguments.length; i++) { - message = message + (i == 2 ? '?' : '&') + 'p' + (i - 2) + '=' + - encodeURIComponent(toDebugString(arguments[i])); - } - return new ErrorConstructor(message); - }; -} + } + if (slide.css('display') === 'none') continue; + if (s.params.slidesPerView === 'auto') { + slideSize = isH() ? slide.outerWidth(true) : slide.outerHeight(true); + if (s.params.roundLengths) slideSize = round(slideSize); + } + else { + slideSize = (s.size - (s.params.slidesPerView - 1) * spaceBetween) / s.params.slidesPerView; + if (s.params.roundLengths) slideSize = round(slideSize); -/* We need to tell jshint what variables are being exported */ -/* global angular: true, - msie: true, - jqLite: true, - jQuery: true, - slice: true, - splice: true, - push: true, - toString: true, - ngMinErr: true, - angularModule: true, - uid: true, - REGEX_STRING_REGEXP: true, - VALIDITY_STATE_PROPERTY: true, + if (isH()) { + s.slides[i].style.width = slideSize + 'px'; + } + else { + s.slides[i].style.height = slideSize + 'px'; + } + } + s.slides[i].swiperSlideSize = slideSize; + s.slidesSizesGrid.push(slideSize); - lowercase: true, - uppercase: true, - manualLowercase: true, - manualUppercase: true, - nodeName_: true, - isArrayLike: true, - forEach: true, - sortedKeys: true, - forEachSorted: true, - reverseParams: true, - nextUid: true, - setHashKey: true, - extend: true, - int: true, - inherit: true, - noop: true, - identity: true, - valueFn: true, - isUndefined: true, - isDefined: true, - isObject: true, - isString: true, - isNumber: true, - isDate: true, - isArray: true, - isFunction: true, - isRegExp: true, - isWindow: true, - isScope: true, - isFile: true, - isFormData: true, - isBlob: true, - isBoolean: true, - isPromiseLike: true, - trim: true, - escapeForRegexp: true, - isElement: true, - makeMap: true, - includes: true, - arrayRemove: true, - copy: true, - shallowCopy: true, - equals: true, - csp: true, - concat: true, - sliceArgs: true, - bind: true, - toJsonReplacer: true, - toJson: true, - fromJson: true, - startingTag: true, - tryDecodeURIComponent: true, - parseKeyValue: true, - toKeyValue: true, - encodeUriSegment: true, - encodeUriQuery: true, - angularInit: true, - bootstrap: true, - getTestability: true, - snake_case: true, - bindJQuery: true, - assertArg: true, - assertArgFn: true, - assertNotHasOwnProperty: true, - getter: true, - getBlockNodes: true, - hasOwnProperty: true, - createMap: true, - NODE_TYPE_ELEMENT: true, - NODE_TYPE_TEXT: true, - NODE_TYPE_COMMENT: true, - NODE_TYPE_DOCUMENT: true, - NODE_TYPE_DOCUMENT_FRAGMENT: true, -*/ + if (s.params.centeredSlides) { + slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween; + if (i === 0) slidePosition = slidePosition - s.size / 2 - spaceBetween; + if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0; + if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition); + s.slidesGrid.push(slidePosition); + } + else { + if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition); + s.slidesGrid.push(slidePosition); + slidePosition = slidePosition + slideSize + spaceBetween; + } -//////////////////////////////////// + s.virtualSize += slideSize + spaceBetween; -/** - * @ngdoc module - * @name ng - * @module ng - * @description - * - * # ng (core module) - * The ng module is loaded by default when an AngularJS application is started. The module itself - * contains the essential components for an AngularJS application to function. The table below - * lists a high level breakdown of each of the services/factories, filters, directives and testing - * components available within this core module. - * - * <div doc-module-components="ng"></div> - */ + prevSlideSize = slideSize; -var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; + index ++; + } + s.virtualSize = Math.max(s.virtualSize, s.size) + s.params.slidesOffsetAfter; + var newSlidesGrid; -// The name of a form control's ValidityState property. -// This is used so that it's possible for internal tests to create mock ValidityStates. -var VALIDITY_STATE_PROPERTY = 'validity'; + if ( + s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) { + s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); + } + if (!s.support.flexbox || s.params.setWrapperSize) { + if (isH()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); + else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'}); + } -/** - * @ngdoc function - * @name angular.lowercase - * @module ng - * @kind function - * - * @description Converts the specified string to lowercase. - * @param {string} string String to be converted to lowercase. - * @returns {string} Lowercased string. - */ -var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; -var hasOwnProperty = Object.prototype.hasOwnProperty; - -/** - * @ngdoc function - * @name angular.uppercase - * @module ng - * @kind function - * - * @description Converts the specified string to uppercase. - * @param {string} string String to be converted to uppercase. - * @returns {string} Uppercased string. - */ -var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;}; + if (s.params.slidesPerColumn > 1) { + s.virtualSize = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows; + s.virtualSize = Math.ceil(s.virtualSize / s.params.slidesPerColumn) - s.params.spaceBetween; + s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); + if (s.params.centeredSlides) { + newSlidesGrid = []; + for (i = 0; i < s.snapGrid.length; i++) { + if (s.snapGrid[i] < s.virtualSize + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]); + } + s.snapGrid = newSlidesGrid; + } + } + // Remove last grid elements depending on width + if (!s.params.centeredSlides) { + newSlidesGrid = []; + for (i = 0; i < s.snapGrid.length; i++) { + if (s.snapGrid[i] <= s.virtualSize - s.size) { + newSlidesGrid.push(s.snapGrid[i]); + } + } + s.snapGrid = newSlidesGrid; + if (Math.floor(s.virtualSize - s.size) > Math.floor(s.snapGrid[s.snapGrid.length - 1])) { + s.snapGrid.push(s.virtualSize - s.size); + } + } + if (s.snapGrid.length === 0) s.snapGrid = [0]; -var manualLowercase = function(s) { - /* jshint bitwise: false */ - return isString(s) - ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) - : s; -}; -var manualUppercase = function(s) { - /* jshint bitwise: false */ - return isString(s) - ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) - : s; -}; + if (s.params.spaceBetween !== 0) { + if (isH()) { + if (s.rtl) s.slides.css({marginLeft: spaceBetween + 'px'}); + else s.slides.css({marginRight: spaceBetween + 'px'}); + } + else s.slides.css({marginBottom: spaceBetween + 'px'}); + } + if (s.params.watchSlidesProgress) { + s.updateSlidesOffset(); + } + }; + s.updateSlidesOffset = function () { + for (var i = 0; i < s.slides.length; i++) { + s.slides[i].swiperSlideOffset = isH() ? s.slides[i].offsetLeft : s.slides[i].offsetTop; + } + }; + /*========================= + Slider/slides progress + ===========================*/ + s.updateSlidesProgress = function (translate) { + if (typeof translate === 'undefined') { + translate = s.translate || 0; + } + if (s.slides.length === 0) return; + if (typeof s.slides[0].swiperSlideOffset === 'undefined') s.updateSlidesOffset(); + + var offsetCenter = -translate; + if (s.rtl) offsetCenter = translate; + + // Visible Slides + s.slides.removeClass(s.params.slideVisibleClass); + for (var i = 0; i < s.slides.length; i++) { + var slide = s.slides[i]; + var slideProgress = (offsetCenter - slide.swiperSlideOffset) / (slide.swiperSlideSize + s.params.spaceBetween); + if (s.params.watchSlidesVisibility) { + var slideBefore = -(offsetCenter - slide.swiperSlideOffset); + var slideAfter = slideBefore + s.slidesSizesGrid[i]; + var isVisible = + (slideBefore >= 0 && slideBefore < s.size) || + (slideAfter > 0 && slideAfter <= s.size) || + (slideBefore <= 0 && slideAfter >= s.size); + if (isVisible) { + s.slides.eq(i).addClass(s.params.slideVisibleClass); + } + } + slide.progress = s.rtl ? -slideProgress : slideProgress; + } + }; + s.updateProgress = function (translate) { + if (typeof translate === 'undefined') { + translate = s.translate || 0; + } + var translatesDiff = s.maxTranslate() - s.minTranslate(); + var wasBeginning = s.isBeginning; + var wasEnd = s.isEnd; + if (translatesDiff === 0) { + s.progress = 0; + s.isBeginning = s.isEnd = true; + } + else { + s.progress = (translate - s.minTranslate()) / (translatesDiff); + s.isBeginning = s.progress <= 0; + s.isEnd = s.progress >= 1; + } + if (s.isBeginning && !wasBeginning) s.emit('onReachBeginning', s); + if (s.isEnd && !wasEnd) s.emit('onReachEnd', s); -// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish -// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods -// with correct but slower alternatives. -if ('i' !== 'I'.toLowerCase()) { - lowercase = manualLowercase; - uppercase = manualUppercase; -} + if (s.params.watchSlidesProgress) s.updateSlidesProgress(translate); + s.emit('onProgress', s, s.progress); + }; + s.updateActiveIndex = function () { + var translate = s.rtl ? s.translate : -s.translate; + var newActiveIndex, i, snapIndex; + for (i = 0; i < s.slidesGrid.length; i ++) { + if (typeof s.slidesGrid[i + 1] !== 'undefined') { + if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1] - (s.slidesGrid[i + 1] - s.slidesGrid[i]) / 2) { + newActiveIndex = i; + } + else if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1]) { + newActiveIndex = i + 1; + } + } + else { + if (translate >= s.slidesGrid[i]) { + newActiveIndex = i; + } + } + } + // Normalize slideIndex + if (newActiveIndex < 0 || typeof newActiveIndex === 'undefined') newActiveIndex = 0; + // for (i = 0; i < s.slidesGrid.length; i++) { + // if (- translate >= s.slidesGrid[i]) { + // newActiveIndex = i; + // } + // } + snapIndex = Math.floor(newActiveIndex / s.params.slidesPerGroup); + if (snapIndex >= s.snapGrid.length) snapIndex = s.snapGrid.length - 1; + + if (newActiveIndex === s.activeIndex) { + return; + } + s.snapIndex = snapIndex; + s.previousIndex = s.activeIndex; + s.activeIndex = newActiveIndex; + s.updateClasses(); + }; + /*========================= + Classes + ===========================*/ + s.updateClasses = function () { + s.slides.removeClass(s.params.slideActiveClass + ' ' + s.params.slideNextClass + ' ' + s.params.slidePrevClass); + var activeSlide = s.slides.eq(s.activeIndex); + // Active classes + activeSlide.addClass(s.params.slideActiveClass); + activeSlide.next('.' + s.params.slideClass).addClass(s.params.slideNextClass); + activeSlide.prev('.' + s.params.slideClass).addClass(s.params.slidePrevClass); + + // Pagination + if (s.bullets && s.bullets.length > 0) { + s.bullets.removeClass(s.params.bulletActiveClass); + var bulletIndex; + if (s.params.loop) { + bulletIndex = Math.ceil(s.activeIndex - s.loopedSlides)/s.params.slidesPerGroup; + if (bulletIndex > s.slides.length - 1 - s.loopedSlides * 2) { + bulletIndex = bulletIndex - (s.slides.length - s.loopedSlides * 2); + } + if (bulletIndex > s.bullets.length - 1) bulletIndex = bulletIndex - s.bullets.length; + } + else { + if (typeof s.snapIndex !== 'undefined') { + bulletIndex = s.snapIndex; + } + else { + bulletIndex = s.activeIndex || 0; + } + } + if (s.paginationContainer.length > 1) { + s.bullets.each(function () { + if ($(this).index() === bulletIndex) $(this).addClass(s.params.bulletActiveClass); + }); + } + else { + s.bullets.eq(bulletIndex).addClass(s.params.bulletActiveClass); + } + } -var - msie, // holds major version number for IE, or NaN if UA is not IE. - jqLite, // delay binding since jQuery could be loaded after us. - jQuery, // delay binding - slice = [].slice, - splice = [].splice, - push = [].push, - toString = Object.prototype.toString, - ngMinErr = minErr('ng'), + // Next/active buttons + if (!s.params.loop) { + if (s.params.prevButton) { + if (s.isBeginning) { + $(s.params.prevButton).addClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.disable($(s.params.prevButton)); + } + else { + $(s.params.prevButton).removeClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.enable($(s.params.prevButton)); + } + } + if (s.params.nextButton) { + if (s.isEnd) { + $(s.params.nextButton).addClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.disable($(s.params.nextButton)); + } + else { + $(s.params.nextButton).removeClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.enable($(s.params.nextButton)); + } + } + } + }; - /** @name angular */ - angular = window.angular || (window.angular = {}), - angularModule, - uid = 0; + /*========================= + Pagination + ===========================*/ + s.updatePagination = function () { + if (!s.params.pagination) return; + if (s.paginationContainer && s.paginationContainer.length > 0) { + var bulletsHTML = ''; + var numberOfBullets = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length; + for (var i = 0; i < numberOfBullets; i++) { + if (s.params.paginationBulletRender) { + bulletsHTML += s.params.paginationBulletRender(i, s.params.bulletClass); + } + else { + bulletsHTML += '<' + s.params.paginationElement+' class="' + s.params.bulletClass + '"></' + s.params.paginationElement + '>'; + } + } + s.paginationContainer.html(bulletsHTML); + s.bullets = s.paginationContainer.find('.' + s.params.bulletClass); + if (s.params.paginationClickable && s.params.a11y && s.a11y) { + s.a11y.initPagination(); + } + } + }; + /*========================= + Common update method + ===========================*/ + s.update = function (updateTranslate) { + s.updateContainerSize(); + s.updateSlidesSize(); + s.updateProgress(); + s.updatePagination(); + s.updateClasses(); + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.set(); + } + function forceSetTranslate() { + newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate()); + s.setWrapperTranslate(newTranslate); + s.updateActiveIndex(); + s.updateClasses(); + } + if (updateTranslate) { + var translated, newTranslate; + if (s.controller && s.controller.spline) { + s.controller.spline = undefined; + } + if (s.params.freeMode) { + forceSetTranslate(); + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + } + else { + if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) { + translated = s.slideTo(s.slides.length - 1, 0, false, true); + } + else { + translated = s.slideTo(s.activeIndex, 0, false, true); + } + if (!translated) { + forceSetTranslate(); + } + } + } + else if (s.params.autoHeight) { + s.updateAutoHeight(); + } + }; -/** - * documentMode is an IE-only property - * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx - */ -msie = document.documentMode; + /*========================= + Resize Handler + ===========================*/ + s.onResize = function (forceUpdatePagination) { + //Breakpoints + if (s.params.breakpoints) { + s.setBreakpoint(); + } + // Disable locks on resize + var allowSwipeToPrev = s.params.allowSwipeToPrev; + var allowSwipeToNext = s.params.allowSwipeToNext; + s.params.allowSwipeToPrev = s.params.allowSwipeToNext = true; -/** - * @private - * @param {*} obj - * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, - * String ...) - */ -function isArrayLike(obj) { - if (obj == null || isWindow(obj)) { - return false; - } + s.updateContainerSize(); + s.updateSlidesSize(); + if (s.params.slidesPerView === 'auto' || s.params.freeMode || forceUpdatePagination) s.updatePagination(); + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.set(); + } + if (s.controller && s.controller.spline) { + s.controller.spline = undefined; + } + if (s.params.freeMode) { + var newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate()); + s.setWrapperTranslate(newTranslate); + s.updateActiveIndex(); + s.updateClasses(); + + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + } + else { + s.updateClasses(); + if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) { + s.slideTo(s.slides.length - 1, 0, false, true); + } + else { + s.slideTo(s.activeIndex, 0, false, true); + } + } + // Return locks after resize + s.params.allowSwipeToPrev = allowSwipeToPrev; + s.params.allowSwipeToNext = allowSwipeToNext; + }; - var length = obj.length; + /*========================= + Events + ===========================*/ + + //Define Touch Events + var desktopEvents = ['mousedown', 'mousemove', 'mouseup']; + if (window.navigator.pointerEnabled) desktopEvents = ['pointerdown', 'pointermove', 'pointerup']; + else if (window.navigator.msPointerEnabled) desktopEvents = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp']; + s.touchEvents = { + start : s.support.touch || !s.params.simulateTouch ? 'touchstart' : desktopEvents[0], + move : s.support.touch || !s.params.simulateTouch ? 'touchmove' : desktopEvents[1], + end : s.support.touch || !s.params.simulateTouch ? 'touchend' : desktopEvents[2] + }; - if (obj.nodeType === NODE_TYPE_ELEMENT && length) { - return true; - } - return isString(obj) || isArray(obj) || length === 0 || - typeof length === 'number' && length > 0 && (length - 1) in obj; -} + // WP8 Touch Events Fix + if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) { + (s.params.touchEventsTarget === 'container' ? s.container : s.wrapper).addClass('swiper-wp8-' + s.params.direction); + } -/** - * @ngdoc function - * @name angular.forEach - * @module ng - * @kind function - * - * @description - * Invokes the `iterator` function once for each item in `obj` collection, which can be either an - * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value` - * is the value of an object property or an array element, `key` is the object property key or - * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional. - * - * It is worth noting that `.forEach` does not iterate over inherited properties because it filters - * using the `hasOwnProperty` method. - * - * Unlike ES262's - * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), - * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just - * return the value provided. - * - ```js - var values = {name: 'misko', gender: 'male'}; - var log = []; - angular.forEach(values, function(value, key) { - this.push(key + ': ' + value); - }, log); - expect(log).toEqual(['name: misko', 'gender: male']); - ``` - * - * @param {Object|Array} obj Object to iterate over. - * @param {Function} iterator Iterator function. - * @param {Object=} context Object to become context (`this`) for the iterator function. - * @returns {Object|Array} Reference to `obj`. - */ + // Attach/detach events + s.initEvents = function (detach) { + var actionDom = detach ? 'off' : 'on'; + var action = detach ? 'removeEventListener' : 'addEventListener'; + var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container[0] : s.wrapper[0]; + var target = s.support.touch ? touchEventsTarget : document; -function forEach(obj, iterator, context) { - var key, length; - if (obj) { - if (isFunction(obj)) { - for (key in obj) { - // Need to check if hasOwnProperty exists, - // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function - if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { - iterator.call(context, obj[key], key, obj); - } - } - } else if (isArray(obj) || isArrayLike(obj)) { - var isPrimitive = typeof obj !== 'object'; - for (key = 0, length = obj.length; key < length; key++) { - if (isPrimitive || key in obj) { - iterator.call(context, obj[key], key, obj); - } - } - } else if (obj.forEach && obj.forEach !== forEach) { - obj.forEach(iterator, context, obj); - } else { - for (key in obj) { - if (obj.hasOwnProperty(key)) { - iterator.call(context, obj[key], key, obj); - } - } - } - } - return obj; -} + var moveCapture = s.params.nested ? true : false; -function sortedKeys(obj) { - return Object.keys(obj).sort(); -} + //Touch Events + if (s.browser.ie) { + touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false); + target[action](s.touchEvents.move, s.onTouchMove, moveCapture); + target[action](s.touchEvents.end, s.onTouchEnd, false); + } + else { + if (s.support.touch) { + touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false); + touchEventsTarget[action](s.touchEvents.move, s.onTouchMove, moveCapture); + touchEventsTarget[action](s.touchEvents.end, s.onTouchEnd, false); + } + if (params.simulateTouch && !s.device.ios && !s.device.android) { + touchEventsTarget[action]('mousedown', s.onTouchStart, false); + document[action]('mousemove', s.onTouchMove, moveCapture); + document[action]('mouseup', s.onTouchEnd, false); + } + } + window[action]('resize', s.onResize); -function forEachSorted(obj, iterator, context) { - var keys = sortedKeys(obj); - for (var i = 0; i < keys.length; i++) { - iterator.call(context, obj[keys[i]], keys[i]); - } - return keys; -} + // Next, Prev, Index + if (s.params.nextButton) { + $(s.params.nextButton)[actionDom]('click', s.onClickNext); + if (s.params.a11y && s.a11y) $(s.params.nextButton)[actionDom]('keydown', s.a11y.onEnterKey); + } + if (s.params.prevButton) { + $(s.params.prevButton)[actionDom]('click', s.onClickPrev); + if (s.params.a11y && s.a11y) $(s.params.prevButton)[actionDom]('keydown', s.a11y.onEnterKey); + } + if (s.params.pagination && s.params.paginationClickable) { + $(s.paginationContainer)[actionDom]('click', '.' + s.params.bulletClass, s.onClickIndex); + if (s.params.a11y && s.a11y) $(s.paginationContainer)[actionDom]('keydown', '.' + s.params.bulletClass, s.a11y.onEnterKey); + } + // Prevent Links Clicks + if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[action]('click', s.preventClicks, true); + }; + s.attachEvents = function (detach) { + s.initEvents(); + }; + s.detachEvents = function () { + s.initEvents(true); + }; -/** - * when using forEach the params are value, key, but it is often useful to have key, value. - * @param {function(string, *)} iteratorFn - * @returns {function(*, string)} - */ -function reverseParams(iteratorFn) { - return function(value, key) { iteratorFn(key, value); }; -} + /*========================= + Handle Clicks + ===========================*/ + // Prevent Clicks + s.allowClick = true; + s.preventClicks = function (e) { + if (!s.allowClick) { + if (s.params.preventClicks) e.preventDefault(); + if (s.params.preventClicksPropagation && s.animating) { + e.stopPropagation(); + e.stopImmediatePropagation(); + } + } + }; + // Clicks + s.onClickNext = function (e) { + e.preventDefault(); + if (s.isEnd && !s.params.loop) return; + s.slideNext(); + }; + s.onClickPrev = function (e) { + e.preventDefault(); + if (s.isBeginning && !s.params.loop) return; + s.slidePrev(); + }; + s.onClickIndex = function (e) { + e.preventDefault(); + var index = $(this).index() * s.params.slidesPerGroup; + if (s.params.loop) index = index + s.loopedSlides; + s.slideTo(index); + }; -/** - * A consistent way of creating unique IDs in angular. - * - * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before - * we hit number precision issues in JavaScript. - * - * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M - * - * @returns {number} an unique alpha-numeric string - */ -function nextUid() { - return ++uid; -} + /*========================= + Handle Touches + ===========================*/ + function findElementInEvent(e, selector) { + var el = $(e.target); + if (!el.is(selector)) { + if (typeof selector === 'string') { + el = el.parents(selector); + } + else if (selector.nodeType) { + var found; + el.parents().each(function (index, _el) { + if (_el === selector) found = selector; + }); + if (!found) return undefined; + else return selector; + } + } + if (el.length === 0) { + return undefined; + } + return el[0]; + } + s.updateClickedSlide = function (e) { + var slide = findElementInEvent(e, '.' + s.params.slideClass); + var slideFound = false; + if (slide) { + for (var i = 0; i < s.slides.length; i++) { + if (s.slides[i] === slide) slideFound = true; + } + } + if (slide && slideFound) { + s.clickedSlide = slide; + s.clickedIndex = $(slide).index(); + } + else { + s.clickedSlide = undefined; + s.clickedIndex = undefined; + return; + } + if (s.params.slideToClickedSlide && s.clickedIndex !== undefined && s.clickedIndex !== s.activeIndex) { + var slideToIndex = s.clickedIndex, + realIndex, + duplicatedSlides; + if (s.params.loop) { + if (s.animating) return; + realIndex = $(s.clickedSlide).attr('data-swiper-slide-index'); + if (s.params.centeredSlides) { + if ((slideToIndex < s.loopedSlides - s.params.slidesPerView/2) || (slideToIndex > s.slides.length - s.loopedSlides + s.params.slidesPerView/2)) { + s.fixLoop(); + slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index(); + setTimeout(function () { + s.slideTo(slideToIndex); + }, 0); + } + else { + s.slideTo(slideToIndex); + } + } + else { + if (slideToIndex > s.slides.length - s.params.slidesPerView) { + s.fixLoop(); + slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index(); + setTimeout(function () { + s.slideTo(slideToIndex); + }, 0); + } + else { + s.slideTo(slideToIndex); + } + } + } + else { + s.slideTo(slideToIndex); + } + } + }; -/** - * Set or clear the hashkey for an object. - * @param obj object - * @param h the hashkey (!truthy to delete the hashkey) - */ -function setHashKey(obj, h) { - if (h) { - obj.$$hashKey = h; - } else { - delete obj.$$hashKey; - } -} + var isTouched, + isMoved, + allowTouchCallbacks, + touchStartTime, + isScrolling, + currentTranslate, + startTranslate, + allowThresholdMove, + // Form elements to match + formElements = 'input, select, textarea, button', + // Last click time + lastClickTime = Date.now(), clickTimeout, + //Velocities + velocities = [], + allowMomentumBounce; + + // Animating Flag + s.animating = false; + + // Touches information + s.touches = { + startX: 0, + startY: 0, + currentX: 0, + currentY: 0, + diff: 0 + }; -/** - * @ngdoc function - * @name angular.extend - * @module ng - * @kind function - * - * @description - * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) - * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so - * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. - * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy). - * - * @param {Object} dst Destination object. - * @param {...Object} src Source object(s). - * @returns {Object} Reference to `dst`. - */ -function extend(dst) { - var h = dst.$$hashKey; + // Touch handlers + var isTouchEvent, startMoving; + s.onTouchStart = function (e) { + if (e.originalEvent) e = e.originalEvent; + isTouchEvent = e.type === 'touchstart'; + if (!isTouchEvent && 'which' in e && e.which === 3) return; + if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) { + s.allowClick = true; + return; + } + if (s.params.swipeHandler) { + if (!findElementInEvent(e, s.params.swipeHandler)) return; + } - for (var i = 1, ii = arguments.length; i < ii; i++) { - var obj = arguments[i]; - if (obj) { - var keys = Object.keys(obj); - for (var j = 0, jj = keys.length; j < jj; j++) { - var key = keys[j]; - dst[key] = obj[key]; - } - } - } + var startX = s.touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; + var startY = s.touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY; - setHashKey(dst, h); - return dst; -} + // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore + if(s.device.ios && s.params.iOSEdgeSwipeDetection && startX <= s.params.iOSEdgeSwipeThreshold) { + return; + } -function int(str) { - return parseInt(str, 10); -} + isTouched = true; + isMoved = false; + allowTouchCallbacks = true; + isScrolling = undefined; + startMoving = undefined; + s.touches.startX = startX; + s.touches.startY = startY; + touchStartTime = Date.now(); + s.allowClick = true; + s.updateContainerSize(); + s.swipeDirection = undefined; + if (s.params.threshold > 0) allowThresholdMove = false; + if (e.type !== 'touchstart') { + var preventDefault = true; + if ($(e.target).is(formElements)) preventDefault = false; + if (document.activeElement && $(document.activeElement).is(formElements)) { + document.activeElement.blur(); + } + if (preventDefault) { + e.preventDefault(); + } + } + s.emit('onTouchStart', s, e); + }; + s.onTouchMove = function (e) { + if (e.originalEvent) e = e.originalEvent; + if (isTouchEvent && e.type === 'mousemove') return; + if (e.preventedByNestedSwiper) return; + if (s.params.onlyExternal) { + // isMoved = true; + s.allowClick = false; + if (isTouched) { + s.touches.startX = s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; + s.touches.startY = s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; + touchStartTime = Date.now(); + } + return; + } + if (isTouchEvent && document.activeElement) { + if (e.target === document.activeElement && $(e.target).is(formElements)) { + isMoved = true; + s.allowClick = false; + return; + } + } + if (allowTouchCallbacks) { + s.emit('onTouchMove', s, e); + } + if (e.targetTouches && e.targetTouches.length > 1) return; -function inherit(parent, extra) { - return extend(Object.create(parent), extra); -} + s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; + s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; -/** - * @ngdoc function - * @name angular.noop - * @module ng - * @kind function - * - * @description - * A function that performs no operations. This function can be useful when writing code in the - * functional style. - ```js - function foo(callback) { - var result = calculateResult(); - (callback || angular.noop)(result); - } - ``` - */ -function noop() {} -noop.$inject = []; + if (typeof isScrolling === 'undefined') { + var touchAngle = Math.atan2(Math.abs(s.touches.currentY - s.touches.startY), Math.abs(s.touches.currentX - s.touches.startX)) * 180 / Math.PI; + isScrolling = isH() ? touchAngle > s.params.touchAngle : (90 - touchAngle > s.params.touchAngle); + } + if (isScrolling) { + s.emit('onTouchMoveOpposite', s, e); + } + if (typeof startMoving === 'undefined' && s.browser.ieTouch) { + if (s.touches.currentX !== s.touches.startX || s.touches.currentY !== s.touches.startY) { + startMoving = true; + } + } + if (!isTouched) return; + if (isScrolling) { + isTouched = false; + return; + } + if (!startMoving && s.browser.ieTouch) { + return; + } + s.allowClick = false; + s.emit('onSliderMove', s, e); + e.preventDefault(); + if (s.params.touchMoveStopPropagation && !s.params.nested) { + e.stopPropagation(); + } + if (!isMoved) { + if (params.loop) { + s.fixLoop(); + } + startTranslate = s.getWrapperTranslate(); + s.setWrapperTransition(0); + if (s.animating) { + s.wrapper.trigger('webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd'); + } + if (s.params.autoplay && s.autoplaying) { + if (s.params.autoplayDisableOnInteraction) { + s.stopAutoplay(); + } + else { + s.pauseAutoplay(); + } + } + allowMomentumBounce = false; + //Grab Cursor + if (s.params.grabCursor) { + s.container[0].style.cursor = 'move'; + s.container[0].style.cursor = '-webkit-grabbing'; + s.container[0].style.cursor = '-moz-grabbin'; + s.container[0].style.cursor = 'grabbing'; + } + } + isMoved = true; -/** - * @ngdoc function - * @name angular.identity - * @module ng - * @kind function - * - * @description - * A function that returns its first argument. This function is useful when writing code in the - * functional style. - * - ```js - function transformer(transformationFn, value) { - return (transformationFn || angular.identity)(value); - }; - ``` - * @param {*} value to be returned. - * @returns {*} the value passed in. - */ -function identity($) {return $;} -identity.$inject = []; + var diff = s.touches.diff = isH() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY; + diff = diff * s.params.touchRatio; + if (s.rtl) diff = -diff; -function valueFn(value) {return function() {return value;};} + s.swipeDirection = diff > 0 ? 'prev' : 'next'; + currentTranslate = diff + startTranslate; -/** - * @ngdoc function - * @name angular.isUndefined - * @module ng - * @kind function - * - * @description - * Determines if a reference is undefined. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is undefined. - */ -function isUndefined(value) {return typeof value === 'undefined';} + var disableParentSwiper = true; + if ((diff > 0 && currentTranslate > s.minTranslate())) { + disableParentSwiper = false; + if (s.params.resistance) currentTranslate = s.minTranslate() - 1 + Math.pow(-s.minTranslate() + startTranslate + diff, s.params.resistanceRatio); + } + else if (diff < 0 && currentTranslate < s.maxTranslate()) { + disableParentSwiper = false; + if (s.params.resistance) currentTranslate = s.maxTranslate() + 1 - Math.pow(s.maxTranslate() - startTranslate - diff, s.params.resistanceRatio); + } + if (disableParentSwiper) { + e.preventedByNestedSwiper = true; + } -/** - * @ngdoc function - * @name angular.isDefined - * @module ng - * @kind function - * - * @description - * Determines if a reference is defined. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is defined. - */ -function isDefined(value) {return typeof value !== 'undefined';} + // Directions locks + if (!s.params.allowSwipeToNext && s.swipeDirection === 'next' && currentTranslate < startTranslate) { + currentTranslate = startTranslate; + } + if (!s.params.allowSwipeToPrev && s.swipeDirection === 'prev' && currentTranslate > startTranslate) { + currentTranslate = startTranslate; + } + if (!s.params.followFinger) return; + + // Threshold + if (s.params.threshold > 0) { + if (Math.abs(diff) > s.params.threshold || allowThresholdMove) { + if (!allowThresholdMove) { + allowThresholdMove = true; + s.touches.startX = s.touches.currentX; + s.touches.startY = s.touches.currentY; + currentTranslate = startTranslate; + s.touches.diff = isH() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY; + return; + } + } + else { + currentTranslate = startTranslate; + return; + } + } + // Update active index in free mode + if (s.params.freeMode || s.params.watchSlidesProgress) { + s.updateActiveIndex(); + } + if (s.params.freeMode) { + //Velocity + if (velocities.length === 0) { + velocities.push({ + position: s.touches[isH() ? 'startX' : 'startY'], + time: touchStartTime + }); + } + velocities.push({ + position: s.touches[isH() ? 'currentX' : 'currentY'], + time: (new window.Date()).getTime() + }); + } + // Update progress + s.updateProgress(currentTranslate); + // Update translate + s.setWrapperTranslate(currentTranslate); + }; + s.onTouchEnd = function (e) { + if (e.originalEvent) e = e.originalEvent; + if (allowTouchCallbacks) { + s.emit('onTouchEnd', s, e); + } + allowTouchCallbacks = false; + if (!isTouched) return; + //Return Grab Cursor + if (s.params.grabCursor && isMoved && isTouched) { + s.container[0].style.cursor = 'move'; + s.container[0].style.cursor = '-webkit-grab'; + s.container[0].style.cursor = '-moz-grab'; + s.container[0].style.cursor = 'grab'; + } -/** - * @ngdoc function - * @name angular.isObject - * @module ng - * @kind function - * - * @description - * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not - * considered to be objects. Note that JavaScript arrays are objects. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is an `Object` but not `null`. - */ -function isObject(value) { - // http://jsperf.com/isobject4 - return value !== null && typeof value === 'object'; -} + // Time diff + var touchEndTime = Date.now(); + var timeDiff = touchEndTime - touchStartTime; + + // Tap, doubleTap, Click + if (s.allowClick) { + s.updateClickedSlide(e); + s.emit('onTap', s, e); + if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) { + if (clickTimeout) clearTimeout(clickTimeout); + clickTimeout = setTimeout(function () { + if (!s) return; + if (s.params.paginationHide && s.paginationContainer.length > 0 && !$(e.target).hasClass(s.params.bulletClass)) { + s.paginationContainer.toggleClass(s.params.paginationHiddenClass); + } + s.emit('onClick', s, e); + }, 300); + } + if (timeDiff < 300 && (touchEndTime - lastClickTime) < 300) { + if (clickTimeout) clearTimeout(clickTimeout); + s.emit('onDoubleTap', s, e); + } + } -/** - * @ngdoc function - * @name angular.isString - * @module ng - * @kind function - * - * @description - * Determines if a reference is a `String`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `String`. - */ -function isString(value) {return typeof value === 'string';} + lastClickTime = Date.now(); + setTimeout(function () { + if (s) s.allowClick = true; + }, 0); + if (!isTouched || !isMoved || !s.swipeDirection || s.touches.diff === 0 || currentTranslate === startTranslate) { + isTouched = isMoved = false; + return; + } + isTouched = isMoved = false; -/** - * @ngdoc function - * @name angular.isNumber - * @module ng - * @kind function - * - * @description - * Determines if a reference is a `Number`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Number`. - */ -function isNumber(value) {return typeof value === 'number';} + var currentPos; + if (s.params.followFinger) { + currentPos = s.rtl ? s.translate : -s.translate; + } + else { + currentPos = -currentTranslate; + } + if (s.params.freeMode) { + if (currentPos < -s.minTranslate()) { + s.slideTo(s.activeIndex); + return; + } + else if (currentPos > -s.maxTranslate()) { + if (s.slides.length < s.snapGrid.length) { + s.slideTo(s.snapGrid.length - 1); + } + else { + s.slideTo(s.slides.length - 1); + } + return; + } + if (s.params.freeModeMomentum) { + if (velocities.length > 1) { + var lastMoveEvent = velocities.pop(), velocityEvent = velocities.pop(); + + var distance = lastMoveEvent.position - velocityEvent.position; + var time = lastMoveEvent.time - velocityEvent.time; + s.velocity = distance / time; + s.velocity = s.velocity / 2; + if (Math.abs(s.velocity) < s.params.freeModeMinimumVelocity) { + s.velocity = 0; + } + // this implies that the user stopped moving a finger then released. + // There would be no events with distance zero, so the last event is stale. + if (time > 150 || (new window.Date().getTime() - lastMoveEvent.time) > 300) { + s.velocity = 0; + } + } else { + s.velocity = 0; + } -/** - * @ngdoc function - * @name angular.isDate - * @module ng - * @kind function - * - * @description - * Determines if a value is a date. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Date`. - */ -function isDate(value) { - return toString.call(value) === '[object Date]'; -} + velocities.length = 0; + var momentumDuration = 1000 * s.params.freeModeMomentumRatio; + var momentumDistance = s.velocity * momentumDuration; + + var newPosition = s.translate + momentumDistance; + if (s.rtl) newPosition = - newPosition; + var doBounce = false; + var afterBouncePosition; + var bounceAmount = Math.abs(s.velocity) * 20 * s.params.freeModeMomentumBounceRatio; + if (newPosition < s.maxTranslate()) { + if (s.params.freeModeMomentumBounce) { + if (newPosition + s.maxTranslate() < -bounceAmount) { + newPosition = s.maxTranslate() - bounceAmount; + } + afterBouncePosition = s.maxTranslate(); + doBounce = true; + allowMomentumBounce = true; + } + else { + newPosition = s.maxTranslate(); + } + } + else if (newPosition > s.minTranslate()) { + if (s.params.freeModeMomentumBounce) { + if (newPosition - s.minTranslate() > bounceAmount) { + newPosition = s.minTranslate() + bounceAmount; + } + afterBouncePosition = s.minTranslate(); + doBounce = true; + allowMomentumBounce = true; + } + else { + newPosition = s.minTranslate(); + } + } + else if (s.params.freeModeSticky) { + var j = 0, + nextSlide; + for (j = 0; j < s.snapGrid.length; j += 1) { + if (s.snapGrid[j] > -newPosition) { + nextSlide = j; + break; + } + + } + if (Math.abs(s.snapGrid[nextSlide] - newPosition) < Math.abs(s.snapGrid[nextSlide - 1] - newPosition) || s.swipeDirection === 'next') { + newPosition = s.snapGrid[nextSlide]; + } else { + newPosition = s.snapGrid[nextSlide - 1]; + } + if (!s.rtl) newPosition = - newPosition; + } + //Fix duration + if (s.velocity !== 0) { + if (s.rtl) { + momentumDuration = Math.abs((-newPosition - s.translate) / s.velocity); + } + else { + momentumDuration = Math.abs((newPosition - s.translate) / s.velocity); + } + } + else if (s.params.freeModeSticky) { + s.slideReset(); + return; + } + if (s.params.freeModeMomentumBounce && doBounce) { + s.updateProgress(afterBouncePosition); + s.setWrapperTransition(momentumDuration); + s.setWrapperTranslate(newPosition); + s.onTransitionStart(); + s.animating = true; + s.wrapper.transitionEnd(function () { + if (!s || !allowMomentumBounce) return; + s.emit('onMomentumBounce', s); + + s.setWrapperTransition(s.params.speed); + s.setWrapperTranslate(afterBouncePosition); + s.wrapper.transitionEnd(function () { + if (!s) return; + s.onTransitionEnd(); + }); + }); + } else if (s.velocity) { + s.updateProgress(newPosition); + s.setWrapperTransition(momentumDuration); + s.setWrapperTranslate(newPosition); + s.onTransitionStart(); + if (!s.animating) { + s.animating = true; + s.wrapper.transitionEnd(function () { + if (!s) return; + s.onTransitionEnd(); + }); + } -/** - * @ngdoc function - * @name angular.isArray - * @module ng - * @kind function - * - * @description - * Determines if a reference is an `Array`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is an `Array`. - */ -var isArray = Array.isArray; + } else { + s.updateProgress(newPosition); + } -/** - * @ngdoc function - * @name angular.isFunction - * @module ng - * @kind function - * - * @description - * Determines if a reference is a `Function`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Function`. - */ -function isFunction(value) {return typeof value === 'function';} + s.updateActiveIndex(); + } + if (!s.params.freeModeMomentum || timeDiff >= s.params.longSwipesMs) { + s.updateProgress(); + s.updateActiveIndex(); + } + return; + } + // Find current slide + var i, stopIndex = 0, groupSize = s.slidesSizesGrid[0]; + for (i = 0; i < s.slidesGrid.length; i += s.params.slidesPerGroup) { + if (typeof s.slidesGrid[i + s.params.slidesPerGroup] !== 'undefined') { + if (currentPos >= s.slidesGrid[i] && currentPos < s.slidesGrid[i + s.params.slidesPerGroup]) { + stopIndex = i; + groupSize = s.slidesGrid[i + s.params.slidesPerGroup] - s.slidesGrid[i]; + } + } + else { + if (currentPos >= s.slidesGrid[i]) { + stopIndex = i; + groupSize = s.slidesGrid[s.slidesGrid.length - 1] - s.slidesGrid[s.slidesGrid.length - 2]; + } + } + } -/** - * Determines if a value is a regular expression object. - * - * @private - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `RegExp`. - */ -function isRegExp(value) { - return toString.call(value) === '[object RegExp]'; -} + // Find current slide size + var ratio = (currentPos - s.slidesGrid[stopIndex]) / groupSize; + if (timeDiff > s.params.longSwipesMs) { + // Long touches + if (!s.params.longSwipes) { + s.slideTo(s.activeIndex); + return; + } + if (s.swipeDirection === 'next') { + if (ratio >= s.params.longSwipesRatio) s.slideTo(stopIndex + s.params.slidesPerGroup); + else s.slideTo(stopIndex); -/** - * Checks if `obj` is a window object. - * - * @private - * @param {*} obj Object to check - * @returns {boolean} True if `obj` is a window obj. - */ -function isWindow(obj) { - return obj && obj.window === obj; -} + } + if (s.swipeDirection === 'prev') { + if (ratio > (1 - s.params.longSwipesRatio)) s.slideTo(stopIndex + s.params.slidesPerGroup); + else s.slideTo(stopIndex); + } + } + else { + // Short swipes + if (!s.params.shortSwipes) { + s.slideTo(s.activeIndex); + return; + } + if (s.swipeDirection === 'next') { + s.slideTo(stopIndex + s.params.slidesPerGroup); + } + if (s.swipeDirection === 'prev') { + s.slideTo(stopIndex); + } + } + }; + /*========================= + Transitions + ===========================*/ + s._slideTo = function (slideIndex, speed) { + return s.slideTo(slideIndex, speed, true, true); + }; + s.slideTo = function (slideIndex, speed, runCallbacks, internal) { + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (typeof slideIndex === 'undefined') slideIndex = 0; + if (slideIndex < 0) slideIndex = 0; + s.snapIndex = Math.floor(slideIndex / s.params.slidesPerGroup); + if (s.snapIndex >= s.snapGrid.length) s.snapIndex = s.snapGrid.length - 1; + + var translate = - s.snapGrid[s.snapIndex]; + // Stop autoplay + if (s.params.autoplay && s.autoplaying) { + if (internal || !s.params.autoplayDisableOnInteraction) { + s.pauseAutoplay(speed); + } + else { + s.stopAutoplay(); + } + } + // Update progress + s.updateProgress(translate); -function isScope(obj) { - return obj && obj.$evalAsync && obj.$watch; -} + // Normalize slideIndex + for (var i = 0; i < s.slidesGrid.length; i++) { + if (- Math.floor(translate * 100) >= Math.floor(s.slidesGrid[i] * 100)) { + slideIndex = i; + } + } + // Directions locks + if (!s.params.allowSwipeToNext && translate < s.translate && translate < s.minTranslate()) { + return false; + } + if (!s.params.allowSwipeToPrev && translate > s.translate && translate > s.maxTranslate()) { + if ((s.activeIndex || 0) !== slideIndex ) return false; + } -function isFile(obj) { - return toString.call(obj) === '[object File]'; -} + // Update Index + if (typeof speed === 'undefined') speed = s.params.speed; + s.previousIndex = s.activeIndex || 0; + s.activeIndex = slideIndex; + if ((s.rtl && -translate === s.translate) || (!s.rtl && translate === s.translate)) { + // Update Height + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + s.updateClasses(); + if (s.params.effect !== 'slide') { + s.setWrapperTranslate(translate); + } + return false; + } + s.updateClasses(); + s.onTransitionStart(runCallbacks); -function isFormData(obj) { - return toString.call(obj) === '[object FormData]'; -} + if (speed === 0) { + s.setWrapperTranslate(translate); + s.setWrapperTransition(0); + s.onTransitionEnd(runCallbacks); + } + else { + s.setWrapperTranslate(translate); + s.setWrapperTransition(speed); + if (!s.animating) { + s.animating = true; + s.wrapper.transitionEnd(function () { + if (!s) return; + s.onTransitionEnd(runCallbacks); + }); + } + } -function isBlob(obj) { - return toString.call(obj) === '[object Blob]'; -} + return true; + }; + s.onTransitionStart = function (runCallbacks) { + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + if (s.lazy) s.lazy.onTransitionStart(); + if (runCallbacks) { + s.emit('onTransitionStart', s); + if (s.activeIndex !== s.previousIndex) { + s.emit('onSlideChangeStart', s); + if (s.activeIndex > s.previousIndex) { + s.emit('onSlideNextStart', s); + } + else { + s.emit('onSlidePrevStart', s); + } + } -function isBoolean(value) { - return typeof value === 'boolean'; -} + } + }; + s.onTransitionEnd = function (runCallbacks) { + s.animating = false; + s.setWrapperTransition(0); + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (s.lazy) s.lazy.onTransitionEnd(); + if (runCallbacks) { + s.emit('onTransitionEnd', s); + if (s.activeIndex !== s.previousIndex) { + s.emit('onSlideChangeEnd', s); + if (s.activeIndex > s.previousIndex) { + s.emit('onSlideNextEnd', s); + } + else { + s.emit('onSlidePrevEnd', s); + } + } + } + if (s.params.hashnav && s.hashnav) { + s.hashnav.setHash(); + } + }; + s.slideNext = function (runCallbacks, speed, internal) { + if (s.params.loop) { + if (s.animating) return false; + s.fixLoop(); + var clientLeft = s.container[0].clientLeft; + return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal); + } + else return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal); + }; + s._slideNext = function (speed) { + return s.slideNext(true, speed, true); + }; + s.slidePrev = function (runCallbacks, speed, internal) { + if (s.params.loop) { + if (s.animating) return false; + s.fixLoop(); + var clientLeft = s.container[0].clientLeft; + return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal); + } + else return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal); + }; + s._slidePrev = function (speed) { + return s.slidePrev(true, speed, true); + }; + s.slideReset = function (runCallbacks, speed, internal) { + return s.slideTo(s.activeIndex, speed, runCallbacks); + }; -function isPromiseLike(obj) { - return obj && isFunction(obj.then); -} + /*========================= + Translate/transition helpers + ===========================*/ + s.setWrapperTransition = function (duration, byController) { + s.wrapper.transition(duration); + if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { + s.effects[s.params.effect].setTransition(duration); + } + if (s.params.parallax && s.parallax) { + s.parallax.setTransition(duration); + } + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.setTransition(duration); + } + if (s.params.control && s.controller) { + s.controller.setTransition(duration, byController); + } + s.emit('onSetTransition', s, duration); + }; + s.setWrapperTranslate = function (translate, updateActiveIndex, byController) { + var x = 0, y = 0, z = 0; + if (isH()) { + x = s.rtl ? -translate : translate; + } + else { + y = translate; + } + if (s.params.roundLengths) { + x = round(x); + y = round(y); + } -var trim = function(value) { - return isString(value) ? value.trim() : value; -}; + if (!s.params.virtualTranslate) { + if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)'); + else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)'); + } -// Copied from: -// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021 -// Prereq: s is a string. -var escapeForRegexp = function(s) { - return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1'). - replace(/\x08/g, '\\x08'); -}; + s.translate = isH() ? x : y; + // Check if we need to update progress + var progress; + var translatesDiff = s.maxTranslate() - s.minTranslate(); + if (translatesDiff === 0) { + progress = 0; + } + else { + progress = (translate - s.minTranslate()) / (translatesDiff); + } + if (progress !== s.progress) { + s.updateProgress(translate); + } -/** - * @ngdoc function - * @name angular.isElement - * @module ng - * @kind function - * - * @description - * Determines if a reference is a DOM element (or wrapped jQuery element). - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element). - */ -function isElement(node) { - return !!(node && - (node.nodeName // we are a direct element - || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API -} + if (updateActiveIndex) s.updateActiveIndex(); + if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { + s.effects[s.params.effect].setTranslate(s.translate); + } + if (s.params.parallax && s.parallax) { + s.parallax.setTranslate(s.translate); + } + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.setTranslate(s.translate); + } + if (s.params.control && s.controller) { + s.controller.setTranslate(s.translate, byController); + } + s.emit('onSetTranslate', s, s.translate); + }; -/** - * @param str 'key1,key2,...' - * @returns {object} in the form of {key1:true, key2:true, ...} - */ -function makeMap(str) { - var obj = {}, items = str.split(","), i; - for (i = 0; i < items.length; i++) - obj[items[i]] = true; - return obj; -} + s.getTranslate = function (el, axis) { + var matrix, curTransform, curStyle, transformMatrix; + // automatic axis detection + if (typeof axis === 'undefined') { + axis = 'x'; + } -function nodeName_(element) { - return lowercase(element.nodeName || (element[0] && element[0].nodeName)); -} + if (s.params.virtualTranslate) { + return s.rtl ? -s.translate : s.translate; + } -function includes(array, obj) { - return Array.prototype.indexOf.call(array, obj) != -1; -} + curStyle = window.getComputedStyle(el, null); + if (window.WebKitCSSMatrix) { + curTransform = curStyle.transform || curStyle.webkitTransform; + if (curTransform.split(',').length > 6) { + curTransform = curTransform.split(', ').map(function(a){ + return a.replace(',','.'); + }).join(', '); + } + // Some old versions of Webkit choke when 'none' is passed; pass + // empty string instead in this case + transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform); + } + else { + transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,'); + matrix = transformMatrix.toString().split(','); + } -function arrayRemove(array, value) { - var index = array.indexOf(value); - if (index >= 0) - array.splice(index, 1); - return value; -} + if (axis === 'x') { + //Latest Chrome and webkits Fix + if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m41; + //Crazy IE10 Matrix + else if (matrix.length === 16) + curTransform = parseFloat(matrix[12]); + //Normal Browsers + else + curTransform = parseFloat(matrix[4]); + } + if (axis === 'y') { + //Latest Chrome and webkits Fix + if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m42; + //Crazy IE10 Matrix + else if (matrix.length === 16) + curTransform = parseFloat(matrix[13]); + //Normal Browsers + else + curTransform = parseFloat(matrix[5]); + } + if (s.rtl && curTransform) curTransform = -curTransform; + return curTransform || 0; + }; + s.getWrapperTranslate = function (axis) { + if (typeof axis === 'undefined') { + axis = isH() ? 'x' : 'y'; + } + return s.getTranslate(s.wrapper[0], axis); + }; -/** - * @ngdoc function - * @name angular.copy - * @module ng - * @kind function - * - * @description - * Creates a deep copy of `source`, which should be an object or an array. - * - * * If no destination is supplied, a copy of the object or array is created. - * * If a destination is provided, all of its elements (for arrays) or properties (for objects) - * are deleted and then all elements/properties from the source are copied to it. - * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. - * * If `source` is identical to 'destination' an exception will be thrown. - * - * @param {*} source The source that will be used to make a copy. - * Can be any type, including primitives, `null`, and `undefined`. - * @param {(Object|Array)=} destination Destination into which the source is copied. If - * provided, must be of the same type as `source`. - * @returns {*} The copy or updated `destination`, if `destination` was specified. - * - * @example - <example module="copyExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form novalidate class="simple-form"> - Name: <input type="text" ng-model="user.name" /><br /> - E-mail: <input type="email" ng-model="user.email" /><br /> - Gender: <input type="radio" ng-model="user.gender" value="male" />male - <input type="radio" ng-model="user.gender" value="female" />female<br /> - <button ng-click="reset()">RESET</button> - <button ng-click="update(user)">SAVE</button> - </form> - <pre>form = {{user | json}}</pre> - <pre>master = {{master | json}}</pre> - </div> + /*========================= + Observer + ===========================*/ + s.observers = []; + function initObserver(target, options) { + options = options || {}; + // create an observer instance + var ObserverFunc = window.MutationObserver || window.WebkitMutationObserver; + var observer = new ObserverFunc(function (mutations) { + mutations.forEach(function (mutation) { + s.onResize(true); + s.emit('onObserverUpdate', s, mutation); + }); + }); - <script> - angular.module('copyExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.master= {}; + observer.observe(target, { + attributes: typeof options.attributes === 'undefined' ? true : options.attributes, + childList: typeof options.childList === 'undefined' ? true : options.childList, + characterData: typeof options.characterData === 'undefined' ? true : options.characterData + }); - $scope.update = function(user) { - // Example with 1 argument - $scope.master= angular.copy(user); - }; + s.observers.push(observer); + } + s.initObservers = function () { + if (s.params.observeParents) { + var containerParents = s.container.parents(); + for (var i = 0; i < containerParents.length; i++) { + initObserver(containerParents[i]); + } + } - $scope.reset = function() { - // Example with 2 arguments - angular.copy($scope.master, $scope.user); - }; + // Observe container + initObserver(s.container[0], {childList: false}); - $scope.reset(); - }]); - </script> - </file> - </example> - */ -function copy(source, destination, stackSource, stackDest) { - if (isWindow(source) || isScope(source)) { - throw ngMinErr('cpws', - "Can't copy! Making copies of Window or Scope instances is not supported."); - } + // Observe wrapper + initObserver(s.wrapper[0], {attributes: false}); + }; + s.disconnectObservers = function () { + for (var i = 0; i < s.observers.length; i++) { + s.observers[i].disconnect(); + } + s.observers = []; + }; + /*========================= + Loop + ===========================*/ + // Create looped slides + s.createLoop = function () { - if (!destination) { - destination = source; - if (source) { - if (isArray(source)) { - destination = copy(source, [], stackSource, stackDest); - } else if (isDate(source)) { - destination = new Date(source.getTime()); - } else if (isRegExp(source)) { - destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); - destination.lastIndex = source.lastIndex; - } else if (isObject(source)) { - var emptyObject = Object.create(Object.getPrototypeOf(source)); - destination = copy(source, emptyObject, stackSource, stackDest); - } - } - } else { - if (source === destination) throw ngMinErr('cpi', - "Can't copy! Source and destination are identical."); + var toRemove = s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass); + angular.element(toRemove).remove(); - stackSource = stackSource || []; - stackDest = stackDest || []; + var slides = s.wrapper.children('.' + s.params.slideClass); - if (isObject(source)) { - var index = stackSource.indexOf(source); - if (index !== -1) return stackDest[index]; + if(s.params.slidesPerView === 'auto' && !s.params.loopedSlides) s.params.loopedSlides = slides.length; - stackSource.push(source); - stackDest.push(destination); - } + s.loopedSlides = parseInt(s.params.loopedSlides || s.params.slidesPerView, 10); + s.loopedSlides = s.loopedSlides + s.params.loopAdditionalSlides; + if (s.loopedSlides > slides.length) { + s.loopedSlides = slides.length; + } - var result; - if (isArray(source)) { - destination.length = 0; - for (var i = 0; i < source.length; i++) { - result = copy(source[i], null, stackSource, stackDest); - if (isObject(source[i])) { - stackSource.push(source[i]); - stackDest.push(result); - } - destination.push(result); - } - } else { - var h = destination.$$hashKey; - if (isArray(destination)) { - destination.length = 0; - } else { - forEach(destination, function(value, key) { - delete destination[key]; - }); - } - for (var key in source) { - if (source.hasOwnProperty(key)) { - result = copy(source[key], null, stackSource, stackDest); - if (isObject(source[key])) { - stackSource.push(source[key]); - stackDest.push(result); - } - destination[key] = result; - } - } - setHashKey(destination,h); - } + var prependSlides = [], appendSlides = [], i, scope, newNode; + slides.each(function (index, el) { + var slide = $(this); + if (index < s.loopedSlides) appendSlides.push(el); + if (index < slides.length && index >= slides.length - s.loopedSlides) prependSlides.push(el); + slide.attr('data-swiper-slide-index', index); + }); + for (i = 0; i < appendSlides.length; i++) { + newNode = angular.element(appendSlides[i]).clone().addClass(s.params.slideDuplicateClass); + newNode.removeAttr('ng-transclude'); + newNode.removeAttr('ng-repeat'); + scope = angular.element(appendSlides[i]).scope(); + newNode = $compile(newNode)(scope); + angular.element(s.wrapper).append(newNode); + //s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); + } + for (i = prependSlides.length - 1; i >= 0; i--) { + //s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); - } - return destination; -} + newNode = angular.element(prependSlides[i]).clone().addClass(s.params.slideDuplicateClass); + newNode.removeAttr('ng-transclude'); + newNode.removeAttr('ng-repeat'); -/** - * Creates a shallow copy of an object, an array or a primitive. - * - * Assumes that there are no proto properties for objects. - */ -function shallowCopy(src, dst) { - if (isArray(src)) { - dst = dst || []; + scope = angular.element(prependSlides[i]).scope(); + newNode = $compile(newNode)(scope); + angular.element(s.wrapper).prepend(newNode); + } + }; + s.destroyLoop = function () { + s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove(); + s.slides.removeAttr('data-swiper-slide-index'); + }; + s.fixLoop = function () { + var newIndex; + //Fix For Negative Oversliding + if (s.activeIndex < s.loopedSlides) { + newIndex = s.slides.length - s.loopedSlides * 3 + s.activeIndex; + newIndex = newIndex + s.loopedSlides; + s.slideTo(newIndex, 0, false, true); + } + //Fix For Positive Oversliding + else if ((s.params.slidesPerView === 'auto' && s.activeIndex >= s.loopedSlides * 2) || (s.activeIndex > s.slides.length - s.params.slidesPerView * 2)) { + newIndex = -s.slides.length + s.activeIndex + s.loopedSlides; + newIndex = newIndex + s.loopedSlides; + s.slideTo(newIndex, 0, false, true); + } + }; + /*========================= + Append/Prepend/Remove Slides + ===========================*/ + s.appendSlide = function (slides) { + if (s.params.loop) { + s.destroyLoop(); + } + if (typeof slides === 'object' && slides.length) { + for (var i = 0; i < slides.length; i++) { + if (slides[i]) s.wrapper.append(slides[i]); + } + } + else { + s.wrapper.append(slides); + } + if (s.params.loop) { + s.createLoop(); + } + if (!(s.params.observer && s.support.observer)) { + s.update(true); + } + }; + s.prependSlide = function (slides) { + if (s.params.loop) { + s.destroyLoop(); + } + var newActiveIndex = s.activeIndex + 1; + if (typeof slides === 'object' && slides.length) { + for (var i = 0; i < slides.length; i++) { + if (slides[i]) s.wrapper.prepend(slides[i]); + } + newActiveIndex = s.activeIndex + slides.length; + } + else { + s.wrapper.prepend(slides); + } + if (s.params.loop) { + s.createLoop(); + } + if (!(s.params.observer && s.support.observer)) { + s.update(true); + } + s.slideTo(newActiveIndex, 0, false); + }; + s.removeSlide = function (slidesIndexes) { + if (s.params.loop) { + s.destroyLoop(); + s.slides = s.wrapper.children('.' + s.params.slideClass); + } + var newActiveIndex = s.activeIndex, + indexToRemove; + if (typeof slidesIndexes === 'object' && slidesIndexes.length) { + for (var i = 0; i < slidesIndexes.length; i++) { + indexToRemove = slidesIndexes[i]; + if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove(); + if (indexToRemove < newActiveIndex) newActiveIndex--; + } + newActiveIndex = Math.max(newActiveIndex, 0); + } + else { + indexToRemove = slidesIndexes; + if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove(); + if (indexToRemove < newActiveIndex) newActiveIndex--; + newActiveIndex = Math.max(newActiveIndex, 0); + } - for (var i = 0, ii = src.length; i < ii; i++) { - dst[i] = src[i]; - } - } else if (isObject(src)) { - dst = dst || {}; + if (s.params.loop) { + s.createLoop(); + } - for (var key in src) { - if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { - dst[key] = src[key]; - } - } - } + if (!(s.params.observer && s.support.observer)) { + s.update(true); + } + if (s.params.loop) { + s.slideTo(newActiveIndex + s.loopedSlides, 0, false); + } + else { + s.slideTo(newActiveIndex, 0, false); + } - return dst || src; -} + }; + s.removeAllSlides = function () { + var slidesIndexes = []; + for (var i = 0; i < s.slides.length; i++) { + slidesIndexes.push(i); + } + s.removeSlide(slidesIndexes); + }; -/** - * @ngdoc function - * @name angular.equals - * @module ng - * @kind function - * - * @description - * Determines if two objects or two values are equivalent. Supports value types, regular - * expressions, arrays and objects. - * - * Two objects or values are considered equivalent if at least one of the following is true: - * - * * Both objects or values pass `===` comparison. - * * Both objects or values are of the same type and all of their properties are equal by - * comparing them with `angular.equals`. - * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal) - * * Both values represent the same regular expression (In JavaScript, - * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual - * representation matches). - * - * During a property comparison, properties of `function` type and properties with names - * that begin with `$` are ignored. - * - * Scope and DOMWindow objects are being compared only by identify (`===`). - * - * @param {*} o1 Object or value to compare. - * @param {*} o2 Object or value to compare. - * @returns {boolean} True if arguments are equal. - */ -function equals(o1, o2) { - if (o1 === o2) return true; - if (o1 === null || o2 === null) return false; - if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN - var t1 = typeof o1, t2 = typeof o2, length, key, keySet; - if (t1 == t2) { - if (t1 == 'object') { - if (isArray(o1)) { - if (!isArray(o2)) return false; - if ((length = o1.length) == o2.length) { - for (key = 0; key < length; key++) { - if (!equals(o1[key], o2[key])) return false; - } - return true; - } - } else if (isDate(o1)) { - if (!isDate(o2)) return false; - return equals(o1.getTime(), o2.getTime()); - } else if (isRegExp(o1) && isRegExp(o2)) { - return o1.toString() == o2.toString(); - } else { - if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false; - keySet = {}; - for (key in o1) { - if (key.charAt(0) === '$' || isFunction(o1[key])) continue; - if (!equals(o1[key], o2[key])) return false; - keySet[key] = true; - } - for (key in o2) { - if (!keySet.hasOwnProperty(key) && - key.charAt(0) !== '$' && - o2[key] !== undefined && - !isFunction(o2[key])) return false; - } - return true; - } - } - } - return false; -} + /*========================= + Effects + ===========================*/ + s.effects = { + fade: { + setTranslate: function () { + for (var i = 0; i < s.slides.length; i++) { + var slide = s.slides.eq(i); + var offset = slide[0].swiperSlideOffset; + var tx = -offset; + if (!s.params.virtualTranslate) tx = tx - s.translate; + var ty = 0; + if (!isH()) { + ty = tx; + tx = 0; + } + var slideOpacity = s.params.fade.crossFade ? + Math.max(1 - Math.abs(slide[0].progress), 0) : + 1 + Math.min(Math.max(slide[0].progress, -1), 0); + slide + .css({ + opacity: slideOpacity + }) + .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px)'); -var csp = function() { - if (isDefined(csp.isActive_)) return csp.isActive_; + } - var active = !!(document.querySelector('[ng-csp]') || - document.querySelector('[data-ng-csp]')); + }, + setTransition: function (duration) { + s.slides.transition(duration); + if (s.params.virtualTranslate && duration !== 0) { + var eventTriggered = false; + s.slides.transitionEnd(function () { + if (eventTriggered) return; + if (!s) return; + eventTriggered = true; + s.animating = false; + var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd']; + for (var i = 0; i < triggerEvents.length; i++) { + s.wrapper.trigger(triggerEvents[i]); + } + }); + } + } + }, + cube: { + setTranslate: function () { + var wrapperRotate = 0, cubeShadow; + if (s.params.cube.shadow) { + if (isH()) { + cubeShadow = s.wrapper.find('.swiper-cube-shadow'); + if (cubeShadow.length === 0) { + cubeShadow = $('<div class="swiper-cube-shadow"></div>'); + s.wrapper.append(cubeShadow); + } + cubeShadow.css({height: s.width + 'px'}); + } + else { + cubeShadow = s.container.find('.swiper-cube-shadow'); + if (cubeShadow.length === 0) { + cubeShadow = $('<div class="swiper-cube-shadow"></div>'); + s.container.append(cubeShadow); + } + } + } + for (var i = 0; i < s.slides.length; i++) { + var slide = s.slides.eq(i); + var slideAngle = i * 90; + var round = Math.floor(slideAngle / 360); + if (s.rtl) { + slideAngle = -slideAngle; + round = Math.floor(-slideAngle / 360); + } + var progress = Math.max(Math.min(slide[0].progress, 1), -1); + var tx = 0, ty = 0, tz = 0; + if (i % 4 === 0) { + tx = - round * 4 * s.size; + tz = 0; + } + else if ((i - 1) % 4 === 0) { + tx = 0; + tz = - round * 4 * s.size; + } + else if ((i - 2) % 4 === 0) { + tx = s.size + round * 4 * s.size; + tz = s.size; + } + else if ((i - 3) % 4 === 0) { + tx = - s.size; + tz = 3 * s.size + s.size * 4 * round; + } + if (s.rtl) { + tx = -tx; + } + + if (!isH()) { + ty = tx; + tx = 0; + } + + var transform = 'rotateX(' + (isH() ? 0 : -slideAngle) + 'deg) rotateY(' + (isH() ? slideAngle : 0) + 'deg) translate3d(' + tx + 'px, ' + ty + 'px, ' + tz + 'px)'; + if (progress <= 1 && progress > -1) { + wrapperRotate = i * 90 + progress * 90; + if (s.rtl) wrapperRotate = -i * 90 - progress * 90; + } + slide.transform(transform); + if (s.params.cube.slideShadows) { + //Set shadows + var shadowBefore = isH() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top'); + var shadowAfter = isH() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom'); + if (shadowBefore.length === 0) { + shadowBefore = $('<div class="swiper-slide-shadow-' + (isH() ? 'left' : 'top') + '"></div>'); + slide.append(shadowBefore); + } + if (shadowAfter.length === 0) { + shadowAfter = $('<div class="swiper-slide-shadow-' + (isH() ? 'right' : 'bottom') + '"></div>'); + slide.append(shadowAfter); + } + var shadowOpacity = slide[0].progress; + if (shadowBefore.length) shadowBefore[0].style.opacity = -slide[0].progress; + if (shadowAfter.length) shadowAfter[0].style.opacity = slide[0].progress; + } + } + s.wrapper.css({ + '-webkit-transform-origin': '50% 50% -' + (s.size / 2) + 'px', + '-moz-transform-origin': '50% 50% -' + (s.size / 2) + 'px', + '-ms-transform-origin': '50% 50% -' + (s.size / 2) + 'px', + 'transform-origin': '50% 50% -' + (s.size / 2) + 'px' + }); + + if (s.params.cube.shadow) { + if (isH()) { + cubeShadow.transform('translate3d(0px, ' + (s.width / 2 + s.params.cube.shadowOffset) + 'px, ' + (-s.width / 2) + 'px) rotateX(90deg) rotateZ(0deg) scale(' + (s.params.cube.shadowScale) + ')'); + } + else { + var shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90; + var multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2); + var scale1 = s.params.cube.shadowScale, + scale2 = s.params.cube.shadowScale / multiplier, + offset = s.params.cube.shadowOffset; + cubeShadow.transform('scale3d(' + scale1 + ', 1, ' + scale2 + ') translate3d(0px, ' + (s.height / 2 + offset) + 'px, ' + (-s.height / 2 / scale2) + 'px) rotateX(-90deg)'); + } + } + var zFactor = (s.isSafari || s.isUiWebView) ? (-s.size / 2) : 0; + s.wrapper.transform('translate3d(0px,0,' + zFactor + 'px) rotateX(' + (isH() ? 0 : wrapperRotate) + 'deg) rotateY(' + (isH() ? -wrapperRotate : 0) + 'deg)'); + }, + setTransition: function (duration) { + s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration); + if (s.params.cube.shadow && !isH()) { + s.container.find('.swiper-cube-shadow').transition(duration); + } + } + }, + coverflow: { + setTranslate: function () { + var transform = s.translate; + var center = isH() ? -transform + s.width / 2 : -transform + s.height / 2; + var rotate = isH() ? s.params.coverflow.rotate: -s.params.coverflow.rotate; + var translate = s.params.coverflow.depth; + //Each slide offset from center + for (var i = 0, length = s.slides.length; i < length; i++) { + var slide = s.slides.eq(i); + var slideSize = s.slidesSizesGrid[i]; + var slideOffset = slide[0].swiperSlideOffset; + var offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * s.params.coverflow.modifier; + + var rotateY = isH() ? rotate * offsetMultiplier : 0; + var rotateX = isH() ? 0 : rotate * offsetMultiplier; + // var rotateZ = 0 + var translateZ = -translate * Math.abs(offsetMultiplier); + + var translateY = isH() ? 0 : s.params.coverflow.stretch * (offsetMultiplier); + var translateX = isH() ? s.params.coverflow.stretch * (offsetMultiplier) : 0; + + //Fix for ultra small values + if (Math.abs(translateX) < 0.001) translateX = 0; + if (Math.abs(translateY) < 0.001) translateY = 0; + if (Math.abs(translateZ) < 0.001) translateZ = 0; + if (Math.abs(rotateY) < 0.001) rotateY = 0; + if (Math.abs(rotateX) < 0.001) rotateX = 0; + + var slideTransform = 'translate3d(' + translateX + 'px,' + translateY + 'px,' + translateZ + 'px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)'; + + slide.transform(slideTransform); + slide[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1; + if (s.params.coverflow.slideShadows) { + //Set shadows + var shadowBefore = isH() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top'); + var shadowAfter = isH() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom'); + if (shadowBefore.length === 0) { + shadowBefore = $('<div class="swiper-slide-shadow-' + (isH() ? 'left' : 'top') + '"></div>'); + slide.append(shadowBefore); + } + if (shadowAfter.length === 0) { + shadowAfter = $('<div class="swiper-slide-shadow-' + (isH() ? 'right' : 'bottom') + '"></div>'); + slide.append(shadowAfter); + } + if (shadowBefore.length) shadowBefore[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0; + if (shadowAfter.length) shadowAfter[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0; + } + } - if (!active) { - try { - /* jshint -W031, -W054 */ - new Function(''); - /* jshint +W031, +W054 */ - } catch (e) { - active = true; - } - } + //Set correct perspective for IE10 + if (s.browser.ie) { + var ws = s.wrapper[0].style; + ws.perspectiveOrigin = center + 'px 50%'; + } + }, + setTransition: function (duration) { + s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration); + } + } + }; - return (csp.isActive_ = active); -}; + /*========================= + Images Lazy Loading + ===========================*/ + s.lazy = { + initialImageLoaded: false, + loadImageInSlide: function (index, loadInDuplicate) { + if (typeof index === 'undefined') return; + if (typeof loadInDuplicate === 'undefined') loadInDuplicate = true; + if (s.slides.length === 0) return; + + var slide = s.slides.eq(index); + var img = slide.find('.swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)'); + if (slide.hasClass('swiper-lazy') && !slide.hasClass('swiper-lazy-loaded') && !slide.hasClass('swiper-lazy-loading')) { + img = img.add(slide[0]); + } + if (img.length === 0) return; + + img.each(function () { + var _img = $(this); + _img.addClass('swiper-lazy-loading'); + var background = _img.attr('data-background'); + var src = _img.attr('data-src'), + srcset = _img.attr('data-srcset'); + s.loadImage(_img[0], (src || background), srcset, false, function () { + if (background) { + _img.css('background-image', 'url(' + background + ')'); + _img.removeAttr('data-background'); + } + else { + if (srcset) { + _img.attr('srcset', srcset); + _img.removeAttr('data-srcset'); + } + if (src) { + _img.attr('src', src); + _img.removeAttr('data-src'); + } + + } + + _img.addClass('swiper-lazy-loaded').removeClass('swiper-lazy-loading'); + slide.find('.swiper-lazy-preloader, .preloader').remove(); + if (s.params.loop && loadInDuplicate) { + var slideOriginalIndex = slide.attr('data-swiper-slide-index'); + if (slide.hasClass(s.params.slideDuplicateClass)) { + var originalSlide = s.wrapper.children('[data-swiper-slide-index="' + slideOriginalIndex + '"]:not(.' + s.params.slideDuplicateClass + ')'); + s.lazy.loadImageInSlide(originalSlide.index(), false); + } + else { + var duplicatedSlide = s.wrapper.children('.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + slideOriginalIndex + '"]'); + s.lazy.loadImageInSlide(duplicatedSlide.index(), false); + } + } + s.emit('onLazyImageReady', s, slide[0], _img[0]); + }); + + s.emit('onLazyImageLoad', s, slide[0], _img[0]); + }); + }, + load: function () { + var i; + if (s.params.watchSlidesVisibility) { + s.wrapper.children('.' + s.params.slideVisibleClass).each(function () { + s.lazy.loadImageInSlide($(this).index()); + }); + } + else { + if (s.params.slidesPerView > 1) { + for (i = s.activeIndex; i < s.activeIndex + s.params.slidesPerView ; i++) { + if (s.slides[i]) s.lazy.loadImageInSlide(i); + } + } + else { + s.lazy.loadImageInSlide(s.activeIndex); + } + } + if (s.params.lazyLoadingInPrevNext) { + if (s.params.slidesPerView > 1) { + // Next Slides + for (i = s.activeIndex + s.params.slidesPerView; i < s.activeIndex + s.params.slidesPerView + s.params.slidesPerView; i++) { + if (s.slides[i]) s.lazy.loadImageInSlide(i); + } + // Prev Slides + for (i = s.activeIndex - s.params.slidesPerView; i < s.activeIndex ; i++) { + if (s.slides[i]) s.lazy.loadImageInSlide(i); + } + } + else { + var nextSlide = s.wrapper.children('.' + s.params.slideNextClass); + if (nextSlide.length > 0) s.lazy.loadImageInSlide(nextSlide.index()); + var prevSlide = s.wrapper.children('.' + s.params.slidePrevClass); + if (prevSlide.length > 0) s.lazy.loadImageInSlide(prevSlide.index()); + } + } + }, + onTransitionStart: function () { + if (s.params.lazyLoading) { + if (s.params.lazyLoadingOnTransitionStart || (!s.params.lazyLoadingOnTransitionStart && !s.lazy.initialImageLoaded)) { + s.lazy.load(); + } + } + }, + onTransitionEnd: function () { + if (s.params.lazyLoading && !s.params.lazyLoadingOnTransitionStart) { + s.lazy.load(); + } + } + }; -function concat(array1, array2, index) { - return array1.concat(slice.call(array2, index)); -} -function sliceArgs(args, startIndex) { - return slice.call(args, startIndex || 0); -} + /*========================= + Scrollbar + ===========================*/ + s.scrollbar = { + isTouched: false, + setDragPosition: function (e) { + var sb = s.scrollbar; + var x = 0, y = 0; + var translate; + var pointerPosition = isH() ? + ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageX : e.pageX || e.clientX) : + ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageY : e.pageY || e.clientY) ; + var position = (pointerPosition) - sb.track.offset()[isH() ? 'left' : 'top'] - sb.dragSize / 2; + var positionMin = -s.minTranslate() * sb.moveDivider; + var positionMax = -s.maxTranslate() * sb.moveDivider; + if (position < positionMin) { + position = positionMin; + } + else if (position > positionMax) { + position = positionMax; + } + position = -position / sb.moveDivider; + s.updateProgress(position); + s.setWrapperTranslate(position, true); + }, + dragStart: function (e) { + var sb = s.scrollbar; + sb.isTouched = true; + e.preventDefault(); + e.stopPropagation(); + + sb.setDragPosition(e); + clearTimeout(sb.dragTimeout); + + sb.track.transition(0); + if (s.params.scrollbarHide) { + sb.track.css('opacity', 1); + } + s.wrapper.transition(100); + sb.drag.transition(100); + s.emit('onScrollbarDragStart', s); + }, + dragMove: function (e) { + var sb = s.scrollbar; + if (!sb.isTouched) return; + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + sb.setDragPosition(e); + s.wrapper.transition(0); + sb.track.transition(0); + sb.drag.transition(0); + s.emit('onScrollbarDragMove', s); + }, + dragEnd: function (e) { + var sb = s.scrollbar; + if (!sb.isTouched) return; + sb.isTouched = false; + if (s.params.scrollbarHide) { + clearTimeout(sb.dragTimeout); + sb.dragTimeout = setTimeout(function () { + sb.track.css('opacity', 0); + sb.track.transition(400); + }, 1000); + } + s.emit('onScrollbarDragEnd', s); + if (s.params.scrollbarSnapOnRelease) { + s.slideReset(); + } + }, + enableDraggable: function () { + var sb = s.scrollbar; + var target = s.support.touch ? sb.track : document; + $(sb.track).on(s.touchEvents.start, sb.dragStart); + $(target).on(s.touchEvents.move, sb.dragMove); + $(target).on(s.touchEvents.end, sb.dragEnd); + }, + disableDraggable: function () { + var sb = s.scrollbar; + var target = s.support.touch ? sb.track : document; + $(sb.track).off(s.touchEvents.start, sb.dragStart); + $(target).off(s.touchEvents.move, sb.dragMove); + $(target).off(s.touchEvents.end, sb.dragEnd); + }, + set: function () { + if (!s.params.scrollbar) return; + var sb = s.scrollbar; + sb.track = $(s.params.scrollbar); + sb.drag = sb.track.find('.swiper-scrollbar-drag'); + if (sb.drag.length === 0) { + sb.drag = $('<div class="swiper-scrollbar-drag"></div>'); + sb.track.append(sb.drag); + } + sb.drag[0].style.width = ''; + sb.drag[0].style.height = ''; + sb.trackSize = isH() ? sb.track[0].offsetWidth : sb.track[0].offsetHeight; -/* jshint -W101 */ -/** - * @ngdoc function - * @name angular.bind - * @module ng - * @kind function - * - * @description - * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for - * `fn`). You can supply optional `args` that are prebound to the function. This feature is also - * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as - * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application). - * - * @param {Object} self Context which `fn` should be evaluated in. - * @param {function()} fn Function to be bound. - * @param {...*} args Optional arguments to be prebound to the `fn` function call. - * @returns {function()} Function that wraps the `fn` with all the specified bindings. - */ -/* jshint +W101 */ -function bind(self, fn) { - var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; - if (isFunction(fn) && !(fn instanceof RegExp)) { - return curryArgs.length - ? function() { - return arguments.length - ? fn.apply(self, concat(curryArgs, arguments, 0)) - : fn.apply(self, curryArgs); - } - : function() { - return arguments.length - ? fn.apply(self, arguments) - : fn.call(self); + sb.divider = s.size / s.virtualSize; + sb.moveDivider = sb.divider * (sb.trackSize / s.size); + sb.dragSize = sb.trackSize * sb.divider; + + if (isH()) { + sb.drag[0].style.width = sb.dragSize + 'px'; + } + else { + sb.drag[0].style.height = sb.dragSize + 'px'; + } + + if (sb.divider >= 1) { + sb.track[0].style.display = 'none'; + } + else { + sb.track[0].style.display = ''; + } + if (s.params.scrollbarHide) { + sb.track[0].style.opacity = 0; + } + }, + setTranslate: function () { + if (!s.params.scrollbar) return; + var diff; + var sb = s.scrollbar; + var translate = s.translate || 0; + var newPos; + + var newSize = sb.dragSize; + newPos = (sb.trackSize - sb.dragSize) * s.progress; + if (s.rtl && isH()) { + newPos = -newPos; + if (newPos > 0) { + newSize = sb.dragSize - newPos; + newPos = 0; + } + else if (-newPos + sb.dragSize > sb.trackSize) { + newSize = sb.trackSize + newPos; + } + } + else { + if (newPos < 0) { + newSize = sb.dragSize + newPos; + newPos = 0; + } + else if (newPos + sb.dragSize > sb.trackSize) { + newSize = sb.trackSize - newPos; + } + } + if (isH()) { + if (s.support.transforms3d) { + sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)'); + } + else { + sb.drag.transform('translateX(' + (newPos) + 'px)'); + } + sb.drag[0].style.width = newSize + 'px'; + } + else { + if (s.support.transforms3d) { + sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)'); + } + else { + sb.drag.transform('translateY(' + (newPos) + 'px)'); + } + sb.drag[0].style.height = newSize + 'px'; + } + if (s.params.scrollbarHide) { + clearTimeout(sb.timeout); + sb.track[0].style.opacity = 1; + sb.timeout = setTimeout(function () { + sb.track[0].style.opacity = 0; + sb.track.transition(400); + }, 1000); + } + }, + setTransition: function (duration) { + if (!s.params.scrollbar) return; + s.scrollbar.drag.transition(duration); + } }; - } else { - // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) - return fn; - } -} + /*========================= + Controller + ===========================*/ + s.controller = { + LinearSpline: function (x, y) { + this.x = x; + this.y = y; + this.lastIndex = x.length - 1; + // Given an x value (x2), return the expected y2 value: + // (x1,y1) is the known point before given value, + // (x3,y3) is the known point after given value. + var i1, i3; + var l = this.x.length; + + this.interpolate = function (x2) { + if (!x2) return 0; + + // Get the indexes of x1 and x3 (the array indexes before and after given x2): + i3 = binarySearch(this.x, x2); + i1 = i3 - 1; + + // We have our indexes i1 & i3, so we can calculate already: + // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1 + return ((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1]; + }; -function toJsonReplacer(key, value) { - var val = value; + var binarySearch = (function() { + var maxIndex, minIndex, guess; + return function(array, val) { + minIndex = -1; + maxIndex = array.length; + while (maxIndex - minIndex > 1) + if (array[guess = maxIndex + minIndex >> 1] <= val) { + minIndex = guess; + } else { + maxIndex = guess; + } + return maxIndex; + }; + })(); + }, + //xxx: for now i will just save one spline function to to + getInterpolateFunction: function(c){ + if(!s.controller.spline) s.controller.spline = s.params.loop ? + new s.controller.LinearSpline(s.slidesGrid, c.slidesGrid) : + new s.controller.LinearSpline(s.snapGrid, c.snapGrid); + }, + setTranslate: function (translate, byController) { + var controlled = s.params.control; + var multiplier, controlledTranslate; + function setControlledTranslate(c) { + // this will create an Interpolate function based on the snapGrids + // x is the Grid of the scrolled scroller and y will be the controlled scroller + // it makes sense to create this only once and recall it for the interpolation + // the function does a lot of value caching for performance + translate = c.rtl && c.params.direction === 'horizontal' ? -s.translate : s.translate; + if (s.params.controlBy === 'slide') { + s.controller.getInterpolateFunction(c); + // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid + // but it did not work out + controlledTranslate = -s.controller.spline.interpolate(-translate); + } - if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { - val = undefined; - } else if (isWindow(value)) { - val = '$WINDOW'; - } else if (value && document === value) { - val = '$DOCUMENT'; - } else if (isScope(value)) { - val = '$SCOPE'; - } + if(!controlledTranslate || s.params.controlBy === 'container'){ + multiplier = (c.maxTranslate() - c.minTranslate()) / (s.maxTranslate() - s.minTranslate()); + controlledTranslate = (translate - s.minTranslate()) * multiplier + c.minTranslate(); + } - return val; -} + if (s.params.controlInverse) { + controlledTranslate = c.maxTranslate() - controlledTranslate; + } + c.updateProgress(controlledTranslate); + c.setWrapperTranslate(controlledTranslate, false, s); + c.updateActiveIndex(); + } + if (s.isArray(controlled)) { + for (var i = 0; i < controlled.length; i++) { + if (controlled[i] !== byController && controlled[i] instanceof Swiper) { + setControlledTranslate(controlled[i]); + } + } + } + else if (controlled instanceof Swiper && byController !== controlled) { + setControlledTranslate(controlled); + } + }, + setTransition: function (duration, byController) { + var controlled = s.params.control; + var i; + function setControlledTransition(c) { + c.setWrapperTransition(duration, s); + if (duration !== 0) { + c.onTransitionStart(); + c.wrapper.transitionEnd(function(){ + if (!controlled) return; + if (c.params.loop && s.params.controlBy === 'slide') { + c.fixLoop(); + } + c.onTransitionEnd(); -/** - * @ngdoc function - * @name angular.toJson - * @module ng - * @kind function - * - * @description - * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be - * stripped since angular uses this notation internally. - * - * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. - * @param {boolean|number=} pretty If set to true, the JSON output will contain newlines and whitespace. - * If set to an integer, the JSON output will contain that many spaces per indentation (the default is 2). - * @returns {string|undefined} JSON-ified string representing `obj`. - */ -function toJson(obj, pretty) { - if (typeof obj === 'undefined') return undefined; - if (!isNumber(pretty)) { - pretty = pretty ? 2 : null; - } - return JSON.stringify(obj, toJsonReplacer, pretty); -} + }); + } + } + if (s.isArray(controlled)) { + for (i = 0; i < controlled.length; i++) { + if (controlled[i] !== byController && controlled[i] instanceof Swiper) { + setControlledTransition(controlled[i]); + } + } + } + else if (controlled instanceof Swiper && byController !== controlled) { + setControlledTransition(controlled); + } + } + }; + /*========================= + Hash Navigation + ===========================*/ + s.hashnav = { + init: function () { + if (!s.params.hashnav) return; + s.hashnav.initialized = true; + var hash = document.location.hash.replace('#', ''); + if (!hash) return; + var speed = 0; + for (var i = 0, length = s.slides.length; i < length; i++) { + var slide = s.slides.eq(i); + var slideHash = slide.attr('data-hash'); + if (slideHash === hash && !slide.hasClass(s.params.slideDuplicateClass)) { + var index = slide.index(); + s.slideTo(index, speed, s.params.runCallbacksOnInit, true); + } + } + }, + setHash: function () { + if (!s.hashnav.initialized || !s.params.hashnav) return; + document.location.hash = s.slides.eq(s.activeIndex).attr('data-hash') || ''; + } + }; -/** - * @ngdoc function - * @name angular.fromJson - * @module ng - * @kind function - * - * @description - * Deserializes a JSON string. - * - * @param {string} json JSON string to deserialize. - * @returns {Object|Array|string|number} Deserialized JSON string. - */ -function fromJson(json) { - return isString(json) - ? JSON.parse(json) - : json; -} + /*========================= + Keyboard Control + ===========================*/ + function handleKeyboard(e) { + if (e.originalEvent) e = e.originalEvent; //jquery fix + var kc = e.keyCode || e.charCode; + // Directions locks + if (!s.params.allowSwipeToNext && (isH() && kc === 39 || !isH() && kc === 40)) { + return false; + } + if (!s.params.allowSwipeToPrev && (isH() && kc === 37 || !isH() && kc === 38)) { + return false; + } + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { + return; + } + if (document.activeElement && document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea')) { + return; + } + if (kc === 37 || kc === 39 || kc === 38 || kc === 40) { + var inView = false; + //Check that swiper should be inside of visible area of window + if (s.container.parents('.swiper-slide').length > 0 && s.container.parents('.swiper-slide-active').length === 0) { + return; + } + var windowScroll = { + left: window.pageXOffset, + top: window.pageYOffset + }; + var windowWidth = window.innerWidth; + var windowHeight = window.innerHeight; + var swiperOffset = s.container.offset(); + if (s.rtl) swiperOffset.left = swiperOffset.left - s.container[0].scrollLeft; + var swiperCoord = [ + [swiperOffset.left, swiperOffset.top], + [swiperOffset.left + s.width, swiperOffset.top], + [swiperOffset.left, swiperOffset.top + s.height], + [swiperOffset.left + s.width, swiperOffset.top + s.height] + ]; + for (var i = 0; i < swiperCoord.length; i++) { + var point = swiperCoord[i]; + if ( + point[0] >= windowScroll.left && point[0] <= windowScroll.left + windowWidth && + point[1] >= windowScroll.top && point[1] <= windowScroll.top + windowHeight + ) { + inView = true; + } + } + if (!inView) return; + } + if (isH()) { + if (kc === 37 || kc === 39) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if ((kc === 39 && !s.rtl) || (kc === 37 && s.rtl)) s.slideNext(); + if ((kc === 37 && !s.rtl) || (kc === 39 && s.rtl)) s.slidePrev(); + } + else { + if (kc === 38 || kc === 40) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if (kc === 40) s.slideNext(); + if (kc === 38) s.slidePrev(); + } + } + s.disableKeyboardControl = function () { + s.params.keyboardControl = false; + $(document).off('keydown', handleKeyboard); + }; + s.enableKeyboardControl = function () { + s.params.keyboardControl = true; + $(document).on('keydown', handleKeyboard); + }; -/** - * @returns {string} Returns the string representation of the element. - */ -function startingTag(element) { - element = jqLite(element).clone(); - try { - // turns out IE does not let you set .html() on elements which - // are not allowed to have children. So we just ignore it. - element.empty(); - } catch (e) {} - var elemHtml = jqLite('<div>').append(element).html(); - try { - return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : - elemHtml. - match(/^(<[^>]+>)/)[1]. - replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); - } catch (e) { - return lowercase(elemHtml); - } -} + /*========================= + Mousewheel Control + ===========================*/ + s.mousewheel = { + event: false, + lastScrollTime: (new window.Date()).getTime() + }; + if (s.params.mousewheelControl) { + try { + new window.WheelEvent('wheel'); + s.mousewheel.event = 'wheel'; + } catch (e) {} + if (!s.mousewheel.event && document.onmousewheel !== undefined) { + s.mousewheel.event = 'mousewheel'; + } + if (!s.mousewheel.event) { + s.mousewheel.event = 'DOMMouseScroll'; + } + } + function handleMousewheel(e) { + if (e.originalEvent) e = e.originalEvent; //jquery fix + var we = s.mousewheel.event; + var delta = 0; + var rtlFactor = s.rtl ? -1 : 1; + //Opera & IE + if (e.detail) delta = -e.detail; + //WebKits + else if (we === 'mousewheel') { + if (s.params.mousewheelForceToAxis) { + if (isH()) { + if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) delta = e.wheelDeltaX * rtlFactor; + else return; + } + else { + if (Math.abs(e.wheelDeltaY) > Math.abs(e.wheelDeltaX)) delta = e.wheelDeltaY; + else return; + } + } + else { + delta = Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY) ? - e.wheelDeltaX * rtlFactor : - e.wheelDeltaY; + } + } + //Old FireFox + else if (we === 'DOMMouseScroll') delta = -e.detail; + //New FireFox + else if (we === 'wheel') { + if (s.params.mousewheelForceToAxis) { + if (isH()) { + if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) delta = -e.deltaX * rtlFactor; + else return; + } + else { + if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) delta = -e.deltaY; + else return; + } + } + else { + delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? - e.deltaX * rtlFactor : - e.deltaY; + } + } + if (delta === 0) return; -///////////////////////////////////////////////// + if (s.params.mousewheelInvert) delta = -delta; -/** - * Tries to decode the URI component without throwing an exception. - * - * @private - * @param str value potential URI component to check. - * @returns {boolean} True if `value` can be decoded - * with the decodeURIComponent function. - */ -function tryDecodeURIComponent(value) { - try { - return decodeURIComponent(value); - } catch (e) { - // Ignore any invalid uri component - } -} + if (!s.params.freeMode) { + if ((new window.Date()).getTime() - s.mousewheel.lastScrollTime > 60) { + if (delta < 0) { + if ((!s.isEnd || s.params.loop) && !s.animating) s.slideNext(); + else if (s.params.mousewheelReleaseOnEdges) return true; + } + else { + if ((!s.isBeginning || s.params.loop) && !s.animating) s.slidePrev(); + else if (s.params.mousewheelReleaseOnEdges) return true; + } + } + s.mousewheel.lastScrollTime = (new window.Date()).getTime(); + } + else { + //Freemode or scrollContainer: + var position = s.getWrapperTranslate() + delta * s.params.mousewheelSensitivity; + var wasBeginning = s.isBeginning, + wasEnd = s.isEnd; -/** - * Parses an escaped url query string into key-value pairs. - * @returns {Object.<string,boolean|Array>} - */ -function parseKeyValue(/**string*/keyValue) { - var obj = {}, key_value, key; - forEach((keyValue || "").split('&'), function(keyValue) { - if (keyValue) { - key_value = keyValue.replace(/\+/g,'%20').split('='); - key = tryDecodeURIComponent(key_value[0]); - if (isDefined(key)) { - var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; - if (!hasOwnProperty.call(obj, key)) { - obj[key] = val; - } else if (isArray(obj[key])) { - obj[key].push(val); - } else { - obj[key] = [obj[key],val]; + if (position >= s.minTranslate()) position = s.minTranslate(); + if (position <= s.maxTranslate()) position = s.maxTranslate(); + + s.setWrapperTransition(0); + s.setWrapperTranslate(position); + s.updateProgress(); + s.updateActiveIndex(); + + if (!wasBeginning && s.isBeginning || !wasEnd && s.isEnd) { + s.updateClasses(); + } + + if (s.params.freeModeSticky) { + clearTimeout(s.mousewheel.timeout); + s.mousewheel.timeout = setTimeout(function () { + s.slideReset(); + }, 300); + } + + // Return page scroll on edge positions + if (position === 0 || position === s.maxTranslate()) return; + } + if (s.params.autoplay) s.stopAutoplay(); + + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + return false; } - } - } - }); - return obj; -} + s.disableMousewheelControl = function () { + if (!s.mousewheel.event) return false; + s.container.off(s.mousewheel.event, handleMousewheel); + return true; + }; -function toKeyValue(obj) { - var parts = []; - forEach(obj, function(value, key) { - if (isArray(value)) { - forEach(value, function(arrayValue) { - parts.push(encodeUriQuery(key, true) + - (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); - }); - } else { - parts.push(encodeUriQuery(key, true) + - (value === true ? '' : '=' + encodeUriQuery(value, true))); - } - }); - return parts.length ? parts.join('&') : ''; -} + s.enableMousewheelControl = function () { + if (!s.mousewheel.event) return false; + s.container.on(s.mousewheel.event, handleMousewheel); + return true; + }; -/** - * We need our custom method because encodeURIComponent is too aggressive and doesn't follow - * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path - * segments: - * segment = *pchar - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * pct-encoded = "%" HEXDIG HEXDIG - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ -function encodeUriSegment(val) { - return encodeUriQuery(val, true). - replace(/%26/gi, '&'). - replace(/%3D/gi, '='). - replace(/%2B/gi, '+'); -} + /*========================= + Parallax + ===========================*/ + function setParallaxTransform(el, progress) { + el = $(el); + var p, pX, pY; + var rtlFactor = s.rtl ? -1 : 1; + + p = el.attr('data-swiper-parallax') || '0'; + pX = el.attr('data-swiper-parallax-x'); + pY = el.attr('data-swiper-parallax-y'); + if (pX || pY) { + pX = pX || '0'; + pY = pY || '0'; + } + else { + if (isH()) { + pX = p; + pY = '0'; + } + else { + pY = p; + pX = '0'; + } + } + if ((pX).indexOf('%') >= 0) { + pX = parseInt(pX, 10) * progress * rtlFactor + '%'; + } + else { + pX = pX * progress * rtlFactor + 'px' ; + } + if ((pY).indexOf('%') >= 0) { + pY = parseInt(pY, 10) * progress + '%'; + } + else { + pY = pY * progress + 'px' ; + } -/** - * This method is intended for encoding *key* or *value* parts of query component. We need a custom - * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be - * encoded per http://tools.ietf.org/html/rfc3986: - * query = *( pchar / "/" / "?" ) - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * pct-encoded = "%" HEXDIG HEXDIG - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ -function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%3B/gi, ';'). - replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); -} + el.transform('translate3d(' + pX + ', ' + pY + ',0px)'); + } + s.parallax = { + setTranslate: function () { + s.container.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){ + setParallaxTransform(this, s.progress); -var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; + }); + s.slides.each(function () { + var slide = $(this); + slide.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function () { + var progress = Math.min(Math.max(slide[0].progress, -1), 1); + setParallaxTransform(this, progress); + }); + }); + }, + setTransition: function (duration) { + if (typeof duration === 'undefined') duration = s.params.speed; + s.container.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){ + var el = $(this); + var parallaxDuration = parseInt(el.attr('data-swiper-parallax-duration'), 10) || duration; + if (duration === 0) parallaxDuration = 0; + el.transition(parallaxDuration); + }); + } + }; -function getNgAttribute(element, ngAttr) { - var attr, i, ii = ngAttrPrefixes.length; - element = jqLite(element); - for (i = 0; i < ii; ++i) { - attr = ngAttrPrefixes[i] + ngAttr; - if (isString(attr = element.attr(attr))) { - return attr; - } - } - return null; -} -/** - * @ngdoc directive - * @name ngApp - * @module ng - * - * @element ANY - * @param {angular.Module} ngApp an optional application - * {@link angular.module module} name to load. - * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be - * created in "strict-di" mode. This means that the application will fail to invoke functions which - * do not use explicit function annotation (and are thus unsuitable for minification), as described - * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in - * tracking down the root of these bugs. - * - * @description - * - * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive - * designates the **root element** of the application and is typically placed near the root element - * of the page - e.g. on the `<body>` or `<html>` tags. - * - * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` - * found in the document will be used to define the root element to auto-bootstrap as an - * application. To run multiple applications in an HTML document you must manually bootstrap them using - * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other. - * - * You can specify an **AngularJS module** to be used as the root module for the application. This - * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It - * should contain the application code needed or have dependencies on other modules that will - * contain the code. See {@link angular.module} for more information. - * - * In the example below if the `ngApp` directive were not placed on the `html` element then the - * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}` - * would not be resolved to `3`. - * - * `ngApp` is the easiest, and most common way to bootstrap an application. - * - <example module="ngAppDemo"> - <file name="index.html"> - <div ng-controller="ngAppDemoController"> - I can add: {{a}} + {{b}} = {{ a+b }} - </div> - </file> - <file name="script.js"> - angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { - $scope.a = 1; - $scope.b = 2; - }); - </file> - </example> - * - * Using `ngStrictDi`, you would see something like this: - * - <example ng-app-included="true"> - <file name="index.html"> - <div ng-app="ngAppStrictDemo" ng-strict-di> - <div ng-controller="GoodController1"> - I can add: {{a}} + {{b}} = {{ a+b }} + /*========================= + Plugins API. Collect all and init all plugins + ===========================*/ + s._plugins = []; + for (var plugin in s.plugins) { + var p = s.plugins[plugin](s, s.params[plugin]); + if (p) s._plugins.push(p); + } + // Method to call all plugins event/method + s.callPlugins = function (eventName) { + for (var i = 0; i < s._plugins.length; i++) { + if (eventName in s._plugins[i]) { + s._plugins[i][eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + } + }; - <p>This renders because the controller does not fail to - instantiate, by using explicit annotation style (see - script.js for details) - </p> - </div> + /*========================= + Events/Callbacks/Plugins Emitter + ===========================*/ + function normalizeEventName (eventName) { + if (eventName.indexOf('on') !== 0) { + if (eventName[0] !== eventName[0].toUpperCase()) { + eventName = 'on' + eventName[0].toUpperCase() + eventName.substring(1); + } + else { + eventName = 'on' + eventName; + } + } + return eventName; + } + s.emitterEventListeners = { - <div ng-controller="GoodController2"> - Name: <input ng-model="name"><br /> - Hello, {{name}}! + }; + s.emit = function (eventName) { + // Trigger callbacks + if (s.params[eventName]) { + s.params[eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + var i; + // Trigger events + if (s.emitterEventListeners[eventName]) { + for (i = 0; i < s.emitterEventListeners[eventName].length; i++) { + s.emitterEventListeners[eventName][i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + } + // Trigger plugins + if (s.callPlugins) s.callPlugins(eventName, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + }; + s.on = function (eventName, handler) { + eventName = normalizeEventName(eventName); + if (!s.emitterEventListeners[eventName]) s.emitterEventListeners[eventName] = []; + s.emitterEventListeners[eventName].push(handler); + return s; + }; + s.off = function (eventName, handler) { + var i; + eventName = normalizeEventName(eventName); + if (typeof handler === 'undefined') { + // Remove all handlers for such event + s.emitterEventListeners[eventName] = []; + return s; + } + if (!s.emitterEventListeners[eventName] || s.emitterEventListeners[eventName].length === 0) return; + for (i = 0; i < s.emitterEventListeners[eventName].length; i++) { + if(s.emitterEventListeners[eventName][i] === handler) s.emitterEventListeners[eventName].splice(i, 1); + } + return s; + }; + s.once = function (eventName, handler) { + eventName = normalizeEventName(eventName); + var _handler = function () { + handler(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); + s.off(eventName, _handler); + }; + s.on(eventName, _handler); + return s; + }; - <p>This renders because the controller does not fail to - instantiate, by using explicit annotation style - (see script.js for details) - </p> - </div> + // Accessibility tools + s.a11y = { + makeFocusable: function ($el) { + $el.attr('tabIndex', '0'); + return $el; + }, + addRole: function ($el, role) { + $el.attr('role', role); + return $el; + }, - <div ng-controller="BadController"> - I can add: {{a}} + {{b}} = {{ a+b }} + addLabel: function ($el, label) { + $el.attr('aria-label', label); + return $el; + }, - <p>The controller could not be instantiated, due to relying - on automatic function annotations (which are disabled in - strict mode). As such, the content of this section is not - interpolated, and there should be an error in your web console. - </p> - </div> - </div> - </file> - <file name="script.js"> - angular.module('ngAppStrictDemo', []) - // BadController will fail to instantiate, due to relying on automatic function annotation, - // rather than an explicit annotation - .controller('BadController', function($scope) { - $scope.a = 1; - $scope.b = 2; - }) - // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated, - // due to using explicit annotations using the array style and $inject property, respectively. - .controller('GoodController1', ['$scope', function($scope) { - $scope.a = 1; - $scope.b = 2; - }]) - .controller('GoodController2', GoodController2); - function GoodController2($scope) { - $scope.name = "World"; - } - GoodController2.$inject = ['$scope']; - </file> - <file name="style.css"> - div[ng-controller] { - margin-bottom: 1em; - -webkit-border-radius: 4px; - border-radius: 4px; - border: 1px solid; - padding: .5em; - } - div[ng-controller^=Good] { - border-color: #d6e9c6; - background-color: #dff0d8; - color: #3c763d; - } - div[ng-controller^=Bad] { - border-color: #ebccd1; - background-color: #f2dede; - color: #a94442; - margin-bottom: 0; - } - </file> - </example> - */ -function angularInit(element, bootstrap) { - var appElement, - module, - config = {}; + disable: function ($el) { + $el.attr('aria-disabled', true); + return $el; + }, - // The element `element` has priority over any other element - forEach(ngAttrPrefixes, function(prefix) { - var name = prefix + 'app'; + enable: function ($el) { + $el.attr('aria-disabled', false); + return $el; + }, - if (!appElement && element.hasAttribute && element.hasAttribute(name)) { - appElement = element; - module = element.getAttribute(name); - } - }); - forEach(ngAttrPrefixes, function(prefix) { - var name = prefix + 'app'; - var candidate; + onEnterKey: function (event) { + if (event.keyCode !== 13) return; + if ($(event.target).is(s.params.nextButton)) { + s.onClickNext(event); + if (s.isEnd) { + s.a11y.notify(s.params.lastSlideMessage); + } + else { + s.a11y.notify(s.params.nextSlideMessage); + } + } + else if ($(event.target).is(s.params.prevButton)) { + s.onClickPrev(event); + if (s.isBeginning) { + s.a11y.notify(s.params.firstSlideMessage); + } + else { + s.a11y.notify(s.params.prevSlideMessage); + } + } + if ($(event.target).is('.' + s.params.bulletClass)) { + $(event.target)[0].click(); + } + }, - if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) { - appElement = candidate; - module = candidate.getAttribute(name); - } - }); - if (appElement) { - config.strictDi = getNgAttribute(appElement, "strict-di") !== null; - bootstrap(appElement, module ? [module] : [], config); - } -} + liveRegion: $('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'), -/** - * @ngdoc function - * @name angular.bootstrap - * @module ng - * @description - * Use this function to manually start up angular application. - * - * See: {@link guide/bootstrap Bootstrap} - * - * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually. - * They must use {@link ng.directive:ngApp ngApp}. - * - * Angular will detect if it has been loaded into the browser more than once and only allow the - * first loaded script to be bootstrapped and will report a warning to the browser console for - * each of the subsequent scripts. This prevents strange results in applications, where otherwise - * multiple instances of Angular try to work on the DOM. - * - * ```html - * <!doctype html> - * <html> - * <body> - * <div ng-controller="WelcomeController"> - * {{greeting}} - * </div> - * - * <script src="angular.js"></script> - * <script> - * var app = angular.module('demo', []) - * .controller('WelcomeController', function($scope) { - * $scope.greeting = 'Welcome!'; - * }); - * angular.bootstrap(document, ['demo']); - * </script> - * </body> - * </html> - * ``` - * - * @param {DOMElement} element DOM element which is the root of angular application. - * @param {Array<String|Function|Array>=} modules an array of modules to load into the application. - * Each item in the array should be the name of a predefined module or a (DI annotated) - * function that will be invoked by the injector as a `config` block. - * See: {@link angular.module modules} - * @param {Object=} config an object for defining configuration options for the application. The - * following keys are supported: - * - * * `strictDi` - disable automatic function annotation for the application. This is meant to - * assist in finding bugs which break minified code. Defaults to `false`. - * - * @returns {auto.$injector} Returns the newly created injector for this app. - */ -function bootstrap(element, modules, config) { - if (!isObject(config)) config = {}; - var defaultConfig = { - strictDi: false - }; - config = extend(defaultConfig, config); - var doBootstrap = function() { - element = jqLite(element); - - if (element.injector()) { - var tag = (element[0] === document) ? 'document' : startingTag(element); - //Encode angle brackets to prevent input from being sanitized to empty string #8683 - throw ngMinErr( - 'btstrpd', - "App Already Bootstrapped with this Element '{0}'", - tag.replace(/</,'<').replace(/>/,'>')); - } + notify: function (message) { + var notification = s.a11y.liveRegion; + if (notification.length === 0) return; + notification.html(''); + notification.html(message); + }, + init: function () { + // Setup accessibility + if (s.params.nextButton) { + var nextButton = $(s.params.nextButton); + s.a11y.makeFocusable(nextButton); + s.a11y.addRole(nextButton, 'button'); + s.a11y.addLabel(nextButton, s.params.nextSlideMessage); + } + if (s.params.prevButton) { + var prevButton = $(s.params.prevButton); + s.a11y.makeFocusable(prevButton); + s.a11y.addRole(prevButton, 'button'); + s.a11y.addLabel(prevButton, s.params.prevSlideMessage); + } - modules = modules || []; - modules.unshift(['$provide', function($provide) { - $provide.value('$rootElement', element); - }]); + $(s.container).append(s.a11y.liveRegion); + }, + initPagination: function () { + if (s.params.pagination && s.params.paginationClickable && s.bullets && s.bullets.length) { + s.bullets.each(function () { + var bullet = $(this); + s.a11y.makeFocusable(bullet); + s.a11y.addRole(bullet, 'button'); + s.a11y.addLabel(bullet, s.params.paginationBulletMessage.replace(/{{index}}/, bullet.index() + 1)); + }); + } + }, + destroy: function () { + if (s.a11y.liveRegion && s.a11y.liveRegion.length > 0) s.a11y.liveRegion.remove(); + } + }; - if (config.debugInfoEnabled) { - // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`. - modules.push(['$compileProvider', function($compileProvider) { - $compileProvider.debugInfoEnabled(true); - }]); - } - modules.unshift('ng'); - var injector = createInjector(modules, config.strictDi); - injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', - function bootstrapApply(scope, element, compile, injector) { - scope.$apply(function() { - element.data('$injector', injector); - compile(element)(scope); - }); - }] - ); - return injector; - }; + /*========================= + Init/Destroy + ===========================*/ + s.init = function () { + if (s.params.loop) s.createLoop(); + s.updateContainerSize(); + s.updateSlidesSize(); + s.updatePagination(); + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.set(); + if (s.params.scrollbarDraggable) { + s.scrollbar.enableDraggable(); + } + } + if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { + if (!s.params.loop) s.updateProgress(); + s.effects[s.params.effect].setTranslate(); + } + if (s.params.loop) { + s.slideTo(s.params.initialSlide + s.loopedSlides, 0, s.params.runCallbacksOnInit); + } + else { + s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit); + if (s.params.initialSlide === 0) { + if (s.parallax && s.params.parallax) s.parallax.setTranslate(); + if (s.lazy && s.params.lazyLoading) { + s.lazy.load(); + s.lazy.initialImageLoaded = true; + } + } + } + s.attachEvents(); + if (s.params.observer && s.support.observer) { + s.initObservers(); + } + if (s.params.preloadImages && !s.params.lazyLoading) { + s.preloadImages(); + } + if (s.params.autoplay) { + s.startAutoplay(); + } + if (s.params.keyboardControl) { + if (s.enableKeyboardControl) s.enableKeyboardControl(); + } + if (s.params.mousewheelControl) { + if (s.enableMousewheelControl) s.enableMousewheelControl(); + } + if (s.params.hashnav) { + if (s.hashnav) s.hashnav.init(); + } + if (s.params.a11y && s.a11y) s.a11y.init(); + s.emit('onInit', s); + }; - var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; - var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + // Cleanup dynamic styles + s.cleanupStyles = function () { + // Container + s.container.removeClass(s.classNames.join(' ')).removeAttr('style'); + + // Wrapper + s.wrapper.removeAttr('style'); + + // Slides + if (s.slides && s.slides.length) { + s.slides + .removeClass([ + s.params.slideVisibleClass, + s.params.slideActiveClass, + s.params.slideNextClass, + s.params.slidePrevClass + ].join(' ')) + .removeAttr('style') + .removeAttr('data-swiper-column') + .removeAttr('data-swiper-row'); + } - if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { - config.debugInfoEnabled = true; - window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ''); - } + // Pagination/Bullets + if (s.paginationContainer && s.paginationContainer.length) { + s.paginationContainer.removeClass(s.params.paginationHiddenClass); + } + if (s.bullets && s.bullets.length) { + s.bullets.removeClass(s.params.bulletActiveClass); + } - if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { - return doBootstrap(); - } + // Buttons + if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass); + if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass); - window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); - angular.resumeBootstrap = function(extraModules) { - forEach(extraModules, function(module) { - modules.push(module); - }); - return doBootstrap(); - }; + // Scrollbar + if (s.params.scrollbar && s.scrollbar) { + if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style'); + if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style'); + } + }; - if (isFunction(angular.resumeDeferredBootstrap)) { - angular.resumeDeferredBootstrap(); - } -} + // Destroy + s.destroy = function (deleteInstance, cleanupStyles) { + // Detach evebts + s.detachEvents(); + // Stop autoplay + s.stopAutoplay(); + // Disable draggable + if (s.params.scrollbar && s.scrollbar) { + if (s.params.scrollbarDraggable) { + s.scrollbar.disableDraggable(); + } + } + // Destroy loop + if (s.params.loop) { + s.destroyLoop(); + } + // Cleanup styles + if (cleanupStyles) { + s.cleanupStyles(); + } + // Disconnect observer + s.disconnectObservers(); + // Disable keyboard/mousewheel + if (s.params.keyboardControl) { + if (s.disableKeyboardControl) s.disableKeyboardControl(); + } + if (s.params.mousewheelControl) { + if (s.disableMousewheelControl) s.disableMousewheelControl(); + } + // Disable a11y + if (s.params.a11y && s.a11y) s.a11y.destroy(); + // Destroy callback + s.emit('onDestroy'); + // Delete instance + if (deleteInstance !== false) s = null; + }; -/** - * @ngdoc function - * @name angular.reloadWithDebugInfo - * @module ng - * @description - * Use this function to reload the current application with debug information turned on. - * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`. - * - * See {@link ng.$compileProvider#debugInfoEnabled} for more. - */ -function reloadWithDebugInfo() { - window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name; - window.location.reload(); -} + s.init(); -/** - * @name angular.getTestability - * @module ng - * @description - * Get the testability service for the instance of Angular on the given - * element. - * @param {DOMElement} element DOM element which is the root of angular application. - */ -function getTestability(rootElement) { - var injector = angular.element(rootElement).injector(); - if (!injector) { - throw ngMinErr('test', - 'no injector found for element argument to getTestability'); - } - return injector.get('$$testability'); -} -var SNAKE_CASE_REGEXP = /[A-Z]/g; -function snake_case(name, separator) { - separator = separator || '_'; - return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { - return (pos ? separator : '') + letter.toLowerCase(); - }); -} -var bindJQueryFired = false; -var skipDestroyOnNextJQueryCleanData; -function bindJQuery() { - var originalCleanData; + // Return swiper instance + return s; + }; - if (bindJQueryFired) { - return; - } - // bind to jQuery if present; - jQuery = window.jQuery; - // Use jQuery if it exists with proper functionality, otherwise default to us. - // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. - // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older - // versions. It will not work for sure with jQuery <1.7, though. - if (jQuery && jQuery.fn.on) { - jqLite = jQuery; - extend(jQuery.fn, { - scope: JQLitePrototype.scope, - isolateScope: JQLitePrototype.isolateScope, - controller: JQLitePrototype.controller, - injector: JQLitePrototype.injector, - inheritedData: JQLitePrototype.inheritedData - }); + /*================================================== + Prototype + ====================================================*/ + Swiper.prototype = { + isSafari: (function () { + var ua = navigator.userAgent.toLowerCase(); + return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0); + })(), + isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent), + isArray: function (arr) { + return Object.prototype.toString.apply(arr) === '[object Array]'; + }, + /*================================================== + Browser + ====================================================*/ + browser: { + ie: window.navigator.pointerEnabled || window.navigator.msPointerEnabled, + ieTouch: (window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 1) || (window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 1) + }, + /*================================================== + Devices + ====================================================*/ + device: (function () { + var ua = navigator.userAgent; + var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); + var ipad = ua.match(/(iPad).*OS\s([\d_]+)/); + var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/); + var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/); + return { + ios: ipad || iphone || ipod, + android: android + }; + })(), + /*================================================== + Feature Detection + ====================================================*/ + support: { + touch : (window.Modernizr && Modernizr.touch === true) || (function () { + return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); + })(), + + transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () { + var div = document.createElement('div').style; + return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div); + })(), + + flexbox: (function () { + var div = document.createElement('div').style; + var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' '); + for (var i = 0; i < styles.length; i++) { + if (styles[i] in div) return true; + } + })(), - // All nodes removed from the DOM via various jQuery APIs like .remove() - // are passed through jQuery.cleanData. Monkey-patch this method to fire - // the $destroy event on all removed nodes. - originalCleanData = jQuery.cleanData; - jQuery.cleanData = function(elems) { - var events; - if (!skipDestroyOnNextJQueryCleanData) { - for (var i = 0, elem; (elem = elems[i]) != null; i++) { - events = jQuery._data(elem, "events"); - if (events && events.$destroy) { - jQuery(elem).triggerHandler('$destroy'); - } - } - } else { - skipDestroyOnNextJQueryCleanData = false; - } - originalCleanData(elems); + observer: (function () { + return ('MutationObserver' in window || 'WebkitMutationObserver' in window); + })() + }, + /*================================================== + Plugins + ====================================================*/ + plugins: {} }; - } else { - jqLite = JQLite; - } - angular.element = jqLite; - // Prevent double-proxying. - bindJQueryFired = true; -} + /*=========================== + Dom7 Library + ===========================*/ + var Dom7 = (function () { + var Dom7 = function (arr) { + var _this = this, i = 0; + // Create array-like object + for (i = 0; i < arr.length; i++) { + _this[i] = arr[i]; + } + _this.length = arr.length; + // Return collection with methods + return this; + }; + var $ = function (selector, context) { + var arr = [], i = 0; + if (selector && !context) { + if (selector instanceof Dom7) { + return selector; + } + } + if (selector) { + // String + if (typeof selector === 'string') { + var els, tempParent, html = selector.trim(); + if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) { + var toCreate = 'div'; + if (html.indexOf('<li') === 0) toCreate = 'ul'; + if (html.indexOf('<tr') === 0) toCreate = 'tbody'; + if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr'; + if (html.indexOf('<tbody') === 0) toCreate = 'table'; + if (html.indexOf('<option') === 0) toCreate = 'select'; + tempParent = document.createElement(toCreate); + tempParent.innerHTML = selector; + for (i = 0; i < tempParent.childNodes.length; i++) { + arr.push(tempParent.childNodes[i]); + } + } + else { + if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) { + // Pure ID selector + els = [document.getElementById(selector.split('#')[1])]; + } + else { + // Other selectors + els = (context || document).querySelectorAll(selector); + } + for (i = 0; i < els.length; i++) { + if (els[i]) arr.push(els[i]); + } + } + } + // Node/element + else if (selector.nodeType || selector === window || selector === document) { + arr.push(selector); + } + //Array of elements or instance of Dom + else if (selector.length > 0 && selector[0].nodeType) { + for (i = 0; i < selector.length; i++) { + arr.push(selector[i]); + } + } + } + return new Dom7(arr); + }; + Dom7.prototype = { + // Classes and attriutes + addClass: function (className) { + if (typeof className === 'undefined') { + return this; + } + var classes = className.split(' '); + for (var i = 0; i < classes.length; i++) { + for (var j = 0; j < this.length; j++) { + this[j].classList.add(classes[i]); + } + } + return this; + }, + removeClass: function (className) { + var classes = className.split(' '); + for (var i = 0; i < classes.length; i++) { + for (var j = 0; j < this.length; j++) { + this[j].classList.remove(classes[i]); + } + } + return this; + }, + hasClass: function (className) { + if (!this[0]) return false; + else return this[0].classList.contains(className); + }, + toggleClass: function (className) { + var classes = className.split(' '); + for (var i = 0; i < classes.length; i++) { + for (var j = 0; j < this.length; j++) { + this[j].classList.toggle(classes[i]); + } + } + return this; + }, + attr: function (attrs, value) { + if (arguments.length === 1 && typeof attrs === 'string') { + // Get attr + if (this[0]) return this[0].getAttribute(attrs); + else return undefined; + } + else { + // Set attrs + for (var i = 0; i < this.length; i++) { + if (arguments.length === 2) { + // String + this[i].setAttribute(attrs, value); + } + else { + // Object + for (var attrName in attrs) { + this[i][attrName] = attrs[attrName]; + this[i].setAttribute(attrName, attrs[attrName]); + } + } + } + return this; + } + }, + removeAttr: function (attr) { + for (var i = 0; i < this.length; i++) { + this[i].removeAttribute(attr); + } + return this; + }, + data: function (key, value) { + if (typeof value === 'undefined') { + // Get value + if (this[0]) { + var dataKey = this[0].getAttribute('data-' + key); + if (dataKey) return dataKey; + else if (this[0].dom7ElementDataStorage && (key in this[0].dom7ElementDataStorage)) return this[0].dom7ElementDataStorage[key]; + else return undefined; + } + else return undefined; + } + else { + // Set value + for (var i = 0; i < this.length; i++) { + var el = this[i]; + if (!el.dom7ElementDataStorage) el.dom7ElementDataStorage = {}; + el.dom7ElementDataStorage[key] = value; + } + return this; + } + }, + // Transforms + transform : function (transform) { + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform; + } + return this; + }, + transition: function (duration) { + if (typeof duration !== 'string') { + duration = duration + 'ms'; + } + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration; + } + return this; + }, + //Events + on: function (eventName, targetSelector, listener, capture) { + function handleLiveEvent(e) { + var target = e.target; + if ($(target).is(targetSelector)) listener.call(target, e); + else { + var parents = $(target).parents(); + for (var k = 0; k < parents.length; k++) { + if ($(parents[k]).is(targetSelector)) listener.call(parents[k], e); + } + } + } + var events = eventName.split(' '); + var i, j; + for (i = 0; i < this.length; i++) { + if (typeof targetSelector === 'function' || targetSelector === false) { + // Usual events + if (typeof targetSelector === 'function') { + listener = arguments[1]; + capture = arguments[2] || false; + } + for (j = 0; j < events.length; j++) { + this[i].addEventListener(events[j], listener, capture); + } + } + else { + //Live events + for (j = 0; j < events.length; j++) { + if (!this[i].dom7LiveListeners) this[i].dom7LiveListeners = []; + this[i].dom7LiveListeners.push({listener: listener, liveListener: handleLiveEvent}); + this[i].addEventListener(events[j], handleLiveEvent, capture); + } + } + } -/** - * throw error if the argument is falsy. - */ -function assertArg(arg, name, reason) { - if (!arg) { - throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); - } - return arg; -} + return this; + }, + off: function (eventName, targetSelector, listener, capture) { + var events = eventName.split(' '); + for (var i = 0; i < events.length; i++) { + for (var j = 0; j < this.length; j++) { + if (typeof targetSelector === 'function' || targetSelector === false) { + // Usual events + if (typeof targetSelector === 'function') { + listener = arguments[1]; + capture = arguments[2] || false; + } + this[j].removeEventListener(events[i], listener, capture); + } + else { + // Live event + if (this[j].dom7LiveListeners) { + for (var k = 0; k < this[j].dom7LiveListeners.length; k++) { + if (this[j].dom7LiveListeners[k].listener === listener) { + this[j].removeEventListener(events[i], this[j].dom7LiveListeners[k].liveListener, capture); + } + } + } + } + } + } + return this; + }, + once: function (eventName, targetSelector, listener, capture) { + var dom = this; + if (typeof targetSelector === 'function') { + targetSelector = false; + listener = arguments[1]; + capture = arguments[2]; + } + function proxy(e) { + listener(e); + dom.off(eventName, targetSelector, proxy, capture); + } + dom.on(eventName, targetSelector, proxy, capture); + }, + trigger: function (eventName, eventData) { + for (var i = 0; i < this.length; i++) { + var evt; + try { + evt = new window.CustomEvent(eventName, {detail: eventData, bubbles: true, cancelable: true}); + } + catch (e) { + evt = document.createEvent('Event'); + evt.initEvent(eventName, true, true); + evt.detail = eventData; + } + this[i].dispatchEvent(evt); + } + return this; + }, + transitionEnd: function (callback) { + var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'], + i, j, dom = this; + function fireCallBack(e) { + /*jshint validthis:true */ + if (e.target !== this) return; + callback.call(this, e); + for (i = 0; i < events.length; i++) { + dom.off(events[i], fireCallBack); + } + } + if (callback) { + for (i = 0; i < events.length; i++) { + dom.on(events[i], fireCallBack); + } + } + return this; + }, + // Sizing/Styles + width: function () { + if (this[0] === window) { + return window.innerWidth; + } + else { + if (this.length > 0) { + return parseFloat(this.css('width')); + } + else { + return null; + } + } + }, + outerWidth: function (includeMargins) { + if (this.length > 0) { + if (includeMargins) + return this[0].offsetWidth + parseFloat(this.css('margin-right')) + parseFloat(this.css('margin-left')); + else + return this[0].offsetWidth; + } + else return null; + }, + height: function () { + if (this[0] === window) { + return window.innerHeight; + } + else { + if (this.length > 0) { + return parseFloat(this.css('height')); + } + else { + return null; + } + } + }, + outerHeight: function (includeMargins) { + if (this.length > 0) { + if (includeMargins) + return this[0].offsetHeight + parseFloat(this.css('margin-top')) + parseFloat(this.css('margin-bottom')); + else + return this[0].offsetHeight; + } + else return null; + }, + offset: function () { + if (this.length > 0) { + var el = this[0]; + var box = el.getBoundingClientRect(); + var body = document.body; + var clientTop = el.clientTop || body.clientTop || 0; + var clientLeft = el.clientLeft || body.clientLeft || 0; + var scrollTop = window.pageYOffset || el.scrollTop; + var scrollLeft = window.pageXOffset || el.scrollLeft; + return { + top: box.top + scrollTop - clientTop, + left: box.left + scrollLeft - clientLeft + }; + } + else { + return null; + } + }, + css: function (props, value) { + var i; + if (arguments.length === 1) { + if (typeof props === 'string') { + if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props); + } + else { + for (i = 0; i < this.length; i++) { + for (var prop in props) { + this[i].style[prop] = props[prop]; + } + } + return this; + } + } + if (arguments.length === 2 && typeof props === 'string') { + for (i = 0; i < this.length; i++) { + this[i].style[props] = value; + } + return this; + } + return this; + }, -function assertArgFn(arg, name, acceptArrayAnnotation) { - if (acceptArrayAnnotation && isArray(arg)) { - arg = arg[arg.length - 1]; - } + //Dom manipulation + each: function (callback) { + for (var i = 0; i < this.length; i++) { + callback.call(this[i], i, this[i]); + } + return this; + }, + html: function (html) { + if (typeof html === 'undefined') { + return this[0] ? this[0].innerHTML : undefined; + } + else { + for (var i = 0; i < this.length; i++) { + this[i].innerHTML = html; + } + return this; + } + }, + is: function (selector) { + if (!this[0]) return false; + var compareWith, i; + if (typeof selector === 'string') { + var el = this[0]; + if (el === document) return selector === document; + if (el === window) return selector === window; + + if (el.matches) return el.matches(selector); + else if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector); + else if (el.mozMatchesSelector) return el.mozMatchesSelector(selector); + else if (el.msMatchesSelector) return el.msMatchesSelector(selector); + else { + compareWith = $(selector); + for (i = 0; i < compareWith.length; i++) { + if (compareWith[i] === this[0]) return true; + } + return false; + } + } + else if (selector === document) return this[0] === document; + else if (selector === window) return this[0] === window; + else { + if (selector.nodeType || selector instanceof Dom7) { + compareWith = selector.nodeType ? [selector] : selector; + for (i = 0; i < compareWith.length; i++) { + if (compareWith[i] === this[0]) return true; + } + return false; + } + return false; + } - assertArg(isFunction(arg), name, 'not a function, got ' + - (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg)); - return arg; -} + }, + index: function () { + if (this[0]) { + var child = this[0]; + var i = 0; + while ((child = child.previousSibling) !== null) { + if (child.nodeType === 1) i++; + } + return i; + } + else return undefined; + }, + eq: function (index) { + if (typeof index === 'undefined') return this; + var length = this.length; + var returnIndex; + if (index > length - 1) { + return new Dom7([]); + } + if (index < 0) { + returnIndex = length + index; + if (returnIndex < 0) return new Dom7([]); + else return new Dom7([this[returnIndex]]); + } + return new Dom7([this[index]]); + }, + append: function (newChild) { + var i, j; + for (i = 0; i < this.length; i++) { + if (typeof newChild === 'string') { + var tempDiv = document.createElement('div'); + tempDiv.innerHTML = newChild; + while (tempDiv.firstChild) { + this[i].appendChild(tempDiv.firstChild); + } + } + else if (newChild instanceof Dom7) { + for (j = 0; j < newChild.length; j++) { + this[i].appendChild(newChild[j]); + } + } + else { + this[i].appendChild(newChild); + } + } + return this; + }, + prepend: function (newChild) { + var i, j; + for (i = 0; i < this.length; i++) { + if (typeof newChild === 'string') { + var tempDiv = document.createElement('div'); + tempDiv.innerHTML = newChild; + for (j = tempDiv.childNodes.length - 1; j >= 0; j--) { + this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]); + } + // this[i].insertAdjacentHTML('afterbegin', newChild); + } + else if (newChild instanceof Dom7) { + for (j = 0; j < newChild.length; j++) { + this[i].insertBefore(newChild[j], this[i].childNodes[0]); + } + } + else { + this[i].insertBefore(newChild, this[i].childNodes[0]); + } + } + return this; + }, + insertBefore: function (selector) { + var before = $(selector); + for (var i = 0; i < this.length; i++) { + if (before.length === 1) { + before[0].parentNode.insertBefore(this[i], before[0]); + } + else if (before.length > 1) { + for (var j = 0; j < before.length; j++) { + before[j].parentNode.insertBefore(this[i].cloneNode(true), before[j]); + } + } + } + }, + insertAfter: function (selector) { + var after = $(selector); + for (var i = 0; i < this.length; i++) { + if (after.length === 1) { + after[0].parentNode.insertBefore(this[i], after[0].nextSibling); + } + else if (after.length > 1) { + for (var j = 0; j < after.length; j++) { + after[j].parentNode.insertBefore(this[i].cloneNode(true), after[j].nextSibling); + } + } + } + }, + next: function (selector) { + if (this.length > 0) { + if (selector) { + if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) return new Dom7([this[0].nextElementSibling]); + else return new Dom7([]); + } + else { + if (this[0].nextElementSibling) return new Dom7([this[0].nextElementSibling]); + else return new Dom7([]); + } + } + else return new Dom7([]); + }, + nextAll: function (selector) { + var nextEls = []; + var el = this[0]; + if (!el) return new Dom7([]); + while (el.nextElementSibling) { + var next = el.nextElementSibling; + if (selector) { + if($(next).is(selector)) nextEls.push(next); + } + else nextEls.push(next); + el = next; + } + return new Dom7(nextEls); + }, + prev: function (selector) { + if (this.length > 0) { + if (selector) { + if (this[0].previousElementSibling && $(this[0].previousElementSibling).is(selector)) return new Dom7([this[0].previousElementSibling]); + else return new Dom7([]); + } + else { + if (this[0].previousElementSibling) return new Dom7([this[0].previousElementSibling]); + else return new Dom7([]); + } + } + else return new Dom7([]); + }, + prevAll: function (selector) { + var prevEls = []; + var el = this[0]; + if (!el) return new Dom7([]); + while (el.previousElementSibling) { + var prev = el.previousElementSibling; + if (selector) { + if($(prev).is(selector)) prevEls.push(prev); + } + else prevEls.push(prev); + el = prev; + } + return new Dom7(prevEls); + }, + parent: function (selector) { + var parents = []; + for (var i = 0; i < this.length; i++) { + if (selector) { + if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode); + } + else { + parents.push(this[i].parentNode); + } + } + return $($.unique(parents)); + }, + parents: function (selector) { + var parents = []; + for (var i = 0; i < this.length; i++) { + var parent = this[i].parentNode; + while (parent) { + if (selector) { + if ($(parent).is(selector)) parents.push(parent); + } + else { + parents.push(parent); + } + parent = parent.parentNode; + } + } + return $($.unique(parents)); + }, + find : function (selector) { + var foundElements = []; + for (var i = 0; i < this.length; i++) { + var found = this[i].querySelectorAll(selector); + for (var j = 0; j < found.length; j++) { + foundElements.push(found[j]); + } + } + return new Dom7(foundElements); + }, + children: function (selector) { + var children = []; + for (var i = 0; i < this.length; i++) { + var childNodes = this[i].childNodes; + + for (var j = 0; j < childNodes.length; j++) { + if (!selector) { + if (childNodes[j].nodeType === 1) children.push(childNodes[j]); + } + else { + if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) children.push(childNodes[j]); + } + } + } + return new Dom7($.unique(children)); + }, + remove: function () { + for (var i = 0; i < this.length; i++) { + if (this[i].parentNode) this[i].parentNode.removeChild(this[i]); + } + return this; + }, + add: function () { + var dom = this; + var i, j; + for (i = 0; i < arguments.length; i++) { + var toAdd = $(arguments[i]); + for (j = 0; j < toAdd.length; j++) { + dom[dom.length] = toAdd[j]; + dom.length++; + } + } + return dom; + } + }; + $.fn = Dom7.prototype; + $.unique = function (arr) { + var unique = []; + for (var i = 0; i < arr.length; i++) { + if (unique.indexOf(arr[i]) === -1) unique.push(arr[i]); + } + return unique; + }; -/** - * throw error if the name given is hasOwnProperty - * @param {String} name the name to test - * @param {String} context the context in which the name is used, such as module or directive - */ -function assertNotHasOwnProperty(name, context) { - if (name === 'hasOwnProperty') { - throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context); - } -} + return $; + })(); -/** - * Return the value accessible from the object by path. Any undefined traversals are ignored - * @param {Object} obj starting object - * @param {String} path path to traverse - * @param {boolean} [bindFnToScope=true] - * @returns {Object} value as accessible by path - */ -//TODO(misko): this function needs to be removed -function getter(obj, path, bindFnToScope) { - if (!path) return obj; - var keys = path.split('.'); - var key; - var lastInstance = obj; - var len = keys.length; - for (var i = 0; i < len; i++) { - key = keys[i]; - if (obj) { - obj = (lastInstance = obj)[key]; + /*=========================== + Get Dom libraries + ===========================*/ + var swiperDomPlugins = ['jQuery', 'Zepto', 'Dom7']; + for (var i = 0; i < swiperDomPlugins.length; i++) { + if (window[swiperDomPlugins[i]]) { + addLibraryPlugin(window[swiperDomPlugins[i]]); + } + } + // Required DOM Plugins + var domLib; + if (typeof Dom7 === 'undefined') { + domLib = window.Dom7 || window.Zepto || window.jQuery; + } + else { + domLib = Dom7; + } + + /*=========================== + Add .swiper plugin from Dom libraries + ===========================*/ + function addLibraryPlugin(lib) { + lib.fn.swiper = function (params) { + var firstInstance; + lib(this).each(function () { + var s = new Swiper(this, params); + if (!firstInstance) firstInstance = s; + }); + return firstInstance; + }; } - } - if (!bindFnToScope && isFunction(obj)) { - return bind(lastInstance, obj); - } - return obj; -} -/** - * Return the DOM siblings between the first and last node in the given array. - * @param {Array} array like object - * @returns {jqLite} jqLite collection containing the nodes - */ -function getBlockNodes(nodes) { - // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original - // collection, otherwise update the original collection. - var node = nodes[0]; - var endNode = nodes[nodes.length - 1]; - var blockNodes = [node]; + if (domLib) { + if (!('transitionEnd' in domLib.fn)) { + domLib.fn.transitionEnd = function (callback) { + var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'], + i, j, dom = this; + function fireCallBack(e) { + /*jshint validthis:true */ + if (e.target !== this) return; + callback.call(this, e); + for (i = 0; i < events.length; i++) { + dom.off(events[i], fireCallBack); + } + } + if (callback) { + for (i = 0; i < events.length; i++) { + dom.on(events[i], fireCallBack); + } + } + return this; + }; + } + if (!('transform' in domLib.fn)) { + domLib.fn.transform = function (transform) { + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform; + } + return this; + }; + } + if (!('transition' in domLib.fn)) { + domLib.fn.transition = function (duration) { + if (typeof duration !== 'string') { + duration = duration + 'ms'; + } + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration; + } + return this; + }; + } + } - do { - node = node.nextSibling; - if (!node) break; - blockNodes.push(node); - } while (node !== endNode); + ionic.views.Swiper = Swiper; +})(); - return jqLite(blockNodes); -} +(function(ionic) { +'use strict'; + ionic.views.Toggle = ionic.views.View.inherit({ + initialize: function(opts) { + var self = this; -/** - * Creates a new object without a prototype. This object is useful for lookup without having to - * guard against prototypically inherited properties via hasOwnProperty. - * - * Related micro-benchmarks: - * - http://jsperf.com/object-create2 - * - http://jsperf.com/proto-map-lookup/2 - * - http://jsperf.com/for-in-vs-object-keys2 - * - * @returns {Object} - */ -function createMap() { - return Object.create(null); -} + this.el = opts.el; + this.checkbox = opts.checkbox; + this.track = opts.track; + this.handle = opts.handle; + this.openPercent = -1; + this.onChange = opts.onChange || function() {}; -var NODE_TYPE_ELEMENT = 1; -var NODE_TYPE_TEXT = 3; -var NODE_TYPE_COMMENT = 8; -var NODE_TYPE_DOCUMENT = 9; -var NODE_TYPE_DOCUMENT_FRAGMENT = 11; + this.triggerThreshold = opts.triggerThreshold || 20; -/** - * @ngdoc type - * @name angular.Module - * @module ng - * @description - * - * Interface for configuring angular {@link angular.module modules}. - */ + this.dragStartHandler = function(e) { + self.dragStart(e); + }; + this.dragHandler = function(e) { + self.drag(e); + }; + this.holdHandler = function(e) { + self.hold(e); + }; + this.releaseHandler = function(e) { + self.release(e); + }; -function setupModuleLoader(window) { + this.dragStartGesture = ionic.onGesture('dragstart', this.dragStartHandler, this.el); + this.dragGesture = ionic.onGesture('drag', this.dragHandler, this.el); + this.dragHoldGesture = ionic.onGesture('hold', this.holdHandler, this.el); + this.dragReleaseGesture = ionic.onGesture('release', this.releaseHandler, this.el); + }, - var $injectorMinErr = minErr('$injector'); - var ngMinErr = minErr('ng'); + destroy: function() { + ionic.offGesture(this.dragStartGesture, 'dragstart', this.dragStartGesture); + ionic.offGesture(this.dragGesture, 'drag', this.dragGesture); + ionic.offGesture(this.dragHoldGesture, 'hold', this.holdHandler); + ionic.offGesture(this.dragReleaseGesture, 'release', this.releaseHandler); + }, - function ensure(obj, name, factory) { - return obj[name] || (obj[name] = factory()); - } + tap: function() { + if(this.el.getAttribute('disabled') !== 'disabled') { + this.val( !this.checkbox.checked ); + } + }, - var angular = ensure(window, 'angular', Object); + dragStart: function(e) { + if(this.checkbox.disabled) return; - // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap - angular.$$minErr = angular.$$minErr || minErr; + this._dragInfo = { + width: this.el.offsetWidth, + left: this.el.offsetLeft, + right: this.el.offsetLeft + this.el.offsetWidth, + triggerX: this.el.offsetWidth / 2, + initialState: this.checkbox.checked + }; - return ensure(angular, 'module', function() { - /** @type {Object.<string, angular.Module>} */ - var modules = {}; + // Stop any parent dragging + e.gesture.srcEvent.preventDefault(); - /** - * @ngdoc function - * @name angular.module - * @module ng - * @description - * - * The `angular.module` is a global place for creating, registering and retrieving Angular - * modules. - * All modules (angular core or 3rd party) that should be available to an application must be - * registered using this mechanism. - * - * When passed two or more arguments, a new module is created. If passed only one argument, an - * existing module (the name passed as the first argument to `module`) is retrieved. - * - * - * # Module - * - * A module is a collection of services, directives, controllers, filters, and configuration information. - * `angular.module` is used to configure the {@link auto.$injector $injector}. - * - * ```js - * // Create a new module - * var myModule = angular.module('myModule', []); - * - * // register a new service - * myModule.value('appName', 'MyCoolApp'); - * - * // configure existing services inside initialization blocks. - * myModule.config(['$locationProvider', function($locationProvider) { - * // Configure existing providers - * $locationProvider.hashPrefix('!'); - * }]); - * ``` - * - * Then you can create an injector and load your modules like this: - * - * ```js - * var injector = angular.injector(['ng', 'myModule']) - * ``` - * - * However it's more likely that you'll just use - * {@link ng.directive:ngApp ngApp} or - * {@link angular.bootstrap} to simplify this process for you. - * - * @param {!string} name The name of the module to create or retrieve. - * @param {!Array.<string>=} requires If specified then new module is being created. If - * unspecified then the module is being retrieved for further configuration. - * @param {Function=} configFn Optional configuration function for the module. Same as - * {@link angular.Module#config Module#config()}. - * @returns {module} new module with the {@link angular.Module} api. - */ - return function module(name, requires, configFn) { - var assertNotHasOwnProperty = function(name, context) { - if (name === 'hasOwnProperty') { - throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); - } - }; + // Trigger hold styles + this.hold(e); + }, - assertNotHasOwnProperty(name, 'module'); - if (requires && modules.hasOwnProperty(name)) { - modules[name] = null; - } - return ensure(modules, name, function() { - if (!requires) { - throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + - "the module name or forgot to load it. If registering a module ensure that you " + - "specify the dependencies as the second argument.", name); - } + drag: function(e) { + var self = this; + if(!this._dragInfo) { return; } - /** @type {!Array.<Array.<*>>} */ - var invokeQueue = []; + // Stop any parent dragging + e.gesture.srcEvent.preventDefault(); - /** @type {!Array.<Function>} */ - var configBlocks = []; + ionic.requestAnimationFrame(function () { + if (!self._dragInfo) { return; } - /** @type {!Array.<Function>} */ - var runBlocks = []; + var px = e.gesture.touches[0].pageX - self._dragInfo.left; + var mx = self._dragInfo.width - self.triggerThreshold; - var config = invokeLater('$injector', 'invoke', 'push', configBlocks); + // The initial state was on, so "tend towards" on + if(self._dragInfo.initialState) { + if(px < self.triggerThreshold) { + self.setOpenPercent(0); + } else if(px > self._dragInfo.triggerX) { + self.setOpenPercent(100); + } + } else { + // The initial state was off, so "tend towards" off + if(px < self._dragInfo.triggerX) { + self.setOpenPercent(0); + } else if(px > mx) { + self.setOpenPercent(100); + } + } + }); + }, - /** @type {angular.Module} */ - var moduleInstance = { - // Private state - _invokeQueue: invokeQueue, - _configBlocks: configBlocks, - _runBlocks: runBlocks, + endDrag: function() { + this._dragInfo = null; + }, - /** - * @ngdoc property - * @name angular.Module#requires - * @module ng - * - * @description - * Holds the list of modules which the injector will load before the current module is - * loaded. - */ - requires: requires, + hold: function() { + this.el.classList.add('dragging'); + }, + release: function(e) { + this.el.classList.remove('dragging'); + this.endDrag(e); + }, - /** - * @ngdoc property - * @name angular.Module#name - * @module ng - * - * @description - * Name of the module. - */ - name: name, + setOpenPercent: function(openPercent) { + // only make a change if the new open percent has changed + if(this.openPercent < 0 || (openPercent < (this.openPercent - 3) || openPercent > (this.openPercent + 3) ) ) { + this.openPercent = openPercent; - /** - * @ngdoc method - * @name angular.Module#provider - * @module ng - * @param {string} name service name - * @param {Function} providerType Construction function for creating new instance of the - * service. - * @description - * See {@link auto.$provide#provider $provide.provider()}. - */ - provider: invokeLater('$provide', 'provider'), + if(openPercent === 0) { + this.val(false); + } else if(openPercent === 100) { + this.val(true); + } else { + var openPixel = Math.round( (openPercent / 100) * this.track.offsetWidth - (this.handle.offsetWidth) ); + openPixel = (openPixel < 1 ? 0 : openPixel); + this.handle.style[ionic.CSS.TRANSFORM] = 'translate3d(' + openPixel + 'px,0,0)'; + } + } + }, - /** - * @ngdoc method - * @name angular.Module#factory - * @module ng - * @param {string} name service name - * @param {Function} providerFunction Function for creating new instance of the service. - * @description - * See {@link auto.$provide#factory $provide.factory()}. - */ - factory: invokeLater('$provide', 'factory'), + val: function(value) { + if(value === true || value === false) { + if(this.handle.style[ionic.CSS.TRANSFORM] !== "") { + this.handle.style[ionic.CSS.TRANSFORM] = ""; + } + this.checkbox.checked = value; + this.openPercent = (value ? 100 : 0); + this.onChange && this.onChange(); + } + return this.checkbox.checked; + } - /** - * @ngdoc method - * @name angular.Module#service - * @module ng - * @param {string} name service name - * @param {Function} constructor A constructor function that will be instantiated. - * @description - * See {@link auto.$provide#service $provide.service()}. - */ - service: invokeLater('$provide', 'service'), + }); - /** - * @ngdoc method - * @name angular.Module#value - * @module ng - * @param {string} name service name - * @param {*} object Service instance object. - * @description - * See {@link auto.$provide#value $provide.value()}. - */ - value: invokeLater('$provide', 'value'), +})(ionic); - /** - * @ngdoc method - * @name angular.Module#constant - * @module ng - * @param {string} name constant name - * @param {*} object Constant value. - * @description - * Because the constant are fixed, they get applied before other provide methods. - * See {@link auto.$provide#constant $provide.constant()}. - */ - constant: invokeLater('$provide', 'constant', 'unshift'), +})(); +/*! + * ionic.bundle.js is a concatenation of: + * ionic.js, angular.js, angular-animate.js, + * angular-sanitize.js, angular-ui-router.js, + * and ionic-angular.js + */ - /** - * @ngdoc method - * @name angular.Module#animation - * @module ng - * @param {string} name animation name - * @param {Function} animationFactory Factory function for creating new instance of an - * animation. - * @description - * - * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. - * - * - * Defines an animation hook that can be later used with - * {@link ngAnimate.$animate $animate} service and directives that use this service. - * - * ```js - * module.animation('.animation-name', function($inject1, $inject2) { - * return { - * eventName : function(element, done) { - * //code to run the animation - * //once complete, then run done() - * return function cancellationFunction(element) { - * //code to cancel the animation - * } - * } - * } - * }) - * ``` - * - * See {@link ng.$animateProvider#register $animateProvider.register()} and - * {@link ngAnimate ngAnimate module} for more information. - */ - animation: invokeLater('$animateProvider', 'register'), +/** + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, document, undefined) {'use strict'; - /** - * @ngdoc method - * @name angular.Module#filter - * @module ng - * @param {string} name Filter name. - * @param {Function} filterFactory Factory function for creating new instance of filter. - * @description - * See {@link ng.$filterProvider#register $filterProvider.register()}. - */ - filter: invokeLater('$filterProvider', 'register'), +/** + * @description + * + * This object provides a utility for producing rich Error messages within + * Angular. It can be called as follows: + * + * var exampleMinErr = minErr('example'); + * throw exampleMinErr('one', 'This {0} is {1}', foo, bar); + * + * The above creates an instance of minErr in the example namespace. The + * resulting error will have a namespaced error code of example.one. The + * resulting error will replace {0} with the value of foo, and {1} with the + * value of bar. The object is not restricted in the number of arguments it can + * take. + * + * If fewer arguments are specified than necessary for interpolation, the extra + * interpolation markers will be preserved in the final string. + * + * Since data will be parsed statically during a build step, some restrictions + * are applied with respect to how minErr instances are created and called. + * Instances should have names of the form namespaceMinErr for a minErr created + * using minErr('namespace') . Error codes, namespaces and template strings + * should all be static strings, not variables or general expressions. + * + * @param {string} module The namespace to use for the new minErr instance. + * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning + * error from returned function, for cases when a particular type of error is useful. + * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance + */ - /** - * @ngdoc method - * @name angular.Module#controller - * @module ng - * @param {string|Object} name Controller name, or an object map of controllers where the - * keys are the names and the values are the constructors. - * @param {Function} constructor Controller constructor function. - * @description - * See {@link ng.$controllerProvider#register $controllerProvider.register()}. - */ - controller: invokeLater('$controllerProvider', 'register'), +function minErr(module, ErrorConstructor) { + ErrorConstructor = ErrorConstructor || Error; + return function() { + var SKIP_INDEXES = 2; - /** - * @ngdoc method - * @name angular.Module#directive - * @module ng - * @param {string|Object} name Directive name, or an object map of directives where the - * keys are the names and the values are the factories. - * @param {Function} directiveFactory Factory function for creating new instance of - * directives. - * @description - * See {@link ng.$compileProvider#directive $compileProvider.directive()}. - */ - directive: invokeLater('$compileProvider', 'directive'), + var templateArgs = arguments, + code = templateArgs[0], + message = '[' + (module ? module + ':' : '') + code + '] ', + template = templateArgs[1], + paramPrefix, i; - /** - * @ngdoc method - * @name angular.Module#config - * @module ng - * @param {Function} configFn Execute this function on module load. Useful for service - * configuration. - * @description - * Use this method to register work which needs to be performed on module loading. - * For more about how to configure services, see - * {@link providers#provider-recipe Provider Recipe}. - */ - config: config, + message += template.replace(/\{\d+\}/g, function(match) { + var index = +match.slice(1, -1), + shiftedIndex = index + SKIP_INDEXES; - /** - * @ngdoc method - * @name angular.Module#run - * @module ng - * @param {Function} initializationFn Execute this function after injector creation. - * Useful for application initialization. - * @description - * Use this method to register work which should be performed when the injector is done - * loading all modules. - */ - run: function(block) { - runBlocks.push(block); - return this; - } - }; + if (shiftedIndex < templateArgs.length) { + return toDebugString(templateArgs[shiftedIndex]); + } - if (configFn) { - config(configFn); - } + return match; + }); - return moduleInstance; + message += '\nhttp://errors.angularjs.org/1.4.3/' + + (module ? module + '/' : '') + code; - /** - * @param {string} provider - * @param {string} method - * @param {String=} insertMethod - * @returns {angular.Module} - */ - function invokeLater(provider, method, insertMethod, queue) { - if (!queue) queue = invokeQueue; - return function() { - queue[insertMethod || 'push']([provider, method, arguments]); - return moduleInstance; - }; - } - }); - }; - }); + for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') { + message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' + + encodeURIComponent(toDebugString(templateArgs[i])); + } + return new ErrorConstructor(message); + }; } -/* global: toDebugString: true */ +/* We need to tell jshint what variables are being exported */ +/* global angular: true, + msie: true, + jqLite: true, + jQuery: true, + slice: true, + splice: true, + push: true, + toString: true, + ngMinErr: true, + angularModule: true, + uid: true, + REGEX_STRING_REGEXP: true, + VALIDITY_STATE_PROPERTY: true, -function serializeObject(obj) { - var seen = []; + lowercase: true, + uppercase: true, + manualLowercase: true, + manualUppercase: true, + nodeName_: true, + isArrayLike: true, + forEach: true, + forEachSorted: true, + reverseParams: true, + nextUid: true, + setHashKey: true, + extend: true, + toInt: true, + inherit: true, + merge: true, + noop: true, + identity: true, + valueFn: true, + isUndefined: true, + isDefined: true, + isObject: true, + isBlankObject: true, + isString: true, + isNumber: true, + isDate: true, + isArray: true, + isFunction: true, + isRegExp: true, + isWindow: true, + isScope: true, + isFile: true, + isFormData: true, + isBlob: true, + isBoolean: true, + isPromiseLike: true, + trim: true, + escapeForRegexp: true, + isElement: true, + makeMap: true, + includes: true, + arrayRemove: true, + copy: true, + shallowCopy: true, + equals: true, + csp: true, + jq: true, + concat: true, + sliceArgs: true, + bind: true, + toJsonReplacer: true, + toJson: true, + fromJson: true, + convertTimezoneToLocal: true, + timezoneToOffset: true, + startingTag: true, + tryDecodeURIComponent: true, + parseKeyValue: true, + toKeyValue: true, + encodeUriSegment: true, + encodeUriQuery: true, + angularInit: true, + bootstrap: true, + getTestability: true, + snake_case: true, + bindJQuery: true, + assertArg: true, + assertArgFn: true, + assertNotHasOwnProperty: true, + getter: true, + getBlockNodes: true, + hasOwnProperty: true, + createMap: true, - return JSON.stringify(obj, function(key, val) { - val = toJsonReplacer(key, val); - if (isObject(val)) { + NODE_TYPE_ELEMENT: true, + NODE_TYPE_ATTRIBUTE: true, + NODE_TYPE_TEXT: true, + NODE_TYPE_COMMENT: true, + NODE_TYPE_DOCUMENT: true, + NODE_TYPE_DOCUMENT_FRAGMENT: true, +*/ - if (seen.indexOf(val) >= 0) return '<<already seen>>'; +//////////////////////////////////// - seen.push(val); - } - return val; - }); -} +/** + * @ngdoc module + * @name ng + * @module ng + * @description + * + * # ng (core module) + * The ng module is loaded by default when an AngularJS application is started. The module itself + * contains the essential components for an AngularJS application to function. The table below + * lists a high level breakdown of each of the services/factories, filters, directives and testing + * components available within this core module. + * + * <div doc-module-components="ng"></div> + */ -function toDebugString(obj) { - if (typeof obj === 'function') { - return obj.toString().replace(/ \{[\s\S]*$/, ''); - } else if (typeof obj === 'undefined') { - return 'undefined'; - } else if (typeof obj !== 'string') { - return serializeObject(obj); - } - return obj; -} +var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/; -/* global angularModule: true, - version: true, - - $LocaleProvider, - $CompileProvider, - - htmlAnchorDirective, - inputDirective, - inputDirective, - formDirective, - scriptDirective, - selectDirective, - styleDirective, - optionDirective, - ngBindDirective, - ngBindHtmlDirective, - ngBindTemplateDirective, - ngClassDirective, - ngClassEvenDirective, - ngClassOddDirective, - ngCspDirective, - ngCloakDirective, - ngControllerDirective, - ngFormDirective, - ngHideDirective, - ngIfDirective, - ngIncludeDirective, - ngIncludeFillContentDirective, - ngInitDirective, - ngNonBindableDirective, - ngPluralizeDirective, - ngRepeatDirective, - ngShowDirective, - ngStyleDirective, - ngSwitchDirective, - ngSwitchWhenDirective, - ngSwitchDefaultDirective, - ngOptionsDirective, - ngTranscludeDirective, - ngModelDirective, - ngListDirective, - ngChangeDirective, - patternDirective, - patternDirective, - requiredDirective, - requiredDirective, - minlengthDirective, - minlengthDirective, - maxlengthDirective, - maxlengthDirective, - ngValueDirective, - ngModelOptionsDirective, - ngAttributeAliasDirectives, - ngEventDirectives, - - $AnchorScrollProvider, - $AnimateProvider, - $BrowserProvider, - $CacheFactoryProvider, - $ControllerProvider, - $DocumentProvider, - $ExceptionHandlerProvider, - $FilterProvider, - $InterpolateProvider, - $IntervalProvider, - $HttpProvider, - $HttpBackendProvider, - $LocationProvider, - $LogProvider, - $ParseProvider, - $RootScopeProvider, - $QProvider, - $$QProvider, - $$SanitizeUriProvider, - $SceProvider, - $SceDelegateProvider, - $SnifferProvider, - $TemplateCacheProvider, - $TemplateRequestProvider, - $$TestabilityProvider, - $TimeoutProvider, - $$RAFProvider, - $$AsyncCallbackProvider, - $WindowProvider, - $$jqLiteProvider -*/ +// The name of a form control's ValidityState property. +// This is used so that it's possible for internal tests to create mock ValidityStates. +var VALIDITY_STATE_PROPERTY = 'validity'; +/** + * @ngdoc function + * @name angular.lowercase + * @module ng + * @kind function + * + * @description Converts the specified string to lowercase. + * @param {string} string String to be converted to lowercase. + * @returns {string} Lowercased string. + */ +var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;}; +var hasOwnProperty = Object.prototype.hasOwnProperty; /** - * @ngdoc object - * @name angular.version + * @ngdoc function + * @name angular.uppercase * @module ng - * @description - * An object that contains information about the current AngularJS version. This object has the - * following properties: + * @kind function * - * - `full` – `{string}` – Full version string, such as "0.9.18". - * - `major` – `{number}` – Major version number, such as "0". - * - `minor` – `{number}` – Minor version number, such as "9". - * - `dot` – `{number}` – Dot version number, such as "18". - * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". + * @description Converts the specified string to uppercase. + * @param {string} string String to be converted to uppercase. + * @returns {string} Uppercased string. */ -var version = { - full: '1.3.13', // all of these placeholder strings will be replaced by grunt's - major: 1, // package task - minor: 3, - dot: 13, - codeName: 'meticulous-riffleshuffle' +var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;}; + + +var manualLowercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) + : s; +}; +var manualUppercase = function(s) { + /* jshint bitwise: false */ + return isString(s) + ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) + : s; }; -function publishExternalAPI(angular) { - extend(angular, { - 'bootstrap': bootstrap, - 'copy': copy, - 'extend': extend, - 'equals': equals, - 'element': jqLite, - 'forEach': forEach, - 'injector': createInjector, - 'noop': noop, - 'bind': bind, - 'toJson': toJson, - 'fromJson': fromJson, - 'identity': identity, - 'isUndefined': isUndefined, - 'isDefined': isDefined, - 'isString': isString, - 'isFunction': isFunction, - 'isObject': isObject, - 'isNumber': isNumber, - 'isElement': isElement, - 'isArray': isArray, - 'version': version, - 'isDate': isDate, - 'lowercase': lowercase, - 'uppercase': uppercase, - 'callbacks': {counter: 0}, - 'getTestability': getTestability, - '$$minErr': minErr, - '$$csp': csp, - 'reloadWithDebugInfo': reloadWithDebugInfo - }); +// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish +// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods +// with correct but slower alternatives. +if ('i' !== 'I'.toLowerCase()) { + lowercase = manualLowercase; + uppercase = manualUppercase; +} - angularModule = setupModuleLoader(window); - try { - angularModule('ngLocale'); - } catch (e) { - angularModule('ngLocale', []).provider('$locale', $LocaleProvider); + +var + msie, // holds major version number for IE, or NaN if UA is not IE. + jqLite, // delay binding since jQuery could be loaded after us. + jQuery, // delay binding + slice = [].slice, + splice = [].splice, + push = [].push, + toString = Object.prototype.toString, + getPrototypeOf = Object.getPrototypeOf, + ngMinErr = minErr('ng'), + + /** @name angular */ + angular = window.angular || (window.angular = {}), + angularModule, + uid = 0; + +/** + * documentMode is an IE-only property + * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx + */ +msie = document.documentMode; + + +/** + * @private + * @param {*} obj + * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, + * String ...) + */ +function isArrayLike(obj) { + if (obj == null || isWindow(obj)) { + return false; } - angularModule('ng', ['ngLocale'], ['$provide', - function ngModule($provide) { - // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it. - $provide.provider({ - $$sanitizeUri: $$SanitizeUriProvider - }); - $provide.provider('$compile', $CompileProvider). - directive({ - a: htmlAnchorDirective, - input: inputDirective, - textarea: inputDirective, - form: formDirective, - script: scriptDirective, - select: selectDirective, - style: styleDirective, - option: optionDirective, - ngBind: ngBindDirective, - ngBindHtml: ngBindHtmlDirective, - ngBindTemplate: ngBindTemplateDirective, - ngClass: ngClassDirective, - ngClassEven: ngClassEvenDirective, - ngClassOdd: ngClassOddDirective, - ngCloak: ngCloakDirective, - ngController: ngControllerDirective, - ngForm: ngFormDirective, - ngHide: ngHideDirective, - ngIf: ngIfDirective, - ngInclude: ngIncludeDirective, - ngInit: ngInitDirective, - ngNonBindable: ngNonBindableDirective, - ngPluralize: ngPluralizeDirective, - ngRepeat: ngRepeatDirective, - ngShow: ngShowDirective, - ngStyle: ngStyleDirective, - ngSwitch: ngSwitchDirective, - ngSwitchWhen: ngSwitchWhenDirective, - ngSwitchDefault: ngSwitchDefaultDirective, - ngOptions: ngOptionsDirective, - ngTransclude: ngTranscludeDirective, - ngModel: ngModelDirective, - ngList: ngListDirective, - ngChange: ngChangeDirective, - pattern: patternDirective, - ngPattern: patternDirective, - required: requiredDirective, - ngRequired: requiredDirective, - minlength: minlengthDirective, - ngMinlength: minlengthDirective, - maxlength: maxlengthDirective, - ngMaxlength: maxlengthDirective, - ngValue: ngValueDirective, - ngModelOptions: ngModelOptionsDirective - }). - directive({ - ngInclude: ngIncludeFillContentDirective - }). - directive(ngAttributeAliasDirectives). - directive(ngEventDirectives); - $provide.provider({ - $anchorScroll: $AnchorScrollProvider, - $animate: $AnimateProvider, - $browser: $BrowserProvider, - $cacheFactory: $CacheFactoryProvider, - $controller: $ControllerProvider, - $document: $DocumentProvider, - $exceptionHandler: $ExceptionHandlerProvider, - $filter: $FilterProvider, - $interpolate: $InterpolateProvider, - $interval: $IntervalProvider, - $http: $HttpProvider, - $httpBackend: $HttpBackendProvider, - $location: $LocationProvider, - $log: $LogProvider, - $parse: $ParseProvider, - $rootScope: $RootScopeProvider, - $q: $QProvider, - $$q: $$QProvider, - $sce: $SceProvider, - $sceDelegate: $SceDelegateProvider, - $sniffer: $SnifferProvider, - $templateCache: $TemplateCacheProvider, - $templateRequest: $TemplateRequestProvider, - $$testability: $$TestabilityProvider, - $timeout: $TimeoutProvider, - $window: $WindowProvider, - $$rAF: $$RAFProvider, - $$asyncCallback: $$AsyncCallbackProvider, - $$jqLite: $$jqLiteProvider - }); - } - ]); -} + // Support: iOS 8.2 (not reproducible in simulator) + // "length" in obj used to prevent JIT error (gh-11508) + var length = "length" in Object(obj) && obj.length; -/* global JQLitePrototype: true, - addEventListenerFn: true, - removeEventListenerFn: true, - BOOLEAN_ATTR: true, - ALIASED_ATTR: true, -*/ + if (obj.nodeType === NODE_TYPE_ELEMENT && length) { + return true; + } -////////////////////////////////// -//JQLite -////////////////////////////////// + return isString(obj) || isArray(obj) || length === 0 || + typeof length === 'number' && length > 0 && (length - 1) in obj; +} /** * @ngdoc function - * @name angular.element + * @name angular.forEach * @module ng * @kind function * * @description - * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. - * - * If jQuery is available, `angular.element` is an alias for the - * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` - * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." - * - * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows - * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most - * commonly needed functionality with the goal of having a very small footprint.</div> - * - * To use jQuery, simply load it before `DOMContentLoaded` event fired. - * - * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or - * jqLite; they are never raw DOM references.</div> - * - * ## Angular's jqLite - * jqLite provides only the following jQuery methods: - * - * - [`addClass()`](http://api.jquery.com/addClass/) - * - [`after()`](http://api.jquery.com/after/) - * - [`append()`](http://api.jquery.com/append/) - * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters - * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData - * - [`children()`](http://api.jquery.com/children/) - Does not support selectors - * - [`clone()`](http://api.jquery.com/clone/) - * - [`contents()`](http://api.jquery.com/contents/) - * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()` - * - [`data()`](http://api.jquery.com/data/) - * - [`detach()`](http://api.jquery.com/detach/) - * - [`empty()`](http://api.jquery.com/empty/) - * - [`eq()`](http://api.jquery.com/eq/) - * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name - * - [`hasClass()`](http://api.jquery.com/hasClass/) - * - [`html()`](http://api.jquery.com/html/) - * - [`next()`](http://api.jquery.com/next/) - Does not support selectors - * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData - * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors - * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors - * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors - * - [`prepend()`](http://api.jquery.com/prepend/) - * - [`prop()`](http://api.jquery.com/prop/) - * - [`ready()`](http://api.jquery.com/ready/) - * - [`remove()`](http://api.jquery.com/remove/) - * - [`removeAttr()`](http://api.jquery.com/removeAttr/) - * - [`removeClass()`](http://api.jquery.com/removeClass/) - * - [`removeData()`](http://api.jquery.com/removeData/) - * - [`replaceWith()`](http://api.jquery.com/replaceWith/) - * - [`text()`](http://api.jquery.com/text/) - * - [`toggleClass()`](http://api.jquery.com/toggleClass/) - * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. - * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces - * - [`val()`](http://api.jquery.com/val/) - * - [`wrap()`](http://api.jquery.com/wrap/) + * Invokes the `iterator` function once for each item in `obj` collection, which can be either an + * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value` + * is the value of an object property or an array element, `key` is the object property key or + * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional. * - * ## jQuery/jqLite Extras - * Angular also provides the following additional methods and events to both jQuery and jqLite: + * It is worth noting that `.forEach` does not iterate over inherited properties because it filters + * using the `hasOwnProperty` method. * - * ### Events - * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event - * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM - * element before it is removed. + * Unlike ES262's + * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18), + * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just + * return the value provided. * - * ### Methods - * - `controller(name)` - retrieves the controller of the current element or its parent. By default - * retrieves controller associated with the `ngController` directive. If `name` is provided as - * camelCase directive name, then the controller for this directive will be retrieved (e.g. - * `'ngModel'`). - * - `injector()` - retrieves the injector of the current element or its parent. - * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current - * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to - * be enabled. - * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the - * current element. This getter should be used only on elements that contain a directive which starts a new isolate - * scope. Calling `scope()` on this element always returns the original non-isolate scope. - * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled. - * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top - * parent element is reached. + ```js + var values = {name: 'misko', gender: 'male'}; + var log = []; + angular.forEach(values, function(value, key) { + this.push(key + ': ' + value); + }, log); + expect(log).toEqual(['name: misko', 'gender: male']); + ``` * - * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. - * @returns {Object} jQuery object. + * @param {Object|Array} obj Object to iterate over. + * @param {Function} iterator Iterator function. + * @param {Object=} context Object to become context (`this`) for the iterator function. + * @returns {Object|Array} Reference to `obj`. */ -JQLite.expando = 'ng339'; +function forEach(obj, iterator, context) { + var key, length; + if (obj) { + if (isFunction(obj)) { + for (key in obj) { + // Need to check if hasOwnProperty exists, + // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function + if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (isArray(obj) || isArrayLike(obj)) { + var isPrimitive = typeof obj !== 'object'; + for (key = 0, length = obj.length; key < length; key++) { + if (isPrimitive || key in obj) { + iterator.call(context, obj[key], key, obj); + } + } + } else if (obj.forEach && obj.forEach !== forEach) { + obj.forEach(iterator, context, obj); + } else if (isBlankObject(obj)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in obj) { + iterator.call(context, obj[key], key, obj); + } + } else if (typeof obj.hasOwnProperty === 'function') { + // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(context, obj[key], key, obj); + } + } + } else { + // Slow path for objects which do not have a method `hasOwnProperty` + for (key in obj) { + if (hasOwnProperty.call(obj, key)) { + iterator.call(context, obj[key], key, obj); + } + } + } + } + return obj; +} -var jqCache = JQLite.cache = {}, - jqId = 1, - addEventListenerFn = function(element, type, fn) { - element.addEventListener(type, fn, false); - }, - removeEventListenerFn = function(element, type, fn) { - element.removeEventListener(type, fn, false); - }; +function forEachSorted(obj, iterator, context) { + var keys = Object.keys(obj).sort(); + for (var i = 0; i < keys.length; i++) { + iterator.call(context, obj[keys[i]], keys[i]); + } + return keys; +} -/* - * !!! This is an undocumented "private" function !!! - */ -JQLite._data = function(node) { - //jQuery always returns an object on cache miss - return this.cache[node[this.expando]] || {}; -}; -function jqNextId() { return ++jqId; } +/** + * when using forEach the params are value, key, but it is often useful to have key, value. + * @param {function(string, *)} iteratorFn + * @returns {function(*, string)} + */ +function reverseParams(iteratorFn) { + return function(value, key) { iteratorFn(key, value); }; +} +/** + * A consistent way of creating unique IDs in angular. + * + * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before + * we hit number precision issues in JavaScript. + * + * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M + * + * @returns {number} an unique alpha-numeric string + */ +function nextUid() { + return ++uid; +} -var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; -var MOZ_HACK_REGEXP = /^moz([A-Z])/; -var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; -var jqLiteMinErr = minErr('jqLite'); /** - * Converts snake_case to camelCase. - * Also there is special case for Moz prefix starting with upper case letter. - * @param name Name to normalize + * Set or clear the hashkey for an object. + * @param obj object + * @param h the hashkey (!truthy to delete the hashkey) */ -function camelCase(name) { - return name. - replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }). - replace(MOZ_HACK_REGEXP, 'Moz$1'); +function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } else { + delete obj.$$hashKey; + } } -var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; -var HTML_REGEXP = /<|&#?\w+;/; -var TAG_NAME_REGEXP = /<([\w:]+)/; -var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; - -var wrapMap = { - 'option': [1, '<select multiple="multiple">', '</select>'], - - 'thead': [1, '<table>', '</table>'], - 'col': [2, '<table><colgroup>', '</colgroup></table>'], - 'tr': [2, '<table><tbody>', '</tbody></table>'], - 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'], - '_default': [0, "", ""] -}; -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; +function baseExtend(dst, objs, deep) { + var h = dst.$$hashKey; + for (var i = 0, ii = objs.length; i < ii; ++i) { + var obj = objs[i]; + if (!isObject(obj) && !isFunction(obj)) continue; + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + var src = obj[key]; + + if (deep && isObject(src)) { + if (isDate(src)) { + dst[key] = new Date(src.valueOf()); + } else { + if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {}; + baseExtend(dst[key], [src], true); + } + } else { + dst[key] = src; + } + } + } -function jqLiteIsTextNode(html) { - return !HTML_REGEXP.test(html); + setHashKey(dst, h); + return dst; } -function jqLiteAcceptsData(node) { - // The window object can accept data but has no nodeType - // Otherwise we are only interested in elements (1) and documents (9) - var nodeType = node.nodeType; - return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; +/** + * @ngdoc function + * @name angular.extend + * @module ng + * @kind function + * + * @description + * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s) + * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so + * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`. + * + * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use + * {@link angular.merge} for this. + * + * @param {Object} dst Destination object. + * @param {...Object} src Source object(s). + * @returns {Object} Reference to `dst`. + */ +function extend(dst) { + return baseExtend(dst, slice.call(arguments, 1), false); } -function jqLiteBuildFragment(html, context) { - var tmp, tag, wrap, - fragment = context.createDocumentFragment(), - nodes = [], i; - if (jqLiteIsTextNode(html)) { - // Convert non-html into a text node - nodes.push(context.createTextNode(html)); - } else { - // Convert html into DOM nodes - tmp = tmp || fragment.appendChild(context.createElement("div")); - tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase(); - wrap = wrapMap[tag] || wrapMap._default; - tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2]; +/** +* @ngdoc function +* @name angular.merge +* @module ng +* @kind function +* +* @description +* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s) +* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so +* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`. +* +* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source +* objects, performing a deep copy. +* +* @param {Object} dst Destination object. +* @param {...Object} src Source object(s). +* @returns {Object} Reference to `dst`. +*/ +function merge(dst) { + return baseExtend(dst, slice.call(arguments, 1), true); +} - // Descend through wrappers to the right content - i = wrap[0]; - while (i--) { - tmp = tmp.lastChild; - } - nodes = concat(nodes, tmp.childNodes); - tmp = fragment.firstChild; - tmp.textContent = ""; - } +function toInt(str) { + return parseInt(str, 10); +} - // Remove wrapper from fragment - fragment.textContent = ""; - fragment.innerHTML = ""; // Clear inner HTML - forEach(nodes, function(node) { - fragment.appendChild(node); - }); - return fragment; +function inherit(parent, extra) { + return extend(Object.create(parent), extra); } -function jqLiteParseHTML(html, context) { - context = context || document; - var parsed; +/** + * @ngdoc function + * @name angular.noop + * @module ng + * @kind function + * + * @description + * A function that performs no operations. This function can be useful when writing code in the + * functional style. + ```js + function foo(callback) { + var result = calculateResult(); + (callback || angular.noop)(result); + } + ``` + */ +function noop() {} +noop.$inject = []; - if ((parsed = SINGLE_TAG_REGEXP.exec(html))) { - return [context.createElement(parsed[1])]; - } - if ((parsed = jqLiteBuildFragment(html, context))) { - return parsed.childNodes; - } +/** + * @ngdoc function + * @name angular.identity + * @module ng + * @kind function + * + * @description + * A function that returns its first argument. This function is useful when writing code in the + * functional style. + * + ```js + function transformer(transformationFn, value) { + return (transformationFn || angular.identity)(value); + }; + ``` + * @param {*} value to be returned. + * @returns {*} the value passed in. + */ +function identity($) {return $;} +identity.$inject = []; - return []; + +function valueFn(value) {return function() {return value;};} + +function hasCustomToString(obj) { + return isFunction(obj.toString) && obj.toString !== Object.prototype.toString; } -///////////////////////////////////////////// -function JQLite(element) { - if (element instanceof JQLite) { - return element; - } - var argIsString; +/** + * @ngdoc function + * @name angular.isUndefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is undefined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is undefined. + */ +function isUndefined(value) {return typeof value === 'undefined';} - if (isString(element)) { - element = trim(element); - argIsString = true; - } - if (!(this instanceof JQLite)) { - if (argIsString && element.charAt(0) != '<') { - throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); - } - return new JQLite(element); - } - if (argIsString) { - jqLiteAddNodes(this, jqLiteParseHTML(element)); - } else { - jqLiteAddNodes(this, element); - } -} +/** + * @ngdoc function + * @name angular.isDefined + * @module ng + * @kind function + * + * @description + * Determines if a reference is defined. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is defined. + */ +function isDefined(value) {return typeof value !== 'undefined';} -function jqLiteClone(element) { - return element.cloneNode(true); + +/** + * @ngdoc function + * @name angular.isObject + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not + * considered to be objects. Note that JavaScript arrays are objects. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Object` but not `null`. + */ +function isObject(value) { + // http://jsperf.com/isobject4 + return value !== null && typeof value === 'object'; } -function jqLiteDealoc(element, onlyDescendants) { - if (!onlyDescendants) jqLiteRemoveData(element); - if (element.querySelectorAll) { - var descendants = element.querySelectorAll('*'); - for (var i = 0, l = descendants.length; i < l; i++) { - jqLiteRemoveData(descendants[i]); - } - } +/** + * Determine if a value is an object with a null prototype + * + * @returns {boolean} True if `value` is an `Object` with a null prototype + */ +function isBlankObject(value) { + return value !== null && typeof value === 'object' && !getPrototypeOf(value); } -function jqLiteOff(element, type, fn, unsupported) { - if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); - var expandoStore = jqLiteExpandoStore(element); - var events = expandoStore && expandoStore.events; - var handle = expandoStore && expandoStore.handle; +/** + * @ngdoc function + * @name angular.isString + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `String`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `String`. + */ +function isString(value) {return typeof value === 'string';} - if (!handle) return; //no listeners registered - if (!type) { - for (type in events) { - if (type !== '$destroy') { - removeEventListenerFn(element, type, handle); - } - delete events[type]; - } - } else { - forEach(type.split(' '), function(type) { - if (isDefined(fn)) { - var listenerFns = events[type]; - arrayRemove(listenerFns || [], fn); - if (listenerFns && listenerFns.length > 0) { - return; - } - } +/** + * @ngdoc function + * @name angular.isNumber + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Number`. + * + * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`. + * + * If you wish to exclude these then you can use the native + * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite) + * method. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Number`. + */ +function isNumber(value) {return typeof value === 'number';} - removeEventListenerFn(element, type, handle); - delete events[type]; - }); - } + +/** + * @ngdoc function + * @name angular.isDate + * @module ng + * @kind function + * + * @description + * Determines if a value is a date. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Date`. + */ +function isDate(value) { + return toString.call(value) === '[object Date]'; } -function jqLiteRemoveData(element, name) { - var expandoId = element.ng339; - var expandoStore = expandoId && jqCache[expandoId]; - if (expandoStore) { - if (name) { - delete expandoStore.data[name]; - return; - } +/** + * @ngdoc function + * @name angular.isArray + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Array`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Array`. + */ +var isArray = Array.isArray; - if (expandoStore.handle) { - if (expandoStore.events.$destroy) { - expandoStore.handle({}, '$destroy'); - } - jqLiteOff(element); - } - delete jqCache[expandoId]; - element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it - } -} +/** + * @ngdoc function + * @name angular.isFunction + * @module ng + * @kind function + * + * @description + * Determines if a reference is a `Function`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `Function`. + */ +function isFunction(value) {return typeof value === 'function';} -function jqLiteExpandoStore(element, createIfNecessary) { - var expandoId = element.ng339, - expandoStore = expandoId && jqCache[expandoId]; +/** + * Determines if a value is a regular expression object. + * + * @private + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a `RegExp`. + */ +function isRegExp(value) { + return toString.call(value) === '[object RegExp]'; +} - if (createIfNecessary && !expandoStore) { - element.ng339 = expandoId = jqNextId(); - expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined}; - } - return expandoStore; +/** + * Checks if `obj` is a window object. + * + * @private + * @param {*} obj Object to check + * @returns {boolean} True if `obj` is a window obj. + */ +function isWindow(obj) { + return obj && obj.window === obj; } -function jqLiteData(element, key, value) { - if (jqLiteAcceptsData(element)) { +function isScope(obj) { + return obj && obj.$evalAsync && obj.$watch; +} - var isSimpleSetter = isDefined(value); - var isSimpleGetter = !isSimpleSetter && key && !isObject(key); - var massGetter = !key; - var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); - var data = expandoStore && expandoStore.data; - if (isSimpleSetter) { // data('key', value) - data[key] = value; - } else { - if (massGetter) { // data() - return data; - } else { - if (isSimpleGetter) { // data('key') - // don't force creation of expandoStore if it doesn't exist yet - return data && data[key]; - } else { // mass-setter: data({key1: val1, key2: val2}) - extend(data, key); - } - } - } - } +function isFile(obj) { + return toString.call(obj) === '[object File]'; } -function jqLiteHasClass(element, selector) { - if (!element.getAttribute) return false; - return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). - indexOf(" " + selector + " ") > -1); -} -function jqLiteRemoveClass(element, cssClasses) { - if (cssClasses && element.setAttribute) { - forEach(cssClasses.split(' '), function(cssClass) { - element.setAttribute('class', trim( - (" " + (element.getAttribute('class') || '') + " ") - .replace(/[\n\t]/g, " ") - .replace(" " + trim(cssClass) + " ", " ")) - ); - }); - } +function isFormData(obj) { + return toString.call(obj) === '[object FormData]'; } -function jqLiteAddClass(element, cssClasses) { - if (cssClasses && element.setAttribute) { - var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') - .replace(/[\n\t]/g, " "); - - forEach(cssClasses.split(' '), function(cssClass) { - cssClass = trim(cssClass); - if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { - existingClasses += cssClass + ' '; - } - }); - element.setAttribute('class', trim(existingClasses)); - } +function isBlob(obj) { + return toString.call(obj) === '[object Blob]'; } -function jqLiteAddNodes(root, elements) { - // THIS CODE IS VERY HOT. Don't make changes without benchmarking. - - if (elements) { +function isBoolean(value) { + return typeof value === 'boolean'; +} - // if a Node (the most common case) - if (elements.nodeType) { - root[root.length++] = elements; - } else { - var length = elements.length; - // if an Array or NodeList and not a Window - if (typeof length === 'number' && elements.window !== elements) { - if (length) { - for (var i = 0; i < length; i++) { - root[root.length++] = elements[i]; - } - } - } else { - root[root.length++] = elements; - } - } - } +function isPromiseLike(obj) { + return obj && isFunction(obj.then); } -function jqLiteController(element, name) { - return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller'); +var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/; +function isTypedArray(value) { + return TYPED_ARRAY_REGEXP.test(toString.call(value)); } -function jqLiteInheritedData(element, name, value) { - // if element is the document object work with the html element instead - // this makes $(document).scope() possible - if (element.nodeType == NODE_TYPE_DOCUMENT) { - element = element.documentElement; - } - var names = isArray(name) ? name : [name]; - while (element) { - for (var i = 0, ii = names.length; i < ii; i++) { - if ((value = jqLite.data(element, names[i])) !== undefined) return value; - } +var trim = function(value) { + return isString(value) ? value.trim() : value; +}; - // If dealing with a document fragment node with a host element, and no parent, use the host - // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM - // to lookup parent controllers. - element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host); - } +// Copied from: +// http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021 +// Prereq: s is a string. +var escapeForRegexp = function(s) { + return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1'). + replace(/\x08/g, '\\x08'); +}; + + +/** + * @ngdoc function + * @name angular.isElement + * @module ng + * @kind function + * + * @description + * Determines if a reference is a DOM element (or wrapped jQuery element). + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element). + */ +function isElement(node) { + return !!(node && + (node.nodeName // we are a direct element + || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API } -function jqLiteEmpty(element) { - jqLiteDealoc(element, true); - while (element.firstChild) { - element.removeChild(element.firstChild); +/** + * @param str 'key1,key2,...' + * @returns {object} in the form of {key1:true, key2:true, ...} + */ +function makeMap(str) { + var obj = {}, items = str.split(","), i; + for (i = 0; i < items.length; i++) { + obj[items[i]] = true; } + return obj; } -function jqLiteRemove(element, keepData) { - if (!keepData) jqLiteDealoc(element); - var parent = element.parentNode; - if (parent) parent.removeChild(element); + +function nodeName_(element) { + return lowercase(element.nodeName || (element[0] && element[0].nodeName)); } +function includes(array, obj) { + return Array.prototype.indexOf.call(array, obj) != -1; +} -function jqLiteDocumentLoaded(action, win) { - win = win || window; - if (win.document.readyState === 'complete') { - // Force the action to be run async for consistent behaviour - // from the action's point of view - // i.e. it will definitely not be in a $apply - win.setTimeout(action); - } else { - // No need to unbind this handler as load is only ever called once - jqLite(win).on('load', action); +function arrayRemove(array, value) { + var index = array.indexOf(value); + if (index >= 0) { + array.splice(index, 1); } + return index; } -////////////////////////////////////////// -// Functions which are declared directly. -////////////////////////////////////////// -var JQLitePrototype = JQLite.prototype = { - ready: function(fn) { - var fired = false; - - function trigger() { - if (fired) return; - fired = true; - fn(); - } - - // check if document is already loaded - if (document.readyState === 'complete') { - setTimeout(trigger); - } else { - this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 - // we can not use jqLite since we are not done loading and jQuery could be loaded later. - // jshint -W064 - JQLite(window).on('load', trigger); // fallback to window.onload for others - // jshint +W064 - } - }, - toString: function() { - var value = []; - forEach(this, function(e) { value.push('' + e);}); - return '[' + value.join(', ') + ']'; - }, - - eq: function(index) { - return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); - }, - - length: 0, - push: push, - sort: [].sort, - splice: [].splice -}; - -////////////////////////////////////////// -// Functions iterating getter/setters. -// these functions return self on setter and -// value on get. -////////////////////////////////////////// -var BOOLEAN_ATTR = {}; -forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { - BOOLEAN_ATTR[lowercase(value)] = value; -}); -var BOOLEAN_ELEMENTS = {}; -forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { - BOOLEAN_ELEMENTS[value] = true; -}); -var ALIASED_ATTR = { - 'ngMinlength': 'minlength', - 'ngMaxlength': 'maxlength', - 'ngMin': 'min', - 'ngMax': 'max', - 'ngPattern': 'pattern' -}; - -function getBooleanAttrName(element, name) { - // check dom last since we will most likely fail on name - var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; - - // booleanAttr is here twice to minimize DOM access - return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; -} - -function getAliasedAttrName(element, name) { - var nodeName = element.nodeName; - return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name]; -} - -forEach({ - data: jqLiteData, - removeData: jqLiteRemoveData -}, function(fn, name) { - JQLite[name] = fn; -}); - -forEach({ - data: jqLiteData, - inheritedData: jqLiteInheritedData, - - scope: function(element) { - // Can't use jqLiteData here directly so we stay compatible with jQuery! - return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']); - }, - - isolateScope: function(element) { - // Can't use jqLiteData here directly so we stay compatible with jQuery! - return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate'); - }, - - controller: jqLiteController, +/** + * @ngdoc function + * @name angular.copy + * @module ng + * @kind function + * + * @description + * Creates a deep copy of `source`, which should be an object or an array. + * + * * If no destination is supplied, a copy of the object or array is created. + * * If a destination is provided, all of its elements (for arrays) or properties (for objects) + * are deleted and then all elements/properties from the source are copied to it. + * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned. + * * If `source` is identical to 'destination' an exception will be thrown. + * + * @param {*} source The source that will be used to make a copy. + * Can be any type, including primitives, `null`, and `undefined`. + * @param {(Object|Array)=} destination Destination into which the source is copied. If + * provided, must be of the same type as `source`. + * @returns {*} The copy or updated `destination`, if `destination` was specified. + * + * @example + <example module="copyExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form novalidate class="simple-form"> + Name: <input type="text" ng-model="user.name" /><br /> + E-mail: <input type="email" ng-model="user.email" /><br /> + Gender: <input type="radio" ng-model="user.gender" value="male" />male + <input type="radio" ng-model="user.gender" value="female" />female<br /> + <button ng-click="reset()">RESET</button> + <button ng-click="update(user)">SAVE</button> + </form> + <pre>form = {{user | json}}</pre> + <pre>master = {{master | json}}</pre> + </div> - injector: function(element) { - return jqLiteInheritedData(element, '$injector'); - }, + <script> + angular.module('copyExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.master= {}; - removeAttr: function(element, name) { - element.removeAttribute(name); - }, + $scope.update = function(user) { + // Example with 1 argument + $scope.master= angular.copy(user); + }; - hasClass: jqLiteHasClass, + $scope.reset = function() { + // Example with 2 arguments + angular.copy($scope.master, $scope.user); + }; - css: function(element, name, value) { - name = camelCase(name); + $scope.reset(); + }]); + </script> + </file> + </example> + */ +function copy(source, destination, stackSource, stackDest) { + if (isWindow(source) || isScope(source)) { + throw ngMinErr('cpws', + "Can't copy! Making copies of Window or Scope instances is not supported."); + } + if (isTypedArray(destination)) { + throw ngMinErr('cpta', + "Can't copy! TypedArray destination cannot be mutated."); + } - if (isDefined(value)) { - element.style[name] = value; - } else { - return element.style[name]; - } - }, + if (!destination) { + destination = source; + if (isObject(source)) { + var index; + if (stackSource && (index = stackSource.indexOf(source)) !== -1) { + return stackDest[index]; + } - attr: function(element, name, value) { - var lowercasedName = lowercase(name); - if (BOOLEAN_ATTR[lowercasedName]) { - if (isDefined(value)) { - if (!!value) { - element[name] = true; - element.setAttribute(name, lowercasedName); - } else { - element[name] = false; - element.removeAttribute(lowercasedName); - } + // TypedArray, Date and RegExp have specific copy functionality and must be + // pushed onto the stack before returning. + // Array and other objects create the base object and recurse to copy child + // objects. The array/object will be pushed onto the stack when recursed. + if (isArray(source)) { + return copy(source, [], stackSource, stackDest); + } else if (isTypedArray(source)) { + destination = new source.constructor(source); + } else if (isDate(source)) { + destination = new Date(source.getTime()); + } else if (isRegExp(source)) { + destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]); + destination.lastIndex = source.lastIndex; } else { - return (element[name] || - (element.attributes.getNamedItem(name) || noop).specified) - ? lowercasedName - : undefined; + var emptyObject = Object.create(getPrototypeOf(source)); + return copy(source, emptyObject, stackSource, stackDest); } - } else if (isDefined(value)) { - element.setAttribute(name, value); - } else if (element.getAttribute) { - // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code - // some elements (e.g. Document) don't have get attribute, so return undefined - var ret = element.getAttribute(name, 2); - // normalize non-existing attributes to undefined (as jQuery) - return ret === null ? undefined : ret; - } - }, - prop: function(element, name, value) { - if (isDefined(value)) { - element[name] = value; - } else { - return element[name]; + if (stackDest) { + stackSource.push(source); + stackDest.push(destination); + } } - }, + } else { + if (source === destination) throw ngMinErr('cpi', + "Can't copy! Source and destination are identical."); - text: (function() { - getText.$dv = ''; - return getText; + stackSource = stackSource || []; + stackDest = stackDest || []; - function getText(element, value) { - if (isUndefined(value)) { - var nodeType = element.nodeType; - return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : ''; - } - element.textContent = value; + if (isObject(source)) { + stackSource.push(source); + stackDest.push(destination); } - })(), - val: function(element, value) { - if (isUndefined(value)) { - if (element.multiple && nodeName_(element) === 'select') { - var result = []; - forEach(element.options, function(option) { - if (option.selected) { - result.push(option.value || option.text); - } + var result, key; + if (isArray(source)) { + destination.length = 0; + for (var i = 0; i < source.length; i++) { + destination.push(copy(source[i], null, stackSource, stackDest)); + } + } else { + var h = destination.$$hashKey; + if (isArray(destination)) { + destination.length = 0; + } else { + forEach(destination, function(value, key) { + delete destination[key]; }); - return result.length === 0 ? null : result; } - return element.value; - } - element.value = value; - }, - - html: function(element, value) { - if (isUndefined(value)) { - return element.innerHTML; - } - jqLiteDealoc(element, true); - element.innerHTML = value; - }, - - empty: jqLiteEmpty -}, function(fn, name) { - /** - * Properties: writes return selection, reads return first value - */ - JQLite.prototype[name] = function(arg1, arg2) { - var i, key; - var nodeCount = this.length; - - // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it - // in a way that survives minification. - // jqLiteEmpty takes no arguments but is a setter. - if (fn !== jqLiteEmpty && - (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) { - if (isObject(arg1)) { - - // we are a write, but the object properties are the key/values - for (i = 0; i < nodeCount; i++) { - if (fn === jqLiteData) { - // data() takes the whole object in jQuery - fn(this[i], arg1); - } else { - for (key in arg1) { - fn(this[i], key, arg1[key]); - } + if (isBlankObject(source)) { + // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty + for (key in source) { + destination[key] = copy(source[key], null, stackSource, stackDest); + } + } else if (source && typeof source.hasOwnProperty === 'function') { + // Slow path, which must rely on hasOwnProperty + for (key in source) { + if (source.hasOwnProperty(key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); } } - // return self for chaining - return this; } else { - // we are a read, so read the first child. - // TODO: do we still need this? - var value = fn.$dv; - // Only if we have $dv do we iterate over all, otherwise it is just the first element. - var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount; - for (var j = 0; j < jj; j++) { - var nodeValue = fn(this[j], arg1, arg2); - value = value ? value + nodeValue : nodeValue; + // Slowest path --- hasOwnProperty can't be called as a method + for (key in source) { + if (hasOwnProperty.call(source, key)) { + destination[key] = copy(source[key], null, stackSource, stackDest); + } } - return value; - } - } else { - // we are a write, so apply to all children - for (i = 0; i < nodeCount; i++) { - fn(this[i], arg1, arg2); } - // return self for chaining - return this; + setHashKey(destination,h); } - }; -}); - -function createEventHandler(element, events) { - var eventHandler = function(event, type) { - // jQuery specific api - event.isDefaultPrevented = function() { - return event.defaultPrevented; - }; - - var eventFns = events[type || event.type]; - var eventFnsLength = eventFns ? eventFns.length : 0; - - if (!eventFnsLength) return; + } + return destination; +} - if (isUndefined(event.immediatePropagationStopped)) { - var originalStopImmediatePropagation = event.stopImmediatePropagation; - event.stopImmediatePropagation = function() { - event.immediatePropagationStopped = true; +/** + * Creates a shallow copy of an object, an array or a primitive. + * + * Assumes that there are no proto properties for objects. + */ +function shallowCopy(src, dst) { + if (isArray(src)) { + dst = dst || []; - if (event.stopPropagation) { - event.stopPropagation(); - } + for (var i = 0, ii = src.length; i < ii; i++) { + dst[i] = src[i]; + } + } else if (isObject(src)) { + dst = dst || {}; - if (originalStopImmediatePropagation) { - originalStopImmediatePropagation.call(event); - } - }; + for (var key in src) { + if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } } + } - event.isImmediatePropagationStopped = function() { - return event.immediatePropagationStopped === true; - }; + return dst || src; +} - // Copy event handlers in case event handlers array is modified during execution. - if ((eventFnsLength > 1)) { - eventFns = shallowCopy(eventFns); - } - for (var i = 0; i < eventFnsLength; i++) { - if (!event.isImmediatePropagationStopped()) { - eventFns[i].call(element, event); +/** + * @ngdoc function + * @name angular.equals + * @module ng + * @kind function + * + * @description + * Determines if two objects or two values are equivalent. Supports value types, regular + * expressions, arrays and objects. + * + * Two objects or values are considered equivalent if at least one of the following is true: + * + * * Both objects or values pass `===` comparison. + * * Both objects or values are of the same type and all of their properties are equal by + * comparing them with `angular.equals`. + * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal) + * * Both values represent the same regular expression (In JavaScript, + * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual + * representation matches). + * + * During a property comparison, properties of `function` type and properties with names + * that begin with `$` are ignored. + * + * Scope and DOMWindow objects are being compared only by identify (`===`). + * + * @param {*} o1 Object or value to compare. + * @param {*} o2 Object or value to compare. + * @returns {boolean} True if arguments are equal. + */ +function equals(o1, o2) { + if (o1 === o2) return true; + if (o1 === null || o2 === null) return false; + if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN + var t1 = typeof o1, t2 = typeof o2, length, key, keySet; + if (t1 == t2) { + if (t1 == 'object') { + if (isArray(o1)) { + if (!isArray(o2)) return false; + if ((length = o1.length) == o2.length) { + for (key = 0; key < length; key++) { + if (!equals(o1[key], o2[key])) return false; + } + return true; + } + } else if (isDate(o1)) { + if (!isDate(o2)) return false; + return equals(o1.getTime(), o2.getTime()); + } else if (isRegExp(o1)) { + return isRegExp(o2) ? o1.toString() == o2.toString() : false; + } else { + if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || + isArray(o2) || isDate(o2) || isRegExp(o2)) return false; + keySet = createMap(); + for (key in o1) { + if (key.charAt(0) === '$' || isFunction(o1[key])) continue; + if (!equals(o1[key], o2[key])) return false; + keySet[key] = true; + } + for (key in o2) { + if (!(key in keySet) && + key.charAt(0) !== '$' && + o2[key] !== undefined && + !isFunction(o2[key])) return false; + } + return true; } } - }; - - // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all - // events on `element` - eventHandler.elem = element; - return eventHandler; + } + return false; } -////////////////////////////////////////// -// Functions iterating traversal. -// These functions chain results into a single -// selector. -////////////////////////////////////////// -forEach({ - removeData: jqLiteRemoveData, +var csp = function() { + if (isDefined(csp.isActive_)) return csp.isActive_; - on: function jqLiteOn(element, type, fn, unsupported) { - if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); + var active = !!(document.querySelector('[ng-csp]') || + document.querySelector('[data-ng-csp]')); - // Do not add event handlers to non-elements because they will not be cleaned up. - if (!jqLiteAcceptsData(element)) { - return; + if (!active) { + try { + /* jshint -W031, -W054 */ + new Function(''); + /* jshint +W031, +W054 */ + } catch (e) { + active = true; } + } - var expandoStore = jqLiteExpandoStore(element, true); - var events = expandoStore.events; - var handle = expandoStore.handle; + return (csp.isActive_ = active); +}; - if (!handle) { - handle = expandoStore.handle = createEventHandler(element, events); +/** + * @ngdoc directive + * @module ng + * @name ngJq + * + * @element ANY + * @param {string=} ngJq the name of the library available under `window` + * to be used for angular.element + * @description + * Use this directive to force the angular.element library. This should be + * used to force either jqLite by leaving ng-jq blank or setting the name of + * the jquery variable under window (eg. jQuery). + * + * Since angular looks for this directive when it is loaded (doesn't wait for the + * DOMContentLoaded event), it must be placed on an element that comes before the script + * which loads angular. Also, only the first instance of `ng-jq` will be used and all + * others ignored. + * + * @example + * This example shows how to force jqLite using the `ngJq` directive to the `html` tag. + ```html + <!doctype html> + <html ng-app ng-jq> + ... + ... + </html> + ``` + * @example + * This example shows how to use a jQuery based library of a different name. + * The library name must be available at the top most 'window'. + ```html + <!doctype html> + <html ng-app ng-jq="jQueryLib"> + ... + ... + </html> + ``` + */ +var jq = function() { + if (isDefined(jq.name_)) return jq.name_; + var el; + var i, ii = ngAttrPrefixes.length, prefix, name; + for (i = 0; i < ii; ++i) { + prefix = ngAttrPrefixes[i]; + if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) { + name = el.getAttribute(prefix + 'jq'); + break; } + } - // http://jsperf.com/string-indexof-vs-split - var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type]; - var i = types.length; + return (jq.name_ = name); +}; - while (i--) { - type = types[i]; - var eventFns = events[type]; +function concat(array1, array2, index) { + return array1.concat(slice.call(array2, index)); +} - if (!eventFns) { - events[type] = []; +function sliceArgs(args, startIndex) { + return slice.call(args, startIndex || 0); +} - if (type === 'mouseenter' || type === 'mouseleave') { - // Refer to jQuery's implementation of mouseenter & mouseleave - // Read about mouseenter and mouseleave: - // http://www.quirksmode.org/js/events_mouse.html#link8 - jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { - var target = this, related = event.relatedTarget; - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if (!related || (related !== target && !target.contains(related))) { - handle(event, type); - } - }); - - } else { - if (type !== '$destroy') { - addEventListenerFn(element, type, handle); - } +/* jshint -W101 */ +/** + * @ngdoc function + * @name angular.bind + * @module ng + * @kind function + * + * @description + * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for + * `fn`). You can supply optional `args` that are prebound to the function. This feature is also + * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as + * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application). + * + * @param {Object} self Context which `fn` should be evaluated in. + * @param {function()} fn Function to be bound. + * @param {...*} args Optional arguments to be prebound to the `fn` function call. + * @returns {function()} Function that wraps the `fn` with all the specified bindings. + */ +/* jshint +W101 */ +function bind(self, fn) { + var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : []; + if (isFunction(fn) && !(fn instanceof RegExp)) { + return curryArgs.length + ? function() { + return arguments.length + ? fn.apply(self, concat(curryArgs, arguments, 0)) + : fn.apply(self, curryArgs); } - eventFns = events[type]; - } - eventFns.push(fn); - } - }, - - off: jqLiteOff, - - one: function(element, type, fn) { - element = jqLite(element); - - //add the listener twice so that when it is called - //you can remove the original function and still be - //able to call element.off(ev, fn) normally - element.on(type, function onFn() { - element.off(type, fn); - element.off(type, onFn); - }); - element.on(type, fn); - }, - - replaceWith: function(element, replaceNode) { - var index, parent = element.parentNode; - jqLiteDealoc(element); - forEach(new JQLite(replaceNode), function(node) { - if (index) { - parent.insertBefore(node, index.nextSibling); - } else { - parent.replaceChild(node, element); - } - index = node; - }); - }, - - children: function(element) { - var children = []; - forEach(element.childNodes, function(element) { - if (element.nodeType === NODE_TYPE_ELEMENT) - children.push(element); - }); - return children; - }, - - contents: function(element) { - return element.contentDocument || element.childNodes || []; - }, - - append: function(element, node) { - var nodeType = element.nodeType; - if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; + : function() { + return arguments.length + ? fn.apply(self, arguments) + : fn.call(self); + }; + } else { + // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) + return fn; + } +} - node = new JQLite(node); - for (var i = 0, ii = node.length; i < ii; i++) { - var child = node[i]; - element.appendChild(child); - } - }, +function toJsonReplacer(key, value) { + var val = value; - prepend: function(element, node) { - if (element.nodeType === NODE_TYPE_ELEMENT) { - var index = element.firstChild; - forEach(new JQLite(node), function(child) { - element.insertBefore(child, index); - }); - } - }, + if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') { + val = undefined; + } else if (isWindow(value)) { + val = '$WINDOW'; + } else if (value && document === value) { + val = '$DOCUMENT'; + } else if (isScope(value)) { + val = '$SCOPE'; + } - wrap: function(element, wrapNode) { - wrapNode = jqLite(wrapNode).eq(0).clone()[0]; - var parent = element.parentNode; - if (parent) { - parent.replaceChild(wrapNode, element); - } - wrapNode.appendChild(element); - }, + return val; +} - remove: jqLiteRemove, - detach: function(element) { - jqLiteRemove(element, true); - }, +/** + * @ngdoc function + * @name angular.toJson + * @module ng + * @kind function + * + * @description + * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be + * stripped since angular uses this notation internally. + * + * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. + * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace. + * If set to an integer, the JSON output will contain that many spaces per indentation. + * @returns {string|undefined} JSON-ified string representing `obj`. + */ +function toJson(obj, pretty) { + if (typeof obj === 'undefined') return undefined; + if (!isNumber(pretty)) { + pretty = pretty ? 2 : null; + } + return JSON.stringify(obj, toJsonReplacer, pretty); +} - after: function(element, newElement) { - var index = element, parent = element.parentNode; - newElement = new JQLite(newElement); - for (var i = 0, ii = newElement.length; i < ii; i++) { - var node = newElement[i]; - parent.insertBefore(node, index.nextSibling); - index = node; - } - }, +/** + * @ngdoc function + * @name angular.fromJson + * @module ng + * @kind function + * + * @description + * Deserializes a JSON string. + * + * @param {string} json JSON string to deserialize. + * @returns {Object|Array|string|number} Deserialized JSON string. + */ +function fromJson(json) { + return isString(json) + ? JSON.parse(json) + : json; +} - addClass: jqLiteAddClass, - removeClass: jqLiteRemoveClass, - toggleClass: function(element, selector, condition) { - if (selector) { - forEach(selector.split(' '), function(className) { - var classCondition = condition; - if (isUndefined(classCondition)) { - classCondition = !jqLiteHasClass(element, className); - } - (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); - }); - } - }, +function timezoneToOffset(timezone, fallback) { + var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000; + return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset; +} - parent: function(element) { - var parent = element.parentNode; - return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; - }, - next: function(element) { - return element.nextElementSibling; - }, +function addDateMinutes(date, minutes) { + date = new Date(date.getTime()); + date.setMinutes(date.getMinutes() + minutes); + return date; +} - find: function(element, selector) { - if (element.getElementsByTagName) { - return element.getElementsByTagName(selector); - } else { - return []; - } - }, - clone: jqLiteClone, +function convertTimezoneToLocal(date, timezone, reverse) { + reverse = reverse ? -1 : 1; + var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset())); +} - triggerHandler: function(element, event, extraParameters) { - var dummyEvent, eventFnsCopy, handlerArgs; - var eventName = event.type || event; - var expandoStore = jqLiteExpandoStore(element); - var events = expandoStore && expandoStore.events; - var eventFns = events && events[eventName]; +/** + * @returns {string} Returns the string representation of the element. + */ +function startingTag(element) { + element = jqLite(element).clone(); + try { + // turns out IE does not let you set .html() on elements which + // are not allowed to have children. So we just ignore it. + element.empty(); + } catch (e) {} + var elemHtml = jqLite('<div>').append(element).html(); + try { + return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) : + elemHtml. + match(/^(<[^>]+>)/)[1]. + replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); + } catch (e) { + return lowercase(elemHtml); + } - if (eventFns) { - // Create a dummy event to pass to the handlers - dummyEvent = { - preventDefault: function() { this.defaultPrevented = true; }, - isDefaultPrevented: function() { return this.defaultPrevented === true; }, - stopImmediatePropagation: function() { this.immediatePropagationStopped = true; }, - isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; }, - stopPropagation: noop, - type: eventName, - target: element - }; +} - // If a custom event was provided then extend our dummy event with it - if (event.type) { - dummyEvent = extend(dummyEvent, event); - } - // Copy event handlers in case event handlers array is modified during execution. - eventFnsCopy = shallowCopy(eventFns); - handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent]; +///////////////////////////////////////////////// - forEach(eventFnsCopy, function(fn) { - if (!dummyEvent.isImmediatePropagationStopped()) { - fn.apply(element, handlerArgs); - } - }); - } +/** + * Tries to decode the URI component without throwing an exception. + * + * @private + * @param str value potential URI component to check. + * @returns {boolean} True if `value` can be decoded + * with the decodeURIComponent function. + */ +function tryDecodeURIComponent(value) { + try { + return decodeURIComponent(value); + } catch (e) { + // Ignore any invalid uri component } -}, function(fn, name) { - /** - * chaining functions - */ - JQLite.prototype[name] = function(arg1, arg2, arg3) { - var value; +} - for (var i = 0, ii = this.length; i < ii; i++) { - if (isUndefined(value)) { - value = fn(this[i], arg1, arg2, arg3); - if (isDefined(value)) { - // any function which returns a value needs to be wrapped - value = jqLite(value); + +/** + * Parses an escaped url query string into key-value pairs. + * @returns {Object.<string,boolean|Array>} + */ +function parseKeyValue(/**string*/keyValue) { + var obj = {}, key_value, key; + forEach((keyValue || "").split('&'), function(keyValue) { + if (keyValue) { + key_value = keyValue.replace(/\+/g,'%20').split('='); + key = tryDecodeURIComponent(key_value[0]); + if (isDefined(key)) { + var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true; + if (!hasOwnProperty.call(obj, key)) { + obj[key] = val; + } else if (isArray(obj[key])) { + obj[key].push(val); + } else { + obj[key] = [obj[key],val]; } - } else { - jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); } } - return isDefined(value) ? value : this; - }; - - // bind legacy bind/unbind to on/off - JQLite.prototype.bind = JQLite.prototype.on; - JQLite.prototype.unbind = JQLite.prototype.off; -}); - - -// Provider for private $$jqLite service -function $$jqLiteProvider() { - this.$get = function $$jqLite() { - return extend(JQLite, { - hasClass: function(node, classes) { - if (node.attr) node = node[0]; - return jqLiteHasClass(node, classes); - }, - addClass: function(node, classes) { - if (node.attr) node = node[0]; - return jqLiteAddClass(node, classes); - }, - removeClass: function(node, classes) { - if (node.attr) node = node[0]; - return jqLiteRemoveClass(node, classes); - } - }); - }; + }); + return obj; } -/** - * Computes a hash of an 'obj'. - * Hash of a: - * string is string - * number is number as string - * object is either result of calling $$hashKey function on the object or uniquely generated id, - * that is also assigned to the $$hashKey property of the object. - * - * @param obj - * @returns {string} hash string such that the same input will have the same hash string. - * The resulting string key is in 'type:hashKey' format. - */ -function hashKey(obj, nextUidFn) { - var key = obj && obj.$$hashKey; - - if (key) { - if (typeof key === 'function') { - key = obj.$$hashKey(); +function toKeyValue(obj) { + var parts = []; + forEach(obj, function(value, key) { + if (isArray(value)) { + forEach(value, function(arrayValue) { + parts.push(encodeUriQuery(key, true) + + (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true))); + }); + } else { + parts.push(encodeUriQuery(key, true) + + (value === true ? '' : '=' + encodeUriQuery(value, true))); } - return key; - } + }); + return parts.length ? parts.join('&') : ''; +} - var objType = typeof obj; - if (objType == 'function' || (objType == 'object' && obj !== null)) { - key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)(); - } else { - key = objType + ':' + obj; - } - return key; +/** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ +function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); } + /** - * HashMap which can use objects as keys + * This method is intended for encoding *key* or *value* parts of query component. We need a custom + * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be + * encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" */ -function HashMap(array, isolatedUid) { - if (isolatedUid) { - var uid = 0; - this.nextUid = function() { - return ++uid; - }; - } - forEach(array, this.put, this); +function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%3B/gi, ';'). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); } -HashMap.prototype = { - /** - * Store key value pair - * @param key key to store can be any type - * @param value value to store can be any type - */ - put: function(key, value) { - this[hashKey(key, this.nextUid)] = value; - }, - /** - * @param key - * @returns {Object} the value for the key - */ - get: function(key) { - return this[hashKey(key, this.nextUid)]; - }, +var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-']; - /** - * Remove the key/value pair - * @param key - */ - remove: function(key) { - var value = this[key = hashKey(key, this.nextUid)]; - delete this[key]; - return value; +function getNgAttribute(element, ngAttr) { + var attr, i, ii = ngAttrPrefixes.length; + for (i = 0; i < ii; ++i) { + attr = ngAttrPrefixes[i] + ngAttr; + if (isString(attr = element.getAttribute(attr))) { + return attr; + } } -}; + return null; +} /** - * @ngdoc function + * @ngdoc directive + * @name ngApp * @module ng - * @name angular.injector - * @kind function + * + * @element ANY + * @param {angular.Module} ngApp an optional application + * {@link angular.module module} name to load. + * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be + * created in "strict-di" mode. This means that the application will fail to invoke functions which + * do not use explicit function annotation (and are thus unsuitable for minification), as described + * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in + * tracking down the root of these bugs. * * @description - * Creates an injector object that can be used for retrieving services as well as for - * dependency injection (see {@link guide/di dependency injection}). * - * @param {Array.<string|Function>} modules A list of module functions or their aliases. See - * {@link angular.module}. The `ng` module must be explicitly added. - * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which - * disallows argument name annotation inference. - * @returns {injector} Injector object. See {@link auto.$injector $injector}. + * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive + * designates the **root element** of the application and is typically placed near the root element + * of the page - e.g. on the `<body>` or `<html>` tags. * - * @example - * Typical usage - * ```js - * // create an injector - * var $injector = angular.injector(['ng']); + * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp` + * found in the document will be used to define the root element to auto-bootstrap as an + * application. To run multiple applications in an HTML document you must manually bootstrap them using + * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other. * - * // use the injector to kick off your application - * // use the type inference to auto inject arguments, or use implicit injection - * $injector.invoke(function($rootScope, $compile, $document) { - * $compile($document)($rootScope); - * $rootScope.$digest(); - * }); - * ``` + * You can specify an **AngularJS module** to be used as the root module for the application. This + * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It + * should contain the application code needed or have dependencies on other modules that will + * contain the code. See {@link angular.module} for more information. * - * Sometimes you want to get access to the injector of a currently running Angular app - * from outside Angular. Perhaps, you want to inject and compile some markup after the - * application has been bootstrapped. You can do this using the extra `injector()` added - * to JQuery/jqLite elements. See {@link angular.element}. + * In the example below if the `ngApp` directive were not placed on the `html` element then the + * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}` + * would not be resolved to `3`. * - * *This is fairly rare but could be the case if a third party library is injecting the - * markup.* + * `ngApp` is the easiest, and most common way to bootstrap an application. * - * In the following example a new block of HTML containing a `ng-controller` - * directive is added to the end of the document body by JQuery. We then compile and link - * it into the current AngularJS scope. + <example module="ngAppDemo"> + <file name="index.html"> + <div ng-controller="ngAppDemoController"> + I can add: {{a}} + {{b}} = {{ a+b }} + </div> + </file> + <file name="script.js"> + angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }); + </file> + </example> * - * ```js - * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>'); - * $(document.body).append($div); + * Using `ngStrictDi`, you would see something like this: * - * angular.element(document).injector().invoke(function($compile) { - * var scope = angular.element($div).scope(); - * $compile($div)(scope); - * }); - * ``` - */ + <example ng-app-included="true"> + <file name="index.html"> + <div ng-app="ngAppStrictDemo" ng-strict-di> + <div ng-controller="GoodController1"> + I can add: {{a}} + {{b}} = {{ a+b }} + <p>This renders because the controller does not fail to + instantiate, by using explicit annotation style (see + script.js for details) + </p> + </div> -/** - * @ngdoc module - * @name auto - * @description - * - * Implicit module which gets automatically added to each {@link auto.$injector $injector}. - */ + <div ng-controller="GoodController2"> + Name: <input ng-model="name"><br /> + Hello, {{name}}! -var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; -var FN_ARG_SPLIT = /,/; -var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; -var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; -var $injectorMinErr = minErr('$injector'); + <p>This renders because the controller does not fail to + instantiate, by using explicit annotation style + (see script.js for details) + </p> + </div> -function anonFn(fn) { - // For anonymous functions, showing at the very least the function signature can help in - // debugging. - var fnText = fn.toString().replace(STRIP_COMMENTS, ''), - args = fnText.match(FN_ARGS); - if (args) { - return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')'; - } - return 'fn'; -} + <div ng-controller="BadController"> + I can add: {{a}} + {{b}} = {{ a+b }} -function annotate(fn, strictDi, name) { - var $inject, - fnText, - argDecl, - last; + <p>The controller could not be instantiated, due to relying + on automatic function annotations (which are disabled in + strict mode). As such, the content of this section is not + interpolated, and there should be an error in your web console. + </p> + </div> + </div> + </file> + <file name="script.js"> + angular.module('ngAppStrictDemo', []) + // BadController will fail to instantiate, due to relying on automatic function annotation, + // rather than an explicit annotation + .controller('BadController', function($scope) { + $scope.a = 1; + $scope.b = 2; + }) + // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated, + // due to using explicit annotations using the array style and $inject property, respectively. + .controller('GoodController1', ['$scope', function($scope) { + $scope.a = 1; + $scope.b = 2; + }]) + .controller('GoodController2', GoodController2); + function GoodController2($scope) { + $scope.name = "World"; + } + GoodController2.$inject = ['$scope']; + </file> + <file name="style.css"> + div[ng-controller] { + margin-bottom: 1em; + -webkit-border-radius: 4px; + border-radius: 4px; + border: 1px solid; + padding: .5em; + } + div[ng-controller^=Good] { + border-color: #d6e9c6; + background-color: #dff0d8; + color: #3c763d; + } + div[ng-controller^=Bad] { + border-color: #ebccd1; + background-color: #f2dede; + color: #a94442; + margin-bottom: 0; + } + </file> + </example> + */ +function angularInit(element, bootstrap) { + var appElement, + module, + config = {}; - if (typeof fn === 'function') { - if (!($inject = fn.$inject)) { - $inject = []; - if (fn.length) { - if (strictDi) { - if (!isString(name) || !name) { - name = fn.name || anonFn(fn); - } - throw $injectorMinErr('strictdi', - '{0} is not using explicit annotation and cannot be invoked in strict mode', name); - } - fnText = fn.toString().replace(STRIP_COMMENTS, ''); - argDecl = fnText.match(FN_ARGS); - forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { - arg.replace(FN_ARG, function(all, underscore, name) { - $inject.push(name); - }); - }); - } - fn.$inject = $inject; + // The element `element` has priority over any other element + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { + appElement = element; + module = element.getAttribute(name); } - } else if (isArray(fn)) { - last = fn.length - 1; - assertArgFn(fn[last], 'fn'); - $inject = fn.slice(0, last); - } else { - assertArgFn(fn, 'fn', true); + }); + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + var candidate; + + if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) { + appElement = candidate; + module = candidate.getAttribute(name); + } + }); + if (appElement) { + config.strictDi = getNgAttribute(appElement, "strict-di") !== null; + bootstrap(appElement, module ? [module] : [], config); } - return $inject; } -/////////////////////////////////////// - /** - * @ngdoc service - * @name $injector - * + * @ngdoc function + * @name angular.bootstrap + * @module ng * @description + * Use this function to manually start up angular application. * - * `$injector` is used to retrieve object instances as defined by - * {@link auto.$provide provider}, instantiate types, invoke methods, - * and load modules. - * - * The following always holds true: - * - * ```js - * var $injector = angular.injector(); - * expect($injector.get('$injector')).toBe($injector); - * expect($injector.invoke(function($injector) { - * return $injector; - * })).toBe($injector); - * ``` - * - * # Injection Function Annotation + * See: {@link guide/bootstrap Bootstrap} * - * JavaScript does not have annotations, and annotations are needed for dependency injection. The - * following are all valid ways of annotating function with injection arguments and are equivalent. + * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually. + * They must use {@link ng.directive:ngApp ngApp}. * - * ```js - * // inferred (only works if code not minified/obfuscated) - * $injector.invoke(function(serviceA){}); + * Angular will detect if it has been loaded into the browser more than once and only allow the + * first loaded script to be bootstrapped and will report a warning to the browser console for + * each of the subsequent scripts. This prevents strange results in applications, where otherwise + * multiple instances of Angular try to work on the DOM. * - * // annotated - * function explicit(serviceA) {}; - * explicit.$inject = ['serviceA']; - * $injector.invoke(explicit); + * ```html + * <!doctype html> + * <html> + * <body> + * <div ng-controller="WelcomeController"> + * {{greeting}} + * </div> * - * // inline - * $injector.invoke(['serviceA', function(serviceA){}]); + * <script src="angular.js"></script> + * <script> + * var app = angular.module('demo', []) + * .controller('WelcomeController', function($scope) { + * $scope.greeting = 'Welcome!'; + * }); + * angular.bootstrap(document, ['demo']); + * </script> + * </body> + * </html> * ``` * - * ## Inference - * - * In JavaScript calling `toString()` on a function returns the function definition. The definition - * can then be parsed and the function arguments can be extracted. This method of discovering - * annotations is disallowed when the injector is in strict mode. - * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the - * argument names. + * @param {DOMElement} element DOM element which is the root of angular application. + * @param {Array<String|Function|Array>=} modules an array of modules to load into the application. + * Each item in the array should be the name of a predefined module or a (DI annotated) + * function that will be invoked by the injector as a `config` block. + * See: {@link angular.module modules} + * @param {Object=} config an object for defining configuration options for the application. The + * following keys are supported: * - * ## `$inject` Annotation - * By adding an `$inject` property onto a function the injection parameters can be specified. + * * `strictDi` - disable automatic function annotation for the application. This is meant to + * assist in finding bugs which break minified code. Defaults to `false`. * - * ## Inline - * As an array of injection names, where the last item in the array is the function to call. + * @returns {auto.$injector} Returns the newly created injector for this app. */ +function bootstrap(element, modules, config) { + if (!isObject(config)) config = {}; + var defaultConfig = { + strictDi: false + }; + config = extend(defaultConfig, config); + var doBootstrap = function() { + element = jqLite(element); + + if (element.injector()) { + var tag = (element[0] === document) ? 'document' : startingTag(element); + //Encode angle brackets to prevent input from being sanitized to empty string #8683 + throw ngMinErr( + 'btstrpd', + "App Already Bootstrapped with this Element '{0}'", + tag.replace(/</,'<').replace(/>/,'>')); + } + + modules = modules || []; + modules.unshift(['$provide', function($provide) { + $provide.value('$rootElement', element); + }]); + + if (config.debugInfoEnabled) { + // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`. + modules.push(['$compileProvider', function($compileProvider) { + $compileProvider.debugInfoEnabled(true); + }]); + } + + modules.unshift('ng'); + var injector = createInjector(modules, config.strictDi); + injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', + function bootstrapApply(scope, element, compile, injector) { + scope.$apply(function() { + element.data('$injector', injector); + compile(element)(scope); + }); + }] + ); + return injector; + }; + + var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/; + var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; + + if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) { + config.debugInfoEnabled = true; + window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, ''); + } + + if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { + return doBootstrap(); + } + + window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); + angular.resumeBootstrap = function(extraModules) { + forEach(extraModules, function(module) { + modules.push(module); + }); + return doBootstrap(); + }; + + if (isFunction(angular.resumeDeferredBootstrap)) { + angular.resumeDeferredBootstrap(); + } +} /** - * @ngdoc method - * @name $injector#get - * + * @ngdoc function + * @name angular.reloadWithDebugInfo + * @module ng * @description - * Return an instance of the service. + * Use this function to reload the current application with debug information turned on. + * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`. * - * @param {string} name The name of the instance to retrieve. - * @param {string} caller An optional string to provide the origin of the function call for error messages. - * @return {*} The instance. + * See {@link ng.$compileProvider#debugInfoEnabled} for more. */ +function reloadWithDebugInfo() { + window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name; + window.location.reload(); +} /** - * @ngdoc method - * @name $injector#invoke - * + * @name angular.getTestability + * @module ng * @description - * Invoke the method and supply the method arguments from the `$injector`. - * - * @param {!Function} fn The function to invoke. Function parameters are injected according to the - * {@link guide/di $inject Annotation} rules. - * @param {Object=} self The `this` for the invoked method. - * @param {Object=} locals Optional object. If preset then any argument names are read from this - * object first, before the `$injector` is consulted. - * @returns {*} the value returned by the invoked `fn` function. + * Get the testability service for the instance of Angular on the given + * element. + * @param {DOMElement} element DOM element which is the root of angular application. */ +function getTestability(rootElement) { + var injector = angular.element(rootElement).injector(); + if (!injector) { + throw ngMinErr('test', + 'no injector found for element argument to getTestability'); + } + return injector.get('$$testability'); +} + +var SNAKE_CASE_REGEXP = /[A-Z]/g; +function snake_case(name, separator) { + separator = separator || '_'; + return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { + return (pos ? separator : '') + letter.toLowerCase(); + }); +} + +var bindJQueryFired = false; +var skipDestroyOnNextJQueryCleanData; +function bindJQuery() { + var originalCleanData; + + if (bindJQueryFired) { + return; + } + + // bind to jQuery if present; + var jqName = jq(); + jQuery = window.jQuery; // use default jQuery. + if (isDefined(jqName)) { // `ngJq` present + jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`. + } + + // Use jQuery if it exists with proper functionality, otherwise default to us. + // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. + // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older + // versions. It will not work for sure with jQuery <1.7, though. + if (jQuery && jQuery.fn.on) { + jqLite = jQuery; + extend(jQuery.fn, { + scope: JQLitePrototype.scope, + isolateScope: JQLitePrototype.isolateScope, + controller: JQLitePrototype.controller, + injector: JQLitePrototype.injector, + inheritedData: JQLitePrototype.inheritedData + }); + + // All nodes removed from the DOM via various jQuery APIs like .remove() + // are passed through jQuery.cleanData. Monkey-patch this method to fire + // the $destroy event on all removed nodes. + originalCleanData = jQuery.cleanData; + jQuery.cleanData = function(elems) { + var events; + if (!skipDestroyOnNextJQueryCleanData) { + for (var i = 0, elem; (elem = elems[i]) != null; i++) { + events = jQuery._data(elem, "events"); + if (events && events.$destroy) { + jQuery(elem).triggerHandler('$destroy'); + } + } + } else { + skipDestroyOnNextJQueryCleanData = false; + } + originalCleanData(elems); + }; + } else { + jqLite = JQLite; + } + + angular.element = jqLite; + + // Prevent double-proxying. + bindJQueryFired = true; +} /** - * @ngdoc method - * @name $injector#has - * - * @description - * Allows the user to query if the particular service exists. - * - * @param {string} name Name of the service to query. - * @returns {boolean} `true` if injector has given service. + * throw error if the argument is falsy. */ +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} + +function assertArgFn(arg, name, acceptArrayAnnotation) { + if (acceptArrayAnnotation && isArray(arg)) { + arg = arg[arg.length - 1]; + } + + assertArg(isFunction(arg), name, 'not a function, got ' + + (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg)); + return arg; +} /** - * @ngdoc method - * @name $injector#instantiate - * @description - * Create a new instance of JS type. The method takes a constructor function, invokes the new - * operator, and supplies all of the arguments to the constructor function as specified by the - * constructor annotation. - * - * @param {Function} Type Annotated constructor function. - * @param {Object=} locals Optional object. If preset then any argument names are read from this - * object first, before the `$injector` is consulted. - * @returns {Object} new instance of `Type`. + * throw error if the name given is hasOwnProperty + * @param {String} name the name to test + * @param {String} context the context in which the name is used, such as module or directive */ +function assertNotHasOwnProperty(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context); + } +} /** - * @ngdoc method - * @name $injector#annotate - * - * @description - * Returns an array of service names which the function is requesting for injection. This API is - * used by the injector to determine which services need to be injected into the function when the - * function is invoked. There are three ways in which the function can be annotated with the needed - * dependencies. - * - * # Argument names - * - * The simplest form is to extract the dependencies from the arguments of the function. This is done - * by converting the function into a string using `toString()` method and extracting the argument - * names. - * ```js - * // Given - * function MyController($scope, $route) { - * // ... - * } - * - * // Then - * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); - * ``` - * - * You can disallow this method by using strict injection mode. - * - * This method does not work with code minification / obfuscation. For this reason the following - * annotation strategies are supported. - * - * # The `$inject` property - * - * If a function has an `$inject` property and its value is an array of strings, then the strings - * represent names of services to be injected into the function. - * ```js - * // Given - * var MyController = function(obfuscatedScope, obfuscatedRoute) { - * // ... - * } - * // Define function dependencies - * MyController['$inject'] = ['$scope', '$route']; - * - * // Then - * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); - * ``` - * - * # The array notation - * - * It is often desirable to inline Injected functions and that's when setting the `$inject` property - * is very inconvenient. In these situations using the array notation to specify the dependencies in - * a way that survives minification is a better choice: - * - * ```js - * // We wish to write this (not minification / obfuscation safe) - * injector.invoke(function($compile, $rootScope) { - * // ... - * }); - * - * // We are forced to write break inlining - * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) { - * // ... - * }; - * tmpFn.$inject = ['$compile', '$rootScope']; - * injector.invoke(tmpFn); - * - * // To better support inline function the inline annotation is supported - * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) { - * // ... - * }]); - * - * // Therefore - * expect(injector.annotate( - * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}]) - * ).toEqual(['$compile', '$rootScope']); - * ``` - * - * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to - * be retrieved as described above. - * - * @param {boolean=} [strictDi=false] Disallow argument name annotation inference. - * - * @returns {Array.<string>} The names of the services which the function requires. + * Return the value accessible from the object by path. Any undefined traversals are ignored + * @param {Object} obj starting object + * @param {String} path path to traverse + * @param {boolean} [bindFnToScope=true] + * @returns {Object} value as accessible by path */ +//TODO(misko): this function needs to be removed +function getter(obj, path, bindFnToScope) { + if (!path) return obj; + var keys = path.split('.'); + var key; + var lastInstance = obj; + var len = keys.length; - - + for (var i = 0; i < len; i++) { + key = keys[i]; + if (obj) { + obj = (lastInstance = obj)[key]; + } + } + if (!bindFnToScope && isFunction(obj)) { + return bind(lastInstance, obj); + } + return obj; +} /** - * @ngdoc service - * @name $provide - * - * @description - * - * The {@link auto.$provide $provide} service has a number of methods for registering components - * with the {@link auto.$injector $injector}. Many of these functions are also exposed on - * {@link angular.Module}. - * - * An Angular **service** is a singleton object created by a **service factory**. These **service - * factories** are functions which, in turn, are created by a **service provider**. - * The **service providers** are constructor functions. When instantiated they must contain a - * property called `$get`, which holds the **service factory** function. - * - * When you request a service, the {@link auto.$injector $injector} is responsible for finding the - * correct **service provider**, instantiating it and then calling its `$get` **service factory** - * function to get the instance of the **service**. - * - * Often services have no configuration options and there is no need to add methods to the service - * provider. The provider will be no more than a constructor function with a `$get` property. For - * these cases the {@link auto.$provide $provide} service has additional helper methods to register - * services without specifying a provider. - * - * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the - * {@link auto.$injector $injector} - * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by - * providers and services. - * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by - * services, not providers. - * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, - * that will be wrapped in a **service provider** object, whose `$get` property will contain the - * given factory function. - * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class` - * that will be wrapped in a **service provider** object, whose `$get` property will instantiate - * a new object using the given constructor function. - * - * See the individual methods for more information and examples. + * Return the DOM siblings between the first and last node in the given array. + * @param {Array} array like object + * @returns {jqLite} jqLite collection containing the nodes */ +function getBlockNodes(nodes) { + // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original + // collection, otherwise update the original collection. + var node = nodes[0]; + var endNode = nodes[nodes.length - 1]; + var blockNodes = [node]; -/** - * @ngdoc method - * @name $provide#provider - * @description - * - * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions - * are constructor functions, whose instances are responsible for "providing" a factory for a - * service. - * - * Service provider names start with the name of the service they provide followed by `Provider`. - * For example, the {@link ng.$log $log} service has a provider called - * {@link ng.$logProvider $logProvider}. - * - * Service provider objects can have additional methods which allow configuration of the provider - * and its service. Importantly, you can configure what kind of service is created by the `$get` - * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a - * method {@link ng.$logProvider#debugEnabled debugEnabled} - * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the - * console or not. - * - * @param {string} name The name of the instance. NOTE: the provider will be available under `name + - 'Provider'` key. - * @param {(Object|function())} provider If the provider is: - * - * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using - * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created. - * - `Constructor`: a new instance of the provider will be created using - * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`. - * - * @returns {Object} registered provider instance - - * @example - * - * The following example shows how to create a simple event tracking service and register it using - * {@link auto.$provide#provider $provide.provider()}. - * - * ```js - * // Define the eventTracker provider - * function EventTrackerProvider() { - * var trackingUrl = '/track'; - * - * // A provider method for configuring where the tracked events should been saved - * this.setTrackingUrl = function(url) { - * trackingUrl = url; - * }; - * - * // The service factory function - * this.$get = ['$http', function($http) { - * var trackedEvents = {}; - * return { - * // Call this to track an event - * event: function(event) { - * var count = trackedEvents[event] || 0; - * count += 1; - * trackedEvents[event] = count; - * return count; - * }, - * // Call this to save the tracked events to the trackingUrl - * save: function() { - * $http.post(trackingUrl, trackedEvents); - * } - * }; - * }]; - * } - * - * describe('eventTracker', function() { - * var postSpy; - * - * beforeEach(module(function($provide) { - * // Register the eventTracker provider - * $provide.provider('eventTracker', EventTrackerProvider); - * })); - * - * beforeEach(module(function(eventTrackerProvider) { - * // Configure eventTracker provider - * eventTrackerProvider.setTrackingUrl('/custom-track'); - * })); - * - * it('tracks events', inject(function(eventTracker) { - * expect(eventTracker.event('login')).toEqual(1); - * expect(eventTracker.event('login')).toEqual(2); - * })); - * - * it('saves to the tracking url', inject(function(eventTracker, $http) { - * postSpy = spyOn($http, 'post'); - * eventTracker.event('login'); - * eventTracker.save(); - * expect(postSpy).toHaveBeenCalled(); - * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track'); - * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track'); - * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 }); - * })); - * }); - * ``` - */ + do { + node = node.nextSibling; + if (!node) break; + blockNodes.push(node); + } while (node !== endNode); -/** - * @ngdoc method - * @name $provide#factory - * @description - * - * Register a **service factory**, which will be called to return the service instance. - * This is short for registering a service where its provider consists of only a `$get` property, - * which is the given service factory function. - * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to - * configure your service in a provider. - * - * @param {string} name The name of the instance. - * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand - * for `$provide.provider(name, {$get: $getFn})`. - * @returns {Object} registered provider instance - * - * @example - * Here is an example of registering a service - * ```js - * $provide.factory('ping', ['$http', function($http) { - * return function ping() { - * return $http.send('/ping'); - * }; - * }]); - * ``` - * You would then inject and use this service like this: - * ```js - * someModule.controller('Ctrl', ['ping', function(ping) { - * ping(); - * }]); - * ``` - */ + return jqLite(blockNodes); +} /** - * @ngdoc method - * @name $provide#service - * @description - * - * Register a **service constructor**, which will be invoked with `new` to create the service - * instance. - * This is short for registering a service where its provider's `$get` property is the service - * constructor function that will be used to instantiate the service instance. - * - * You should use {@link auto.$provide#service $provide.service(class)} if you define your service - * as a type/class. - * - * @param {string} name The name of the instance. - * @param {Function} constructor A class (constructor function) that will be instantiated. - * @returns {Object} registered provider instance - * - * @example - * Here is an example of registering a service using - * {@link auto.$provide#service $provide.service(class)}. - * ```js - * var Ping = function($http) { - * this.$http = $http; - * }; + * Creates a new object without a prototype. This object is useful for lookup without having to + * guard against prototypically inherited properties via hasOwnProperty. * - * Ping.$inject = ['$http']; + * Related micro-benchmarks: + * - http://jsperf.com/object-create2 + * - http://jsperf.com/proto-map-lookup/2 + * - http://jsperf.com/for-in-vs-object-keys2 * - * Ping.prototype.send = function() { - * return this.$http.get('/ping'); - * }; - * $provide.service('ping', Ping); - * ``` - * You would then inject and use this service like this: - * ```js - * someModule.controller('Ctrl', ['ping', function(ping) { - * ping.send(); - * }]); - * ``` + * @returns {Object} */ +function createMap() { + return Object.create(null); +} +var NODE_TYPE_ELEMENT = 1; +var NODE_TYPE_ATTRIBUTE = 2; +var NODE_TYPE_TEXT = 3; +var NODE_TYPE_COMMENT = 8; +var NODE_TYPE_DOCUMENT = 9; +var NODE_TYPE_DOCUMENT_FRAGMENT = 11; /** - * @ngdoc method - * @name $provide#value + * @ngdoc type + * @name angular.Module + * @module ng * @description * - * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a - * number, an array, an object or a function. This is short for registering a service where its - * provider's `$get` property is a factory function that takes no arguments and returns the **value - * service**. - * - * Value services are similar to constant services, except that they cannot be injected into a - * module configuration function (see {@link angular.Module#config}) but they can be overridden by - * an Angular - * {@link auto.$provide#decorator decorator}. - * - * @param {string} name The name of the instance. - * @param {*} value The value. - * @returns {Object} registered provider instance - * - * @example - * Here are some examples of creating value services. - * ```js - * $provide.value('ADMIN_USER', 'admin'); - * - * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 }); - * - * $provide.value('halfOf', function(value) { - * return value / 2; - * }); - * ``` + * Interface for configuring angular {@link angular.module modules}. */ +function setupModuleLoader(window) { -/** - * @ngdoc method - * @name $provide#constant - * @description - * - * Register a **constant service**, such as a string, a number, an array, an object or a function, - * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be - * injected into a module configuration function (see {@link angular.Module#config}) and it cannot - * be overridden by an Angular {@link auto.$provide#decorator decorator}. - * - * @param {string} name The name of the constant. - * @param {*} value The constant value. - * @returns {Object} registered instance - * - * @example - * Here a some examples of creating constants: - * ```js - * $provide.constant('SHARD_HEIGHT', 306); - * - * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']); - * - * $provide.constant('double', function(value) { - * return value * 2; - * }); - * ``` - */ + var $injectorMinErr = minErr('$injector'); + var ngMinErr = minErr('ng'); + function ensure(obj, name, factory) { + return obj[name] || (obj[name] = factory()); + } -/** - * @ngdoc method - * @name $provide#decorator - * @description - * - * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator - * intercepts the creation of a service, allowing it to override or modify the behaviour of the - * service. The object returned by the decorator may be the original service, or a new service - * object which replaces or wraps and delegates to the original service. - * - * @param {string} name The name of the service to decorate. - * @param {function()} decorator This function will be invoked when the service needs to be - * instantiated and should return the decorated service instance. The function is called using - * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. - * Local injection arguments: - * - * * `$delegate` - The original service instance, which can be monkey patched, configured, - * decorated or delegated to. - * - * @example - * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting - * calls to {@link ng.$log#error $log.warn()}. - * ```js - * $provide.decorator('$log', ['$delegate', function($delegate) { - * $delegate.warn = $delegate.error; - * return $delegate; - * }]); - * ``` - */ + var angular = ensure(window, 'angular', Object); + // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap + angular.$$minErr = angular.$$minErr || minErr; -function createInjector(modulesToLoad, strictDi) { - strictDi = (strictDi === true); - var INSTANTIATING = {}, - providerSuffix = 'Provider', - path = [], - loadedModules = new HashMap([], true), - providerCache = { - $provide: { - provider: supportObject(provider), - factory: supportObject(factory), - service: supportObject(service), - value: supportObject(value), - constant: supportObject(constant), - decorator: decorator - } - }, - providerInjector = (providerCache.$injector = - createInternalInjector(providerCache, function(serviceName, caller) { - if (angular.isString(caller)) { - path.push(caller); - } - throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); - })), - instanceCache = {}, - instanceInjector = (instanceCache.$injector = - createInternalInjector(instanceCache, function(serviceName, caller) { - var provider = providerInjector.get(serviceName + providerSuffix, caller); - return instanceInjector.invoke(provider.$get, provider, undefined, serviceName); - })); + return ensure(angular, 'module', function() { + /** @type {Object.<string, angular.Module>} */ + var modules = {}; + /** + * @ngdoc function + * @name angular.module + * @module ng + * @description + * + * The `angular.module` is a global place for creating, registering and retrieving Angular + * modules. + * All modules (angular core or 3rd party) that should be available to an application must be + * registered using this mechanism. + * + * When passed two or more arguments, a new module is created. If passed only one argument, an + * existing module (the name passed as the first argument to `module`) is retrieved. + * + * + * # Module + * + * A module is a collection of services, directives, controllers, filters, and configuration information. + * `angular.module` is used to configure the {@link auto.$injector $injector}. + * + * ```js + * // Create a new module + * var myModule = angular.module('myModule', []); + * + * // register a new service + * myModule.value('appName', 'MyCoolApp'); + * + * // configure existing services inside initialization blocks. + * myModule.config(['$locationProvider', function($locationProvider) { + * // Configure existing providers + * $locationProvider.hashPrefix('!'); + * }]); + * ``` + * + * Then you can create an injector and load your modules like this: + * + * ```js + * var injector = angular.injector(['ng', 'myModule']) + * ``` + * + * However it's more likely that you'll just use + * {@link ng.directive:ngApp ngApp} or + * {@link angular.bootstrap} to simplify this process for you. + * + * @param {!string} name The name of the module to create or retrieve. + * @param {!Array.<string>=} requires If specified then new module is being created. If + * unspecified then the module is being retrieved for further configuration. + * @param {Function=} configFn Optional configuration function for the module. Same as + * {@link angular.Module#config Module#config()}. + * @returns {module} new module with the {@link angular.Module} api. + */ + return function module(name, requires, configFn) { + var assertNotHasOwnProperty = function(name, context) { + if (name === 'hasOwnProperty') { + throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context); + } + }; - forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); }); + assertNotHasOwnProperty(name, 'module'); + if (requires && modules.hasOwnProperty(name)) { + modules[name] = null; + } + return ensure(modules, name, function() { + if (!requires) { + throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " + + "the module name or forgot to load it. If registering a module ensure that you " + + "specify the dependencies as the second argument.", name); + } - return instanceInjector; + /** @type {!Array.<Array.<*>>} */ + var invokeQueue = []; - //////////////////////////////////// - // $provider - //////////////////////////////////// + /** @type {!Array.<Function>} */ + var configBlocks = []; - function supportObject(delegate) { - return function(key, value) { - if (isObject(key)) { - forEach(key, reverseParams(delegate)); - } else { - return delegate(key, value); - } - }; - } + /** @type {!Array.<Function>} */ + var runBlocks = []; - function provider(name, provider_) { - assertNotHasOwnProperty(name, 'service'); - if (isFunction(provider_) || isArray(provider_)) { - provider_ = providerInjector.instantiate(provider_); - } - if (!provider_.$get) { - throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); - } - return providerCache[name + providerSuffix] = provider_; - } + var config = invokeLater('$injector', 'invoke', 'push', configBlocks); - function enforceReturnValue(name, factory) { - return function enforcedReturnValue() { - var result = instanceInjector.invoke(factory, this); - if (isUndefined(result)) { - throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name); - } - return result; - }; - } + /** @type {angular.Module} */ + var moduleInstance = { + // Private state + _invokeQueue: invokeQueue, + _configBlocks: configBlocks, + _runBlocks: runBlocks, - function factory(name, factoryFn, enforce) { - return provider(name, { - $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn - }); - } + /** + * @ngdoc property + * @name angular.Module#requires + * @module ng + * + * @description + * Holds the list of modules which the injector will load before the current module is + * loaded. + */ + requires: requires, - function service(name, constructor) { - return factory(name, ['$injector', function($injector) { - return $injector.instantiate(constructor); - }]); - } + /** + * @ngdoc property + * @name angular.Module#name + * @module ng + * + * @description + * Name of the module. + */ + name: name, - function value(name, val) { return factory(name, valueFn(val), false); } - function constant(name, value) { - assertNotHasOwnProperty(name, 'constant'); - providerCache[name] = value; - instanceCache[name] = value; - } + /** + * @ngdoc method + * @name angular.Module#provider + * @module ng + * @param {string} name service name + * @param {Function} providerType Construction function for creating new instance of the + * service. + * @description + * See {@link auto.$provide#provider $provide.provider()}. + */ + provider: invokeLaterAndSetModuleName('$provide', 'provider'), - function decorator(serviceName, decorFn) { - var origProvider = providerInjector.get(serviceName + providerSuffix), - orig$get = origProvider.$get; + /** + * @ngdoc method + * @name angular.Module#factory + * @module ng + * @param {string} name service name + * @param {Function} providerFunction Function for creating new instance of the service. + * @description + * See {@link auto.$provide#factory $provide.factory()}. + */ + factory: invokeLaterAndSetModuleName('$provide', 'factory'), - origProvider.$get = function() { - var origInstance = instanceInjector.invoke(orig$get, origProvider); - return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); - }; - } + /** + * @ngdoc method + * @name angular.Module#service + * @module ng + * @param {string} name service name + * @param {Function} constructor A constructor function that will be instantiated. + * @description + * See {@link auto.$provide#service $provide.service()}. + */ + service: invokeLaterAndSetModuleName('$provide', 'service'), - //////////////////////////////////// - // Module Loading - //////////////////////////////////// - function loadModules(modulesToLoad) { - var runBlocks = [], moduleFn; - forEach(modulesToLoad, function(module) { - if (loadedModules.get(module)) return; - loadedModules.put(module, true); + /** + * @ngdoc method + * @name angular.Module#value + * @module ng + * @param {string} name service name + * @param {*} object Service instance object. + * @description + * See {@link auto.$provide#value $provide.value()}. + */ + value: invokeLater('$provide', 'value'), - function runInvokeQueue(queue) { - var i, ii; - for (i = 0, ii = queue.length; i < ii; i++) { - var invokeArgs = queue[i], - provider = providerInjector.get(invokeArgs[0]); + /** + * @ngdoc method + * @name angular.Module#constant + * @module ng + * @param {string} name constant name + * @param {*} object Constant value. + * @description + * Because the constant are fixed, they get applied before other provide methods. + * See {@link auto.$provide#constant $provide.constant()}. + */ + constant: invokeLater('$provide', 'constant', 'unshift'), - provider[invokeArgs[1]].apply(provider, invokeArgs[2]); - } - } + /** + * @ngdoc method + * @name angular.Module#decorator + * @module ng + * @param {string} The name of the service to decorate. + * @param {Function} This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. + * @description + * See {@link auto.$provide#decorator $provide.decorator()}. + */ + decorator: invokeLaterAndSetModuleName('$provide', 'decorator'), - try { - if (isString(module)) { - moduleFn = angularModule(module); - runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); - runInvokeQueue(moduleFn._invokeQueue); - runInvokeQueue(moduleFn._configBlocks); - } else if (isFunction(module)) { - runBlocks.push(providerInjector.invoke(module)); - } else if (isArray(module)) { - runBlocks.push(providerInjector.invoke(module)); - } else { - assertArgFn(module, 'module'); - } - } catch (e) { - if (isArray(module)) { - module = module[module.length - 1]; - } - if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { - // Safari & FF's stack traces don't contain error.message content - // unlike those of Chrome and IE - // So if stack doesn't contain message, we create a new string that contains both. - // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. - /* jshint -W022 */ - e = e.message + '\n' + e.stack; - } - throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", - module, e.stack || e.message || e); - } - }); - return runBlocks; - } + /** + * @ngdoc method + * @name angular.Module#animation + * @module ng + * @param {string} name animation name + * @param {Function} animationFactory Factory function for creating new instance of an + * animation. + * @description + * + * **NOTE**: animations take effect only if the **ngAnimate** module is loaded. + * + * + * Defines an animation hook that can be later used with + * {@link $animate $animate} service and directives that use this service. + * + * ```js + * module.animation('.animation-name', function($inject1, $inject2) { + * return { + * eventName : function(element, done) { + * //code to run the animation + * //once complete, then run done() + * return function cancellationFunction(element) { + * //code to cancel the animation + * } + * } + * } + * }) + * ``` + * + * See {@link ng.$animateProvider#register $animateProvider.register()} and + * {@link ngAnimate ngAnimate module} for more information. + */ + animation: invokeLaterAndSetModuleName('$animateProvider', 'register'), - //////////////////////////////////// - // internal Injector - //////////////////////////////////// + /** + * @ngdoc method + * @name angular.Module#filter + * @module ng + * @param {string} name Filter name - this must be a valid angular expression identifier + * @param {Function} filterFactory Factory function for creating new instance of filter. + * @description + * See {@link ng.$filterProvider#register $filterProvider.register()}. + * + * <div class="alert alert-warning"> + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + * </div> + */ + filter: invokeLaterAndSetModuleName('$filterProvider', 'register'), - function createInternalInjector(cache, factory) { + /** + * @ngdoc method + * @name angular.Module#controller + * @module ng + * @param {string|Object} name Controller name, or an object map of controllers where the + * keys are the names and the values are the constructors. + * @param {Function} constructor Controller constructor function. + * @description + * See {@link ng.$controllerProvider#register $controllerProvider.register()}. + */ + controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'), - function getService(serviceName, caller) { - if (cache.hasOwnProperty(serviceName)) { - if (cache[serviceName] === INSTANTIATING) { - throw $injectorMinErr('cdep', 'Circular dependency found: {0}', - serviceName + ' <- ' + path.join(' <- ')); - } - return cache[serviceName]; - } else { - try { - path.unshift(serviceName); - cache[serviceName] = INSTANTIATING; - return cache[serviceName] = factory(serviceName, caller); - } catch (err) { - if (cache[serviceName] === INSTANTIATING) { - delete cache[serviceName]; + /** + * @ngdoc method + * @name angular.Module#directive + * @module ng + * @param {string|Object} name Directive name, or an object map of directives where the + * keys are the names and the values are the factories. + * @param {Function} directiveFactory Factory function for creating new instance of + * directives. + * @description + * See {@link ng.$compileProvider#directive $compileProvider.directive()}. + */ + directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'), + + /** + * @ngdoc method + * @name angular.Module#config + * @module ng + * @param {Function} configFn Execute this function on module load. Useful for service + * configuration. + * @description + * Use this method to register work which needs to be performed on module loading. + * For more about how to configure services, see + * {@link providers#provider-recipe Provider Recipe}. + */ + config: config, + + /** + * @ngdoc method + * @name angular.Module#run + * @module ng + * @param {Function} initializationFn Execute this function after injector creation. + * Useful for application initialization. + * @description + * Use this method to register work which should be performed when the injector is done + * loading all modules. + */ + run: function(block) { + runBlocks.push(block); + return this; } - throw err; - } finally { - path.shift(); + }; + + if (configFn) { + config(configFn); } - } - } - function invoke(fn, self, locals, serviceName) { - if (typeof locals === 'string') { - serviceName = locals; - locals = null; - } + return moduleInstance; - var args = [], - $inject = createInjector.$$annotate(fn, strictDi, serviceName), - length, i, - key; + /** + * @param {string} provider + * @param {string} method + * @param {String=} insertMethod + * @returns {angular.Module} + */ + function invokeLater(provider, method, insertMethod, queue) { + if (!queue) queue = invokeQueue; + return function() { + queue[insertMethod || 'push']([provider, method, arguments]); + return moduleInstance; + }; + } - for (i = 0, length = $inject.length; i < length; i++) { - key = $inject[i]; - if (typeof key !== 'string') { - throw $injectorMinErr('itkn', - 'Incorrect injection token! Expected service name as string, got {0}', key); + /** + * @param {string} provider + * @param {string} method + * @returns {angular.Module} + */ + function invokeLaterAndSetModuleName(provider, method) { + return function(recipeName, factoryFunction) { + if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name; + invokeQueue.push([provider, method, arguments]); + return moduleInstance; + }; } - args.push( - locals && locals.hasOwnProperty(key) - ? locals[key] - : getService(key, serviceName) - ); - } - if (isArray(fn)) { - fn = fn[length]; - } + }); + }; + }); - // http://jsperf.com/angularjs-invoke-apply-vs-switch - // #5388 - return fn.apply(self, args); - } +} - function instantiate(Type, locals, serviceName) { - // Check if Type is annotated and use just the given function at n-1 as parameter - // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); - // Object creation: http://jsperf.com/create-constructor/2 - var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null); - var returnedValue = invoke(Type, instance, locals, serviceName); +/* global: toDebugString: true */ - return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; +function serializeObject(obj) { + var seen = []; + + return JSON.stringify(obj, function(key, val) { + val = toJsonReplacer(key, val); + if (isObject(val)) { + + if (seen.indexOf(val) >= 0) return '<<already seen>>'; + + seen.push(val); } + return val; + }); +} - return { - invoke: invoke, - instantiate: instantiate, - get: getService, - annotate: createInjector.$$annotate, - has: function(name) { - return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); - } - }; +function toDebugString(obj) { + if (typeof obj === 'function') { + return obj.toString().replace(/ \{[\s\S]*$/, ''); + } else if (typeof obj === 'undefined') { + return 'undefined'; + } else if (typeof obj !== 'string') { + return serializeObject(obj); } + return obj; } -createInjector.$$annotate = annotate; +/* global angularModule: true, + version: true, + + $LocaleProvider, + $CompileProvider, + + htmlAnchorDirective, + inputDirective, + inputDirective, + formDirective, + scriptDirective, + selectDirective, + styleDirective, + optionDirective, + ngBindDirective, + ngBindHtmlDirective, + ngBindTemplateDirective, + ngClassDirective, + ngClassEvenDirective, + ngClassOddDirective, + ngCspDirective, + ngCloakDirective, + ngControllerDirective, + ngFormDirective, + ngHideDirective, + ngIfDirective, + ngIncludeDirective, + ngIncludeFillContentDirective, + ngInitDirective, + ngNonBindableDirective, + ngPluralizeDirective, + ngRepeatDirective, + ngShowDirective, + ngStyleDirective, + ngSwitchDirective, + ngSwitchWhenDirective, + ngSwitchDefaultDirective, + ngOptionsDirective, + ngTranscludeDirective, + ngModelDirective, + ngListDirective, + ngChangeDirective, + patternDirective, + patternDirective, + requiredDirective, + requiredDirective, + minlengthDirective, + minlengthDirective, + maxlengthDirective, + maxlengthDirective, + ngValueDirective, + ngModelOptionsDirective, + ngAttributeAliasDirectives, + ngEventDirectives, + + $AnchorScrollProvider, + $AnimateProvider, + $$CoreAnimateQueueProvider, + $$CoreAnimateRunnerProvider, + $BrowserProvider, + $CacheFactoryProvider, + $ControllerProvider, + $DocumentProvider, + $ExceptionHandlerProvider, + $FilterProvider, + $InterpolateProvider, + $IntervalProvider, + $$HashMapProvider, + $HttpProvider, + $HttpParamSerializerProvider, + $HttpParamSerializerJQLikeProvider, + $HttpBackendProvider, + $LocationProvider, + $LogProvider, + $ParseProvider, + $RootScopeProvider, + $QProvider, + $$QProvider, + $$SanitizeUriProvider, + $SceProvider, + $SceDelegateProvider, + $SnifferProvider, + $TemplateCacheProvider, + $TemplateRequestProvider, + $$TestabilityProvider, + $TimeoutProvider, + $$RAFProvider, + $WindowProvider, + $$jqLiteProvider, + $$CookieReaderProvider +*/ + /** - * @ngdoc provider - * @name $anchorScrollProvider - * + * @ngdoc object + * @name angular.version + * @module ng * @description - * Use `$anchorScrollProvider` to disable automatic scrolling whenever - * {@link ng.$location#hash $location.hash()} changes. + * An object that contains information about the current AngularJS version. This object has the + * following properties: + * + * - `full` – `{string}` – Full version string, such as "0.9.18". + * - `major` – `{number}` – Major version number, such as "0". + * - `minor` – `{number}` – Minor version number, such as "9". + * - `dot` – `{number}` – Dot version number, such as "18". + * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". */ -function $AnchorScrollProvider() { - - var autoScrollingEnabled = true; +var version = { + full: '1.4.3', // all of these placeholder strings will be replaced by grunt's + major: 1, // package task + minor: 4, + dot: 3, + codeName: 'foam-acceleration' +}; - /** - * @ngdoc method - * @name $anchorScrollProvider#disableAutoScrolling - * - * @description - * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to - * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br /> - * Use this method to disable automatic scrolling. - * - * If automatic scrolling is disabled, one must explicitly call - * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the - * current hash. - */ - this.disableAutoScrolling = function() { - autoScrollingEnabled = false; - }; - /** - * @ngdoc service - * @name $anchorScroll - * @kind function - * @requires $window - * @requires $location - * @requires $rootScope - * - * @description - * When called, it checks the current value of {@link ng.$location#hash $location.hash()} and - * scrolls to the related element, according to the rules specified in the - * [Html5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). - * - * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to - * match any anchor whenever it changes. This can be disabled by calling - * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}. - * - * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a - * vertical scroll-offset (either fixed or dynamic). - * - * @property {(number|function|jqLite)} yOffset - * If set, specifies a vertical scroll-offset. This is often useful when there are fixed - * positioned elements at the top of the page, such as navbars, headers etc. - * - * `yOffset` can be specified in various ways: - * - **number**: A fixed number of pixels to be used as offset.<br /><br /> - * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return - * a number representing the offset (in pixels).<br /><br /> - * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from - * the top of the page to the element's bottom will be used as offset.<br /> - * **Note**: The element will be taken into account only as long as its `position` is set to - * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust - * their height and/or positioning according to the viewport's size. - * - * <br /> - * <div class="alert alert-warning"> - * In order for `yOffset` to work properly, scrolling should take place on the document's root and - * not some child element. - * </div> - * - * @example - <example module="anchorScrollExample"> - <file name="index.html"> - <div id="scrollArea" ng-controller="ScrollController"> - <a ng-click="gotoBottom()">Go to bottom</a> - <a id="bottom"></a> You're at the bottom! - </div> - </file> - <file name="script.js"> - angular.module('anchorScrollExample', []) - .controller('ScrollController', ['$scope', '$location', '$anchorScroll', - function ($scope, $location, $anchorScroll) { - $scope.gotoBottom = function() { - // set the location.hash to the id of - // the element you wish to scroll to. - $location.hash('bottom'); +function publishExternalAPI(angular) { + extend(angular, { + 'bootstrap': bootstrap, + 'copy': copy, + 'extend': extend, + 'merge': merge, + 'equals': equals, + 'element': jqLite, + 'forEach': forEach, + 'injector': createInjector, + 'noop': noop, + 'bind': bind, + 'toJson': toJson, + 'fromJson': fromJson, + 'identity': identity, + 'isUndefined': isUndefined, + 'isDefined': isDefined, + 'isString': isString, + 'isFunction': isFunction, + 'isObject': isObject, + 'isNumber': isNumber, + 'isElement': isElement, + 'isArray': isArray, + 'version': version, + 'isDate': isDate, + 'lowercase': lowercase, + 'uppercase': uppercase, + 'callbacks': {counter: 0}, + 'getTestability': getTestability, + '$$minErr': minErr, + '$$csp': csp, + 'reloadWithDebugInfo': reloadWithDebugInfo + }); - // call $anchorScroll() - $anchorScroll(); - }; - }]); - </file> - <file name="style.css"> - #scrollArea { - height: 280px; - overflow: auto; - } + angularModule = setupModuleLoader(window); + try { + angularModule('ngLocale'); + } catch (e) { + angularModule('ngLocale', []).provider('$locale', $LocaleProvider); + } - #bottom { - display: block; - margin-top: 2000px; - } - </file> - </example> - * - * <hr /> - * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value). - * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details. - * - * @example - <example module="anchorScrollOffsetExample"> - <file name="index.html"> - <div class="fixed-header" ng-controller="headerCtrl"> - <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]"> - Go to anchor {{x}} - </a> - </div> - <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]"> - Anchor {{x}} of 5 - </div> - </file> - <file name="script.js"> - angular.module('anchorScrollOffsetExample', []) - .run(['$anchorScroll', function($anchorScroll) { - $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels - }]) - .controller('headerCtrl', ['$anchorScroll', '$location', '$scope', - function ($anchorScroll, $location, $scope) { - $scope.gotoAnchor = function(x) { - var newHash = 'anchor' + x; - if ($location.hash() !== newHash) { - // set the $location.hash to `newHash` and - // $anchorScroll will automatically scroll to it - $location.hash('anchor' + x); - } else { - // call $anchorScroll() explicitly, - // since $location.hash hasn't changed - $anchorScroll(); - } - }; - } - ]); - </file> - <file name="style.css"> - body { - padding-top: 50px; - } + angularModule('ng', ['ngLocale'], ['$provide', + function ngModule($provide) { + // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it. + $provide.provider({ + $$sanitizeUri: $$SanitizeUriProvider + }); + $provide.provider('$compile', $CompileProvider). + directive({ + a: htmlAnchorDirective, + input: inputDirective, + textarea: inputDirective, + form: formDirective, + script: scriptDirective, + select: selectDirective, + style: styleDirective, + option: optionDirective, + ngBind: ngBindDirective, + ngBindHtml: ngBindHtmlDirective, + ngBindTemplate: ngBindTemplateDirective, + ngClass: ngClassDirective, + ngClassEven: ngClassEvenDirective, + ngClassOdd: ngClassOddDirective, + ngCloak: ngCloakDirective, + ngController: ngControllerDirective, + ngForm: ngFormDirective, + ngHide: ngHideDirective, + ngIf: ngIfDirective, + ngInclude: ngIncludeDirective, + ngInit: ngInitDirective, + ngNonBindable: ngNonBindableDirective, + ngPluralize: ngPluralizeDirective, + ngRepeat: ngRepeatDirective, + ngShow: ngShowDirective, + ngStyle: ngStyleDirective, + ngSwitch: ngSwitchDirective, + ngSwitchWhen: ngSwitchWhenDirective, + ngSwitchDefault: ngSwitchDefaultDirective, + ngOptions: ngOptionsDirective, + ngTransclude: ngTranscludeDirective, + ngModel: ngModelDirective, + ngList: ngListDirective, + ngChange: ngChangeDirective, + pattern: patternDirective, + ngPattern: patternDirective, + required: requiredDirective, + ngRequired: requiredDirective, + minlength: minlengthDirective, + ngMinlength: minlengthDirective, + maxlength: maxlengthDirective, + ngMaxlength: maxlengthDirective, + ngValue: ngValueDirective, + ngModelOptions: ngModelOptionsDirective + }). + directive({ + ngInclude: ngIncludeFillContentDirective + }). + directive(ngAttributeAliasDirectives). + directive(ngEventDirectives); + $provide.provider({ + $anchorScroll: $AnchorScrollProvider, + $animate: $AnimateProvider, + $$animateQueue: $$CoreAnimateQueueProvider, + $$AnimateRunner: $$CoreAnimateRunnerProvider, + $browser: $BrowserProvider, + $cacheFactory: $CacheFactoryProvider, + $controller: $ControllerProvider, + $document: $DocumentProvider, + $exceptionHandler: $ExceptionHandlerProvider, + $filter: $FilterProvider, + $interpolate: $InterpolateProvider, + $interval: $IntervalProvider, + $http: $HttpProvider, + $httpParamSerializer: $HttpParamSerializerProvider, + $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider, + $httpBackend: $HttpBackendProvider, + $location: $LocationProvider, + $log: $LogProvider, + $parse: $ParseProvider, + $rootScope: $RootScopeProvider, + $q: $QProvider, + $$q: $$QProvider, + $sce: $SceProvider, + $sceDelegate: $SceDelegateProvider, + $sniffer: $SnifferProvider, + $templateCache: $TemplateCacheProvider, + $templateRequest: $TemplateRequestProvider, + $$testability: $$TestabilityProvider, + $timeout: $TimeoutProvider, + $window: $WindowProvider, + $$rAF: $$RAFProvider, + $$jqLite: $$jqLiteProvider, + $$HashMap: $$HashMapProvider, + $$cookieReader: $$CookieReaderProvider + }); + } + ]); +} - .anchor { - border: 2px dashed DarkOrchid; - padding: 10px 10px 200px 10px; - } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - .fixed-header { - background-color: rgba(0, 0, 0, 0.2); - height: 50px; - position: fixed; - top: 0; left: 0; right: 0; - } +/* global JQLitePrototype: true, + addEventListenerFn: true, + removeEventListenerFn: true, + BOOLEAN_ATTR: true, + ALIASED_ATTR: true, +*/ - .fixed-header > a { - display: inline-block; - margin: 5px 15px; - } - </file> - </example> - */ - this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { - var document = $window.document; +////////////////////////////////// +//JQLite +////////////////////////////////// - // Helper function to get first anchor from a NodeList - // (using `Array#some()` instead of `angular#forEach()` since it's more performant - // and working in all supported browsers.) - function getFirstAnchor(list) { - var result = null; - Array.prototype.some.call(list, function(element) { - if (nodeName_(element) === 'a') { - result = element; - return true; - } - }); - return result; - } +/** + * @ngdoc function + * @name angular.element + * @module ng + * @kind function + * + * @description + * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. + * + * If jQuery is available, `angular.element` is an alias for the + * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element` + * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." + * + * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows + * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most + * commonly needed functionality with the goal of having a very small footprint.</div> + * + * To use `jQuery`, simply ensure it is loaded before the `angular.js` file. + * + * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or + * jqLite; they are never raw DOM references.</div> + * + * ## Angular's jqLite + * jqLite provides only the following jQuery methods: + * + * - [`addClass()`](http://api.jquery.com/addClass/) + * - [`after()`](http://api.jquery.com/after/) + * - [`append()`](http://api.jquery.com/append/) + * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters + * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData + * - [`children()`](http://api.jquery.com/children/) - Does not support selectors + * - [`clone()`](http://api.jquery.com/clone/) + * - [`contents()`](http://api.jquery.com/contents/) + * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'. + * - [`data()`](http://api.jquery.com/data/) + * - [`detach()`](http://api.jquery.com/detach/) + * - [`empty()`](http://api.jquery.com/empty/) + * - [`eq()`](http://api.jquery.com/eq/) + * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name + * - [`hasClass()`](http://api.jquery.com/hasClass/) + * - [`html()`](http://api.jquery.com/html/) + * - [`next()`](http://api.jquery.com/next/) - Does not support selectors + * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData + * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors + * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors + * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors + * - [`prepend()`](http://api.jquery.com/prepend/) + * - [`prop()`](http://api.jquery.com/prop/) + * - [`ready()`](http://api.jquery.com/ready/) + * - [`remove()`](http://api.jquery.com/remove/) + * - [`removeAttr()`](http://api.jquery.com/removeAttr/) + * - [`removeClass()`](http://api.jquery.com/removeClass/) + * - [`removeData()`](http://api.jquery.com/removeData/) + * - [`replaceWith()`](http://api.jquery.com/replaceWith/) + * - [`text()`](http://api.jquery.com/text/) + * - [`toggleClass()`](http://api.jquery.com/toggleClass/) + * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. + * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces + * - [`val()`](http://api.jquery.com/val/) + * - [`wrap()`](http://api.jquery.com/wrap/) + * + * ## jQuery/jqLite Extras + * Angular also provides the following additional methods and events to both jQuery and jqLite: + * + * ### Events + * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event + * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM + * element before it is removed. + * + * ### Methods + * - `controller(name)` - retrieves the controller of the current element or its parent. By default + * retrieves controller associated with the `ngController` directive. If `name` is provided as + * camelCase directive name, then the controller for this directive will be retrieved (e.g. + * `'ngModel'`). + * - `injector()` - retrieves the injector of the current element or its parent. + * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current + * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to + * be enabled. + * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the + * current element. This getter should be used only on elements that contain a directive which starts a new isolate + * scope. Calling `scope()` on this element always returns the original non-isolate scope. + * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled. + * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top + * parent element is reached. + * + * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. + * @returns {Object} jQuery object. + */ - function getYOffset() { +JQLite.expando = 'ng339'; - var offset = scroll.yOffset; +var jqCache = JQLite.cache = {}, + jqId = 1, + addEventListenerFn = function(element, type, fn) { + element.addEventListener(type, fn, false); + }, + removeEventListenerFn = function(element, type, fn) { + element.removeEventListener(type, fn, false); + }; - if (isFunction(offset)) { - offset = offset(); - } else if (isElement(offset)) { - var elem = offset[0]; - var style = $window.getComputedStyle(elem); - if (style.position !== 'fixed') { - offset = 0; - } else { - offset = elem.getBoundingClientRect().bottom; - } - } else if (!isNumber(offset)) { - offset = 0; - } +/* + * !!! This is an undocumented "private" function !!! + */ +JQLite._data = function(node) { + //jQuery always returns an object on cache miss + return this.cache[node[this.expando]] || {}; +}; - return offset; - } +function jqNextId() { return ++jqId; } - function scrollTo(elem) { - if (elem) { - elem.scrollIntoView(); - var offset = getYOffset(); +var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; +var MOZ_HACK_REGEXP = /^moz([A-Z])/; +var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"}; +var jqLiteMinErr = minErr('jqLite'); - if (offset) { - // `offset` is the number of pixels we should scroll UP in order to align `elem` properly. - // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the - // top of the viewport. - // - // IF the number of pixels from the top of `elem` to the end of the page's content is less - // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some - // way down the page. - // - // This is often the case for elements near the bottom of the page. - // - // In such cases we do not need to scroll the whole `offset` up, just the difference between - // the top of the element and the offset, which is enough to align the top of `elem` at the - // desired position. - var elemTop = elem.getBoundingClientRect().top; - $window.scrollBy(0, elemTop - offset); - } - } else { - $window.scrollTo(0, 0); - } - } +/** + * Converts snake_case to camelCase. + * Also there is special case for Moz prefix starting with upper case letter. + * @param name Name to normalize + */ +function camelCase(name) { + return name. + replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }). + replace(MOZ_HACK_REGEXP, 'Moz$1'); +} - function scroll() { - var hash = $location.hash(), elm; +var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/; +var HTML_REGEXP = /<|&#?\w+;/; +var TAG_NAME_REGEXP = /<([\w:]+)/; +var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; - // empty hash, scroll to the top of the page - if (!hash) scrollTo(null); +var wrapMap = { + 'option': [1, '<select multiple="multiple">', '</select>'], - // element with given id - else if ((elm = document.getElementById(hash))) scrollTo(elm); + 'thead': [1, '<table>', '</table>'], + 'col': [2, '<table><colgroup>', '</colgroup></table>'], + 'tr': [2, '<table><tbody>', '</tbody></table>'], + 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'], + '_default': [0, "", ""] +}; - // first anchor with given name :-D - else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm); +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; - // no element and hash == 'top', scroll to the top of the page - else if (hash === 'top') scrollTo(null); - } - // does not scroll when user clicks on anchor link that is currently on - // (no url change, no $location.hash() change), browser native does scroll - if (autoScrollingEnabled) { - $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, - function autoScrollWatchAction(newVal, oldVal) { - // skip the initial scroll if $location.hash is empty - if (newVal === oldVal && newVal === '') return; +function jqLiteIsTextNode(html) { + return !HTML_REGEXP.test(html); +} - jqLiteDocumentLoaded(function() { - $rootScope.$evalAsync(scroll); - }); - }); - } +function jqLiteAcceptsData(node) { + // The window object can accept data but has no nodeType + // Otherwise we are only interested in elements (1) and documents (9) + var nodeType = node.nodeType; + return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT; +} - return scroll; - }]; +function jqLiteHasData(node) { + for (var key in jqCache[node.ng339]) { + return true; + } + return false; } -var $animateMinErr = minErr('$animate'); +function jqLiteBuildFragment(html, context) { + var tmp, tag, wrap, + fragment = context.createDocumentFragment(), + nodes = [], i; -/** - * @ngdoc provider - * @name $animateProvider - * - * @description - * Default implementation of $animate that doesn't perform any animations, instead just - * synchronously performs DOM - * updates and calls done() callbacks. - * - * In order to enable animations the ngAnimate module has to be loaded. - * - * To see the functional implementation check out src/ngAnimate/animate.js - */ -var $AnimateProvider = ['$provide', function($provide) { + if (jqLiteIsTextNode(html)) { + // Convert non-html into a text node + nodes.push(context.createTextNode(html)); + } else { + // Convert html into DOM nodes + tmp = tmp || fragment.appendChild(context.createElement("div")); + tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase(); + wrap = wrapMap[tag] || wrapMap._default; + tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2]; + // Descend through wrappers to the right content + i = wrap[0]; + while (i--) { + tmp = tmp.lastChild; + } - this.$$selectors = {}; + nodes = concat(nodes, tmp.childNodes); + tmp = fragment.firstChild; + tmp.textContent = ""; + } - /** - * @ngdoc method - * @name $animateProvider#register - * - * @description - * Registers a new injectable animation factory function. The factory function produces the - * animation object which contains callback functions for each event that is expected to be - * animated. - * - * * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction` - * must be called once the element animation is complete. If a function is returned then the - * animation service will use this function to cancel the animation whenever a cancel event is - * triggered. - * - * - * ```js - * return { - * eventFn : function(element, done) { - * //code to run the animation - * //once complete, then run done() - * return function cancellationFunction() { - * //code to cancel the animation - * } - * } - * } - * ``` - * - * @param {string} name The name of the animation. - * @param {Function} factory The factory function that will be executed to return the animation - * object. - */ - this.register = function(name, factory) { - var key = name + '-animation'; - if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel', - "Expecting class selector starting with '.' got '{0}'.", name); - this.$$selectors[name.substr(1)] = key; - $provide.factory(key, factory); - }; + // Remove wrapper from fragment + fragment.textContent = ""; + fragment.innerHTML = ""; // Clear inner HTML + forEach(nodes, function(node) { + fragment.appendChild(node); + }); - /** - * @ngdoc method - * @name $animateProvider#classNameFilter - * - * @description - * Sets and/or returns the CSS class regular expression that is checked when performing - * an animation. Upon bootstrap the classNameFilter value is not set at all and will - * therefore enable $animate to attempt to perform an animation on any element. - * When setting the classNameFilter value, animations will only be performed on elements - * that successfully match the filter expression. This in turn can boost performance - * for low-powered devices as well as applications containing a lot of structural operations. - * @param {RegExp=} expression The className expression which will be checked against all animations - * @return {RegExp} The current CSS className expression value. If null then there is no expression value - */ - this.classNameFilter = function(expression) { - if (arguments.length === 1) { - this.$$classNameFilter = (expression instanceof RegExp) ? expression : null; - } - return this.$$classNameFilter; - }; + return fragment; +} - this.$get = ['$$q', '$$asyncCallback', '$rootScope', function($$q, $$asyncCallback, $rootScope) { +function jqLiteParseHTML(html, context) { + context = context || document; + var parsed; - var currentDefer; + if ((parsed = SINGLE_TAG_REGEXP.exec(html))) { + return [context.createElement(parsed[1])]; + } - function runAnimationPostDigest(fn) { - var cancelFn, defer = $$q.defer(); - defer.promise.$$cancelFn = function ngAnimateMaybeCancel() { - cancelFn && cancelFn(); - }; + if ((parsed = jqLiteBuildFragment(html, context))) { + return parsed.childNodes; + } - $rootScope.$$postDigest(function ngAnimatePostDigest() { - cancelFn = fn(function ngAnimateNotifyComplete() { - defer.resolve(); - }); - }); + return []; +} - return defer.promise; - } +///////////////////////////////////////////// +function JQLite(element) { + if (element instanceof JQLite) { + return element; + } - function resolveElementClasses(element, classes) { - var toAdd = [], toRemove = []; + var argIsString; - var hasClasses = createMap(); - forEach((element.attr('class') || '').split(/\s+/), function(className) { - hasClasses[className] = true; - }); + if (isString(element)) { + element = trim(element); + argIsString = true; + } + if (!(this instanceof JQLite)) { + if (argIsString && element.charAt(0) != '<') { + throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element'); + } + return new JQLite(element); + } + + if (argIsString) { + jqLiteAddNodes(this, jqLiteParseHTML(element)); + } else { + jqLiteAddNodes(this, element); + } +} - forEach(classes, function(status, className) { - var hasClass = hasClasses[className]; +function jqLiteClone(element) { + return element.cloneNode(true); +} - // If the most recent class manipulation (via $animate) was to remove the class, and the - // element currently has the class, the class is scheduled for removal. Otherwise, if - // the most recent class manipulation (via $animate) was to add the class, and the - // element does not currently have the class, the class is scheduled to be added. - if (status === false && hasClass) { - toRemove.push(className); - } else if (status === true && !hasClass) { - toAdd.push(className); - } - }); +function jqLiteDealoc(element, onlyDescendants) { + if (!onlyDescendants) jqLiteRemoveData(element); - return (toAdd.length + toRemove.length) > 0 && - [toAdd.length ? toAdd : null, toRemove.length ? toRemove : null]; + if (element.querySelectorAll) { + var descendants = element.querySelectorAll('*'); + for (var i = 0, l = descendants.length; i < l; i++) { + jqLiteRemoveData(descendants[i]); } + } +} + +function jqLiteOff(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument'); + + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var handle = expandoStore && expandoStore.handle; + + if (!handle) return; //no listeners registered - function cachedClassManipulation(cache, classes, op) { - for (var i=0, ii = classes.length; i < ii; ++i) { - var className = classes[i]; - cache[className] = op; + if (!type) { + for (type in events) { + if (type !== '$destroy') { + removeEventListenerFn(element, type, handle); } + delete events[type]; } - - function asyncPromise() { - // only serve one instance of a promise in order to save CPU cycles - if (!currentDefer) { - currentDefer = $$q.defer(); - $$asyncCallback(function() { - currentDefer.resolve(); - currentDefer = null; - }); + } else { + forEach(type.split(' '), function(type) { + if (isDefined(fn)) { + var listenerFns = events[type]; + arrayRemove(listenerFns || [], fn); + if (listenerFns && listenerFns.length > 0) { + return; + } } - return currentDefer.promise; + + removeEventListenerFn(element, type, handle); + delete events[type]; + }); + } +} + +function jqLiteRemoveData(element, name) { + var expandoId = element.ng339; + var expandoStore = expandoId && jqCache[expandoId]; + + if (expandoStore) { + if (name) { + delete expandoStore.data[name]; + return; } - function applyStyles(element, options) { - if (angular.isObject(options)) { - var styles = extend(options.from || {}, options.to || {}); - element.css(styles); + if (expandoStore.handle) { + if (expandoStore.events.$destroy) { + expandoStore.handle({}, '$destroy'); } + jqLiteOff(element); } + delete jqCache[expandoId]; + element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it + } +} - /** - * - * @ngdoc service - * @name $animate - * @description The $animate service provides rudimentary DOM manipulation functions to - * insert, remove and move elements within the DOM, as well as adding and removing classes. - * This service is the core service used by the ngAnimate $animator service which provides - * high-level animation hooks for CSS and JavaScript. - * - * $animate is available in the AngularJS core, however, the ngAnimate module must be included - * to enable full out animation support. Otherwise, $animate will only perform simple DOM - * manipulation operations. - * - * To learn more about enabling animation support, click here to visit the {@link ngAnimate - * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service - * page}. - */ - return { - animate: function(element, from, to) { - applyStyles(element, { from: from, to: to }); - return asyncPromise(); - }, - - /** - * - * @ngdoc method - * @name $animate#enter - * @kind function - * @description Inserts the element into the DOM either after the `after` element or - * as the first child within the `parent` element. When the function is called a promise - * is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will be inserted into the DOM - * @param {DOMElement} parent the parent element which will append the element as - * a child (if the after element is not present) - * @param {DOMElement} after the sibling element which will append the element - * after itself - * @param {object=} options an optional collection of styles that will be applied to the element. - * @return {Promise} the animation callback promise - */ - enter: function(element, parent, after, options) { - applyStyles(element, options); - after ? after.after(element) - : parent.prepend(element); - return asyncPromise(); - }, - - /** - * - * @ngdoc method - * @name $animate#leave - * @kind function - * @description Removes the element from the DOM. When the function is called a promise - * is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will be removed from the DOM - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise - */ - leave: function(element, options) { - element.remove(); - return asyncPromise(); - }, - /** - * - * @ngdoc method - * @name $animate#move - * @kind function - * @description Moves the position of the provided element within the DOM to be placed - * either after the `after` element or inside of the `parent` element. When the function - * is called a promise is returned that will be resolved at a later time. - * - * @param {DOMElement} element the element which will be moved around within the - * DOM - * @param {DOMElement} parent the parent element where the element will be - * inserted into (if the after element is not present) - * @param {DOMElement} after the sibling element where the element will be - * positioned next to - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise - */ - move: function(element, parent, after, options) { - // Do not remove element before insert. Removing will cause data associated with the - // element to be dropped. Insert will implicitly do the remove. - return this.enter(element, parent, after, options); - }, +function jqLiteExpandoStore(element, createIfNecessary) { + var expandoId = element.ng339, + expandoStore = expandoId && jqCache[expandoId]; - /** - * - * @ngdoc method - * @name $animate#addClass - * @kind function - * @description Adds the provided className CSS class value to the provided element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have the className value - * added to it - * @param {string} className the CSS class which will be added to the element - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise - */ - addClass: function(element, className, options) { - return this.setClass(element, className, [], options); - }, + if (createIfNecessary && !expandoStore) { + element.ng339 = expandoId = jqNextId(); + expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined}; + } - $$addClassImmediately: function(element, className, options) { - element = jqLite(element); - className = !isString(className) - ? (isArray(className) ? className.join(' ') : '') - : className; - forEach(element, function(element) { - jqLiteAddClass(element, className); - }); - applyStyles(element, options); - return asyncPromise(); - }, + return expandoStore; +} - /** - * - * @ngdoc method - * @name $animate#removeClass - * @kind function - * @description Removes the provided className CSS class value from the provided element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have the className value - * removed from it - * @param {string} className the CSS class which will be removed from the element - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise - */ - removeClass: function(element, className, options) { - return this.setClass(element, [], className, options); - }, - $$removeClassImmediately: function(element, className, options) { - element = jqLite(element); - className = !isString(className) - ? (isArray(className) ? className.join(' ') : '') - : className; - forEach(element, function(element) { - jqLiteRemoveClass(element, className); - }); - applyStyles(element, options); - return asyncPromise(); - }, +function jqLiteData(element, key, value) { + if (jqLiteAcceptsData(element)) { - /** - * - * @ngdoc method - * @name $animate#setClass - * @kind function - * @description Adds and/or removes the given CSS classes to and from the element. - * When the function is called a promise is returned that will be resolved at a later time. - * @param {DOMElement} element the element which will have its CSS classes changed - * removed from it - * @param {string} add the CSS classes which will be added to the element - * @param {string} remove the CSS class which will be removed from the element - * @param {object=} options an optional collection of options that will be applied to the element. - * @return {Promise} the animation callback promise - */ - setClass: function(element, add, remove, options) { - var self = this; - var STORAGE_KEY = '$$animateClasses'; - var createdCache = false; - element = jqLite(element); - - var cache = element.data(STORAGE_KEY); - if (!cache) { - cache = { - classes: {}, - options: options - }; - createdCache = true; - } else if (options && cache.options) { - cache.options = angular.extend(cache.options || {}, options); - } - - var classes = cache.classes; - - add = isArray(add) ? add : add.split(' '); - remove = isArray(remove) ? remove : remove.split(' '); - cachedClassManipulation(classes, add, true); - cachedClassManipulation(classes, remove, false); - - if (createdCache) { - cache.promise = runAnimationPostDigest(function(done) { - var cache = element.data(STORAGE_KEY); - element.removeData(STORAGE_KEY); - - // in the event that the element is removed before postDigest - // is run then the cache will be undefined and there will be - // no need anymore to add or remove and of the element classes - if (cache) { - var classes = resolveElementClasses(element, cache.classes); - if (classes) { - self.$$setClassImmediately(element, classes[0], classes[1], cache.options); - } - } + var isSimpleSetter = isDefined(value); + var isSimpleGetter = !isSimpleSetter && key && !isObject(key); + var massGetter = !key; + var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter); + var data = expandoStore && expandoStore.data; - done(); - }); - element.data(STORAGE_KEY, cache); + if (isSimpleSetter) { // data('key', value) + data[key] = value; + } else { + if (massGetter) { // data() + return data; + } else { + if (isSimpleGetter) { // data('key') + // don't force creation of expandoStore if it doesn't exist yet + return data && data[key]; + } else { // mass-setter: data({key1: val1, key2: val2}) + extend(data, key); } + } + } + } +} - return cache.promise; - }, +function jqLiteHasClass(element, selector) { + if (!element.getAttribute) return false; + return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " "). + indexOf(" " + selector + " ") > -1); +} - $$setClassImmediately: function(element, add, remove, options) { - add && this.$$addClassImmediately(element, add); - remove && this.$$removeClassImmediately(element, remove); - applyStyles(element, options); - return asyncPromise(); - }, +function jqLiteRemoveClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + forEach(cssClasses.split(' '), function(cssClass) { + element.setAttribute('class', trim( + (" " + (element.getAttribute('class') || '') + " ") + .replace(/[\n\t]/g, " ") + .replace(" " + trim(cssClass) + " ", " ")) + ); + }); + } +} - enabled: noop, - cancel: noop - }; - }]; -}]; +function jqLiteAddClass(element, cssClasses) { + if (cssClasses && element.setAttribute) { + var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ') + .replace(/[\n\t]/g, " "); -function $$AsyncCallbackProvider() { - this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) { - return $$rAF.supported - ? function(fn) { return $$rAF(fn); } - : function(fn) { - return $timeout(fn, 0, false); - }; - }]; -} + forEach(cssClasses.split(' '), function(cssClass) { + cssClass = trim(cssClass); + if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) { + existingClasses += cssClass + ' '; + } + }); -/* global stripHash: true */ + element.setAttribute('class', trim(existingClasses)); + } +} -/** - * ! This is a private undocumented service ! - * - * @name $browser - * @requires $log - * @description - * This object has two goals: - * - * - hide all the global state in the browser caused by the window object - * - abstract away all the browser specific features and inconsistencies - * - * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` - * service, which can be used for convenient testing of the application without the interaction with - * the real browser apis. - */ -/** - * @param {object} window The global window object. - * @param {object} document jQuery wrapped document. - * @param {object} $log window.console or an object with the same interface. - * @param {object} $sniffer $sniffer service - */ -function Browser(window, document, $log, $sniffer) { - var self = this, - rawDocument = document[0], - location = window.location, - history = window.history, - setTimeout = window.setTimeout, - clearTimeout = window.clearTimeout, - pendingDeferIds = {}; - self.isMock = false; +function jqLiteAddNodes(root, elements) { + // THIS CODE IS VERY HOT. Don't make changes without benchmarking. - var outstandingRequestCount = 0; - var outstandingRequestCallbacks = []; + if (elements) { - // TODO(vojta): remove this temporary api - self.$$completeOutstandingRequest = completeOutstandingRequest; - self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; + // if a Node (the most common case) + if (elements.nodeType) { + root[root.length++] = elements; + } else { + var length = elements.length; - /** - * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` - * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. - */ - function completeOutstandingRequest(fn) { - try { - fn.apply(null, sliceArgs(arguments, 1)); - } finally { - outstandingRequestCount--; - if (outstandingRequestCount === 0) { - while (outstandingRequestCallbacks.length) { - try { - outstandingRequestCallbacks.pop()(); - } catch (e) { - $log.error(e); + // if an Array or NodeList and not a Window + if (typeof length === 'number' && elements.window !== elements) { + if (length) { + for (var i = 0; i < length; i++) { + root[root.length++] = elements[i]; } } + } else { + root[root.length++] = elements; } } } +} - function getHash(url) { - var index = url.indexOf('#'); - return index === -1 ? '' : url.substr(index + 1); - } - /** - * @private - * Note: this method is used only by scenario runner - * TODO(vojta): prefix this method with $$ ? - * @param {function()} callback Function that will be called when no outstanding request - */ - self.notifyWhenNoOutstandingRequests = function(callback) { - // force browser to execute all pollFns - this is needed so that cookies and other pollers fire - // at some deterministic time in respect to the test runner's actions. Leaving things up to the - // regular poller would result in flaky tests. - forEach(pollFns, function(pollFn) { pollFn(); }); +function jqLiteController(element, name) { + return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller'); +} - if (outstandingRequestCount === 0) { - callback(); - } else { - outstandingRequestCallbacks.push(callback); - } - }; +function jqLiteInheritedData(element, name, value) { + // if element is the document object work with the html element instead + // this makes $(document).scope() possible + if (element.nodeType == NODE_TYPE_DOCUMENT) { + element = element.documentElement; + } + var names = isArray(name) ? name : [name]; - ////////////////////////////////////////////////////////////// - // Poll Watcher API - ////////////////////////////////////////////////////////////// - var pollFns = [], - pollTimeout; + while (element) { + for (var i = 0, ii = names.length; i < ii; i++) { + if ((value = jqLite.data(element, names[i])) !== undefined) return value; + } - /** - * @name $browser#addPollFn - * - * @param {function()} fn Poll function to add - * - * @description - * Adds a function to the list of functions that poller periodically executes, - * and starts polling if not started yet. - * - * @returns {function()} the added function - */ - self.addPollFn = function(fn) { - if (isUndefined(pollTimeout)) startPoller(100, setTimeout); - pollFns.push(fn); - return fn; - }; + // If dealing with a document fragment node with a host element, and no parent, use the host + // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM + // to lookup parent controllers. + element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host); + } +} - /** - * @param {number} interval How often should browser call poll functions (ms) - * @param {function()} setTimeout Reference to a real or fake `setTimeout` function. - * - * @description - * Configures the poller to run in the specified intervals, using the specified - * setTimeout fn and kicks it off. - */ - function startPoller(interval, setTimeout) { - (function check() { - forEach(pollFns, function(pollFn) { pollFn(); }); - pollTimeout = setTimeout(check, interval); - })(); +function jqLiteEmpty(element) { + jqLiteDealoc(element, true); + while (element.firstChild) { + element.removeChild(element.firstChild); } +} - ////////////////////////////////////////////////////////////// - // URL API - ////////////////////////////////////////////////////////////// +function jqLiteRemove(element, keepData) { + if (!keepData) jqLiteDealoc(element); + var parent = element.parentNode; + if (parent) parent.removeChild(element); +} - var cachedState, lastHistoryState, - lastBrowserUrl = location.href, - baseElement = document.find('base'), - reloadLocation = null; - cacheState(); - lastHistoryState = cachedState; +function jqLiteDocumentLoaded(action, win) { + win = win || window; + if (win.document.readyState === 'complete') { + // Force the action to be run async for consistent behaviour + // from the action's point of view + // i.e. it will definitely not be in a $apply + win.setTimeout(action); + } else { + // No need to unbind this handler as load is only ever called once + jqLite(win).on('load', action); + } +} - /** - * @name $browser#url - * - * @description - * GETTER: - * Without any argument, this method just returns current value of location.href. - * - * SETTER: - * With at least one argument, this method sets url to new value. - * If html5 history api supported, pushState/replaceState is used, otherwise - * location.href/location.replace is used. - * Returns its own instance to allow chaining - * - * NOTE: this api is intended for use only by the $location service. Please use the - * {@link ng.$location $location service} to change url. - * - * @param {string} url New url (when used as setter) - * @param {boolean=} replace Should new url replace current history record? - * @param {object=} state object to use with pushState/replaceState - */ - self.url = function(url, replace, state) { - // In modern browsers `history.state` is `null` by default; treating it separately - // from `undefined` would cause `$browser.url('/foo')` to change `history.state` - // to undefined via `pushState`. Instead, let's change `undefined` to `null` here. - if (isUndefined(state)) { - state = null; +////////////////////////////////////////// +// Functions which are declared directly. +////////////////////////////////////////// +var JQLitePrototype = JQLite.prototype = { + ready: function(fn) { + var fired = false; + + function trigger() { + if (fired) return; + fired = true; + fn(); } - // Android Browser BFCache causes location, history reference to become stale. - if (location !== window.location) location = window.location; - if (history !== window.history) history = window.history; + // check if document is already loaded + if (document.readyState === 'complete') { + setTimeout(trigger); + } else { + this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9 + // we can not use jqLite since we are not done loading and jQuery could be loaded later. + // jshint -W064 + JQLite(window).on('load', trigger); // fallback to window.onload for others + // jshint +W064 + } + }, + toString: function() { + var value = []; + forEach(this, function(e) { value.push('' + e);}); + return '[' + value.join(', ') + ']'; + }, - // setter - if (url) { - var sameState = lastHistoryState === state; + eq: function(index) { + return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); + }, - // Don't change anything if previous and current URLs and states match. This also prevents - // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode. - // See https://github.com/angular/angular.js/commit/ffb2701 - if (lastBrowserUrl === url && (!$sniffer.history || sameState)) { - return self; - } - var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url); - lastBrowserUrl = url; - lastHistoryState = state; - // Don't use history API if only the hash changed - // due to a bug in IE10/IE11 which leads - // to not firing a `hashchange` nor `popstate` event - // in some cases (see #9143). - if ($sniffer.history && (!sameBase || !sameState)) { - history[replace ? 'replaceState' : 'pushState'](state, '', url); - cacheState(); - // Do the assignment again so that those two variables are referentially identical. - lastHistoryState = cachedState; - } else { - if (!sameBase) { - reloadLocation = url; - } - if (replace) { - location.replace(url); - } else if (!sameBase) { - location.href = url; - } else { - location.hash = getHash(url); - } - } - return self; - // getter - } else { - // - reloadLocation is needed as browsers don't allow to read out - // the new location.href if a reload happened. - // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 - return reloadLocation || location.href.replace(/%27/g,"'"); - } - }; + length: 0, + push: push, + sort: [].sort, + splice: [].splice +}; - /** - * @name $browser#state - * - * @description - * This method is a getter. - * - * Return history.state or null if history.state is undefined. - * - * @returns {object} state - */ - self.state = function() { - return cachedState; - }; +////////////////////////////////////////// +// Functions iterating getter/setters. +// these functions return self on setter and +// value on get. +////////////////////////////////////////// +var BOOLEAN_ATTR = {}; +forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { + BOOLEAN_ATTR[lowercase(value)] = value; +}); +var BOOLEAN_ELEMENTS = {}; +forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { + BOOLEAN_ELEMENTS[value] = true; +}); +var ALIASED_ATTR = { + 'ngMinlength': 'minlength', + 'ngMaxlength': 'maxlength', + 'ngMin': 'min', + 'ngMax': 'max', + 'ngPattern': 'pattern' +}; - var urlChangeListeners = [], - urlChangeInit = false; +function getBooleanAttrName(element, name) { + // check dom last since we will most likely fail on name + var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; - function cacheStateAndFireUrlChange() { - cacheState(); - fireUrlChange(); - } + // booleanAttr is here twice to minimize DOM access + return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; +} - // This variable should be used *only* inside the cacheState function. - var lastCachedState = null; - function cacheState() { - // This should be the only place in $browser where `history.state` is read. - cachedState = window.history.state; - cachedState = isUndefined(cachedState) ? null : cachedState; +function getAliasedAttrName(element, name) { + var nodeName = element.nodeName; + return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name]; +} - // Prevent callbacks fo fire twice if both hashchange & popstate were fired. - if (equals(cachedState, lastCachedState)) { - cachedState = lastCachedState; - } - lastCachedState = cachedState; - } +forEach({ + data: jqLiteData, + removeData: jqLiteRemoveData, + hasData: jqLiteHasData +}, function(fn, name) { + JQLite[name] = fn; +}); - function fireUrlChange() { - if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) { - return; - } +forEach({ + data: jqLiteData, + inheritedData: jqLiteInheritedData, - lastBrowserUrl = self.url(); - lastHistoryState = cachedState; - forEach(urlChangeListeners, function(listener) { - listener(self.url(), cachedState); - }); - } + scope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']); + }, - /** - * @name $browser#onUrlChange - * - * @description - * Register callback function that will be called, when url changes. - * - * It's only called when the url is changed from outside of angular: - * - user types different url into address bar - * - user clicks on history (forward/back) button - * - user clicks on a link - * - * It's not called when url is changed by $browser.url() method - * - * The listener gets called with new url as parameter. - * - * NOTE: this api is intended for use only by the $location service. Please use the - * {@link ng.$location $location service} to monitor url changes in angular apps. - * - * @param {function(string)} listener Listener function to be called when url changes. - * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. - */ - self.onUrlChange = function(callback) { - // TODO(vojta): refactor to use node's syntax for events - if (!urlChangeInit) { - // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) - // don't fire popstate when user change the address bar and don't fire hashchange when url - // changed by push/replaceState + isolateScope: function(element) { + // Can't use jqLiteData here directly so we stay compatible with jQuery! + return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate'); + }, - // html5 history api - popstate event - if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange); - // hashchange event - jqLite(window).on('hashchange', cacheStateAndFireUrlChange); + controller: jqLiteController, - urlChangeInit = true; + injector: function(element) { + return jqLiteInheritedData(element, '$injector'); + }, + + removeAttr: function(element, name) { + element.removeAttribute(name); + }, + + hasClass: jqLiteHasClass, + + css: function(element, name, value) { + name = camelCase(name); + + if (isDefined(value)) { + element.style[name] = value; + } else { + return element.style[name]; } + }, - urlChangeListeners.push(callback); - return callback; - }; + attr: function(element, name, value) { + var nodeType = element.nodeType; + if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) { + return; + } + var lowercasedName = lowercase(name); + if (BOOLEAN_ATTR[lowercasedName]) { + if (isDefined(value)) { + if (!!value) { + element[name] = true; + element.setAttribute(name, lowercasedName); + } else { + element[name] = false; + element.removeAttribute(lowercasedName); + } + } else { + return (element[name] || + (element.attributes.getNamedItem(name) || noop).specified) + ? lowercasedName + : undefined; + } + } else if (isDefined(value)) { + element.setAttribute(name, value); + } else if (element.getAttribute) { + // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code + // some elements (e.g. Document) don't have get attribute, so return undefined + var ret = element.getAttribute(name, 2); + // normalize non-existing attributes to undefined (as jQuery) + return ret === null ? undefined : ret; + } + }, - /** - * Checks whether the url has changed outside of Angular. - * Needs to be exported to be able to check for changes that have been done in sync, - * as hashchange/popstate events fire in async. - */ - self.$$checkUrlChange = fireUrlChange; + prop: function(element, name, value) { + if (isDefined(value)) { + element[name] = value; + } else { + return element[name]; + } + }, - ////////////////////////////////////////////////////////////// - // Misc API - ////////////////////////////////////////////////////////////// + text: (function() { + getText.$dv = ''; + return getText; - /** - * @name $browser#baseHref - * - * @description - * Returns current <base href> - * (always relative - without domain) - * - * @returns {string} The current base href - */ - self.baseHref = function() { - var href = baseElement.attr('href'); - return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; - }; + function getText(element, value) { + if (isUndefined(value)) { + var nodeType = element.nodeType; + return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : ''; + } + element.textContent = value; + } + })(), - ////////////////////////////////////////////////////////////// - // Cookies API - ////////////////////////////////////////////////////////////// - var lastCookies = {}; - var lastCookieString = ''; - var cookiePath = self.baseHref(); + val: function(element, value) { + if (isUndefined(value)) { + if (element.multiple && nodeName_(element) === 'select') { + var result = []; + forEach(element.options, function(option) { + if (option.selected) { + result.push(option.value || option.text); + } + }); + return result.length === 0 ? null : result; + } + return element.value; + } + element.value = value; + }, - function safeDecodeURIComponent(str) { - try { - return decodeURIComponent(str); - } catch (e) { - return str; + html: function(element, value) { + if (isUndefined(value)) { + return element.innerHTML; } - } + jqLiteDealoc(element, true); + element.innerHTML = value; + }, + empty: jqLiteEmpty +}, function(fn, name) { /** - * @name $browser#cookies - * - * @param {string=} name Cookie name - * @param {string=} value Cookie value - * - * @description - * The cookies method provides a 'private' low level access to browser cookies. - * It is not meant to be used directly, use the $cookie service instead. - * - * The return values vary depending on the arguments that the method was called with as follows: - * - * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify - * it - * - cookies(name, value) -> set name to value, if value is undefined delete the cookie - * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that - * way) - * - * @returns {Object} Hash of all cookies (if called without any parameter) + * Properties: writes return selection, reads return first value */ - self.cookies = function(name, value) { - var cookieLength, cookieArray, cookie, i, index; + JQLite.prototype[name] = function(arg1, arg2) { + var i, key; + var nodeCount = this.length; - if (name) { - if (value === undefined) { - rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath + - ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; - } else { - if (isString(value)) { - cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + - ';path=' + cookiePath).length + 1; + // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it + // in a way that survives minification. + // jqLiteEmpty takes no arguments but is a setter. + if (fn !== jqLiteEmpty && + (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) { + if (isObject(arg1)) { - // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: - // - 300 cookies - // - 20 cookies per unique domain - // - 4096 bytes per cookie - if (cookieLength > 4096) { - $log.warn("Cookie '" + name + - "' possibly not set or overflowed because it was too large (" + - cookieLength + " > 4096 bytes)!"); + // we are a write, but the object properties are the key/values + for (i = 0; i < nodeCount; i++) { + if (fn === jqLiteData) { + // data() takes the whole object in jQuery + fn(this[i], arg1); + } else { + for (key in arg1) { + fn(this[i], key, arg1[key]); + } } } + // return self for chaining + return this; + } else { + // we are a read, so read the first child. + // TODO: do we still need this? + var value = fn.$dv; + // Only if we have $dv do we iterate over all, otherwise it is just the first element. + var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount; + for (var j = 0; j < jj; j++) { + var nodeValue = fn(this[j], arg1, arg2); + value = value ? value + nodeValue : nodeValue; + } + return value; } } else { - if (rawDocument.cookie !== lastCookieString) { - lastCookieString = rawDocument.cookie; - cookieArray = lastCookieString.split("; "); - lastCookies = {}; - - for (i = 0; i < cookieArray.length; i++) { - cookie = cookieArray[i]; - index = cookie.indexOf('='); - if (index > 0) { //ignore nameless cookies - name = safeDecodeURIComponent(cookie.substring(0, index)); - // the first value that is seen for a cookie is the most - // specific one. values for the same cookie name that - // follow are for less specific paths. - if (lastCookies[name] === undefined) { - lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); - } - } - } + // we are a write, so apply to all children + for (i = 0; i < nodeCount; i++) { + fn(this[i], arg1, arg2); } - return lastCookies; + // return self for chaining + return this; } }; +}); +function createEventHandler(element, events) { + var eventHandler = function(event, type) { + // jQuery specific api + event.isDefaultPrevented = function() { + return event.defaultPrevented; + }; - /** - * @name $browser#defer - * @param {function()} fn A function, who's execution should be deferred. - * @param {number=} [delay=0] of milliseconds to defer the function execution. - * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. - * - * @description - * Executes a fn asynchronously via `setTimeout(fn, delay)`. - * - * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using - * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed - * via `$browser.defer.flush()`. - * - */ - self.defer = function(fn, delay) { - var timeoutId; - outstandingRequestCount++; - timeoutId = setTimeout(function() { - delete pendingDeferIds[timeoutId]; - completeOutstandingRequest(fn); - }, delay || 0); - pendingDeferIds[timeoutId] = true; - return timeoutId; - }; + var eventFns = events[type || event.type]; + var eventFnsLength = eventFns ? eventFns.length : 0; + if (!eventFnsLength) return; - /** - * @name $browser#defer.cancel - * - * @description - * Cancels a deferred task identified with `deferId`. - * - * @param {*} deferId Token returned by the `$browser.defer` function. - * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully - * canceled. - */ - self.defer.cancel = function(deferId) { - if (pendingDeferIds[deferId]) { - delete pendingDeferIds[deferId]; - clearTimeout(deferId); - completeOutstandingRequest(noop); - return true; + if (isUndefined(event.immediatePropagationStopped)) { + var originalStopImmediatePropagation = event.stopImmediatePropagation; + event.stopImmediatePropagation = function() { + event.immediatePropagationStopped = true; + + if (event.stopPropagation) { + event.stopPropagation(); + } + + if (originalStopImmediatePropagation) { + originalStopImmediatePropagation.call(event); + } + }; + } + + event.isImmediatePropagationStopped = function() { + return event.immediatePropagationStopped === true; + }; + + // Copy event handlers in case event handlers array is modified during execution. + if ((eventFnsLength > 1)) { + eventFns = shallowCopy(eventFns); + } + + for (var i = 0; i < eventFnsLength; i++) { + if (!event.isImmediatePropagationStopped()) { + eventFns[i].call(element, event); + } } - return false; }; + // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all + // events on `element` + eventHandler.elem = element; + return eventHandler; } -function $BrowserProvider() { - this.$get = ['$window', '$log', '$sniffer', '$document', - function($window, $log, $sniffer, $document) { - return new Browser($window, $document, $log, $sniffer); - }]; -} +////////////////////////////////////////// +// Functions iterating traversal. +// These functions chain results into a single +// selector. +////////////////////////////////////////// +forEach({ + removeData: jqLiteRemoveData, -/** - * @ngdoc service - * @name $cacheFactory - * - * @description - * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to - * them. - * - * ```js - * - * var cache = $cacheFactory('cacheId'); - * expect($cacheFactory.get('cacheId')).toBe(cache); - * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined(); - * - * cache.put("key", "value"); - * cache.put("another key", "another value"); - * - * // We've specified no options on creation - * expect(cache.info()).toEqual({id: 'cacheId', size: 2}); - * - * ``` - * - * - * @param {string} cacheId Name or id of the newly created cache. - * @param {object=} options Options object that specifies the cache behavior. Properties: - * - * - `{number=}` `capacity` — turns the cache into LRU cache. - * - * @returns {object} Newly created cache object with the following set of methods: - * - * - `{object}` `info()` — Returns id, size, and options of cache. - * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns - * it. - * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. - * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. - * - `{void}` `removeAll()` — Removes all cached values. - * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. - * - * @example - <example module="cacheExampleApp"> - <file name="index.html"> - <div ng-controller="CacheController"> - <input ng-model="newCacheKey" placeholder="Key"> - <input ng-model="newCacheValue" placeholder="Value"> - <button ng-click="put(newCacheKey, newCacheValue)">Cache</button> + on: function jqLiteOn(element, type, fn, unsupported) { + if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters'); - <p ng-if="keys.length">Cached Values</p> - <div ng-repeat="key in keys"> - <span ng-bind="key"></span> - <span>: </span> - <b ng-bind="cache.get(key)"></b> - </div> + // Do not add event handlers to non-elements because they will not be cleaned up. + if (!jqLiteAcceptsData(element)) { + return; + } - <p>Cache Info</p> - <div ng-repeat="(key, value) in cache.info()"> - <span ng-bind="key"></span> - <span>: </span> - <b ng-bind="value"></b> - </div> - </div> - </file> - <file name="script.js"> - angular.module('cacheExampleApp', []). - controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) { - $scope.keys = []; - $scope.cache = $cacheFactory('cacheId'); - $scope.put = function(key, value) { - if ($scope.cache.get(key) === undefined) { - $scope.keys.push(key); - } - $scope.cache.put(key, value === undefined ? null : value); - }; - }]); - </file> - <file name="style.css"> - p { - margin: 10px 0 3px; - } - </file> - </example> - */ -function $CacheFactoryProvider() { + var expandoStore = jqLiteExpandoStore(element, true); + var events = expandoStore.events; + var handle = expandoStore.handle; - this.$get = function() { - var caches = {}; + if (!handle) { + handle = expandoStore.handle = createEventHandler(element, events); + } - function cacheFactory(cacheId, options) { - if (cacheId in caches) { - throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId); - } - - var size = 0, - stats = extend({}, options, {id: cacheId}), - data = {}, - capacity = (options && options.capacity) || Number.MAX_VALUE, - lruHash = {}, - freshEnd = null, - staleEnd = null; + // http://jsperf.com/string-indexof-vs-split + var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type]; + var i = types.length; - /** - * @ngdoc type - * @name $cacheFactory.Cache - * - * @description - * A cache object used to store and retrieve data, primarily used by - * {@link $http $http} and the {@link ng.directive:script script} directive to cache - * templates and other data. - * - * ```js - * angular.module('superCache') - * .factory('superCache', ['$cacheFactory', function($cacheFactory) { - * return $cacheFactory('super-cache'); - * }]); - * ``` - * - * Example test: - * - * ```js - * it('should behave like a cache', inject(function(superCache) { - * superCache.put('key', 'value'); - * superCache.put('another key', 'another value'); - * - * expect(superCache.info()).toEqual({ - * id: 'super-cache', - * size: 2 - * }); - * - * superCache.remove('another key'); - * expect(superCache.get('another key')).toBeUndefined(); - * - * superCache.removeAll(); - * expect(superCache.info()).toEqual({ - * id: 'super-cache', - * size: 0 - * }); - * })); - * ``` - */ - return caches[cacheId] = { + while (i--) { + type = types[i]; + var eventFns = events[type]; - /** - * @ngdoc method - * @name $cacheFactory.Cache#put - * @kind function - * - * @description - * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be - * retrieved later, and incrementing the size of the cache if the key was not already - * present in the cache. If behaving like an LRU cache, it will also remove stale - * entries from the set. - * - * It will not insert undefined values into the cache. - * - * @param {string} key the key under which the cached data is stored. - * @param {*} value the value to store alongside the key. If it is undefined, the key - * will not be stored. - * @returns {*} the value stored. - */ - put: function(key, value) { - if (capacity < Number.MAX_VALUE) { - var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); + if (!eventFns) { + events[type] = []; - refresh(lruEntry); - } + if (type === 'mouseenter' || type === 'mouseleave') { + // Refer to jQuery's implementation of mouseenter & mouseleave + // Read about mouseenter and mouseleave: + // http://www.quirksmode.org/js/events_mouse.html#link8 - if (isUndefined(value)) return; - if (!(key in data)) size++; - data[key] = value; + jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) { + var target = this, related = event.relatedTarget; + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if (!related || (related !== target && !target.contains(related))) { + handle(event, type); + } + }); - if (size > capacity) { - this.remove(staleEnd.key); + } else { + if (type !== '$destroy') { + addEventListenerFn(element, type, handle); } + } + eventFns = events[type]; + } + eventFns.push(fn); + } + }, - return value; - }, + off: jqLiteOff, - /** - * @ngdoc method - * @name $cacheFactory.Cache#get - * @kind function - * - * @description - * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object. - * - * @param {string} key the key of the data to be retrieved - * @returns {*} the value stored. - */ - get: function(key) { - if (capacity < Number.MAX_VALUE) { - var lruEntry = lruHash[key]; + one: function(element, type, fn) { + element = jqLite(element); - if (!lruEntry) return; + //add the listener twice so that when it is called + //you can remove the original function and still be + //able to call element.off(ev, fn) normally + element.on(type, function onFn() { + element.off(type, fn); + element.off(type, onFn); + }); + element.on(type, fn); + }, - refresh(lruEntry); - } + replaceWith: function(element, replaceNode) { + var index, parent = element.parentNode; + jqLiteDealoc(element); + forEach(new JQLite(replaceNode), function(node) { + if (index) { + parent.insertBefore(node, index.nextSibling); + } else { + parent.replaceChild(node, element); + } + index = node; + }); + }, - return data[key]; - }, + children: function(element) { + var children = []; + forEach(element.childNodes, function(element) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + children.push(element); + } + }); + return children; + }, + contents: function(element) { + return element.contentDocument || element.childNodes || []; + }, - /** - * @ngdoc method - * @name $cacheFactory.Cache#remove - * @kind function - * - * @description - * Removes an entry from the {@link $cacheFactory.Cache Cache} object. - * - * @param {string} key the key of the entry to be removed - */ - remove: function(key) { - if (capacity < Number.MAX_VALUE) { - var lruEntry = lruHash[key]; + append: function(element, node) { + var nodeType = element.nodeType; + if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return; - if (!lruEntry) return; + node = new JQLite(node); - if (lruEntry == freshEnd) freshEnd = lruEntry.p; - if (lruEntry == staleEnd) staleEnd = lruEntry.n; - link(lruEntry.n,lruEntry.p); + for (var i = 0, ii = node.length; i < ii; i++) { + var child = node[i]; + element.appendChild(child); + } + }, - delete lruHash[key]; - } + prepend: function(element, node) { + if (element.nodeType === NODE_TYPE_ELEMENT) { + var index = element.firstChild; + forEach(new JQLite(node), function(child) { + element.insertBefore(child, index); + }); + } + }, - delete data[key]; - size--; - }, + wrap: function(element, wrapNode) { + wrapNode = jqLite(wrapNode).eq(0).clone()[0]; + var parent = element.parentNode; + if (parent) { + parent.replaceChild(wrapNode, element); + } + wrapNode.appendChild(element); + }, + remove: jqLiteRemove, - /** - * @ngdoc method - * @name $cacheFactory.Cache#removeAll - * @kind function - * - * @description - * Clears the cache object of any entries. - */ - removeAll: function() { - data = {}; - size = 0; - lruHash = {}; - freshEnd = staleEnd = null; - }, + detach: function(element) { + jqLiteRemove(element, true); + }, + after: function(element, newElement) { + var index = element, parent = element.parentNode; + newElement = new JQLite(newElement); - /** - * @ngdoc method - * @name $cacheFactory.Cache#destroy - * @kind function - * - * @description - * Destroys the {@link $cacheFactory.Cache Cache} object entirely, - * removing it from the {@link $cacheFactory $cacheFactory} set. - */ - destroy: function() { - data = null; - stats = null; - lruHash = null; - delete caches[cacheId]; - }, + for (var i = 0, ii = newElement.length; i < ii; i++) { + var node = newElement[i]; + parent.insertBefore(node, index.nextSibling); + index = node; + } + }, + addClass: jqLiteAddClass, + removeClass: jqLiteRemoveClass, - /** - * @ngdoc method - * @name $cacheFactory.Cache#info - * @kind function - * - * @description - * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}. - * - * @returns {object} an object with the following properties: - * <ul> - * <li>**id**: the id of the cache instance</li> - * <li>**size**: the number of entries kept in the cache instance</li> - * <li>**...**: any additional properties from the options object when creating the - * cache.</li> - * </ul> - */ - info: function() { - return extend({}, stats, {size: size}); + toggleClass: function(element, selector, condition) { + if (selector) { + forEach(selector.split(' '), function(className) { + var classCondition = condition; + if (isUndefined(classCondition)) { + classCondition = !jqLiteHasClass(element, className); } + (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className); + }); + } + }, + + parent: function(element) { + var parent = element.parentNode; + return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null; + }, + + next: function(element) { + return element.nextElementSibling; + }, + + find: function(element, selector) { + if (element.getElementsByTagName) { + return element.getElementsByTagName(selector); + } else { + return []; + } + }, + + clone: jqLiteClone, + + triggerHandler: function(element, event, extraParameters) { + + var dummyEvent, eventFnsCopy, handlerArgs; + var eventName = event.type || event; + var expandoStore = jqLiteExpandoStore(element); + var events = expandoStore && expandoStore.events; + var eventFns = events && events[eventName]; + + if (eventFns) { + // Create a dummy event to pass to the handlers + dummyEvent = { + preventDefault: function() { this.defaultPrevented = true; }, + isDefaultPrevented: function() { return this.defaultPrevented === true; }, + stopImmediatePropagation: function() { this.immediatePropagationStopped = true; }, + isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; }, + stopPropagation: noop, + type: eventName, + target: element }; + // If a custom event was provided then extend our dummy event with it + if (event.type) { + dummyEvent = extend(dummyEvent, event); + } - /** - * makes the `entry` the freshEnd of the LRU linked list - */ - function refresh(entry) { - if (entry != freshEnd) { - if (!staleEnd) { - staleEnd = entry; - } else if (staleEnd == entry) { - staleEnd = entry.n; - } + // Copy event handlers in case event handlers array is modified during execution. + eventFnsCopy = shallowCopy(eventFns); + handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent]; - link(entry.n, entry.p); - link(entry, freshEnd); - freshEnd = entry; - freshEnd.n = null; + forEach(eventFnsCopy, function(fn) { + if (!dummyEvent.isImmediatePropagationStopped()) { + fn.apply(element, handlerArgs); + } + }); + } + } +}, function(fn, name) { + /** + * chaining functions + */ + JQLite.prototype[name] = function(arg1, arg2, arg3) { + var value; + + for (var i = 0, ii = this.length; i < ii; i++) { + if (isUndefined(value)) { + value = fn(this[i], arg1, arg2, arg3); + if (isDefined(value)) { + // any function which returns a value needs to be wrapped + value = jqLite(value); } + } else { + jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3)); } + } + return isDefined(value) ? value : this; + }; + + // bind legacy bind/unbind to on/off + JQLite.prototype.bind = JQLite.prototype.on; + JQLite.prototype.unbind = JQLite.prototype.off; +}); - /** - * bidirectionally links two entries of the LRU linked list - */ - function link(nextEntry, prevEntry) { - if (nextEntry != prevEntry) { - if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify - if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify - } +// Provider for private $$jqLite service +function $$jqLiteProvider() { + this.$get = function $$jqLite() { + return extend(JQLite, { + hasClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteHasClass(node, classes); + }, + addClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteAddClass(node, classes); + }, + removeClass: function(node, classes) { + if (node.attr) node = node[0]; + return jqLiteRemoveClass(node, classes); } + }); + }; +} + +/** + * Computes a hash of an 'obj'. + * Hash of a: + * string is string + * number is number as string + * object is either result of calling $$hashKey function on the object or uniquely generated id, + * that is also assigned to the $$hashKey property of the object. + * + * @param obj + * @returns {string} hash string such that the same input will have the same hash string. + * The resulting string key is in 'type:hashKey' format. + */ +function hashKey(obj, nextUidFn) { + var key = obj && obj.$$hashKey; + + if (key) { + if (typeof key === 'function') { + key = obj.$$hashKey(); } + return key; + } + + var objType = typeof obj; + if (objType == 'function' || (objType == 'object' && obj !== null)) { + key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)(); + } else { + key = objType + ':' + obj; + } + return key; +} +/** + * HashMap which can use objects as keys + */ +function HashMap(array, isolatedUid) { + if (isolatedUid) { + var uid = 0; + this.nextUid = function() { + return ++uid; + }; + } + forEach(array, this.put, this); +} +HashMap.prototype = { /** - * @ngdoc method - * @name $cacheFactory#info - * - * @description - * Get information about all the caches that have been created - * - * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info` + * Store key value pair + * @param key key to store can be any type + * @param value value to store can be any type */ - cacheFactory.info = function() { - var info = {}; - forEach(caches, function(cache, cacheId) { - info[cacheId] = cache.info(); - }); - return info; - }; - + put: function(key, value) { + this[hashKey(key, this.nextUid)] = value; + }, /** - * @ngdoc method - * @name $cacheFactory#get - * - * @description - * Get access to a cache object by the `cacheId` used when it was created. - * - * @param {string} cacheId Name or id of a cache to access. - * @returns {object} Cache object identified by the cacheId or undefined if no such cache. + * @param key + * @returns {Object} the value for the key */ - cacheFactory.get = function(cacheId) { - return caches[cacheId]; - }; + get: function(key) { + return this[hashKey(key, this.nextUid)]; + }, + /** + * Remove the key/value pair + * @param key + */ + remove: function(key) { + var value = this[key = hashKey(key, this.nextUid)]; + delete this[key]; + return value; + } +}; - return cacheFactory; - }; -} +var $$HashMapProvider = [function() { + this.$get = [function() { + return HashMap; + }]; +}]; /** - * @ngdoc service - * @name $templateCache + * @ngdoc function + * @module ng + * @name angular.injector + * @kind function * * @description - * The first time a template is used, it is loaded in the template cache for quick retrieval. You - * can load templates directly into the cache in a `script` tag, or by consuming the - * `$templateCache` service directly. + * Creates an injector object that can be used for retrieving services as well as for + * dependency injection (see {@link guide/di dependency injection}). * - * Adding via the `script` tag: + * @param {Array.<string|Function>} modules A list of module functions or their aliases. See + * {@link angular.module}. The `ng` module must be explicitly added. + * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which + * disallows argument name annotation inference. + * @returns {injector} Injector object. See {@link auto.$injector $injector}. * - * ```html - * <script type="text/ng-template" id="templateId.html"> - * <p>This is the content of the template</p> - * </script> - * ``` + * @example + * Typical usage + * ```js + * // create an injector + * var $injector = angular.injector(['ng']); * - * **Note:** the `script` tag containing the template does not need to be included in the `head` of - * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, - * element with ng-app attribute), otherwise the template will be ignored. + * // use the injector to kick off your application + * // use the type inference to auto inject arguments, or use implicit injection + * $injector.invoke(function($rootScope, $compile, $document) { + * $compile($document)($rootScope); + * $rootScope.$digest(); + * }); + * ``` * - * Adding via the $templateCache service: + * Sometimes you want to get access to the injector of a currently running Angular app + * from outside Angular. Perhaps, you want to inject and compile some markup after the + * application has been bootstrapped. You can do this using the extra `injector()` added + * to JQuery/jqLite elements. See {@link angular.element}. * - * ```js - * var myApp = angular.module('myApp', []); - * myApp.run(function($templateCache) { - * $templateCache.put('templateId.html', 'This is the content of the template'); - * }); - * ``` + * *This is fairly rare but could be the case if a third party library is injecting the + * markup.* * - * To retrieve the template later, simply use it in your HTML: - * ```html - * <div ng-include=" 'templateId.html' "></div> - * ``` + * In the following example a new block of HTML containing a `ng-controller` + * directive is added to the end of the document body by JQuery. We then compile and link + * it into the current AngularJS scope. * - * or get it via Javascript: * ```js - * $templateCache.get('templateId.html') - * ``` - * - * See {@link ng.$cacheFactory $cacheFactory}. + * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>'); + * $(document.body).append($div); * + * angular.element(document).injector().invoke(function($compile) { + * var scope = angular.element($div).scope(); + * $compile($div)(scope); + * }); + * ``` */ -function $TemplateCacheProvider() { - this.$get = ['$cacheFactory', function($cacheFactory) { - return $cacheFactory('templates'); - }]; -} -/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! - * - * DOM-related variables: - * - * - "node" - DOM Node - * - "element" - DOM Element or Node - * - "$node" or "$element" - jqLite-wrapped node or element - * - * - * Compiler related stuff: + +/** + * @ngdoc module + * @name auto + * @description * - * - "linkFn" - linking fn of a single directive - * - "nodeLinkFn" - function that aggregates all linking fns for a particular node - * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node - * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) + * Implicit module which gets automatically added to each {@link auto.$injector $injector}. */ +var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; +var FN_ARG_SPLIT = /,/; +var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; +var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; +var $injectorMinErr = minErr('$injector'); + +function anonFn(fn) { + // For anonymous functions, showing at the very least the function signature can help in + // debugging. + var fnText = fn.toString().replace(STRIP_COMMENTS, ''), + args = fnText.match(FN_ARGS); + if (args) { + return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')'; + } + return 'fn'; +} + +function annotate(fn, strictDi, name) { + var $inject, + fnText, + argDecl, + last; + + if (typeof fn === 'function') { + if (!($inject = fn.$inject)) { + $inject = []; + if (fn.length) { + if (strictDi) { + if (!isString(name) || !name) { + name = fn.name || anonFn(fn); + } + throw $injectorMinErr('strictdi', + '{0} is not using explicit annotation and cannot be invoked in strict mode', name); + } + fnText = fn.toString().replace(STRIP_COMMENTS, ''); + argDecl = fnText.match(FN_ARGS); + forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { + arg.replace(FN_ARG, function(all, underscore, name) { + $inject.push(name); + }); + }); + } + fn.$inject = $inject; + } + } else if (isArray(fn)) { + last = fn.length - 1; + assertArgFn(fn[last], 'fn'); + $inject = fn.slice(0, last); + } else { + assertArgFn(fn, 'fn', true); + } + return $inject; +} + +/////////////////////////////////////// /** * @ngdoc service - * @name $compile - * @kind function + * @name $injector * * @description - * Compiles an HTML string or DOM into a template and produces a template function, which - * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together. - * - * The compilation is a process of walking the DOM tree and matching DOM elements to - * {@link ng.$compileProvider#directive directives}. - * - * <div class="alert alert-warning"> - * **Note:** This document is an in-depth reference of all directive options. - * For a gentle introduction to directives with examples of common use cases, - * see the {@link guide/directive directive guide}. - * </div> - * - * ## Comprehensive Directive API - * - * There are many different options for a directive. - * - * The difference resides in the return value of the factory function. - * You can either return a "Directive Definition Object" (see below) that defines the directive properties, - * or just the `postLink` function (all other properties will have the default values). * - * <div class="alert alert-success"> - * **Best Practice:** It's recommended to use the "directive definition object" form. - * </div> + * `$injector` is used to retrieve object instances as defined by + * {@link auto.$provide provider}, instantiate types, invoke methods, + * and load modules. * - * Here's an example directive declared with a Directive Definition Object: + * The following always holds true: * * ```js - * var myModule = angular.module(...); - * - * myModule.directive('directiveName', function factory(injectables) { - * var directiveDefinitionObject = { - * priority: 0, - * template: '<div></div>', // or // function(tElement, tAttrs) { ... }, - * // or - * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, - * transclude: false, - * restrict: 'A', - * templateNamespace: 'html', - * scope: false, - * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, - * controllerAs: 'stringAlias', - * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], - * compile: function compile(tElement, tAttrs, transclude) { - * return { - * pre: function preLink(scope, iElement, iAttrs, controller) { ... }, - * post: function postLink(scope, iElement, iAttrs, controller) { ... } - * } - * // or - * // return function postLink( ... ) { ... } - * }, - * // or - * // link: { - * // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, - * // post: function postLink(scope, iElement, iAttrs, controller) { ... } - * // } - * // or - * // link: function postLink( ... ) { ... } - * }; - * return directiveDefinitionObject; - * }); + * var $injector = angular.injector(); + * expect($injector.get('$injector')).toBe($injector); + * expect($injector.invoke(function($injector) { + * return $injector; + * })).toBe($injector); * ``` * - * <div class="alert alert-warning"> - * **Note:** Any unspecified options will use the default value. You can see the default values below. - * </div> + * # Injection Function Annotation * - * Therefore the above can be simplified as: + * JavaScript does not have annotations, and annotations are needed for dependency injection. The + * following are all valid ways of annotating function with injection arguments and are equivalent. * * ```js - * var myModule = angular.module(...); + * // inferred (only works if code not minified/obfuscated) + * $injector.invoke(function(serviceA){}); * - * myModule.directive('directiveName', function factory(injectables) { - * var directiveDefinitionObject = { - * link: function postLink(scope, iElement, iAttrs) { ... } - * }; - * return directiveDefinitionObject; - * // or - * // return function postLink(scope, iElement, iAttrs) { ... } - * }); + * // annotated + * function explicit(serviceA) {}; + * explicit.$inject = ['serviceA']; + * $injector.invoke(explicit); + * + * // inline + * $injector.invoke(['serviceA', function(serviceA){}]); * ``` * + * ## Inference * + * In JavaScript calling `toString()` on a function returns the function definition. The definition + * can then be parsed and the function arguments can be extracted. This method of discovering + * annotations is disallowed when the injector is in strict mode. + * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the + * argument names. * - * ### Directive Definition Object + * ## `$inject` Annotation + * By adding an `$inject` property onto a function the injection parameters can be specified. * - * The directive definition object provides instructions to the {@link ng.$compile - * compiler}. The attributes are: + * ## Inline + * As an array of injection names, where the last item in the array is the function to call. + */ + +/** + * @ngdoc method + * @name $injector#get * - * #### `multiElement` - * When this property is set to true, the HTML compiler will collect DOM nodes between - * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them - * together as the directive elements. It is recommended that this feature be used on directives - * which are not strictly behavioural (such as {@link ngClick}), and which - * do not manipulate or replace child nodes (such as {@link ngInclude}). + * @description + * Return an instance of the service. * - * #### `priority` - * When there are multiple directives defined on a single DOM element, sometimes it - * is necessary to specify the order in which the directives are applied. The `priority` is used - * to sort the directives before their `compile` functions get called. Priority is defined as a - * number. Directives with greater numerical `priority` are compiled first. Pre-link functions - * are also run in priority order, but post-link functions are run in reverse order. The order - * of directives with the same priority is undefined. The default priority is `0`. + * @param {string} name The name of the instance to retrieve. + * @param {string=} caller An optional string to provide the origin of the function call for error messages. + * @return {*} The instance. + */ + +/** + * @ngdoc method + * @name $injector#invoke * - * #### `terminal` - * If set to true then the current `priority` will be the last set of directives - * which will execute (any directives at the current priority will still execute - * as the order of execution on same `priority` is undefined). Note that expressions - * and other directives used in the directive's template will also be excluded from execution. + * @description + * Invoke the method and supply the method arguments from the `$injector`. * - * #### `scope` - * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the - * same element request a new scope, only one new scope is created. The new scope rule does not - * apply for the root of the template since the root of the template always gets a new scope. + * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are + * injected according to the {@link guide/di $inject Annotation} rules. + * @param {Object=} self The `this` for the invoked method. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {*} the value returned by the invoked `fn` function. + */ + +/** + * @ngdoc method + * @name $injector#has * - * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from - * normal scope in that it does not prototypically inherit from the parent scope. This is useful - * when creating reusable components, which should not accidentally read or modify data in the - * parent scope. + * @description + * Allows the user to query if the particular service exists. * - * The 'isolate' scope takes an object hash which defines a set of local scope properties - * derived from the parent scope. These local properties are useful for aliasing values for - * templates. Locals definition is a hash of local scope property to its source: + * @param {string} name Name of the service to query. + * @returns {boolean} `true` if injector has given service. + */ + +/** + * @ngdoc method + * @name $injector#instantiate + * @description + * Create a new instance of JS type. The method takes a constructor function, invokes the new + * operator, and supplies all of the arguments to the constructor function as specified by the + * constructor annotation. * - * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is - * always a string since DOM attributes are strings. If no `attr` name is specified then the - * attribute name is assumed to be the same as the local name. - * Given `<widget my-attr="hello {{name}}">` and widget definition - * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect - * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the - * `localName` property on the widget scope. The `name` is read from the parent scope (not - * component scope). + * @param {Function} Type Annotated constructor function. + * @param {Object=} locals Optional object. If preset then any argument names are read from this + * object first, before the `$injector` is consulted. + * @returns {Object} new instance of `Type`. + */ + +/** + * @ngdoc method + * @name $injector#annotate * - * * `=` or `=attr` - set up bi-directional binding between a local scope property and the - * parent scope property of name defined via the value of the `attr` attribute. If no `attr` - * name is specified then the attribute name is assumed to be the same as the local name. - * Given `<widget my-attr="parentModel">` and widget definition of - * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the - * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected - * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent - * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You - * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If - * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use - * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional). + * @description + * Returns an array of service names which the function is requesting for injection. This API is + * used by the injector to determine which services need to be injected into the function when the + * function is invoked. There are three ways in which the function can be annotated with the needed + * dependencies. * - * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. - * If no `attr` name is specified then the attribute name is assumed to be the same as the - * local name. Given `<widget my-attr="count = count + value">` and widget definition of - * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to - * a function wrapper for the `count = count + value` expression. Often it's desirable to - * pass data from the isolated scope via an expression to the parent scope, this can be - * done by passing a map of local variable names and values into the expression wrapper fn. - * For example, if the expression is `increment(amount)` then we can specify the amount value - * by calling the `localFn` as `localFn({amount: 22})`. + * # Argument names * + * The simplest form is to extract the dependencies from the arguments of the function. This is done + * by converting the function into a string using `toString()` method and extracting the argument + * names. + * ```js + * // Given + * function MyController($scope, $route) { + * // ... + * } * - * #### `bindToController` - * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will - * allow a component to have its properties bound to the controller, rather than to scope. When the controller - * is instantiated, the initial values of the isolate scope bindings are already available. + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` * - * #### `controller` - * Controller constructor function. The controller is instantiated before the - * pre-linking phase and it is shared with other directives (see - * `require` attribute). This allows the directives to communicate with each other and augment - * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals: + * You can disallow this method by using strict injection mode. * - * * `$scope` - Current scope associated with the element - * * `$element` - Current element - * * `$attrs` - Current attributes object for the element - * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope: - * `function([scope], cloneLinkingFn, futureParentElement)`. - * * `scope`: optional argument to override the scope. - * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content. - * * `futureParentElement`: - * * defines the parent to which the `cloneLinkingFn` will add the cloned elements. - * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`. - * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) - * and when the `cloneLinkinFn` is passed, - * as those elements need to created and cloned in a special way when they are defined outside their - * usual containers (e.g. like `<svg>`). - * * See also the `directive.templateNamespace` property. + * This method does not work with code minification / obfuscation. For this reason the following + * annotation strategies are supported. * + * # The `$inject` property * - * #### `require` - * Require another directive and inject its controller as the fourth argument to the linking function. The - * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the - * injected argument will be an array in corresponding order. If no such directive can be - * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with: + * If a function has an `$inject` property and its value is an array of strings, then the strings + * represent names of services to be injected into the function. + * ```js + * // Given + * var MyController = function(obfuscatedScope, obfuscatedRoute) { + * // ... + * } + * // Define function dependencies + * MyController['$inject'] = ['$scope', '$route']; * - * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. - * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. - * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found. - * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found. - * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass - * `null` to the `link` fn if not found. - * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass - * `null` to the `link` fn if not found. + * // Then + * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']); + * ``` * + * # The array notation * - * #### `controllerAs` - * Controller alias at the directive scope. An alias for the controller so it - * can be referenced at the directive template. The directive needs to define a scope for this - * configuration to be used. Useful in the case when directive is used as component. + * It is often desirable to inline Injected functions and that's when setting the `$inject` property + * is very inconvenient. In these situations using the array notation to specify the dependencies in + * a way that survives minification is a better choice: * + * ```js + * // We wish to write this (not minification / obfuscation safe) + * injector.invoke(function($compile, $rootScope) { + * // ... + * }); * - * #### `restrict` - * String of subset of `EACM` which restricts the directive to a specific directive - * declaration style. If omitted, the defaults (elements and attributes) are used. + * // We are forced to write break inlining + * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) { + * // ... + * }; + * tmpFn.$inject = ['$compile', '$rootScope']; + * injector.invoke(tmpFn); * - * * `E` - Element name (default): `<my-directive></my-directive>` - * * `A` - Attribute (default): `<div my-directive="exp"></div>` - * * `C` - Class: `<div class="my-directive: exp;"></div>` - * * `M` - Comment: `<!-- directive: my-directive exp -->` + * // To better support inline function the inline annotation is supported + * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) { + * // ... + * }]); * + * // Therefore + * expect(injector.annotate( + * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}]) + * ).toEqual(['$compile', '$rootScope']); + * ``` * - * #### `templateNamespace` - * String representing the document type used by the markup in the template. - * AngularJS needs this information as those elements need to be created and cloned - * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`. + * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to + * be retrieved as described above. * - * * `html` - All root nodes in the template are HTML. Root nodes may also be - * top-level elements such as `<svg>` or `<math>`. - * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`). - * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`). + * @param {boolean=} [strictDi=false] Disallow argument name annotation inference. * - * If no `templateNamespace` is specified, then the namespace is considered to be `html`. + * @returns {Array.<string>} The names of the services which the function requires. + */ + + + + +/** + * @ngdoc service + * @name $provide * - * #### `template` - * HTML markup that may: - * * Replace the contents of the directive's element (default). - * * Replace the directive's element itself (if `replace` is true - DEPRECATED). - * * Wrap the contents of the directive's element (if `transclude` is true). + * @description * - * Value may be: + * The {@link auto.$provide $provide} service has a number of methods for registering components + * with the {@link auto.$injector $injector}. Many of these functions are also exposed on + * {@link angular.Module}. * - * * A string. For example `<div red-on-hover>{{delete_str}}</div>`. - * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile` - * function api below) and returns a string value. + * An Angular **service** is a singleton object created by a **service factory**. These **service + * factories** are functions which, in turn, are created by a **service provider**. + * The **service providers** are constructor functions. When instantiated they must contain a + * property called `$get`, which holds the **service factory** function. * + * When you request a service, the {@link auto.$injector $injector} is responsible for finding the + * correct **service provider**, instantiating it and then calling its `$get` **service factory** + * function to get the instance of the **service**. * - * #### `templateUrl` - * This is similar to `template` but the template is loaded from the specified URL, asynchronously. + * Often services have no configuration options and there is no need to add methods to the service + * provider. The provider will be no more than a constructor function with a `$get` property. For + * these cases the {@link auto.$provide $provide} service has additional helper methods to register + * services without specifying a provider. * - * Because template loading is asynchronous the compiler will suspend compilation of directives on that element - * for later when the template has been resolved. In the meantime it will continue to compile and link - * sibling and parent elements as though this element had not contained any directives. + * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the + * {@link auto.$injector $injector} + * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by + * providers and services. + * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by + * services, not providers. + * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`, + * that will be wrapped in a **service provider** object, whose `$get` property will contain the + * given factory function. + * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class` + * that will be wrapped in a **service provider** object, whose `$get` property will instantiate + * a new object using the given constructor function. * - * The compiler does not suspend the entire compilation to wait for templates to be loaded because this - * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the - * case when only one deeply nested directive has `templateUrl`. + * See the individual methods for more information and examples. + */ + +/** + * @ngdoc method + * @name $provide#provider + * @description * - * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache} - * - * You can specify `templateUrl` as a string representing the URL or as a function which takes two - * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns - * a string value representing the url. In either case, the template URL is passed through {@link - * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}. - * - * - * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0) - * specify what the template should replace. Defaults to `false`. - * - * * `true` - the template will replace the directive's element. - * * `false` - the template will replace the contents of the directive's element. - * - * The replacement process migrates all of the attributes / classes from the old element to the new - * one. See the {@link guide/directive#template-expanding-directive - * Directives Guide} for an example. - * - * There are very few scenarios where element replacement is required for the application function, - * the main one being reusable custom components that are used within SVG contexts - * (because SVG doesn't work with custom elements in the DOM tree). - * - * #### `transclude` - * Extract the contents of the element where the directive appears and make it available to the directive. - * The contents are compiled and provided to the directive as a **transclusion function**. See the - * {@link $compile#transclusion Transclusion} section below. - * - * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the - * directive's element or the entire element: - * - * * `true` - transclude the content (i.e. the child nodes) of the directive's element. - * * `'element'` - transclude the whole of the directive's element including any directives on this - * element that defined at a lower priority than this directive. When used, the `template` - * property is ignored. - * - * - * #### `compile` - * - * ```js - * function compile(tElement, tAttrs, transclude) { ... } - * ``` - * - * The compile function deals with transforming the template DOM. Since most directives do not do - * template transformation, it is not used often. The compile function takes the following arguments: - * - * * `tElement` - template element - The element where the directive has been declared. It is - * safe to do template transformation on the element and child elements only. + * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions + * are constructor functions, whose instances are responsible for "providing" a factory for a + * service. * - * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared - * between all directive compile functions. + * Service provider names start with the name of the service they provide followed by `Provider`. + * For example, the {@link ng.$log $log} service has a provider called + * {@link ng.$logProvider $logProvider}. * - * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)` + * Service provider objects can have additional methods which allow configuration of the provider + * and its service. Importantly, you can configure what kind of service is created by the `$get` + * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a + * method {@link ng.$logProvider#debugEnabled debugEnabled} + * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the + * console or not. * - * <div class="alert alert-warning"> - * **Note:** The template instance and the link instance may be different objects if the template has - * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that - * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration - * should be done in a linking function rather than in a compile function. - * </div> - - * <div class="alert alert-warning"> - * **Note:** The compile function cannot handle directives that recursively use themselves in their - * own templates or compile functions. Compiling these directives results in an infinite loop and a - * stack overflow errors. + * @param {string} name The name of the instance. NOTE: the provider will be available under `name + + 'Provider'` key. + * @param {(Object|function())} provider If the provider is: * - * This can be avoided by manually using $compile in the postLink function to imperatively compile - * a directive's template instead of relying on automatic template compilation via `template` or - * `templateUrl` declaration or manual compilation inside the compile function. - * </div> + * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using + * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created. + * - `Constructor`: a new instance of the provider will be created using + * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`. * - * <div class="alert alert-error"> - * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it - * e.g. does not know about the right outer scope. Please use the transclude function that is passed - * to the link function instead. - * </div> + * @returns {Object} registered provider instance - * A compile function can have a return value which can be either a function or an object. - * - * * returning a (post-link) function - is equivalent to registering the linking function via the - * `link` property of the config object when the compile function is empty. - * - * * returning an object with function(s) registered via `pre` and `post` properties - allows you to - * control when a linking function should be called during the linking phase. See info about - * pre-linking and post-linking functions below. - * + * @example * - * #### `link` - * This property is used only if the `compile` property is not defined. + * The following example shows how to create a simple event tracking service and register it using + * {@link auto.$provide#provider $provide.provider()}. * * ```js - * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... } - * ``` - * - * The link function is responsible for registering DOM listeners as well as updating the DOM. It is - * executed after the template has been cloned. This is where most of the directive logic will be - * put. - * - * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the - * directive for registering {@link ng.$rootScope.Scope#$watch watches}. - * - * * `iElement` - instance element - The element where the directive is to be used. It is safe to - * manipulate the children of the element only in `postLink` function since the children have - * already been linked. - * - * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared - * between all directive linking functions. - * - * * `controller` - a controller instance - A controller instance if at least one directive on the - * element defines a controller. The controller is shared among all the directives, which allows - * the directives to use the controllers as a communication channel. - * - * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. - * This is the same as the `$transclude` - * parameter of directive controllers, see there for details. - * `function([scope], cloneLinkingFn, futureParentElement)`. - * - * #### Pre-linking function - * - * Executed before the child elements are linked. Not safe to do DOM transformation since the - * compiler linking function will fail to locate the correct elements for linking. - * - * #### Post-linking function - * - * Executed after the child elements are linked. - * - * Note that child elements that contain `templateUrl` directives will not have been compiled - * and linked since they are waiting for their template to load asynchronously and their own - * compilation and linking has been suspended until that occurs. - * - * It is safe to do DOM transformation in the post-linking function on elements that are not waiting - * for their async templates to be resolved. - * - * - * ### Transclusion - * - * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and - * copying them to another part of the DOM, while maintaining their connection to the original AngularJS - * scope from where they were taken. - * - * Transclusion is used (often with {@link ngTransclude}) to insert the - * original contents of a directive's element into a specified place in the template of the directive. - * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded - * content has access to the properties on the scope from which it was taken, even if the directive - * has isolated scope. - * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}. + * // Define the eventTracker provider + * function EventTrackerProvider() { + * var trackingUrl = '/track'; * - * This makes it possible for the widget to have private state for its template, while the transcluded - * content has access to its originating scope. + * // A provider method for configuring where the tracked events should been saved + * this.setTrackingUrl = function(url) { + * trackingUrl = url; + * }; * - * <div class="alert alert-warning"> - * **Note:** When testing an element transclude directive you must not place the directive at the root of the - * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives - * Testing Transclusion Directives}. - * </div> + * // The service factory function + * this.$get = ['$http', function($http) { + * var trackedEvents = {}; + * return { + * // Call this to track an event + * event: function(event) { + * var count = trackedEvents[event] || 0; + * count += 1; + * trackedEvents[event] = count; + * return count; + * }, + * // Call this to save the tracked events to the trackingUrl + * save: function() { + * $http.post(trackingUrl, trackedEvents); + * } + * }; + * }]; + * } * - * #### Transclusion Functions + * describe('eventTracker', function() { + * var postSpy; * - * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion - * function** to the directive's `link` function and `controller`. This transclusion function is a special - * **linking function** that will return the compiled contents linked to a new transclusion scope. + * beforeEach(module(function($provide) { + * // Register the eventTracker provider + * $provide.provider('eventTracker', EventTrackerProvider); + * })); * - * <div class="alert alert-info"> - * If you are just using {@link ngTransclude} then you don't need to worry about this function, since - * ngTransclude will deal with it for us. - * </div> + * beforeEach(module(function(eventTrackerProvider) { + * // Configure eventTracker provider + * eventTrackerProvider.setTrackingUrl('/custom-track'); + * })); * - * If you want to manually control the insertion and removal of the transcluded content in your directive - * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery - * object that contains the compiled DOM, which is linked to the correct transclusion scope. + * it('tracks events', inject(function(eventTracker) { + * expect(eventTracker.event('login')).toEqual(1); + * expect(eventTracker.event('login')).toEqual(2); + * })); * - * When you call a transclusion function you can pass in a **clone attach function**. This function accepts - * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded - * content and the `scope` is the newly created transclusion scope, to which the clone is bound. + * it('saves to the tracking url', inject(function(eventTracker, $http) { + * postSpy = spyOn($http, 'post'); + * eventTracker.event('login'); + * eventTracker.save(); + * expect(postSpy).toHaveBeenCalled(); + * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track'); + * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track'); + * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 }); + * })); + * }); + * ``` + */ + +/** + * @ngdoc method + * @name $provide#factory + * @description * - * <div class="alert alert-info"> - * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function - * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope. - * </div> + * Register a **service factory**, which will be called to return the service instance. + * This is short for registering a service where its provider consists of only a `$get` property, + * which is the given service factory function. + * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to + * configure your service in a provider. * - * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone - * attach function**: + * @param {string} name The name of the instance. + * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation. + * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`. + * @returns {Object} registered provider instance * + * @example + * Here is an example of registering a service * ```js - * var transcludedContent, transclusionScope; - * - * $transclude(function(clone, scope) { - * element.append(clone); - * transcludedContent = clone; - * transclusionScope = scope; - * }); + * $provide.factory('ping', ['$http', function($http) { + * return function ping() { + * return $http.send('/ping'); + * }; + * }]); * ``` - * - * Later, if you want to remove the transcluded content from your DOM then you should also destroy the - * associated transclusion scope: - * + * You would then inject and use this service like this: * ```js - * transcludedContent.remove(); - * transclusionScope.$destroy(); + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping(); + * }]); * ``` + */ + + +/** + * @ngdoc method + * @name $provide#service + * @description * - * <div class="alert alert-info"> - * **Best Practice**: if you intend to add and remove transcluded content manually in your directive - * (by calling the transclude function to get the DOM and and calling `element.remove()` to remove it), - * then you are also responsible for calling `$destroy` on the transclusion scope. - * </div> - * - * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat} - * automatically destroy their transluded clones as necessary so you do not need to worry about this if - * you are simply using {@link ngTransclude} to inject the transclusion into your directive. - * - * - * #### Transclusion Scopes - * - * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion - * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed - * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it - * was taken. - * - * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look - * like this: + * Register a **service constructor**, which will be invoked with `new` to create the service + * instance. + * This is short for registering a service where its provider's `$get` property is the service + * constructor function that will be used to instantiate the service instance. * - * ```html - * <div ng-app> - * <div isolate> - * <div transclusion> - * </div> - * </div> - * </div> - * ``` + * You should use {@link auto.$provide#service $provide.service(class)} if you define your service + * as a type/class. * - * The `$parent` scope hierarchy will look like this: + * @param {string} name The name of the instance. + * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function) + * that will be instantiated. + * @returns {Object} registered provider instance * - * ``` - * - $rootScope - * - isolate - * - transclusion - * ``` + * @example + * Here is an example of registering a service using + * {@link auto.$provide#service $provide.service(class)}. + * ```js + * var Ping = function($http) { + * this.$http = $http; + * }; * - * but the scopes will inherit prototypically from different scopes to their `$parent`. + * Ping.$inject = ['$http']; * + * Ping.prototype.send = function() { + * return this.$http.get('/ping'); + * }; + * $provide.service('ping', Ping); * ``` - * - $rootScope - * - transclusion - * - isolate + * You would then inject and use this service like this: + * ```js + * someModule.controller('Ctrl', ['ping', function(ping) { + * ping.send(); + * }]); * ``` + */ + + +/** + * @ngdoc method + * @name $provide#value + * @description * + * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a + * number, an array, an object or a function. This is short for registering a service where its + * provider's `$get` property is a factory function that takes no arguments and returns the **value + * service**. * - * ### Attributes - * - * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the - * `link()` or `compile()` functions. It has a variety of uses. - * - * accessing *Normalized attribute names:* - * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. - * the attributes object allows for normalized access to - * the attributes. - * - * * *Directive inter-communication:* All directives share the same instance of the attributes - * object which allows the directives to use the attributes object as inter directive - * communication. - * - * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object - * allowing other directives to read the interpolated value. + * Value services are similar to constant services, except that they cannot be injected into a + * module configuration function (see {@link angular.Module#config}) but they can be overridden by + * an Angular + * {@link auto.$provide#decorator decorator}. * - * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes - * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also - * the only way to easily get the actual value because during the linking phase the interpolation - * hasn't been evaluated yet and so the value is at this time set to `undefined`. + * @param {string} name The name of the instance. + * @param {*} value The value. + * @returns {Object} registered provider instance * + * @example + * Here are some examples of creating value services. * ```js - * function linkingFn(scope, elm, attrs, ctrl) { - * // get the attribute value - * console.log(attrs.ngModel); + * $provide.value('ADMIN_USER', 'admin'); * - * // change the attribute - * attrs.$set('ngModel', 'new value'); + * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 }); * - * // observe changes to interpolated attribute - * attrs.$observe('ngModel', function(value) { - * console.log('ngModel has changed value to ' + value); + * $provide.value('halfOf', function(value) { + * return value / 2; * }); - * } * ``` - * - * ## Example - * - * <div class="alert alert-warning"> - * **Note**: Typically directives are registered with `module.directive`. The example below is - * to illustrate how `$compile` works. - * </div> - * - <example module="compileExample"> - <file name="index.html"> - <script> - angular.module('compileExample', [], function($compileProvider) { - // configure new 'compile' directive by passing a directive - // factory function. The factory function injects the '$compile' - $compileProvider.directive('compile', function($compile) { - // directive factory creates a link function - return function(scope, element, attrs) { - scope.$watch( - function(scope) { - // watch the 'compile' expression for changes - return scope.$eval(attrs.compile); - }, - function(value) { - // when the 'compile' expression changes - // assign it into the current DOM - element.html(value); + */ - // compile the new DOM and link it to the current - // scope. - // NOTE: we only compile .childNodes so that - // we don't get into infinite loop compiling ourselves - $compile(element.contents())(scope); - } - ); - }; - }); - }) - .controller('GreeterController', ['$scope', function($scope) { - $scope.name = 'Angular'; - $scope.html = 'Hello {{name}}'; - }]); - </script> - <div ng-controller="GreeterController"> - <input ng-model="name"> <br> - <textarea ng-model="html"></textarea> <br> - <div compile="html"></div> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should auto compile', function() { - var textarea = $('textarea'); - var output = $('div[compile]'); - // The initial state reads 'Hello Angular'. - expect(output.getText()).toBe('Hello Angular'); - textarea.clear(); - textarea.sendKeys('{{name}}!'); - expect(output.getText()).toBe('Angular!'); - }); - </file> - </example> +/** + * @ngdoc method + * @name $provide#constant + * @description * + * Register a **constant service**, such as a string, a number, an array, an object or a function, + * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be + * injected into a module configuration function (see {@link angular.Module#config}) and it cannot + * be overridden by an Angular {@link auto.$provide#decorator decorator}. * - * @param {string|DOMElement} element Element or HTML string to compile into a template function. - * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. + * @param {string} name The name of the constant. + * @param {*} value The constant value. + * @returns {Object} registered instance * - * <div class="alert alert-error"> - * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it - * e.g. will not use the right outer scope. Please pass the transclude function as a - * `parentBoundTranscludeFn` to the link function instead. - * </div> + * @example + * Here a some examples of creating constants: + * ```js + * $provide.constant('SHARD_HEIGHT', 306); * - * @param {number} maxPriority only apply directives lower than given priority (Only effects the - * root element(s), not their children) - * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template - * (a DOM element/tree) to a scope. Where: + * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']); * - * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. - * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the - * `template` and call the `cloneAttachFn` function allowing the caller to attach the - * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is - * called as: <br> `cloneAttachFn(clonedElement, scope)` where: + * $provide.constant('double', function(value) { + * return value * 2; + * }); + * ``` + */ + + +/** + * @ngdoc method + * @name $provide#decorator + * @description * - * * `clonedElement` - is a clone of the original `element` passed into the compiler. - * * `scope` - is the current scope with which the linking function is working with. + * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator + * intercepts the creation of a service, allowing it to override or modify the behaviour of the + * service. The object returned by the decorator may be the original service, or a new service + * object which replaces or wraps and delegates to the original service. * - * * `options` - An optional object hash with linking options. If `options` is provided, then the following - * keys may be used to control linking behavior: + * @param {string} name The name of the service to decorate. + * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be + * instantiated and should return the decorated service instance. The function is called using + * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable. + * Local injection arguments: * - * * `parentBoundTranscludeFn` - the transclude function made available to - * directives; if given, it will be passed through to the link functions of - * directives found in `element` during compilation. - * * `transcludeControllers` - an object hash with keys that map controller names - * to controller instances; if given, it will make the controllers - * available to directives. - * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add - * the cloned elements; only needed for transcludes that are allowed to contain non html - * elements (e.g. SVG elements). See also the directive.controller property. + * * `$delegate` - The original service instance, which can be monkey patched, configured, + * decorated or delegated to. * - * Calling the linking function returns the element of the template. It is either the original - * element passed in, or the clone of the element if the `cloneAttachFn` is provided. - * - * After linking the view is not updated until after a call to $digest which typically is done by - * Angular automatically. - * - * If you need access to the bound view, there are two ways to do it: - * - * - If you are not asking the linking function to clone the template, create the DOM element(s) - * before you send them to the compiler and keep this reference around. - * ```js - * var element = $compile('<p>{{total}}</p>')(scope); - * ``` - * - * - if on the other hand, you need the element to be cloned, the view reference from the original - * example would not point to the clone, but rather to the original template that was cloned. In - * this case, you can access the clone via the cloneAttachFn: - * ```js - * var templateElement = angular.element('<p>{{total}}</p>'), - * scope = ....; - * - * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) { - * //attach the clone to DOM document at the right place - * }); - * - * //now we have reference to the cloned DOM via `clonedElement` - * ``` - * - * - * For information on how the compiler works, see the - * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. + * @example + * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting + * calls to {@link ng.$log#error $log.warn()}. + * ```js + * $provide.decorator('$log', ['$delegate', function($delegate) { + * $delegate.warn = $delegate.error; + * return $delegate; + * }]); + * ``` */ -var $compileMinErr = minErr('$compile'); -/** - * @ngdoc provider - * @name $compileProvider - * - * @description - */ -$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider']; -function $CompileProvider($provide, $$sanitizeUriProvider) { - var hasDirectives = {}, - Suffix = 'Directive', - COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, - CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, - ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), - REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; +function createInjector(modulesToLoad, strictDi) { + strictDi = (strictDi === true); + var INSTANTIATING = {}, + providerSuffix = 'Provider', + path = [], + loadedModules = new HashMap([], true), + providerCache = { + $provide: { + provider: supportObject(provider), + factory: supportObject(factory), + service: supportObject(service), + value: supportObject(value), + constant: supportObject(constant), + decorator: decorator + } + }, + providerInjector = (providerCache.$injector = + createInternalInjector(providerCache, function(serviceName, caller) { + if (angular.isString(caller)) { + path.push(caller); + } + throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- ')); + })), + instanceCache = {}, + instanceInjector = (instanceCache.$injector = + createInternalInjector(instanceCache, function(serviceName, caller) { + var provider = providerInjector.get(serviceName + providerSuffix, caller); + return instanceInjector.invoke(provider.$get, provider, undefined, serviceName); + })); - // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes - // The assumption is that future DOM event attribute names will begin with - // 'on' and be composed of only English letters. - var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; - function parseIsolateBindings(scope, directiveName) { - var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; + forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); }); - var bindings = {}; + return instanceInjector; - forEach(scope, function(definition, scopeName) { - var match = definition.match(LOCAL_REGEXP); + //////////////////////////////////// + // $provider + //////////////////////////////////// - if (!match) { - throw $compileMinErr('iscp', - "Invalid isolate scope definition for directive '{0}'." + - " Definition: {... {1}: '{2}' ...}", - directiveName, scopeName, definition); + function supportObject(delegate) { + return function(key, value) { + if (isObject(key)) { + forEach(key, reverseParams(delegate)); + } else { + return delegate(key, value); } + }; + } - bindings[scopeName] = { - mode: match[1][0], - collection: match[2] === '*', - optional: match[3] === '?', - attrName: match[4] || scopeName - }; + function provider(name, provider_) { + assertNotHasOwnProperty(name, 'service'); + if (isFunction(provider_) || isArray(provider_)) { + provider_ = providerInjector.instantiate(provider_); + } + if (!provider_.$get) { + throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); + } + return providerCache[name + providerSuffix] = provider_; + } + + function enforceReturnValue(name, factory) { + return function enforcedReturnValue() { + var result = instanceInjector.invoke(factory, this); + if (isUndefined(result)) { + throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name); + } + return result; + }; + } + + function factory(name, factoryFn, enforce) { + return provider(name, { + $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn }); + } - return bindings; + function service(name, constructor) { + return factory(name, ['$injector', function($injector) { + return $injector.instantiate(constructor); + }]); } - /** - * @ngdoc method - * @name $compileProvider#directive - * @kind function - * - * @description - * Register a new directive with the compiler. - * - * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which - * will match as <code>ng-bind</code>), or an object map of directives where the keys are the - * names and the values are the factories. - * @param {Function|Array} directiveFactory An injectable directive factory function. See - * {@link guide/directive} for more info. - * @returns {ng.$compileProvider} Self for chaining. - */ - this.directive = function registerDirective(name, directiveFactory) { - assertNotHasOwnProperty(name, 'directive'); - if (isString(name)) { - assertArg(directiveFactory, 'directiveFactory'); - if (!hasDirectives.hasOwnProperty(name)) { - hasDirectives[name] = []; - $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', - function($injector, $exceptionHandler) { - var directives = []; - forEach(hasDirectives[name], function(directiveFactory, index) { - try { - var directive = $injector.invoke(directiveFactory); - if (isFunction(directive)) { - directive = { compile: valueFn(directive) }; - } else if (!directive.compile && directive.link) { - directive.compile = valueFn(directive.link); - } - directive.priority = directive.priority || 0; - directive.index = index; - directive.name = directive.name || name; - directive.require = directive.require || (directive.controller && directive.name); - directive.restrict = directive.restrict || 'EA'; - if (isObject(directive.scope)) { - directive.$$isolateBindings = parseIsolateBindings(directive.scope, directive.name); - } - directives.push(directive); - } catch (e) { - $exceptionHandler(e); - } - }); - return directives; - }]); + function value(name, val) { return factory(name, valueFn(val), false); } + + function constant(name, value) { + assertNotHasOwnProperty(name, 'constant'); + providerCache[name] = value; + instanceCache[name] = value; + } + + function decorator(serviceName, decorFn) { + var origProvider = providerInjector.get(serviceName + providerSuffix), + orig$get = origProvider.$get; + + origProvider.$get = function() { + var origInstance = instanceInjector.invoke(orig$get, origProvider); + return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); + }; + } + + //////////////////////////////////// + // Module Loading + //////////////////////////////////// + function loadModules(modulesToLoad) { + var runBlocks = [], moduleFn; + forEach(modulesToLoad, function(module) { + if (loadedModules.get(module)) return; + loadedModules.put(module, true); + + function runInvokeQueue(queue) { + var i, ii; + for (i = 0, ii = queue.length; i < ii; i++) { + var invokeArgs = queue[i], + provider = providerInjector.get(invokeArgs[0]); + + provider[invokeArgs[1]].apply(provider, invokeArgs[2]); + } + } + + try { + if (isString(module)) { + moduleFn = angularModule(module); + runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); + runInvokeQueue(moduleFn._invokeQueue); + runInvokeQueue(moduleFn._configBlocks); + } else if (isFunction(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else if (isArray(module)) { + runBlocks.push(providerInjector.invoke(module)); + } else { + assertArgFn(module, 'module'); + } + } catch (e) { + if (isArray(module)) { + module = module[module.length - 1]; + } + if (e.message && e.stack && e.stack.indexOf(e.message) == -1) { + // Safari & FF's stack traces don't contain error.message content + // unlike those of Chrome and IE + // So if stack doesn't contain message, we create a new string that contains both. + // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here. + /* jshint -W022 */ + e = e.message + '\n' + e.stack; + } + throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}", + module, e.stack || e.message || e); + } + }); + return runBlocks; + } + + //////////////////////////////////// + // internal Injector + //////////////////////////////////// + + function createInternalInjector(cache, factory) { + + function getService(serviceName, caller) { + if (cache.hasOwnProperty(serviceName)) { + if (cache[serviceName] === INSTANTIATING) { + throw $injectorMinErr('cdep', 'Circular dependency found: {0}', + serviceName + ' <- ' + path.join(' <- ')); + } + return cache[serviceName]; + } else { + try { + path.unshift(serviceName); + cache[serviceName] = INSTANTIATING; + return cache[serviceName] = factory(serviceName, caller); + } catch (err) { + if (cache[serviceName] === INSTANTIATING) { + delete cache[serviceName]; + } + throw err; + } finally { + path.shift(); + } } - hasDirectives[name].push(directiveFactory); - } else { - forEach(name, reverseParams(registerDirective)); } - return this; - }; + function invoke(fn, self, locals, serviceName) { + if (typeof locals === 'string') { + serviceName = locals; + locals = null; + } + + var args = [], + $inject = createInjector.$$annotate(fn, strictDi, serviceName), + length, i, + key; + + for (i = 0, length = $inject.length; i < length; i++) { + key = $inject[i]; + if (typeof key !== 'string') { + throw $injectorMinErr('itkn', + 'Incorrect injection token! Expected service name as string, got {0}', key); + } + args.push( + locals && locals.hasOwnProperty(key) + ? locals[key] + : getService(key, serviceName) + ); + } + if (isArray(fn)) { + fn = fn[length]; + } + + // http://jsperf.com/angularjs-invoke-apply-vs-switch + // #5388 + return fn.apply(self, args); + } + + function instantiate(Type, locals, serviceName) { + // Check if Type is annotated and use just the given function at n-1 as parameter + // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); + // Object creation: http://jsperf.com/create-constructor/2 + var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null); + var returnedValue = invoke(Type, instance, locals, serviceName); + + return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance; + } + + return { + invoke: invoke, + instantiate: instantiate, + get: getService, + annotate: createInjector.$$annotate, + has: function(name) { + return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); + } + }; + } +} + +createInjector.$$annotate = annotate; + +/** + * @ngdoc provider + * @name $anchorScrollProvider + * + * @description + * Use `$anchorScrollProvider` to disable automatic scrolling whenever + * {@link ng.$location#hash $location.hash()} changes. + */ +function $AnchorScrollProvider() { + + var autoScrollingEnabled = true; /** * @ngdoc method - * @name $compileProvider#aHrefSanitizationWhitelist - * @kind function + * @name $anchorScrollProvider#disableAutoScrolling * * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during a[href] sanitization. - * - * The sanitization is a security measure aimed at preventing XSS attacks via html links. - * - * Any url about to be assigned to a[href] via data-binding is first normalized and turned into - * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` - * regular expression. If a match is found, the original url is written into the dom. Otherwise, - * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to + * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br /> + * Use this method to disable automatic scrolling. * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. + * If automatic scrolling is disabled, one must explicitly call + * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the + * current hash. */ - this.aHrefSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); - return this; - } else { - return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); - } + this.disableAutoScrolling = function() { + autoScrollingEnabled = false; }; - /** - * @ngdoc method - * @name $compileProvider#imgSrcSanitizationWhitelist + * @ngdoc service + * @name $anchorScroll * @kind function + * @requires $window + * @requires $location + * @requires $rootScope * * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during img[src] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the + * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified + * in the + * [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document). * - * Any url about to be assigned to img[src] via data-binding is first normalized and turned into - * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` - * regular expression. If a match is found, the original url is written into the dom. Otherwise, - * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to + * match any anchor whenever it changes. This can be disabled by calling + * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}. * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.imgSrcSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); - return this; - } else { - return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); - } - }; - - /** - * @ngdoc method - * @name $compileProvider#debugInfoEnabled + * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a + * vertical scroll-offset (either fixed or dynamic). * - * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the - * current debugInfoEnabled state - * @returns {*} current value if used as getter or itself (chaining) if used as setter + * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of + * {@link ng.$location#hash $location.hash()} will be used. * - * @kind function + * @property {(number|function|jqLite)} yOffset + * If set, specifies a vertical scroll-offset. This is often useful when there are fixed + * positioned elements at the top of the page, such as navbars, headers etc. * - * @description - * Call this method to enable/disable various debug runtime information in the compiler such as adding - * binding information and a reference to the current scope on to DOM elements. - * If enabled, the compiler will add the following to DOM elements that have been bound to the scope - * * `ng-binding` CSS class - * * `$binding` data property containing an array of the binding expressions + * `yOffset` can be specified in various ways: + * - **number**: A fixed number of pixels to be used as offset.<br /><br /> + * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return + * a number representing the offset (in pixels).<br /><br /> + * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from + * the top of the page to the element's bottom will be used as offset.<br /> + * **Note**: The element will be taken into account only as long as its `position` is set to + * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust + * their height and/or positioning according to the viewport's size. * - * You may want to disable this in production for a significant performance boost. See - * {@link guide/production#disabling-debug-data Disabling Debug Data} for more. + * <br /> + * <div class="alert alert-warning"> + * In order for `yOffset` to work properly, scrolling should take place on the document's root and + * not some child element. + * </div> * - * The default value is true. - */ - var debugInfoEnabled = true; - this.debugInfoEnabled = function(enabled) { - if (isDefined(enabled)) { - debugInfoEnabled = enabled; - return this; - } - return debugInfoEnabled; - }; - - this.$get = [ - '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', - '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri', - function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, - $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { - - var Attributes = function(element, attributesToCopy) { - if (attributesToCopy) { - var keys = Object.keys(attributesToCopy); - var i, l, key; - - for (i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - this[key] = attributesToCopy[key]; - } - } else { - this.$attr = {}; - } + * @example + <example module="anchorScrollExample"> + <file name="index.html"> + <div id="scrollArea" ng-controller="ScrollController"> + <a ng-click="gotoBottom()">Go to bottom</a> + <a id="bottom"></a> You're at the bottom! + </div> + </file> + <file name="script.js"> + angular.module('anchorScrollExample', []) + .controller('ScrollController', ['$scope', '$location', '$anchorScroll', + function ($scope, $location, $anchorScroll) { + $scope.gotoBottom = function() { + // set the location.hash to the id of + // the element you wish to scroll to. + $location.hash('bottom'); - this.$$element = element; - }; - - Attributes.prototype = { - /** - * @ngdoc method - * @name $compile.directive.Attributes#$normalize - * @kind function - * - * @description - * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or - * `data-`) to its normalized, camelCase form. - * - * Also there is special case for Moz prefix starting with upper case letter. - * - * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} - * - * @param {string} name Name to normalize - */ - $normalize: directiveNormalize, + // call $anchorScroll() + $anchorScroll(); + }; + }]); + </file> + <file name="style.css"> + #scrollArea { + height: 280px; + overflow: auto; + } + #bottom { + display: block; + margin-top: 2000px; + } + </file> + </example> + * + * <hr /> + * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value). + * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details. + * + * @example + <example module="anchorScrollOffsetExample"> + <file name="index.html"> + <div class="fixed-header" ng-controller="headerCtrl"> + <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]"> + Go to anchor {{x}} + </a> + </div> + <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]"> + Anchor {{x}} of 5 + </div> + </file> + <file name="script.js"> + angular.module('anchorScrollOffsetExample', []) + .run(['$anchorScroll', function($anchorScroll) { + $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels + }]) + .controller('headerCtrl', ['$anchorScroll', '$location', '$scope', + function ($anchorScroll, $location, $scope) { + $scope.gotoAnchor = function(x) { + var newHash = 'anchor' + x; + if ($location.hash() !== newHash) { + // set the $location.hash to `newHash` and + // $anchorScroll will automatically scroll to it + $location.hash('anchor' + x); + } else { + // call $anchorScroll() explicitly, + // since $location.hash hasn't changed + $anchorScroll(); + } + }; + } + ]); + </file> + <file name="style.css"> + body { + padding-top: 50px; + } - /** - * @ngdoc method - * @name $compile.directive.Attributes#$addClass - * @kind function - * - * @description - * Adds the CSS class value specified by the classVal parameter to the element. If animations - * are enabled then an animation will be triggered for the class addition. - * - * @param {string} classVal The className value that will be added to the element - */ - $addClass: function(classVal) { - if (classVal && classVal.length > 0) { - $animate.addClass(this.$$element, classVal); - } - }, + .anchor { + border: 2px dashed DarkOrchid; + padding: 10px 10px 200px 10px; + } - /** - * @ngdoc method - * @name $compile.directive.Attributes#$removeClass - * @kind function - * - * @description - * Removes the CSS class value specified by the classVal parameter from the element. If - * animations are enabled then an animation will be triggered for the class removal. - * - * @param {string} classVal The className value that will be removed from the element - */ - $removeClass: function(classVal) { - if (classVal && classVal.length > 0) { - $animate.removeClass(this.$$element, classVal); - } - }, + .fixed-header { + background-color: rgba(0, 0, 0, 0.2); + height: 50px; + position: fixed; + top: 0; left: 0; right: 0; + } - /** - * @ngdoc method - * @name $compile.directive.Attributes#$updateClass - * @kind function - * - * @description - * Adds and removes the appropriate CSS class values to the element based on the difference - * between the new and old CSS class values (specified as newClasses and oldClasses). - * - * @param {string} newClasses The current CSS className value - * @param {string} oldClasses The former CSS className value - */ - $updateClass: function(newClasses, oldClasses) { - var toAdd = tokenDifference(newClasses, oldClasses); - if (toAdd && toAdd.length) { - $animate.addClass(this.$$element, toAdd); - } + .fixed-header > a { + display: inline-block; + margin: 5px 15px; + } + </file> + </example> + */ + this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { + var document = $window.document; - var toRemove = tokenDifference(oldClasses, newClasses); - if (toRemove && toRemove.length) { - $animate.removeClass(this.$$element, toRemove); + // Helper function to get first anchor from a NodeList + // (using `Array#some()` instead of `angular#forEach()` since it's more performant + // and working in all supported browsers.) + function getFirstAnchor(list) { + var result = null; + Array.prototype.some.call(list, function(element) { + if (nodeName_(element) === 'a') { + result = element; + return true; } - }, - - /** - * Set a normalized attribute on the element in a way such that all directives - * can share the attribute. This function properly handles boolean attributes. - * @param {string} key Normalized key. (ie ngAttribute) - * @param {string|boolean} value The value to set. If `null` attribute will be deleted. - * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. - * Defaults to true. - * @param {string=} attrName Optional none normalized name. Defaults to key. - */ - $set: function(key, value, writeAttr, attrName) { - // TODO: decide whether or not to throw an error if "class" - //is set through this function since it may cause $updateClass to - //become unstable. - - var node = this.$$element[0], - booleanKey = getBooleanAttrName(node, key), - aliasedKey = getAliasedAttrName(node, key), - observer = key, - nodeName; + }); + return result; + } - if (booleanKey) { - this.$$element.prop(key, value); - attrName = booleanKey; - } else if (aliasedKey) { - this[aliasedKey] = value; - observer = aliasedKey; - } + function getYOffset() { - this[key] = value; + var offset = scroll.yOffset; - // translate normalized key to actual key - if (attrName) { - this.$attr[key] = attrName; + if (isFunction(offset)) { + offset = offset(); + } else if (isElement(offset)) { + var elem = offset[0]; + var style = $window.getComputedStyle(elem); + if (style.position !== 'fixed') { + offset = 0; } else { - attrName = this.$attr[key]; - if (!attrName) { - this.$attr[key] = attrName = snake_case(key, '-'); - } + offset = elem.getBoundingClientRect().bottom; } + } else if (!isNumber(offset)) { + offset = 0; + } - nodeName = nodeName_(this.$$element); - - if ((nodeName === 'a' && key === 'href') || - (nodeName === 'img' && key === 'src')) { - // sanitize a[href] and img[src] values - this[key] = value = $$sanitizeUri(value, key === 'src'); - } else if (nodeName === 'img' && key === 'srcset') { - // sanitize img[srcset] values - var result = ""; - - // first check if there are spaces because it's not the same pattern - var trimmedSrcset = trim(value); - // ( 999x ,| 999w ,| ,|, ) - var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; - var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; + return offset; + } - // split srcset into tuple of uri and descriptor except for the last item - var rawUris = trimmedSrcset.split(pattern); + function scrollTo(elem) { + if (elem) { + elem.scrollIntoView(); - // for each tuples - var nbrUrisWith2parts = Math.floor(rawUris.length / 2); - for (var i = 0; i < nbrUrisWith2parts; i++) { - var innerIdx = i * 2; - // sanitize the uri - result += $$sanitizeUri(trim(rawUris[innerIdx]), true); - // add the descriptor - result += (" " + trim(rawUris[innerIdx + 1])); - } + var offset = getYOffset(); - // split the last item into uri and descriptor - var lastTuple = trim(rawUris[i * 2]).split(/\s/); + if (offset) { + // `offset` is the number of pixels we should scroll UP in order to align `elem` properly. + // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the + // top of the viewport. + // + // IF the number of pixels from the top of `elem` to the end of the page's content is less + // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some + // way down the page. + // + // This is often the case for elements near the bottom of the page. + // + // In such cases we do not need to scroll the whole `offset` up, just the difference between + // the top of the element and the offset, which is enough to align the top of `elem` at the + // desired position. + var elemTop = elem.getBoundingClientRect().top; + $window.scrollBy(0, elemTop - offset); + } + } else { + $window.scrollTo(0, 0); + } + } - // sanitize the last uri - result += $$sanitizeUri(trim(lastTuple[0]), true); + function scroll(hash) { + hash = isString(hash) ? hash : $location.hash(); + var elm; - // and add the last descriptor if any - if (lastTuple.length === 2) { - result += (" " + trim(lastTuple[1])); - } - this[key] = value = result; - } + // empty hash, scroll to the top of the page + if (!hash) scrollTo(null); - if (writeAttr !== false) { - if (value === null || value === undefined) { - this.$$element.removeAttr(attrName); - } else { - this.$$element.attr(attrName, value); - } - } + // element with given id + else if ((elm = document.getElementById(hash))) scrollTo(elm); - // fire observers - var $$observers = this.$$observers; - $$observers && forEach($$observers[observer], function(fn) { - try { - fn(value); - } catch (e) { - $exceptionHandler(e); - } - }); - }, + // first anchor with given name :-D + else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm); + // no element and hash == 'top', scroll to the top of the page + else if (hash === 'top') scrollTo(null); + } - /** - * @ngdoc method - * @name $compile.directive.Attributes#$observe - * @kind function - * - * @description - * Observes an interpolated attribute. - * - * The observer function will be invoked once during the next `$digest` following - * compilation. The observer is then invoked whenever the interpolated value - * changes. - * - * @param {string} key Normalized key. (ie ngAttribute) . - * @param {function(interpolatedValue)} fn Function that will be called whenever - the interpolated value of the attribute changes. - * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info. - * @returns {function()} Returns a deregistration function for this observer. - */ - $observe: function(key, fn) { - var attrs = this, - $$observers = (attrs.$$observers || (attrs.$$observers = createMap())), - listeners = ($$observers[key] || ($$observers[key] = [])); + // does not scroll when user clicks on anchor link that is currently on + // (no url change, no $location.hash() change), browser native does scroll + if (autoScrollingEnabled) { + $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, + function autoScrollWatchAction(newVal, oldVal) { + // skip the initial scroll if $location.hash is empty + if (newVal === oldVal && newVal === '') return; - listeners.push(fn); - $rootScope.$evalAsync(function() { - if (!listeners.$$inter && attrs.hasOwnProperty(key)) { - // no one registered attribute interpolation function, so lets call it manually - fn(attrs[key]); - } + jqLiteDocumentLoaded(function() { + $rootScope.$evalAsync(scroll); + }); }); + } - return function() { - arrayRemove(listeners, fn); - }; - } - }; + return scroll; + }]; +} +var $animateMinErr = minErr('$animate'); +var ELEMENT_NODE = 1; +var NG_ANIMATE_CLASSNAME = 'ng-animate'; - function safeAddClass($element, className) { - try { - $element.addClass(className); - } catch (e) { - // ignore, since it means that we are trying to set class on - // SVG element, where class name is read-only. - } - } +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} +function extractElementNode(element) { + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType === ELEMENT_NODE) { + return elm; + } + } +} - var startSymbol = $interpolate.startSymbol(), - endSymbol = $interpolate.endSymbol(), - denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') - ? identity - : function denormalizeTemplate(template) { - return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); - }, - NG_ATTR_BINDING = /^ngAttr[A-Z]/; +function splitClasses(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } - compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { - var bindings = $element.data('$binding') || []; + // Use createMap() to prevent class assumptions involving property names in + // Object.prototype + var obj = createMap(); + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; +} - if (isArray(binding)) { - bindings = bindings.concat(binding); - } else { - bindings.push(binding); +// if any other type of options value besides an Object value is +// passed into the $animate.method() animation then this helper code +// will be run which will ignore it. While this patch is not the +// greatest solution to this, a lot of existing plugins depend on +// $animate to either call the callback (< 1.2) or return a promise +// that can be changed. This helper function ensures that the options +// are wiped clean incase a callback function is provided. +function prepareAnimateOptions(options) { + return isObject(options) + ? options + : {}; +} + +var $$CoreAnimateRunnerProvider = function() { + this.$get = ['$q', '$$rAF', function($q, $$rAF) { + function AnimateRunner() {} + AnimateRunner.all = noop; + AnimateRunner.chain = noop; + AnimateRunner.prototype = { + end: noop, + cancel: noop, + resume: noop, + pause: noop, + complete: noop, + then: function(pass, fail) { + return $q(function(resolve) { + $$rAF(function() { + resolve(); + }); + }).then(pass, fail); } + }; + return AnimateRunner; + }]; +}; - $element.data('$binding', bindings); - } : noop; - - compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { - safeAddClass($element, 'ng-binding'); - } : noop; +// this is prefixed with Core since it conflicts with +// the animateQueueProvider defined in ngAnimate/animateQueue.js +var $$CoreAnimateQueueProvider = function() { + var postDigestQueue = new HashMap(); + var postDigestElements = []; - compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { - var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope'; - $element.data(dataName, scope); - } : noop; + this.$get = ['$$AnimateRunner', '$rootScope', + function($$AnimateRunner, $rootScope) { + return { + enabled: noop, + on: noop, + off: noop, + pin: noop, - compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { - safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope'); - } : noop; + push: function(element, event, options, domOperation) { + domOperation && domOperation(); - return compile; + options = options || {}; + options.from && element.css(options.from); + options.to && element.css(options.to); - //================================ + if (options.addClass || options.removeClass) { + addRemoveClassesPostDigest(element, options.addClass, options.removeClass); + } - function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, - previousCompileContext) { - if (!($compileNodes instanceof jqLite)) { - // jquery always rewraps, whereas we need to preserve the original selector so that we can - // modify it. - $compileNodes = jqLite($compileNodes); + return new $$AnimateRunner(); // jshint ignore:line } - // We can not compile top level text elements since text nodes can be merged and we will - // not be able to attach scope data to them, so we will wrap them in <span> - forEach($compileNodes, function(node, index) { - if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) { - $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0]; - } - }); - var compositeLinkFn = - compileNodes($compileNodes, transcludeFn, $compileNodes, - maxPriority, ignoreDirective, previousCompileContext); - compile.$$addScopeClass($compileNodes); - var namespace = null; - return function publicLinkFn(scope, cloneConnectFn, options) { - assertArg(scope, 'scope'); + }; - options = options || {}; - var parentBoundTranscludeFn = options.parentBoundTranscludeFn, - transcludeControllers = options.transcludeControllers, - futureParentElement = options.futureParentElement; + function addRemoveClassesPostDigest(element, add, remove) { + var data = postDigestQueue.get(element); + var classVal; - // When `parentBoundTranscludeFn` is passed, it is a - // `controllersBoundTransclude` function (it was previously passed - // as `transclude` to directive.link) so we must unwrap it to get - // its `boundTranscludeFn` - if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { - parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; - } + if (!data) { + postDigestQueue.put(element, data = {}); + postDigestElements.push(element); + } - if (!namespace) { - namespace = detectNamespaceForChildElements(futureParentElement); - } - var $linkNode; - if (namespace !== 'html') { - // When using a directive with replace:true and templateUrl the $compileNodes - // (or a child element inside of them) - // might change, so we need to recreate the namespace adapted compileNodes - // for call to the link function. - // Note: This will already clone the nodes... - $linkNode = jqLite( - wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html()) - ); - } else if (cloneConnectFn) { - // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart - // and sometimes changes the structure of the DOM. - $linkNode = JQLitePrototype.clone.call($compileNodes); - } else { - $linkNode = $compileNodes; - } + if (add) { + forEach(add.split(' '), function(className) { + if (className) { + data[className] = true; + } + }); + } - if (transcludeControllers) { - for (var controllerName in transcludeControllers) { - $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance); + if (remove) { + forEach(remove.split(' '), function(className) { + if (className) { + data[className] = false; } - } + }); + } - compile.$$addScopeInfo($linkNode, scope); + if (postDigestElements.length > 1) return; + + $rootScope.$$postDigest(function() { + forEach(postDigestElements, function(element) { + var data = postDigestQueue.get(element); + if (data) { + var existing = splitClasses(element.attr('class')); + var toAdd = ''; + var toRemove = ''; + forEach(data, function(status, className) { + var hasClass = !!existing[className]; + if (status !== hasClass) { + if (status) { + toAdd += (toAdd.length ? ' ' : '') + className; + } else { + toRemove += (toRemove.length ? ' ' : '') + className; + } + } + }); - if (cloneConnectFn) cloneConnectFn($linkNode, scope); - if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); - return $linkNode; - }; - } + forEach(element, function(elm) { + toAdd && jqLiteAddClass(elm, toAdd); + toRemove && jqLiteRemoveClass(elm, toRemove); + }); + postDigestQueue.remove(element); + } + }); - function detectNamespaceForChildElements(parentElement) { - // TODO: Make this detect MathML as well... - var node = parentElement && parentElement[0]; - if (!node) { - return 'html'; - } else { - return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html'; - } + postDigestElements.length = 0; + }); } + }]; +}; - /** - * Compile function matches each node in nodeList against the directives. Once all directives - * for a particular node are collected their compile functions are executed. The compile - * functions return values - the linking functions - are combined into a composite linking - * function, which is the a linking function for the node. - * - * @param {NodeList} nodeList an array of nodes or NodeList to compile - * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the - * scope argument is auto-generated to the new child of the transcluded parent scope. - * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then - * the rootElement must be set the jqLite collection of the compile root. This is - * needed so that the jqLite collection items can be replaced with widgets. - * @param {number=} maxPriority Max directive priority. - * @returns {Function} A composite linking function of all of the matched directives or null. - */ - function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, - previousCompileContext) { - var linkFns = [], - attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; - - for (var i = 0; i < nodeList.length; i++) { - attrs = new Attributes(); +/** + * @ngdoc provider + * @name $animateProvider + * + * @description + * Default implementation of $animate that doesn't perform any animations, instead just + * synchronously performs DOM updates and resolves the returned runner promise. + * + * In order to enable animations the `ngAnimate` module has to be loaded. + * + * To see the functional implementation check out `src/ngAnimate/animate.js`. + */ +var $AnimateProvider = ['$provide', function($provide) { + var provider = this; - // we must always refer to nodeList[i] since the nodes can be replaced underneath us. - directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, - ignoreDirective); + this.$$registeredAnimations = Object.create(null); - nodeLinkFn = (directives.length) - ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, - null, [], [], previousCompileContext) - : null; + /** + * @ngdoc method + * @name $animateProvider#register + * + * @description + * Registers a new injectable animation factory function. The factory function produces the + * animation object which contains callback functions for each event that is expected to be + * animated. + * + * * `eventFn`: `function(element, ... , doneFunction, options)` + * The element to animate, the `doneFunction` and the options fed into the animation. Depending + * on the type of animation additional arguments will be injected into the animation function. The + * list below explains the function signatures for the different animation methods: + * + * - setClass: function(element, addedClasses, removedClasses, doneFunction, options) + * - addClass: function(element, addedClasses, doneFunction, options) + * - removeClass: function(element, removedClasses, doneFunction, options) + * - enter, leave, move: function(element, doneFunction, options) + * - animate: function(element, fromStyles, toStyles, doneFunction, options) + * + * Make sure to trigger the `doneFunction` once the animation is fully complete. + * + * ```js + * return { + * //enter, leave, move signature + * eventFn : function(element, done, options) { + * //code to run the animation + * //once complete, then run done() + * return function endFunction(wasCancelled) { + * //code to cancel the animation + * } + * } + * } + * ``` + * + * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to). + * @param {Function} factory The factory function that will be executed to return the animation + * object. + */ + this.register = function(name, factory) { + if (name && name.charAt(0) !== '.') { + throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name); + } - if (nodeLinkFn && nodeLinkFn.scope) { - compile.$$addScopeClass(attrs.$$element); - } + var key = name + '-animation'; + provider.$$registeredAnimations[name.substr(1)] = key; + $provide.factory(key, factory); + }; - childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || - !(childNodes = nodeList[i].childNodes) || - !childNodes.length) - ? null - : compileNodes(childNodes, - nodeLinkFn ? ( - (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) - && nodeLinkFn.transclude) : transcludeFn); + /** + * @ngdoc method + * @name $animateProvider#classNameFilter + * + * @description + * Sets and/or returns the CSS class regular expression that is checked when performing + * an animation. Upon bootstrap the classNameFilter value is not set at all and will + * therefore enable $animate to attempt to perform an animation on any element that is triggered. + * When setting the `classNameFilter` value, animations will only be performed on elements + * that successfully match the filter expression. This in turn can boost performance + * for low-powered devices as well as applications containing a lot of structural operations. + * @param {RegExp=} expression The className expression which will be checked against all animations + * @return {RegExp} The current CSS className expression value. If null then there is no expression value + */ + this.classNameFilter = function(expression) { + if (arguments.length === 1) { + this.$$classNameFilter = (expression instanceof RegExp) ? expression : null; + if (this.$$classNameFilter) { + var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)"); + if (reservedRegex.test(this.$$classNameFilter.toString())) { + throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME); - if (nodeLinkFn || childLinkFn) { - linkFns.push(i, nodeLinkFn, childLinkFn); - linkFnFound = true; - nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; } - - //use the previous context only for the first element in the virtual group - previousCompileContext = null; } + } + return this.$$classNameFilter; + }; - // return a linking function if we have found anything, null otherwise - return linkFnFound ? compositeLinkFn : null; - - function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { - var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; - var stableNodeList; - - - if (nodeLinkFnFound) { - // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our - // offsets don't get screwed up - var nodeListLength = nodeList.length; - stableNodeList = new Array(nodeListLength); - - // create a sparse array by only copying the elements which have a linkFn - for (i = 0; i < linkFns.length; i+=3) { - idx = linkFns[i]; - stableNodeList[idx] = nodeList[idx]; - } - } else { - stableNodeList = nodeList; + this.$get = ['$$animateQueue', function($$animateQueue) { + function domInsert(element, parentElement, afterElement) { + // if for some reason the previous element was removed + // from the dom sometime before this code runs then let's + // just stick to using the parent element as the anchor + if (afterElement) { + var afterNode = extractElementNode(afterElement); + if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) { + afterElement = null; } + } + afterElement ? afterElement.after(element) : parentElement.prepend(element); + } - for (i = 0, ii = linkFns.length; i < ii;) { - node = stableNodeList[linkFns[i++]]; - nodeLinkFn = linkFns[i++]; - childLinkFn = linkFns[i++]; + /** + * @ngdoc service + * @name $animate + * @description The $animate service exposes a series of DOM utility methods that provide support + * for animation hooks. The default behavior is the application of DOM operations, however, + * when an animation is detected (and animations are enabled), $animate will do the heavy lifting + * to ensure that animation runs with the triggered DOM operation. + * + * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't + * included and only when it is active then the animation hooks that `$animate` triggers will be + * functional. Once active then all structural `ng-` directives will trigger animations as they perform + * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`, + * `ngShow`, `ngHide` and `ngMessages` also provide support for animations. + * + * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives. + * + * To learn more about enabling animation support, click here to visit the + * {@link ngAnimate ngAnimate module page}. + */ + return { + // we don't call it directly since non-existant arguments may + // be interpreted as null within the sub enabled function - if (nodeLinkFn) { - if (nodeLinkFn.scope) { - childScope = scope.$new(); - compile.$$addScopeInfo(jqLite(node), childScope); - } else { - childScope = scope; - } + /** + * + * @ngdoc method + * @name $animate#on + * @kind function + * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...) + * has fired on the given element or among any of its children. Once the listener is fired, the provided callback + * is fired with the following params: + * + * ```js + * $animate.on('enter', container, + * function callback(element, phase) { + * // cool we detected an enter animation within the container + * } + * ); + * ``` + * + * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself + * as well as among its children + * @param {Function} callback the callback function that will be fired when the listener is triggered + * + * The arguments present in the callback function are: + * * `element` - The captured DOM element that the animation was fired on. + * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends). + */ + on: $$animateQueue.on, - if (nodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn( - scope, nodeLinkFn.transclude, parentBoundTranscludeFn, - nodeLinkFn.elementTranscludeOnThisElement); + /** + * + * @ngdoc method + * @name $animate#off + * @kind function + * @description Deregisters an event listener based on the event which has been associated with the provided element. This method + * can be used in three different ways depending on the arguments: + * + * ```js + * // remove all the animation event listeners listening for `enter` + * $animate.off('enter'); + * + * // remove all the animation event listeners listening for `enter` on the given element and its children + * $animate.off('enter', container); + * + * // remove the event listener function provided by `listenerFn` that is set + * // to listen for `enter` on the given `element` as well as its children + * $animate.off('enter', container, callback); + * ``` + * + * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...) + * @param {DOMElement=} container the container element the event listener was placed on + * @param {Function=} callback the callback function that was registered as the listener + */ + off: $$animateQueue.off, - } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { - childBoundTranscludeFn = parentBoundTranscludeFn; + /** + * @ngdoc method + * @name $animate#pin + * @kind function + * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists + * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the + * element despite being outside the realm of the application or within another application. Say for example if the application + * was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated + * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind + * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association. + * + * Note that this feature is only active when the `ngAnimate` module is used. + * + * @param {DOMElement} element the external element that will be pinned + * @param {DOMElement} parentElement the host parent element that will be associated with the external element + */ + pin: $$animateQueue.pin, - } else if (!parentBoundTranscludeFn && transcludeFn) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); + /** + * + * @ngdoc method + * @name $animate#enabled + * @kind function + * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This + * function can be called in four ways: + * + * ```js + * // returns true or false + * $animate.enabled(); + * + * // changes the enabled state for all animations + * $animate.enabled(false); + * $animate.enabled(true); + * + * // returns true or false if animations are enabled for an element + * $animate.enabled(element); + * + * // changes the enabled state for an element and its children + * $animate.enabled(element, true); + * $animate.enabled(element, false); + * ``` + * + * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state + * @param {boolean=} enabled whether or not the animations will be enabled for the element + * + * @return {boolean} whether or not animations are enabled + */ + enabled: $$animateQueue.enabled, - } else { - childBoundTranscludeFn = null; - } + /** + * @ngdoc method + * @name $animate#cancel + * @kind function + * @description Cancels the provided animation. + * + * @param {Promise} animationPromise The animation promise that is returned when an animation is started. + */ + cancel: function(runner) { + runner.end && runner.end(); + }, - nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn); + /** + * + * @ngdoc method + * @name $animate#enter + * @kind function + * @description Inserts the element into the DOM either after the `after` element (if provided) or + * as the first child within the `parent` element and then triggers an animation. + * A promise is returned that will be resolved during the next digest once the animation + * has completed. + * + * @param {DOMElement} element the element which will be inserted into the DOM + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + enter: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options)); + }, - } else if (childLinkFn) { - childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); - } - } - } - } + /** + * + * @ngdoc method + * @name $animate#move + * @kind function + * @description Inserts (moves) the element into its new position in the DOM either after + * the `after` element (if provided) or as the first child within the `parent` element + * and then triggers an animation. A promise is returned that will be resolved + * during the next digest once the animation has completed. + * + * @param {DOMElement} element the element which will be moved into the new DOM position + * @param {DOMElement} parent the parent element which will append the element as + * a child (so long as the after element is not present) + * @param {DOMElement=} after the sibling element after which the element will be appended + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + move: function(element, parent, after, options) { + parent = parent && jqLite(parent); + after = after && jqLite(after); + parent = parent || after.parent(); + domInsert(element, parent, after); + return $$animateQueue.push(element, 'move', prepareAnimateOptions(options)); + }, - function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) { + /** + * @ngdoc method + * @name $animate#leave + * @kind function + * @description Triggers an animation and then removes the element from the DOM. + * When the function is called a promise is returned that will be resolved during the next + * digest once the animation has completed. + * + * @param {DOMElement} element the element which will be removed from the DOM + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + leave: function(element, options) { + return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() { + element.remove(); + }); + }, - var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { + /** + * @ngdoc method + * @name $animate#addClass + * @kind function + * + * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon + * execution, the addClass operation will only be handled after the next digest and it will not trigger an + * animation if element already contains the CSS class or if the class is removed at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + addClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addclass, className); + return $$animateQueue.push(element, 'addClass', options); + }, - if (!transcludedScope) { - transcludedScope = scope.$new(false, containingScope); - transcludedScope.$$transcluded = true; - } + /** + * @ngdoc method + * @name $animate#removeClass + * @kind function + * + * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon + * execution, the removeClass operation will only be handled after the next digest and it will not trigger an + * animation if element does not contain the CSS class or if the class is added at a later step. + * Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + removeClass: function(element, className, options) { + options = prepareAnimateOptions(options); + options.removeClass = mergeClasses(options.removeClass, className); + return $$animateQueue.push(element, 'removeClass', options); + }, - return transcludeFn(transcludedScope, cloneFn, { - parentBoundTranscludeFn: previousBoundTranscludeFn, - transcludeControllers: controllers, - futureParentElement: futureParentElement - }); - }; + /** + * @ngdoc method + * @name $animate#setClass + * @kind function + * + * @description Performs both the addition and removal of a CSS classes on an element and (during the process) + * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and + * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has + * passed. Note that class-based animations are treated differently compared to structural animations + * (like enter, move and leave) since the CSS classes may be added/removed at different points + * depending if CSS or JavaScript animations are used. + * + * @param {DOMElement} element the element which the CSS classes will be applied to + * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces) + * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + setClass: function(element, add, remove, options) { + options = prepareAnimateOptions(options); + options.addClass = mergeClasses(options.addClass, add); + options.removeClass = mergeClasses(options.removeClass, remove); + return $$animateQueue.push(element, 'setClass', options); + }, - return boundTranscludeFn; - } + /** + * @ngdoc method + * @name $animate#animate + * @kind function + * + * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element. + * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take + * on the provided styles. For example, if a transition animation is set for the given className then the provided from and + * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles + * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter). + * + * @param {DOMElement} element the element which the CSS styles will be applied to + * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation. + * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation. + * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If + * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element. + * (Note that if no animation is detected then this value will not be appplied to the element.) + * @param {object=} options an optional collection of options/styles that will be applied to the element + * + * @return {Promise} the animation callback promise + */ + animate: function(element, from, to, className, options) { + options = prepareAnimateOptions(options); + options.from = options.from ? extend(options.from, from) : from; + options.to = options.to ? extend(options.to, to) : to; - /** - * Looks for directives on the given node and adds them to the directive collection which is - * sorted. - * - * @param node Node to search. - * @param directives An array to which the directives are added to. This array is sorted before - * the function returns. - * @param attrs The shared attrs object which is used to populate the normalized attributes. - * @param {number=} maxPriority Max directive priority. - */ - function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { - var nodeType = node.nodeType, - attrsMap = attrs.$attr, - match, - className; + className = className || 'ng-inline-animate'; + options.tempClasses = mergeClasses(options.tempClasses, className); + return $$animateQueue.push(element, 'animate', options); + } + }; + }]; +}]; - switch (nodeType) { - case NODE_TYPE_ELEMENT: /* Element */ - // use the node name: <directive> - addDirective(directives, - directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective); +function $$AsyncCallbackProvider() { + this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) { + return $$rAF.supported + ? function(fn) { return $$rAF(fn); } + : function(fn) { + return $timeout(fn, 0, false); + }; + }]; +} - // iterate over the attributes - for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, - j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { - var attrStartName = false; - var attrEndName = false; +/* global stripHash: true */ - attr = nAttrs[j]; - name = attr.name; - value = trim(attr.value); +/** + * ! This is a private undocumented service ! + * + * @name $browser + * @requires $log + * @description + * This object has two goals: + * + * - hide all the global state in the browser caused by the window object + * - abstract away all the browser specific features and inconsistencies + * + * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` + * service, which can be used for convenient testing of the application without the interaction with + * the real browser apis. + */ +/** + * @param {object} window The global window object. + * @param {object} document jQuery wrapped document. + * @param {object} $log window.console or an object with the same interface. + * @param {object} $sniffer $sniffer service + */ +function Browser(window, document, $log, $sniffer) { + var self = this, + rawDocument = document[0], + location = window.location, + history = window.history, + setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + pendingDeferIds = {}; - // support ngAttr attribute binding - ngAttrName = directiveNormalize(name); - if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { - name = name.replace(PREFIX_REGEXP, '') - .substr(8).replace(/_(.)/g, function(match, letter) { - return letter.toUpperCase(); - }); - } + self.isMock = false; - var directiveNName = ngAttrName.replace(/(Start|End)$/, ''); - if (directiveIsMultiElement(directiveNName)) { - if (ngAttrName === directiveNName + 'Start') { - attrStartName = name; - attrEndName = name.substr(0, name.length - 5) + 'end'; - name = name.substr(0, name.length - 6); - } - } + var outstandingRequestCount = 0; + var outstandingRequestCallbacks = []; - nName = directiveNormalize(name.toLowerCase()); - attrsMap[nName] = name; - if (isNgAttr || !attrs.hasOwnProperty(nName)) { - attrs[nName] = value; - if (getBooleanAttrName(node, nName)) { - attrs[nName] = true; // presence means true - } - } - addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); - addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, - attrEndName); - } + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = completeOutstandingRequest; + self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; - // use class as directive - className = node.className; - if (isObject(className)) { - // Maybe SVGAnimatedString - className = className.animVal; - } - if (isString(className) && className !== '') { - while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { - nName = directiveNormalize(match[2]); - if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) { - attrs[nName] = trim(match[3]); - } - className = className.substr(match.index + match[0].length); - } - } - break; - case NODE_TYPE_TEXT: /* Text Node */ - addTextInterpolateDirective(directives, node.nodeValue); - break; - case NODE_TYPE_COMMENT: /* Comment */ + /** + * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` + * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. + */ + function completeOutstandingRequest(fn) { + try { + fn.apply(null, sliceArgs(arguments, 1)); + } finally { + outstandingRequestCount--; + if (outstandingRequestCount === 0) { + while (outstandingRequestCallbacks.length) { try { - match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); - if (match) { - nName = directiveNormalize(match[1]); - if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { - attrs[nName] = trim(match[2]); - } - } + outstandingRequestCallbacks.pop()(); } catch (e) { - // turns out that under some circumstances IE9 throws errors when one attempts to read - // comment's node value. - // Just ignore it and continue. (Can't seem to reproduce in test case.) + $log.error(e); } - break; + } } - - directives.sort(byPriority); - return directives; } + } - /** - * Given a node with an directive-start it collects all of the siblings until it finds - * directive-end. - * @param node - * @param attrStart - * @param attrEnd - * @returns {*} - */ - function groupScan(node, attrStart, attrEnd) { - var nodes = []; - var depth = 0; - if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { - do { - if (!node) { - throw $compileMinErr('uterdir', - "Unterminated attribute, found '{0}' but no matching '{1}' found.", - attrStart, attrEnd); - } - if (node.nodeType == NODE_TYPE_ELEMENT) { - if (node.hasAttribute(attrStart)) depth++; - if (node.hasAttribute(attrEnd)) depth--; - } - nodes.push(node); - node = node.nextSibling; - } while (depth > 0); - } else { - nodes.push(node); - } + function getHash(url) { + var index = url.indexOf('#'); + return index === -1 ? '' : url.substr(index); + } - return jqLite(nodes); + /** + * @private + * Note: this method is used only by scenario runner + * TODO(vojta): prefix this method with $$ ? + * @param {function()} callback Function that will be called when no outstanding request + */ + self.notifyWhenNoOutstandingRequests = function(callback) { + if (outstandingRequestCount === 0) { + callback(); + } else { + outstandingRequestCallbacks.push(callback); } + }; - /** - * Wrapper for linking function which converts normal linking function into a grouped - * linking function. - * @param linkFn - * @param attrStart - * @param attrEnd - * @returns {Function} - */ - function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { - return function(scope, element, attrs, controllers, transcludeFn) { - element = groupScan(element[0], attrStart, attrEnd); - return linkFn(scope, element, attrs, controllers, transcludeFn); - }; - } + ////////////////////////////////////////////////////////////// + // URL API + ////////////////////////////////////////////////////////////// - /** - * Once the directives have been collected, their compile functions are executed. This method - * is responsible for inlining directive templates as well as terminating the application - * of the directives if the terminal directive has been reached. - * - * @param {Array} directives Array of collected directives to execute their compile function. - * this needs to be pre-sorted by priority order. - * @param {Node} compileNode The raw DOM node to apply the compile functions to - * @param {Object} templateAttrs The shared attribute function - * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the - * scope argument is auto-generated to the new - * child of the transcluded parent scope. - * @param {JQLite} jqCollection If we are working on the root of the compile tree then this - * argument has the root jqLite array so that we can replace nodes - * on it. - * @param {Object=} originalReplaceDirective An optional directive that will be ignored when - * compiling the transclusion. - * @param {Array.<Function>} preLinkFns - * @param {Array.<Function>} postLinkFns - * @param {Object} previousCompileContext Context used for previous compilation of the current - * node - * @returns {Function} linkFn - */ - function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, - jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, - previousCompileContext) { - previousCompileContext = previousCompileContext || {}; + var cachedState, lastHistoryState, + lastBrowserUrl = location.href, + baseElement = document.find('base'), + reloadLocation = null; - var terminalPriority = -Number.MAX_VALUE, - newScopeDirective, - controllerDirectives = previousCompileContext.controllerDirectives, - controllers, - newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, - templateDirective = previousCompileContext.templateDirective, - nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, - hasTranscludeDirective = false, - hasTemplate = false, - hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, - $compileNode = templateAttrs.$$element = jqLite(compileNode), - directive, - directiveName, - $template, - replaceDirective = originalReplaceDirective, - childTranscludeFn = transcludeFn, - linkFn, - directiveValue; - - // executes all directives on the current element - for (var i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - var attrStart = directive.$$start; - var attrEnd = directive.$$end; - - // collect multiblock sections - if (attrStart) { - $compileNode = groupScan(compileNode, attrStart, attrEnd); - } - $template = undefined; + cacheState(); + lastHistoryState = cachedState; - if (terminalPriority > directive.priority) { - break; // prevent further processing of directives - } + /** + * @name $browser#url + * + * @description + * GETTER: + * Without any argument, this method just returns current value of location.href. + * + * SETTER: + * With at least one argument, this method sets url to new value. + * If html5 history api supported, pushState/replaceState is used, otherwise + * location.href/location.replace is used. + * Returns its own instance to allow chaining + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to change url. + * + * @param {string} url New url (when used as setter) + * @param {boolean=} replace Should new url replace current history record? + * @param {object=} state object to use with pushState/replaceState + */ + self.url = function(url, replace, state) { + // In modern browsers `history.state` is `null` by default; treating it separately + // from `undefined` would cause `$browser.url('/foo')` to change `history.state` + // to undefined via `pushState`. Instead, let's change `undefined` to `null` here. + if (isUndefined(state)) { + state = null; + } - if (directiveValue = directive.scope) { + // Android Browser BFCache causes location, history reference to become stale. + if (location !== window.location) location = window.location; + if (history !== window.history) history = window.history; - // skip the check for directives with async templates, we'll check the derived sync - // directive when the template arrives - if (!directive.templateUrl) { - if (isObject(directiveValue)) { - // This directive is trying to add an isolated scope. - // Check that there is no scope of any kind already - assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective, - directive, $compileNode); - newIsolateScopeDirective = directive; - } else { - // This directive is trying to add a child scope. - // Check that there is no isolated scope already - assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, - $compileNode); - } - } + // setter + if (url) { + var sameState = lastHistoryState === state; - newScopeDirective = newScopeDirective || directive; + // Don't change anything if previous and current URLs and states match. This also prevents + // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode. + // See https://github.com/angular/angular.js/commit/ffb2701 + if (lastBrowserUrl === url && (!$sniffer.history || sameState)) { + return self; + } + var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url); + lastBrowserUrl = url; + lastHistoryState = state; + // Don't use history API if only the hash changed + // due to a bug in IE10/IE11 which leads + // to not firing a `hashchange` nor `popstate` event + // in some cases (see #9143). + if ($sniffer.history && (!sameBase || !sameState)) { + history[replace ? 'replaceState' : 'pushState'](state, '', url); + cacheState(); + // Do the assignment again so that those two variables are referentially identical. + lastHistoryState = cachedState; + } else { + if (!sameBase || reloadLocation) { + reloadLocation = url; } - - directiveName = directive.name; - - if (!directive.templateUrl && directive.controller) { - directiveValue = directive.controller; - controllerDirectives = controllerDirectives || {}; - assertNoDuplicate("'" + directiveName + "' controller", - controllerDirectives[directiveName], directive, $compileNode); - controllerDirectives[directiveName] = directive; + if (replace) { + location.replace(url); + } else if (!sameBase) { + location.href = url; + } else { + location.hash = getHash(url); } + } + return self; + // getter + } else { + // - reloadLocation is needed as browsers don't allow to read out + // the new location.href if a reload happened. + // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 + return reloadLocation || location.href.replace(/%27/g,"'"); + } + }; - if (directiveValue = directive.transclude) { - hasTranscludeDirective = true; - - // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. - // This option should only be used by directives that know how to safely handle element transclusion, - // where the transcluded nodes are added or replaced after linking. - if (!directive.$$tlb) { - assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); - nonTlbTranscludeDirective = directive; - } + /** + * @name $browser#state + * + * @description + * This method is a getter. + * + * Return history.state or null if history.state is undefined. + * + * @returns {object} state + */ + self.state = function() { + return cachedState; + }; - if (directiveValue == 'element') { - hasElementTranscludeDirective = true; - terminalPriority = directive.priority; - $template = $compileNode; - $compileNode = templateAttrs.$$element = - jqLite(document.createComment(' ' + directiveName + ': ' + - templateAttrs[directiveName] + ' ')); - compileNode = $compileNode[0]; - replaceWith(jqCollection, sliceArgs($template), compileNode); + var urlChangeListeners = [], + urlChangeInit = false; - childTranscludeFn = compile($template, transcludeFn, terminalPriority, - replaceDirective && replaceDirective.name, { - // Don't pass in: - // - controllerDirectives - otherwise we'll create duplicates controllers - // - newIsolateScopeDirective or templateDirective - combining templates with - // element transclusion doesn't make sense. - // - // We need only nonTlbTranscludeDirective so that we prevent putting transclusion - // on the same element more than once. - nonTlbTranscludeDirective: nonTlbTranscludeDirective - }); - } else { - $template = jqLite(jqLiteClone(compileNode)).contents(); - $compileNode.empty(); // clear contents - childTranscludeFn = compile($template, transcludeFn); - } - } + function cacheStateAndFireUrlChange() { + cacheState(); + fireUrlChange(); + } - if (directive.template) { - hasTemplate = true; - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; + function getCurrentState() { + try { + return history.state; + } catch (e) { + // MSIE can reportedly throw when there is no state (UNCONFIRMED). + } + } - directiveValue = (isFunction(directive.template)) - ? directive.template($compileNode, templateAttrs) - : directive.template; + // This variable should be used *only* inside the cacheState function. + var lastCachedState = null; + function cacheState() { + // This should be the only place in $browser where `history.state` is read. + cachedState = getCurrentState(); + cachedState = isUndefined(cachedState) ? null : cachedState; - directiveValue = denormalizeTemplate(directiveValue); + // Prevent callbacks fo fire twice if both hashchange & popstate were fired. + if (equals(cachedState, lastCachedState)) { + cachedState = lastCachedState; + } + lastCachedState = cachedState; + } - if (directive.replace) { - replaceDirective = directive; - if (jqLiteIsTextNode(directiveValue)) { - $template = []; - } else { - $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); - } - compileNode = $template[0]; + function fireUrlChange() { + if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) { + return; + } - if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { - throw $compileMinErr('tplrt', - "Template for directive '{0}' must have exactly one root element. {1}", - directiveName, ''); - } + lastBrowserUrl = self.url(); + lastHistoryState = cachedState; + forEach(urlChangeListeners, function(listener) { + listener(self.url(), cachedState); + }); + } - replaceWith(jqCollection, $compileNode, compileNode); + /** + * @name $browser#onUrlChange + * + * @description + * Register callback function that will be called, when url changes. + * + * It's only called when the url is changed from outside of angular: + * - user types different url into address bar + * - user clicks on history (forward/back) button + * - user clicks on a link + * + * It's not called when url is changed by $browser.url() method + * + * The listener gets called with new url as parameter. + * + * NOTE: this api is intended for use only by the $location service. Please use the + * {@link ng.$location $location service} to monitor url changes in angular apps. + * + * @param {function(string)} listener Listener function to be called when url changes. + * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. + */ + self.onUrlChange = function(callback) { + // TODO(vojta): refactor to use node's syntax for events + if (!urlChangeInit) { + // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) + // don't fire popstate when user change the address bar and don't fire hashchange when url + // changed by push/replaceState - var newTemplateAttrs = {$attr: {}}; + // html5 history api - popstate event + if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange); + // hashchange event + jqLite(window).on('hashchange', cacheStateAndFireUrlChange); - // combine directives from the original node and from the template: - // - take the array of directives for this element - // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed) - // - collect directives from the template and sort them by priority - // - combine directives as: processed + template + unprocessed - var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); - var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + urlChangeInit = true; + } - if (newIsolateScopeDirective) { - markDirectivesAsIsolate(templateDirectives); - } - directives = directives.concat(templateDirectives).concat(unprocessedDirectives); - mergeTemplateAttributes(templateAttrs, newTemplateAttrs); + urlChangeListeners.push(callback); + return callback; + }; - ii = directives.length; - } else { - $compileNode.html(directiveValue); - } - } + /** + * @private + * Remove popstate and hashchange handler from window. + * + * NOTE: this api is intended for use only by $rootScope. + */ + self.$$applicationDestroyed = function() { + jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange); + }; - if (directive.templateUrl) { - hasTemplate = true; - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; + /** + * Checks whether the url has changed outside of Angular. + * Needs to be exported to be able to check for changes that have been done in sync, + * as hashchange/popstate events fire in async. + */ + self.$$checkUrlChange = fireUrlChange; - if (directive.replace) { - replaceDirective = directive; - } + ////////////////////////////////////////////////////////////// + // Misc API + ////////////////////////////////////////////////////////////// - nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, - templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { - controllerDirectives: controllerDirectives, - newIsolateScopeDirective: newIsolateScopeDirective, - templateDirective: templateDirective, - nonTlbTranscludeDirective: nonTlbTranscludeDirective - }); - ii = directives.length; - } else if (directive.compile) { - try { - linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); - if (isFunction(linkFn)) { - addLinkFns(null, linkFn, attrStart, attrEnd); - } else if (linkFn) { - addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); - } - } catch (e) { - $exceptionHandler(e, startingTag($compileNode)); - } - } + /** + * @name $browser#baseHref + * + * @description + * Returns current <base href> + * (always relative - without domain) + * + * @returns {string} The current base href + */ + self.baseHref = function() { + var href = baseElement.attr('href'); + return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : ''; + }; - if (directive.terminal) { - nodeLinkFn.terminal = true; - terminalPriority = Math.max(terminalPriority, directive.priority); - } + /** + * @name $browser#defer + * @param {function()} fn A function, who's execution should be deferred. + * @param {number=} [delay=0] of milliseconds to defer the function execution. + * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. + * + * @description + * Executes a fn asynchronously via `setTimeout(fn, delay)`. + * + * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using + * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed + * via `$browser.defer.flush()`. + * + */ + self.defer = function(fn, delay) { + var timeoutId; + outstandingRequestCount++; + timeoutId = setTimeout(function() { + delete pendingDeferIds[timeoutId]; + completeOutstandingRequest(fn); + }, delay || 0); + pendingDeferIds[timeoutId] = true; + return timeoutId; + }; - } - nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; - nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; - nodeLinkFn.elementTranscludeOnThisElement = hasElementTranscludeDirective; - nodeLinkFn.templateOnThisElement = hasTemplate; - nodeLinkFn.transclude = childTranscludeFn; + /** + * @name $browser#defer.cancel + * + * @description + * Cancels a deferred task identified with `deferId`. + * + * @param {*} deferId Token returned by the `$browser.defer` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + self.defer.cancel = function(deferId) { + if (pendingDeferIds[deferId]) { + delete pendingDeferIds[deferId]; + clearTimeout(deferId); + completeOutstandingRequest(noop); + return true; + } + return false; + }; - previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; +} - // might be normal or delayed nodeLinkFn depending on if templateUrl is present - return nodeLinkFn; +function $BrowserProvider() { + this.$get = ['$window', '$log', '$sniffer', '$document', + function($window, $log, $sniffer, $document) { + return new Browser($window, $document, $log, $sniffer); + }]; +} - //////////////////// +/** + * @ngdoc service + * @name $cacheFactory + * + * @description + * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to + * them. + * + * ```js + * + * var cache = $cacheFactory('cacheId'); + * expect($cacheFactory.get('cacheId')).toBe(cache); + * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined(); + * + * cache.put("key", "value"); + * cache.put("another key", "another value"); + * + * // We've specified no options on creation + * expect(cache.info()).toEqual({id: 'cacheId', size: 2}); + * + * ``` + * + * + * @param {string} cacheId Name or id of the newly created cache. + * @param {object=} options Options object that specifies the cache behavior. Properties: + * + * - `{number=}` `capacity` — turns the cache into LRU cache. + * + * @returns {object} Newly created cache object with the following set of methods: + * + * - `{object}` `info()` — Returns id, size, and options of cache. + * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns + * it. + * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. + * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. + * - `{void}` `removeAll()` — Removes all cached values. + * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. + * + * @example + <example module="cacheExampleApp"> + <file name="index.html"> + <div ng-controller="CacheController"> + <input ng-model="newCacheKey" placeholder="Key"> + <input ng-model="newCacheValue" placeholder="Value"> + <button ng-click="put(newCacheKey, newCacheValue)">Cache</button> - function addLinkFns(pre, post, attrStart, attrEnd) { - if (pre) { - if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); - pre.require = directive.require; - pre.directiveName = directiveName; - if (newIsolateScopeDirective === directive || directive.$$isolateScope) { - pre = cloneAndAnnotateFn(pre, {isolateScope: true}); - } - preLinkFns.push(pre); - } - if (post) { - if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); - post.require = directive.require; - post.directiveName = directiveName; - if (newIsolateScopeDirective === directive || directive.$$isolateScope) { - post = cloneAndAnnotateFn(post, {isolateScope: true}); - } - postLinkFns.push(post); - } - } + <p ng-if="keys.length">Cached Values</p> + <div ng-repeat="key in keys"> + <span ng-bind="key"></span> + <span>: </span> + <b ng-bind="cache.get(key)"></b> + </div> + <p>Cache Info</p> + <div ng-repeat="(key, value) in cache.info()"> + <span ng-bind="key"></span> + <span>: </span> + <b ng-bind="value"></b> + </div> + </div> + </file> + <file name="script.js"> + angular.module('cacheExampleApp', []). + controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) { + $scope.keys = []; + $scope.cache = $cacheFactory('cacheId'); + $scope.put = function(key, value) { + if ($scope.cache.get(key) === undefined) { + $scope.keys.push(key); + } + $scope.cache.put(key, value === undefined ? null : value); + }; + }]); + </file> + <file name="style.css"> + p { + margin: 10px 0 3px; + } + </file> + </example> + */ +function $CacheFactoryProvider() { - function getControllers(directiveName, require, $element, elementControllers) { - var value, retrievalMethod = 'data', optional = false; - var $searchElement = $element; - var match; - if (isString(require)) { - match = require.match(REQUIRE_PREFIX_REGEXP); - require = require.substring(match[0].length); + this.$get = function() { + var caches = {}; - if (match[3]) { - if (match[1]) match[3] = null; - else match[1] = match[3]; - } - if (match[1] === '^') { - retrievalMethod = 'inheritedData'; - } else if (match[1] === '^^') { - retrievalMethod = 'inheritedData'; - $searchElement = $element.parent(); - } - if (match[2] === '?') { - optional = true; - } + function cacheFactory(cacheId, options) { + if (cacheId in caches) { + throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId); + } - value = null; + var size = 0, + stats = extend({}, options, {id: cacheId}), + data = {}, + capacity = (options && options.capacity) || Number.MAX_VALUE, + lruHash = {}, + freshEnd = null, + staleEnd = null; - if (elementControllers && retrievalMethod === 'data') { - if (value = elementControllers[require]) { - value = value.instance; - } - } - value = value || $searchElement[retrievalMethod]('$' + require + 'Controller'); + /** + * @ngdoc type + * @name $cacheFactory.Cache + * + * @description + * A cache object used to store and retrieve data, primarily used by + * {@link $http $http} and the {@link ng.directive:script script} directive to cache + * templates and other data. + * + * ```js + * angular.module('superCache') + * .factory('superCache', ['$cacheFactory', function($cacheFactory) { + * return $cacheFactory('super-cache'); + * }]); + * ``` + * + * Example test: + * + * ```js + * it('should behave like a cache', inject(function(superCache) { + * superCache.put('key', 'value'); + * superCache.put('another key', 'another value'); + * + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 2 + * }); + * + * superCache.remove('another key'); + * expect(superCache.get('another key')).toBeUndefined(); + * + * superCache.removeAll(); + * expect(superCache.info()).toEqual({ + * id: 'super-cache', + * size: 0 + * }); + * })); + * ``` + */ + return caches[cacheId] = { - if (!value && !optional) { - throw $compileMinErr('ctreq', - "Controller '{0}', required by directive '{1}', can't be found!", - require, directiveName); + /** + * @ngdoc method + * @name $cacheFactory.Cache#put + * @kind function + * + * @description + * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be + * retrieved later, and incrementing the size of the cache if the key was not already + * present in the cache. If behaving like an LRU cache, it will also remove stale + * entries from the set. + * + * It will not insert undefined values into the cache. + * + * @param {string} key the key under which the cached data is stored. + * @param {*} value the value to store alongside the key. If it is undefined, the key + * will not be stored. + * @returns {*} the value stored. + */ + put: function(key, value) { + if (isUndefined(value)) return; + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); + + refresh(lruEntry); } - return value || null; - } else if (isArray(require)) { - value = []; - forEach(require, function(require) { - value.push(getControllers(directiveName, require, $element, elementControllers)); - }); - } - return value; - } + if (!(key in data)) size++; + data[key] = value; - function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { - var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, - attrs; + if (size > capacity) { + this.remove(staleEnd.key); + } - if (compileNode === linkNode) { - attrs = templateAttrs; - $element = templateAttrs.$$element; - } else { - $element = jqLite(linkNode); - attrs = new Attributes($element, templateAttrs); - } + return value; + }, - if (newIsolateScopeDirective) { - isolateScope = scope.$new(true); - } + /** + * @ngdoc method + * @name $cacheFactory.Cache#get + * @kind function + * + * @description + * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the data to be retrieved + * @returns {*} the value stored. + */ + get: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; - if (boundTranscludeFn) { - // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn` - // is later passed as `parentBoundTranscludeFn` to `publicLinkFn` - transcludeFn = controllersBoundTransclude; - transcludeFn.$$boundTransclude = boundTranscludeFn; - } + if (!lruEntry) return; - if (controllerDirectives) { - // TODO: merge `controllers` and `elementControllers` into single object. - controllers = {}; - elementControllers = {}; - forEach(controllerDirectives, function(directive) { - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }, controllerInstance; - - controller = directive.controller; - if (controller == '@') { - controller = attrs[directive.name]; - } - - controllerInstance = $controller(controller, locals, true, directive.controllerAs); - - // For directives with element transclusion the element is a comment, - // but jQuery .data doesn't support attaching data to comment nodes as it's hard to - // clean up (http://bugs.jquery.com/ticket/8335). - // Instead, we save the controllers for the element in a local hash and attach to .data - // later, once we have the actual element. - elementControllers[directive.name] = controllerInstance; - if (!hasElementTranscludeDirective) { - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); - } - - controllers[directive.name] = controllerInstance; - }); - } + refresh(lruEntry); + } - if (newIsolateScopeDirective) { - compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || - templateDirective === newIsolateScopeDirective.$$originalDirective))); - compile.$$addScopeClass($element, true); + return data[key]; + }, - var isolateScopeController = controllers && controllers[newIsolateScopeDirective.name]; - var isolateBindingContext = isolateScope; - if (isolateScopeController && isolateScopeController.identifier && - newIsolateScopeDirective.bindToController === true) { - isolateBindingContext = isolateScopeController.instance; - } - forEach(isolateScope.$$isolateBindings = newIsolateScopeDirective.$$isolateBindings, function(definition, scopeName) { - var attrName = definition.attrName, - optional = definition.optional, - mode = definition.mode, // @, =, or & - lastValue, - parentGet, parentSet, compare; + /** + * @ngdoc method + * @name $cacheFactory.Cache#remove + * @kind function + * + * @description + * Removes an entry from the {@link $cacheFactory.Cache Cache} object. + * + * @param {string} key the key of the entry to be removed + */ + remove: function(key) { + if (capacity < Number.MAX_VALUE) { + var lruEntry = lruHash[key]; - switch (mode) { + if (!lruEntry) return; - case '@': - attrs.$observe(attrName, function(value) { - isolateBindingContext[scopeName] = value; - }); - attrs.$$observers[attrName].$$scope = scope; - if (attrs[attrName]) { - // If the attribute has been provided then we trigger an interpolation to ensure - // the value is there for use in the link fn - isolateBindingContext[scopeName] = $interpolate(attrs[attrName])(scope); - } - break; + if (lruEntry == freshEnd) freshEnd = lruEntry.p; + if (lruEntry == staleEnd) staleEnd = lruEntry.n; + link(lruEntry.n,lruEntry.p); - case '=': - if (optional && !attrs[attrName]) { - return; - } - parentGet = $parse(attrs[attrName]); - if (parentGet.literal) { - compare = equals; - } else { - compare = function(a, b) { return a === b || (a !== a && b !== b); }; - } - parentSet = parentGet.assign || function() { - // reset the change, or we will throw this exception on every $digest - lastValue = isolateBindingContext[scopeName] = parentGet(scope); - throw $compileMinErr('nonassign', - "Expression '{0}' used with directive '{1}' is non-assignable!", - attrs[attrName], newIsolateScopeDirective.name); - }; - lastValue = isolateBindingContext[scopeName] = parentGet(scope); - var parentValueWatch = function parentValueWatch(parentValue) { - if (!compare(parentValue, isolateBindingContext[scopeName])) { - // we are out of sync and need to copy - if (!compare(parentValue, lastValue)) { - // parent changed and it has precedence - isolateBindingContext[scopeName] = parentValue; - } else { - // if the parent can be assigned then do so - parentSet(scope, parentValue = isolateBindingContext[scopeName]); - } - } - return lastValue = parentValue; - }; - parentValueWatch.$stateful = true; - var unwatch; - if (definition.collection) { - unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); - } else { - unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); - } - isolateScope.$on('$destroy', unwatch); - break; + delete lruHash[key]; + } - case '&': - parentGet = $parse(attrs[attrName]); - isolateBindingContext[scopeName] = function(locals) { - return parentGet(scope, locals); - }; - break; - } - }); - } - if (controllers) { - forEach(controllers, function(controller) { - controller(); - }); - controllers = null; - } + delete data[key]; + size--; + }, - // PRELINKING - for (i = 0, ii = preLinkFns.length; i < ii; i++) { - linkFn = preLinkFns[i]; - invokeLinkFn(linkFn, - linkFn.isolateScope ? isolateScope : scope, - $element, - attrs, - linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), - transcludeFn - ); - } - // RECURSION - // We only pass the isolate scope, if the isolate directive has a template, - // otherwise the child elements do not belong to the isolate directive. - var scopeToChild = scope; - if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { - scopeToChild = isolateScope; - } - childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); + /** + * @ngdoc method + * @name $cacheFactory.Cache#removeAll + * @kind function + * + * @description + * Clears the cache object of any entries. + */ + removeAll: function() { + data = {}; + size = 0; + lruHash = {}; + freshEnd = staleEnd = null; + }, - // POSTLINKING - for (i = postLinkFns.length - 1; i >= 0; i--) { - linkFn = postLinkFns[i]; - invokeLinkFn(linkFn, - linkFn.isolateScope ? isolateScope : scope, - $element, - attrs, - linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), - transcludeFn - ); - } - // This is the function that is injected as `$transclude`. - // Note: all arguments are optional! - function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) { - var transcludeControllers; + /** + * @ngdoc method + * @name $cacheFactory.Cache#destroy + * @kind function + * + * @description + * Destroys the {@link $cacheFactory.Cache Cache} object entirely, + * removing it from the {@link $cacheFactory $cacheFactory} set. + */ + destroy: function() { + data = null; + stats = null; + lruHash = null; + delete caches[cacheId]; + }, - // No scope passed in: - if (!isScope(scope)) { - futureParentElement = cloneAttachFn; - cloneAttachFn = scope; - scope = undefined; - } - if (hasElementTranscludeDirective) { - transcludeControllers = elementControllers; - } - if (!futureParentElement) { - futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; - } - return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + /** + * @ngdoc method + * @name $cacheFactory.Cache#info + * @kind function + * + * @description + * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}. + * + * @returns {object} an object with the following properties: + * <ul> + * <li>**id**: the id of the cache instance</li> + * <li>**size**: the number of entries kept in the cache instance</li> + * <li>**...**: any additional properties from the options object when creating the + * cache.</li> + * </ul> + */ + info: function() { + return extend({}, stats, {size: size}); } - } - } + }; - function markDirectivesAsIsolate(directives) { - // mark all directives as needing isolate scope. - for (var j = 0, jj = directives.length; j < jj; j++) { - directives[j] = inherit(directives[j], {$$isolateScope: true}); - } - } - /** - * looks up the directive and decorates it with exception handling and proper parameters. We - * call this the boundDirective. - * - * @param {string} name name of the directive to look up. - * @param {string} location The directive must be found in specific format. - * String containing any of theses characters: - * - * * `E`: element name - * * `A': attribute - * * `C`: class - * * `M`: comment - * @returns {boolean} true if directive was added. - */ - function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, - endAttrName) { - if (name === ignoreDirective) return null; - var match = null; - if (hasDirectives.hasOwnProperty(name)) { - for (var directive, directives = $injector.get(name + Suffix), - i = 0, ii = directives.length; i < ii; i++) { - try { - directive = directives[i]; - if ((maxPriority === undefined || maxPriority > directive.priority) && - directive.restrict.indexOf(location) != -1) { - if (startAttrName) { - directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); - } - tDirectives.push(directive); - match = directive; - } - } catch (e) { $exceptionHandler(e); } + /** + * makes the `entry` the freshEnd of the LRU linked list + */ + function refresh(entry) { + if (entry != freshEnd) { + if (!staleEnd) { + staleEnd = entry; + } else if (staleEnd == entry) { + staleEnd = entry.n; + } + + link(entry.n, entry.p); + link(entry, freshEnd); + freshEnd = entry; + freshEnd.n = null; } } - return match; - } - /** - * looks up the directive and returns true if it is a multi-element directive, - * and therefore requires DOM nodes between -start and -end markers to be grouped - * together. - * - * @param {string} name name of the directive to look up. - * @returns true if directive was registered as multi-element. - */ - function directiveIsMultiElement(name) { - if (hasDirectives.hasOwnProperty(name)) { - for (var directive, directives = $injector.get(name + Suffix), - i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - if (directive.multiElement) { - return true; - } + /** + * bidirectionally links two entries of the LRU linked list + */ + function link(nextEntry, prevEntry) { + if (nextEntry != prevEntry) { + if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify + if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify } } - return false; } - /** - * When the element is replaced with HTML template then the new attributes - * on the template need to be merged with the existing attributes in the DOM. - * The desired effect is to have both of the attributes present. - * - * @param {object} dst destination attributes (original DOM) - * @param {object} src source attributes (from the directive template) - */ - function mergeTemplateAttributes(dst, src) { - var srcAttr = src.$attr, - dstAttr = dst.$attr, - $element = dst.$$element; - - // reapply the old attributes to the new element - forEach(dst, function(value, key) { - if (key.charAt(0) != '$') { - if (src[key] && src[key] !== value) { - value += (key === 'style' ? ';' : ' ') + src[key]; - } - dst.$set(key, value, true, srcAttr[key]); - } - }); - // copy the new attributes on the old attrs object - forEach(src, function(value, key) { - if (key == 'class') { - safeAddClass($element, value); - dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; - } else if (key == 'style') { - $element.attr('style', $element.attr('style') + ';' + value); - dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value; - // `dst` will never contain hasOwnProperty as DOM parser won't let it. - // You will get an "InvalidCharacterError: DOM Exception 5" error if you - // have an attribute like "has-own-property" or "data-has-own-property", etc. - } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { - dst[key] = value; - dstAttr[key] = srcAttr[key]; - } + /** + * @ngdoc method + * @name $cacheFactory#info + * + * @description + * Get information about all the caches that have been created + * + * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info` + */ + cacheFactory.info = function() { + var info = {}; + forEach(caches, function(cache, cacheId) { + info[cacheId] = cache.info(); }); - } + return info; + }; - function compileTemplateUrl(directives, $compileNode, tAttrs, - $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { - var linkQueue = [], - afterTemplateNodeLinkFn, - afterTemplateChildLinkFn, - beforeTemplateCompileNode = $compileNode[0], - origAsyncDirective = directives.shift(), - derivedSyncDirective = inherit(origAsyncDirective, { - templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective - }), - templateUrl = (isFunction(origAsyncDirective.templateUrl)) - ? origAsyncDirective.templateUrl($compileNode, tAttrs) - : origAsyncDirective.templateUrl, - templateNamespace = origAsyncDirective.templateNamespace; + /** + * @ngdoc method + * @name $cacheFactory#get + * + * @description + * Get access to a cache object by the `cacheId` used when it was created. + * + * @param {string} cacheId Name or id of a cache to access. + * @returns {object} Cache object identified by the cacheId or undefined if no such cache. + */ + cacheFactory.get = function(cacheId) { + return caches[cacheId]; + }; - $compileNode.empty(); - $templateRequest($sce.getTrustedResourceUrl(templateUrl)) - .then(function(content) { - var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; + return cacheFactory; + }; +} - content = denormalizeTemplate(content); +/** + * @ngdoc service + * @name $templateCache + * + * @description + * The first time a template is used, it is loaded in the template cache for quick retrieval. You + * can load templates directly into the cache in a `script` tag, or by consuming the + * `$templateCache` service directly. + * + * Adding via the `script` tag: + * + * ```html + * <script type="text/ng-template" id="templateId.html"> + * <p>This is the content of the template</p> + * </script> + * ``` + * + * **Note:** the `script` tag containing the template does not need to be included in the `head` of + * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE, + * element with ng-app attribute), otherwise the template will be ignored. + * + * Adding via the `$templateCache` service: + * + * ```js + * var myApp = angular.module('myApp', []); + * myApp.run(function($templateCache) { + * $templateCache.put('templateId.html', 'This is the content of the template'); + * }); + * ``` + * + * To retrieve the template later, simply use it in your HTML: + * ```html + * <div ng-include=" 'templateId.html' "></div> + * ``` + * + * or get it via Javascript: + * ```js + * $templateCache.get('templateId.html') + * ``` + * + * See {@link ng.$cacheFactory $cacheFactory}. + * + */ +function $TemplateCacheProvider() { + this.$get = ['$cacheFactory', function($cacheFactory) { + return $cacheFactory('templates'); + }]; +} - if (origAsyncDirective.replace) { - if (jqLiteIsTextNode(content)) { - $template = []; - } else { - $template = removeComments(wrapTemplate(templateNamespace, trim(content))); - } - compileNode = $template[0]; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { - throw $compileMinErr('tplrt', - "Template for directive '{0}' must have exactly one root element. {1}", - origAsyncDirective.name, templateUrl); - } +/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! + * + * DOM-related variables: + * + * - "node" - DOM Node + * - "element" - DOM Element or Node + * - "$node" or "$element" - jqLite-wrapped node or element + * + * + * Compiler related stuff: + * + * - "linkFn" - linking fn of a single directive + * - "nodeLinkFn" - function that aggregates all linking fns for a particular node + * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node + * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) + */ - tempTemplateAttrs = {$attr: {}}; - replaceWith($rootElement, $compileNode, compileNode); - var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); - - if (isObject(origAsyncDirective.scope)) { - markDirectivesAsIsolate(templateDirectives); - } - directives = templateDirectives.concat(directives); - mergeTemplateAttributes(tAttrs, tempTemplateAttrs); - } else { - compileNode = beforeTemplateCompileNode; - $compileNode.html(content); - } - - directives.unshift(derivedSyncDirective); - - afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, - childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, - previousCompileContext); - forEach($rootElement, function(node, i) { - if (node == compileNode) { - $rootElement[i] = $compileNode[0]; - } - }); - afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); - - while (linkQueue.length) { - var scope = linkQueue.shift(), - beforeTemplateLinkNode = linkQueue.shift(), - linkRootElement = linkQueue.shift(), - boundTranscludeFn = linkQueue.shift(), - linkNode = $compileNode[0]; - - if (scope.$$destroyed) continue; - - if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { - var oldClasses = beforeTemplateLinkNode.className; - - if (!(previousCompileContext.hasElementTranscludeDirective && - origAsyncDirective.replace)) { - // it was cloned therefore we have to clone as well. - linkNode = jqLiteClone(compileNode); - } - replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); - - // Copy in CSS classes from original node - safeAddClass(jqLite(linkNode), oldClasses); - } - if (afterTemplateNodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); - } else { - childBoundTranscludeFn = boundTranscludeFn; - } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, - childBoundTranscludeFn); - } - linkQueue = null; - }); - - return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { - var childBoundTranscludeFn = boundTranscludeFn; - if (scope.$$destroyed) return; - if (linkQueue) { - linkQueue.push(scope, - node, - rootElement, - childBoundTranscludeFn); - } else { - if (afterTemplateNodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); - } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn); - } - }; - } - - - /** - * Sorting function for bound directives. - */ - function byPriority(a, b) { - var diff = b.priority - a.priority; - if (diff !== 0) return diff; - if (a.name !== b.name) return (a.name < b.name) ? -1 : 1; - return a.index - b.index; - } - - - function assertNoDuplicate(what, previousDirective, directive, element) { - if (previousDirective) { - throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}', - previousDirective.name, directive.name, what, startingTag(element)); - } - } - - - function addTextInterpolateDirective(directives, text) { - var interpolateFn = $interpolate(text, true); - if (interpolateFn) { - directives.push({ - priority: 0, - compile: function textInterpolateCompileFn(templateNode) { - var templateNodeParent = templateNode.parent(), - hasCompileParent = !!templateNodeParent.length; - - // When transcluding a template that has bindings in the root - // we don't have a parent and thus need to add the class during linking fn. - if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); - - return function textInterpolateLinkFn(scope, node) { - var parent = node.parent(); - if (!hasCompileParent) compile.$$addBindingClass(parent); - compile.$$addBindingInfo(parent, interpolateFn.expressions); - scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { - node[0].nodeValue = value; - }); - }; - } - }); - } - } - - - function wrapTemplate(type, template) { - type = lowercase(type || 'html'); - switch (type) { - case 'svg': - case 'math': - var wrapper = document.createElement('div'); - wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>'; - return wrapper.childNodes[0].childNodes; - default: - return template; - } - } - - - function getTrustedContext(node, attrNormalizedName) { - if (attrNormalizedName == "srcdoc") { - return $sce.HTML; - } - var tag = nodeName_(node); - // maction[xlink:href] can source SVG. It's not limited to <maction>. - if (attrNormalizedName == "xlinkHref" || - (tag == "form" && attrNormalizedName == "action") || - (tag != "img" && (attrNormalizedName == "src" || - attrNormalizedName == "ngSrc"))) { - return $sce.RESOURCE_URL; - } - } - - - function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) { - var trustedContext = getTrustedContext(node, name); - allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing; - - var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing); - - // no interpolation found -> ignore - if (!interpolateFn) return; - - - if (name === "multiple" && nodeName_(node) === "select") { - throw $compileMinErr("selmulti", - "Binding to the 'multiple' attribute is not supported. Element: {0}", - startingTag(node)); - } - - directives.push({ - priority: 100, - compile: function() { - return { - pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = (attr.$$observers || (attr.$$observers = {})); - - if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { - throw $compileMinErr('nodomevents', - "Interpolations for HTML DOM event attributes are disallowed. Please use the " + - "ng- versions (such as ng-click instead of onclick) instead."); - } - - // If the attribute has changed since last $interpolate()ed - var newValue = attr[name]; - if (newValue !== value) { - // we need to interpolate again since the attribute value has been updated - // (e.g. by another directive's compile function) - // ensure unset/empty values make interpolateFn falsy - interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); - value = newValue; - } - - // if attribute was updated so that there is no interpolation going on we don't want to - // register any observers - if (!interpolateFn) return; - - // initialize attr object so that it's ready in case we need the value for isolate - // scope initialization, otherwise the value would not be available from isolate - // directive's linking fn during linking phase - attr[name] = interpolateFn(scope); - - ($$observers[name] || ($$observers[name] = [])).$$inter = true; - (attr.$$observers && attr.$$observers[name].$$scope || scope). - $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { - //special case for class attribute addition + removal - //so that class changes can tap into the animation - //hooks provided by the $animate service. Be sure to - //skip animations when the first digest occurs (when - //both the new and the old values are the same) since - //the CSS classes are the non-interpolated values - if (name === 'class' && newValue != oldValue) { - attr.$updateClass(newValue, oldValue); - } else { - attr.$set(name, newValue); - } - }); - } - }; - } - }); - } - - - /** - * This is a special jqLite.replaceWith, which can replace items which - * have no parents, provided that the containing jqLite collection is provided. - * - * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes - * in the root of the tree. - * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep - * the shell, but replace its DOM node reference. - * @param {Node} newNode The new DOM node. - */ - function replaceWith($rootElement, elementsToRemove, newNode) { - var firstElementToRemove = elementsToRemove[0], - removeCount = elementsToRemove.length, - parent = firstElementToRemove.parentNode, - i, ii; - - if ($rootElement) { - for (i = 0, ii = $rootElement.length; i < ii; i++) { - if ($rootElement[i] == firstElementToRemove) { - $rootElement[i++] = newNode; - for (var j = i, j2 = j + removeCount - 1, - jj = $rootElement.length; - j < jj; j++, j2++) { - if (j2 < jj) { - $rootElement[j] = $rootElement[j2]; - } else { - delete $rootElement[j]; - } - } - $rootElement.length -= removeCount - 1; - - // If the replaced element is also the jQuery .context then replace it - // .context is a deprecated jQuery api, so we should set it only when jQuery set it - // http://api.jquery.com/context/ - if ($rootElement.context === firstElementToRemove) { - $rootElement.context = newNode; - } - break; - } - } - } - - if (parent) { - parent.replaceChild(newNode, firstElementToRemove); - } - - // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it? - var fragment = document.createDocumentFragment(); - fragment.appendChild(firstElementToRemove); - - // Copy over user data (that includes Angular's $scope etc.). Don't copy private - // data here because there's no public interface in jQuery to do that and copying over - // event listeners (which is the main use of private data) wouldn't work anyway. - jqLite(newNode).data(jqLite(firstElementToRemove).data()); - - // Remove data of the replaced element. We cannot just call .remove() - // on the element it since that would deallocate scope that is needed - // for the new node. Instead, remove the data "manually". - if (!jQuery) { - delete jqLite.cache[firstElementToRemove[jqLite.expando]]; - } else { - // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after - // the replaced element. The cleanData version monkey-patched by Angular would cause - // the scope to be trashed and we do need the very same scope to work with the new - // element. However, we cannot just cache the non-patched version and use it here as - // that would break if another library patches the method after Angular does (one - // example is jQuery UI). Instead, set a flag indicating scope destroying should be - // skipped this one time. - skipDestroyOnNextJQueryCleanData = true; - jQuery.cleanData([firstElementToRemove]); - } - - for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { - var element = elementsToRemove[k]; - jqLite(element).remove(); // must do this way to clean up expando - fragment.appendChild(element); - delete elementsToRemove[k]; - } - - elementsToRemove[0] = newNode; - elementsToRemove.length = 1; - } - - - function cloneAndAnnotateFn(fn, annotation) { - return extend(function() { return fn.apply(null, arguments); }, fn, annotation); - } - - - function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { - try { - linkFn(scope, $element, attrs, controllers, transcludeFn); - } catch (e) { - $exceptionHandler(e, startingTag($element)); - } - } - }]; -} - -var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; -/** - * Converts all accepted directives format into proper directive name. - * @param name Name to normalize - */ -function directiveNormalize(name) { - return camelCase(name.replace(PREFIX_REGEXP, '')); -} /** - * @ngdoc type - * @name $compile.directive.Attributes + * @ngdoc service + * @name $compile + * @kind function * * @description - * A shared object between directive compile / linking functions which contains normalized DOM - * element attributes. The values reflect current binding state `{{ }}`. The normalization is - * needed since all of these are treated as equivalent in Angular: + * Compiles an HTML string or DOM into a template and produces a template function, which + * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together. + * + * The compilation is a process of walking the DOM tree and matching DOM elements to + * {@link ng.$compileProvider#directive directives}. + * + * <div class="alert alert-warning"> + * **Note:** This document is an in-depth reference of all directive options. + * For a gentle introduction to directives with examples of common use cases, + * see the {@link guide/directive directive guide}. + * </div> + * + * ## Comprehensive Directive API * + * There are many different options for a directive. + * + * The difference resides in the return value of the factory function. + * You can either return a "Directive Definition Object" (see below) that defines the directive properties, + * or just the `postLink` function (all other properties will have the default values). + * + * <div class="alert alert-success"> + * **Best Practice:** It's recommended to use the "directive definition object" form. + * </div> + * + * Here's an example directive declared with a Directive Definition Object: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * priority: 0, + * template: '<div></div>', // or // function(tElement, tAttrs) { ... }, + * // or + * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, + * transclude: false, + * restrict: 'A', + * templateNamespace: 'html', + * scope: false, + * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, + * controllerAs: 'stringIdentifier', + * bindToController: false, + * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], + * compile: function compile(tElement, tAttrs, transclude) { + * return { + * pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * post: function postLink(scope, iElement, iAttrs, controller) { ... } + * } + * // or + * // return function postLink( ... ) { ... } + * }, + * // or + * // link: { + * // pre: function preLink(scope, iElement, iAttrs, controller) { ... }, + * // post: function postLink(scope, iElement, iAttrs, controller) { ... } + * // } + * // or + * // link: function postLink( ... ) { ... } + * }; + * return directiveDefinitionObject; + * }); * ``` - * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a"> + * + * <div class="alert alert-warning"> + * **Note:** Any unspecified options will use the default value. You can see the default values below. + * </div> + * + * Therefore the above can be simplified as: + * + * ```js + * var myModule = angular.module(...); + * + * myModule.directive('directiveName', function factory(injectables) { + * var directiveDefinitionObject = { + * link: function postLink(scope, iElement, iAttrs) { ... } + * }; + * return directiveDefinitionObject; + * // or + * // return function postLink(scope, iElement, iAttrs) { ... } + * }); * ``` - */ - -/** - * @ngdoc property - * @name $compile.directive.Attributes#$attr * - * @description - * A map of DOM element attribute names to the normalized name. This is - * needed to do reverse lookup from normalized name back to actual name. - */ - - -/** - * @ngdoc method - * @name $compile.directive.Attributes#$set - * @kind function * - * @description - * Set DOM element attribute value. * + * ### Directive Definition Object * - * @param {string} name Normalized element attribute name of the property to modify. The name is - * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr} - * property to the original name. - * @param {string} value Value to set the attribute to. The value can be an interpolated string. - */ - - - -/** - * Closure compiler type information - */ - -function nodesetLinkingFn( - /* angular.Scope */ scope, - /* NodeList */ nodeList, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -) {} - -function directiveLinkingFn( - /* nodesetLinkingFn */ nodesetLinkingFn, - /* angular.Scope */ scope, - /* Node */ node, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -) {} - -function tokenDifference(str1, str2) { - var values = '', - tokens1 = str1.split(/\s+/), - tokens2 = str2.split(/\s+/); - - outer: - for (var i = 0; i < tokens1.length; i++) { - var token = tokens1[i]; - for (var j = 0; j < tokens2.length; j++) { - if (token == tokens2[j]) continue outer; - } - values += (values.length > 0 ? ' ' : '') + token; - } - return values; -} - -function removeComments(jqNodes) { - jqNodes = jqLite(jqNodes); - var i = jqNodes.length; - - if (i <= 1) { - return jqNodes; - } - - while (i--) { - var node = jqNodes[i]; - if (node.nodeType === NODE_TYPE_COMMENT) { - splice.call(jqNodes, i, 1); - } - } - return jqNodes; -} - -var $controllerMinErr = minErr('$controller'); - -/** - * @ngdoc provider - * @name $controllerProvider - * @description - * The {@link ng.$controller $controller service} is used by Angular to create new - * controllers. + * The directive definition object provides instructions to the {@link ng.$compile + * compiler}. The attributes are: * - * This provider allows controller registration via the - * {@link ng.$controllerProvider#register register} method. - */ -function $ControllerProvider() { - var controllers = {}, - globals = false, - CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; - - - /** - * @ngdoc method - * @name $controllerProvider#register - * @param {string|Object} name Controller name, or an object map of controllers where the keys are - * the names and the values are the constructors. - * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI - * annotations in the array notation). - */ - this.register = function(name, constructor) { - assertNotHasOwnProperty(name, 'controller'); - if (isObject(name)) { - extend(controllers, name); - } else { - controllers[name] = constructor; - } - }; - - /** - * @ngdoc method - * @name $controllerProvider#allowGlobals - * @description If called, allows `$controller` to find controller constructors on `window` - */ - this.allowGlobals = function() { - globals = true; - }; - - - this.$get = ['$injector', '$window', function($injector, $window) { - - /** - * @ngdoc service - * @name $controller - * @requires $injector - * - * @param {Function|string} constructor If called with a function then it's considered to be the - * controller constructor function. Otherwise it's considered to be a string which is used - * to retrieve the controller constructor using the following steps: - * - * * check if a controller with given name is registered via `$controllerProvider` - * * check if evaluating the string on the current scope returns a constructor - * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global - * `window` object (not recommended) - * - * The string can use the `controller as property` syntax, where the controller instance is published - * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this - * to work correctly. - * - * @param {Object} locals Injection locals for Controller. - * @return {Object} Instance of given controller. - * - * @description - * `$controller` service is responsible for instantiating controllers. - * - * It's just a simple call to {@link auto.$injector $injector}, but extracted into - * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). - */ - return function(expression, locals, later, ident) { - // PRIVATE API: - // param `later` --- indicates that the controller's constructor is invoked at a later time. - // If true, $controller will allocate the object with the correct - // prototype chain, but will not invoke the controller until a returned - // callback is invoked. - // param `ident` --- An optional label which overrides the label parsed from the controller - // expression, if any. - var instance, match, constructor, identifier; - later = later === true; - if (ident && isString(ident)) { - identifier = ident; - } - - if (isString(expression)) { - match = expression.match(CNTRL_REG); - if (!match) { - throw $controllerMinErr('ctrlfmt', - "Badly formed controller string '{0}'. " + - "Must match `__name__ as __id__` or `__name__`.", expression); - } - constructor = match[1], - identifier = identifier || match[3]; - expression = controllers.hasOwnProperty(constructor) - ? controllers[constructor] - : getter(locals.$scope, constructor, true) || - (globals ? getter($window, constructor, true) : undefined); - - assertArgFn(expression, constructor, true); - } - - if (later) { - // Instantiate controller later: - // This machinery is used to create an instance of the object before calling the - // controller's constructor itself. - // - // This allows properties to be added to the controller before the constructor is - // invoked. Primarily, this is used for isolate scope bindings in $compile. - // - // This feature is not intended for use by applications, and is thus not documented - // publicly. - // Object creation: http://jsperf.com/create-constructor/2 - var controllerPrototype = (isArray(expression) ? - expression[expression.length - 1] : expression).prototype; - instance = Object.create(controllerPrototype || null); - - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - - return extend(function() { - $injector.invoke(expression, instance, locals, constructor); - return instance; - }, { - instance: instance, - identifier: identifier - }); - } - - instance = $injector.instantiate(expression, locals, constructor); - - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - - return instance; - }; - - function addIdentifier(locals, identifier, instance, name) { - if (!(locals && isObject(locals.$scope))) { - throw minErr('$controller')('noscp', - "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", - name, identifier); - } - - locals.$scope[identifier] = instance; - } - }]; -} - -/** - * @ngdoc service - * @name $document - * @requires $window + * #### `multiElement` + * When this property is set to true, the HTML compiler will collect DOM nodes between + * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them + * together as the directive elements. It is recommended that this feature be used on directives + * which are not strictly behavioural (such as {@link ngClick}), and which + * do not manipulate or replace child nodes (such as {@link ngInclude}). * - * @description - * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object. + * #### `priority` + * When there are multiple directives defined on a single DOM element, sometimes it + * is necessary to specify the order in which the directives are applied. The `priority` is used + * to sort the directives before their `compile` functions get called. Priority is defined as a + * number. Directives with greater numerical `priority` are compiled first. Pre-link functions + * are also run in priority order, but post-link functions are run in reverse order. The order + * of directives with the same priority is undefined. The default priority is `0`. * - * @example - <example module="documentExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <p>$document title: <b ng-bind="title"></b></p> - <p>window.document title: <b ng-bind="windowTitle"></b></p> - </div> - </file> - <file name="script.js"> - angular.module('documentExample', []) - .controller('ExampleController', ['$scope', '$document', function($scope, $document) { - $scope.title = $document[0].title; - $scope.windowTitle = angular.element(window.document)[0].title; - }]); - </file> - </example> - */ -function $DocumentProvider() { - this.$get = ['$window', function(window) { - return jqLite(window.document); - }]; -} - -/** - * @ngdoc service - * @name $exceptionHandler - * @requires ng.$log + * #### `terminal` + * If set to true then the current `priority` will be the last set of directives + * which will execute (any directives at the current priority will still execute + * as the order of execution on same `priority` is undefined). Note that expressions + * and other directives used in the directive's template will also be excluded from execution. * - * @description - * Any uncaught exception in angular expressions is delegated to this service. - * The default implementation simply delegates to `$log.error` which logs it into - * the browser console. + * #### `scope` + * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the + * same element request a new scope, only one new scope is created. The new scope rule does not + * apply for the root of the template since the root of the template always gets a new scope. * - * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by - * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. + * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from + * normal scope in that it does not prototypically inherit from the parent scope. This is useful + * when creating reusable components, which should not accidentally read or modify data in the + * parent scope. * - * ## Example: + * The 'isolate' scope takes an object hash which defines a set of local scope properties + * derived from the parent scope. These local properties are useful for aliasing values for + * templates. Locals definition is a hash of local scope property to its source: + * + * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is + * always a string since DOM attributes are strings. If no `attr` name is specified then the + * attribute name is assumed to be the same as the local name. + * Given `<widget my-attr="hello {{name}}">` and widget definition + * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect + * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the + * `localName` property on the widget scope. The `name` is read from the parent scope (not + * component scope). + * + * * `=` or `=attr` - set up bi-directional binding between a local scope property and the + * parent scope property of name defined via the value of the `attr` attribute. If no `attr` + * name is specified then the attribute name is assumed to be the same as the local name. + * Given `<widget my-attr="parentModel">` and widget definition of + * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the + * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected + * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent + * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You + * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If + * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use + * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional). + * + * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope. + * If no `attr` name is specified then the attribute name is assumed to be the same as the + * local name. Given `<widget my-attr="count = count + value">` and widget definition of + * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to + * a function wrapper for the `count = count + value` expression. Often it's desirable to + * pass data from the isolated scope via an expression to the parent scope, this can be + * done by passing a map of local variable names and values into the expression wrapper fn. + * For example, if the expression is `increment(amount)` then we can specify the amount value + * by calling the `localFn` as `localFn({amount: 22})`. + * + * + * #### `bindToController` + * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will + * allow a component to have its properties bound to the controller, rather than to scope. When the controller + * is instantiated, the initial values of the isolate scope bindings are already available. + * + * #### `controller` + * Controller constructor function. The controller is instantiated before the + * pre-linking phase and it is shared with other directives (see + * `require` attribute). This allows the directives to communicate with each other and augment + * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals: + * + * * `$scope` - Current scope associated with the element + * * `$element` - Current element + * * `$attrs` - Current attributes object for the element + * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope: + * `function([scope], cloneLinkingFn, futureParentElement)`. + * * `scope`: optional argument to override the scope. + * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content. + * * `futureParentElement`: + * * defines the parent to which the `cloneLinkingFn` will add the cloned elements. + * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`. + * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements) + * and when the `cloneLinkinFn` is passed, + * as those elements need to created and cloned in a special way when they are defined outside their + * usual containers (e.g. like `<svg>`). + * * See also the `directive.templateNamespace` property. + * + * + * #### `require` + * Require another directive and inject its controller as the fourth argument to the linking function. The + * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the + * injected argument will be an array in corresponding order. If no such directive can be + * found, or if the directive does not have a controller, then an error is raised (unless no link function + * is specified, in which case error checking is skipped). The name can be prefixed with: + * + * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. + * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. + * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found. + * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found. + * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass + * `null` to the `link` fn if not found. + * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass + * `null` to the `link` fn if not found. + * + * + * #### `controllerAs` + * Identifier name for a reference to the controller in the directive's scope. + * This allows the controller to be referenced from the directive template. The directive + * needs to define a scope for this configuration to be used. Useful in the case when + * directive is used as component. + * + * + * #### `restrict` + * String of subset of `EACM` which restricts the directive to a specific directive + * declaration style. If omitted, the defaults (elements and attributes) are used. + * + * * `E` - Element name (default): `<my-directive></my-directive>` + * * `A` - Attribute (default): `<div my-directive="exp"></div>` + * * `C` - Class: `<div class="my-directive: exp;"></div>` + * * `M` - Comment: `<!-- directive: my-directive exp -->` + * + * + * #### `templateNamespace` + * String representing the document type used by the markup in the template. + * AngularJS needs this information as those elements need to be created and cloned + * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`. + * + * * `html` - All root nodes in the template are HTML. Root nodes may also be + * top-level elements such as `<svg>` or `<math>`. + * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`). + * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`). + * + * If no `templateNamespace` is specified, then the namespace is considered to be `html`. + * + * #### `template` + * HTML markup that may: + * * Replace the contents of the directive's element (default). + * * Replace the directive's element itself (if `replace` is true - DEPRECATED). + * * Wrap the contents of the directive's element (if `transclude` is true). + * + * Value may be: + * + * * A string. For example `<div red-on-hover>{{delete_str}}</div>`. + * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile` + * function api below) and returns a string value. + * + * + * #### `templateUrl` + * This is similar to `template` but the template is loaded from the specified URL, asynchronously. + * + * Because template loading is asynchronous the compiler will suspend compilation of directives on that element + * for later when the template has been resolved. In the meantime it will continue to compile and link + * sibling and parent elements as though this element had not contained any directives. + * + * The compiler does not suspend the entire compilation to wait for templates to be loaded because this + * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the + * case when only one deeply nested directive has `templateUrl`. + * + * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache} + * + * You can specify `templateUrl` as a string representing the URL or as a function which takes two + * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns + * a string value representing the url. In either case, the template URL is passed through {@link + * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}. + * + * + * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0) + * specify what the template should replace. Defaults to `false`. + * + * * `true` - the template will replace the directive's element. + * * `false` - the template will replace the contents of the directive's element. + * + * The replacement process migrates all of the attributes / classes from the old element to the new + * one. See the {@link guide/directive#template-expanding-directive + * Directives Guide} for an example. + * + * There are very few scenarios where element replacement is required for the application function, + * the main one being reusable custom components that are used within SVG contexts + * (because SVG doesn't work with custom elements in the DOM tree). + * + * #### `transclude` + * Extract the contents of the element where the directive appears and make it available to the directive. + * The contents are compiled and provided to the directive as a **transclusion function**. See the + * {@link $compile#transclusion Transclusion} section below. + * + * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the + * directive's element or the entire element: + * + * * `true` - transclude the content (i.e. the child nodes) of the directive's element. + * * `'element'` - transclude the whole of the directive's element including any directives on this + * element that defined at a lower priority than this directive. When used, the `template` + * property is ignored. + * + * + * #### `compile` * * ```js - * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() { - * return function(exception, cause) { - * exception.message += ' (caused by "' + cause + '")'; - * throw exception; - * }; - * }); + * function compile(tElement, tAttrs, transclude) { ... } * ``` * - * This example will override the normal action of `$exceptionHandler`, to make angular - * exceptions fail hard when they happen, instead of just logging to the console. + * The compile function deals with transforming the template DOM. Since most directives do not do + * template transformation, it is not used often. The compile function takes the following arguments: * - * <hr /> - * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind` - * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler} - * (unless executed during a digest). + * * `tElement` - template element - The element where the directive has been declared. It is + * safe to do template transformation on the element and child elements only. * - * If you wish, you can manually delegate exceptions, e.g. - * `try { ... } catch(e) { $exceptionHandler(e); }` + * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared + * between all directive compile functions. * - * @param {Error} exception Exception associated with the error. - * @param {string=} cause optional information about the context in which - * the error was thrown. + * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)` * - */ -function $ExceptionHandlerProvider() { - this.$get = ['$log', function($log) { - return function(exception, cause) { - $log.error.apply($log, arguments); - }; - }]; -} - -var APPLICATION_JSON = 'application/json'; -var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'}; -var JSON_START = /^\[|^\{(?!\{)/; -var JSON_ENDS = { - '[': /]$/, - '{': /}$/ -}; -var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; - -function defaultHttpResponseTransform(data, headers) { - if (isString(data)) { - // Strip json vulnerability protection prefix and trim whitespace - var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim(); - - if (tempData) { - var contentType = headers('Content-Type'); - if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) { - data = fromJson(tempData); - } - } - } - - return data; -} - -function isJsonLike(str) { - var jsonStart = str.match(JSON_START); - return jsonStart && JSON_ENDS[jsonStart[0]].test(str); -} + * <div class="alert alert-warning"> + * **Note:** The template instance and the link instance may be different objects if the template has + * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that + * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration + * should be done in a linking function rather than in a compile function. + * </div> -/** - * Parse headers into key value object + * <div class="alert alert-warning"> + * **Note:** The compile function cannot handle directives that recursively use themselves in their + * own templates or compile functions. Compiling these directives results in an infinite loop and a + * stack overflow errors. * - * @param {string} headers Raw headers as a string - * @returns {Object} Parsed headers as key value object - */ -function parseHeaders(headers) { - var parsed = createMap(), key, val, i; - - if (!headers) return parsed; - - forEach(headers.split('\n'), function(line) { - i = line.indexOf(':'); - key = lowercase(trim(line.substr(0, i))); - val = trim(line.substr(i + 1)); - - if (key) { - parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; - } - }); - - return parsed; -} - + * This can be avoided by manually using $compile in the postLink function to imperatively compile + * a directive's template instead of relying on automatic template compilation via `template` or + * `templateUrl` declaration or manual compilation inside the compile function. + * </div> + * + * <div class="alert alert-danger"> + * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it + * e.g. does not know about the right outer scope. Please use the transclude function that is passed + * to the link function instead. + * </div> -/** - * Returns a function that provides access to parsed headers. + * A compile function can have a return value which can be either a function or an object. * - * Headers are lazy parsed when first requested. - * @see parseHeaders + * * returning a (post-link) function - is equivalent to registering the linking function via the + * `link` property of the config object when the compile function is empty. * - * @param {(string|Object)} headers Headers to provide access to. - * @returns {function(string=)} Returns a getter function which if called with: + * * returning an object with function(s) registered via `pre` and `post` properties - allows you to + * control when a linking function should be called during the linking phase. See info about + * pre-linking and post-linking functions below. * - * - if called with single an argument returns a single header value or null - * - if called with no arguments returns an object containing all headers. - */ -function headersGetter(headers) { - var headersObj = isObject(headers) ? headers : undefined; - - return function(name) { - if (!headersObj) headersObj = parseHeaders(headers); - - if (name) { - var value = headersObj[lowercase(name)]; - if (value === void 0) { - value = null; - } - return value; - } - - return headersObj; - }; -} - - -/** - * Chain all given functions * - * This function is used for both request and response transforming + * #### `link` + * This property is used only if the `compile` property is not defined. * - * @param {*} data Data to transform. - * @param {function(string=)} headers HTTP headers getter fn. - * @param {number} status HTTP status code of the response. - * @param {(Function|Array.<Function>)} fns Function or an array of functions. - * @returns {*} Transformed data. - */ -function transformData(data, headers, status, fns) { - if (isFunction(fns)) - return fns(data, headers, status); - - forEach(fns, function(fn) { - data = fn(data, headers, status); - }); - - return data; -} - - -function isSuccess(status) { - return 200 <= status && status < 300; -} - - -/** - * @ngdoc provider - * @name $httpProvider - * @description - * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service. - * */ -function $HttpProvider() { - /** - * @ngdoc property - * @name $httpProvider#defaults - * @description - * - * Object containing default values for all {@link ng.$http $http} requests. - * - * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`} - * that will provide the cache for all requests who set their `cache` property to `true`. - * If you set the `default.cache = false` then only requests that specify their own custom - * cache object will be cached. See {@link $http#caching $http Caching} for more information. - * - * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. - * Defaults value is `'XSRF-TOKEN'`. - * - * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the - * XSRF token. Defaults value is `'X-XSRF-TOKEN'`. - * - * - **`defaults.headers`** - {Object} - Default headers for all $http requests. - * Refer to {@link ng.$http#setting-http-headers $http} for documentation on - * setting default headers. - * - **`defaults.headers.common`** - * - **`defaults.headers.post`** - * - **`defaults.headers.put`** - * - **`defaults.headers.patch`** - * - **/ - var defaults = this.defaults = { - // transform incoming response data - transformResponse: [defaultHttpResponseTransform], + * ```js + * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... } + * ``` + * + * The link function is responsible for registering DOM listeners as well as updating the DOM. It is + * executed after the template has been cloned. This is where most of the directive logic will be + * put. + * + * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the + * directive for registering {@link ng.$rootScope.Scope#$watch watches}. + * + * * `iElement` - instance element - The element where the directive is to be used. It is safe to + * manipulate the children of the element only in `postLink` function since the children have + * already been linked. + * + * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared + * between all directive linking functions. + * + * * `controller` - the directive's required controller instance(s) - Instances are shared + * among all directives, which allows the directives to use the controllers as a communication + * channel. The exact value depends on the directive's `require` property: + * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one + * * `string`: the controller instance + * * `array`: array of controller instances + * + * If a required controller cannot be found, and it is optional, the instance is `null`, + * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown. + * + * Note that you can also require the directive's own controller - it will be made available like + * like any other controller. + * + * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope. + * This is the same as the `$transclude` + * parameter of directive controllers, see there for details. + * `function([scope], cloneLinkingFn, futureParentElement)`. + * + * #### Pre-linking function + * + * Executed before the child elements are linked. Not safe to do DOM transformation since the + * compiler linking function will fail to locate the correct elements for linking. + * + * #### Post-linking function + * + * Executed after the child elements are linked. + * + * Note that child elements that contain `templateUrl` directives will not have been compiled + * and linked since they are waiting for their template to load asynchronously and their own + * compilation and linking has been suspended until that occurs. + * + * It is safe to do DOM transformation in the post-linking function on elements that are not waiting + * for their async templates to be resolved. + * + * + * ### Transclusion + * + * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and + * copying them to another part of the DOM, while maintaining their connection to the original AngularJS + * scope from where they were taken. + * + * Transclusion is used (often with {@link ngTransclude}) to insert the + * original contents of a directive's element into a specified place in the template of the directive. + * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded + * content has access to the properties on the scope from which it was taken, even if the directive + * has isolated scope. + * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}. + * + * This makes it possible for the widget to have private state for its template, while the transcluded + * content has access to its originating scope. + * + * <div class="alert alert-warning"> + * **Note:** When testing an element transclude directive you must not place the directive at the root of the + * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives + * Testing Transclusion Directives}. + * </div> + * + * #### Transclusion Functions + * + * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion + * function** to the directive's `link` function and `controller`. This transclusion function is a special + * **linking function** that will return the compiled contents linked to a new transclusion scope. + * + * <div class="alert alert-info"> + * If you are just using {@link ngTransclude} then you don't need to worry about this function, since + * ngTransclude will deal with it for us. + * </div> + * + * If you want to manually control the insertion and removal of the transcluded content in your directive + * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery + * object that contains the compiled DOM, which is linked to the correct transclusion scope. + * + * When you call a transclusion function you can pass in a **clone attach function**. This function accepts + * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded + * content and the `scope` is the newly created transclusion scope, to which the clone is bound. + * + * <div class="alert alert-info"> + * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function + * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope. + * </div> + * + * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone + * attach function**: + * + * ```js + * var transcludedContent, transclusionScope; + * + * $transclude(function(clone, scope) { + * element.append(clone); + * transcludedContent = clone; + * transclusionScope = scope; + * }); + * ``` + * + * Later, if you want to remove the transcluded content from your DOM then you should also destroy the + * associated transclusion scope: + * + * ```js + * transcludedContent.remove(); + * transclusionScope.$destroy(); + * ``` + * + * <div class="alert alert-info"> + * **Best Practice**: if you intend to add and remove transcluded content manually in your directive + * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it), + * then you are also responsible for calling `$destroy` on the transclusion scope. + * </div> + * + * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat} + * automatically destroy their transluded clones as necessary so you do not need to worry about this if + * you are simply using {@link ngTransclude} to inject the transclusion into your directive. + * + * + * #### Transclusion Scopes + * + * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion + * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed + * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it + * was taken. + * + * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look + * like this: + * + * ```html + * <div ng-app> + * <div isolate> + * <div transclusion> + * </div> + * </div> + * </div> + * ``` + * + * The `$parent` scope hierarchy will look like this: + * + * ``` + * - $rootScope + * - isolate + * - transclusion + * ``` + * + * but the scopes will inherit prototypically from different scopes to their `$parent`. + * + * ``` + * - $rootScope + * - transclusion + * - isolate + * ``` + * + * + * ### Attributes + * + * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the + * `link()` or `compile()` functions. It has a variety of uses. + * + * accessing *Normalized attribute names:* + * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'. + * the attributes object allows for normalized access to + * the attributes. + * + * * *Directive inter-communication:* All directives share the same instance of the attributes + * object which allows the directives to use the attributes object as inter directive + * communication. + * + * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object + * allowing other directives to read the interpolated value. + * + * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes + * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also + * the only way to easily get the actual value because during the linking phase the interpolation + * hasn't been evaluated yet and so the value is at this time set to `undefined`. + * + * ```js + * function linkingFn(scope, elm, attrs, ctrl) { + * // get the attribute value + * console.log(attrs.ngModel); + * + * // change the attribute + * attrs.$set('ngModel', 'new value'); + * + * // observe changes to interpolated attribute + * attrs.$observe('ngModel', function(value) { + * console.log('ngModel has changed value to ' + value); + * }); + * } + * ``` + * + * ## Example + * + * <div class="alert alert-warning"> + * **Note**: Typically directives are registered with `module.directive`. The example below is + * to illustrate how `$compile` works. + * </div> + * + <example module="compileExample"> + <file name="index.html"> + <script> + angular.module('compileExample', [], function($compileProvider) { + // configure new 'compile' directive by passing a directive + // factory function. The factory function injects the '$compile' + $compileProvider.directive('compile', function($compile) { + // directive factory creates a link function + return function(scope, element, attrs) { + scope.$watch( + function(scope) { + // watch the 'compile' expression for changes + return scope.$eval(attrs.compile); + }, + function(value) { + // when the 'compile' expression changes + // assign it into the current DOM + element.html(value); - // transform outgoing request data - transformRequest: [function(d) { - return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; - }], + // compile the new DOM and link it to the current + // scope. + // NOTE: we only compile .childNodes so that + // we don't get into infinite loop compiling ourselves + $compile(element.contents())(scope); + } + ); + }; + }); + }) + .controller('GreeterController', ['$scope', function($scope) { + $scope.name = 'Angular'; + $scope.html = 'Hello {{name}}'; + }]); + </script> + <div ng-controller="GreeterController"> + <input ng-model="name"> <br/> + <textarea ng-model="html"></textarea> <br/> + <div compile="html"></div> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should auto compile', function() { + var textarea = $('textarea'); + var output = $('div[compile]'); + // The initial state reads 'Hello Angular'. + expect(output.getText()).toBe('Hello Angular'); + textarea.clear(); + textarea.sendKeys('{{name}}!'); + expect(output.getText()).toBe('Angular!'); + }); + </file> + </example> - // default headers - headers: { - common: { - 'Accept': 'application/json, text/plain, */*' - }, - post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), - put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), - patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) - }, + * + * + * @param {string|DOMElement} element Element or HTML string to compile into a template function. + * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. + * + * <div class="alert alert-danger"> + * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it + * e.g. will not use the right outer scope. Please pass the transclude function as a + * `parentBoundTranscludeFn` to the link function instead. + * </div> + * + * @param {number} maxPriority only apply directives lower than given priority (Only effects the + * root element(s), not their children) + * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template + * (a DOM element/tree) to a scope. Where: + * + * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. + * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the + * `template` and call the `cloneAttachFn` function allowing the caller to attach the + * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is + * called as: <br/> `cloneAttachFn(clonedElement, scope)` where: + * + * * `clonedElement` - is a clone of the original `element` passed into the compiler. + * * `scope` - is the current scope with which the linking function is working with. + * + * * `options` - An optional object hash with linking options. If `options` is provided, then the following + * keys may be used to control linking behavior: + * + * * `parentBoundTranscludeFn` - the transclude function made available to + * directives; if given, it will be passed through to the link functions of + * directives found in `element` during compilation. + * * `transcludeControllers` - an object hash with keys that map controller names + * to controller instances; if given, it will make the controllers + * available to directives. + * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add + * the cloned elements; only needed for transcludes that are allowed to contain non html + * elements (e.g. SVG elements). See also the directive.controller property. + * + * Calling the linking function returns the element of the template. It is either the original + * element passed in, or the clone of the element if the `cloneAttachFn` is provided. + * + * After linking the view is not updated until after a call to $digest which typically is done by + * Angular automatically. + * + * If you need access to the bound view, there are two ways to do it: + * + * - If you are not asking the linking function to clone the template, create the DOM element(s) + * before you send them to the compiler and keep this reference around. + * ```js + * var element = $compile('<p>{{total}}</p>')(scope); + * ``` + * + * - if on the other hand, you need the element to be cloned, the view reference from the original + * example would not point to the clone, but rather to the original template that was cloned. In + * this case, you can access the clone via the cloneAttachFn: + * ```js + * var templateElement = angular.element('<p>{{total}}</p>'), + * scope = ....; + * + * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) { + * //attach the clone to DOM document at the right place + * }); + * + * //now we have reference to the cloned DOM via `clonedElement` + * ``` + * + * + * For information on how the compiler works, see the + * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. + */ - xsrfCookieName: 'XSRF-TOKEN', - xsrfHeaderName: 'X-XSRF-TOKEN' - }; +var $compileMinErr = minErr('$compile'); + +/** + * @ngdoc provider + * @name $compileProvider + * + * @description + */ +$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider']; +function $CompileProvider($provide, $$sanitizeUriProvider) { + var hasDirectives = {}, + Suffix = 'Directive', + COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/, + CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/, + ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), + REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; + + // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes + // The assumption is that future DOM event attribute names will begin with + // 'on' and be composed of only English letters. + var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; + + function parseIsolateBindings(scope, directiveName, isController) { + var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/; + + var bindings = {}; + + forEach(scope, function(definition, scopeName) { + var match = definition.match(LOCAL_REGEXP); + + if (!match) { + throw $compileMinErr('iscp', + "Invalid {3} for directive '{0}'." + + " Definition: {... {1}: '{2}' ...}", + directiveName, scopeName, definition, + (isController ? "controller bindings definition" : + "isolate scope definition")); + } + + bindings[scopeName] = { + mode: match[1][0], + collection: match[2] === '*', + optional: match[3] === '?', + attrName: match[4] || scopeName + }; + }); + + return bindings; + } + + function parseDirectiveBindings(directive, directiveName) { + var bindings = { + isolateScope: null, + bindToController: null + }; + if (isObject(directive.scope)) { + if (directive.bindToController === true) { + bindings.bindToController = parseIsolateBindings(directive.scope, + directiveName, true); + bindings.isolateScope = {}; + } else { + bindings.isolateScope = parseIsolateBindings(directive.scope, + directiveName, false); + } + } + if (isObject(directive.bindToController)) { + bindings.bindToController = + parseIsolateBindings(directive.bindToController, directiveName, true); + } + if (isObject(bindings.bindToController)) { + var controller = directive.controller; + var controllerAs = directive.controllerAs; + if (!controller) { + // There is no controller, there may or may not be a controllerAs property + throw $compileMinErr('noctrl', + "Cannot bind to controller without directive '{0}'s controller.", + directiveName); + } else if (!identifierForController(controller, controllerAs)) { + // There is a controller, but no identifier or controllerAs property + throw $compileMinErr('noident', + "Cannot bind to controller without identifier for directive '{0}'.", + directiveName); + } + } + return bindings; + } + + function assertValidDirectiveName(name) { + var letter = name.charAt(0); + if (!letter || letter !== lowercase(letter)) { + throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name); + } + if (name !== name.trim()) { + throw $compileMinErr('baddir', + "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces", + name); + } + } - var useApplyAsync = false; /** * @ngdoc method - * @name $httpProvider#useApplyAsync + * @name $compileProvider#directive + * @kind function + * * @description + * Register a new directive with the compiler. * - * Configure $http service to combine processing of multiple http responses received at around - * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in - * significant performance improvement for bigger applications that make many HTTP requests - * concurrently (common during application bootstrap). + * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which + * will match as <code>ng-bind</code>), or an object map of directives where the keys are the + * names and the values are the factories. + * @param {Function|Array} directiveFactory An injectable directive factory function. See + * {@link guide/directive} for more info. + * @returns {ng.$compileProvider} Self for chaining. + */ + this.directive = function registerDirective(name, directiveFactory) { + assertNotHasOwnProperty(name, 'directive'); + if (isString(name)) { + assertValidDirectiveName(name); + assertArg(directiveFactory, 'directiveFactory'); + if (!hasDirectives.hasOwnProperty(name)) { + hasDirectives[name] = []; + $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', + function($injector, $exceptionHandler) { + var directives = []; + forEach(hasDirectives[name], function(directiveFactory, index) { + try { + var directive = $injector.invoke(directiveFactory); + if (isFunction(directive)) { + directive = { compile: valueFn(directive) }; + } else if (!directive.compile && directive.link) { + directive.compile = valueFn(directive.link); + } + directive.priority = directive.priority || 0; + directive.index = index; + directive.name = directive.name || name; + directive.require = directive.require || (directive.controller && directive.name); + directive.restrict = directive.restrict || 'EA'; + var bindings = directive.$$bindings = + parseDirectiveBindings(directive, directive.name); + if (isObject(bindings.isolateScope)) { + directive.$$isolateBindings = bindings.isolateScope; + } + directive.$$moduleName = directiveFactory.$$moduleName; + directives.push(directive); + } catch (e) { + $exceptionHandler(e); + } + }); + return directives; + }]); + } + hasDirectives[name].push(directiveFactory); + } else { + forEach(name, reverseParams(registerDirective)); + } + return this; + }; + + + /** + * @ngdoc method + * @name $compileProvider#aHrefSanitizationWhitelist + * @kind function * - * Defaults to false. If no value is specifed, returns the current configured value. + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. * - * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred - * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window - * to load and share the same digest cycle. + * The sanitization is a security measure aimed at preventing XSS attacks via html links. * - * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. - * otherwise, returns the current configured value. - **/ - this.useApplyAsync = function(value) { - if (isDefined(value)) { - useApplyAsync = !!value; + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); return this; + } else { + return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); } - return useApplyAsync; }; + /** - * @ngdoc property - * @name $httpProvider#interceptors + * @ngdoc method + * @name $compileProvider#imgSrcSanitizationWhitelist + * @kind function + * * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. * - * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http} - * pre-processing of request or postprocessing of responses. + * The sanitization is a security measure aimed at prevent XSS attacks via html links. * - * These service factories are ordered by request, i.e. they are applied in the same order as the - * array, on request, but reverse order, on response. + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. * - * {@link ng.$http#interceptors Interceptors detailed info} + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); + return this; + } else { + return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); + } + }; + + /** + * @ngdoc method + * @name $compileProvider#debugInfoEnabled + * + * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the + * current debugInfoEnabled state + * @returns {*} current value if used as getter or itself (chaining) if used as setter + * + * @kind function + * + * @description + * Call this method to enable/disable various debug runtime information in the compiler such as adding + * binding information and a reference to the current scope on to DOM elements. + * If enabled, the compiler will add the following to DOM elements that have been bound to the scope + * * `ng-binding` CSS class + * * `$binding` data property containing an array of the binding expressions + * + * You may want to disable this in production for a significant performance boost. See + * {@link guide/production#disabling-debug-data Disabling Debug Data} for more. + * + * The default value is true. + */ + var debugInfoEnabled = true; + this.debugInfoEnabled = function(enabled) { + if (isDefined(enabled)) { + debugInfoEnabled = enabled; + return this; + } + return debugInfoEnabled; + }; + + this.$get = [ + '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', + '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri', + function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, + $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) { + + var Attributes = function(element, attributesToCopy) { + if (attributesToCopy) { + var keys = Object.keys(attributesToCopy); + var i, l, key; + + for (i = 0, l = keys.length; i < l; i++) { + key = keys[i]; + this[key] = attributesToCopy[key]; + } + } else { + this.$attr = {}; + } + + this.$$element = element; + }; + + Attributes.prototype = { + /** + * @ngdoc method + * @name $compile.directive.Attributes#$normalize + * @kind function + * + * @description + * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or + * `data-`) to its normalized, camelCase form. + * + * Also there is special case for Moz prefix starting with upper case letter. + * + * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} + * + * @param {string} name Name to normalize + */ + $normalize: directiveNormalize, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$addClass + * @kind function + * + * @description + * Adds the CSS class value specified by the classVal parameter to the element. If animations + * are enabled then an animation will be triggered for the class addition. + * + * @param {string} classVal The className value that will be added to the element + */ + $addClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.addClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$removeClass + * @kind function + * + * @description + * Removes the CSS class value specified by the classVal parameter from the element. If + * animations are enabled then an animation will be triggered for the class removal. + * + * @param {string} classVal The className value that will be removed from the element + */ + $removeClass: function(classVal) { + if (classVal && classVal.length > 0) { + $animate.removeClass(this.$$element, classVal); + } + }, + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$updateClass + * @kind function + * + * @description + * Adds and removes the appropriate CSS class values to the element based on the difference + * between the new and old CSS class values (specified as newClasses and oldClasses). + * + * @param {string} newClasses The current CSS className value + * @param {string} oldClasses The former CSS className value + */ + $updateClass: function(newClasses, oldClasses) { + var toAdd = tokenDifference(newClasses, oldClasses); + if (toAdd && toAdd.length) { + $animate.addClass(this.$$element, toAdd); + } + + var toRemove = tokenDifference(oldClasses, newClasses); + if (toRemove && toRemove.length) { + $animate.removeClass(this.$$element, toRemove); + } + }, + + /** + * Set a normalized attribute on the element in a way such that all directives + * can share the attribute. This function properly handles boolean attributes. + * @param {string} key Normalized key. (ie ngAttribute) + * @param {string|boolean} value The value to set. If `null` attribute will be deleted. + * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. + * Defaults to true. + * @param {string=} attrName Optional none normalized name. Defaults to key. + */ + $set: function(key, value, writeAttr, attrName) { + // TODO: decide whether or not to throw an error if "class" + //is set through this function since it may cause $updateClass to + //become unstable. + + var node = this.$$element[0], + booleanKey = getBooleanAttrName(node, key), + aliasedKey = getAliasedAttrName(node, key), + observer = key, + nodeName; + + if (booleanKey) { + this.$$element.prop(key, value); + attrName = booleanKey; + } else if (aliasedKey) { + this[aliasedKey] = value; + observer = aliasedKey; + } + + this[key] = value; + + // translate normalized key to actual key + if (attrName) { + this.$attr[key] = attrName; + } else { + attrName = this.$attr[key]; + if (!attrName) { + this.$attr[key] = attrName = snake_case(key, '-'); + } + } + + nodeName = nodeName_(this.$$element); + + if ((nodeName === 'a' && key === 'href') || + (nodeName === 'img' && key === 'src')) { + // sanitize a[href] and img[src] values + this[key] = value = $$sanitizeUri(value, key === 'src'); + } else if (nodeName === 'img' && key === 'srcset') { + // sanitize img[srcset] values + var result = ""; + + // first check if there are spaces because it's not the same pattern + var trimmedSrcset = trim(value); + // ( 999x ,| 999w ,| ,|, ) + var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; + var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; + + // split srcset into tuple of uri and descriptor except for the last item + var rawUris = trimmedSrcset.split(pattern); + + // for each tuples + var nbrUrisWith2parts = Math.floor(rawUris.length / 2); + for (var i = 0; i < nbrUrisWith2parts; i++) { + var innerIdx = i * 2; + // sanitize the uri + result += $$sanitizeUri(trim(rawUris[innerIdx]), true); + // add the descriptor + result += (" " + trim(rawUris[innerIdx + 1])); + } + + // split the last item into uri and descriptor + var lastTuple = trim(rawUris[i * 2]).split(/\s/); + + // sanitize the last uri + result += $$sanitizeUri(trim(lastTuple[0]), true); + + // and add the last descriptor if any + if (lastTuple.length === 2) { + result += (" " + trim(lastTuple[1])); + } + this[key] = value = result; + } + + if (writeAttr !== false) { + if (value === null || value === undefined) { + this.$$element.removeAttr(attrName); + } else { + this.$$element.attr(attrName, value); + } + } + + // fire observers + var $$observers = this.$$observers; + $$observers && forEach($$observers[observer], function(fn) { + try { + fn(value); + } catch (e) { + $exceptionHandler(e); + } + }); + }, + + + /** + * @ngdoc method + * @name $compile.directive.Attributes#$observe + * @kind function + * + * @description + * Observes an interpolated attribute. + * + * The observer function will be invoked once during the next `$digest` following + * compilation. The observer is then invoked whenever the interpolated value + * changes. + * + * @param {string} key Normalized key. (ie ngAttribute) . + * @param {function(interpolatedValue)} fn Function that will be called whenever + the interpolated value of the attribute changes. + * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info. + * @returns {function()} Returns a deregistration function for this observer. + */ + $observe: function(key, fn) { + var attrs = this, + $$observers = (attrs.$$observers || (attrs.$$observers = createMap())), + listeners = ($$observers[key] || ($$observers[key] = [])); + + listeners.push(fn); + $rootScope.$evalAsync(function() { + if (!listeners.$$inter && attrs.hasOwnProperty(key)) { + // no one registered attribute interpolation function, so lets call it manually + fn(attrs[key]); + } + }); + + return function() { + arrayRemove(listeners, fn); + }; + } + }; + + + function safeAddClass($element, className) { + try { + $element.addClass(className); + } catch (e) { + // ignore, since it means that we are trying to set class on + // SVG element, where class name is read-only. + } + } + + + var startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') + ? identity + : function denormalizeTemplate(template) { + return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); + }, + NG_ATTR_BINDING = /^ngAttr[A-Z]/; + + compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { + var bindings = $element.data('$binding') || []; + + if (isArray(binding)) { + bindings = bindings.concat(binding); + } else { + bindings.push(binding); + } + + $element.data('$binding', bindings); + } : noop; + + compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { + safeAddClass($element, 'ng-binding'); + } : noop; + + compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { + var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope'; + $element.data(dataName, scope); + } : noop; + + compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { + safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope'); + } : noop; + + return compile; + + //================================ + + function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, + previousCompileContext) { + if (!($compileNodes instanceof jqLite)) { + // jquery always rewraps, whereas we need to preserve the original selector so that we can + // modify it. + $compileNodes = jqLite($compileNodes); + } + // We can not compile top level text elements since text nodes can be merged and we will + // not be able to attach scope data to them, so we will wrap them in <span> + forEach($compileNodes, function(node, index) { + if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) { + $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0]; + } + }); + var compositeLinkFn = + compileNodes($compileNodes, transcludeFn, $compileNodes, + maxPriority, ignoreDirective, previousCompileContext); + compile.$$addScopeClass($compileNodes); + var namespace = null; + return function publicLinkFn(scope, cloneConnectFn, options) { + assertArg(scope, 'scope'); + + options = options || {}; + var parentBoundTranscludeFn = options.parentBoundTranscludeFn, + transcludeControllers = options.transcludeControllers, + futureParentElement = options.futureParentElement; + + // When `parentBoundTranscludeFn` is passed, it is a + // `controllersBoundTransclude` function (it was previously passed + // as `transclude` to directive.link) so we must unwrap it to get + // its `boundTranscludeFn` + if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { + parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; + } + + if (!namespace) { + namespace = detectNamespaceForChildElements(futureParentElement); + } + var $linkNode; + if (namespace !== 'html') { + // When using a directive with replace:true and templateUrl the $compileNodes + // (or a child element inside of them) + // might change, so we need to recreate the namespace adapted compileNodes + // for call to the link function. + // Note: This will already clone the nodes... + $linkNode = jqLite( + wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html()) + ); + } else if (cloneConnectFn) { + // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart + // and sometimes changes the structure of the DOM. + $linkNode = JQLitePrototype.clone.call($compileNodes); + } else { + $linkNode = $compileNodes; + } + + if (transcludeControllers) { + for (var controllerName in transcludeControllers) { + $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance); + } + } + + compile.$$addScopeInfo($linkNode, scope); + + if (cloneConnectFn) cloneConnectFn($linkNode, scope); + if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); + return $linkNode; + }; + } + + function detectNamespaceForChildElements(parentElement) { + // TODO: Make this detect MathML as well... + var node = parentElement && parentElement[0]; + if (!node) { + return 'html'; + } else { + return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html'; + } + } + + /** + * Compile function matches each node in nodeList against the directives. Once all directives + * for a particular node are collected their compile functions are executed. The compile + * functions return values - the linking functions - are combined into a composite linking + * function, which is the a linking function for the node. + * + * @param {NodeList} nodeList an array of nodes or NodeList to compile + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new child of the transcluded parent scope. + * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then + * the rootElement must be set the jqLite collection of the compile root. This is + * needed so that the jqLite collection items can be replaced with widgets. + * @param {number=} maxPriority Max directive priority. + * @returns {Function} A composite linking function of all of the matched directives or null. + */ + function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, + previousCompileContext) { + var linkFns = [], + attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; + + for (var i = 0; i < nodeList.length; i++) { + attrs = new Attributes(); + + // we must always refer to nodeList[i] since the nodes can be replaced underneath us. + directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, + ignoreDirective); + + nodeLinkFn = (directives.length) + ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, + null, [], [], previousCompileContext) + : null; + + if (nodeLinkFn && nodeLinkFn.scope) { + compile.$$addScopeClass(attrs.$$element); + } + + childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || + !(childNodes = nodeList[i].childNodes) || + !childNodes.length) + ? null + : compileNodes(childNodes, + nodeLinkFn ? ( + (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) + && nodeLinkFn.transclude) : transcludeFn); + + if (nodeLinkFn || childLinkFn) { + linkFns.push(i, nodeLinkFn, childLinkFn); + linkFnFound = true; + nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; + } + + //use the previous context only for the first element in the virtual group + previousCompileContext = null; + } + + // return a linking function if we have found anything, null otherwise + return linkFnFound ? compositeLinkFn : null; + + function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { + var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; + var stableNodeList; + + + if (nodeLinkFnFound) { + // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our + // offsets don't get screwed up + var nodeListLength = nodeList.length; + stableNodeList = new Array(nodeListLength); + + // create a sparse array by only copying the elements which have a linkFn + for (i = 0; i < linkFns.length; i+=3) { + idx = linkFns[i]; + stableNodeList[idx] = nodeList[idx]; + } + } else { + stableNodeList = nodeList; + } + + for (i = 0, ii = linkFns.length; i < ii;) { + node = stableNodeList[linkFns[i++]]; + nodeLinkFn = linkFns[i++]; + childLinkFn = linkFns[i++]; + + if (nodeLinkFn) { + if (nodeLinkFn.scope) { + childScope = scope.$new(); + compile.$$addScopeInfo(jqLite(node), childScope); + var destroyBindings = nodeLinkFn.$$destroyBindings; + if (destroyBindings) { + nodeLinkFn.$$destroyBindings = null; + childScope.$on('$destroyed', destroyBindings); + } + } else { + childScope = scope; + } + + if (nodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn( + scope, nodeLinkFn.transclude, parentBoundTranscludeFn); + + } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { + childBoundTranscludeFn = parentBoundTranscludeFn; + + } else if (!parentBoundTranscludeFn && transcludeFn) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); + + } else { + childBoundTranscludeFn = null; + } + + nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn, + nodeLinkFn); + + } else if (childLinkFn) { + childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); + } + } + } + } + + function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) { + + var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { + + if (!transcludedScope) { + transcludedScope = scope.$new(false, containingScope); + transcludedScope.$$transcluded = true; + } + + return transcludeFn(transcludedScope, cloneFn, { + parentBoundTranscludeFn: previousBoundTranscludeFn, + transcludeControllers: controllers, + futureParentElement: futureParentElement + }); + }; + + return boundTranscludeFn; + } + + /** + * Looks for directives on the given node and adds them to the directive collection which is + * sorted. + * + * @param node Node to search. + * @param directives An array to which the directives are added to. This array is sorted before + * the function returns. + * @param attrs The shared attrs object which is used to populate the normalized attributes. + * @param {number=} maxPriority Max directive priority. + */ + function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { + var nodeType = node.nodeType, + attrsMap = attrs.$attr, + match, + className; + + switch (nodeType) { + case NODE_TYPE_ELEMENT: /* Element */ + // use the node name: <directive> + addDirective(directives, + directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective); + + // iterate over the attributes + for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes, + j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { + var attrStartName = false; + var attrEndName = false; + + attr = nAttrs[j]; + name = attr.name; + value = trim(attr.value); + + // support ngAttr attribute binding + ngAttrName = directiveNormalize(name); + if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) { + name = name.replace(PREFIX_REGEXP, '') + .substr(8).replace(/_(.)/g, function(match, letter) { + return letter.toUpperCase(); + }); + } + + var directiveNName = ngAttrName.replace(/(Start|End)$/, ''); + if (directiveIsMultiElement(directiveNName)) { + if (ngAttrName === directiveNName + 'Start') { + attrStartName = name; + attrEndName = name.substr(0, name.length - 5) + 'end'; + name = name.substr(0, name.length - 6); + } + } + + nName = directiveNormalize(name.toLowerCase()); + attrsMap[nName] = name; + if (isNgAttr || !attrs.hasOwnProperty(nName)) { + attrs[nName] = value; + if (getBooleanAttrName(node, nName)) { + attrs[nName] = true; // presence means true + } + } + addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); + addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, + attrEndName); + } + + // use class as directive + className = node.className; + if (isObject(className)) { + // Maybe SVGAnimatedString + className = className.animVal; + } + if (isString(className) && className !== '') { + while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { + nName = directiveNormalize(match[2]); + if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[3]); + } + className = className.substr(match.index + match[0].length); + } + } + break; + case NODE_TYPE_TEXT: /* Text Node */ + if (msie === 11) { + // Workaround for #11781 + while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) { + node.nodeValue = node.nodeValue + node.nextSibling.nodeValue; + node.parentNode.removeChild(node.nextSibling); + } + } + addTextInterpolateDirective(directives, node.nodeValue); + break; + case NODE_TYPE_COMMENT: /* Comment */ + try { + match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); + if (match) { + nName = directiveNormalize(match[1]); + if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { + attrs[nName] = trim(match[2]); + } + } + } catch (e) { + // turns out that under some circumstances IE9 throws errors when one attempts to read + // comment's node value. + // Just ignore it and continue. (Can't seem to reproduce in test case.) + } + break; + } + + directives.sort(byPriority); + return directives; + } + + /** + * Given a node with an directive-start it collects all of the siblings until it finds + * directive-end. + * @param node + * @param attrStart + * @param attrEnd + * @returns {*} + */ + function groupScan(node, attrStart, attrEnd) { + var nodes = []; + var depth = 0; + if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { + do { + if (!node) { + throw $compileMinErr('uterdir', + "Unterminated attribute, found '{0}' but no matching '{1}' found.", + attrStart, attrEnd); + } + if (node.nodeType == NODE_TYPE_ELEMENT) { + if (node.hasAttribute(attrStart)) depth++; + if (node.hasAttribute(attrEnd)) depth--; + } + nodes.push(node); + node = node.nextSibling; + } while (depth > 0); + } else { + nodes.push(node); + } + + return jqLite(nodes); + } + + /** + * Wrapper for linking function which converts normal linking function into a grouped + * linking function. + * @param linkFn + * @param attrStart + * @param attrEnd + * @returns {Function} + */ + function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { + return function(scope, element, attrs, controllers, transcludeFn) { + element = groupScan(element[0], attrStart, attrEnd); + return linkFn(scope, element, attrs, controllers, transcludeFn); + }; + } + + /** + * Once the directives have been collected, their compile functions are executed. This method + * is responsible for inlining directive templates as well as terminating the application + * of the directives if the terminal directive has been reached. + * + * @param {Array} directives Array of collected directives to execute their compile function. + * this needs to be pre-sorted by priority order. + * @param {Node} compileNode The raw DOM node to apply the compile functions to + * @param {Object} templateAttrs The shared attribute function + * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the + * scope argument is auto-generated to the new + * child of the transcluded parent scope. + * @param {JQLite} jqCollection If we are working on the root of the compile tree then this + * argument has the root jqLite array so that we can replace nodes + * on it. + * @param {Object=} originalReplaceDirective An optional directive that will be ignored when + * compiling the transclusion. + * @param {Array.<Function>} preLinkFns + * @param {Array.<Function>} postLinkFns + * @param {Object} previousCompileContext Context used for previous compilation of the current + * node + * @returns {Function} linkFn + */ + function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, + jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, + previousCompileContext) { + previousCompileContext = previousCompileContext || {}; + + var terminalPriority = -Number.MAX_VALUE, + newScopeDirective = previousCompileContext.newScopeDirective, + controllerDirectives = previousCompileContext.controllerDirectives, + newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, + templateDirective = previousCompileContext.templateDirective, + nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, + hasTranscludeDirective = false, + hasTemplate = false, + hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, + $compileNode = templateAttrs.$$element = jqLite(compileNode), + directive, + directiveName, + $template, + replaceDirective = originalReplaceDirective, + childTranscludeFn = transcludeFn, + linkFn, + directiveValue; + + // executes all directives on the current element + for (var i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + var attrStart = directive.$$start; + var attrEnd = directive.$$end; + + // collect multiblock sections + if (attrStart) { + $compileNode = groupScan(compileNode, attrStart, attrEnd); + } + $template = undefined; + + if (terminalPriority > directive.priority) { + break; // prevent further processing of directives + } + + if (directiveValue = directive.scope) { + + // skip the check for directives with async templates, we'll check the derived sync + // directive when the template arrives + if (!directive.templateUrl) { + if (isObject(directiveValue)) { + // This directive is trying to add an isolated scope. + // Check that there is no scope of any kind already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective, + directive, $compileNode); + newIsolateScopeDirective = directive; + } else { + // This directive is trying to add a child scope. + // Check that there is no isolated scope already + assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, + $compileNode); + } + } + + newScopeDirective = newScopeDirective || directive; + } + + directiveName = directive.name; + + if (!directive.templateUrl && directive.controller) { + directiveValue = directive.controller; + controllerDirectives = controllerDirectives || createMap(); + assertNoDuplicate("'" + directiveName + "' controller", + controllerDirectives[directiveName], directive, $compileNode); + controllerDirectives[directiveName] = directive; + } + + if (directiveValue = directive.transclude) { + hasTranscludeDirective = true; + + // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. + // This option should only be used by directives that know how to safely handle element transclusion, + // where the transcluded nodes are added or replaced after linking. + if (!directive.$$tlb) { + assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); + nonTlbTranscludeDirective = directive; + } + + if (directiveValue == 'element') { + hasElementTranscludeDirective = true; + terminalPriority = directive.priority; + $template = $compileNode; + $compileNode = templateAttrs.$$element = + jqLite(document.createComment(' ' + directiveName + ': ' + + templateAttrs[directiveName] + ' ')); + compileNode = $compileNode[0]; + replaceWith(jqCollection, sliceArgs($template), compileNode); + + childTranscludeFn = compile($template, transcludeFn, terminalPriority, + replaceDirective && replaceDirective.name, { + // Don't pass in: + // - controllerDirectives - otherwise we'll create duplicates controllers + // - newIsolateScopeDirective or templateDirective - combining templates with + // element transclusion doesn't make sense. + // + // We need only nonTlbTranscludeDirective so that we prevent putting transclusion + // on the same element more than once. + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + } else { + $template = jqLite(jqLiteClone(compileNode)).contents(); + $compileNode.empty(); // clear contents + childTranscludeFn = compile($template, transcludeFn); + } + } + + if (directive.template) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + directiveValue = (isFunction(directive.template)) + ? directive.template($compileNode, templateAttrs) + : directive.template; + + directiveValue = denormalizeTemplate(directiveValue); + + if (directive.replace) { + replaceDirective = directive; + if (jqLiteIsTextNode(directiveValue)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + directiveName, ''); + } + + replaceWith(jqCollection, $compileNode, compileNode); + + var newTemplateAttrs = {$attr: {}}; + + // combine directives from the original node and from the template: + // - take the array of directives for this element + // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed) + // - collect directives from the template and sort them by priority + // - combine directives as: processed + template + unprocessed + var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); + var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); + + if (newIsolateScopeDirective) { + markDirectivesAsIsolate(templateDirectives); + } + directives = directives.concat(templateDirectives).concat(unprocessedDirectives); + mergeTemplateAttributes(templateAttrs, newTemplateAttrs); + + ii = directives.length; + } else { + $compileNode.html(directiveValue); + } + } + + if (directive.templateUrl) { + hasTemplate = true; + assertNoDuplicate('template', templateDirective, directive, $compileNode); + templateDirective = directive; + + if (directive.replace) { + replaceDirective = directive; + } + + nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, + templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { + controllerDirectives: controllerDirectives, + newScopeDirective: (newScopeDirective !== directive) && newScopeDirective, + newIsolateScopeDirective: newIsolateScopeDirective, + templateDirective: templateDirective, + nonTlbTranscludeDirective: nonTlbTranscludeDirective + }); + ii = directives.length; + } else if (directive.compile) { + try { + linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); + if (isFunction(linkFn)) { + addLinkFns(null, linkFn, attrStart, attrEnd); + } else if (linkFn) { + addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd); + } + } catch (e) { + $exceptionHandler(e, startingTag($compileNode)); + } + } + + if (directive.terminal) { + nodeLinkFn.terminal = true; + terminalPriority = Math.max(terminalPriority, directive.priority); + } + + } + + nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; + nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; + nodeLinkFn.templateOnThisElement = hasTemplate; + nodeLinkFn.transclude = childTranscludeFn; + + previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; + + // might be normal or delayed nodeLinkFn depending on if templateUrl is present + return nodeLinkFn; + + //////////////////// + + function addLinkFns(pre, post, attrStart, attrEnd) { + if (pre) { + if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); + pre.require = directive.require; + pre.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + pre = cloneAndAnnotateFn(pre, {isolateScope: true}); + } + preLinkFns.push(pre); + } + if (post) { + if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); + post.require = directive.require; + post.directiveName = directiveName; + if (newIsolateScopeDirective === directive || directive.$$isolateScope) { + post = cloneAndAnnotateFn(post, {isolateScope: true}); + } + postLinkFns.push(post); + } + } + + + function getControllers(directiveName, require, $element, elementControllers) { + var value; + + if (isString(require)) { + var match = require.match(REQUIRE_PREFIX_REGEXP); + var name = require.substring(match[0].length); + var inheritType = match[1] || match[3]; + var optional = match[2] === '?'; + + //If only parents then start at the parent element + if (inheritType === '^^') { + $element = $element.parent(); + //Otherwise attempt getting the controller from elementControllers in case + //the element is transcluded (and has no data) and to avoid .data if possible + } else { + value = elementControllers && elementControllers[name]; + value = value && value.instance; + } + + if (!value) { + var dataName = '$' + name + 'Controller'; + value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); + } + + if (!value && !optional) { + throw $compileMinErr('ctreq', + "Controller '{0}', required by directive '{1}', can't be found!", + name, directiveName); + } + } else if (isArray(require)) { + value = []; + for (var i = 0, ii = require.length; i < ii; i++) { + value[i] = getControllers(directiveName, require[i], $element, elementControllers); + } + } + + return value || null; + } + + function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) { + var elementControllers = createMap(); + for (var controllerKey in controllerDirectives) { + var directive = controllerDirectives[controllerKey]; + var locals = { + $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, + $element: $element, + $attrs: attrs, + $transclude: transcludeFn + }; + + var controller = directive.controller; + if (controller == '@') { + controller = attrs[directive.name]; + } + + var controllerInstance = $controller(controller, locals, true, directive.controllerAs); + + // For directives with element transclusion the element is a comment, + // but jQuery .data doesn't support attaching data to comment nodes as it's hard to + // clean up (http://bugs.jquery.com/ticket/8335). + // Instead, we save the controllers for the element in a local hash and attach to .data + // later, once we have the actual element. + elementControllers[directive.name] = controllerInstance; + if (!hasElementTranscludeDirective) { + $element.data('$' + directive.name + 'Controller', controllerInstance.instance); + } + } + return elementControllers; + } + + function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn, + thisLinkFn) { + var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element, + attrs; + + if (compileNode === linkNode) { + attrs = templateAttrs; + $element = templateAttrs.$$element; + } else { + $element = jqLite(linkNode); + attrs = new Attributes($element, templateAttrs); + } + + if (newIsolateScopeDirective) { + isolateScope = scope.$new(true); + } + + if (boundTranscludeFn) { + // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn` + // is later passed as `parentBoundTranscludeFn` to `publicLinkFn` + transcludeFn = controllersBoundTransclude; + transcludeFn.$$boundTransclude = boundTranscludeFn; + } + + if (controllerDirectives) { + elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope); + } + + if (newIsolateScopeDirective) { + // Initialize isolate scope bindings for new isolate scope directive. + compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || + templateDirective === newIsolateScopeDirective.$$originalDirective))); + compile.$$addScopeClass($element, true); + isolateScope.$$isolateBindings = + newIsolateScopeDirective.$$isolateBindings; + initializeDirectiveBindings(scope, attrs, isolateScope, + isolateScope.$$isolateBindings, + newIsolateScopeDirective, isolateScope); + } + if (elementControllers) { + // Initialize bindToController bindings for new/isolate scopes + var scopeDirective = newIsolateScopeDirective || newScopeDirective; + var bindings; + var controllerForBindings; + if (scopeDirective && elementControllers[scopeDirective.name]) { + bindings = scopeDirective.$$bindings.bindToController; + controller = elementControllers[scopeDirective.name]; + + if (controller && controller.identifier && bindings) { + controllerForBindings = controller; + thisLinkFn.$$destroyBindings = + initializeDirectiveBindings(scope, attrs, controller.instance, + bindings, scopeDirective); + } + } + for (i in elementControllers) { + controller = elementControllers[i]; + var controllerResult = controller(); + + if (controllerResult !== controller.instance) { + // If the controller constructor has a return value, overwrite the instance + // from setupControllers and update the element data + controller.instance = controllerResult; + $element.data('$' + i + 'Controller', controllerResult); + if (controller === controllerForBindings) { + // Remove and re-install bindToController bindings + thisLinkFn.$$destroyBindings(); + thisLinkFn.$$destroyBindings = + initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective); + } + } + } + } + + // PRELINKING + for (i = 0, ii = preLinkFns.length; i < ii; i++) { + linkFn = preLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // RECURSION + // We only pass the isolate scope, if the isolate directive has a template, + // otherwise the child elements do not belong to the isolate directive. + var scopeToChild = scope; + if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { + scopeToChild = isolateScope; + } + childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); + + // POSTLINKING + for (i = postLinkFns.length - 1; i >= 0; i--) { + linkFn = postLinkFns[i]; + invokeLinkFn(linkFn, + linkFn.isolateScope ? isolateScope : scope, + $element, + attrs, + linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), + transcludeFn + ); + } + + // This is the function that is injected as `$transclude`. + // Note: all arguments are optional! + function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) { + var transcludeControllers; + + // No scope passed in: + if (!isScope(scope)) { + futureParentElement = cloneAttachFn; + cloneAttachFn = scope; + scope = undefined; + } + + if (hasElementTranscludeDirective) { + transcludeControllers = elementControllers; + } + if (!futureParentElement) { + futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; + } + return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); + } + } + } + + function markDirectivesAsIsolate(directives) { + // mark all directives as needing isolate scope. + for (var j = 0, jj = directives.length; j < jj; j++) { + directives[j] = inherit(directives[j], {$$isolateScope: true}); + } + } + + /** + * looks up the directive and decorates it with exception handling and proper parameters. We + * call this the boundDirective. + * + * @param {string} name name of the directive to look up. + * @param {string} location The directive must be found in specific format. + * String containing any of theses characters: + * + * * `E`: element name + * * `A': attribute + * * `C`: class + * * `M`: comment + * @returns {boolean} true if directive was added. + */ + function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, + endAttrName) { + if (name === ignoreDirective) return null; + var match = null; + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + try { + directive = directives[i]; + if ((maxPriority === undefined || maxPriority > directive.priority) && + directive.restrict.indexOf(location) != -1) { + if (startAttrName) { + directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); + } + tDirectives.push(directive); + match = directive; + } + } catch (e) { $exceptionHandler(e); } + } + } + return match; + } + + + /** + * looks up the directive and returns true if it is a multi-element directive, + * and therefore requires DOM nodes between -start and -end markers to be grouped + * together. + * + * @param {string} name name of the directive to look up. + * @returns true if directive was registered as multi-element. + */ + function directiveIsMultiElement(name) { + if (hasDirectives.hasOwnProperty(name)) { + for (var directive, directives = $injector.get(name + Suffix), + i = 0, ii = directives.length; i < ii; i++) { + directive = directives[i]; + if (directive.multiElement) { + return true; + } + } + } + return false; + } + + /** + * When the element is replaced with HTML template then the new attributes + * on the template need to be merged with the existing attributes in the DOM. + * The desired effect is to have both of the attributes present. + * + * @param {object} dst destination attributes (original DOM) + * @param {object} src source attributes (from the directive template) + */ + function mergeTemplateAttributes(dst, src) { + var srcAttr = src.$attr, + dstAttr = dst.$attr, + $element = dst.$$element; + + // reapply the old attributes to the new element + forEach(dst, function(value, key) { + if (key.charAt(0) != '$') { + if (src[key] && src[key] !== value) { + value += (key === 'style' ? ';' : ' ') + src[key]; + } + dst.$set(key, value, true, srcAttr[key]); + } + }); + + // copy the new attributes on the old attrs object + forEach(src, function(value, key) { + if (key == 'class') { + safeAddClass($element, value); + dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; + } else if (key == 'style') { + $element.attr('style', $element.attr('style') + ';' + value); + dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value; + // `dst` will never contain hasOwnProperty as DOM parser won't let it. + // You will get an "InvalidCharacterError: DOM Exception 5" error if you + // have an attribute like "has-own-property" or "data-has-own-property", etc. + } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { + dst[key] = value; + dstAttr[key] = srcAttr[key]; + } + }); + } + + + function compileTemplateUrl(directives, $compileNode, tAttrs, + $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { + var linkQueue = [], + afterTemplateNodeLinkFn, + afterTemplateChildLinkFn, + beforeTemplateCompileNode = $compileNode[0], + origAsyncDirective = directives.shift(), + derivedSyncDirective = inherit(origAsyncDirective, { + templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective + }), + templateUrl = (isFunction(origAsyncDirective.templateUrl)) + ? origAsyncDirective.templateUrl($compileNode, tAttrs) + : origAsyncDirective.templateUrl, + templateNamespace = origAsyncDirective.templateNamespace; + + $compileNode.empty(); + + $templateRequest(templateUrl) + .then(function(content) { + var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; + + content = denormalizeTemplate(content); + + if (origAsyncDirective.replace) { + if (jqLiteIsTextNode(content)) { + $template = []; + } else { + $template = removeComments(wrapTemplate(templateNamespace, trim(content))); + } + compileNode = $template[0]; + + if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { + throw $compileMinErr('tplrt', + "Template for directive '{0}' must have exactly one root element. {1}", + origAsyncDirective.name, templateUrl); + } + + tempTemplateAttrs = {$attr: {}}; + replaceWith($rootElement, $compileNode, compileNode); + var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); + + if (isObject(origAsyncDirective.scope)) { + markDirectivesAsIsolate(templateDirectives); + } + directives = templateDirectives.concat(directives); + mergeTemplateAttributes(tAttrs, tempTemplateAttrs); + } else { + compileNode = beforeTemplateCompileNode; + $compileNode.html(content); + } + + directives.unshift(derivedSyncDirective); + + afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, + childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, + previousCompileContext); + forEach($rootElement, function(node, i) { + if (node == compileNode) { + $rootElement[i] = $compileNode[0]; + } + }); + afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); + + while (linkQueue.length) { + var scope = linkQueue.shift(), + beforeTemplateLinkNode = linkQueue.shift(), + linkRootElement = linkQueue.shift(), + boundTranscludeFn = linkQueue.shift(), + linkNode = $compileNode[0]; + + if (scope.$$destroyed) continue; + + if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { + var oldClasses = beforeTemplateLinkNode.className; + + if (!(previousCompileContext.hasElementTranscludeDirective && + origAsyncDirective.replace)) { + // it was cloned therefore we have to clone as well. + linkNode = jqLiteClone(compileNode); + } + replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); + + // Copy in CSS classes from original node + safeAddClass(jqLite(linkNode), oldClasses); + } + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } else { + childBoundTranscludeFn = boundTranscludeFn; + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, + childBoundTranscludeFn, afterTemplateNodeLinkFn); + } + linkQueue = null; + }); + + return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { + var childBoundTranscludeFn = boundTranscludeFn; + if (scope.$$destroyed) return; + if (linkQueue) { + linkQueue.push(scope, + node, + rootElement, + childBoundTranscludeFn); + } else { + if (afterTemplateNodeLinkFn.transcludeOnThisElement) { + childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); + } + afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn, + afterTemplateNodeLinkFn); + } + }; + } + + + /** + * Sorting function for bound directives. + */ + function byPriority(a, b) { + var diff = b.priority - a.priority; + if (diff !== 0) return diff; + if (a.name !== b.name) return (a.name < b.name) ? -1 : 1; + return a.index - b.index; + } + + function assertNoDuplicate(what, previousDirective, directive, element) { + + function wrapModuleNameIfDefined(moduleName) { + return moduleName ? + (' (module: ' + moduleName + ')') : + ''; + } + + if (previousDirective) { + throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}', + previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName), + directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element)); + } + } + + + function addTextInterpolateDirective(directives, text) { + var interpolateFn = $interpolate(text, true); + if (interpolateFn) { + directives.push({ + priority: 0, + compile: function textInterpolateCompileFn(templateNode) { + var templateNodeParent = templateNode.parent(), + hasCompileParent = !!templateNodeParent.length; + + // When transcluding a template that has bindings in the root + // we don't have a parent and thus need to add the class during linking fn. + if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); + + return function textInterpolateLinkFn(scope, node) { + var parent = node.parent(); + if (!hasCompileParent) compile.$$addBindingClass(parent); + compile.$$addBindingInfo(parent, interpolateFn.expressions); + scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { + node[0].nodeValue = value; + }); + }; + } + }); + } + } + + + function wrapTemplate(type, template) { + type = lowercase(type || 'html'); + switch (type) { + case 'svg': + case 'math': + var wrapper = document.createElement('div'); + wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>'; + return wrapper.childNodes[0].childNodes; + default: + return template; + } + } + + + function getTrustedContext(node, attrNormalizedName) { + if (attrNormalizedName == "srcdoc") { + return $sce.HTML; + } + var tag = nodeName_(node); + // maction[xlink:href] can source SVG. It's not limited to <maction>. + if (attrNormalizedName == "xlinkHref" || + (tag == "form" && attrNormalizedName == "action") || + (tag != "img" && (attrNormalizedName == "src" || + attrNormalizedName == "ngSrc"))) { + return $sce.RESOURCE_URL; + } + } + + + function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) { + var trustedContext = getTrustedContext(node, name); + allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing; + + var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing); + + // no interpolation found -> ignore + if (!interpolateFn) return; + + + if (name === "multiple" && nodeName_(node) === "select") { + throw $compileMinErr("selmulti", + "Binding to the 'multiple' attribute is not supported. Element: {0}", + startingTag(node)); + } + + directives.push({ + priority: 100, + compile: function() { + return { + pre: function attrInterpolatePreLinkFn(scope, element, attr) { + var $$observers = (attr.$$observers || (attr.$$observers = {})); + + if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { + throw $compileMinErr('nodomevents', + "Interpolations for HTML DOM event attributes are disallowed. Please use the " + + "ng- versions (such as ng-click instead of onclick) instead."); + } + + // If the attribute has changed since last $interpolate()ed + var newValue = attr[name]; + if (newValue !== value) { + // we need to interpolate again since the attribute value has been updated + // (e.g. by another directive's compile function) + // ensure unset/empty values make interpolateFn falsy + interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); + value = newValue; + } + + // if attribute was updated so that there is no interpolation going on we don't want to + // register any observers + if (!interpolateFn) return; + + // initialize attr object so that it's ready in case we need the value for isolate + // scope initialization, otherwise the value would not be available from isolate + // directive's linking fn during linking phase + attr[name] = interpolateFn(scope); + + ($$observers[name] || ($$observers[name] = [])).$$inter = true; + (attr.$$observers && attr.$$observers[name].$$scope || scope). + $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { + //special case for class attribute addition + removal + //so that class changes can tap into the animation + //hooks provided by the $animate service. Be sure to + //skip animations when the first digest occurs (when + //both the new and the old values are the same) since + //the CSS classes are the non-interpolated values + if (name === 'class' && newValue != oldValue) { + attr.$updateClass(newValue, oldValue); + } else { + attr.$set(name, newValue); + } + }); + } + }; + } + }); + } + + + /** + * This is a special jqLite.replaceWith, which can replace items which + * have no parents, provided that the containing jqLite collection is provided. + * + * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes + * in the root of the tree. + * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep + * the shell, but replace its DOM node reference. + * @param {Node} newNode The new DOM node. + */ + function replaceWith($rootElement, elementsToRemove, newNode) { + var firstElementToRemove = elementsToRemove[0], + removeCount = elementsToRemove.length, + parent = firstElementToRemove.parentNode, + i, ii; + + if ($rootElement) { + for (i = 0, ii = $rootElement.length; i < ii; i++) { + if ($rootElement[i] == firstElementToRemove) { + $rootElement[i++] = newNode; + for (var j = i, j2 = j + removeCount - 1, + jj = $rootElement.length; + j < jj; j++, j2++) { + if (j2 < jj) { + $rootElement[j] = $rootElement[j2]; + } else { + delete $rootElement[j]; + } + } + $rootElement.length -= removeCount - 1; + + // If the replaced element is also the jQuery .context then replace it + // .context is a deprecated jQuery api, so we should set it only when jQuery set it + // http://api.jquery.com/context/ + if ($rootElement.context === firstElementToRemove) { + $rootElement.context = newNode; + } + break; + } + } + } + + if (parent) { + parent.replaceChild(newNode, firstElementToRemove); + } + + // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it? + var fragment = document.createDocumentFragment(); + fragment.appendChild(firstElementToRemove); + + if (jqLite.hasData(firstElementToRemove)) { + // Copy over user data (that includes Angular's $scope etc.). Don't copy private + // data here because there's no public interface in jQuery to do that and copying over + // event listeners (which is the main use of private data) wouldn't work anyway. + jqLite(newNode).data(jqLite(firstElementToRemove).data()); + + // Remove data of the replaced element. We cannot just call .remove() + // on the element it since that would deallocate scope that is needed + // for the new node. Instead, remove the data "manually". + if (!jQuery) { + delete jqLite.cache[firstElementToRemove[jqLite.expando]]; + } else { + // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after + // the replaced element. The cleanData version monkey-patched by Angular would cause + // the scope to be trashed and we do need the very same scope to work with the new + // element. However, we cannot just cache the non-patched version and use it here as + // that would break if another library patches the method after Angular does (one + // example is jQuery UI). Instead, set a flag indicating scope destroying should be + // skipped this one time. + skipDestroyOnNextJQueryCleanData = true; + jQuery.cleanData([firstElementToRemove]); + } + } + + for (var k = 1, kk = elementsToRemove.length; k < kk; k++) { + var element = elementsToRemove[k]; + jqLite(element).remove(); // must do this way to clean up expando + fragment.appendChild(element); + delete elementsToRemove[k]; + } + + elementsToRemove[0] = newNode; + elementsToRemove.length = 1; + } + + + function cloneAndAnnotateFn(fn, annotation) { + return extend(function() { return fn.apply(null, arguments); }, fn, annotation); + } + + + function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { + try { + linkFn(scope, $element, attrs, controllers, transcludeFn); + } catch (e) { + $exceptionHandler(e, startingTag($element)); + } + } + + + // Set up $watches for isolate scope and controller bindings. This process + // only occurs for isolate scopes and new scopes with controllerAs. + function initializeDirectiveBindings(scope, attrs, destination, bindings, + directive, newScope) { + var onNewScopeDestroyed; + forEach(bindings, function(definition, scopeName) { + var attrName = definition.attrName, + optional = definition.optional, + mode = definition.mode, // @, =, or & + lastValue, + parentGet, parentSet, compare; + + if (!hasOwnProperty.call(attrs, attrName)) { + // In the case of user defined a binding with the same name as a method in Object.prototype but didn't set + // the corresponding attribute. We need to make sure subsequent code won't access to the prototype function + attrs[attrName] = undefined; + } + + switch (mode) { + + case '@': + if (!attrs[attrName] && !optional) { + destination[scopeName] = undefined; + } + + attrs.$observe(attrName, function(value) { + destination[scopeName] = value; + }); + attrs.$$observers[attrName].$$scope = scope; + if (attrs[attrName]) { + // If the attribute has been provided then we trigger an interpolation to ensure + // the value is there for use in the link fn + destination[scopeName] = $interpolate(attrs[attrName])(scope); + } + break; + + case '=': + if (optional && !attrs[attrName]) { + return; + } + parentGet = $parse(attrs[attrName]); + + if (parentGet.literal) { + compare = equals; + } else { + compare = function(a, b) { return a === b || (a !== a && b !== b); }; + } + parentSet = parentGet.assign || function() { + // reset the change, or we will throw this exception on every $digest + lastValue = destination[scopeName] = parentGet(scope); + throw $compileMinErr('nonassign', + "Expression '{0}' used with directive '{1}' is non-assignable!", + attrs[attrName], directive.name); + }; + lastValue = destination[scopeName] = parentGet(scope); + var parentValueWatch = function parentValueWatch(parentValue) { + if (!compare(parentValue, destination[scopeName])) { + // we are out of sync and need to copy + if (!compare(parentValue, lastValue)) { + // parent changed and it has precedence + destination[scopeName] = parentValue; + } else { + // if the parent can be assigned then do so + parentSet(scope, parentValue = destination[scopeName]); + } + } + return lastValue = parentValue; + }; + parentValueWatch.$stateful = true; + var unwatch; + if (definition.collection) { + unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch); + } else { + unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); + } + onNewScopeDestroyed = (onNewScopeDestroyed || []); + onNewScopeDestroyed.push(unwatch); + break; + + case '&': + parentGet = $parse(attrs[attrName]); + + // Don't assign noop to destination if expression is not valid + if (parentGet === noop && optional) break; + + destination[scopeName] = function(locals) { + return parentGet(scope, locals); + }; + break; + } + }); + var destroyBindings = onNewScopeDestroyed ? function destroyBindings() { + for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) { + onNewScopeDestroyed[i](); + } + } : noop; + if (newScope && destroyBindings !== noop) { + newScope.$on('$destroy', destroyBindings); + return noop; + } + return destroyBindings; + } + }]; +} + +var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; +/** + * Converts all accepted directives format into proper directive name. + * @param name Name to normalize + */ +function directiveNormalize(name) { + return camelCase(name.replace(PREFIX_REGEXP, '')); +} + +/** + * @ngdoc type + * @name $compile.directive.Attributes + * + * @description + * A shared object between directive compile / linking functions which contains normalized DOM + * element attributes. The values reflect current binding state `{{ }}`. The normalization is + * needed since all of these are treated as equivalent in Angular: + * + * ``` + * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a"> + * ``` + */ + +/** + * @ngdoc property + * @name $compile.directive.Attributes#$attr + * + * @description + * A map of DOM element attribute names to the normalized name. This is + * needed to do reverse lookup from normalized name back to actual name. + */ + + +/** + * @ngdoc method + * @name $compile.directive.Attributes#$set + * @kind function + * + * @description + * Set DOM element attribute value. + * + * + * @param {string} name Normalized element attribute name of the property to modify. The name is + * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr} + * property to the original name. + * @param {string} value Value to set the attribute to. The value can be an interpolated string. + */ + + + +/** + * Closure compiler type information + */ + +function nodesetLinkingFn( + /* angular.Scope */ scope, + /* NodeList */ nodeList, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function directiveLinkingFn( + /* nodesetLinkingFn */ nodesetLinkingFn, + /* angular.Scope */ scope, + /* Node */ node, + /* Element */ rootElement, + /* function(Function) */ boundTranscludeFn +) {} + +function tokenDifference(str1, str2) { + var values = '', + tokens1 = str1.split(/\s+/), + tokens2 = str2.split(/\s+/); + + outer: + for (var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for (var j = 0; j < tokens2.length; j++) { + if (token == tokens2[j]) continue outer; + } + values += (values.length > 0 ? ' ' : '') + token; + } + return values; +} + +function removeComments(jqNodes) { + jqNodes = jqLite(jqNodes); + var i = jqNodes.length; + + if (i <= 1) { + return jqNodes; + } + + while (i--) { + var node = jqNodes[i]; + if (node.nodeType === NODE_TYPE_COMMENT) { + splice.call(jqNodes, i, 1); + } + } + return jqNodes; +} + +var $controllerMinErr = minErr('$controller'); + + +var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; +function identifierForController(controller, ident) { + if (ident && isString(ident)) return ident; + if (isString(controller)) { + var match = CNTRL_REG.exec(controller); + if (match) return match[3]; + } +} + + +/** + * @ngdoc provider + * @name $controllerProvider + * @description + * The {@link ng.$controller $controller service} is used by Angular to create new + * controllers. + * + * This provider allows controller registration via the + * {@link ng.$controllerProvider#register register} method. + */ +function $ControllerProvider() { + var controllers = {}, + globals = false; + + /** + * @ngdoc method + * @name $controllerProvider#register + * @param {string|Object} name Controller name, or an object map of controllers where the keys are + * the names and the values are the constructors. + * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI + * annotations in the array notation). + */ + this.register = function(name, constructor) { + assertNotHasOwnProperty(name, 'controller'); + if (isObject(name)) { + extend(controllers, name); + } else { + controllers[name] = constructor; + } + }; + + /** + * @ngdoc method + * @name $controllerProvider#allowGlobals + * @description If called, allows `$controller` to find controller constructors on `window` + */ + this.allowGlobals = function() { + globals = true; + }; + + + this.$get = ['$injector', '$window', function($injector, $window) { + + /** + * @ngdoc service + * @name $controller + * @requires $injector + * + * @param {Function|string} constructor If called with a function then it's considered to be the + * controller constructor function. Otherwise it's considered to be a string which is used + * to retrieve the controller constructor using the following steps: + * + * * check if a controller with given name is registered via `$controllerProvider` + * * check if evaluating the string on the current scope returns a constructor + * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global + * `window` object (not recommended) + * + * The string can use the `controller as property` syntax, where the controller instance is published + * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this + * to work correctly. + * + * @param {Object} locals Injection locals for Controller. + * @return {Object} Instance of given controller. + * + * @description + * `$controller` service is responsible for instantiating controllers. + * + * It's just a simple call to {@link auto.$injector $injector}, but extracted into + * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). + */ + return function(expression, locals, later, ident) { + // PRIVATE API: + // param `later` --- indicates that the controller's constructor is invoked at a later time. + // If true, $controller will allocate the object with the correct + // prototype chain, but will not invoke the controller until a returned + // callback is invoked. + // param `ident` --- An optional label which overrides the label parsed from the controller + // expression, if any. + var instance, match, constructor, identifier; + later = later === true; + if (ident && isString(ident)) { + identifier = ident; + } + + if (isString(expression)) { + match = expression.match(CNTRL_REG); + if (!match) { + throw $controllerMinErr('ctrlfmt', + "Badly formed controller string '{0}'. " + + "Must match `__name__ as __id__` or `__name__`.", expression); + } + constructor = match[1], + identifier = identifier || match[3]; + expression = controllers.hasOwnProperty(constructor) + ? controllers[constructor] + : getter(locals.$scope, constructor, true) || + (globals ? getter($window, constructor, true) : undefined); + + assertArgFn(expression, constructor, true); + } + + if (later) { + // Instantiate controller later: + // This machinery is used to create an instance of the object before calling the + // controller's constructor itself. + // + // This allows properties to be added to the controller before the constructor is + // invoked. Primarily, this is used for isolate scope bindings in $compile. + // + // This feature is not intended for use by applications, and is thus not documented + // publicly. + // Object creation: http://jsperf.com/create-constructor/2 + var controllerPrototype = (isArray(expression) ? + expression[expression.length - 1] : expression).prototype; + instance = Object.create(controllerPrototype || null); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + var instantiate; + return instantiate = extend(function() { + var result = $injector.invoke(expression, instance, locals, constructor); + if (result !== instance && (isObject(result) || isFunction(result))) { + instance = result; + if (identifier) { + // If result changed, re-assign controllerAs value to scope. + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + } + return instance; + }, { + instance: instance, + identifier: identifier + }); + } + + instance = $injector.instantiate(expression, locals, constructor); + + if (identifier) { + addIdentifier(locals, identifier, instance, constructor || expression.name); + } + + return instance; + }; + + function addIdentifier(locals, identifier, instance, name) { + if (!(locals && isObject(locals.$scope))) { + throw minErr('$controller')('noscp', + "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.", + name, identifier); + } + + locals.$scope[identifier] = instance; + } + }]; +} + +/** + * @ngdoc service + * @name $document + * @requires $window + * + * @description + * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object. + * + * @example + <example module="documentExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <p>$document title: <b ng-bind="title"></b></p> + <p>window.document title: <b ng-bind="windowTitle"></b></p> + </div> + </file> + <file name="script.js"> + angular.module('documentExample', []) + .controller('ExampleController', ['$scope', '$document', function($scope, $document) { + $scope.title = $document[0].title; + $scope.windowTitle = angular.element(window.document)[0].title; + }]); + </file> + </example> + */ +function $DocumentProvider() { + this.$get = ['$window', function(window) { + return jqLite(window.document); + }]; +} + +/** + * @ngdoc service + * @name $exceptionHandler + * @requires ng.$log + * + * @description + * Any uncaught exception in angular expressions is delegated to this service. + * The default implementation simply delegates to `$log.error` which logs it into + * the browser console. + * + * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by + * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. + * + * ## Example: + * + * ```js + * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() { + * return function(exception, cause) { + * exception.message += ' (caused by "' + cause + '")'; + * throw exception; + * }; + * }); + * ``` + * + * This example will override the normal action of `$exceptionHandler`, to make angular + * exceptions fail hard when they happen, instead of just logging to the console. + * + * <hr /> + * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind` + * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler} + * (unless executed during a digest). + * + * If you wish, you can manually delegate exceptions, e.g. + * `try { ... } catch(e) { $exceptionHandler(e); }` + * + * @param {Error} exception Exception associated with the error. + * @param {string=} cause optional information about the context in which + * the error was thrown. + * + */ +function $ExceptionHandlerProvider() { + this.$get = ['$log', function($log) { + return function(exception, cause) { + $log.error.apply($log, arguments); + }; + }]; +} + +var APPLICATION_JSON = 'application/json'; +var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'}; +var JSON_START = /^\[|^\{(?!\{)/; +var JSON_ENDS = { + '[': /]$/, + '{': /}$/ +}; +var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/; + +function serializeValue(v) { + if (isObject(v)) { + return isDate(v) ? v.toISOString() : toJson(v); + } + return v; +} + + +function $HttpParamSerializerProvider() { + /** + * @ngdoc service + * @name $httpParamSerializer + * @description + * + * Default {@link $http `$http`} params serializer that converts objects to strings + * according to the following rules: + * + * * `{'foo': 'bar'}` results in `foo=bar` + * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object) + * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element) + * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object) + * + * Note that serializer will sort the request parameters alphabetically. + * */ + + this.$get = function() { + return function ngParamSerializer(params) { + if (!params) return ''; + var parts = []; + forEachSorted(params, function(value, key) { + if (value === null || isUndefined(value)) return; + if (isArray(value)) { + forEach(value, function(v, k) { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v))); + }); + } else { + parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value))); + } + }); + + return parts.join('&'); + }; + }; +} + +function $HttpParamSerializerJQLikeProvider() { + /** + * @ngdoc service + * @name $httpParamSerializerJQLike + * @description + * + * Alternative {@link $http `$http`} params serializer that follows + * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic. + * The serializer will also sort the params alphabetically. + * + * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property: + * + * ```js + * $http({ + * url: myUrl, + * method: 'GET', + * params: myParams, + * paramSerializer: '$httpParamSerializerJQLike' + * }); + * ``` + * + * It is also possible to set it as the default `paramSerializer` in the + * {@link $httpProvider#defaults `$httpProvider`}. + * + * Additionally, you can inject the serializer and use it explicitly, for example to serialize + * form data for submission: + * + * ```js + * .controller(function($http, $httpParamSerializerJQLike) { + * //... + * + * $http({ + * url: myUrl, + * method: 'POST', + * data: $httpParamSerializerJQLike(myData), + * headers: { + * 'Content-Type': 'application/x-www-form-urlencoded' + * } + * }); + * + * }); + * ``` + * + * */ + this.$get = function() { + return function jQueryLikeParamSerializer(params) { + if (!params) return ''; + var parts = []; + serialize(params, '', true); + return parts.join('&'); + + function serialize(toSerialize, prefix, topLevel) { + if (toSerialize === null || isUndefined(toSerialize)) return; + if (isArray(toSerialize)) { + forEach(toSerialize, function(value) { + serialize(value, prefix + '[]'); + }); + } else if (isObject(toSerialize) && !isDate(toSerialize)) { + forEachSorted(toSerialize, function(value, key) { + serialize(value, prefix + + (topLevel ? '' : '[') + + key + + (topLevel ? '' : ']')); + }); + } else { + parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize))); + } + } + }; + }; +} + +function defaultHttpResponseTransform(data, headers) { + if (isString(data)) { + // Strip json vulnerability protection prefix and trim whitespace + var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim(); + + if (tempData) { + var contentType = headers('Content-Type'); + if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) { + data = fromJson(tempData); + } + } + } + + return data; +} + +function isJsonLike(str) { + var jsonStart = str.match(JSON_START); + return jsonStart && JSON_ENDS[jsonStart[0]].test(str); +} + +/** + * Parse headers into key value object + * + * @param {string} headers Raw headers as a string + * @returns {Object} Parsed headers as key value object + */ +function parseHeaders(headers) { + var parsed = createMap(), i; + + function fillInParsed(key, val) { + if (key) { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + } + + if (isString(headers)) { + forEach(headers.split('\n'), function(line) { + i = line.indexOf(':'); + fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1))); + }); + } else if (isObject(headers)) { + forEach(headers, function(headerVal, headerKey) { + fillInParsed(lowercase(headerKey), trim(headerVal)); + }); + } + + return parsed; +} + + +/** + * Returns a function that provides access to parsed headers. + * + * Headers are lazy parsed when first requested. + * @see parseHeaders + * + * @param {(string|Object)} headers Headers to provide access to. + * @returns {function(string=)} Returns a getter function which if called with: + * + * - if called with single an argument returns a single header value or null + * - if called with no arguments returns an object containing all headers. + */ +function headersGetter(headers) { + var headersObj; + + return function(name) { + if (!headersObj) headersObj = parseHeaders(headers); + + if (name) { + var value = headersObj[lowercase(name)]; + if (value === void 0) { + value = null; + } + return value; + } + + return headersObj; + }; +} + + +/** + * Chain all given functions + * + * This function is used for both request and response transforming + * + * @param {*} data Data to transform. + * @param {function(string=)} headers HTTP headers getter fn. + * @param {number} status HTTP status code of the response. + * @param {(Function|Array.<Function>)} fns Function or an array of functions. + * @returns {*} Transformed data. + */ +function transformData(data, headers, status, fns) { + if (isFunction(fns)) { + return fns(data, headers, status); + } + + forEach(fns, function(fn) { + data = fn(data, headers, status); + }); + + return data; +} + + +function isSuccess(status) { + return 200 <= status && status < 300; +} + + +/** + * @ngdoc provider + * @name $httpProvider + * @description + * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service. + * */ +function $HttpProvider() { + /** + * @ngdoc property + * @name $httpProvider#defaults + * @description + * + * Object containing default values for all {@link ng.$http $http} requests. + * + * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`} + * that will provide the cache for all requests who set their `cache` property to `true`. + * If you set the `defaults.cache = false` then only requests that specify their own custom + * cache object will be cached. See {@link $http#caching $http Caching} for more information. + * + * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. + * Defaults value is `'XSRF-TOKEN'`. + * + * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the + * XSRF token. Defaults value is `'X-XSRF-TOKEN'`. + * + * - **`defaults.headers`** - {Object} - Default headers for all $http requests. + * Refer to {@link ng.$http#setting-http-headers $http} for documentation on + * setting default headers. + * - **`defaults.headers.common`** + * - **`defaults.headers.post`** + * - **`defaults.headers.put`** + * - **`defaults.headers.patch`** + * + * + * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function + * used to the prepare string representation of request parameters (specified as an object). + * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}. + * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}. + * + **/ + var defaults = this.defaults = { + // transform incoming response data + transformResponse: [defaultHttpResponseTransform], + + // transform outgoing request data + transformRequest: [function(d) { + return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; + }], + + // default headers + headers: { + common: { + 'Accept': 'application/json, text/plain, */*' + }, + post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), + patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) + }, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + paramSerializer: '$httpParamSerializer' + }; + + var useApplyAsync = false; + /** + * @ngdoc method + * @name $httpProvider#useApplyAsync + * @description + * + * Configure $http service to combine processing of multiple http responses received at around + * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in + * significant performance improvement for bigger applications that make many HTTP requests + * concurrently (common during application bootstrap). + * + * Defaults to false. If no value is specified, returns the current configured value. + * + * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred + * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window + * to load and share the same digest cycle. + * + * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. + * otherwise, returns the current configured value. + **/ + this.useApplyAsync = function(value) { + if (isDefined(value)) { + useApplyAsync = !!value; + return this; + } + return useApplyAsync; + }; + + /** + * @ngdoc property + * @name $httpProvider#interceptors + * @description + * + * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http} + * pre-processing of request or postprocessing of responses. + * + * These service factories are ordered by request, i.e. they are applied in the same order as the + * array, on request, but reverse order, on response. + * + * {@link ng.$http#interceptors Interceptors detailed info} **/ var interceptorFactories = this.interceptors = []; - this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector', - function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) { + this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', + function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) { var defaultCache = $cacheFactory('$http'); + /** + * Make sure that default param serializer is exposed as a function + */ + defaults.paramSerializer = isString(defaults.paramSerializer) ? + $injector.get(defaults.paramSerializer) : defaults.paramSerializer; + /** * Interceptors stored in reverse order. Inner interceptors before outer interceptors. * The reversal is needed so that we can build up the interception chain around the @@ -17733,7 +22907,7 @@ function $HttpProvider() { * To add or overwrite these defaults, simply add or remove a property from these configuration * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object * with the lowercased HTTP method name as the key, e.g. - * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }. + * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`. * * The defaults can also be set at runtime via the `$http.defaults` object in the same * fashion. For example: @@ -17757,7 +22931,7 @@ function $HttpProvider() { * headers: { * 'Content-Type': undefined * }, - * data: { test: 'test' }, + * data: { test: 'test' } * } * * $http(req).success(function(){...}).error(function(){...}); @@ -17888,17107 +23062,21620 @@ function $HttpProvider() { * return config; * }, * - * // optional method - * 'requestError': function(rejection) { - * // do something on error - * if (canRecover(rejection)) { - * return responseOrNewPromise - * } - * return $q.reject(rejection); - * }, + * // optional method + * 'requestError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * }, + * + * + * + * // optional method + * 'response': function(response) { + * // do something on success + * return response; + * }, + * + * // optional method + * 'responseError': function(rejection) { + * // do something on error + * if (canRecover(rejection)) { + * return responseOrNewPromise + * } + * return $q.reject(rejection); + * } + * }; + * }); + * + * $httpProvider.interceptors.push('myHttpInterceptor'); + * + * + * // alternatively, register the interceptor via an anonymous factory + * $httpProvider.interceptors.push(function($q, dependency1, dependency2) { + * return { + * 'request': function(config) { + * // same as above + * }, + * + * 'response': function(response) { + * // same as above + * } + * }; + * }); + * ``` + * + * ## Security Considerations + * + * When designing web applications, consider security threats from: + * + * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) + * + * Both server and the client must cooperate in order to eliminate these threats. Angular comes + * pre-configured with strategies that address these issues, but for this to work backend server + * cooperation is required. + * + * ### JSON Vulnerability Protection + * + * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) + * allows third party website to turn your JSON resource URL into + * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To + * counter this your server can prefix all JSON requests with following string `")]}',\n"`. + * Angular will automatically strip the prefix before processing it as JSON. + * + * For example if your server needs to return: + * ```js + * ['one','two'] + * ``` + * + * which is vulnerable to attack, your server can return: + * ```js + * )]}', + * ['one','two'] + * ``` + * + * Angular will strip the prefix, before processing the JSON. + * + * + * ### Cross Site Request Forgery (XSRF) Protection + * + * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which + * an unauthorized site can gain your user's private data. Angular provides a mechanism + * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie + * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only + * JavaScript that runs on your domain could read the cookie, your server can be assured that + * the XHR came from JavaScript running on your domain. The header will not be set for + * cross-domain requests. + * + * To take advantage of this, your server needs to set a token in a JavaScript readable session + * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the + * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure + * that only JavaScript running on your domain could have sent the request. The token must be + * unique for each user and must be verifiable by the server (to prevent the JavaScript from + * making up its own tokens). We recommend that the token is a digest of your site's + * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) + * for added security. + * + * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName + * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time, + * or the per-request config object. + * + * In order to prevent collisions in environments where multiple Angular apps share the + * same domain or subdomain, we recommend that each application uses unique cookie name. + * + * + * @param {object} config Object describing the request to be made and how it should be + * processed. The object has following properties: + * + * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) + * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. + * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized + * with the `paramSerializer` and appended as GET parameters. + * - **data** – `{string|Object}` – Data to be sent as the request message data. + * - **headers** – `{Object}` – Map of strings or functions which return strings representing + * HTTP headers to send to the server. If the return value of a function is null, the + * header will not be sent. Functions accept a config object as an argument. + * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. + * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. + * - **transformRequest** – + * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default Transformations} + * - **transformResponse** – + * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` – + * transform function or an array of such functions. The transform function takes the http + * response body, headers and status and returns its transformed (typically deserialized) version. + * See {@link ng.$http#overriding-the-default-transformations-per-request + * Overriding the Default TransformationjqLiks} + * - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to + * prepare the string representation of request parameters (specified as an object). + * If specified as string, it is interpreted as function registered with the + * {@link $injector $injector}, which means you can create your own serializer + * by registering it as a {@link auto.$provide#service service}. + * The default serializer is the {@link $httpParamSerializer $httpParamSerializer}; + * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike} + * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} + * that should abort the request when resolved. + * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) + * for more information. + * - **responseType** - `{string}` - see + * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype). + * + * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the + * standard `then` method and two http specific methods: `success` and `error`. The `then` + * method takes two arguments a success and an error callback which will be called with a + * response object. The `success` and `error` methods take a single argument - a function that + * will be called when the request succeeds or fails respectively. The arguments passed into + * these functions are destructured representation of the response object passed into the + * `then` method. The response object has these properties: + * + * - **data** – `{string|Object}` – The response body transformed with the transform + * functions. + * - **status** – `{number}` – HTTP status code of the response. + * - **headers** – `{function([headerName])}` – Header getter function. + * - **config** – `{Object}` – The configuration object that was used to generate the request. + * - **statusText** – `{string}` – HTTP status text of the response. + * + * @property {Array.<Object>} pendingRequests Array of config objects for currently pending + * requests. This is primarily meant to be used for debugging purposes. + * + * + * @example +<example module="httpExample"> +<file name="index.html"> + <div ng-controller="FetchController"> + <select ng-model="method" aria-label="Request method"> + <option>GET</option> + <option>JSONP</option> + </select> + <input type="text" ng-model="url" size="80" aria-label="URL" /> + <button id="fetchbtn" ng-click="fetch()">fetch</button><br> + <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button> + <button id="samplejsonpbtn" + ng-click="updateModel('JSONP', + 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')"> + Sample JSONP + </button> + <button id="invalidjsonpbtn" + ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')"> + Invalid JSONP + </button> + <pre>http status code: {{status}}</pre> + <pre>http response data: {{data}}</pre> + </div> +</file> +<file name="script.js"> + angular.module('httpExample', []) + .controller('FetchController', ['$scope', '$http', '$templateCache', + function($scope, $http, $templateCache) { + $scope.method = 'GET'; + $scope.url = 'http-hello.html'; + + $scope.fetch = function() { + $scope.code = null; + $scope.response = null; + + $http({method: $scope.method, url: $scope.url, cache: $templateCache}). + success(function(data, status) { + $scope.status = status; + $scope.data = data; + }). + error(function(data, status) { + $scope.data = data || "Request failed"; + $scope.status = status; + }); + }; + + $scope.updateModel = function(method, url) { + $scope.method = method; + $scope.url = url; + }; + }]); +</file> +<file name="http-hello.html"> + Hello, $http! +</file> +<file name="protractor.js" type="protractor"> + var status = element(by.binding('status')); + var data = element(by.binding('data')); + var fetchBtn = element(by.id('fetchbtn')); + var sampleGetBtn = element(by.id('samplegetbtn')); + var sampleJsonpBtn = element(by.id('samplejsonpbtn')); + var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); + + it('should make an xhr GET request', function() { + sampleGetBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('200'); + expect(data.getText()).toMatch(/Hello, \$http!/); + }); + +// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185 +// it('should make a JSONP request to angularjs.org', function() { +// sampleJsonpBtn.click(); +// fetchBtn.click(); +// expect(status.getText()).toMatch('200'); +// expect(data.getText()).toMatch(/Super Hero!/); +// }); + + it('should make JSONP request to invalid URL and invoke the error handler', + function() { + invalidJsonpBtn.click(); + fetchBtn.click(); + expect(status.getText()).toMatch('0'); + expect(data.getText()).toMatch('Request failed'); + }); +</file> +</example> + */ + function $http(requestConfig) { + + if (!angular.isObject(requestConfig)) { + throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); + } + + var config = extend({ + method: 'get', + transformRequest: defaults.transformRequest, + transformResponse: defaults.transformResponse, + paramSerializer: defaults.paramSerializer + }, requestConfig); + + config.headers = mergeHeaders(requestConfig); + config.method = uppercase(config.method); + config.paramSerializer = isString(config.paramSerializer) ? + $injector.get(config.paramSerializer) : config.paramSerializer; + + var serverRequest = function(config) { + var headers = config.headers; + var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); + + // strip content-type if data is undefined + if (isUndefined(reqData)) { + forEach(headers, function(value, header) { + if (lowercase(header) === 'content-type') { + delete headers[header]; + } + }); + } + + if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { + config.withCredentials = defaults.withCredentials; + } + + // send request + return sendReq(config, reqData).then(transformResponse, transformResponse); + }; + + var chain = [serverRequest, undefined]; + var promise = $q.when(config); + + // apply interceptors + forEach(reversedInterceptors, function(interceptor) { + if (interceptor.request || interceptor.requestError) { + chain.unshift(interceptor.request, interceptor.requestError); + } + if (interceptor.response || interceptor.responseError) { + chain.push(interceptor.response, interceptor.responseError); + } + }); + + while (chain.length) { + var thenFn = chain.shift(); + var rejectFn = chain.shift(); + + promise = promise.then(thenFn, rejectFn); + } + + promise.success = function(fn) { + assertArgFn(fn, 'fn'); + + promise.then(function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + promise.error = function(fn) { + assertArgFn(fn, 'fn'); + + promise.then(null, function(response) { + fn(response.data, response.status, response.headers, config); + }); + return promise; + }; + + return promise; + + function transformResponse(response) { + // make a copy since the response must be cacheable + var resp = extend({}, response); + if (!response.data) { + resp.data = response.data; + } else { + resp.data = transformData(response.data, response.headers, response.status, config.transformResponse); + } + return (isSuccess(response.status)) + ? resp + : $q.reject(resp); + } + + function executeHeaderFns(headers, config) { + var headerContent, processedHeaders = {}; + + forEach(headers, function(headerFn, header) { + if (isFunction(headerFn)) { + headerContent = headerFn(config); + if (headerContent != null) { + processedHeaders[header] = headerContent; + } + } else { + processedHeaders[header] = headerFn; + } + }); + + return processedHeaders; + } + + function mergeHeaders(config) { + var defHeaders = defaults.headers, + reqHeaders = extend({}, config.headers), + defHeaderName, lowercaseDefHeaderName, reqHeaderName; + + defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + + // using for-in instead of forEach to avoid unecessary iteration after header has been found + defaultHeadersIteration: + for (defHeaderName in defHeaders) { + lowercaseDefHeaderName = lowercase(defHeaderName); + + for (reqHeaderName in reqHeaders) { + if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { + continue defaultHeadersIteration; + } + } + + reqHeaders[defHeaderName] = defHeaders[defHeaderName]; + } + + // execute if header value is a function for merged headers + return executeHeaderFns(reqHeaders, shallowCopy(config)); + } + } + + $http.pendingRequests = []; + + /** + * @ngdoc method + * @name $http#get + * + * @description + * Shortcut method to perform `GET` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#delete * + * @description + * Shortcut method to perform `DELETE` request. * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#head * - * // optional method - * 'response': function(response) { - * // do something on success - * return response; - * }, + * @description + * Shortcut method to perform `HEAD` request. * - * // optional method - * 'responseError': function(rejection) { - * // do something on error - * if (canRecover(rejection)) { - * return responseOrNewPromise - * } - * return $q.reject(rejection); - * } - * }; - * }); + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#jsonp * - * $httpProvider.interceptors.push('myHttpInterceptor'); + * @description + * Shortcut method to perform `JSONP` request. * + * @param {string} url Relative or absolute URL specifying the destination of the request. + * The name of the callback should be the string `JSON_CALLBACK`. + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethods('get', 'delete', 'head', 'jsonp'); + + /** + * @ngdoc method + * @name $http#post * - * // alternatively, register the interceptor via an anonymous factory - * $httpProvider.interceptors.push(function($q, dependency1, dependency2) { - * return { - * 'request': function(config) { - * // same as above - * }, + * @description + * Shortcut method to perform `POST` request. * - * 'response': function(response) { - * // same as above - * } - * }; - * }); - * ``` + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#put * - * ## Security Considerations + * @description + * Shortcut method to perform `PUT` request. * - * When designing web applications, consider security threats from: + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + + /** + * @ngdoc method + * @name $http#patch + * + * @description + * Shortcut method to perform `PATCH` request. + * + * @param {string} url Relative or absolute URL specifying the destination of the request + * @param {*} data Request content + * @param {Object=} config Optional configuration object + * @returns {HttpPromise} Future object + */ + createShortMethodsWithData('post', 'put', 'patch'); + + /** + * @ngdoc property + * @name $http#defaults + * + * @description + * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of + * default headers, withCredentials as well as request and response transformations. + * + * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. + */ + $http.defaults = defaults; + + + return $http; + + + function createShortMethods(names) { + forEach(arguments, function(name) { + $http[name] = function(url, config) { + return $http(extend({}, config || {}, { + method: name, + url: url + })); + }; + }); + } + + + function createShortMethodsWithData(name) { + forEach(arguments, function(name) { + $http[name] = function(url, data, config) { + return $http(extend({}, config || {}, { + method: name, + url: url, + data: data + })); + }; + }); + } + + + /** + * Makes the request. * - * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) - * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) + * !!! ACCESSES CLOSURE VARS: + * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests + */ + function sendReq(config, reqData) { + var deferred = $q.defer(), + promise = deferred.promise, + cache, + cachedResp, + reqHeaders = config.headers, + url = buildUrl(config.url, config.paramSerializer(config.params)); + + $http.pendingRequests.push(config); + promise.then(removePendingReq, removePendingReq); + + + if ((config.cache || defaults.cache) && config.cache !== false && + (config.method === 'GET' || config.method === 'JSONP')) { + cache = isObject(config.cache) ? config.cache + : isObject(defaults.cache) ? defaults.cache + : defaultCache; + } + + if (cache) { + cachedResp = cache.get(url); + if (isDefined(cachedResp)) { + if (isPromiseLike(cachedResp)) { + // cached request has already been sent, but there is no response yet + cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); + } else { + // serving from cache + if (isArray(cachedResp)) { + resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]); + } else { + resolvePromise(cachedResp, 200, {}, 'OK'); + } + } + } else { + // put the promise for the non-transformed response into cache as a placeholder + cache.put(url, promise); + } + } + + + // if we won't have the response in cache, set the xsrf headers and + // send the request to the backend + if (isUndefined(cachedResp)) { + var xsrfValue = urlIsSameOrigin(config.url) + ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] + : undefined; + if (xsrfValue) { + reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; + } + + $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, + config.withCredentials, config.responseType); + } + + return promise; + + + /** + * Callback registered to $httpBackend(): + * - caches the response if desired + * - resolves the raw $http promise + * - calls $apply + */ + function done(status, response, headersString, statusText) { + if (cache) { + if (isSuccess(status)) { + cache.put(url, [status, response, parseHeaders(headersString), statusText]); + } else { + // remove promise from the cache + cache.remove(url); + } + } + + function resolveHttpPromise() { + resolvePromise(response, status, headersString, statusText); + } + + if (useApplyAsync) { + $rootScope.$applyAsync(resolveHttpPromise); + } else { + resolveHttpPromise(); + if (!$rootScope.$$phase) $rootScope.$apply(); + } + } + + + /** + * Resolves the raw $http promise. + */ + function resolvePromise(response, status, headers, statusText) { + // normalize internal statuses to 0 + status = Math.max(status, 0); + + (isSuccess(status) ? deferred.resolve : deferred.reject)({ + data: response, + status: status, + headers: headersGetter(headers), + config: config, + statusText: statusText + }); + } + + function resolvePromiseWithResult(result) { + resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText); + } + + function removePendingReq() { + var idx = $http.pendingRequests.indexOf(config); + if (idx !== -1) $http.pendingRequests.splice(idx, 1); + } + } + + + function buildUrl(url, serializedParams) { + if (serializedParams.length > 0) { + url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams; + } + return url; + } + }]; +} + +function createXhr() { + return new window.XMLHttpRequest(); +} + +/** + * @ngdoc service + * @name $httpBackend + * @requires $window + * @requires $document + * + * @description + * HTTP backend used by the {@link ng.$http service} that delegates to + * XMLHttpRequest object or JSONP and deals with browser incompatibilities. + * + * You should never need to use this service directly, instead use the higher-level abstractions: + * {@link ng.$http $http} or {@link ngResource.$resource $resource}. + * + * During testing this implementation is swapped with {@link ngMock.$httpBackend mock + * $httpBackend} which can be trained with responses. + */ +function $HttpBackendProvider() { + this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { + return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + }]; +} + +function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { + // TODO(vojta): fix the signature + return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { + $browser.$$incOutstandingRequestCount(); + url = url || $browser.url(); + + if (lowercase(method) == 'jsonp') { + var callbackId = '_' + (callbacks.counter++).toString(36); + callbacks[callbackId] = function(data) { + callbacks[callbackId].data = data; + callbacks[callbackId].called = true; + }; + + var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), + callbackId, function(status, text) { + completeRequest(callback, status, callbacks[callbackId].data, "", text); + callbacks[callbackId] = noop; + }); + } else { + + var xhr = createXhr(); + + xhr.open(method, url, true); + forEach(headers, function(value, key) { + if (isDefined(value)) { + xhr.setRequestHeader(key, value); + } + }); + + xhr.onload = function requestLoaded() { + var statusText = xhr.statusText || ''; + + // responseText is the old-school way of retrieving response (supported by IE8 & 9) + // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) + var response = ('response' in xhr) ? xhr.response : xhr.responseText; + + // normalize IE9 bug (http://bugs.jquery.com/ticket/1450) + var status = xhr.status === 1223 ? 204 : xhr.status; + + // fix status code when it is 0 (0 status is undocumented). + // Occurs when accessing file resources or on Android 4.1 stock browser + // while retrieving files from application cache. + if (status === 0) { + status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0; + } + + completeRequest(callback, + status, + response, + xhr.getAllResponseHeaders(), + statusText); + }; + + var requestError = function() { + // The response is always empty + // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error + completeRequest(callback, -1, null, null, ''); + }; + + xhr.onerror = requestError; + xhr.onabort = requestError; + + if (withCredentials) { + xhr.withCredentials = true; + } + + if (responseType) { + try { + xhr.responseType = responseType; + } catch (e) { + // WebKit added support for the json responseType value on 09/03/2013 + // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are + // known to throw when setting the value "json" as the response type. Other older + // browsers implementing the responseType + // + // The json response type can be ignored if not supported, because JSON payloads are + // parsed on the client-side regardless. + if (responseType !== 'json') { + throw e; + } + } + } + + xhr.send(post); + } + + if (timeout > 0) { + var timeoutId = $browserDefer(timeoutRequest, timeout); + } else if (isPromiseLike(timeout)) { + timeout.then(timeoutRequest); + } + + + function timeoutRequest() { + jsonpDone && jsonpDone(); + xhr && xhr.abort(); + } + + function completeRequest(callback, status, response, headersString, statusText) { + // cancel timeout and subsequent timeout promise resolution + if (timeoutId !== undefined) { + $browserDefer.cancel(timeoutId); + } + jsonpDone = xhr = null; + + callback(status, response, headersString, statusText); + $browser.$$completeOutstandingRequest(noop); + } + }; + + function jsonpReq(url, callbackId, done) { + // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.: + // - fetches local scripts via XHR and evals them + // - adds and immediately removes script elements from the document + var script = rawDocument.createElement('script'), callback = null; + script.type = "text/javascript"; + script.src = url; + script.async = true; + + callback = function(event) { + removeEventListenerFn(script, "load", callback); + removeEventListenerFn(script, "error", callback); + rawDocument.body.removeChild(script); + script = null; + var status = -1; + var text = "unknown"; + + if (event) { + if (event.type === "load" && !callbacks[callbackId].called) { + event = { type: "error" }; + } + text = event.type; + status = event.type === "error" ? 404 : 200; + } + + if (done) { + done(status, text); + } + }; + + addEventListenerFn(script, "load", callback); + addEventListenerFn(script, "error", callback); + rawDocument.body.appendChild(script); + return callback; + } +} + +var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate'); +$interpolateMinErr.throwNoconcat = function(text) { + throw $interpolateMinErr('noconcat', + "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + + "interpolations that concatenate multiple expressions when a trusted value is " + + "required. See http://docs.angularjs.org/api/ng.$sce", text); +}; + +$interpolateMinErr.interr = function(text, err) { + return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString()); +}; + +/** + * @ngdoc provider + * @name $interpolateProvider + * + * @description + * + * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. + * + * @example +<example module="customInterpolationApp"> +<file name="index.html"> +<script> + var customInterpolationApp = angular.module('customInterpolationApp', []); + + customInterpolationApp.config(function($interpolateProvider) { + $interpolateProvider.startSymbol('//'); + $interpolateProvider.endSymbol('//'); + }); + + + customInterpolationApp.controller('DemoController', function() { + this.label = "This binding is brought you by // interpolation symbols."; + }); +</script> +<div ng-app="App" ng-controller="DemoController as demo"> + //demo.label// +</div> +</file> +<file name="protractor.js" type="protractor"> + it('should interpolate binding with custom symbols', function() { + expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); + }); +</file> +</example> + */ +function $InterpolateProvider() { + var startSymbol = '{{'; + var endSymbol = '}}'; + + /** + * @ngdoc method + * @name $interpolateProvider#startSymbol + * @description + * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. + * + * @param {string=} value new value to set the starting symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.startSymbol = function(value) { + if (value) { + startSymbol = value; + return this; + } else { + return startSymbol; + } + }; + + /** + * @ngdoc method + * @name $interpolateProvider#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * @param {string=} value new value to set the ending symbol to. + * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + */ + this.endSymbol = function(value) { + if (value) { + endSymbol = value; + return this; + } else { + return endSymbol; + } + }; + + + this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) { + var startSymbolLength = startSymbol.length, + endSymbolLength = endSymbol.length, + escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'), + escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g'); + + function escape(ch) { + return '\\\\\\' + ch; + } + + function unescapeText(text) { + return text.replace(escapedStartRegexp, startSymbol). + replace(escapedEndRegexp, endSymbol); + } + + function stringify(value) { + if (value == null) { // null || undefined + return ''; + } + switch (typeof value) { + case 'string': + break; + case 'number': + value = '' + value; + break; + default: + value = toJson(value); + } + + return value; + } + + /** + * @ngdoc service + * @name $interpolate + * @kind function * - * Both server and the client must cooperate in order to eliminate these threats. Angular comes - * pre-configured with strategies that address these issues, but for this to work backend server - * cooperation is required. + * @requires $parse + * @requires $sce * - * ### JSON Vulnerability Protection + * @description * - * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) - * allows third party website to turn your JSON resource URL into - * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To - * counter this your server can prefix all JSON requests with following string `")]}',\n"`. - * Angular will automatically strip the prefix before processing it as JSON. + * Compiles a string with markup into an interpolation function. This service is used by the + * HTML {@link ng.$compile $compile} service for data binding. See + * {@link ng.$interpolateProvider $interpolateProvider} for configuring the + * interpolation markup. * - * For example if your server needs to return: - * ```js - * ['one','two'] - * ``` * - * which is vulnerable to attack, your server can return: * ```js - * )]}', - * ['one','two'] + * var $interpolate = ...; // injected + * var exp = $interpolate('Hello {{name | uppercase}}!'); + * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!'); * ``` * - * Angular will strip the prefix, before processing the JSON. - * - * - * ### Cross Site Request Forgery (XSRF) Protection + * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is + * `true`, the interpolation function will return `undefined` unless all embedded expressions + * evaluate to a value other than `undefined`. * - * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which - * an unauthorized site can gain your user's private data. Angular provides a mechanism - * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie - * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only - * JavaScript that runs on your domain could read the cookie, your server can be assured that - * the XHR came from JavaScript running on your domain. The header will not be set for - * cross-domain requests. + * ```js + * var $interpolate = ...; // injected + * var context = {greeting: 'Hello', name: undefined }; * - * To take advantage of this, your server needs to set a token in a JavaScript readable session - * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the - * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure - * that only JavaScript running on your domain could have sent the request. The token must be - * unique for each user and must be verifiable by the server (to prevent the JavaScript from - * making up its own tokens). We recommend that the token is a digest of your site's - * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) - * for added security. + * // default "forgiving" mode + * var exp = $interpolate('{{greeting}} {{name}}!'); + * expect(exp(context)).toEqual('Hello !'); * - * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName - * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time, - * or the per-request config object. + * // "allOrNothing" mode + * exp = $interpolate('{{greeting}} {{name}}!', false, null, true); + * expect(exp(context)).toBeUndefined(); + * context.name = 'Angular'; + * expect(exp(context)).toEqual('Hello Angular!'); + * ``` * + * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior. * - * @param {object} config Object describing the request to be made and how it should be - * processed. The object has following properties: + * ####Escaped Interpolation + * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers + * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash). + * It will be rendered as a regular start/end marker, and will not be interpreted as an expression + * or binding. * - * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) - * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. - * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned - * to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be - * JSONified. - * - **data** – `{string|Object}` – Data to be sent as the request message data. - * - **headers** – `{Object}` – Map of strings or functions which return strings representing - * HTTP headers to send to the server. If the return value of a function is null, the - * header will not be sent. - * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. - * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. - * - **transformRequest** – - * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` – - * transform function or an array of such functions. The transform function takes the http - * request body and headers and returns its transformed (typically serialized) version. - * See {@link ng.$http#overriding-the-default-transformations-per-request - * Overriding the Default Transformations} - * - **transformResponse** – - * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` – - * transform function or an array of such functions. The transform function takes the http - * response body, headers and status and returns its transformed (typically deserialized) version. - * See {@link ng.$http#overriding-the-default-transformations-per-request - * Overriding the Default Transformations} - * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the - * GET request, otherwise if a cache instance built with - * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for - * caching. - * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} - * that should abort the request when resolved. - * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the - * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) - * for more information. - * - **responseType** - `{string}` - see - * [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType). + * This enables web-servers to prevent script injection attacks and defacing attacks, to some + * degree, while also enabling code examples to work without relying on the + * {@link ng.directive:ngNonBindable ngNonBindable} directive. * - * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the - * standard `then` method and two http specific methods: `success` and `error`. The `then` - * method takes two arguments a success and an error callback which will be called with a - * response object. The `success` and `error` methods take a single argument - a function that - * will be called when the request succeeds or fails respectively. The arguments passed into - * these functions are destructured representation of the response object passed into the - * `then` method. The response object has these properties: + * **For security purposes, it is strongly encouraged that web servers escape user-supplied data, + * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all + * interpolation start/end markers with their escaped counterparts.** * - * - **data** – `{string|Object}` – The response body transformed with the transform - * functions. - * - **status** – `{number}` – HTTP status code of the response. - * - **headers** – `{function([headerName])}` – Header getter function. - * - **config** – `{Object}` – The configuration object that was used to generate the request. - * - **statusText** – `{string}` – HTTP status text of the response. + * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered + * output when the $interpolate service processes the text. So, for HTML elements interpolated + * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter + * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such, + * this is typically useful only when user-data is used in rendering a template from the server, or + * when otherwise untrusted data is used by a directive. * - * @property {Array.<Object>} pendingRequests Array of config objects for currently pending - * requests. This is primarily meant to be used for debugging purposes. + * <example> + * <file name="index.html"> + * <div ng-init="username='A user'"> + * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\} + * </p> + * <p><strong>{{username}}</strong> attempts to inject code which will deface the + * application, but fails to accomplish their task, because the server has correctly + * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash) + * characters.</p> + * <p>Instead, the result of the attempted script injection is visible, and can be removed + * from the database by an administrator.</p> + * </div> + * </file> + * </example> * + * @param {string} text The text with markup to interpolate. + * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have + * embedded expression in order to return an interpolation function. Strings with no + * embedded expression will return null for the interpolation function. + * @param {string=} trustedContext when provided, the returned function passes the interpolated + * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult, + * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that + * provides Strict Contextual Escaping for details. + * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined + * unless all embedded expressions evaluate to a value other than `undefined`. + * @returns {function(context)} an interpolation function which is used to compute the + * interpolated string. The function has these parameters: * - * @example -<example module="httpExample"> -<file name="index.html"> - <div ng-controller="FetchController"> - <select ng-model="method"> - <option>GET</option> - <option>JSONP</option> - </select> - <input type="text" ng-model="url" size="80"/> - <button id="fetchbtn" ng-click="fetch()">fetch</button><br> - <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button> - <button id="samplejsonpbtn" - ng-click="updateModel('JSONP', - 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')"> - Sample JSONP - </button> - <button id="invalidjsonpbtn" - ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')"> - Invalid JSONP - </button> - <pre>http status code: {{status}}</pre> - <pre>http response data: {{data}}</pre> - </div> -</file> -<file name="script.js"> - angular.module('httpExample', []) - .controller('FetchController', ['$scope', '$http', '$templateCache', - function($scope, $http, $templateCache) { - $scope.method = 'GET'; - $scope.url = 'http-hello.html'; + * - `context`: evaluation context for all expressions embedded in the interpolated text + */ + function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { + allOrNothing = !!allOrNothing; + var startIndex, + endIndex, + index = 0, + expressions = [], + parseFns = [], + textLength = text.length, + exp, + concat = [], + expressionPositions = []; - $scope.fetch = function() { - $scope.code = null; - $scope.response = null; + while (index < textLength) { + if (((startIndex = text.indexOf(startSymbol, index)) != -1) && + ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) { + if (index !== startIndex) { + concat.push(unescapeText(text.substring(index, startIndex))); + } + exp = text.substring(startIndex + startSymbolLength, endIndex); + expressions.push(exp); + parseFns.push($parse(exp, parseStringifyInterceptor)); + index = endIndex + endSymbolLength; + expressionPositions.push(concat.length); + concat.push(''); + } else { + // we did not find an interpolation, so we have to add the remainder to the separators array + if (index !== textLength) { + concat.push(unescapeText(text.substring(index))); + } + break; + } + } - $http({method: $scope.method, url: $scope.url, cache: $templateCache}). - success(function(data, status) { - $scope.status = status; - $scope.data = data; - }). - error(function(data, status) { - $scope.data = data || "Request failed"; - $scope.status = status; - }); + // Concatenating expressions makes it hard to reason about whether some combination of + // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a + // single expression be used for iframe[src], object[src], etc., we ensure that the value + // that's used is assigned or constructed by some JS code somewhere that is more testable or + // make it obvious that you bound the value to some user controlled value. This helps reduce + // the load when auditing for XSS issues. + if (trustedContext && concat.length > 1) { + $interpolateMinErr.throwNoconcat(text); + } + + if (!mustHaveExpression || expressions.length) { + var compute = function(values) { + for (var i = 0, ii = expressions.length; i < ii; i++) { + if (allOrNothing && isUndefined(values[i])) return; + concat[expressionPositions[i]] = values[i]; + } + return concat.join(''); }; - $scope.updateModel = function(method, url) { - $scope.method = method; - $scope.url = url; + var getValue = function(value) { + return trustedContext ? + $sce.getTrusted(trustedContext, value) : + $sce.valueOf(value); }; - }]); -</file> -<file name="http-hello.html"> - Hello, $http! -</file> -<file name="protractor.js" type="protractor"> - var status = element(by.binding('status')); - var data = element(by.binding('data')); - var fetchBtn = element(by.id('fetchbtn')); - var sampleGetBtn = element(by.id('samplegetbtn')); - var sampleJsonpBtn = element(by.id('samplejsonpbtn')); - var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); - it('should make an xhr GET request', function() { - sampleGetBtn.click(); - fetchBtn.click(); - expect(status.getText()).toMatch('200'); - expect(data.getText()).toMatch(/Hello, \$http!/); - }); + return extend(function interpolationFn(context) { + var i = 0; + var ii = expressions.length; + var values = new Array(ii); -// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185 -// it('should make a JSONP request to angularjs.org', function() { -// sampleJsonpBtn.click(); -// fetchBtn.click(); -// expect(status.getText()).toMatch('200'); -// expect(data.getText()).toMatch(/Super Hero!/); -// }); + try { + for (; i < ii; i++) { + values[i] = parseFns[i](context); + } - it('should make JSONP request to invalid URL and invoke the error handler', - function() { - invalidJsonpBtn.click(); - fetchBtn.click(); - expect(status.getText()).toMatch('0'); - expect(data.getText()).toMatch('Request failed'); - }); -</file> -</example> - */ - function $http(requestConfig) { + return compute(values); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } - if (!angular.isObject(requestConfig)) { - throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); + }, { + // all of these properties are undocumented for now + exp: text, //just for compatibility with regular watchers created via $watch + expressions: expressions, + $$watchDelegate: function(scope, listener) { + var lastValue; + return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { + var currValue = compute(values); + if (isFunction(listener)) { + listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); + } + lastValue = currValue; + }); + } + }); + } + + function parseStringifyInterceptor(value) { + try { + value = getValue(value); + return allOrNothing && !isDefined(value) ? value : stringify(value); + } catch (err) { + $exceptionHandler($interpolateMinErr.interr(text, err)); + } } + } + + + /** + * @ngdoc method + * @name $interpolate#startSymbol + * @description + * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`. + * + * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change + * the symbol. + * + * @returns {string} start symbol. + */ + $interpolate.startSymbol = function() { + return startSymbol; + }; + + + /** + * @ngdoc method + * @name $interpolate#endSymbol + * @description + * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * + * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change + * the symbol. + * + * @returns {string} end symbol. + */ + $interpolate.endSymbol = function() { + return endSymbol; + }; + + return $interpolate; + }]; +} + +function $IntervalProvider() { + this.$get = ['$rootScope', '$window', '$q', '$$q', + function($rootScope, $window, $q, $$q) { + var intervals = {}; + + + /** + * @ngdoc service + * @name $interval + * + * @description + * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay` + * milliseconds. + * + * The return value of registering an interval function is a promise. This promise will be + * notified upon each tick of the interval, and will be resolved after `count` iterations, or + * run indefinitely if `count` is not defined. The value of the notification will be the + * number of iterations that have run. + * To cancel an interval, call `$interval.cancel(promise)`. + * + * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + * <div class="alert alert-warning"> + * **Note**: Intervals created by this service must be explicitly destroyed when you are finished + * with them. In particular they are not automatically destroyed when a controller's scope or a + * directive's element are destroyed. + * You should take this into consideration and make sure to always cancel the interval at the + * appropriate moment. See the example below for more details on how and when to do this. + * </div> + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. + * @returns {promise} A promise which will be notified on each iteration. + * + * @example + * <example module="intervalExample"> + * <file name="index.html"> + * <script> + * angular.module('intervalExample', []) + * .controller('ExampleController', ['$scope', '$interval', + * function($scope, $interval) { + * $scope.format = 'M/d/yy h:mm:ss a'; + * $scope.blood_1 = 100; + * $scope.blood_2 = 120; + * + * var stop; + * $scope.fight = function() { + * // Don't start a new fight if we are already fighting + * if ( angular.isDefined(stop) ) return; + * + * stop = $interval(function() { + * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) { + * $scope.blood_1 = $scope.blood_1 - 3; + * $scope.blood_2 = $scope.blood_2 - 4; + * } else { + * $scope.stopFight(); + * } + * }, 100); + * }; + * + * $scope.stopFight = function() { + * if (angular.isDefined(stop)) { + * $interval.cancel(stop); + * stop = undefined; + * } + * }; + * + * $scope.resetFight = function() { + * $scope.blood_1 = 100; + * $scope.blood_2 = 120; + * }; + * + * $scope.$on('$destroy', function() { + * // Make sure that the interval is destroyed too + * $scope.stopFight(); + * }); + * }]) + * // Register the 'myCurrentTime' directive factory method. + * // We inject $interval and dateFilter service since the factory method is DI. + * .directive('myCurrentTime', ['$interval', 'dateFilter', + * function($interval, dateFilter) { + * // return the directive link function. (compile function not needed) + * return function(scope, element, attrs) { + * var format, // date format + * stopTime; // so that we can cancel the time updates + * + * // used to update the UI + * function updateTime() { + * element.text(dateFilter(new Date(), format)); + * } + * + * // watch the expression, and update the UI on change. + * scope.$watch(attrs.myCurrentTime, function(value) { + * format = value; + * updateTime(); + * }); + * + * stopTime = $interval(updateTime, 1000); + * + * // listen on DOM destroy (removal) event, and cancel the next UI update + * // to prevent updating time after the DOM element was removed. + * element.on('$destroy', function() { + * $interval.cancel(stopTime); + * }); + * } + * }]); + * </script> + * + * <div> + * <div ng-controller="ExampleController"> + * <label>Date format: <input ng-model="format"></label> <hr/> + * Current time is: <span my-current-time="format"></span> + * <hr/> + * Blood 1 : <font color='red'>{{blood_1}}</font> + * Blood 2 : <font color='red'>{{blood_2}}</font> + * <button type="button" data-ng-click="fight()">Fight</button> + * <button type="button" data-ng-click="stopFight()">StopFight</button> + * <button type="button" data-ng-click="resetFight()">resetFight</button> + * </div> + * </div> + * + * </file> + * </example> + */ + function interval(fn, delay, count, invokeApply) { + var hasParams = arguments.length > 4, + args = hasParams ? sliceArgs(arguments, 4) : [], + setInterval = $window.setInterval, + clearInterval = $window.clearInterval, + iteration = 0, + skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise; - var config = extend({ - method: 'get', - transformRequest: defaults.transformRequest, - transformResponse: defaults.transformResponse - }, requestConfig); + count = isDefined(count) ? count : 0; - config.headers = mergeHeaders(requestConfig); - config.method = uppercase(config.method); + promise.then(null, null, (!hasParams) ? fn : function() { + fn.apply(null, args); + }); - var serverRequest = function(config) { - var headers = config.headers; - var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); + promise.$$intervalId = setInterval(function tick() { + deferred.notify(iteration++); - // strip content-type if data is undefined - if (isUndefined(reqData)) { - forEach(headers, function(value, header) { - if (lowercase(header) === 'content-type') { - delete headers[header]; - } - }); + if (count > 0 && iteration >= count) { + deferred.resolve(iteration); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; } - if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { - config.withCredentials = defaults.withCredentials; - } + if (!skipApply) $rootScope.$apply(); - // send request - return sendReq(config, reqData).then(transformResponse, transformResponse); - }; + }, delay); - var chain = [serverRequest, undefined]; - var promise = $q.when(config); + intervals[promise.$$intervalId] = deferred; - // apply interceptors - forEach(reversedInterceptors, function(interceptor) { - if (interceptor.request || interceptor.requestError) { - chain.unshift(interceptor.request, interceptor.requestError); - } - if (interceptor.response || interceptor.responseError) { - chain.push(interceptor.response, interceptor.responseError); - } - }); + return promise; + } - while (chain.length) { - var thenFn = chain.shift(); - var rejectFn = chain.shift(); - promise = promise.then(thenFn, rejectFn); + /** + * @ngdoc method + * @name $interval#cancel + * + * @description + * Cancels a task associated with the `promise`. + * + * @param {promise} promise returned by the `$interval` function. + * @returns {boolean} Returns `true` if the task was successfully canceled. + */ + interval.cancel = function(promise) { + if (promise && promise.$$intervalId in intervals) { + intervals[promise.$$intervalId].reject('canceled'); + $window.clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + return true; } + return false; + }; - promise.success = function(fn) { - promise.then(function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; + return interval; + }]; +} - promise.error = function(fn) { - promise.then(null, function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; +/** + * @ngdoc service + * @name $locale + * + * @description + * $locale service provides localization rules for various Angular components. As of right now the + * only public api is: + * + * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) + */ +function $LocaleProvider() { + this.$get = function() { + return { + id: 'en-us', - return promise; + NUMBER_FORMATS: { + DECIMAL_SEP: '.', + GROUP_SEP: ',', + PATTERNS: [ + { // Decimal Pattern + minInt: 1, + minFrac: 0, + maxFrac: 3, + posPre: '', + posSuf: '', + negPre: '-', + negSuf: '', + gSize: 3, + lgSize: 3 + },{ //Currency Pattern + minInt: 1, + minFrac: 2, + maxFrac: 2, + posPre: '\u00A4', + posSuf: '', + negPre: '(\u00A4', + negSuf: ')', + gSize: 3, + lgSize: 3 + } + ], + CURRENCY_SYM: '$' + }, - function transformResponse(response) { - // make a copy since the response must be cacheable - var resp = extend({}, response); - if (!response.data) { - resp.data = response.data; - } else { - resp.data = transformData(response.data, response.headers, response.status, config.transformResponse); + DATETIME_FORMATS: { + MONTH: + 'January,February,March,April,May,June,July,August,September,October,November,December' + .split(','), + SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), + DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), + SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), + AMPMS: ['AM','PM'], + medium: 'MMM d, y h:mm:ss a', + 'short': 'M/d/yy h:mm a', + fullDate: 'EEEE, MMMM d, y', + longDate: 'MMMM d, y', + mediumDate: 'MMM d, y', + shortDate: 'M/d/yy', + mediumTime: 'h:mm:ss a', + shortTime: 'h:mm a', + ERANAMES: [ + "Before Christ", + "Anno Domini" + ], + ERAS: [ + "BC", + "AD" + ] + }, + + pluralCat: function(num) { + if (num === 1) { + return 'one'; } - return (isSuccess(response.status)) - ? resp - : $q.reject(resp); + return 'other'; } + }; + }; +} - function executeHeaderFns(headers) { - var headerContent, processedHeaders = {}; +var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, + DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; +var $locationMinErr = minErr('$location'); - forEach(headers, function(headerFn, header) { - if (isFunction(headerFn)) { - headerContent = headerFn(); - if (headerContent != null) { - processedHeaders[header] = headerContent; - } - } else { - processedHeaders[header] = headerFn; - } - }); - return processedHeaders; - } +/** + * Encode path using encodeUriSegment, ignoring forward slashes + * + * @param {string} path Path to encode + * @returns {string} + */ +function encodePath(path) { + var segments = path.split('/'), + i = segments.length; - function mergeHeaders(config) { - var defHeaders = defaults.headers, - reqHeaders = extend({}, config.headers), - defHeaderName, lowercaseDefHeaderName, reqHeaderName; + while (i--) { + segments[i] = encodeUriSegment(segments[i]); + } - defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + return segments.join('/'); +} - // using for-in instead of forEach to avoid unecessary iteration after header has been found - defaultHeadersIteration: - for (defHeaderName in defHeaders) { - lowercaseDefHeaderName = lowercase(defHeaderName); +function parseAbsoluteUrl(absoluteUrl, locationObj) { + var parsedUrl = urlResolve(absoluteUrl); - for (reqHeaderName in reqHeaders) { - if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { - continue defaultHeadersIteration; - } - } + locationObj.$$protocol = parsedUrl.protocol; + locationObj.$$host = parsedUrl.hostname; + locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; +} - reqHeaders[defHeaderName] = defHeaders[defHeaderName]; - } - // execute if header value is a function for merged headers - return executeHeaderFns(reqHeaders); - } - } +function parseAppUrl(relativeUrl, locationObj) { + var prefixed = (relativeUrl.charAt(0) !== '/'); + if (prefixed) { + relativeUrl = '/' + relativeUrl; + } + var match = urlResolve(relativeUrl); + locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? + match.pathname.substring(1) : match.pathname); + locationObj.$$search = parseKeyValue(match.search); + locationObj.$$hash = decodeURIComponent(match.hash); - $http.pendingRequests = []; + // make sure path starts with '/'; + if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') { + locationObj.$$path = '/' + locationObj.$$path; + } +} - /** - * @ngdoc method - * @name $http#get - * - * @description - * Shortcut method to perform `GET` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - /** - * @ngdoc method - * @name $http#delete - * - * @description - * Shortcut method to perform `DELETE` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ +/** + * + * @param {string} begin + * @param {string} whole + * @returns {string} returns text from whole after begin or undefined if it does not begin with + * expected string. + */ +function beginsWith(begin, whole) { + if (whole.indexOf(begin) === 0) { + return whole.substr(begin.length); + } +} - /** - * @ngdoc method - * @name $http#head - * - * @description - * Shortcut method to perform `HEAD` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - /** - * @ngdoc method - * @name $http#jsonp - * - * @description - * Shortcut method to perform `JSONP` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request. - * The name of the callback should be the string `JSON_CALLBACK`. - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - createShortMethods('get', 'delete', 'head', 'jsonp'); +function stripHash(url) { + var index = url.indexOf('#'); + return index == -1 ? url : url.substr(0, index); +} - /** - * @ngdoc method - * @name $http#post - * - * @description - * Shortcut method to perform `POST` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ +function trimEmptyHash(url) { + return url.replace(/(#.+)|#$/, '$1'); +} - /** - * @ngdoc method - * @name $http#put - * - * @description - * Shortcut method to perform `PUT` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - /** - * @ngdoc method - * @name $http#patch - * - * @description - * Shortcut method to perform `PATCH` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - createShortMethodsWithData('post', 'put', 'patch'); +function stripFile(url) { + return url.substr(0, stripHash(url).lastIndexOf('/') + 1); +} - /** - * @ngdoc property - * @name $http#defaults - * - * @description - * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of - * default headers, withCredentials as well as request and response transformations. - * - * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. - */ - $http.defaults = defaults; +/* return the server only (scheme://host:port) */ +function serverBase(url) { + return url.substring(0, url.indexOf('/', url.indexOf('//') + 2)); +} - return $http; +/** + * LocationHtml5Url represents an url + * This object is exposed as $location service when HTML5 mode is enabled and supported + * + * @constructor + * @param {string} appBase application base URL + * @param {string} basePrefix url path prefix + */ +function LocationHtml5Url(appBase, basePrefix) { + this.$$html5 = true; + basePrefix = basePrefix || ''; + var appBaseNoFile = stripFile(appBase); + parseAbsoluteUrl(appBase, this); - function createShortMethods(names) { - forEach(arguments, function(name) { - $http[name] = function(url, config) { - return $http(extend(config || {}, { - method: name, - url: url - })); - }; - }); + /** + * Parse given html5 (regular) url string into properties + * @param {string} url HTML5 url + * @private + */ + this.$$parse = function(url) { + var pathUrl = beginsWith(appBaseNoFile, url); + if (!isString(pathUrl)) { + throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, + appBaseNoFile); } + parseAppUrl(pathUrl, this); - function createShortMethodsWithData(name) { - forEach(arguments, function(name) { - $http[name] = function(url, data, config) { - return $http(extend(config || {}, { - method: name, - url: url, - data: data - })); - }; - }); + if (!this.$$path) { + this.$$path = '/'; } + this.$$compose(); + }; - /** - * Makes the request. - * - * !!! ACCESSES CLOSURE VARS: - * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests - */ - function sendReq(config, reqData) { - var deferred = $q.defer(), - promise = deferred.promise, - cache, - cachedResp, - reqHeaders = config.headers, - url = buildUrl(config.url, config.params); - - $http.pendingRequests.push(config); - promise.then(removePendingReq, removePendingReq); + /** + * Compose url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/' + }; - if ((config.cache || defaults.cache) && config.cache !== false && - (config.method === 'GET' || config.method === 'JSONP')) { - cache = isObject(config.cache) ? config.cache - : isObject(defaults.cache) ? defaults.cache - : defaultCache; - } + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + var appUrl, prevAppUrl; + var rewrittenUrl; - if (cache) { - cachedResp = cache.get(url); - if (isDefined(cachedResp)) { - if (isPromiseLike(cachedResp)) { - // cached request has already been sent, but there is no response yet - cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); - } else { - // serving from cache - if (isArray(cachedResp)) { - resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]); - } else { - resolvePromise(cachedResp, 200, {}, 'OK'); - } - } - } else { - // put the promise for the non-transformed response into cache as a placeholder - cache.put(url, promise); - } + if ((appUrl = beginsWith(appBase, url)) !== undefined) { + prevAppUrl = appUrl; + if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) { + rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl); + } else { + rewrittenUrl = appBase + prevAppUrl; } + } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) { + rewrittenUrl = appBaseNoFile + appUrl; + } else if (appBaseNoFile == url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; +} - // if we won't have the response in cache, set the xsrf headers and - // send the request to the backend - if (isUndefined(cachedResp)) { - var xsrfValue = urlIsSameOrigin(config.url) - ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName] - : undefined; - if (xsrfValue) { - reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; - } +/** + * LocationHashbangUrl represents url + * This object is exposed as $location service when developer doesn't opt into html5 mode. + * It also serves as the base class for html5 mode fallback on legacy browsers. + * + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix + */ +function LocationHashbangUrl(appBase, hashPrefix) { + var appBaseNoFile = stripFile(appBase); - $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, - config.withCredentials, config.responseType); - } + parseAbsoluteUrl(appBase, this); - return promise; + /** + * Parse given hashbang url into properties + * @param {string} url Hashbang url + * @private + */ + this.$$parse = function(url) { + var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); + var withoutHashUrl; - /** - * Callback registered to $httpBackend(): - * - caches the response if desired - * - resolves the raw $http promise - * - calls $apply - */ - function done(status, response, headersString, statusText) { - if (cache) { - if (isSuccess(status)) { - cache.put(url, [status, response, parseHeaders(headersString), statusText]); - } else { - // remove promise from the cache - cache.remove(url); - } - } + if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') { - function resolveHttpPromise() { - resolvePromise(response, status, headersString, statusText); - } + // The rest of the url starts with a hash so we have + // got either a hashbang path or a plain hash fragment + withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl); + if (isUndefined(withoutHashUrl)) { + // There was no hashbang prefix so we just have a hash fragment + withoutHashUrl = withoutBaseUrl; + } - if (useApplyAsync) { - $rootScope.$applyAsync(resolveHttpPromise); - } else { - resolveHttpPromise(); - if (!$rootScope.$$phase) $rootScope.$apply(); + } else { + // There was no hashbang path nor hash fragment: + // If we are in HTML5 mode we use what is left as the path; + // Otherwise we ignore what is left + if (this.$$html5) { + withoutHashUrl = withoutBaseUrl; + } else { + withoutHashUrl = ''; + if (isUndefined(withoutBaseUrl)) { + appBase = url; + this.replace(); } } + } + parseAppUrl(withoutHashUrl, this); - /** - * Resolves the raw $http promise. - */ - function resolvePromise(response, status, headers, statusText) { - // normalize internal statuses to 0 - status = Math.max(status, 0); + this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); - (isSuccess(status) ? deferred.resolve : deferred.reject)({ - data: response, - status: status, - headers: headersGetter(headers), - config: config, - statusText: statusText - }); - } + this.$$compose(); - function resolvePromiseWithResult(result) { - resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText); + /* + * In Windows, on an anchor node on documents loaded from + * the filesystem, the browser will return a pathname + * prefixed with the drive name ('/C:/path') when a + * pathname without a drive is set: + * * a.setAttribute('href', '/foo') + * * a.pathname === '/C:/foo' //true + * + * Inside of Angular, we're always using pathnames that + * do not include drive names for routing. + */ + function removeWindowsDriveName(path, url, base) { + /* + Matches paths for file protocol on windows, + such as /C:/foo/bar, and captures only /foo/bar. + */ + var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; + + var firstPathSegmentMatch; + + //Get the relative path from the input URL. + if (url.indexOf(base) === 0) { + url = url.replace(base, ''); } - function removePendingReq() { - var idx = $http.pendingRequests.indexOf(config); - if (idx !== -1) $http.pendingRequests.splice(idx, 1); + // The input URL intentionally contains a first path segment that ends with a colon. + if (windowsFilePathExp.exec(url)) { + return path; } + + firstPathSegmentMatch = windowsFilePathExp.exec(path); + return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; } + }; + /** + * Compose hashbang url and update `absUrl` property + * @private + */ + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; - function buildUrl(url, params) { - if (!params) return url; - var parts = []; - forEachSorted(params, function(value, key) { - if (value === null || isUndefined(value)) return; - if (!isArray(value)) value = [value]; + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ''); + }; - forEach(value, function(v) { - if (isObject(v)) { - if (isDate(v)) { - v = v.toISOString(); - } else { - v = toJson(v); - } - } - parts.push(encodeUriQuery(key) + '=' + - encodeUriQuery(v)); - }); - }); - if (parts.length > 0) { - url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); - } - return url; + this.$$parseLinkUrl = function(url, relHref) { + if (stripHash(appBase) == stripHash(url)) { + this.$$parse(url); + return true; } - }]; + return false; + }; } -function createXhr() { - return new window.XMLHttpRequest(); -} /** - * @ngdoc service - * @name $httpBackend - * @requires $window - * @requires $document - * - * @description - * HTTP backend used by the {@link ng.$http service} that delegates to - * XMLHttpRequest object or JSONP and deals with browser incompatibilities. - * - * You should never need to use this service directly, instead use the higher-level abstractions: - * {@link ng.$http $http} or {@link ngResource.$resource $resource}. + * LocationHashbangUrl represents url + * This object is exposed as $location service when html5 history api is enabled but the browser + * does not support it. * - * During testing this implementation is swapped with {@link ngMock.$httpBackend mock - * $httpBackend} which can be trained with responses. + * @constructor + * @param {string} appBase application base URL + * @param {string} hashPrefix hashbang prefix */ -function $HttpBackendProvider() { - this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); - }]; +function LocationHashbangInHtml5Url(appBase, hashPrefix) { + this.$$html5 = true; + LocationHashbangUrl.apply(this, arguments); + + var appBaseNoFile = stripFile(appBase); + + this.$$parseLinkUrl = function(url, relHref) { + if (relHref && relHref[0] === '#') { + // special case for links to hash fragments: + // keep the old url and only replace the hash fragment + this.hash(relHref.slice(1)); + return true; + } + + var rewrittenUrl; + var appUrl; + + if (appBase == stripHash(url)) { + rewrittenUrl = url; + } else if ((appUrl = beginsWith(appBaseNoFile, url))) { + rewrittenUrl = appBase + hashPrefix + appUrl; + } else if (appBaseNoFile === url + '/') { + rewrittenUrl = appBaseNoFile; + } + if (rewrittenUrl) { + this.$$parse(rewrittenUrl); + } + return !!rewrittenUrl; + }; + + this.$$compose = function() { + var search = toKeyValue(this.$$search), + hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + + this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; + // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#' + this.$$absUrl = appBase + hashPrefix + this.$$url; + }; + } -function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { - // TODO(vojta): fix the signature - return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { - $browser.$$incOutstandingRequestCount(); - url = url || $browser.url(); - if (lowercase(method) == 'jsonp') { - var callbackId = '_' + (callbacks.counter++).toString(36); - callbacks[callbackId] = function(data) { - callbacks[callbackId].data = data; - callbacks[callbackId].called = true; - }; +var locationPrototype = { - var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), - callbackId, function(status, text) { - completeRequest(callback, status, callbacks[callbackId].data, "", text); - callbacks[callbackId] = noop; - }); - } else { + /** + * Are we in html5 mode? + * @private + */ + $$html5: false, - var xhr = createXhr(); + /** + * Has any change been replacing? + * @private + */ + $$replace: false, - xhr.open(method, url, true); - forEach(headers, function(value, key) { - if (isDefined(value)) { - xhr.setRequestHeader(key, value); - } - }); + /** + * @ngdoc method + * @name $location#absUrl + * + * @description + * This method is getter only. + * + * Return full url representation with all segments encoded according to rules specified in + * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt). + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var absUrl = $location.absUrl(); + * // => "http://example.com/#/some/path?foo=bar&baz=xoxo" + * ``` + * + * @return {string} full url + */ + absUrl: locationGetter('$$absUrl'), - xhr.onload = function requestLoaded() { - var statusText = xhr.statusText || ''; + /** + * @ngdoc method + * @name $location#url + * + * @description + * This method is getter / setter. + * + * Return url (e.g. `/path?a=b#hash`) when called without any parameter. + * + * Change path, search and hash, when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var url = $location.url(); + * // => "/some/path?foo=bar&baz=xoxo" + * ``` + * + * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`) + * @return {string} url + */ + url: function(url) { + if (isUndefined(url)) { + return this.$$url; + } - // responseText is the old-school way of retrieving response (supported by IE8 & 9) - // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) - var response = ('response' in xhr) ? xhr.response : xhr.responseText; + var match = PATH_MATCH.exec(url); + if (match[1] || url === '') this.path(decodeURIComponent(match[1])); + if (match[2] || match[1] || url === '') this.search(match[3] || ''); + this.hash(match[5] || ''); - // normalize IE9 bug (http://bugs.jquery.com/ticket/1450) - var status = xhr.status === 1223 ? 204 : xhr.status; + return this; + }, - // fix status code when it is 0 (0 status is undocumented). - // Occurs when accessing file resources or on Android 4.1 stock browser - // while retrieving files from application cache. - if (status === 0) { - status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0; - } + /** + * @ngdoc method + * @name $location#protocol + * + * @description + * This method is getter only. + * + * Return protocol of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var protocol = $location.protocol(); + * // => "http" + * ``` + * + * @return {string} protocol of current url + */ + protocol: locationGetter('$$protocol'), - completeRequest(callback, - status, - response, - xhr.getAllResponseHeaders(), - statusText); - }; + /** + * @ngdoc method + * @name $location#host + * + * @description + * This method is getter only. + * + * Return host of current url. + * + * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var host = $location.host(); + * // => "example.com" + * + * // given url http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo + * host = $location.host(); + * // => "example.com" + * host = location.host; + * // => "example.com:8080" + * ``` + * + * @return {string} host of current url. + */ + host: locationGetter('$$host'), - var requestError = function() { - // The response is always empty - // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error - completeRequest(callback, -1, null, null, ''); - }; + /** + * @ngdoc method + * @name $location#port + * + * @description + * This method is getter only. + * + * Return port of current url. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var port = $location.port(); + * // => 80 + * ``` + * + * @return {Number} port + */ + port: locationGetter('$$port'), - xhr.onerror = requestError; - xhr.onabort = requestError; + /** + * @ngdoc method + * @name $location#path + * + * @description + * This method is getter / setter. + * + * Return path of current url when called without any parameter. + * + * Change path when called with parameter and return `$location`. + * + * Note: Path should always begin with forward slash (/), this method will add the forward slash + * if it is missing. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var path = $location.path(); + * // => "/some/path" + * ``` + * + * @param {(string|number)=} path New path + * @return {string} path + */ + path: locationGetterSetter('$$path', function(path) { + path = path !== null ? path.toString() : ''; + return path.charAt(0) == '/' ? path : '/' + path; + }), - if (withCredentials) { - xhr.withCredentials = true; - } + /** + * @ngdoc method + * @name $location#search + * + * @description + * This method is getter / setter. + * + * Return search part (as object) of current url when called without any parameter. + * + * Change search part when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo + * var searchObject = $location.search(); + * // => {foo: 'bar', baz: 'xoxo'} + * + * // set foo to 'yipee' + * $location.search('foo', 'yipee'); + * // $location.search() => {foo: 'yipee', baz: 'xoxo'} + * ``` + * + * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or + * hash object. + * + * When called with a single argument the method acts as a setter, setting the `search` component + * of `$location` to the specified value. + * + * If the argument is a hash object containing an array of values, these values will be encoded + * as duplicate search parameters in the url. + * + * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue` + * will override only a single search property. + * + * If `paramValue` is an array, it will override the property of the `search` component of + * `$location` specified via the first argument. + * + * If `paramValue` is `null`, the property specified via the first argument will be deleted. + * + * If `paramValue` is `true`, the property specified via the first argument will be added with no + * value nor trailing equal sign. + * + * @return {Object} If called with no arguments returns the parsed `search` object. If called with + * one or more arguments returns `$location` object itself. + */ + search: function(search, paramValue) { + switch (arguments.length) { + case 0: + return this.$$search; + case 1: + if (isString(search) || isNumber(search)) { + search = search.toString(); + this.$$search = parseKeyValue(search); + } else if (isObject(search)) { + search = copy(search, {}); + // remove object undefined or null properties + forEach(search, function(value, key) { + if (value == null) delete search[key]; + }); + + this.$$search = search; + } else { + throw $locationMinErr('isrcharg', + 'The first argument of the `$location#search()` call must be a string or an object.'); + } + break; + default: + if (isUndefined(paramValue) || paramValue === null) { + delete this.$$search[search]; + } else { + this.$$search[search] = paramValue; + } + } + + this.$$compose(); + return this; + }, + + /** + * @ngdoc method + * @name $location#hash + * + * @description + * This method is getter / setter. + * + * Return hash fragment when called without any parameter. + * + * Change hash fragment when called with parameter and return `$location`. + * + * + * ```js + * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue + * var hash = $location.hash(); + * // => "hashValue" + * ``` + * + * @param {(string|number)=} hash New hash fragment + * @return {string} hash + */ + hash: locationGetterSetter('$$hash', function(hash) { + return hash !== null ? hash.toString() : ''; + }), + + /** + * @ngdoc method + * @name $location#replace + * + * @description + * If called, all changes to $location during current `$digest` will be replacing current history + * record, instead of adding new one. + */ + replace: function() { + this.$$replace = true; + return this; + } +}; - if (responseType) { - try { - xhr.responseType = responseType; - } catch (e) { - // WebKit added support for the json responseType value on 09/03/2013 - // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are - // known to throw when setting the value "json" as the response type. Other older - // browsers implementing the responseType - // - // The json response type can be ignored if not supported, because JSON payloads are - // parsed on the client-side regardless. - if (responseType !== 'json') { - throw e; - } - } - } +forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) { + Location.prototype = Object.create(locationPrototype); - xhr.send(post || null); + /** + * @ngdoc method + * @name $location#state + * + * @description + * This method is getter / setter. + * + * Return the history state object when called without any parameter. + * + * Change the history state object when called with one parameter and return `$location`. + * The state object is later passed to `pushState` or `replaceState`. + * + * NOTE: This method is supported only in HTML5 mode and only in browsers supporting + * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support + * older browsers (like IE9 or Android < 4.0), don't use this method. + * + * @param {object=} state State object for pushState or replaceState + * @return {object} state + */ + Location.prototype.state = function(state) { + if (!arguments.length) { + return this.$$state; } - if (timeout > 0) { - var timeoutId = $browserDefer(timeoutRequest, timeout); - } else if (isPromiseLike(timeout)) { - timeout.then(timeoutRequest); + if (Location !== LocationHtml5Url || !this.$$html5) { + throw $locationMinErr('nostate', 'History API state support is available only ' + + 'in HTML5 mode and only in browsers supporting HTML5 History API'); } + // The user might modify `stateObject` after invoking `$location.state(stateObject)` + // but we're changing the $$state reference to $browser.state() during the $digest + // so the modification window is narrow. + this.$$state = isUndefined(state) ? null : state; + return this; + }; +}); - function timeoutRequest() { - jsonpDone && jsonpDone(); - xhr && xhr.abort(); - } - - function completeRequest(callback, status, response, headersString, statusText) { - // cancel timeout and subsequent timeout promise resolution - if (timeoutId !== undefined) { - $browserDefer.cancel(timeoutId); - } - jsonpDone = xhr = null; - callback(status, response, headersString, statusText); - $browser.$$completeOutstandingRequest(noop); - } +function locationGetter(property) { + return function() { + return this[property]; }; +} - function jsonpReq(url, callbackId, done) { - // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.: - // - fetches local scripts via XHR and evals them - // - adds and immediately removes script elements from the document - var script = rawDocument.createElement('script'), callback = null; - script.type = "text/javascript"; - script.src = url; - script.async = true; - - callback = function(event) { - removeEventListenerFn(script, "load", callback); - removeEventListenerFn(script, "error", callback); - rawDocument.body.removeChild(script); - script = null; - var status = -1; - var text = "unknown"; - if (event) { - if (event.type === "load" && !callbacks[callbackId].called) { - event = { type: "error" }; - } - text = event.type; - status = event.type === "error" ? 404 : 200; - } +function locationGetterSetter(property, preprocess) { + return function(value) { + if (isUndefined(value)) { + return this[property]; + } - if (done) { - done(status, text); - } - }; + this[property] = preprocess(value); + this.$$compose(); - addEventListenerFn(script, "load", callback); - addEventListenerFn(script, "error", callback); - rawDocument.body.appendChild(script); - return callback; - } + return this; + }; } -var $interpolateMinErr = minErr('$interpolate'); /** - * @ngdoc provider - * @name $interpolateProvider + * @ngdoc service + * @name $location + * + * @requires $rootElement * * @description + * The $location service parses the URL in the browser address bar (based on the + * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL + * available to your application. Changes to the URL in the address bar are reflected into + * $location service and changes to $location are reflected into the browser address bar. * - * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. + * **The $location service:** * - * @example -<example module="customInterpolationApp"> -<file name="index.html"> -<script> - var customInterpolationApp = angular.module('customInterpolationApp', []); - - customInterpolationApp.config(function($interpolateProvider) { - $interpolateProvider.startSymbol('//'); - $interpolateProvider.endSymbol('//'); - }); - + * - Exposes the current URL in the browser address bar, so you can + * - Watch and observe the URL. + * - Change the URL. + * - Synchronizes the URL with the browser when the user + * - Changes the address bar. + * - Clicks the back or forward button (or clicks a History link). + * - Clicks on a link. + * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). + * + * For more information see {@link guide/$location Developer Guide: Using $location} + */ - customInterpolationApp.controller('DemoController', function() { - this.label = "This binding is brought you by // interpolation symbols."; - }); -</script> -<div ng-app="App" ng-controller="DemoController as demo"> - //demo.label// -</div> -</file> -<file name="protractor.js" type="protractor"> - it('should interpolate binding with custom symbols', function() { - expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); - }); -</file> -</example> +/** + * @ngdoc provider + * @name $locationProvider + * @description + * Use the `$locationProvider` to configure how the application deep linking paths are stored. */ -function $InterpolateProvider() { - var startSymbol = '{{'; - var endSymbol = '}}'; +function $LocationProvider() { + var hashPrefix = '', + html5Mode = { + enabled: false, + requireBase: true, + rewriteLinks: true + }; /** * @ngdoc method - * @name $interpolateProvider#startSymbol + * @name $locationProvider#hashPrefix * @description - * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. - * - * @param {string=} value new value to set the starting symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + * @param {string=} prefix Prefix for hash part (containing path and search) + * @returns {*} current value if used as getter or itself (chaining) if used as setter */ - this.startSymbol = function(value) { - if (value) { - startSymbol = value; + this.hashPrefix = function(prefix) { + if (isDefined(prefix)) { + hashPrefix = prefix; return this; } else { - return startSymbol; + return hashPrefix; } }; /** * @ngdoc method - * @name $interpolateProvider#endSymbol + * @name $locationProvider#html5Mode * @description - * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. + * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value. + * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported + * properties: + * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to + * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not + * support `pushState`. + * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies + * whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are + * true, and a base tag is not present, an error will be thrown when `$location` is injected. + * See the {@link guide/$location $location guide for more information} + * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled, + * enables/disables url rewriting for relative links. * - * @param {string=} value new value to set the ending symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. + * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter */ - this.endSymbol = function(value) { - if (value) { - endSymbol = value; + this.html5Mode = function(mode) { + if (isBoolean(mode)) { + html5Mode.enabled = mode; + return this; + } else if (isObject(mode)) { + + if (isBoolean(mode.enabled)) { + html5Mode.enabled = mode.enabled; + } + + if (isBoolean(mode.requireBase)) { + html5Mode.requireBase = mode.requireBase; + } + + if (isBoolean(mode.rewriteLinks)) { + html5Mode.rewriteLinks = mode.rewriteLinks; + } + return this; } else { - return endSymbol; + return html5Mode; } }; + /** + * @ngdoc event + * @name $location#$locationChangeStart + * @eventType broadcast on root scope + * @description + * Broadcasted before a URL will change. + * + * This change can be prevented by calling + * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more + * details about event object. Upon successful change + * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ - this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) { - var startSymbolLength = startSymbol.length, - endSymbolLength = endSymbol.length, - escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'), - escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g'); + /** + * @ngdoc event + * @name $location#$locationChangeSuccess + * @eventType broadcast on root scope + * @description + * Broadcasted after a URL was changed. + * + * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when + * the browser supports the HTML5 History API. + * + * @param {Object} angularEvent Synthetic event object. + * @param {string} newUrl New URL + * @param {string=} oldUrl URL that was before it was changed. + * @param {string=} newState New history state object + * @param {string=} oldState History state object that was before it was changed. + */ - function escape(ch) { - return '\\\\\\' + ch; + this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window', + function($rootScope, $browser, $sniffer, $rootElement, $window) { + var $location, + LocationMode, + baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to '' + initialUrl = $browser.url(), + appBase; + + if (html5Mode.enabled) { + if (!baseHref && html5Mode.requireBase) { + throw $locationMinErr('nobase', + "$location in HTML5 mode requires a <base> tag to be present!"); + } + appBase = serverBase(initialUrl) + (baseHref || '/'); + LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; + } else { + appBase = stripHash(initialUrl); + LocationMode = LocationHashbangUrl; } + $location = new LocationMode(appBase, '#' + hashPrefix); + $location.$$parseLinkUrl(initialUrl, initialUrl); - /** - * @ngdoc service - * @name $interpolate - * @kind function - * - * @requires $parse - * @requires $sce - * - * @description - * - * Compiles a string with markup into an interpolation function. This service is used by the - * HTML {@link ng.$compile $compile} service for data binding. See - * {@link ng.$interpolateProvider $interpolateProvider} for configuring the - * interpolation markup. - * - * - * ```js - * var $interpolate = ...; // injected - * var exp = $interpolate('Hello {{name | uppercase}}!'); - * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!'); - * ``` - * - * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is - * `true`, the interpolation function will return `undefined` unless all embedded expressions - * evaluate to a value other than `undefined`. - * - * ```js - * var $interpolate = ...; // injected - * var context = {greeting: 'Hello', name: undefined }; - * - * // default "forgiving" mode - * var exp = $interpolate('{{greeting}} {{name}}!'); - * expect(exp(context)).toEqual('Hello !'); - * - * // "allOrNothing" mode - * exp = $interpolate('{{greeting}} {{name}}!', false, null, true); - * expect(exp(context)).toBeUndefined(); - * context.name = 'Angular'; - * expect(exp(context)).toEqual('Hello Angular!'); - * ``` - * - * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior. - * - * ####Escaped Interpolation - * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers - * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash). - * It will be rendered as a regular start/end marker, and will not be interpreted as an expression - * or binding. - * - * This enables web-servers to prevent script injection attacks and defacing attacks, to some - * degree, while also enabling code examples to work without relying on the - * {@link ng.directive:ngNonBindable ngNonBindable} directive. - * - * **For security purposes, it is strongly encouraged that web servers escape user-supplied data, - * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all - * interpolation start/end markers with their escaped counterparts.** - * - * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered - * output when the $interpolate service processes the text. So, for HTML elements interpolated - * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter - * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such, - * this is typically useful only when user-data is used in rendering a template from the server, or - * when otherwise untrusted data is used by a directive. - * - * <example> - * <file name="index.html"> - * <div ng-init="username='A user'"> - * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\} - * </p> - * <p><strong>{{username}}</strong> attempts to inject code which will deface the - * application, but fails to accomplish their task, because the server has correctly - * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash) - * characters.</p> - * <p>Instead, the result of the attempted script injection is visible, and can be removed - * from the database by an administrator.</p> - * </div> - * </file> - * </example> - * - * @param {string} text The text with markup to interpolate. - * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have - * embedded expression in order to return an interpolation function. Strings with no - * embedded expression will return null for the interpolation function. - * @param {string=} trustedContext when provided, the returned function passes the interpolated - * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult, - * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that - * provides Strict Contextual Escaping for details. - * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined - * unless all embedded expressions evaluate to a value other than `undefined`. - * @returns {function(context)} an interpolation function which is used to compute the - * interpolated string. The function has these parameters: - * - * - `context`: evaluation context for all expressions embedded in the interpolated text - */ - function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { - allOrNothing = !!allOrNothing; - var startIndex, - endIndex, - index = 0, - expressions = [], - parseFns = [], - textLength = text.length, - exp, - concat = [], - expressionPositions = []; + $location.$$state = $browser.state(); - while (index < textLength) { - if (((startIndex = text.indexOf(startSymbol, index)) != -1) && - ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) { - if (index !== startIndex) { - concat.push(unescapeText(text.substring(index, startIndex))); - } - exp = text.substring(startIndex + startSymbolLength, endIndex); - expressions.push(exp); - parseFns.push($parse(exp, parseStringifyInterceptor)); - index = endIndex + endSymbolLength; - expressionPositions.push(concat.length); - concat.push(''); - } else { - // we did not find an interpolation, so we have to add the remainder to the separators array - if (index !== textLength) { - concat.push(unescapeText(text.substring(index))); - } - break; - } - } + var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; - // Concatenating expressions makes it hard to reason about whether some combination of - // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a - // single expression be used for iframe[src], object[src], etc., we ensure that the value - // that's used is assigned or constructed by some JS code somewhere that is more testable or - // make it obvious that you bound the value to some user controlled value. This helps reduce - // the load when auditing for XSS issues. - if (trustedContext && concat.length > 1) { - throw $interpolateMinErr('noconcat', - "Error while interpolating: {0}\nStrict Contextual Escaping disallows " + - "interpolations that concatenate multiple expressions when a trusted value is " + - "required. See http://docs.angularjs.org/api/ng.$sce", text); + function setBrowserUrlWithFallback(url, replace, state) { + var oldUrl = $location.url(); + var oldState = $location.$$state; + try { + $browser.url(url, replace, state); + + // Make sure $location.state() returns referentially identical (not just deeply equal) + // state object; this makes possible quick checking if the state changed in the digest + // loop. Checking deep equality would be too expensive. + $location.$$state = $browser.state(); + } catch (e) { + // Restore old values if pushState fails + $location.url(oldUrl); + $location.$$state = oldState; + + throw e; } + } - if (!mustHaveExpression || expressions.length) { - var compute = function(values) { - for (var i = 0, ii = expressions.length; i < ii; i++) { - if (allOrNothing && isUndefined(values[i])) return; - concat[expressionPositions[i]] = values[i]; - } - return concat.join(''); - }; + $rootElement.on('click', function(event) { + // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) + // currently we open nice url link and redirect then - var getValue = function(value) { - return trustedContext ? - $sce.getTrusted(trustedContext, value) : - $sce.valueOf(value); - }; + if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return; - var stringify = function(value) { - if (value == null) { // null || undefined - return ''; - } - switch (typeof value) { - case 'string': - break; - case 'number': - value = '' + value; - break; - default: - value = toJson(value); - } + var elm = jqLite(event.target); - return value; - }; + // traverse the DOM up to find first A tag + while (nodeName_(elm[0]) !== 'a') { + // ignore rewriting if no A tag (reached root element, or no parent - removed from document) + if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; + } - return extend(function interpolationFn(context) { - var i = 0; - var ii = expressions.length; - var values = new Array(ii); + var absHref = elm.prop('href'); + // get the actual href attribute - see + // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx + var relHref = elm.attr('href') || elm.attr('xlink:href'); - try { - for (; i < ii; i++) { - values[i] = parseFns[i](context); - } + if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') { + // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during + // an animation. + absHref = urlResolve(absHref.animVal).href; + } - return compute(values); - } catch (err) { - var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, - err.toString()); - $exceptionHandler(newErr); - } + // Ignore when url is started with javascript: or mailto: + if (IGNORE_URI_REGEXP.test(absHref)) return; - }, { - // all of these properties are undocumented for now - exp: text, //just for compatibility with regular watchers created via $watch - expressions: expressions, - $$watchDelegate: function(scope, listener, objectEquality) { - var lastValue; - return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) { - var currValue = compute(values); - if (isFunction(listener)) { - listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); - } - lastValue = currValue; - }, objectEquality); + if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) { + if ($location.$$parseLinkUrl(absHref, relHref)) { + // We do a preventDefault for all urls that are part of the angular application, + // in html5mode and also without, so that we are able to abort navigation without + // getting double entries in the location history. + event.preventDefault(); + // update location manually + if ($location.absUrl() != $browser.url()) { + $rootScope.$apply(); + // hack to work around FF6 bug 684208 when scenario runner clicks on links + $window.angular['ff-684208-preventDefault'] = true; } - }); + } } + }); - function unescapeText(text) { - return text.replace(escapedStartRegexp, startSymbol). - replace(escapedEndRegexp, endSymbol); - } - function parseStringifyInterceptor(value) { - try { - value = getValue(value); - return allOrNothing && !isDefined(value) ? value : stringify(value); - } catch (err) { - var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, - err.toString()); - $exceptionHandler(newErr); - } - } + // rewrite hashbang url <> html5 url + if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) { + $browser.url($location.absUrl(), true); } + var initializing = true; - /** - * @ngdoc method - * @name $interpolate#startSymbol - * @description - * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`. - * - * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change - * the symbol. - * - * @returns {string} start symbol. - */ - $interpolate.startSymbol = function() { - return startSymbol; - }; - + // update $location when $browser url changes + $browser.onUrlChange(function(newUrl, newState) { + $rootScope.$evalAsync(function() { + var oldUrl = $location.absUrl(); + var oldState = $location.$$state; + var defaultPrevented; - /** - * @ngdoc method - * @name $interpolate#endSymbol - * @description - * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. - * - * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change - * the symbol. - * - * @returns {string} end symbol. - */ - $interpolate.endSymbol = function() { - return endSymbol; - }; + $location.$$parse(newUrl); + $location.$$state = newState; - return $interpolate; - }]; -} + defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + newState, oldState).defaultPrevented; -function $IntervalProvider() { - this.$get = ['$rootScope', '$window', '$q', '$$q', - function($rootScope, $window, $q, $$q) { - var intervals = {}; + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + setBrowserUrlWithFallback(oldUrl, false, oldState); + } else { + initializing = false; + afterLocationChange(oldUrl, oldState); + } + }); + if (!$rootScope.$$phase) $rootScope.$digest(); + }); - /** - * @ngdoc service - * @name $interval - * - * @description - * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay` - * milliseconds. - * - * The return value of registering an interval function is a promise. This promise will be - * notified upon each tick of the interval, and will be resolved after `count` iterations, or - * run indefinitely if `count` is not defined. The value of the notification will be the - * number of iterations that have run. - * To cancel an interval, call `$interval.cancel(promise)`. - * - * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to - * move forward by `millis` milliseconds and trigger any functions scheduled to run in that - * time. - * - * <div class="alert alert-warning"> - * **Note**: Intervals created by this service must be explicitly destroyed when you are finished - * with them. In particular they are not automatically destroyed when a controller's scope or a - * directive's element are destroyed. - * You should take this into consideration and make sure to always cancel the interval at the - * appropriate moment. See the example below for more details on how and when to do this. - * </div> - * - * @param {function()} fn A function that should be called repeatedly. - * @param {number} delay Number of milliseconds between each function call. - * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat - * indefinitely. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. - * @returns {promise} A promise which will be notified on each iteration. - * - * @example - * <example module="intervalExample"> - * <file name="index.html"> - * <script> - * angular.module('intervalExample', []) - * .controller('ExampleController', ['$scope', '$interval', - * function($scope, $interval) { - * $scope.format = 'M/d/yy h:mm:ss a'; - * $scope.blood_1 = 100; - * $scope.blood_2 = 120; - * - * var stop; - * $scope.fight = function() { - * // Don't start a new fight if we are already fighting - * if ( angular.isDefined(stop) ) return; - * - * stop = $interval(function() { - * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) { - * $scope.blood_1 = $scope.blood_1 - 3; - * $scope.blood_2 = $scope.blood_2 - 4; - * } else { - * $scope.stopFight(); - * } - * }, 100); - * }; - * - * $scope.stopFight = function() { - * if (angular.isDefined(stop)) { - * $interval.cancel(stop); - * stop = undefined; - * } - * }; - * - * $scope.resetFight = function() { - * $scope.blood_1 = 100; - * $scope.blood_2 = 120; - * }; - * - * $scope.$on('$destroy', function() { - * // Make sure that the interval is destroyed too - * $scope.stopFight(); - * }); - * }]) - * // Register the 'myCurrentTime' directive factory method. - * // We inject $interval and dateFilter service since the factory method is DI. - * .directive('myCurrentTime', ['$interval', 'dateFilter', - * function($interval, dateFilter) { - * // return the directive link function. (compile function not needed) - * return function(scope, element, attrs) { - * var format, // date format - * stopTime; // so that we can cancel the time updates - * - * // used to update the UI - * function updateTime() { - * element.text(dateFilter(new Date(), format)); - * } - * - * // watch the expression, and update the UI on change. - * scope.$watch(attrs.myCurrentTime, function(value) { - * format = value; - * updateTime(); - * }); - * - * stopTime = $interval(updateTime, 1000); - * - * // listen on DOM destroy (removal) event, and cancel the next UI update - * // to prevent updating time after the DOM element was removed. - * element.on('$destroy', function() { - * $interval.cancel(stopTime); - * }); - * } - * }]); - * </script> - * - * <div> - * <div ng-controller="ExampleController"> - * Date format: <input ng-model="format"> <hr/> - * Current time is: <span my-current-time="format"></span> - * <hr/> - * Blood 1 : <font color='red'>{{blood_1}}</font> - * Blood 2 : <font color='red'>{{blood_2}}</font> - * <button type="button" data-ng-click="fight()">Fight</button> - * <button type="button" data-ng-click="stopFight()">StopFight</button> - * <button type="button" data-ng-click="resetFight()">resetFight</button> - * </div> - * </div> - * - * </file> - * </example> - */ - function interval(fn, delay, count, invokeApply) { - var setInterval = $window.setInterval, - clearInterval = $window.clearInterval, - iteration = 0, - skipApply = (isDefined(invokeApply) && !invokeApply), - deferred = (skipApply ? $$q : $q).defer(), - promise = deferred.promise; + // update browser + $rootScope.$watch(function $locationWatch() { + var oldUrl = trimEmptyHash($browser.url()); + var newUrl = trimEmptyHash($location.absUrl()); + var oldState = $browser.state(); + var currentReplace = $location.$$replace; + var urlOrStateChanged = oldUrl !== newUrl || + ($location.$$html5 && $sniffer.history && oldState !== $location.$$state); - count = isDefined(count) ? count : 0; + if (initializing || urlOrStateChanged) { + initializing = false; - promise.then(null, null, fn); + $rootScope.$evalAsync(function() { + var newUrl = $location.absUrl(); + var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, + $location.$$state, oldState).defaultPrevented; - promise.$$intervalId = setInterval(function tick() { - deferred.notify(iteration++); + // if the location was changed by a `$locationChangeStart` handler then stop + // processing this location change + if ($location.absUrl() !== newUrl) return; - if (count > 0 && iteration >= count) { - deferred.resolve(iteration); - clearInterval(promise.$$intervalId); - delete intervals[promise.$$intervalId]; - } + if (defaultPrevented) { + $location.$$parse(oldUrl); + $location.$$state = oldState; + } else { + if (urlOrStateChanged) { + setBrowserUrlWithFallback(newUrl, currentReplace, + oldState === $location.$$state ? null : $location.$$state); + } + afterLocationChange(oldUrl, oldState); + } + }); + } - if (!skipApply) $rootScope.$apply(); + $location.$$replace = false; - }, delay); + // we don't need to return anything because $evalAsync will make the digest loop dirty when + // there is a change + }); - intervals[promise.$$intervalId] = deferred; + return $location; - return promise; + function afterLocationChange(oldUrl, oldState) { + $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl, + $location.$$state, oldState); } - - - /** - * @ngdoc method - * @name $interval#cancel - * - * @description - * Cancels a task associated with the `promise`. - * - * @param {promise} promise returned by the `$interval` function. - * @returns {boolean} Returns `true` if the task was successfully canceled. - */ - interval.cancel = function(promise) { - if (promise && promise.$$intervalId in intervals) { - intervals[promise.$$intervalId].reject('canceled'); - $window.clearInterval(promise.$$intervalId); - delete intervals[promise.$$intervalId]; - return true; - } - return false; - }; - - return interval; - }]; +}]; } /** * @ngdoc service - * @name $locale + * @name $log + * @requires $window * * @description - * $locale service provides localization rules for various Angular components. As of right now the - * only public api is: + * Simple service for logging. Default implementation safely writes the message + * into the browser's console (if present). * - * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) + * The main purpose of this service is to simplify debugging and troubleshooting. + * + * The default is to log `debug` messages. You can use + * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this. + * + * @example + <example module="logExample"> + <file name="script.js"> + angular.module('logExample', []) + .controller('LogController', ['$scope', '$log', function($scope, $log) { + $scope.$log = $log; + $scope.message = 'Hello World!'; + }]); + </file> + <file name="index.html"> + <div ng-controller="LogController"> + <p>Reload this page with open console, enter text and hit the log button...</p> + <label>Message: + <input type="text" ng-model="message" /></label> + <button ng-click="$log.log(message)">log</button> + <button ng-click="$log.warn(message)">warn</button> + <button ng-click="$log.info(message)">info</button> + <button ng-click="$log.error(message)">error</button> + <button ng-click="$log.debug(message)">debug</button> + </div> + </file> + </example> */ -function $LocaleProvider() { - this.$get = function() { + +/** + * @ngdoc provider + * @name $logProvider + * @description + * Use the `$logProvider` to configure how the application logs messages + */ +function $LogProvider() { + var debug = true, + self = this; + + /** + * @ngdoc method + * @name $logProvider#debugEnabled + * @description + * @param {boolean=} flag enable or disable debug level messages + * @returns {*} current value if used as getter or itself (chaining) if used as setter + */ + this.debugEnabled = function(flag) { + if (isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = ['$window', function($window) { return { - id: 'en-us', + /** + * @ngdoc method + * @name $log#log + * + * @description + * Write a log message + */ + log: consoleLog('log'), - NUMBER_FORMATS: { - DECIMAL_SEP: '.', - GROUP_SEP: ',', - PATTERNS: [ - { // Decimal Pattern - minInt: 1, - minFrac: 0, - maxFrac: 3, - posPre: '', - posSuf: '', - negPre: '-', - negSuf: '', - gSize: 3, - lgSize: 3 - },{ //Currency Pattern - minInt: 1, - minFrac: 2, - maxFrac: 2, - posPre: '\u00A4', - posSuf: '', - negPre: '(\u00A4', - negSuf: ')', - gSize: 3, - lgSize: 3 - } - ], - CURRENCY_SYM: '$' - }, + /** + * @ngdoc method + * @name $log#info + * + * @description + * Write an information message + */ + info: consoleLog('info'), - DATETIME_FORMATS: { - MONTH: - 'January,February,March,April,May,June,July,August,September,October,November,December' - .split(','), - SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), - DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), - SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), - AMPMS: ['AM','PM'], - medium: 'MMM d, y h:mm:ss a', - 'short': 'M/d/yy h:mm a', - fullDate: 'EEEE, MMMM d, y', - longDate: 'MMMM d, y', - mediumDate: 'MMM d, y', - shortDate: 'M/d/yy', - mediumTime: 'h:mm:ss a', - shortTime: 'h:mm a' - }, + /** + * @ngdoc method + * @name $log#warn + * + * @description + * Write a warning message + */ + warn: consoleLog('warn'), - pluralCat: function(num) { - if (num === 1) { - return 'one'; - } - return 'other'; - } + /** + * @ngdoc method + * @name $log#error + * + * @description + * Write an error message + */ + error: consoleLog('error'), + + /** + * @ngdoc method + * @name $log#debug + * + * @description + * Write a debug message + */ + debug: (function() { + var fn = consoleLog('debug'); + + return function() { + if (debug) { + fn.apply(self, arguments); + } + }; + }()) }; - }; -} -var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/, - DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; -var $locationMinErr = minErr('$location'); + function formatError(arg) { + if (arg instanceof Error) { + if (arg.stack) { + arg = (arg.message && arg.stack.indexOf(arg.message) === -1) + ? 'Error: ' + arg.message + '\n' + arg.stack + : arg.stack; + } else if (arg.sourceURL) { + arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; + } + } + return arg; + } + function consoleLog(type) { + var console = $window.console || {}, + logFn = console[type] || console.log || noop, + hasApply = false; -/** - * Encode path using encodeUriSegment, ignoring forward slashes - * - * @param {string} path Path to encode - * @returns {string} - */ -function encodePath(path) { - var segments = path.split('/'), - i = segments.length; + // Note: reading logFn.apply throws an error in IE11 in IE8 document mode. + // The reason behind this is that console.log has type "object" in IE8... + try { + hasApply = !!logFn.apply; + } catch (e) {} - while (i--) { - segments[i] = encodeUriSegment(segments[i]); - } + if (hasApply) { + return function() { + var args = []; + forEach(arguments, function(arg) { + args.push(formatError(arg)); + }); + return logFn.apply(console, args); + }; + } - return segments.join('/'); + // we are IE which either doesn't have window.console => this is noop and we do nothing, + // or we are IE where console.log doesn't have apply so we log at least first 2 args + return function(arg1, arg2) { + logFn(arg1, arg2 == null ? '' : arg2); + }; + } + }]; } -function parseAbsoluteUrl(absoluteUrl, locationObj) { - var parsedUrl = urlResolve(absoluteUrl); +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - locationObj.$$protocol = parsedUrl.protocol; - locationObj.$$host = parsedUrl.hostname; - locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; -} +var $parseMinErr = minErr('$parse'); +// Sandboxing Angular Expressions +// ------------------------------ +// Angular expressions are generally considered safe because these expressions only have direct +// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by +// obtaining a reference to native JS functions such as the Function constructor. +// +// As an example, consider the following Angular expression: +// +// {}.toString.constructor('alert("evil JS code")') +// +// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits +// against the expression language, but not to prevent exploits that were enabled by exposing +// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good +// practice and therefore we are not even trying to protect against interaction with an object +// explicitly exposed in this way. +// +// In general, it is not possible to access a Window object from an angular expression unless a +// window or some DOM object that has a reference to window is published onto a Scope. +// Similarly we prevent invocations of function known to be dangerous, as well as assignments to +// native objects. +// +// See https://docs.angularjs.org/guide/security -function parseAppUrl(relativeUrl, locationObj) { - var prefixed = (relativeUrl.charAt(0) !== '/'); - if (prefixed) { - relativeUrl = '/' + relativeUrl; - } - var match = urlResolve(relativeUrl); - locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? - match.pathname.substring(1) : match.pathname); - locationObj.$$search = parseKeyValue(match.search); - locationObj.$$hash = decodeURIComponent(match.hash); - // make sure path starts with '/'; - if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') { - locationObj.$$path = '/' + locationObj.$$path; +function ensureSafeMemberName(name, fullExpression) { + if (name === "__defineGetter__" || name === "__defineSetter__" + || name === "__lookupGetter__" || name === "__lookupSetter__" + || name === "__proto__") { + throw $parseMinErr('isecfld', + 'Attempting to access a disallowed field in Angular expressions! ' + + 'Expression: {0}', fullExpression); } + return name; } - -/** - * - * @param {string} begin - * @param {string} whole - * @returns {string} returns text from whole after begin or undefined if it does not begin with - * expected string. - */ -function beginsWith(begin, whole) { - if (whole.indexOf(begin) === 0) { - return whole.substr(begin.length); +function ensureSafeObject(obj, fullExpression) { + // nifty check if obj is Function that is fast and works across iframes and other contexts + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isWindow(obj) + obj.window === obj) { + throw $parseMinErr('isecwindow', + 'Referencing the Window in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// isElement(obj) + obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) { + throw $parseMinErr('isecdom', + 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (// block Object so that we can't get hold of dangerous Object.* methods + obj === Object) { + throw $parseMinErr('isecobj', + 'Referencing Object in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } } + return obj; } +var CALL = Function.prototype.call; +var APPLY = Function.prototype.apply; +var BIND = Function.prototype.bind; -function stripHash(url) { - var index = url.indexOf('#'); - return index == -1 ? url : url.substr(0, index); -} - -function trimEmptyHash(url) { - return url.replace(/(#.+)|#$/, '$1'); +function ensureSafeFunction(obj, fullExpression) { + if (obj) { + if (obj.constructor === obj) { + throw $parseMinErr('isecfn', + 'Referencing Function in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } else if (obj === CALL || obj === APPLY || obj === BIND) { + throw $parseMinErr('isecff', + 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}', + fullExpression); + } + } } +var OPERATORS = createMap(); +forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; }); +var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; -function stripFile(url) { - return url.substr(0, stripHash(url).lastIndexOf('/') + 1); -} -/* return the server only (scheme://host:port) */ -function serverBase(url) { - return url.substring(0, url.indexOf('/', url.indexOf('//') + 2)); -} +///////////////////////////////////////// /** - * LocationHtml5Url represents an url - * This object is exposed as $location service when HTML5 mode is enabled and supported - * * @constructor - * @param {string} appBase application base URL - * @param {string} basePrefix url path prefix */ -function LocationHtml5Url(appBase, basePrefix) { - this.$$html5 = true; - basePrefix = basePrefix || ''; - var appBaseNoFile = stripFile(appBase); - parseAbsoluteUrl(appBase, this); +var Lexer = function(options) { + this.options = options; +}; +Lexer.prototype = { + constructor: Lexer, - /** - * Parse given html5 (regular) url string into properties - * @param {string} url HTML5 url - * @private - */ - this.$$parse = function(url) { - var pathUrl = beginsWith(appBaseNoFile, url); - if (!isString(pathUrl)) { - throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, - appBaseNoFile); + lex: function(text) { + this.text = text; + this.index = 0; + this.tokens = []; + + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (ch === '"' || ch === "'") { + this.readString(ch); + } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) { + this.readNumber(); + } else if (this.isIdent(ch)) { + this.readIdent(); + } else if (this.is(ch, '(){}[].,;:?')) { + this.tokens.push({index: this.index, text: ch}); + this.index++; + } else if (this.isWhitespace(ch)) { + this.index++; + } else { + var ch2 = ch + this.peek(); + var ch3 = ch2 + this.peek(2); + var op1 = OPERATORS[ch]; + var op2 = OPERATORS[ch2]; + var op3 = OPERATORS[ch3]; + if (op1 || op2 || op3) { + var token = op3 ? ch3 : (op2 ? ch2 : ch); + this.tokens.push({index: this.index, text: token, operator: true}); + this.index += token.length; + } else { + this.throwError('Unexpected next character ', this.index, this.index + 1); + } + } } + return this.tokens; + }, - parseAppUrl(pathUrl, this); + is: function(ch, chars) { + return chars.indexOf(ch) !== -1; + }, - if (!this.$$path) { - this.$$path = '/'; - } + peek: function(i) { + var num = i || 1; + return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false; + }, - this.$$compose(); - }; + isNumber: function(ch) { + return ('0' <= ch && ch <= '9') && typeof ch === "string"; + }, - /** - * Compose url and update `absUrl` property - * @private - */ - this.$$compose = function() { - var search = toKeyValue(this.$$search), - hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + isWhitespace: function(ch) { + // IE treats non-breaking space as \u00A0 + return (ch === ' ' || ch === '\r' || ch === '\t' || + ch === '\n' || ch === '\v' || ch === '\u00A0'); + }, - this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; - this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/' - }; + isIdent: function(ch) { + return ('a' <= ch && ch <= 'z' || + 'A' <= ch && ch <= 'Z' || + '_' === ch || ch === '$'); + }, - this.$$parseLinkUrl = function(url, relHref) { - if (relHref && relHref[0] === '#') { - // special case for links to hash fragments: - // keep the old url and only replace the hash fragment - this.hash(relHref.slice(1)); - return true; - } - var appUrl, prevAppUrl; - var rewrittenUrl; + isExpOperator: function(ch) { + return (ch === '-' || ch === '+' || this.isNumber(ch)); + }, - if ((appUrl = beginsWith(appBase, url)) !== undefined) { - prevAppUrl = appUrl; - if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) { - rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl); + throwError: function(error, start, end) { + end = end || this.index; + var colStr = (isDefined(start) + ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']' + : ' ' + end); + throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].', + error, colStr, this.text); + }, + + readNumber: function() { + var number = ''; + var start = this.index; + while (this.index < this.text.length) { + var ch = lowercase(this.text.charAt(this.index)); + if (ch == '.' || this.isNumber(ch)) { + number += ch; } else { - rewrittenUrl = appBase + prevAppUrl; + var peekCh = this.peek(); + if (ch == 'e' && this.isExpOperator(peekCh)) { + number += ch; + } else if (this.isExpOperator(ch) && + peekCh && this.isNumber(peekCh) && + number.charAt(number.length - 1) == 'e') { + number += ch; + } else if (this.isExpOperator(ch) && + (!peekCh || !this.isNumber(peekCh)) && + number.charAt(number.length - 1) == 'e') { + this.throwError('Invalid exponent'); + } else { + break; + } } - } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) { - rewrittenUrl = appBaseNoFile + appUrl; - } else if (appBaseNoFile == url + '/') { - rewrittenUrl = appBaseNoFile; + this.index++; } - if (rewrittenUrl) { - this.$$parse(rewrittenUrl); + this.tokens.push({ + index: start, + text: number, + constant: true, + value: Number(number) + }); + }, + + readIdent: function() { + var start = this.index; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + if (!(this.isIdent(ch) || this.isNumber(ch))) { + break; + } + this.index++; } - return !!rewrittenUrl; - }; -} + this.tokens.push({ + index: start, + text: this.text.slice(start, this.index), + identifier: true + }); + }, + readString: function(quote) { + var start = this.index; + this.index++; + var string = ''; + var rawString = quote; + var escape = false; + while (this.index < this.text.length) { + var ch = this.text.charAt(this.index); + rawString += ch; + if (escape) { + if (ch === 'u') { + var hex = this.text.substring(this.index + 1, this.index + 5); + if (!hex.match(/[\da-f]{4}/i)) { + this.throwError('Invalid unicode escape [\\u' + hex + ']'); + } + this.index += 4; + string += String.fromCharCode(parseInt(hex, 16)); + } else { + var rep = ESCAPE[ch]; + string = string + (rep || ch); + } + escape = false; + } else if (ch === '\\') { + escape = true; + } else if (ch === quote) { + this.index++; + this.tokens.push({ + index: start, + text: rawString, + constant: true, + value: string + }); + return; + } else { + string += ch; + } + this.index++; + } + this.throwError('Unterminated quote', start); + } +}; -/** - * LocationHashbangUrl represents url - * This object is exposed as $location service when developer doesn't opt into html5 mode. - * It also serves as the base class for html5 mode fallback on legacy browsers. - * - * @constructor - * @param {string} appBase application base URL - * @param {string} hashPrefix hashbang prefix - */ -function LocationHashbangUrl(appBase, hashPrefix) { - var appBaseNoFile = stripFile(appBase); +var AST = function(lexer, options) { + this.lexer = lexer; + this.options = options; +}; - parseAbsoluteUrl(appBase, this); +AST.Program = 'Program'; +AST.ExpressionStatement = 'ExpressionStatement'; +AST.AssignmentExpression = 'AssignmentExpression'; +AST.ConditionalExpression = 'ConditionalExpression'; +AST.LogicalExpression = 'LogicalExpression'; +AST.BinaryExpression = 'BinaryExpression'; +AST.UnaryExpression = 'UnaryExpression'; +AST.CallExpression = 'CallExpression'; +AST.MemberExpression = 'MemberExpression'; +AST.Identifier = 'Identifier'; +AST.Literal = 'Literal'; +AST.ArrayExpression = 'ArrayExpression'; +AST.Property = 'Property'; +AST.ObjectExpression = 'ObjectExpression'; +AST.ThisExpression = 'ThisExpression'; + +// Internal use only +AST.NGValueParameter = 'NGValueParameter'; + +AST.prototype = { + ast: function(text) { + this.text = text; + this.tokens = this.lexer.lex(text); + var value = this.program(); - /** - * Parse given hashbang url into properties - * @param {string} url Hashbang url - * @private - */ - this.$$parse = function(url) { - var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url); - var withoutHashUrl; + if (this.tokens.length !== 0) { + this.throwError('is an unexpected token', this.tokens[0]); + } - if (withoutBaseUrl.charAt(0) === '#') { + return value; + }, - // The rest of the url starts with a hash so we have - // got either a hashbang path or a plain hash fragment - withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl); - if (isUndefined(withoutHashUrl)) { - // There was no hashbang prefix so we just have a hash fragment - withoutHashUrl = withoutBaseUrl; + program: function() { + var body = []; + while (true) { + if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) + body.push(this.expressionStatement()); + if (!this.expect(';')) { + return { type: AST.Program, body: body}; } - - } else { - // There was no hashbang path nor hash fragment: - // If we are in HTML5 mode we use what is left as the path; - // Otherwise we ignore what is left - withoutHashUrl = this.$$html5 ? withoutBaseUrl : ''; } + }, - parseAppUrl(withoutHashUrl, this); - - this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); - - this.$$compose(); + expressionStatement: function() { + return { type: AST.ExpressionStatement, expression: this.filterChain() }; + }, - /* - * In Windows, on an anchor node on documents loaded from - * the filesystem, the browser will return a pathname - * prefixed with the drive name ('/C:/path') when a - * pathname without a drive is set: - * * a.setAttribute('href', '/foo') - * * a.pathname === '/C:/foo' //true - * - * Inside of Angular, we're always using pathnames that - * do not include drive names for routing. - */ - function removeWindowsDriveName(path, url, base) { - /* - Matches paths for file protocol on windows, - such as /C:/foo/bar, and captures only /foo/bar. - */ - var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; + filterChain: function() { + var left = this.expression(); + var token; + while ((token = this.expect('|'))) { + left = this.filter(left); + } + return left; + }, - var firstPathSegmentMatch; + expression: function() { + return this.assignment(); + }, - //Get the relative path from the input URL. - if (url.indexOf(base) === 0) { - url = url.replace(base, ''); - } + assignment: function() { + var result = this.ternary(); + if (this.expect('=')) { + result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='}; + } + return result; + }, - // The input URL intentionally contains a first path segment that ends with a colon. - if (windowsFilePathExp.exec(url)) { - return path; + ternary: function() { + var test = this.logicalOR(); + var alternate; + var consequent; + if (this.expect('?')) { + alternate = this.expression(); + if (this.consume(':')) { + consequent = this.expression(); + return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent}; } + } + return test; + }, - firstPathSegmentMatch = windowsFilePathExp.exec(path); - return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; + logicalOR: function() { + var left = this.logicalAND(); + while (this.expect('||')) { + left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() }; } - }; + return left; + }, - /** - * Compose hashbang url and update `absUrl` property - * @private - */ - this.$$compose = function() { - var search = toKeyValue(this.$$search), - hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + logicalAND: function() { + var left = this.equality(); + while (this.expect('&&')) { + left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()}; + } + return left; + }, - this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; - this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : ''); - }; + equality: function() { + var left = this.relational(); + var token; + while ((token = this.expect('==','!=','===','!=='))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() }; + } + return left; + }, - this.$$parseLinkUrl = function(url, relHref) { - if (stripHash(appBase) == stripHash(url)) { - this.$$parse(url); - return true; + relational: function() { + var left = this.additive(); + var token; + while ((token = this.expect('<', '>', '<=', '>='))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() }; } - return false; - }; -} + return left; + }, + additive: function() { + var left = this.multiplicative(); + var token; + while ((token = this.expect('+','-'))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() }; + } + return left; + }, -/** - * LocationHashbangUrl represents url - * This object is exposed as $location service when html5 history api is enabled but the browser - * does not support it. - * - * @constructor - * @param {string} appBase application base URL - * @param {string} hashPrefix hashbang prefix - */ -function LocationHashbangInHtml5Url(appBase, hashPrefix) { - this.$$html5 = true; - LocationHashbangUrl.apply(this, arguments); + multiplicative: function() { + var left = this.unary(); + var token; + while ((token = this.expect('*','/','%'))) { + left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() }; + } + return left; + }, - var appBaseNoFile = stripFile(appBase); + unary: function() { + var token; + if ((token = this.expect('+', '-', '!'))) { + return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() }; + } else { + return this.primary(); + } + }, - this.$$parseLinkUrl = function(url, relHref) { - if (relHref && relHref[0] === '#') { - // special case for links to hash fragments: - // keep the old url and only replace the hash fragment - this.hash(relHref.slice(1)); - return true; + primary: function() { + var primary; + if (this.expect('(')) { + primary = this.filterChain(); + this.consume(')'); + } else if (this.expect('[')) { + primary = this.arrayDeclaration(); + } else if (this.expect('{')) { + primary = this.object(); + } else if (this.constants.hasOwnProperty(this.peek().text)) { + primary = copy(this.constants[this.consume().text]); + } else if (this.peek().identifier) { + primary = this.identifier(); + } else if (this.peek().constant) { + primary = this.constant(); + } else { + this.throwError('not a primary expression', this.peek()); } - var rewrittenUrl; - var appUrl; - - if (appBase == stripHash(url)) { - rewrittenUrl = url; - } else if ((appUrl = beginsWith(appBaseNoFile, url))) { - rewrittenUrl = appBase + hashPrefix + appUrl; - } else if (appBaseNoFile === url + '/') { - rewrittenUrl = appBaseNoFile; - } - if (rewrittenUrl) { - this.$$parse(rewrittenUrl); + var next; + while ((next = this.expect('(', '[', '.'))) { + if (next.text === '(') { + primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() }; + this.consume(')'); + } else if (next.text === '[') { + primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true }; + this.consume(']'); + } else if (next.text === '.') { + primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false }; + } else { + this.throwError('IMPOSSIBLE'); + } } - return !!rewrittenUrl; - }; - - this.$$compose = function() { - var search = toKeyValue(this.$$search), - hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : ''; + return primary; + }, - this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash; - // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#' - this.$$absUrl = appBase + hashPrefix + this.$$url; - }; + filter: function(baseExpression) { + var args = [baseExpression]; + var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true}; -} + while (this.expect(':')) { + args.push(this.expression()); + } + return result; + }, -var locationPrototype = { + parseArguments: function() { + var args = []; + if (this.peekToken().text !== ')') { + do { + args.push(this.expression()); + } while (this.expect(',')); + } + return args; + }, - /** - * Are we in html5 mode? - * @private - */ - $$html5: false, + identifier: function() { + var token = this.consume(); + if (!token.identifier) { + this.throwError('is not a valid identifier', token); + } + return { type: AST.Identifier, name: token.text }; + }, - /** - * Has any change been replacing? - * @private - */ - $$replace: false, + constant: function() { + // TODO check that it is a constant + return { type: AST.Literal, value: this.consume().value }; + }, - /** - * @ngdoc method - * @name $location#absUrl - * - * @description - * This method is getter only. - * - * Return full url representation with all segments encoded according to rules specified in - * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt). - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo - * var absUrl = $location.absUrl(); - * // => "http://example.com/#/some/path?foo=bar&baz=xoxo" - * ``` - * - * @return {string} full url - */ - absUrl: locationGetter('$$absUrl'), + arrayDeclaration: function() { + var elements = []; + if (this.peekToken().text !== ']') { + do { + if (this.peek(']')) { + // Support trailing commas per ES5.1. + break; + } + elements.push(this.expression()); + } while (this.expect(',')); + } + this.consume(']'); - /** - * @ngdoc method - * @name $location#url - * - * @description - * This method is getter / setter. - * - * Return url (e.g. `/path?a=b#hash`) when called without any parameter. - * - * Change path, search and hash, when called with parameter and return `$location`. - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo - * var url = $location.url(); - * // => "/some/path?foo=bar&baz=xoxo" - * ``` - * - * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`) - * @return {string} url - */ - url: function(url) { - if (isUndefined(url)) - return this.$$url; + return { type: AST.ArrayExpression, elements: elements }; + }, - var match = PATH_MATCH.exec(url); - if (match[1] || url === '') this.path(decodeURIComponent(match[1])); - if (match[2] || match[1] || url === '') this.search(match[3] || ''); - this.hash(match[5] || ''); + object: function() { + var properties = [], property; + if (this.peekToken().text !== '}') { + do { + if (this.peek('}')) { + // Support trailing commas per ES5.1. + break; + } + property = {type: AST.Property, kind: 'init'}; + if (this.peek().constant) { + property.key = this.constant(); + } else if (this.peek().identifier) { + property.key = this.identifier(); + } else { + this.throwError("invalid key", this.peek()); + } + this.consume(':'); + property.value = this.expression(); + properties.push(property); + } while (this.expect(',')); + } + this.consume('}'); - return this; + return {type: AST.ObjectExpression, properties: properties }; }, - /** - * @ngdoc method - * @name $location#protocol - * - * @description - * This method is getter only. - * - * Return protocol of current url. - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo - * var protocol = $location.protocol(); - * // => "http" - * ``` - * - * @return {string} protocol of current url - */ - protocol: locationGetter('$$protocol'), + throwError: function(msg, token) { + throw $parseMinErr('syntax', + 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', + token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); + }, - /** - * @ngdoc method - * @name $location#host - * - * @description - * This method is getter only. - * - * Return host of current url. - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo - * var host = $location.host(); - * // => "example.com" - * ``` - * - * @return {string} host of current url. - */ - host: locationGetter('$$host'), + consume: function(e1) { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } - /** - * @ngdoc method - * @name $location#port - * - * @description - * This method is getter only. - * - * Return port of current url. - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo - * var port = $location.port(); - * // => 80 - * ``` - * - * @return {Number} port - */ - port: locationGetter('$$port'), + var token = this.expect(e1); + if (!token) { + this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); + } + return token; + }, - /** - * @ngdoc method - * @name $location#path - * - * @description - * This method is getter / setter. - * - * Return path of current url when called without any parameter. - * - * Change path when called with parameter and return `$location`. - * - * Note: Path should always begin with forward slash (/), this method will add the forward slash - * if it is missing. - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo - * var path = $location.path(); - * // => "/some/path" - * ``` - * - * @param {(string|number)=} path New path - * @return {string} path - */ - path: locationGetterSetter('$$path', function(path) { - path = path !== null ? path.toString() : ''; - return path.charAt(0) == '/' ? path : '/' + path; - }), + peekToken: function() { + if (this.tokens.length === 0) { + throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); + } + return this.tokens[0]; + }, - /** - * @ngdoc method - * @name $location#search - * - * @description - * This method is getter / setter. - * - * Return search part (as object) of current url when called without any parameter. - * - * Change search part when called with parameter and return `$location`. - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo - * var searchObject = $location.search(); - * // => {foo: 'bar', baz: 'xoxo'} - * - * // set foo to 'yipee' - * $location.search('foo', 'yipee'); - * // $location.search() => {foo: 'yipee', baz: 'xoxo'} - * ``` - * - * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or - * hash object. - * - * When called with a single argument the method acts as a setter, setting the `search` component - * of `$location` to the specified value. - * - * If the argument is a hash object containing an array of values, these values will be encoded - * as duplicate search parameters in the url. - * - * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue` - * will override only a single search property. - * - * If `paramValue` is an array, it will override the property of the `search` component of - * `$location` specified via the first argument. - * - * If `paramValue` is `null`, the property specified via the first argument will be deleted. - * - * If `paramValue` is `true`, the property specified via the first argument will be added with no - * value nor trailing equal sign. - * - * @return {Object} If called with no arguments returns the parsed `search` object. If called with - * one or more arguments returns `$location` object itself. - */ - search: function(search, paramValue) { - switch (arguments.length) { - case 0: - return this.$$search; - case 1: - if (isString(search) || isNumber(search)) { - search = search.toString(); - this.$$search = parseKeyValue(search); - } else if (isObject(search)) { - search = copy(search, {}); - // remove object undefined or null properties - forEach(search, function(value, key) { - if (value == null) delete search[key]; - }); + peek: function(e1, e2, e3, e4) { + return this.peekAhead(0, e1, e2, e3, e4); + }, - this.$$search = search; - } else { - throw $locationMinErr('isrcharg', - 'The first argument of the `$location#search()` call must be a string or an object.'); - } - break; - default: - if (isUndefined(paramValue) || paramValue === null) { - delete this.$$search[search]; - } else { - this.$$search[search] = paramValue; - } + peekAhead: function(i, e1, e2, e3, e4) { + if (this.tokens.length > i) { + var token = this.tokens[i]; + var t = token.text; + if (t === e1 || t === e2 || t === e3 || t === e4 || + (!e1 && !e2 && !e3 && !e4)) { + return token; + } } + return false; + }, - this.$$compose(); - return this; + expect: function(e1, e2, e3, e4) { + var token = this.peek(e1, e2, e3, e4); + if (token) { + this.tokens.shift(); + return token; + } + return false; }, - /** - * @ngdoc method - * @name $location#hash - * - * @description - * This method is getter / setter. - * - * Return hash fragment when called without any parameter. - * - * Change hash fragment when called with parameter and return `$location`. - * - * - * ```js - * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue - * var hash = $location.hash(); - * // => "hashValue" - * ``` - * - * @param {(string|number)=} hash New hash fragment - * @return {string} hash - */ - hash: locationGetterSetter('$$hash', function(hash) { - return hash !== null ? hash.toString() : ''; - }), - /** - * @ngdoc method - * @name $location#replace - * - * @description - * If called, all changes to $location during current `$digest` will be replacing current history - * record, instead of adding new one. + /* `undefined` is not a constant, it is an identifier, + * but using it as an identifier is not supported */ - replace: function() { - this.$$replace = true; - return this; + constants: { + 'true': { type: AST.Literal, value: true }, + 'false': { type: AST.Literal, value: false }, + 'null': { type: AST.Literal, value: null }, + 'undefined': {type: AST.Literal, value: undefined }, + 'this': {type: AST.ThisExpression } } }; -forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) { - Location.prototype = Object.create(locationPrototype); - - /** - * @ngdoc method - * @name $location#state - * - * @description - * This method is getter / setter. - * - * Return the history state object when called without any parameter. - * - * Change the history state object when called with one parameter and return `$location`. - * The state object is later passed to `pushState` or `replaceState`. - * - * NOTE: This method is supported only in HTML5 mode and only in browsers supporting - * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support - * older browsers (like IE9 or Android < 4.0), don't use this method. - * - * @param {object=} state State object for pushState or replaceState - * @return {object} state - */ - Location.prototype.state = function(state) { - if (!arguments.length) - return this.$$state; - - if (Location !== LocationHtml5Url || !this.$$html5) { - throw $locationMinErr('nostate', 'History API state support is available only ' + - 'in HTML5 mode and only in browsers supporting HTML5 History API'); - } - // The user might modify `stateObject` after invoking `$location.state(stateObject)` - // but we're changing the $$state reference to $browser.state() during the $digest - // so the modification window is narrow. - this.$$state = isUndefined(state) ? null : state; - - return this; - }; -}); - - -function locationGetter(property) { - return function() { - return this[property]; - }; +function ifDefined(v, d) { + return typeof v !== 'undefined' ? v : d; } +function plusFn(l, r) { + if (typeof l === 'undefined') return r; + if (typeof r === 'undefined') return l; + return l + r; +} -function locationGetterSetter(property, preprocess) { - return function(value) { - if (isUndefined(value)) - return this[property]; +function isStateless($filter, filterName) { + var fn = $filter(filterName); + return !fn.$stateful; +} - this[property] = preprocess(value); - this.$$compose(); +function findConstantAndWatchExpressions(ast, $filter) { + var allConstants; + var argsToWatch; + switch (ast.type) { + case AST.Program: + allConstants = true; + forEach(ast.body, function(expr) { + findConstantAndWatchExpressions(expr.expression, $filter); + allConstants = allConstants && expr.expression.constant; + }); + ast.constant = allConstants; + break; + case AST.Literal: + ast.constant = true; + ast.toWatch = []; + break; + case AST.UnaryExpression: + findConstantAndWatchExpressions(ast.argument, $filter); + ast.constant = ast.argument.constant; + ast.toWatch = ast.argument.toWatch; + break; + case AST.BinaryExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch); + break; + case AST.LogicalExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.ConditionalExpression: + findConstantAndWatchExpressions(ast.test, $filter); + findConstantAndWatchExpressions(ast.alternate, $filter); + findConstantAndWatchExpressions(ast.consequent, $filter); + ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant; + ast.toWatch = ast.constant ? [] : [ast]; + break; + case AST.Identifier: + ast.constant = false; + ast.toWatch = [ast]; + break; + case AST.MemberExpression: + findConstantAndWatchExpressions(ast.object, $filter); + if (ast.computed) { + findConstantAndWatchExpressions(ast.property, $filter); + } + ast.constant = ast.object.constant && (!ast.computed || ast.property.constant); + ast.toWatch = [ast]; + break; + case AST.CallExpression: + allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false; + argsToWatch = []; + forEach(ast.arguments, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast]; + break; + case AST.AssignmentExpression: + findConstantAndWatchExpressions(ast.left, $filter); + findConstantAndWatchExpressions(ast.right, $filter); + ast.constant = ast.left.constant && ast.right.constant; + ast.toWatch = [ast]; + break; + case AST.ArrayExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.elements, function(expr) { + findConstantAndWatchExpressions(expr, $filter); + allConstants = allConstants && expr.constant; + if (!expr.constant) { + argsToWatch.push.apply(argsToWatch, expr.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ObjectExpression: + allConstants = true; + argsToWatch = []; + forEach(ast.properties, function(property) { + findConstantAndWatchExpressions(property.value, $filter); + allConstants = allConstants && property.value.constant; + if (!property.value.constant) { + argsToWatch.push.apply(argsToWatch, property.value.toWatch); + } + }); + ast.constant = allConstants; + ast.toWatch = argsToWatch; + break; + case AST.ThisExpression: + ast.constant = false; + ast.toWatch = []; + break; + } +} - return this; - }; +function getInputs(body) { + if (body.length != 1) return; + var lastExpression = body[0].expression; + var candidate = lastExpression.toWatch; + if (candidate.length !== 1) return candidate; + return candidate[0] !== lastExpression ? candidate : undefined; } +function isAssignable(ast) { + return ast.type === AST.Identifier || ast.type === AST.MemberExpression; +} -/** - * @ngdoc service - * @name $location - * - * @requires $rootElement - * - * @description - * The $location service parses the URL in the browser address bar (based on the - * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL - * available to your application. Changes to the URL in the address bar are reflected into - * $location service and changes to $location are reflected into the browser address bar. - * - * **The $location service:** - * - * - Exposes the current URL in the browser address bar, so you can - * - Watch and observe the URL. - * - Change the URL. - * - Synchronizes the URL with the browser when the user - * - Changes the address bar. - * - Clicks the back or forward button (or clicks a History link). - * - Clicks on a link. - * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). - * - * For more information see {@link guide/$location Developer Guide: Using $location} - */ +function assignableAST(ast) { + if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) { + return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='}; + } +} -/** - * @ngdoc provider - * @name $locationProvider - * @description - * Use the `$locationProvider` to configure how the application deep linking paths are stored. - */ -function $LocationProvider() { - var hashPrefix = '', - html5Mode = { - enabled: false, - requireBase: true, - rewriteLinks: true - }; +function isLiteral(ast) { + return ast.body.length === 0 || + ast.body.length === 1 && ( + ast.body[0].expression.type === AST.Literal || + ast.body[0].expression.type === AST.ArrayExpression || + ast.body[0].expression.type === AST.ObjectExpression); +} - /** - * @ngdoc method - * @name $locationProvider#hashPrefix - * @description - * @param {string=} prefix Prefix for hash part (containing path and search) - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.hashPrefix = function(prefix) { - if (isDefined(prefix)) { - hashPrefix = prefix; - return this; - } else { - return hashPrefix; - } - }; +function isConstant(ast) { + return ast.constant; +} - /** - * @ngdoc method - * @name $locationProvider#html5Mode - * @description - * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value. - * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported - * properties: - * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to - * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not - * support `pushState`. - * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies - * whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are - * true, and a base tag is not present, an error will be thrown when `$location` is injected. - * See the {@link guide/$location $location guide for more information} - * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled, - * enables/disables url rewriting for relative links. - * - * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter - */ - this.html5Mode = function(mode) { - if (isBoolean(mode)) { - html5Mode.enabled = mode; - return this; - } else if (isObject(mode)) { +function ASTCompiler(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} - if (isBoolean(mode.enabled)) { - html5Mode.enabled = mode.enabled; - } +ASTCompiler.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.state = { + nextId: 0, + filters: {}, + expensiveChecks: expensiveChecks, + fn: {vars: [], body: [], own: {}}, + assign: {vars: [], body: [], own: {}}, + inputs: [] + }; + findConstantAndWatchExpressions(ast, self.$filter); + var extra = ''; + var assignable; + this.stage = 'assign'; + if ((assignable = assignableAST(ast))) { + this.state.computing = 'assign'; + var result = this.nextId(); + this.recurse(assignable, result); + extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l'); + } + var toWatch = getInputs(ast.body); + self.stage = 'inputs'; + forEach(toWatch, function(watch, key) { + var fnKey = 'fn' + key; + self.state[fnKey] = {vars: [], body: [], own: {}}; + self.state.computing = fnKey; + var intoId = self.nextId(); + self.recurse(watch, intoId); + self.return_(intoId); + self.state.inputs.push(fnKey); + watch.watchId = key; + }); + this.state.computing = 'fn'; + this.stage = 'main'; + this.recurse(ast); + var fnString = + // The build and minification steps remove the string "use strict" from the code, but this is done using a regex. + // This is a workaround for this until we do a better job at only removing the prefix only when we should. + '"' + this.USE + ' ' + this.STRICT + '";\n' + + this.filterPrefix() + + 'var fn=' + this.generateFunction('fn', 's,l,a,i') + + extra + + this.watchFns() + + 'return fn;'; - if (isBoolean(mode.requireBase)) { - html5Mode.requireBase = mode.requireBase; - } + /* jshint -W054 */ + var fn = (new Function('$filter', + 'ensureSafeMemberName', + 'ensureSafeObject', + 'ensureSafeFunction', + 'ifDefined', + 'plus', + 'text', + fnString))( + this.$filter, + ensureSafeMemberName, + ensureSafeObject, + ensureSafeFunction, + ifDefined, + plusFn, + expression); + /* jshint +W054 */ + this.state = this.stage = undefined; + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, - if (isBoolean(mode.rewriteLinks)) { - html5Mode.rewriteLinks = mode.rewriteLinks; - } + USE: 'use', - return this; - } else { - return html5Mode; + STRICT: 'strict', + + watchFns: function() { + var result = []; + var fns = this.state.inputs; + var self = this; + forEach(fns, function(name) { + result.push('var ' + name + '=' + self.generateFunction(name, 's')); + }); + if (fns.length) { + result.push('fn.inputs=[' + fns.join(',') + '];'); } - }; + return result.join(''); + }, - /** - * @ngdoc event - * @name $location#$locationChangeStart - * @eventType broadcast on root scope - * @description - * Broadcasted before a URL will change. - * - * This change can be prevented by calling - * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more - * details about event object. Upon successful change - * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. - * - * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when - * the browser supports the HTML5 History API. - * - * @param {Object} angularEvent Synthetic event object. - * @param {string} newUrl New URL - * @param {string=} oldUrl URL that was before it was changed. - * @param {string=} newState New history state object - * @param {string=} oldState History state object that was before it was changed. - */ + generateFunction: function(name, params) { + return 'function(' + params + '){' + + this.varsPrefix(name) + + this.body(name) + + '};'; + }, - /** - * @ngdoc event - * @name $location#$locationChangeSuccess - * @eventType broadcast on root scope - * @description - * Broadcasted after a URL was changed. - * - * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when - * the browser supports the HTML5 History API. - * - * @param {Object} angularEvent Synthetic event object. - * @param {string} newUrl New URL - * @param {string=} oldUrl URL that was before it was changed. - * @param {string=} newState New history state object - * @param {string=} oldState History state object that was before it was changed. - */ + filterPrefix: function() { + var parts = []; + var self = this; + forEach(this.state.filters, function(id, filter) { + parts.push(id + '=$filter(' + self.escape(filter) + ')'); + }); + if (parts.length) return 'var ' + parts.join(',') + ';'; + return ''; + }, - this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window', - function($rootScope, $browser, $sniffer, $rootElement, $window) { - var $location, - LocationMode, - baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to '' - initialUrl = $browser.url(), - appBase; + varsPrefix: function(section) { + return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : ''; + }, - if (html5Mode.enabled) { - if (!baseHref && html5Mode.requireBase) { - throw $locationMinErr('nobase', - "$location in HTML5 mode requires a <base> tag to be present!"); + body: function(section) { + return this.state[section].body.join(''); + }, + + recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var left, right, self = this, args, expression; + recursionFn = recursionFn || noop; + if (!skipWatchIdCheck && isDefined(ast.watchId)) { + intoId = intoId || this.nextId(); + this.if_('i', + this.lazyAssign(intoId, this.computedMember('i', ast.watchId)), + this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true) + ); + return; + } + switch (ast.type) { + case AST.Program: + forEach(ast.body, function(expression, pos) { + self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; }); + if (pos !== ast.body.length - 1) { + self.current().body.push(right, ';'); + } else { + self.return_(right); + } + }); + break; + case AST.Literal: + expression = this.escape(ast.value); + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.UnaryExpression: + this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; }); + expression = ast.operator + '(' + this.ifDefined(right, 0) + ')'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.BinaryExpression: + this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; }); + this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; }); + if (ast.operator === '+') { + expression = this.plus(left, right); + } else if (ast.operator === '-') { + expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0); + } else { + expression = '(' + left + ')' + ast.operator + '(' + right + ')'; } - appBase = serverBase(initialUrl) + (baseHref || '/'); - LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; - } else { - appBase = stripHash(initialUrl); - LocationMode = LocationHashbangUrl; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.LogicalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.left, intoId); + self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); + recursionFn(intoId); + break; + case AST.ConditionalExpression: + intoId = intoId || this.nextId(); + self.recurse(ast.test, intoId); + self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); + recursionFn(intoId); + break; + case AST.Identifier: + intoId = intoId || this.nextId(); + if (nameId) { + nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s'); + nameId.computed = false; + nameId.name = ast.name; + } + ensureSafeMemberName(ast.name); + self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)), + function() { + self.if_(self.stage === 'inputs' || 's', function() { + if (create && create !== 1) { + self.if_( + self.not(self.nonComputedMember('s', ast.name)), + self.lazyAssign(self.nonComputedMember('s', ast.name), '{}')); + } + self.assign(intoId, self.nonComputedMember('s', ast.name)); + }); + }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name)) + ); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) { + self.addEnsureSafeObject(intoId); + } + recursionFn(intoId); + break; + case AST.MemberExpression: + left = nameId && (nameId.context = this.nextId()) || this.nextId(); + intoId = intoId || this.nextId(); + self.recurse(ast.object, left, undefined, function() { + self.if_(self.notNull(left), function() { + if (ast.computed) { + right = self.nextId(); + self.recurse(ast.property, right); + self.addEnsureSafeMemberName(right); + if (create && create !== 1) { + self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); + } + expression = self.ensureSafeObject(self.computedMember(left, right)); + self.assign(intoId, expression); + if (nameId) { + nameId.computed = true; + nameId.name = right; + } + } else { + ensureSafeMemberName(ast.property.name); + if (create && create !== 1) { + self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}')); + } + expression = self.nonComputedMember(left, ast.property.name); + if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) { + expression = self.ensureSafeObject(expression); + } + self.assign(intoId, expression); + if (nameId) { + nameId.computed = false; + nameId.name = ast.property.name; + } + } + }, function() { + self.assign(intoId, 'undefined'); + }); + recursionFn(intoId); + }, !!create); + break; + case AST.CallExpression: + intoId = intoId || this.nextId(); + if (ast.filter) { + right = self.filter(ast.callee.name); + args = []; + forEach(ast.arguments, function(expr) { + var argument = self.nextId(); + self.recurse(expr, argument); + args.push(argument); + }); + expression = right + '(' + args.join(',') + ')'; + self.assign(intoId, expression); + recursionFn(intoId); + } else { + right = self.nextId(); + left = {}; + args = []; + self.recurse(ast.callee, right, left, function() { + self.if_(self.notNull(right), function() { + self.addEnsureSafeFunction(right); + forEach(ast.arguments, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(self.ensureSafeObject(argument)); + }); + }); + if (left.name) { + if (!self.state.expensiveChecks) { + self.addEnsureSafeObject(left.context); + } + expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')'; + } else { + expression = right + '(' + args.join(',') + ')'; + } + expression = self.ensureSafeObject(expression); + self.assign(intoId, expression); + }, function() { + self.assign(intoId, 'undefined'); + }); + recursionFn(intoId); + }); + } + break; + case AST.AssignmentExpression: + right = this.nextId(); + left = {}; + if (!isAssignable(ast.left)) { + throw $parseMinErr('lval', 'Trying to assing a value to a non l-value'); + } + this.recurse(ast.left, undefined, left, function() { + self.if_(self.notNull(left.context), function() { + self.recurse(ast.right, right); + self.addEnsureSafeObject(self.member(left.context, left.name, left.computed)); + expression = self.member(left.context, left.name, left.computed) + ast.operator + right; + self.assign(intoId, expression); + recursionFn(intoId || expression); + }); + }, 1); + break; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + self.recurse(expr, self.nextId(), undefined, function(argument) { + args.push(argument); + }); + }); + expression = '[' + args.join(',') + ']'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + self.recurse(property.value, self.nextId(), undefined, function(expr) { + args.push(self.escape( + property.key.type === AST.Identifier ? property.key.name : + ('' + property.key.value)) + + ':' + expr); + }); + }); + expression = '{' + args.join(',') + '}'; + this.assign(intoId, expression); + recursionFn(expression); + break; + case AST.ThisExpression: + this.assign(intoId, 's'); + recursionFn('s'); + break; + case AST.NGValueParameter: + this.assign(intoId, 'v'); + recursionFn('v'); + break; } - $location = new LocationMode(appBase, '#' + hashPrefix); - $location.$$parseLinkUrl(initialUrl, initialUrl); + }, - $location.$$state = $browser.state(); + getHasOwnProperty: function(element, property) { + var key = element + '.' + property; + var own = this.current().own; + if (!own.hasOwnProperty(key)) { + own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')'); + } + return own[key]; + }, - var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; + assign: function(id, value) { + if (!id) return; + this.current().body.push(id, '=', value, ';'); + return id; + }, - function setBrowserUrlWithFallback(url, replace, state) { - var oldUrl = $location.url(); - var oldState = $location.$$state; - try { - $browser.url(url, replace, state); + filter: function(filterName) { + if (!this.state.filters.hasOwnProperty(filterName)) { + this.state.filters[filterName] = this.nextId(true); + } + return this.state.filters[filterName]; + }, - // Make sure $location.state() returns referentially identical (not just deeply equal) - // state object; this makes possible quick checking if the state changed in the digest - // loop. Checking deep equality would be too expensive. - $location.$$state = $browser.state(); - } catch (e) { - // Restore old values if pushState fails - $location.url(oldUrl); - $location.$$state = oldState; + ifDefined: function(id, defaultValue) { + return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')'; + }, - throw e; + plus: function(left, right) { + return 'plus(' + left + ',' + right + ')'; + }, + + return_: function(id) { + this.current().body.push('return ', id, ';'); + }, + + if_: function(test, alternate, consequent) { + if (test === true) { + alternate(); + } else { + var body = this.current().body; + body.push('if(', test, '){'); + alternate(); + body.push('}'); + if (consequent) { + body.push('else{'); + consequent(); + body.push('}'); } } + }, - $rootElement.on('click', function(event) { - // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) - // currently we open nice url link and redirect then + not: function(expression) { + return '!(' + expression + ')'; + }, - if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return; + notNull: function(expression) { + return expression + '!=null'; + }, - var elm = jqLite(event.target); + nonComputedMember: function(left, right) { + return left + '.' + right; + }, - // traverse the DOM up to find first A tag - while (nodeName_(elm[0]) !== 'a') { - // ignore rewriting if no A tag (reached root element, or no parent - removed from document) - if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; - } + computedMember: function(left, right) { + return left + '[' + right + ']'; + }, - var absHref = elm.prop('href'); - // get the actual href attribute - see - // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx - var relHref = elm.attr('href') || elm.attr('xlink:href'); + member: function(left, right, computed) { + if (computed) return this.computedMember(left, right); + return this.nonComputedMember(left, right); + }, - if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') { - // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during - // an animation. - absHref = urlResolve(absHref.animVal).href; - } + addEnsureSafeObject: function(item) { + this.current().body.push(this.ensureSafeObject(item), ';'); + }, - // Ignore when url is started with javascript: or mailto: - if (IGNORE_URI_REGEXP.test(absHref)) return; + addEnsureSafeMemberName: function(item) { + this.current().body.push(this.ensureSafeMemberName(item), ';'); + }, - if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) { - if ($location.$$parseLinkUrl(absHref, relHref)) { - // We do a preventDefault for all urls that are part of the angular application, - // in html5mode and also without, so that we are able to abort navigation without - // getting double entries in the location history. - event.preventDefault(); - // update location manually - if ($location.absUrl() != $browser.url()) { - $rootScope.$apply(); - // hack to work around FF6 bug 684208 when scenario runner clicks on links - $window.angular['ff-684208-preventDefault'] = true; - } - } - } - }); + addEnsureSafeFunction: function(item) { + this.current().body.push(this.ensureSafeFunction(item), ';'); + }, + ensureSafeObject: function(item) { + return 'ensureSafeObject(' + item + ',text)'; + }, - // rewrite hashbang url <> html5 url - if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) { - $browser.url($location.absUrl(), true); - } + ensureSafeMemberName: function(item) { + return 'ensureSafeMemberName(' + item + ',text)'; + }, - var initializing = true; + ensureSafeFunction: function(item) { + return 'ensureSafeFunction(' + item + ',text)'; + }, - // update $location when $browser url changes - $browser.onUrlChange(function(newUrl, newState) { - $rootScope.$evalAsync(function() { - var oldUrl = $location.absUrl(); - var oldState = $location.$$state; - var defaultPrevented; + lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { + var self = this; + return function() { + self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck); + }; + }, - $location.$$parse(newUrl); - $location.$$state = newState; + lazyAssign: function(id, value) { + var self = this; + return function() { + self.assign(id, value); + }; + }, - defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, - newState, oldState).defaultPrevented; + stringEscapeRegex: /[^ a-zA-Z0-9]/g, - // if the location was changed by a `$locationChangeStart` handler then stop - // processing this location change - if ($location.absUrl() !== newUrl) return; + stringEscapeFn: function(c) { + return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4); + }, - if (defaultPrevented) { - $location.$$parse(oldUrl); - $location.$$state = oldState; - setBrowserUrlWithFallback(oldUrl, false, oldState); - } else { - initializing = false; - afterLocationChange(oldUrl, oldState); - } - }); - if (!$rootScope.$$phase) $rootScope.$digest(); - }); + escape: function(value) { + if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'"; + if (isNumber(value)) return value.toString(); + if (value === true) return 'true'; + if (value === false) return 'false'; + if (value === null) return 'null'; + if (typeof value === 'undefined') return 'undefined'; - // update browser - $rootScope.$watch(function $locationWatch() { - var oldUrl = trimEmptyHash($browser.url()); - var newUrl = trimEmptyHash($location.absUrl()); - var oldState = $browser.state(); - var currentReplace = $location.$$replace; - var urlOrStateChanged = oldUrl !== newUrl || - ($location.$$html5 && $sniffer.history && oldState !== $location.$$state); + throw $parseMinErr('esc', 'IMPOSSIBLE'); + }, - if (initializing || urlOrStateChanged) { - initializing = false; + nextId: function(skip, init) { + var id = 'v' + (this.state.nextId++); + if (!skip) { + this.current().vars.push(id + (init ? '=' + init : '')); + } + return id; + }, - $rootScope.$evalAsync(function() { - var newUrl = $location.absUrl(); - var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, - $location.$$state, oldState).defaultPrevented; + current: function() { + return this.state[this.state.computing]; + } +}; - // if the location was changed by a `$locationChangeStart` handler then stop - // processing this location change - if ($location.absUrl() !== newUrl) return; - if (defaultPrevented) { - $location.$$parse(oldUrl); - $location.$$state = oldState; - } else { - if (urlOrStateChanged) { - setBrowserUrlWithFallback(newUrl, currentReplace, - oldState === $location.$$state ? null : $location.$$state); +function ASTInterpreter(astBuilder, $filter) { + this.astBuilder = astBuilder; + this.$filter = $filter; +} + +ASTInterpreter.prototype = { + compile: function(expression, expensiveChecks) { + var self = this; + var ast = this.astBuilder.ast(expression); + this.expression = expression; + this.expensiveChecks = expensiveChecks; + findConstantAndWatchExpressions(ast, self.$filter); + var assignable; + var assign; + if ((assignable = assignableAST(ast))) { + assign = this.recurse(assignable); + } + var toWatch = getInputs(ast.body); + var inputs; + if (toWatch) { + inputs = []; + forEach(toWatch, function(watch, key) { + var input = self.recurse(watch); + watch.input = input; + inputs.push(input); + watch.watchId = key; + }); + } + var expressions = []; + forEach(ast.body, function(expression) { + expressions.push(self.recurse(expression.expression)); + }); + var fn = ast.body.length === 0 ? function() {} : + ast.body.length === 1 ? expressions[0] : + function(scope, locals) { + var lastValue; + forEach(expressions, function(exp) { + lastValue = exp(scope, locals); + }); + return lastValue; + }; + if (assign) { + fn.assign = function(scope, value, locals) { + return assign(scope, locals, value); + }; + } + if (inputs) { + fn.inputs = inputs; + } + fn.literal = isLiteral(ast); + fn.constant = isConstant(ast); + return fn; + }, + + recurse: function(ast, context, create) { + var left, right, self = this, args, expression; + if (ast.input) { + return this.inputs(ast.input, ast.watchId); + } + switch (ast.type) { + case AST.Literal: + return this.value(ast.value, context); + case AST.UnaryExpression: + right = this.recurse(ast.argument); + return this['unary' + ast.operator](right, context); + case AST.BinaryExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.LogicalExpression: + left = this.recurse(ast.left); + right = this.recurse(ast.right); + return this['binary' + ast.operator](left, right, context); + case AST.ConditionalExpression: + return this['ternary?:']( + this.recurse(ast.test), + this.recurse(ast.alternate), + this.recurse(ast.consequent), + context + ); + case AST.Identifier: + ensureSafeMemberName(ast.name, self.expression); + return self.identifier(ast.name, + self.expensiveChecks || isPossiblyDangerousMemberName(ast.name), + context, create, self.expression); + case AST.MemberExpression: + left = this.recurse(ast.object, false, !!create); + if (!ast.computed) { + ensureSafeMemberName(ast.property.name, self.expression); + right = ast.property.name; + } + if (ast.computed) right = this.recurse(ast.property); + return ast.computed ? + this.computedMember(left, right, context, create, self.expression) : + this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression); + case AST.CallExpression: + args = []; + forEach(ast.arguments, function(expr) { + args.push(self.recurse(expr)); + }); + if (ast.filter) right = this.$filter(ast.callee.name); + if (!ast.filter) right = this.recurse(ast.callee, true); + return ast.filter ? + function(scope, locals, assign, inputs) { + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(args[i](scope, locals, assign, inputs)); + } + var value = right.apply(undefined, values, inputs); + return context ? {context: undefined, name: undefined, value: value} : value; + } : + function(scope, locals, assign, inputs) { + var rhs = right(scope, locals, assign, inputs); + var value; + if (rhs.value != null) { + ensureSafeObject(rhs.context, self.expression); + ensureSafeFunction(rhs.value, self.expression); + var values = []; + for (var i = 0; i < args.length; ++i) { + values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression)); } - afterLocationChange(oldUrl, oldState); + value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression); } + return context ? {value: value} : value; + }; + case AST.AssignmentExpression: + left = this.recurse(ast.left, true, 1); + right = this.recurse(ast.right); + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + ensureSafeObject(lhs.value, self.expression); + lhs.context[lhs.name] = rhs; + return context ? {value: rhs} : rhs; + }; + case AST.ArrayExpression: + args = []; + forEach(ast.elements, function(expr) { + args.push(self.recurse(expr)); + }); + return function(scope, locals, assign, inputs) { + var value = []; + for (var i = 0; i < args.length; ++i) { + value.push(args[i](scope, locals, assign, inputs)); + } + return context ? {value: value} : value; + }; + case AST.ObjectExpression: + args = []; + forEach(ast.properties, function(property) { + args.push({key: property.key.type === AST.Identifier ? + property.key.name : + ('' + property.key.value), + value: self.recurse(property.value) }); + }); + return function(scope, locals, assign, inputs) { + var value = {}; + for (var i = 0; i < args.length; ++i) { + value[args[i].key] = args[i].value(scope, locals, assign, inputs); + } + return context ? {value: value} : value; + }; + case AST.ThisExpression: + return function(scope) { + return context ? {value: scope} : scope; + }; + case AST.NGValueParameter: + return function(scope, locals, assign, inputs) { + return context ? {value: assign} : assign; + }; + } + }, + + 'unary+': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = +arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary-': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = argument(scope, locals, assign, inputs); + if (isDefined(arg)) { + arg = -arg; + } else { + arg = 0; + } + return context ? {value: arg} : arg; + }; + }, + 'unary!': function(argument, context) { + return function(scope, locals, assign, inputs) { + var arg = !argument(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary+': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = plusFn(lhs, rhs); + return context ? {value: arg} : arg; + }; + }, + 'binary-': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs = right(scope, locals, assign, inputs); + var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0); + return context ? {value: arg} : arg; + }; + }, + 'binary*': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary/': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary%': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary===': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary==': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary!=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary<=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary>=': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary&&': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'binary||': function(left, right, context) { + return function(scope, locals, assign, inputs) { + var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + 'ternary?:': function(test, alternate, consequent, context) { + return function(scope, locals, assign, inputs) { + var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs); + return context ? {value: arg} : arg; + }; + }, + value: function(value, context) { + return function() { return context ? {context: undefined, name: undefined, value: value} : value; }; + }, + identifier: function(name, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var base = locals && (name in locals) ? locals : scope; + if (create && create !== 1 && base && !(base[name])) { + base[name] = {}; + } + var value = base ? base[name] : undefined; + if (expensiveChecks) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: base, name: name, value: value}; + } else { + return value; + } + }; + }, + computedMember: function(left, right, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + var rhs; + var value; + if (lhs != null) { + rhs = right(scope, locals, assign, inputs); + ensureSafeMemberName(rhs, expression); + if (create && create !== 1 && lhs && !(lhs[rhs])) { + lhs[rhs] = {}; + } + value = lhs[rhs]; + ensureSafeObject(value, expression); + } + if (context) { + return {context: lhs, name: rhs, value: value}; + } else { + return value; + } + }; + }, + nonComputedMember: function(left, right, expensiveChecks, context, create, expression) { + return function(scope, locals, assign, inputs) { + var lhs = left(scope, locals, assign, inputs); + if (create && create !== 1 && lhs && !(lhs[right])) { + lhs[right] = {}; + } + var value = lhs != null ? lhs[right] : undefined; + if (expensiveChecks || isPossiblyDangerousMemberName(right)) { + ensureSafeObject(value, expression); + } + if (context) { + return {context: lhs, name: right, value: value}; + } else { + return value; } + }; + }, + inputs: function(input, watchId) { + return function(scope, value, locals, inputs) { + if (inputs) return inputs[watchId]; + return input(scope, value, locals); + }; + } +}; - $location.$$replace = false; +/** + * @constructor + */ +var Parser = function(lexer, $filter, options) { + this.lexer = lexer; + this.$filter = $filter; + this.options = options; + this.ast = new AST(this.lexer); + this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) : + new ASTCompiler(this.ast, $filter); +}; - // we don't need to return anything because $evalAsync will make the digest loop dirty when - // there is a change - }); +Parser.prototype = { + constructor: Parser, - return $location; + parse: function(text) { + return this.astCompiler.compile(text, this.options.expensiveChecks); + } +}; - function afterLocationChange(oldUrl, oldState) { - $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl, - $location.$$state, oldState); +////////////////////////////////////////////////// +// Parser helper functions +////////////////////////////////////////////////// + +function setter(obj, path, setValue, fullExp) { + ensureSafeObject(obj, fullExp); + + var element = path.split('.'), key; + for (var i = 0; element.length > 1; i++) { + key = ensureSafeMemberName(element.shift(), fullExp); + var propertyObj = ensureSafeObject(obj[key], fullExp); + if (!propertyObj) { + propertyObj = {}; + obj[key] = propertyObj; } -}]; + obj = propertyObj; + } + key = ensureSafeMemberName(element.shift(), fullExp); + ensureSafeObject(obj[key], fullExp); + obj[key] = setValue; + return setValue; } +var getterFnCacheDefault = createMap(); +var getterFnCacheExpensive = createMap(); + +function isPossiblyDangerousMemberName(name) { + return name == 'constructor'; +} + +var objectValueOf = Object.prototype.valueOf; + +function getValueOf(value) { + return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); +} + +/////////////////////////////////// + /** * @ngdoc service - * @name $log - * @requires $window + * @name $parse + * @kind function * * @description - * Simple service for logging. Default implementation safely writes the message - * into the browser's console (if present). * - * The main purpose of this service is to simplify debugging and troubleshooting. + * Converts Angular {@link guide/expression expression} into a function. * - * The default is to log `debug` messages. You can use - * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this. + * ```js + * var getter = $parse('user.name'); + * var setter = getter.assign; + * var context = {user:{name:'angular'}}; + * var locals = {user:{name:'local'}}; + * + * expect(getter(context)).toEqual('angular'); + * setter(context, 'newValue'); + * expect(context.user.name).toEqual('newValue'); + * expect(getter(context, locals)).toEqual('local'); + * ``` + * + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + * + * The returned function also has the following properties: + * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript + * literal. + * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript + * constant literals. + * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be + * set to a function to change its value on the given context. * - * @example - <example module="logExample"> - <file name="script.js"> - angular.module('logExample', []) - .controller('LogController', ['$scope', '$log', function($scope, $log) { - $scope.$log = $log; - $scope.message = 'Hello World!'; - }]); - </file> - <file name="index.html"> - <div ng-controller="LogController"> - <p>Reload this page with open console, enter text and hit the log button...</p> - Message: - <input type="text" ng-model="message"/> - <button ng-click="$log.log(message)">log</button> - <button ng-click="$log.warn(message)">warn</button> - <button ng-click="$log.info(message)">info</button> - <button ng-click="$log.error(message)">error</button> - </div> - </file> - </example> */ + /** * @ngdoc provider - * @name $logProvider + * @name $parseProvider + * * @description - * Use the `$logProvider` to configure how the application logs messages + * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} + * service. */ -function $LogProvider() { - var debug = true, - self = this; - - /** - * @ngdoc method - * @name $logProvider#debugEnabled - * @description - * @param {boolean=} flag enable or disable debug level messages - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.debugEnabled = function(flag) { - if (isDefined(flag)) { - debug = flag; - return this; - } else { - return debug; - } - }; - - this.$get = ['$window', function($window) { - return { - /** - * @ngdoc method - * @name $log#log - * - * @description - * Write a log message - */ - log: consoleLog('log'), +function $ParseProvider() { + var cacheDefault = createMap(); + var cacheExpensive = createMap(); - /** - * @ngdoc method - * @name $log#info - * - * @description - * Write an information message - */ - info: consoleLog('info'), + this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { + var $parseOptions = { + csp: $sniffer.csp, + expensiveChecks: false + }, + $parseOptionsExpensive = { + csp: $sniffer.csp, + expensiveChecks: true + }; - /** - * @ngdoc method - * @name $log#warn - * - * @description - * Write a warning message - */ - warn: consoleLog('warn'), + return function $parse(exp, interceptorFn, expensiveChecks) { + var parsedExpression, oneTime, cacheKey; - /** - * @ngdoc method - * @name $log#error - * - * @description - * Write an error message - */ - error: consoleLog('error'), + switch (typeof exp) { + case 'string': + exp = exp.trim(); + cacheKey = exp; - /** - * @ngdoc method - * @name $log#debug - * - * @description - * Write a debug message - */ - debug: (function() { - var fn = consoleLog('debug'); + var cache = (expensiveChecks ? cacheExpensive : cacheDefault); + parsedExpression = cache[cacheKey]; - return function() { - if (debug) { - fn.apply(self, arguments); + if (!parsedExpression) { + if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { + oneTime = true; + exp = exp.substring(2); + } + var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; + var lexer = new Lexer(parseOptions); + var parser = new Parser(lexer, $filter, parseOptions); + parsedExpression = parser.parse(exp); + if (parsedExpression.constant) { + parsedExpression.$$watchDelegate = constantWatchDelegate; + } else if (oneTime) { + parsedExpression.$$watchDelegate = parsedExpression.literal ? + oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; + } else if (parsedExpression.inputs) { + parsedExpression.$$watchDelegate = inputsWatchDelegate; + } + cache[cacheKey] = parsedExpression; } - }; - }()) + return addInterceptor(parsedExpression, interceptorFn); + + case 'function': + return addInterceptor(exp, interceptorFn); + + default: + return noop; + } }; - function formatError(arg) { - if (arg instanceof Error) { - if (arg.stack) { - arg = (arg.message && arg.stack.indexOf(arg.message) === -1) - ? 'Error: ' + arg.message + '\n' + arg.stack - : arg.stack; - } else if (arg.sourceURL) { - arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; - } + function expressionInputDirtyCheck(newValue, oldValueOfValue) { + + if (newValue == null || oldValueOfValue == null) { // null/undefined + return newValue === oldValueOfValue; } - return arg; - } - function consoleLog(type) { - var console = $window.console || {}, - logFn = console[type] || console.log || noop, - hasApply = false; + if (typeof newValue === 'object') { - // Note: reading logFn.apply throws an error in IE11 in IE8 document mode. - // The reason behind this is that console.log has type "object" in IE8... - try { - hasApply = !!logFn.apply; - } catch (e) {} + // attempt to convert the value to a primitive type + // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can + // be cheaply dirty-checked + newValue = getValueOf(newValue); - if (hasApply) { - return function() { - var args = []; - forEach(arguments, function(arg) { - args.push(formatError(arg)); - }); - return logFn.apply(console, args); - }; + if (typeof newValue === 'object') { + // objects/arrays are not supported - deep-watching them would be too expensive + return false; + } + + // fall-through to the primitive equality check } - // we are IE which either doesn't have window.console => this is noop and we do nothing, - // or we are IE where console.log doesn't have apply so we log at least first 2 args - return function(arg1, arg2) { - logFn(arg1, arg2 == null ? '' : arg2); - }; + //Primitive or NaN + return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); } - }]; -} -var $parseMinErr = minErr('$parse'); + function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { + var inputExpressions = parsedExpression.inputs; + var lastResult; -// Sandboxing Angular Expressions -// ------------------------------ -// Angular expressions are generally considered safe because these expressions only have direct -// access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by -// obtaining a reference to native JS functions such as the Function constructor. -// -// As an example, consider the following Angular expression: -// -// {}.toString.constructor('alert("evil JS code")') -// -// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits -// against the expression language, but not to prevent exploits that were enabled by exposing -// sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good -// practice and therefore we are not even trying to protect against interaction with an object -// explicitly exposed in this way. -// -// In general, it is not possible to access a Window object from an angular expression unless a -// window or some DOM object that has a reference to window is published onto a Scope. -// Similarly we prevent invocations of function known to be dangerous, as well as assignments to -// native objects. -// -// See https://docs.angularjs.org/guide/security + if (inputExpressions.length === 1) { + var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails + inputExpressions = inputExpressions[0]; + return scope.$watch(function expressionInputWatch(scope) { + var newInputValue = inputExpressions(scope); + if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) { + lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]); + oldInputValueOf = newInputValue && getValueOf(newInputValue); + } + return lastResult; + }, listener, objectEquality, prettyPrintExpression); + } + var oldInputValueOfValues = []; + var oldInputValues = []; + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails + oldInputValues[i] = null; + } -function ensureSafeMemberName(name, fullExpression) { - if (name === "__defineGetter__" || name === "__defineSetter__" - || name === "__lookupGetter__" || name === "__lookupSetter__" - || name === "__proto__") { - throw $parseMinErr('isecfld', - 'Attempting to access a disallowed field in Angular expressions! ' - + 'Expression: {0}', fullExpression); - } - return name; -} + return scope.$watch(function expressionInputsWatch(scope) { + var changed = false; -function ensureSafeObject(obj, fullExpression) { - // nifty check if obj is Function that is fast and works across iframes and other contexts - if (obj) { - if (obj.constructor === obj) { - throw $parseMinErr('isecfn', - 'Referencing Function in Angular expressions is disallowed! Expression: {0}', - fullExpression); - } else if (// isWindow(obj) - obj.window === obj) { - throw $parseMinErr('isecwindow', - 'Referencing the Window in Angular expressions is disallowed! Expression: {0}', - fullExpression); - } else if (// isElement(obj) - obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) { - throw $parseMinErr('isecdom', - 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}', - fullExpression); - } else if (// block Object so that we can't get hold of dangerous Object.* methods - obj === Object) { - throw $parseMinErr('isecobj', - 'Referencing Object in Angular expressions is disallowed! Expression: {0}', - fullExpression); - } - } - return obj; -} + for (var i = 0, ii = inputExpressions.length; i < ii; i++) { + var newInputValue = inputExpressions[i](scope); + if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { + oldInputValues[i] = newInputValue; + oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + } + } -var CALL = Function.prototype.call; -var APPLY = Function.prototype.apply; -var BIND = Function.prototype.bind; + if (changed) { + lastResult = parsedExpression(scope, undefined, undefined, oldInputValues); + } -function ensureSafeFunction(obj, fullExpression) { - if (obj) { - if (obj.constructor === obj) { - throw $parseMinErr('isecfn', - 'Referencing Function in Angular expressions is disallowed! Expression: {0}', - fullExpression); - } else if (obj === CALL || obj === APPLY || obj === BIND) { - throw $parseMinErr('isecff', - 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}', - fullExpression); + return lastResult; + }, listener, objectEquality, prettyPrintExpression); } - } -} -//Keyword constants -var CONSTANTS = createMap(); -forEach({ - 'null': function() { return null; }, - 'true': function() { return true; }, - 'false': function() { return false; }, - 'undefined': function() {} -}, function(constantGetter, name) { - constantGetter.constant = constantGetter.literal = constantGetter.sharedGetter = true; - CONSTANTS[name] = constantGetter; -}); + function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.apply(this, arguments); + } + if (isDefined(value)) { + scope.$$postDigest(function() { + if (isDefined(lastValue)) { + unwatch(); + } + }); + } + }, objectEquality); + } -//Not quite a constant, but can be lex/parsed the same -CONSTANTS['this'] = function(self) { return self; }; -CONSTANTS['this'].sharedGetter = true; + function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch, lastValue; + return unwatch = scope.$watch(function oneTimeWatch(scope) { + return parsedExpression(scope); + }, function oneTimeListener(value, old, scope) { + lastValue = value; + if (isFunction(listener)) { + listener.call(this, value, old, scope); + } + if (isAllDefined(value)) { + scope.$$postDigest(function() { + if (isAllDefined(lastValue)) unwatch(); + }); + } + }, objectEquality); + function isAllDefined(value) { + var allDefined = true; + forEach(value, function(val) { + if (!isDefined(val)) allDefined = false; + }); + return allDefined; + } + } -//Operators - will be wrapped by binaryFn/unaryFn/assignment/filter -var OPERATORS = extend(createMap(), { - '+':function(self, locals, a, b) { - a=a(self, locals); b=b(self, locals); - if (isDefined(a)) { - if (isDefined(b)) { - return a + b; + function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { + var unwatch; + return unwatch = scope.$watch(function constantWatch(scope) { + return parsedExpression(scope); + }, function constantListener(value, old, scope) { + if (isFunction(listener)) { + listener.apply(this, arguments); } - return a; + unwatch(); + }, objectEquality); + } + + function addInterceptor(parsedExpression, interceptorFn) { + if (!interceptorFn) return parsedExpression; + var watchDelegate = parsedExpression.$$watchDelegate; + + var regularWatch = + watchDelegate !== oneTimeLiteralWatchDelegate && + watchDelegate !== oneTimeWatchDelegate; + + var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + return interceptorFn(value, scope, locals); + } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) { + var value = parsedExpression(scope, locals, assign, inputs); + var result = interceptorFn(value, scope, locals); + // we only return the interceptor's result if the + // initial value is defined (for bind-once) + return isDefined(value) ? result : value; + }; + + // Propagate $$watchDelegates other then inputsWatchDelegate + if (parsedExpression.$$watchDelegate && + parsedExpression.$$watchDelegate !== inputsWatchDelegate) { + fn.$$watchDelegate = parsedExpression.$$watchDelegate; + } else if (!interceptorFn.$stateful) { + // If there is an interceptor, but no watchDelegate then treat the interceptor like + // we treat filters - it is assumed to be a pure function unless flagged with $stateful + fn.$$watchDelegate = inputsWatchDelegate; + fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]; } - return isDefined(b) ? b : undefined;}, - '-':function(self, locals, a, b) { - a=a(self, locals); b=b(self, locals); - return (isDefined(a) ? a : 0) - (isDefined(b) ? b : 0); - }, - '*':function(self, locals, a, b) {return a(self, locals) * b(self, locals);}, - '/':function(self, locals, a, b) {return a(self, locals) / b(self, locals);}, - '%':function(self, locals, a, b) {return a(self, locals) % b(self, locals);}, - '===':function(self, locals, a, b) {return a(self, locals) === b(self, locals);}, - '!==':function(self, locals, a, b) {return a(self, locals) !== b(self, locals);}, - '==':function(self, locals, a, b) {return a(self, locals) == b(self, locals);}, - '!=':function(self, locals, a, b) {return a(self, locals) != b(self, locals);}, - '<':function(self, locals, a, b) {return a(self, locals) < b(self, locals);}, - '>':function(self, locals, a, b) {return a(self, locals) > b(self, locals);}, - '<=':function(self, locals, a, b) {return a(self, locals) <= b(self, locals);}, - '>=':function(self, locals, a, b) {return a(self, locals) >= b(self, locals);}, - '&&':function(self, locals, a, b) {return a(self, locals) && b(self, locals);}, - '||':function(self, locals, a, b) {return a(self, locals) || b(self, locals);}, - '!':function(self, locals, a) {return !a(self, locals);}, - - //Tokenized as operators but parsed as assignment/filters - '=':true, - '|':true -}); -var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; + return fn; + } + }]; +} + +/** + * @ngdoc service + * @name $q + * @requires $rootScope + * + * @description + * A service that helps you run functions asynchronously, and use their return values (or exceptions) + * when they are done processing. + * + * This is an implementation of promises/deferred objects inspired by + * [Kris Kowal's Q](https://github.com/kriskowal/q). + * + * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred + * implementations, and the other which resembles ES6 promises to some degree. + * + * # $q constructor + * + * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` + * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony, + * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). + * + * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are + * available yet. + * + * It can be used like so: + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * // perform some asynchronous operation, resolve or reject the promise when appropriate. + * return $q(function(resolve, reject) { + * setTimeout(function() { + * if (okToGreet(name)) { + * resolve('Hello, ' + name + '!'); + * } else { + * reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * }); + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }); + * ``` + * + * Note: progress/notify callbacks are not currently supported via the ES6-style interface. + * + * However, the more traditional CommonJS-style usage is still available, and documented below. + * + * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an + * interface for interacting with an object that represents the result of an action that is + * performed asynchronously, and may or may not be finished at any given point in time. + * + * From the perspective of dealing with error handling, deferred and promise APIs are to + * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. + * + * ```js + * // for the purpose of this example let's assume that variables `$q` and `okToGreet` + * // are available in the current lexical scope (they could have been injected or passed in). + * + * function asyncGreet(name) { + * var deferred = $q.defer(); + * + * setTimeout(function() { + * deferred.notify('About to greet ' + name + '.'); + * + * if (okToGreet(name)) { + * deferred.resolve('Hello, ' + name + '!'); + * } else { + * deferred.reject('Greeting ' + name + ' is not allowed.'); + * } + * }, 1000); + * + * return deferred.promise; + * } + * + * var promise = asyncGreet('Robin Hood'); + * promise.then(function(greeting) { + * alert('Success: ' + greeting); + * }, function(reason) { + * alert('Failed: ' + reason); + * }, function(update) { + * alert('Got notification: ' + update); + * }); + * ``` + * + * At first it might not be obvious why this extra complexity is worth the trouble. The payoff + * comes in the way of guarantees that promise and deferred APIs make, see + * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. + * + * Additionally the promise api allows for composition that is very hard to do with the + * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. + * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the + * section on serial or parallel joining of promises. + * + * # The Deferred API + * + * A new instance of deferred is constructed by calling `$q.defer()`. + * + * The purpose of the deferred object is to expose the associated Promise instance as well as APIs + * that can be used for signaling the successful or unsuccessful completion, as well as the status + * of the task. + * + * **Methods** + * + * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection + * constructed via `$q.reject`, the promise will be rejected instead. + * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to + * resolving it with a rejection constructed via `$q.reject`. + * - `notify(value)` - provides updates on the status of the promise's execution. This may be called + * multiple times before the promise is either resolved or rejected. + * + * **Properties** + * + * - promise – `{Promise}` – promise object associated with this deferred. + * + * + * # The Promise API + * + * A new promise instance is created when a deferred instance is created and can be retrieved by + * calling `deferred.promise`. + * + * The purpose of the promise object is to allow for interested parties to get access to the result + * of the deferred task when it completes. + * + * **Methods** + * + * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or + * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously + * as soon as the result is available. The callbacks are called with a single argument: the result + * or rejection reason. Additionally, the notify callback may be called zero or more times to + * provide a progress indication, before the promise is resolved or rejected. + * + * This method *returns a new promise* which is resolved or rejected via the return value of the + * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved + * with the value which is resolved in that promise using + * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)). + * It also notifies via the return value of the `notifyCallback` method. The promise cannot be + * resolved or rejected from the notifyCallback method. + * + * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` + * + * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, + * but to do so without modifying the final value. This is useful to release resources or do some + * clean-up that needs to be done whether the promise was rejected or resolved. See the [full + * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for + * more information. + * + * # Chaining promises + * + * Because calling the `then` method of a promise returns a new derived promise, it is easily + * possible to create a chain of promises: + * + * ```js + * promiseB = promiseA.then(function(result) { + * return result + 1; + * }); + * + * // promiseB will be resolved immediately after promiseA is resolved and its value + * // will be the result of promiseA incremented by 1 + * ``` + * + * It is possible to create chains of any length and since a promise can be resolved with another + * promise (which will defer its resolution further), it is possible to pause/defer resolution of + * the promises at any point in the chain. This makes it possible to implement powerful APIs like + * $http's response interceptors. + * + * + * # Differences between Kris Kowal's Q and $q + * + * There are two main differences: + * + * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation + * mechanism in angular, which means faster propagation of resolution or rejection into your + * models and avoiding unnecessary browser repaints, which would result in flickering UI. + * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains + * all the important functionality needed for common async tasks. + * + * # Testing + * + * ```js + * it('should simulate promise', inject(function($q, $rootScope) { + * var deferred = $q.defer(); + * var promise = deferred.promise; + * var resolvedValue; + * + * promise.then(function(value) { resolvedValue = value; }); + * expect(resolvedValue).toBeUndefined(); + * + * // Simulate resolving of promise + * deferred.resolve(123); + * // Note that the 'then' function does not get called synchronously. + * // This is because we want the promise API to always be async, whether or not + * // it got called synchronously or asynchronously. + * expect(resolvedValue).toBeUndefined(); + * + * // Propagate promise resolution to 'then' functions using $apply(). + * $rootScope.$apply(); + * expect(resolvedValue).toEqual(123); + * })); + * ``` + * + * @param {function(function, function)} resolver Function which is responsible for resolving or + * rejecting the newly created promise. The first parameter is a function which resolves the + * promise, the second parameter is a function which rejects the promise. + * + * @returns {Promise} The newly created promise. + */ +function $QProvider() { -///////////////////////////////////////// + this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { + return qFactory(function(callback) { + $rootScope.$evalAsync(callback); + }, $exceptionHandler); + }]; +} +function $$QProvider() { + this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { + return qFactory(function(callback) { + $browser.defer(callback); + }, $exceptionHandler); + }]; +} /** - * @constructor + * Constructs a promise manager. + * + * @param {function(function)} nextTick Function for executing functions in the next turn. + * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for + * debugging purposes. + * @returns {object} Promise manager. */ -var Lexer = function(options) { - this.options = options; -}; - -Lexer.prototype = { - constructor: Lexer, - - lex: function(text) { - this.text = text; - this.index = 0; - this.tokens = []; - - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - if (ch === '"' || ch === "'") { - this.readString(ch); - } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) { - this.readNumber(); - } else if (this.isIdent(ch)) { - this.readIdent(); - } else if (this.is(ch, '(){}[].,;:?')) { - this.tokens.push({index: this.index, text: ch}); - this.index++; - } else if (this.isWhitespace(ch)) { - this.index++; - } else { - var ch2 = ch + this.peek(); - var ch3 = ch2 + this.peek(2); - var op1 = OPERATORS[ch]; - var op2 = OPERATORS[ch2]; - var op3 = OPERATORS[ch3]; - if (op1 || op2 || op3) { - var token = op3 ? ch3 : (op2 ? ch2 : ch); - this.tokens.push({index: this.index, text: token, operator: true}); - this.index += token.length; - } else { - this.throwError('Unexpected next character ', this.index, this.index + 1); - } - } +function qFactory(nextTick, exceptionHandler) { + var $qMinErr = minErr('$q', TypeError); + function callOnce(self, resolveFn, rejectFn) { + var called = false; + function wrap(fn) { + return function(value) { + if (called) return; + called = true; + fn.call(self, value); + }; } - return this.tokens; - }, - is: function(ch, chars) { - return chars.indexOf(ch) !== -1; - }, + return [wrap(resolveFn), wrap(rejectFn)]; + } - peek: function(i) { - var num = i || 1; - return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false; - }, + /** + * @ngdoc method + * @name ng.$q#defer + * @kind function + * + * @description + * Creates a `Deferred` object which represents a task which will finish in the future. + * + * @returns {Deferred} Returns a new instance of deferred. + */ + var defer = function() { + return new Deferred(); + }; - isNumber: function(ch) { - return ('0' <= ch && ch <= '9') && typeof ch === "string"; - }, + function Promise() { + this.$$state = { status: 0 }; + } - isWhitespace: function(ch) { - // IE treats non-breaking space as \u00A0 - return (ch === ' ' || ch === '\r' || ch === '\t' || - ch === '\n' || ch === '\v' || ch === '\u00A0'); - }, + Promise.prototype = { + then: function(onFulfilled, onRejected, progressBack) { + var result = new Deferred(); - isIdent: function(ch) { - return ('a' <= ch && ch <= 'z' || - 'A' <= ch && ch <= 'Z' || - '_' === ch || ch === '$'); - }, + this.$$state.pending = this.$$state.pending || []; + this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); + if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); - isExpOperator: function(ch) { - return (ch === '-' || ch === '+' || this.isNumber(ch)); - }, + return result.promise; + }, - throwError: function(error, start, end) { - end = end || this.index; - var colStr = (isDefined(start) - ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']' - : ' ' + end); - throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].', - error, colStr, this.text); - }, + "catch": function(callback) { + return this.then(null, callback); + }, - readNumber: function() { - var number = ''; - var start = this.index; - while (this.index < this.text.length) { - var ch = lowercase(this.text.charAt(this.index)); - if (ch == '.' || this.isNumber(ch)) { - number += ch; - } else { - var peekCh = this.peek(); - if (ch == 'e' && this.isExpOperator(peekCh)) { - number += ch; - } else if (this.isExpOperator(ch) && - peekCh && this.isNumber(peekCh) && - number.charAt(number.length - 1) == 'e') { - number += ch; - } else if (this.isExpOperator(ch) && - (!peekCh || !this.isNumber(peekCh)) && - number.charAt(number.length - 1) == 'e') { - this.throwError('Invalid exponent'); - } else { - break; - } - } - this.index++; + "finally": function(callback, progressBack) { + return this.then(function(value) { + return handleCallback(value, true, callback); + }, function(error) { + return handleCallback(error, false, callback); + }, progressBack); } - this.tokens.push({ - index: start, - text: number, - constant: true, - value: Number(number) - }); - }, + }; - readIdent: function() { - var start = this.index; - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - if (!(this.isIdent(ch) || this.isNumber(ch))) { - break; - } - this.index++; - } - this.tokens.push({ - index: start, - text: this.text.slice(start, this.index), - identifier: true - }); - }, + //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native + function simpleBind(context, fn) { + return function(value) { + fn.call(context, value); + }; + } - readString: function(quote) { - var start = this.index; - this.index++; - var string = ''; - var rawString = quote; - var escape = false; - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - rawString += ch; - if (escape) { - if (ch === 'u') { - var hex = this.text.substring(this.index + 1, this.index + 5); - if (!hex.match(/[\da-f]{4}/i)) - this.throwError('Invalid unicode escape [\\u' + hex + ']'); - this.index += 4; - string += String.fromCharCode(parseInt(hex, 16)); + function processQueue(state) { + var fn, deferred, pending; + + pending = state.pending; + state.processScheduled = false; + state.pending = undefined; + for (var i = 0, ii = pending.length; i < ii; ++i) { + deferred = pending[i][0]; + fn = pending[i][state.status]; + try { + if (isFunction(fn)) { + deferred.resolve(fn(state.value)); + } else if (state.status === 1) { + deferred.resolve(state.value); } else { - var rep = ESCAPE[ch]; - string = string + (rep || ch); + deferred.reject(state.value); } - escape = false; - } else if (ch === '\\') { - escape = true; - } else if (ch === quote) { - this.index++; - this.tokens.push({ - index: start, - text: rawString, - constant: true, - value: string - }); - return; - } else { - string += ch; + } catch (e) { + deferred.reject(e); + exceptionHandler(e); } - this.index++; } - this.throwError('Unterminated quote', start); } -}; - - -function isConstant(exp) { - return exp.constant; -} - -/** - * @constructor - */ -var Parser = function(lexer, $filter, options) { - this.lexer = lexer; - this.$filter = $filter; - this.options = options; -}; - -Parser.ZERO = extend(function() { - return 0; -}, { - sharedGetter: true, - constant: true -}); - -Parser.prototype = { - constructor: Parser, - - parse: function(text) { - this.text = text; - this.tokens = this.lexer.lex(text); - - var value = this.statements(); - - if (this.tokens.length !== 0) { - this.throwError('is an unexpected token', this.tokens[0]); - } - value.literal = !!value.literal; - value.constant = !!value.constant; - - return value; - }, + function scheduleProcessQueue(state) { + if (state.processScheduled || !state.pending) return; + state.processScheduled = true; + nextTick(function() { processQueue(state); }); + } - primary: function() { - var primary; - if (this.expect('(')) { - primary = this.filterChain(); - this.consume(')'); - } else if (this.expect('[')) { - primary = this.arrayDeclaration(); - } else if (this.expect('{')) { - primary = this.object(); - } else if (this.peek().identifier && this.peek().text in CONSTANTS) { - primary = CONSTANTS[this.consume().text]; - } else if (this.peek().identifier) { - primary = this.identifier(); - } else if (this.peek().constant) { - primary = this.constant(); - } else { - this.throwError('not a primary expression', this.peek()); - } + function Deferred() { + this.promise = new Promise(); + //Necessary to support unbound execution :/ + this.resolve = simpleBind(this, this.resolve); + this.reject = simpleBind(this, this.reject); + this.notify = simpleBind(this, this.notify); + } - var next, context; - while ((next = this.expect('(', '[', '.'))) { - if (next.text === '(') { - primary = this.functionCall(primary, context); - context = null; - } else if (next.text === '[') { - context = primary; - primary = this.objectIndex(primary); - } else if (next.text === '.') { - context = primary; - primary = this.fieldAccess(primary); + Deferred.prototype = { + resolve: function(val) { + if (this.promise.$$state.status) return; + if (val === this.promise) { + this.$$reject($qMinErr( + 'qcycle', + "Expected promise to be resolved with value other than itself '{0}'", + val)); } else { - this.throwError('IMPOSSIBLE'); - } - } - return primary; - }, - - throwError: function(msg, token) { - throw $parseMinErr('syntax', - 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', - token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); - }, - - peekToken: function() { - if (this.tokens.length === 0) - throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); - return this.tokens[0]; - }, - - peek: function(e1, e2, e3, e4) { - return this.peekAhead(0, e1, e2, e3, e4); - }, - peekAhead: function(i, e1, e2, e3, e4) { - if (this.tokens.length > i) { - var token = this.tokens[i]; - var t = token.text; - if (t === e1 || t === e2 || t === e3 || t === e4 || - (!e1 && !e2 && !e3 && !e4)) { - return token; - } - } - return false; - }, - - expect: function(e1, e2, e3, e4) { - var token = this.peek(e1, e2, e3, e4); - if (token) { - this.tokens.shift(); - return token; - } - return false; - }, - - consume: function(e1) { - if (this.tokens.length === 0) { - throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); - } - - var token = this.expect(e1); - if (!token) { - this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); - } - return token; - }, - - unaryFn: function(op, right) { - var fn = OPERATORS[op]; - return extend(function $parseUnaryFn(self, locals) { - return fn(self, locals, right); - }, { - constant:right.constant, - inputs: [right] - }); - }, - - binaryFn: function(left, op, right, isBranching) { - var fn = OPERATORS[op]; - return extend(function $parseBinaryFn(self, locals) { - return fn(self, locals, left, right); - }, { - constant: left.constant && right.constant, - inputs: !isBranching && [left, right] - }); - }, - - identifier: function() { - var id = this.consume().text; - - //Continue reading each `.identifier` unless it is a method invocation - while (this.peek('.') && this.peekAhead(1).identifier && !this.peekAhead(2, '(')) { - id += this.consume().text + this.consume().text; - } - - return getterFn(id, this.options, this.text); - }, - - constant: function() { - var value = this.consume().value; - - return extend(function $parseConstant() { - return value; - }, { - constant: true, - literal: true - }); - }, - - statements: function() { - var statements = []; - while (true) { - if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) - statements.push(this.filterChain()); - if (!this.expect(';')) { - // optimize for the common case where there is only one statement. - // TODO(size): maybe we should not support multiple statements? - return (statements.length === 1) - ? statements[0] - : function $parseStatements(self, locals) { - var value; - for (var i = 0, ii = statements.length; i < ii; i++) { - value = statements[i](self, locals); - } - return value; - }; - } - } - }, - - filterChain: function() { - var left = this.expression(); - var token; - while ((token = this.expect('|'))) { - left = this.filter(left); - } - return left; - }, - - filter: function(inputFn) { - var fn = this.$filter(this.consume().text); - var argsFn; - var args; - - if (this.peek(':')) { - argsFn = []; - args = []; // we can safely reuse the array - while (this.expect(':')) { - argsFn.push(this.expression()); + this.$$resolve(val); } - } - var inputs = [inputFn].concat(argsFn || []); + }, - return extend(function $parseFilter(self, locals) { - var input = inputFn(self, locals); - if (args) { - args[0] = input; + $$resolve: function(val) { + var then, fns; - var i = argsFn.length; - while (i--) { - args[i + 1] = argsFn[i](self, locals); + fns = callOnce(this, this.$$resolve, this.$$reject); + try { + if ((isObject(val) || isFunction(val))) then = val && val.then; + if (isFunction(then)) { + this.promise.$$state.status = -1; + then.call(val, fns[0], fns[1], this.notify); + } else { + this.promise.$$state.value = val; + this.promise.$$state.status = 1; + scheduleProcessQueue(this.promise.$$state); } - - return fn.apply(undefined, args); + } catch (e) { + fns[1](e); + exceptionHandler(e); } + }, - return fn(input); - }, { - constant: !fn.$stateful && inputs.every(isConstant), - inputs: !fn.$stateful && inputs - }); - }, - - expression: function() { - return this.assignment(); - }, + reject: function(reason) { + if (this.promise.$$state.status) return; + this.$$reject(reason); + }, - assignment: function() { - var left = this.ternary(); - var right; - var token; - if ((token = this.expect('='))) { - if (!left.assign) { - this.throwError('implies assignment but [' + - this.text.substring(0, token.index) + '] can not be assigned to', token); - } - right = this.ternary(); - return extend(function $parseAssignment(scope, locals) { - return left.assign(scope, right(scope, locals), locals); - }, { - inputs: [left, right] - }); - } - return left; - }, + $$reject: function(reason) { + this.promise.$$state.value = reason; + this.promise.$$state.status = 2; + scheduleProcessQueue(this.promise.$$state); + }, - ternary: function() { - var left = this.logicalOR(); - var middle; - var token; - if ((token = this.expect('?'))) { - middle = this.assignment(); - if (this.consume(':')) { - var right = this.assignment(); + notify: function(progress) { + var callbacks = this.promise.$$state.pending; - return extend(function $parseTernary(self, locals) { - return left(self, locals) ? middle(self, locals) : right(self, locals); - }, { - constant: left.constant && middle.constant && right.constant + if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) { + nextTick(function() { + var callback, result; + for (var i = 0, ii = callbacks.length; i < ii; i++) { + result = callbacks[i][0]; + callback = callbacks[i][3]; + try { + result.notify(isFunction(callback) ? callback(progress) : progress); + } catch (e) { + exceptionHandler(e); + } + } }); } } + }; - return left; - }, - - logicalOR: function() { - var left = this.logicalAND(); - var token; - while ((token = this.expect('||'))) { - left = this.binaryFn(left, token.text, this.logicalAND(), true); - } - return left; - }, - - logicalAND: function() { - var left = this.equality(); - var token; - while ((token = this.expect('&&'))) { - left = this.binaryFn(left, token.text, this.equality(), true); - } - return left; - }, - - equality: function() { - var left = this.relational(); - var token; - while ((token = this.expect('==','!=','===','!=='))) { - left = this.binaryFn(left, token.text, this.relational()); - } - return left; - }, - - relational: function() { - var left = this.additive(); - var token; - while ((token = this.expect('<', '>', '<=', '>='))) { - left = this.binaryFn(left, token.text, this.additive()); - } - return left; - }, + /** + * @ngdoc method + * @name $q#reject + * @kind function + * + * @description + * Creates a promise that is resolved as rejected with the specified `reason`. This api should be + * used to forward rejection in a chain of promises. If you are dealing with the last promise in + * a promise chain, you don't need to worry about it. + * + * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of + * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via + * a promise error callback and you want to forward the error to the promise derived from the + * current promise, you have to "rethrow" the error by returning a rejection constructed via + * `reject`. + * + * ```js + * promiseB = promiseA.then(function(result) { + * // success: do something and resolve promiseB + * // with the old or a new result + * return result; + * }, function(reason) { + * // error: handle the error if possible and + * // resolve promiseB with newPromiseOrValue, + * // otherwise forward the rejection to promiseB + * if (canHandle(reason)) { + * // handle the error and recover + * return newPromiseOrValue; + * } + * return $q.reject(reason); + * }); + * ``` + * + * @param {*} reason Constant, message, exception or an object representing the rejection reason. + * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. + */ + var reject = function(reason) { + var result = new Deferred(); + result.reject(reason); + return result.promise; + }; - additive: function() { - var left = this.multiplicative(); - var token; - while ((token = this.expect('+','-'))) { - left = this.binaryFn(left, token.text, this.multiplicative()); + var makePromise = function makePromise(value, resolved) { + var result = new Deferred(); + if (resolved) { + result.resolve(value); + } else { + result.reject(value); } - return left; - }, + return result.promise; + }; - multiplicative: function() { - var left = this.unary(); - var token; - while ((token = this.expect('*','/','%'))) { - left = this.binaryFn(left, token.text, this.unary()); + var handleCallback = function handleCallback(value, isResolved, callback) { + var callbackOutput = null; + try { + if (isFunction(callback)) callbackOutput = callback(); + } catch (e) { + return makePromise(e, false); } - return left; - }, - - unary: function() { - var token; - if (this.expect('+')) { - return this.primary(); - } else if ((token = this.expect('-'))) { - return this.binaryFn(Parser.ZERO, token.text, this.unary()); - } else if ((token = this.expect('!'))) { - return this.unaryFn(token.text, this.unary()); + if (isPromiseLike(callbackOutput)) { + return callbackOutput.then(function() { + return makePromise(value, isResolved); + }, function(error) { + return makePromise(error, false); + }); } else { - return this.primary(); - } - }, - - fieldAccess: function(object) { - var getter = this.identifier(); - - return extend(function $parseFieldAccess(scope, locals, self) { - var o = self || object(scope, locals); - return (o == null) ? undefined : getter(o); - }, { - assign: function(scope, value, locals) { - var o = object(scope, locals); - if (!o) object.assign(scope, o = {}, locals); - return getter.assign(o, value); - } - }); - }, - - objectIndex: function(obj) { - var expression = this.text; - - var indexFn = this.expression(); - this.consume(']'); - - return extend(function $parseObjectIndex(self, locals) { - var o = obj(self, locals), - i = indexFn(self, locals), - v; - - ensureSafeMemberName(i, expression); - if (!o) return undefined; - v = ensureSafeObject(o[i], expression); - return v; - }, { - assign: function(self, value, locals) { - var key = ensureSafeMemberName(indexFn(self, locals), expression); - // prevent overwriting of Function.constructor which would break ensureSafeObject check - var o = ensureSafeObject(obj(self, locals), expression); - if (!o) obj.assign(self, o = {}, locals); - return o[key] = value; - } - }); - }, - - functionCall: function(fnGetter, contextGetter) { - var argsFn = []; - if (this.peekToken().text !== ')') { - do { - argsFn.push(this.expression()); - } while (this.expect(',')); + return makePromise(value, isResolved); } - this.consume(')'); - - var expressionText = this.text; - // we can safely reuse the array across invocations - var args = argsFn.length ? [] : null; - - return function $parseFunctionCall(scope, locals) { - var context = contextGetter ? contextGetter(scope, locals) : isDefined(contextGetter) ? undefined : scope; - var fn = fnGetter(scope, locals, context) || noop; + }; - if (args) { - var i = argsFn.length; - while (i--) { - args[i] = ensureSafeObject(argsFn[i](scope, locals), expressionText); - } - } + /** + * @ngdoc method + * @name $q#when + * @kind function + * + * @description + * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. + * This is useful when you are dealing with an object that might or might not be a promise, or if + * the promise comes from a source that can't be trusted. + * + * @param {*} value Value or a promise + * @returns {Promise} Returns a promise of the passed value or promise + */ - ensureSafeObject(context, expressionText); - ensureSafeFunction(fn, expressionText); - // IE doesn't have apply for some native functions - var v = fn.apply - ? fn.apply(context, args) - : fn(args[0], args[1], args[2], args[3], args[4]); + var when = function(value, callback, errback, progressBack) { + var result = new Deferred(); + result.resolve(value); + return result.promise.then(callback, errback, progressBack); + }; - if (args) { - // Free-up the memory (arguments of the last function call). - args.length = 0; - } + /** + * @ngdoc method + * @name $q#resolve + * @kind function + * + * @description + * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6. + * + * @param {*} value Value or a promise + * @returns {Promise} Returns a promise of the passed value or promise + */ + var resolve = when; - return ensureSafeObject(v, expressionText); - }; - }, + /** + * @ngdoc method + * @name $q#all + * @kind function + * + * @description + * Combines multiple promises into a single promise that is resolved when all of the input + * promises are resolved. + * + * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises. + * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, + * each value corresponding to the promise at the same index/key in the `promises` array/hash. + * If any of the promises is resolved with a rejection, this resulting promise will be rejected + * with the same rejection value. + */ - // This is used with json array declaration - arrayDeclaration: function() { - var elementFns = []; - if (this.peekToken().text !== ']') { - do { - if (this.peek(']')) { - // Support trailing commas per ES5.1. - break; - } - elementFns.push(this.expression()); - } while (this.expect(',')); - } - this.consume(']'); + function all(promises) { + var deferred = new Deferred(), + counter = 0, + results = isArray(promises) ? [] : {}; - return extend(function $parseArrayLiteral(self, locals) { - var array = []; - for (var i = 0, ii = elementFns.length; i < ii; i++) { - array.push(elementFns[i](self, locals)); - } - return array; - }, { - literal: true, - constant: elementFns.every(isConstant), - inputs: elementFns + forEach(promises, function(promise, key) { + counter++; + when(promise).then(function(value) { + if (results.hasOwnProperty(key)) return; + results[key] = value; + if (!(--counter)) deferred.resolve(results); + }, function(reason) { + if (results.hasOwnProperty(key)) return; + deferred.reject(reason); + }); }); - }, - object: function() { - var keys = [], valueFns = []; - if (this.peekToken().text !== '}') { - do { - if (this.peek('}')) { - // Support trailing commas per ES5.1. - break; - } - var token = this.consume(); - if (token.constant) { - keys.push(token.value); - } else if (token.identifier) { - keys.push(token.text); - } else { - this.throwError("invalid key", token); - } - this.consume(':'); - valueFns.push(this.expression()); - } while (this.expect(',')); + if (counter === 0) { + deferred.resolve(results); } - this.consume('}'); - return extend(function $parseObjectLiteral(self, locals) { - var object = {}; - for (var i = 0, ii = valueFns.length; i < ii; i++) { - object[keys[i]] = valueFns[i](self, locals); - } - return object; - }, { - literal: true, - constant: valueFns.every(isConstant), - inputs: valueFns - }); + return deferred.promise; } -}; + var $Q = function Q(resolver) { + if (!isFunction(resolver)) { + throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); + } -////////////////////////////////////////////////// -// Parser helper functions -////////////////////////////////////////////////// + if (!(this instanceof Q)) { + // More useful when $Q is the Promise itself. + return new Q(resolver); + } -function setter(obj, locals, path, setValue, fullExp) { - ensureSafeObject(obj, fullExp); - ensureSafeObject(locals, fullExp); + var deferred = new Deferred(); - var element = path.split('.'), key; - for (var i = 0; element.length > 1; i++) { - key = ensureSafeMemberName(element.shift(), fullExp); - var propertyObj = (i === 0 && locals && locals[key]) || obj[key]; - if (!propertyObj) { - propertyObj = {}; - obj[key] = propertyObj; + function resolveFn(value) { + deferred.resolve(value); } - obj = ensureSafeObject(propertyObj, fullExp); - } - key = ensureSafeMemberName(element.shift(), fullExp); - ensureSafeObject(obj[key], fullExp); - obj[key] = setValue; - return setValue; -} -var getterFnCacheDefault = createMap(); -var getterFnCacheExpensive = createMap(); + function rejectFn(reason) { + deferred.reject(reason); + } -function isPossiblyDangerousMemberName(name) { - return name == 'constructor'; -} + resolver(resolveFn, rejectFn); -/** - * Implementation of the "Black Hole" variant from: - * - http://jsperf.com/angularjs-parse-getter/4 - * - http://jsperf.com/path-evaluation-simplified/7 - */ -function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, expensiveChecks) { - ensureSafeMemberName(key0, fullExp); - ensureSafeMemberName(key1, fullExp); - ensureSafeMemberName(key2, fullExp); - ensureSafeMemberName(key3, fullExp); - ensureSafeMemberName(key4, fullExp); - var eso = function(o) { - return ensureSafeObject(o, fullExp); + return deferred.promise; }; - var eso0 = (expensiveChecks || isPossiblyDangerousMemberName(key0)) ? eso : identity; - var eso1 = (expensiveChecks || isPossiblyDangerousMemberName(key1)) ? eso : identity; - var eso2 = (expensiveChecks || isPossiblyDangerousMemberName(key2)) ? eso : identity; - var eso3 = (expensiveChecks || isPossiblyDangerousMemberName(key3)) ? eso : identity; - var eso4 = (expensiveChecks || isPossiblyDangerousMemberName(key4)) ? eso : identity; - return function cspSafeGetter(scope, locals) { - var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope; + $Q.defer = defer; + $Q.reject = reject; + $Q.when = when; + $Q.resolve = resolve; + $Q.all = all; - if (pathVal == null) return pathVal; - pathVal = eso0(pathVal[key0]); + return $Q; +} - if (!key1) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso1(pathVal[key1]); +function $$RAFProvider() { //rAF + this.$get = ['$window', '$timeout', function($window, $timeout) { + var requestAnimationFrame = $window.requestAnimationFrame || + $window.webkitRequestAnimationFrame; - if (!key2) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso2(pathVal[key2]); + var cancelAnimationFrame = $window.cancelAnimationFrame || + $window.webkitCancelAnimationFrame || + $window.webkitCancelRequestAnimationFrame; - if (!key3) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso3(pathVal[key3]); + var rafSupported = !!requestAnimationFrame; + var rafFn = rafSupported + ? function(fn) { + var id = requestAnimationFrame(fn); + return function() { + cancelAnimationFrame(id); + }; + } + : function(fn) { + var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 + return function() { + $timeout.cancel(timer); + }; + }; - if (!key4) return pathVal; - if (pathVal == null) return undefined; - pathVal = eso4(pathVal[key4]); + queueFn.supported = rafSupported; - return pathVal; - }; -} + var cancelLastRAF; + var taskCount = 0; + var taskQueue = []; + return queueFn; -function getterFnWithEnsureSafeObject(fn, fullExpression) { - return function(s, l) { - return fn(s, l, ensureSafeObject, fullExpression); - }; -} + function flush() { + for (var i = 0; i < taskQueue.length; i++) { + var task = taskQueue[i]; + if (task) { + taskQueue[i] = null; + task(); + } + } + taskCount = taskQueue.length = 0; + } -function getterFn(path, options, fullExp) { - var expensiveChecks = options.expensiveChecks; - var getterFnCache = (expensiveChecks ? getterFnCacheExpensive : getterFnCacheDefault); - var fn = getterFnCache[path]; - if (fn) return fn; + function queueFn(asyncFn) { + var index = taskQueue.length; + taskCount++; + taskQueue.push(asyncFn); - var pathKeys = path.split('.'), - pathKeysLength = pathKeys.length; + if (index === 0) { + cancelLastRAF = rafFn(flush); + } - // http://jsperf.com/angularjs-parse-getter/6 - if (options.csp) { - if (pathKeysLength < 6) { - fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp, expensiveChecks); - } else { - fn = function cspSafeGetter(scope, locals) { - var i = 0, val; - do { - val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], - pathKeys[i++], fullExp, expensiveChecks)(scope, locals); + return function cancelQueueFn() { + if (index >= 0) { + taskQueue[index] = null; + index = null; - locals = undefined; // clear after first iteration - scope = val; - } while (i < pathKeysLength); - return val; + if (--taskCount === 0 && cancelLastRAF) { + cancelLastRAF(); + cancelLastRAF = null; + taskQueue.length = 0; + } + } }; } - } else { - var code = ''; - if (expensiveChecks) { - code += 's = eso(s, fe);\nl = eso(l, fe);\n'; - } - var needsEnsureSafeObject = expensiveChecks; - forEach(pathKeys, function(key, index) { - ensureSafeMemberName(key, fullExp); - var lookupJs = (index - // we simply dereference 's' on any .dot notation - ? 's' - // but if we are first then we check locals first, and if so read it first - : '((l&&l.hasOwnProperty("' + key + '"))?l:s)') + '.' + key; - if (expensiveChecks || isPossiblyDangerousMemberName(key)) { - lookupJs = 'eso(' + lookupJs + ', fe)'; - needsEnsureSafeObject = true; - } - code += 'if(s == null) return undefined;\n' + - 's=' + lookupJs + ';\n'; - }); - code += 'return s;'; - - /* jshint -W054 */ - var evaledFnGetter = new Function('s', 'l', 'eso', 'fe', code); // s=scope, l=locals, eso=ensureSafeObject - /* jshint +W054 */ - evaledFnGetter.toString = valueFn(code); - if (needsEnsureSafeObject) { - evaledFnGetter = getterFnWithEnsureSafeObject(evaledFnGetter, fullExp); - } - fn = evaledFnGetter; - } - - fn.sharedGetter = true; - fn.assign = function(self, value, locals) { - return setter(self, locals, path, value, path); - }; - getterFnCache[path] = fn; - return fn; -} - -var objectValueOf = Object.prototype.valueOf; - -function getValueOf(value) { - return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); + }]; } -/////////////////////////////////// - /** - * @ngdoc service - * @name $parse - * @kind function - * - * @description - * - * Converts Angular {@link guide/expression expression} into a function. - * - * ```js - * var getter = $parse('user.name'); - * var setter = getter.assign; - * var context = {user:{name:'angular'}}; - * var locals = {user:{name:'local'}}; + * DESIGN NOTES * - * expect(getter(context)).toEqual('angular'); - * setter(context, 'newValue'); - * expect(context.user.name).toEqual('newValue'); - * expect(getter(context, locals)).toEqual('local'); - * ``` + * The design decisions behind the scope are heavily favored for speed and memory consumption. * + * The typical use of scope is to watch the expressions, which most of the time return the same + * value as last time so we optimize the operation. * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: + * Closures construction is expensive in terms of speed as well as memory: + * - No closures, instead use prototypical inheritance for API + * - Internal state needs to be stored on scope directly, which means that private state is + * exposed as $$____ properties * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. + * Loop operations are optimized by using while(count--) { ... } + * - this means that in order to keep the same order of execution as addition we have to add + * items to the array at the beginning (unshift) instead of at the end (push) * - * The returned function also has the following properties: - * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript - * literal. - * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript - * constant literals. - * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be - * set to a function to change its value on the given context. + * Child scopes are created and removed often + * - Using an array would be slow since inserts in middle are expensive so we use linked list * + * There are few watches then a lot of observers. This is why you don't want the observer to be + * implemented in the same way as watch. Watch requires return of initialization function which + * are expensive to construct. */ /** * @ngdoc provider - * @name $parseProvider - * + * @name $rootScopeProvider * @description - * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} - * service. + * + * Provider for the $rootScope service. */ -function $ParseProvider() { - var cacheDefault = createMap(); - var cacheExpensive = createMap(); - - - this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { - var $parseOptions = { - csp: $sniffer.csp, - expensiveChecks: false - }, - $parseOptionsExpensive = { - csp: $sniffer.csp, - expensiveChecks: true - }; +/** + * @ngdoc method + * @name $rootScopeProvider#digestTtl + * @description + * + * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and + * assuming that the model is unstable. + * + * The current default is 10 iterations. + * + * In complex applications it's possible that the dependencies between `$watch`s will result in + * several digest iterations. However if an application needs more than the default 10 digest + * iterations for its model to stabilize then you should investigate what is causing the model to + * continuously change during the digest. + * + * Increasing the TTL could have performance implications, so you should not change it without + * proper justification. + * + * @param {number} limit The number of digest iterations. + */ - function wrapSharedExpression(exp) { - var wrapped = exp; - if (exp.sharedGetter) { - wrapped = function $parseWrapper(self, locals) { - return exp(self, locals); - }; - wrapped.literal = exp.literal; - wrapped.constant = exp.constant; - wrapped.assign = exp.assign; - } +/** + * @ngdoc service + * @name $rootScope + * @description + * + * Every application has a single root {@link ng.$rootScope.Scope scope}. + * All other scopes are descendant scopes of the root scope. Scopes provide separation + * between the model and the view, via a mechanism for watching the model for changes. + * They also provide an event emission/broadcast and subscription facility. See the + * {@link guide/scope developer guide on scopes}. + */ +function $RootScopeProvider() { + var TTL = 10; + var $rootScopeMinErr = minErr('$rootScope'); + var lastDirtyWatch = null; + var applyAsyncId = null; - return wrapped; + this.digestTtl = function(value) { + if (arguments.length) { + TTL = value; } + return TTL; + }; - return function $parse(exp, interceptorFn, expensiveChecks) { - var parsedExpression, oneTime, cacheKey; - - switch (typeof exp) { - case 'string': - cacheKey = exp = exp.trim(); - - var cache = (expensiveChecks ? cacheExpensive : cacheDefault); - parsedExpression = cache[cacheKey]; - - if (!parsedExpression) { - if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { - oneTime = true; - exp = exp.substring(2); - } - - var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions; - var lexer = new Lexer(parseOptions); - var parser = new Parser(lexer, $filter, parseOptions); - parsedExpression = parser.parse(exp); - - if (parsedExpression.constant) { - parsedExpression.$$watchDelegate = constantWatchDelegate; - } else if (oneTime) { - //oneTime is not part of the exp passed to the Parser so we may have to - //wrap the parsedExpression before adding a $$watchDelegate - parsedExpression = wrapSharedExpression(parsedExpression); - parsedExpression.$$watchDelegate = parsedExpression.literal ? - oneTimeLiteralWatchDelegate : oneTimeWatchDelegate; - } else if (parsedExpression.inputs) { - parsedExpression.$$watchDelegate = inputsWatchDelegate; - } - - cache[cacheKey] = parsedExpression; - } - return addInterceptor(parsedExpression, interceptorFn); - - case 'function': - return addInterceptor(exp, interceptorFn); - - default: - return addInterceptor(noop, interceptorFn); - } - }; - - function collectExpressionInputs(inputs, list) { - for (var i = 0, ii = inputs.length; i < ii; i++) { - var input = inputs[i]; - if (!input.constant) { - if (input.inputs) { - collectExpressionInputs(input.inputs, list); - } else if (list.indexOf(input) === -1) { // TODO(perf) can we do better? - list.push(input); - } - } - } - - return list; + function createChildScopeClass(parent) { + function ChildScope() { + this.$$watchers = this.$$nextSibling = + this.$$childHead = this.$$childTail = null; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$id = nextUid(); + this.$$ChildScope = null; } + ChildScope.prototype = parent; + return ChildScope; + } - function expressionInputDirtyCheck(newValue, oldValueOfValue) { - - if (newValue == null || oldValueOfValue == null) { // null/undefined - return newValue === oldValueOfValue; - } - - if (typeof newValue === 'object') { + this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', + function($injector, $exceptionHandler, $parse, $browser) { - // attempt to convert the value to a primitive type - // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can - // be cheaply dirty-checked - newValue = getValueOf(newValue); + function destroyChildScope($event) { + $event.currentScope.$$destroyed = true; + } - if (typeof newValue === 'object') { - // objects/arrays are not supported - deep-watching them would be too expensive - return false; - } + /** + * @ngdoc type + * @name $rootScope.Scope + * + * @description + * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the + * {@link auto.$injector $injector}. Child scopes are created using the + * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when + * compiled HTML template is executed.) + * + * Here is a simple scope snippet to show how you can interact with the scope. + * ```html + * <file src="./test/ng/rootScopeSpec.js" tag="docs1" /> + * ``` + * + * # Inheritance + * A scope can inherit from a parent scope, as in this example: + * ```js + var parent = $rootScope; + var child = parent.$new(); - // fall-through to the primitive equality check - } + parent.salutation = "Hello"; + expect(child.salutation).toEqual('Hello'); - //Primitive or NaN - return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); + child.salutation = "Welcome"; + expect(child.salutation).toEqual('Welcome'); + expect(parent.salutation).toEqual('Hello'); + * ``` + * + * When interacting with `Scope` in tests, additional helper methods are available on the + * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional + * details. + * + * + * @param {Object.<string, function()>=} providers Map of service factory which need to be + * provided for the current scope. Defaults to {@link ng}. + * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should + * append/override services provided by `providers`. This is handy + * when unit-testing and having the need to override a default + * service. + * @returns {Object} Newly created scope. + * + */ + function Scope() { + this.$id = nextUid(); + this.$$phase = this.$parent = this.$$watchers = + this.$$nextSibling = this.$$prevSibling = + this.$$childHead = this.$$childTail = null; + this.$root = this; + this.$$destroyed = false; + this.$$listeners = {}; + this.$$listenerCount = {}; + this.$$watchersCount = 0; + this.$$isolateBindings = null; } - function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var inputExpressions = parsedExpression.$$inputs || - (parsedExpression.$$inputs = collectExpressionInputs(parsedExpression.inputs, [])); + /** + * @ngdoc property + * @name $rootScope.Scope#$id + * + * @description + * Unique scope ID (monotonically increasing) useful for debugging. + */ - var lastResult; + /** + * @ngdoc property + * @name $rootScope.Scope#$parent + * + * @description + * Reference to the parent scope. + */ - if (inputExpressions.length === 1) { - var oldInputValue = expressionInputDirtyCheck; // init to something unique so that equals check fails - inputExpressions = inputExpressions[0]; - return scope.$watch(function expressionInputWatch(scope) { - var newInputValue = inputExpressions(scope); - if (!expressionInputDirtyCheck(newInputValue, oldInputValue)) { - lastResult = parsedExpression(scope); - oldInputValue = newInputValue && getValueOf(newInputValue); - } - return lastResult; - }, listener, objectEquality); - } + /** + * @ngdoc property + * @name $rootScope.Scope#$root + * + * @description + * Reference to the root scope. + */ - var oldInputValueOfValues = []; - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails - } + Scope.prototype = { + constructor: Scope, + /** + * @ngdoc method + * @name $rootScope.Scope#$new + * @kind function + * + * @description + * Creates a new child {@link ng.$rootScope.Scope scope}. + * + * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event. + * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. + * + * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is + * desired for the scope and its child scopes to be permanently detached from the parent and + * thus stop participating in model change detection and listener notification by invoking. + * + * @param {boolean} isolate If true, then the scope does not prototypically inherit from the + * parent scope. The scope is isolated, as it can not see parent scope properties. + * When creating widgets, it is useful for the widget to not accidentally read parent + * state. + * + * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent` + * of the newly created scope. Defaults to `this` scope if not provided. + * This is used when creating a transclude scope to correctly place it + * in the scope hierarchy while maintaining the correct prototypical + * inheritance. + * + * @returns {Object} The newly created child scope. + * + */ + $new: function(isolate, parent) { + var child; - return scope.$watch(function expressionInputsWatch(scope) { - var changed = false; + parent = parent || this; - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - var newInputValue = inputExpressions[i](scope); - if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) { - oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); + if (isolate) { + child = new Scope(); + child.$root = this.$root; + } else { + // Only create a child scope class if somebody asks for one, + // but cache it to allow the VM to optimize lookups. + if (!this.$$ChildScope) { + this.$$ChildScope = createChildScopeClass(this); } + child = new this.$$ChildScope(); } - - if (changed) { - lastResult = parsedExpression(scope); + child.$parent = parent; + child.$$prevSibling = parent.$$childTail; + if (parent.$$childHead) { + parent.$$childTail.$$nextSibling = child; + parent.$$childTail = child; + } else { + parent.$$childHead = parent.$$childTail = child; } - return lastResult; - }, listener, objectEquality); - } - - function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch, lastValue; - return unwatch = scope.$watch(function oneTimeWatch(scope) { - return parsedExpression(scope); - }, function oneTimeListener(value, old, scope) { - lastValue = value; - if (isFunction(listener)) { - listener.apply(this, arguments); - } - if (isDefined(value)) { - scope.$$postDigest(function() { - if (isDefined(lastValue)) { - unwatch(); - } - }); - } - }, objectEquality); - } + // When the new scope is not isolated or we inherit from `this`, and + // the parent scope is destroyed, the property `$$destroyed` is inherited + // prototypically. In all other cases, this property needs to be set + // when the parent scope is destroyed. + // The listener needs to be added after the parent is set + if (isolate || parent != this) child.$on('$destroy', destroyChildScope); - function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch, lastValue; - return unwatch = scope.$watch(function oneTimeWatch(scope) { - return parsedExpression(scope); - }, function oneTimeListener(value, old, scope) { - lastValue = value; - if (isFunction(listener)) { - listener.call(this, value, old, scope); - } - if (isAllDefined(value)) { - scope.$$postDigest(function() { - if (isAllDefined(lastValue)) unwatch(); - }); - } - }, objectEquality); + return child; + }, - function isAllDefined(value) { - var allDefined = true; - forEach(value, function(val) { - if (!isDefined(val)) allDefined = false; - }); - return allDefined; - } - } + /** + * @ngdoc method + * @name $rootScope.Scope#$watch + * @kind function + * + * @description + * Registers a `listener` callback to be executed whenever the `watchExpression` changes. + * + * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest + * $digest()} and should return the value that will be watched. (Since + * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the + * `watchExpression` can execute multiple times per + * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) + * - The `listener` is called only when the value from the current `watchExpression` and the + * previous call to `watchExpression` are not equal (with the exception of the initial run, + * see below). Inequality is determined according to reference inequality, + * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) + * via the `!==` Javascript operator, unless `objectEquality == true` + * (see next point) + * - When `objectEquality == true`, inequality of the `watchExpression` is determined + * according to the {@link angular.equals} function. To save the value of the object for + * later comparison, the {@link angular.copy} function is used. This therefore means that + * watching complex objects will have adverse memory and performance implications. + * - The watch `listener` may change the model, which may trigger other `listener`s to fire. + * This is achieved by rerunning the watchers until no changes are detected. The rerun + * iteration limit is 10 to prevent an infinite loop deadlock. + * + * + * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, + * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` + * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a + * change is detected, be prepared for multiple calls to your listener.) + * + * After a watcher is registered with the scope, the `listener` fn is called asynchronously + * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the + * watcher. In rare cases, this is undesirable because the listener is called when the result + * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you + * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the + * listener was called due to initialization. + * + * + * + * # Example + * ```js + // let's assume that scope was dependency injected as the $rootScope + var scope = $rootScope; + scope.name = 'misko'; + scope.counter = 0; - function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch; - return unwatch = scope.$watch(function constantWatch(scope) { - return parsedExpression(scope); - }, function constantListener(value, old, scope) { - if (isFunction(listener)) { - listener.apply(this, arguments); - } - unwatch(); - }, objectEquality); - } + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); - function addInterceptor(parsedExpression, interceptorFn) { - if (!interceptorFn) return parsedExpression; - var watchDelegate = parsedExpression.$$watchDelegate; + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); - var regularWatch = - watchDelegate !== oneTimeLiteralWatchDelegate && - watchDelegate !== oneTimeWatchDelegate; + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); - var fn = regularWatch ? function regularInterceptedExpression(scope, locals) { - var value = parsedExpression(scope, locals); - return interceptorFn(value, scope, locals); - } : function oneTimeInterceptedExpression(scope, locals) { - var value = parsedExpression(scope, locals); - var result = interceptorFn(value, scope, locals); - // we only return the interceptor's result if the - // initial value is defined (for bind-once) - return isDefined(value) ? result : value; - }; + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); - // Propagate $$watchDelegates other then inputsWatchDelegate - if (parsedExpression.$$watchDelegate && - parsedExpression.$$watchDelegate !== inputsWatchDelegate) { - fn.$$watchDelegate = parsedExpression.$$watchDelegate; - } else if (!interceptorFn.$stateful) { - // If there is an interceptor, but no watchDelegate then treat the interceptor like - // we treat filters - it is assumed to be a pure function unless flagged with $stateful - fn.$$watchDelegate = inputsWatchDelegate; - fn.inputs = [parsedExpression]; - } - return fn; - } - }]; -} -/** - * @ngdoc service - * @name $q - * @requires $rootScope - * - * @description - * A service that helps you run functions asynchronously, and use their return values (or exceptions) - * when they are done processing. - * - * This is an implementation of promises/deferred objects inspired by - * [Kris Kowal's Q](https://github.com/kriskowal/q). - * - * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred - * implementations, and the other which resembles ES6 promises to some degree. - * - * # $q constructor - * - * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` - * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony, - * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). - * - * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are - * available yet. - * - * It can be used like so: - * - * ```js - * // for the purpose of this example let's assume that variables `$q` and `okToGreet` - * // are available in the current lexical scope (they could have been injected or passed in). - * - * function asyncGreet(name) { - * // perform some asynchronous operation, resolve or reject the promise when appropriate. - * return $q(function(resolve, reject) { - * setTimeout(function() { - * if (okToGreet(name)) { - * resolve('Hello, ' + name + '!'); - * } else { - * reject('Greeting ' + name + ' is not allowed.'); - * } - * }, 1000); - * }); - * } - * - * var promise = asyncGreet('Robin Hood'); - * promise.then(function(greeting) { - * alert('Success: ' + greeting); - * }, function(reason) { - * alert('Failed: ' + reason); - * }); - * ``` - * - * Note: progress/notify callbacks are not currently supported via the ES6-style interface. - * - * However, the more traditional CommonJS-style usage is still available, and documented below. - * - * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an - * interface for interacting with an object that represents the result of an action that is - * performed asynchronously, and may or may not be finished at any given point in time. - * - * From the perspective of dealing with error handling, deferred and promise APIs are to - * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. - * - * ```js - * // for the purpose of this example let's assume that variables `$q` and `okToGreet` - * // are available in the current lexical scope (they could have been injected or passed in). - * - * function asyncGreet(name) { - * var deferred = $q.defer(); - * - * setTimeout(function() { - * deferred.notify('About to greet ' + name + '.'); - * - * if (okToGreet(name)) { - * deferred.resolve('Hello, ' + name + '!'); - * } else { - * deferred.reject('Greeting ' + name + ' is not allowed.'); - * } - * }, 1000); - * - * return deferred.promise; - * } - * - * var promise = asyncGreet('Robin Hood'); - * promise.then(function(greeting) { - * alert('Success: ' + greeting); - * }, function(reason) { - * alert('Failed: ' + reason); - * }, function(update) { - * alert('Got notification: ' + update); - * }); - * ``` - * - * At first it might not be obvious why this extra complexity is worth the trouble. The payoff - * comes in the way of guarantees that promise and deferred APIs make, see - * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. - * - * Additionally the promise api allows for composition that is very hard to do with the - * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. - * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the - * section on serial or parallel joining of promises. - * - * # The Deferred API - * - * A new instance of deferred is constructed by calling `$q.defer()`. - * - * The purpose of the deferred object is to expose the associated Promise instance as well as APIs - * that can be used for signaling the successful or unsuccessful completion, as well as the status - * of the task. - * - * **Methods** - * - * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection - * constructed via `$q.reject`, the promise will be rejected instead. - * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to - * resolving it with a rejection constructed via `$q.reject`. - * - `notify(value)` - provides updates on the status of the promise's execution. This may be called - * multiple times before the promise is either resolved or rejected. - * - * **Properties** - * - * - promise – `{Promise}` – promise object associated with this deferred. - * - * - * # The Promise API - * - * A new promise instance is created when a deferred instance is created and can be retrieved by - * calling `deferred.promise`. - * - * The purpose of the promise object is to allow for interested parties to get access to the result - * of the deferred task when it completes. - * - * **Methods** - * - * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or - * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously - * as soon as the result is available. The callbacks are called with a single argument: the result - * or rejection reason. Additionally, the notify callback may be called zero or more times to - * provide a progress indication, before the promise is resolved or rejected. - * - * This method *returns a new promise* which is resolved or rejected via the return value of the - * `successCallback`, `errorCallback`. It also notifies via the return value of the - * `notifyCallback` method. The promise cannot be resolved or rejected from the notifyCallback - * method. - * - * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` - * - * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, - * but to do so without modifying the final value. This is useful to release resources or do some - * clean-up that needs to be done whether the promise was rejected or resolved. See the [full - * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for - * more information. - * - * # Chaining promises - * - * Because calling the `then` method of a promise returns a new derived promise, it is easily - * possible to create a chain of promises: - * - * ```js - * promiseB = promiseA.then(function(result) { - * return result + 1; - * }); - * - * // promiseB will be resolved immediately after promiseA is resolved and its value - * // will be the result of promiseA incremented by 1 - * ``` - * - * It is possible to create chains of any length and since a promise can be resolved with another - * promise (which will defer its resolution further), it is possible to pause/defer resolution of - * the promises at any point in the chain. This makes it possible to implement powerful APIs like - * $http's response interceptors. - * - * - * # Differences between Kris Kowal's Q and $q - * - * There are two main differences: - * - * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation - * mechanism in angular, which means faster propagation of resolution or rejection into your - * models and avoiding unnecessary browser repaints, which would result in flickering UI. - * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains - * all the important functionality needed for common async tasks. - * - * # Testing - * - * ```js - * it('should simulate promise', inject(function($q, $rootScope) { - * var deferred = $q.defer(); - * var promise = deferred.promise; - * var resolvedValue; - * - * promise.then(function(value) { resolvedValue = value; }); - * expect(resolvedValue).toBeUndefined(); - * - * // Simulate resolving of promise - * deferred.resolve(123); - * // Note that the 'then' function does not get called synchronously. - * // This is because we want the promise API to always be async, whether or not - * // it got called synchronously or asynchronously. - * expect(resolvedValue).toBeUndefined(); - * - * // Propagate promise resolution to 'then' functions using $apply(). - * $rootScope.$apply(); - * expect(resolvedValue).toEqual(123); - * })); - * ``` - * - * @param {function(function, function)} resolver Function which is responsible for resolving or - * rejecting the newly created promise. The first parameter is a function which resolves the - * promise, the second parameter is a function which rejects the promise. - * - * @returns {Promise} The newly created promise. - */ -function $QProvider() { + // Using a function as a watchExpression + var food; + scope.foodCounter = 0; + expect(scope.foodCounter).toEqual(0); + scope.$watch( + // This function returns the value being watched. It is called for each turn of the $digest loop + function() { return food; }, + // This is the change listener, called when the value returned from the above function changes + function(newValue, oldValue) { + if ( newValue !== oldValue ) { + // Only increment the counter if the value changed + scope.foodCounter = scope.foodCounter + 1; + } + } + ); + // No digest has been run so the counter will be zero + expect(scope.foodCounter).toEqual(0); - this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { - return qFactory(function(callback) { - $rootScope.$evalAsync(callback); - }, $exceptionHandler); - }]; -} + // Run the digest but since food has not changed count will still be zero + scope.$digest(); + expect(scope.foodCounter).toEqual(0); -function $$QProvider() { - this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { - return qFactory(function(callback) { - $browser.defer(callback); - }, $exceptionHandler); - }]; -} + // Update food and run digest. Now the counter will increment + food = 'cheeseburger'; + scope.$digest(); + expect(scope.foodCounter).toEqual(1); -/** - * Constructs a promise manager. - * - * @param {function(function)} nextTick Function for executing functions in the next turn. - * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for - * debugging purposes. - * @returns {object} Promise manager. - */ -function qFactory(nextTick, exceptionHandler) { - var $qMinErr = minErr('$q', TypeError); - function callOnce(self, resolveFn, rejectFn) { - var called = false; - function wrap(fn) { - return function(value) { - if (called) return; - called = true; - fn.call(self, value); - }; - } + * ``` + * + * + * + * @param {(function()|string)} watchExpression Expression that is evaluated on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers + * a call to the `listener`. + * + * - `string`: Evaluated as {@link guide/expression expression} + * - `function(scope)`: called with current `scope` as a parameter. + * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value + * of `watchExpression` changes. + * + * - `newVal` contains the current value of the `watchExpression` + * - `oldVal` contains the previous value of the `watchExpression` + * - `scope` refers to the current scope + * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of + * comparing for reference equality. + * @returns {function()} Returns a deregistration function for this listener. + */ + $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) { + var get = $parse(watchExp); - return [wrap(resolveFn), wrap(rejectFn)]; - } + if (get.$$watchDelegate) { + return get.$$watchDelegate(this, listener, objectEquality, get, watchExp); + } + var scope = this, + array = scope.$$watchers, + watcher = { + fn: listener, + last: initWatchVal, + get: get, + exp: prettyPrintExpression || watchExp, + eq: !!objectEquality + }; - /** - * @ngdoc method - * @name ng.$q#defer - * @kind function - * - * @description - * Creates a `Deferred` object which represents a task which will finish in the future. - * - * @returns {Deferred} Returns a new instance of deferred. - */ - var defer = function() { - return new Deferred(); - }; + lastDirtyWatch = null; - function Promise() { - this.$$state = { status: 0 }; - } + if (!isFunction(listener)) { + watcher.fn = noop; + } - Promise.prototype = { - then: function(onFulfilled, onRejected, progressBack) { - var result = new Deferred(); + if (!array) { + array = scope.$$watchers = []; + } + // we use unshift since we use a while loop in $digest for speed. + // the while loop reads in reverse order. + array.unshift(watcher); + incrementWatchersCount(this, 1); - this.$$state.pending = this.$$state.pending || []; - this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); - if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); + return function deregisterWatch() { + if (arrayRemove(array, watcher) >= 0) { + incrementWatchersCount(scope, -1); + } + lastDirtyWatch = null; + }; + }, - return result.promise; - }, + /** + * @ngdoc method + * @name $rootScope.Scope#$watchGroup + * @kind function + * + * @description + * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`. + * If any one expression in the collection changes the `listener` is executed. + * + * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every + * call to $digest() to see if any items changes. + * - The `listener` is called whenever any expression in the `watchExpressions` array changes. + * + * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually + * watched using {@link ng.$rootScope.Scope#$watch $watch()} + * + * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any + * expression in `watchExpressions` changes + * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching + * those of `watchExpression` + * The `scope` refers to the current scope. + * @returns {function()} Returns a de-registration function for all listeners. + */ + $watchGroup: function(watchExpressions, listener) { + var oldValues = new Array(watchExpressions.length); + var newValues = new Array(watchExpressions.length); + var deregisterFns = []; + var self = this; + var changeReactionScheduled = false; + var firstRun = true; - "catch": function(callback) { - return this.then(null, callback); - }, + if (!watchExpressions.length) { + // No expressions means we call the listener ASAP + var shouldCall = true; + self.$evalAsync(function() { + if (shouldCall) listener(newValues, newValues, self); + }); + return function deregisterWatchGroup() { + shouldCall = false; + }; + } - "finally": function(callback, progressBack) { - return this.then(function(value) { - return handleCallback(value, true, callback); - }, function(error) { - return handleCallback(error, false, callback); - }, progressBack); - } - }; + if (watchExpressions.length === 1) { + // Special case size of one + return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { + newValues[0] = value; + oldValues[0] = oldValue; + listener(newValues, (value === oldValue) ? newValues : oldValues, scope); + }); + } - //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native - function simpleBind(context, fn) { - return function(value) { - fn.call(context, value); - }; - } + forEach(watchExpressions, function(expr, i) { + var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) { + newValues[i] = value; + oldValues[i] = oldValue; + if (!changeReactionScheduled) { + changeReactionScheduled = true; + self.$evalAsync(watchGroupAction); + } + }); + deregisterFns.push(unwatchFn); + }); - function processQueue(state) { - var fn, promise, pending; + function watchGroupAction() { + changeReactionScheduled = false; - pending = state.pending; - state.processScheduled = false; - state.pending = undefined; - for (var i = 0, ii = pending.length; i < ii; ++i) { - promise = pending[i][0]; - fn = pending[i][state.status]; - try { - if (isFunction(fn)) { - promise.resolve(fn(state.value)); - } else if (state.status === 1) { - promise.resolve(state.value); - } else { - promise.reject(state.value); + if (firstRun) { + firstRun = false; + listener(newValues, newValues, self); + } else { + listener(newValues, oldValues, self); + } } - } catch (e) { - promise.reject(e); - exceptionHandler(e); - } - } - } - function scheduleProcessQueue(state) { - if (state.processScheduled || !state.pending) return; - state.processScheduled = true; - nextTick(function() { processQueue(state); }); - } + return function deregisterWatchGroup() { + while (deregisterFns.length) { + deregisterFns.shift()(); + } + }; + }, - function Deferred() { - this.promise = new Promise(); - //Necessary to support unbound execution :/ - this.resolve = simpleBind(this, this.resolve); - this.reject = simpleBind(this, this.reject); - this.notify = simpleBind(this, this.notify); - } - Deferred.prototype = { - resolve: function(val) { - if (this.promise.$$state.status) return; - if (val === this.promise) { - this.$$reject($qMinErr( - 'qcycle', - "Expected promise to be resolved with value other than itself '{0}'", - val)); - } else { - this.$$resolve(val); - } + /** + * @ngdoc method + * @name $rootScope.Scope#$watchCollection + * @kind function + * + * @description + * Shallow watches the properties of an object and fires whenever any of the properties change + * (for arrays, this implies watching the array items; for object maps, this implies watching + * the properties). If a change is detected, the `listener` callback is fired. + * + * - The `obj` collection is observed via standard $watch operation and is examined on every + * call to $digest() to see if any items have been added, removed, or moved. + * - The `listener` is called whenever anything within the `obj` has changed. Examples include + * adding, removing, and moving items belonging to an object or array. + * + * + * # Example + * ```js + $scope.names = ['igor', 'matias', 'misko', 'james']; + $scope.dataCount = 4; - }, + $scope.$watchCollection('names', function(newNames, oldNames) { + $scope.dataCount = newNames.length; + }); - $$resolve: function(val) { - var then, fns; + expect($scope.dataCount).toEqual(4); + $scope.$digest(); - fns = callOnce(this, this.$$resolve, this.$$reject); - try { - if ((isObject(val) || isFunction(val))) then = val && val.then; - if (isFunction(then)) { - this.promise.$$state.status = -1; - then.call(val, fns[0], fns[1], this.notify); - } else { - this.promise.$$state.value = val; - this.promise.$$state.status = 1; - scheduleProcessQueue(this.promise.$$state); - } - } catch (e) { - fns[1](e); - exceptionHandler(e); - } - }, + //still at 4 ... no changes + expect($scope.dataCount).toEqual(4); - reject: function(reason) { - if (this.promise.$$state.status) return; - this.$$reject(reason); - }, + $scope.names.pop(); + $scope.$digest(); - $$reject: function(reason) { - this.promise.$$state.value = reason; - this.promise.$$state.status = 2; - scheduleProcessQueue(this.promise.$$state); - }, + //now there's been a change + expect($scope.dataCount).toEqual(3); + * ``` + * + * + * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The + * expression value should evaluate to an object or an array which is observed on each + * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the + * collection will trigger a call to the `listener`. + * + * @param {function(newCollection, oldCollection, scope)} listener a callback function called + * when a change is detected. + * - The `newCollection` object is the newly modified data obtained from the `obj` expression + * - The `oldCollection` object is a copy of the former collection data. + * Due to performance considerations, the`oldCollection` value is computed only if the + * `listener` function declares two or more arguments. + * - The `scope` argument refers to the current scope. + * + * @returns {function()} Returns a de-registration function for this listener. When the + * de-registration function is executed, the internal watch operation is terminated. + */ + $watchCollection: function(obj, listener) { + $watchCollectionInterceptor.$stateful = true; - notify: function(progress) { - var callbacks = this.promise.$$state.pending; + var self = this; + // the current value, updated on each dirty-check run + var newValue; + // a shallow copy of the newValue from the last dirty-check run, + // updated to match newValue during dirty-check run + var oldValue; + // a shallow copy of the newValue from when the last change happened + var veryOldValue; + // only track veryOldValue if the listener is asking for it + var trackVeryOldValue = (listener.length > 1); + var changeDetected = 0; + var changeDetector = $parse(obj, $watchCollectionInterceptor); + var internalArray = []; + var internalObject = {}; + var initRun = true; + var oldLength = 0; - if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) { - nextTick(function() { - var callback, result; - for (var i = 0, ii = callbacks.length; i < ii; i++) { - result = callbacks[i][0]; - callback = callbacks[i][3]; - try { - result.notify(isFunction(callback) ? callback(progress) : progress); - } catch (e) { - exceptionHandler(e); + function $watchCollectionInterceptor(_value) { + newValue = _value; + var newLength, key, bothNaN, newItem, oldItem; + + // If the new value is undefined, then return undefined as the watch may be a one-time watch + if (isUndefined(newValue)) return; + + if (!isObject(newValue)) { // if primitive + if (oldValue !== newValue) { + oldValue = newValue; + changeDetected++; + } + } else if (isArrayLike(newValue)) { + if (oldValue !== internalArray) { + // we are transitioning from something which was not an array into array. + oldValue = internalArray; + oldLength = oldValue.length = 0; + changeDetected++; } - } - }); - } - } - }; - /** - * @ngdoc method - * @name $q#reject - * @kind function - * - * @description - * Creates a promise that is resolved as rejected with the specified `reason`. This api should be - * used to forward rejection in a chain of promises. If you are dealing with the last promise in - * a promise chain, you don't need to worry about it. - * - * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of - * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via - * a promise error callback and you want to forward the error to the promise derived from the - * current promise, you have to "rethrow" the error by returning a rejection constructed via - * `reject`. - * - * ```js - * promiseB = promiseA.then(function(result) { - * // success: do something and resolve promiseB - * // with the old or a new result - * return result; - * }, function(reason) { - * // error: handle the error if possible and - * // resolve promiseB with newPromiseOrValue, - * // otherwise forward the rejection to promiseB - * if (canHandle(reason)) { - * // handle the error and recover - * return newPromiseOrValue; - * } - * return $q.reject(reason); - * }); - * ``` - * - * @param {*} reason Constant, message, exception or an object representing the rejection reason. - * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. - */ - var reject = function(reason) { - var result = new Deferred(); - result.reject(reason); - return result.promise; - }; + newLength = newValue.length; - var makePromise = function makePromise(value, resolved) { - var result = new Deferred(); - if (resolved) { - result.resolve(value); - } else { - result.reject(value); - } - return result.promise; - }; + if (oldLength !== newLength) { + // if lengths do not match we need to trigger change notification + changeDetected++; + oldValue.length = oldLength = newLength; + } + // copy the items to oldValue and look for changes. + for (var i = 0; i < newLength; i++) { + oldItem = oldValue[i]; + newItem = newValue[i]; - var handleCallback = function handleCallback(value, isResolved, callback) { - var callbackOutput = null; - try { - if (isFunction(callback)) callbackOutput = callback(); - } catch (e) { - return makePromise(e, false); - } - if (isPromiseLike(callbackOutput)) { - return callbackOutput.then(function() { - return makePromise(value, isResolved); - }, function(error) { - return makePromise(error, false); - }); - } else { - return makePromise(value, isResolved); - } - }; + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[i] = newItem; + } + } + } else { + if (oldValue !== internalObject) { + // we are transitioning from something which was not an object into object. + oldValue = internalObject = {}; + oldLength = 0; + changeDetected++; + } + // copy the items to oldValue and look for changes. + newLength = 0; + for (key in newValue) { + if (newValue.hasOwnProperty(key)) { + newLength++; + newItem = newValue[key]; + oldItem = oldValue[key]; - /** - * @ngdoc method - * @name $q#when - * @kind function - * - * @description - * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. - * This is useful when you are dealing with an object that might or might not be a promise, or if - * the promise comes from a source that can't be trusted. - * - * @param {*} value Value or a promise - * @returns {Promise} Returns a promise of the passed value or promise - */ + if (key in oldValue) { + bothNaN = (oldItem !== oldItem) && (newItem !== newItem); + if (!bothNaN && (oldItem !== newItem)) { + changeDetected++; + oldValue[key] = newItem; + } + } else { + oldLength++; + oldValue[key] = newItem; + changeDetected++; + } + } + } + if (oldLength > newLength) { + // we used to have more keys, need to find them and destroy them. + changeDetected++; + for (key in oldValue) { + if (!newValue.hasOwnProperty(key)) { + oldLength--; + delete oldValue[key]; + } + } + } + } + return changeDetected; + } + function $watchCollectionAction() { + if (initRun) { + initRun = false; + listener(newValue, newValue, self); + } else { + listener(newValue, veryOldValue, self); + } - var when = function(value, callback, errback, progressBack) { - var result = new Deferred(); - result.resolve(value); - return result.promise.then(callback, errback, progressBack); - }; + // make a copy for the next time a collection is changed + if (trackVeryOldValue) { + if (!isObject(newValue)) { + //primitive + veryOldValue = newValue; + } else if (isArrayLike(newValue)) { + veryOldValue = new Array(newValue.length); + for (var i = 0; i < newValue.length; i++) { + veryOldValue[i] = newValue[i]; + } + } else { // if object + veryOldValue = {}; + for (var key in newValue) { + if (hasOwnProperty.call(newValue, key)) { + veryOldValue[key] = newValue[key]; + } + } + } + } + } - /** - * @ngdoc method - * @name $q#all - * @kind function - * - * @description - * Combines multiple promises into a single promise that is resolved when all of the input - * promises are resolved. - * - * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises. - * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, - * each value corresponding to the promise at the same index/key in the `promises` array/hash. - * If any of the promises is resolved with a rejection, this resulting promise will be rejected - * with the same rejection value. - */ + return this.$watch(changeDetector, $watchCollectionAction); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$digest + * @kind function + * + * @description + * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and + * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change + * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} + * until no more listeners are firing. This means that it is possible to get into an infinite + * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of + * iterations exceeds 10. + * + * Usually, you don't call `$digest()` directly in + * {@link ng.directive:ngController controllers} or in + * {@link ng.$compileProvider#directive directives}. + * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within + * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`. + * + * If you want to be notified whenever `$digest()` is called, + * you can register a `watchExpression` function with + * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`. + * + * In unit tests, you may need to call `$digest()` to simulate the scope life cycle. + * + * # Example + * ```js + var scope = ...; + scope.name = 'misko'; + scope.counter = 0; - function all(promises) { - var deferred = new Deferred(), - counter = 0, - results = isArray(promises) ? [] : {}; + expect(scope.counter).toEqual(0); + scope.$watch('name', function(newValue, oldValue) { + scope.counter = scope.counter + 1; + }); + expect(scope.counter).toEqual(0); - forEach(promises, function(promise, key) { - counter++; - when(promise).then(function(value) { - if (results.hasOwnProperty(key)) return; - results[key] = value; - if (!(--counter)) deferred.resolve(results); - }, function(reason) { - if (results.hasOwnProperty(key)) return; - deferred.reject(reason); - }); - }); + scope.$digest(); + // the listener is always called during the first $digest loop after it was registered + expect(scope.counter).toEqual(1); - if (counter === 0) { - deferred.resolve(results); - } + scope.$digest(); + // but now it will not be called unless the value changes + expect(scope.counter).toEqual(1); - return deferred.promise; - } + scope.name = 'adam'; + scope.$digest(); + expect(scope.counter).toEqual(2); + * ``` + * + */ + $digest: function() { + var watch, value, last, + watchers, + length, + dirty, ttl = TTL, + next, current, target = this, + watchLog = [], + logIdx, logMsg, asyncTask; - var $Q = function Q(resolver) { - if (!isFunction(resolver)) { - throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver); - } + beginPhase('$digest'); + // Check for changes to browser url that happened in sync before the call to $digest + $browser.$$checkUrlChange(); - if (!(this instanceof Q)) { - // More useful when $Q is the Promise itself. - return new Q(resolver); - } + if (this === $rootScope && applyAsyncId !== null) { + // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then + // cancel the scheduled $apply and flush the queue of expressions to be evaluated. + $browser.defer.cancel(applyAsyncId); + flushApplyAsync(); + } - var deferred = new Deferred(); + lastDirtyWatch = null; - function resolveFn(value) { - deferred.resolve(value); - } + do { // "while dirty" loop + dirty = false; + current = target; - function rejectFn(reason) { - deferred.reject(reason); - } + while (asyncQueue.length) { + try { + asyncTask = asyncQueue.shift(); + asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); + } catch (e) { + $exceptionHandler(e); + } + lastDirtyWatch = null; + } - resolver(resolveFn, rejectFn); + traverseScopesLoop: + do { // "traverse the scopes" loop + if ((watchers = current.$$watchers)) { + // process our watches + length = watchers.length; + while (length--) { + try { + watch = watchers[length]; + // Most common watches are on primitives, in which case we can short + // circuit it with === operator, only when === fails do we use .equals + if (watch) { + if ((value = watch.get(current)) !== (last = watch.last) && + !(watch.eq + ? equals(value, last) + : (typeof value === 'number' && typeof last === 'number' + && isNaN(value) && isNaN(last)))) { + dirty = true; + lastDirtyWatch = watch; + watch.last = watch.eq ? copy(value, null) : value; + watch.fn(value, ((last === initWatchVal) ? value : last), current); + if (ttl < 5) { + logIdx = 4 - ttl; + if (!watchLog[logIdx]) watchLog[logIdx] = []; + watchLog[logIdx].push({ + msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp, + newVal: value, + oldVal: last + }); + } + } else if (watch === lastDirtyWatch) { + // If the most recently dirty watcher is now clean, short circuit since the remaining watchers + // have already been tested. + dirty = false; + break traverseScopesLoop; + } + } + } catch (e) { + $exceptionHandler(e); + } + } + } - return deferred.promise; - }; + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $broadcast + if (!(next = ((current.$$watchersCount && current.$$childHead) || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } while ((current = next)); - $Q.defer = defer; - $Q.reject = reject; - $Q.when = when; - $Q.all = all; + // `break traverseScopesLoop;` takes us to here - return $Q; -} + if ((dirty || asyncQueue.length) && !(ttl--)) { + clearPhase(); + throw $rootScopeMinErr('infdig', + '{0} $digest() iterations reached. Aborting!\n' + + 'Watchers fired in the last 5 iterations: {1}', + TTL, watchLog); + } -function $$RAFProvider() { //rAF - this.$get = ['$window', '$timeout', function($window, $timeout) { - var requestAnimationFrame = $window.requestAnimationFrame || - $window.webkitRequestAnimationFrame; + } while (dirty || asyncQueue.length); - var cancelAnimationFrame = $window.cancelAnimationFrame || - $window.webkitCancelAnimationFrame || - $window.webkitCancelRequestAnimationFrame; + clearPhase(); - var rafSupported = !!requestAnimationFrame; - var raf = rafSupported - ? function(fn) { - var id = requestAnimationFrame(fn); - return function() { - cancelAnimationFrame(id); - }; + while (postDigestQueue.length) { + try { + postDigestQueue.shift()(); + } catch (e) { + $exceptionHandler(e); + } } - : function(fn) { - var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 - return function() { - $timeout.cancel(timer); - }; - }; + }, - raf.supported = rafSupported; - return raf; - }]; -} + /** + * @ngdoc event + * @name $rootScope.Scope#$destroy + * @eventType broadcast on scope being destroyed + * + * @description + * Broadcasted when a scope and its children are being destroyed. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ -/** - * DESIGN NOTES - * - * The design decisions behind the scope are heavily favored for speed and memory consumption. - * - * The typical use of scope is to watch the expressions, which most of the time return the same - * value as last time so we optimize the operation. - * - * Closures construction is expensive in terms of speed as well as memory: - * - No closures, instead use prototypical inheritance for API - * - Internal state needs to be stored on scope directly, which means that private state is - * exposed as $$____ properties - * - * Loop operations are optimized by using while(count--) { ... } - * - this means that in order to keep the same order of execution as addition we have to add - * items to the array at the beginning (unshift) instead of at the end (push) - * - * Child scopes are created and removed often - * - Using an array would be slow since inserts in middle are expensive so we use linked list - * - * There are few watches then a lot of observers. This is why you don't want the observer to be - * implemented in the same way as watch. Watch requires return of initialization function which - * are expensive to construct. - */ + /** + * @ngdoc method + * @name $rootScope.Scope#$destroy + * @kind function + * + * @description + * Removes the current scope (and all of its children) from the parent scope. Removal implies + * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer + * propagate to the current scope and its children. Removal also implies that the current + * scope is eligible for garbage collection. + * + * The `$destroy()` is usually used by directives such as + * {@link ng.directive:ngRepeat ngRepeat} for managing the + * unrolling of the loop. + * + * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. + * Application code can register a `$destroy` event handler that will give it a chance to + * perform any necessary cleanup. + * + * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to + * clean up DOM bindings before an element is removed from the DOM. + */ + $destroy: function() { + // We can't destroy a scope that has been already destroyed. + if (this.$$destroyed) return; + var parent = this.$parent; + this.$broadcast('$destroy'); + this.$$destroyed = true; -/** - * @ngdoc provider - * @name $rootScopeProvider - * @description - * - * Provider for the $rootScope service. - */ + if (this === $rootScope) { + //Remove handlers attached to window when $rootScope is removed + $browser.$$applicationDestroyed(); + } -/** - * @ngdoc method - * @name $rootScopeProvider#digestTtl - * @description - * - * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and - * assuming that the model is unstable. - * - * The current default is 10 iterations. - * - * In complex applications it's possible that the dependencies between `$watch`s will result in - * several digest iterations. However if an application needs more than the default 10 digest - * iterations for its model to stabilize then you should investigate what is causing the model to - * continuously change during the digest. - * - * Increasing the TTL could have performance implications, so you should not change it without - * proper justification. - * - * @param {number} limit The number of digest iterations. - */ + incrementWatchersCount(this, -this.$$watchersCount); + for (var eventName in this.$$listenerCount) { + decrementListenerCount(this, this.$$listenerCount[eventName], eventName); + } + // sever all the references to parent scopes (after this cleanup, the current scope should + // not be retained by any of our references and should be eligible for garbage collection) + if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; + if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; + if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; + if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; -/** - * @ngdoc service - * @name $rootScope - * @description - * - * Every application has a single root {@link ng.$rootScope.Scope scope}. - * All other scopes are descendant scopes of the root scope. Scopes provide separation - * between the model and the view, via a mechanism for watching the model for changes. - * They also provide an event emission/broadcast and subscription facility. See the - * {@link guide/scope developer guide on scopes}. - */ -function $RootScopeProvider() { - var TTL = 10; - var $rootScopeMinErr = minErr('$rootScope'); - var lastDirtyWatch = null; - var applyAsyncId = null; + // Disable listeners, watchers and apply/digest methods + this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; + this.$on = this.$watch = this.$watchGroup = function() { return noop; }; + this.$$listeners = {}; - this.digestTtl = function(value) { - if (arguments.length) { - TTL = value; - } - return TTL; - }; + // All of the code below is bogus code that works around V8's memory leak via optimized code + // and inline caches. + // + // see: + // - https://code.google.com/p/v8/issues/detail?id=2073#c26 + // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 + // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 - this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser', - function($injector, $exceptionHandler, $parse, $browser) { + this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = + this.$$childTail = this.$root = this.$$watchers = null; + }, - /** - * @ngdoc type - * @name $rootScope.Scope - * - * @description - * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the - * {@link auto.$injector $injector}. Child scopes are created using the - * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when - * compiled HTML template is executed.) - * - * Here is a simple scope snippet to show how you can interact with the scope. - * ```html - * <file src="./test/ng/rootScopeSpec.js" tag="docs1" /> - * ``` - * - * # Inheritance - * A scope can inherit from a parent scope, as in this example: - * ```js - var parent = $rootScope; - var child = parent.$new(); + /** + * @ngdoc method + * @name $rootScope.Scope#$eval + * @kind function + * + * @description + * Executes the `expression` on the current scope and returns the result. Any exceptions in + * the expression are propagated (uncaught). This is useful when evaluating Angular + * expressions. + * + * # Example + * ```js + var scope = ng.$rootScope.Scope(); + scope.a = 1; + scope.b = 2; - parent.salutation = "Hello"; - expect(child.salutation).toEqual('Hello'); + expect(scope.$eval('a+b')).toEqual(3); + expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3); + * ``` + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + * @returns {*} The result of evaluating the expression. + */ + $eval: function(expr, locals) { + return $parse(expr)(this, locals); + }, - child.salutation = "Welcome"; - expect(child.salutation).toEqual('Welcome'); - expect(parent.salutation).toEqual('Hello'); - * ``` - * - * When interacting with `Scope` in tests, additional helper methods are available on the - * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional - * details. - * - * - * @param {Object.<string, function()>=} providers Map of service factory which need to be - * provided for the current scope. Defaults to {@link ng}. - * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should - * append/override services provided by `providers`. This is handy - * when unit-testing and having the need to override a default - * service. - * @returns {Object} Newly created scope. - * - */ - function Scope() { - this.$id = nextUid(); - this.$$phase = this.$parent = this.$$watchers = - this.$$nextSibling = this.$$prevSibling = - this.$$childHead = this.$$childTail = null; - this.$root = this; - this.$$destroyed = false; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$$isolateBindings = null; - } + /** + * @ngdoc method + * @name $rootScope.Scope#$evalAsync + * @kind function + * + * @description + * Executes the expression on the current scope at a later point in time. + * + * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only + * that: + * + * - it will execute after the function that scheduled the evaluation (preferably before DOM + * rendering). + * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after + * `expression` execution. + * + * Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle + * will be scheduled. However, it is encouraged to always call code that changes the model + * from within an `$apply` call. That includes code evaluated via `$evalAsync`. + * + * @param {(string|function())=} expression An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with the current `scope` parameter. + * + * @param {(object)=} locals Local variables object, useful for overriding values in scope. + */ + $evalAsync: function(expr, locals) { + // if we are outside of an $digest loop and this is the first time we are scheduling async + // task also schedule async auto-flush + if (!$rootScope.$$phase && !asyncQueue.length) { + $browser.defer(function() { + if (asyncQueue.length) { + $rootScope.$digest(); + } + }); + } - /** - * @ngdoc property - * @name $rootScope.Scope#$id - * - * @description - * Unique scope ID (monotonically increasing) useful for debugging. - */ + asyncQueue.push({scope: this, expression: expr, locals: locals}); + }, - /** - * @ngdoc property - * @name $rootScope.Scope#$parent - * - * @description - * Reference to the parent scope. - */ + $$postDigest: function(fn) { + postDigestQueue.push(fn); + }, + + /** + * @ngdoc method + * @name $rootScope.Scope#$apply + * @kind function + * + * @description + * `$apply()` is used to execute an expression in angular from outside of the angular + * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). + * Because we are calling into the angular framework we need to perform proper scope life + * cycle of {@link ng.$exceptionHandler exception handling}, + * {@link ng.$rootScope.Scope#$digest executing watches}. + * + * ## Life cycle + * + * # Pseudo-Code of `$apply()` + * ```js + function $apply(expr) { + try { + return $eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + $root.$digest(); + } + } + * ``` + * + * + * Scope's `$apply()` method transitions through the following stages: + * + * 1. The {@link guide/expression expression} is executed using the + * {@link ng.$rootScope.Scope#$eval $eval()} method. + * 2. Any exceptions from the execution of the expression are forwarded to the + * {@link ng.$exceptionHandler $exceptionHandler} service. + * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the + * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. + * + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. + * + * @returns {*} The result of evaluating the expression. + */ + $apply: function(expr) { + try { + beginPhase('$apply'); + return this.$eval(expr); + } catch (e) { + $exceptionHandler(e); + } finally { + clearPhase(); + try { + $rootScope.$digest(); + } catch (e) { + $exceptionHandler(e); + throw e; + } + } + }, /** - * @ngdoc property - * @name $rootScope.Scope#$root + * @ngdoc method + * @name $rootScope.Scope#$applyAsync + * @kind function * * @description - * Reference to the root scope. + * Schedule the invocation of $apply to occur at a later time. The actual time difference + * varies across browsers, but is typically around ~10 milliseconds. + * + * This can be used to queue up multiple expressions which need to be evaluated in the same + * digest. + * + * @param {(string|function())=} exp An angular expression to be executed. + * + * - `string`: execute using the rules as defined in {@link guide/expression expression}. + * - `function(scope)`: execute the function with current `scope` parameter. */ + $applyAsync: function(expr) { + var scope = this; + expr && applyAsyncQueue.push($applyAsyncExpression); + scheduleApplyAsync(); + + function $applyAsyncExpression() { + scope.$eval(expr); + } + }, - Scope.prototype = { - constructor: Scope, /** * @ngdoc method - * @name $rootScope.Scope#$new + * @name $rootScope.Scope#$on * @kind function * * @description - * Creates a new child {@link ng.$rootScope.Scope scope}. + * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for + * discussion of event life cycle. * - * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event. - * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. + * The event listener function format is: `function(event, args...)`. The `event` object + * passed into the listener has the following attributes: * - * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is - * desired for the scope and its child scopes to be permanently detached from the parent and - * thus stop participating in model change detection and listener notification by invoking. + * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or + * `$broadcast`-ed. + * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the + * event propagates through the scope hierarchy, this property is set to null. + * - `name` - `{string}`: name of the event. + * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel + * further event propagation (available only for events that were `$emit`-ed). + * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag + * to true. + * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. * - * @param {boolean} isolate If true, then the scope does not prototypically inherit from the - * parent scope. The scope is isolated, as it can not see parent scope properties. - * When creating widgets, it is useful for the widget to not accidentally read parent - * state. + * @param {string} name Event name to listen on. + * @param {function(event, ...args)} listener Function to call when the event is emitted. + * @returns {function()} Returns a deregistration function for this listener. + */ + $on: function(name, listener) { + var namedListeners = this.$$listeners[name]; + if (!namedListeners) { + this.$$listeners[name] = namedListeners = []; + } + namedListeners.push(listener); + + var current = this; + do { + if (!current.$$listenerCount[name]) { + current.$$listenerCount[name] = 0; + } + current.$$listenerCount[name]++; + } while ((current = current.$parent)); + + var self = this; + return function() { + var indexOfListener = namedListeners.indexOf(listener); + if (indexOfListener !== -1) { + namedListeners[indexOfListener] = null; + decrementListenerCount(self, 1, name); + } + }; + }, + + + /** + * @ngdoc method + * @name $rootScope.Scope#$emit + * @kind function * - * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent` - * of the newly created scope. Defaults to `this` scope if not provided. - * This is used when creating a transclude scope to correctly place it - * in the scope hierarchy while maintaining the correct prototypical - * inheritance. + * @description + * Dispatches an event `name` upwards through the scope hierarchy notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. * - * @returns {Object} The newly created child scope. + * The event life cycle starts at the scope on which `$emit` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event traverses upwards toward the root scope and calls all + * registered listeners along the way. The event will stop propagating if one of the listeners + * cancels it. * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. + * + * @param {string} name Event name to emit. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}). */ - $new: function(isolate, parent) { - var child; + $emit: function(name, args) { + var empty = [], + namedListeners, + scope = this, + stopPropagation = false, + event = { + name: name, + targetScope: scope, + stopPropagation: function() {stopPropagation = true;}, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }, + listenerArgs = concat([event], arguments, 1), + i, length; - parent = parent || this; + do { + namedListeners = scope.$$listeners[name] || empty; + event.currentScope = scope; + for (i = 0, length = namedListeners.length; i < length; i++) { - if (isolate) { - child = new Scope(); - child.$root = this.$root; - } else { - // Only create a child scope class if somebody asks for one, - // but cache it to allow the VM to optimize lookups. - if (!this.$$ChildScope) { - this.$$ChildScope = function ChildScope() { - this.$$watchers = this.$$nextSibling = - this.$$childHead = this.$$childTail = null; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$id = nextUid(); - this.$$ChildScope = null; - }; - this.$$ChildScope.prototype = this; + // if listeners were deregistered, defragment the array + if (!namedListeners[i]) { + namedListeners.splice(i, 1); + i--; + length--; + continue; + } + try { + //allow all listeners attached to the current scope to run + namedListeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } } - child = new this.$$ChildScope(); - } - child.$parent = parent; - child.$$prevSibling = parent.$$childTail; - if (parent.$$childHead) { - parent.$$childTail.$$nextSibling = child; - parent.$$childTail = child; - } else { - parent.$$childHead = parent.$$childTail = child; - } - - // When the new scope is not isolated or we inherit from `this`, and - // the parent scope is destroyed, the property `$$destroyed` is inherited - // prototypically. In all other cases, this property needs to be set - // when the parent scope is destroyed. - // The listener needs to be added after the parent is set - if (isolate || parent != this) child.$on('$destroy', destroyChild); + //if any listener on the current scope stops propagation, prevent bubbling + if (stopPropagation) { + event.currentScope = null; + return event; + } + //traverse upwards + scope = scope.$parent; + } while (scope); - return child; + event.currentScope = null; - function destroyChild() { - child.$$destroyed = true; - } + return event; }, + /** * @ngdoc method - * @name $rootScope.Scope#$watch + * @name $rootScope.Scope#$broadcast * @kind function * * @description - * Registers a `listener` callback to be executed whenever the `watchExpression` changes. - * - * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest - * $digest()} and should return the value that will be watched. (Since - * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the - * `watchExpression` can execute multiple times per - * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) - * - The `listener` is called only when the value from the current `watchExpression` and the - * previous call to `watchExpression` are not equal (with the exception of the initial run, - * see below). Inequality is determined according to reference inequality, - * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) - * via the `!==` Javascript operator, unless `objectEquality == true` - * (see next point) - * - When `objectEquality == true`, inequality of the `watchExpression` is determined - * according to the {@link angular.equals} function. To save the value of the object for - * later comparison, the {@link angular.copy} function is used. This therefore means that - * watching complex objects will have adverse memory and performance implications. - * - The watch `listener` may change the model, which may trigger other `listener`s to fire. - * This is achieved by rerunning the watchers until no changes are detected. The rerun - * iteration limit is 10 to prevent an infinite loop deadlock. - * - * - * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, - * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` - * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a - * change is detected, be prepared for multiple calls to your listener.) - * - * After a watcher is registered with the scope, the `listener` fn is called asynchronously - * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the - * watcher. In rare cases, this is undesirable because the listener is called when the result - * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you - * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the - * listener was called due to initialization. + * Dispatches an event `name` downwards to all child scopes (and their children) notifying the + * registered {@link ng.$rootScope.Scope#$on} listeners. * + * The event life cycle starts at the scope on which `$broadcast` was called. All + * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get + * notified. Afterwards, the event propagates to all direct and indirect scopes of the current + * scope and calls all registered listeners along the way. The event cannot be canceled. * + * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed + * onto the {@link ng.$exceptionHandler $exceptionHandler} service. * - * # Example - * ```js - // let's assume that scope was dependency injected as the $rootScope - var scope = $rootScope; - scope.name = 'misko'; - scope.counter = 0; + * @param {string} name Event name to broadcast. + * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. + * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} + */ + $broadcast: function(name, args) { + var target = this, + current = target, + next = target, + event = { + name: name, + targetScope: target, + preventDefault: function() { + event.defaultPrevented = true; + }, + defaultPrevented: false + }; - expect(scope.counter).toEqual(0); - scope.$watch('name', function(newValue, oldValue) { - scope.counter = scope.counter + 1; - }); - expect(scope.counter).toEqual(0); + if (!target.$$listenerCount[name]) return event; - scope.$digest(); - // the listener is always called during the first $digest loop after it was registered - expect(scope.counter).toEqual(1); + var listenerArgs = concat([event], arguments, 1), + listeners, i, length; - scope.$digest(); - // but now it will not be called unless the value changes - expect(scope.counter).toEqual(1); + //down while you can, then up and next sibling or up and next sibling until back at root + while ((current = next)) { + event.currentScope = current; + listeners = current.$$listeners[name] || []; + for (i = 0, length = listeners.length; i < length; i++) { + // if listeners were deregistered, defragment the array + if (!listeners[i]) { + listeners.splice(i, 1); + i--; + length--; + continue; + } - scope.name = 'adam'; - scope.$digest(); - expect(scope.counter).toEqual(2); + try { + listeners[i].apply(null, listenerArgs); + } catch (e) { + $exceptionHandler(e); + } + } + // Insanity Warning: scope depth-first traversal + // yes, this code is a bit crazy, but it works and we have tests to prove it! + // this piece should be kept in sync with the traversal in $digest + // (though it differs due to having the extra check for $$listenerCount) + if (!(next = ((current.$$listenerCount[name] && current.$$childHead) || + (current !== target && current.$$nextSibling)))) { + while (current !== target && !(next = current.$$nextSibling)) { + current = current.$parent; + } + } + } + event.currentScope = null; + return event; + } + }; - // Using a function as a watchExpression - var food; - scope.foodCounter = 0; - expect(scope.foodCounter).toEqual(0); - scope.$watch( - // This function returns the value being watched. It is called for each turn of the $digest loop - function() { return food; }, - // This is the change listener, called when the value returned from the above function changes - function(newValue, oldValue) { - if ( newValue !== oldValue ) { - // Only increment the counter if the value changed - scope.foodCounter = scope.foodCounter + 1; - } - } - ); - // No digest has been run so the counter will be zero - expect(scope.foodCounter).toEqual(0); + var $rootScope = new Scope(); - // Run the digest but since food has not changed count will still be zero - scope.$digest(); - expect(scope.foodCounter).toEqual(0); + //The internal queues. Expose them on the $rootScope for debugging/testing purposes. + var asyncQueue = $rootScope.$$asyncQueue = []; + var postDigestQueue = $rootScope.$$postDigestQueue = []; + var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; - // Update food and run digest. Now the counter will increment - food = 'cheeseburger'; - scope.$digest(); - expect(scope.foodCounter).toEqual(1); + return $rootScope; - * ``` - * - * - * - * @param {(function()|string)} watchExpression Expression that is evaluated on each - * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers - * a call to the `listener`. - * - * - `string`: Evaluated as {@link guide/expression expression} - * - `function(scope)`: called with current `scope` as a parameter. - * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value - * of `watchExpression` changes. - * - * - `newVal` contains the current value of the `watchExpression` - * - `oldVal` contains the previous value of the `watchExpression` - * - `scope` refers to the current scope - * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of - * comparing for reference equality. - * @returns {function()} Returns a deregistration function for this listener. - */ - $watch: function(watchExp, listener, objectEquality) { - var get = $parse(watchExp); - if (get.$$watchDelegate) { - return get.$$watchDelegate(this, listener, objectEquality, get); - } - var scope = this, - array = scope.$$watchers, - watcher = { - fn: listener, - last: initWatchVal, - get: get, - exp: watchExp, - eq: !!objectEquality - }; + function beginPhase(phase) { + if ($rootScope.$$phase) { + throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase); + } - lastDirtyWatch = null; + $rootScope.$$phase = phase; + } - if (!isFunction(listener)) { - watcher.fn = noop; + function clearPhase() { + $rootScope.$$phase = null; + } + + function incrementWatchersCount(current, count) { + do { + current.$$watchersCount += count; + } while ((current = current.$parent)); + } + + function decrementListenerCount(current, count, name) { + do { + current.$$listenerCount[name] -= count; + + if (current.$$listenerCount[name] === 0) { + delete current.$$listenerCount[name]; } + } while ((current = current.$parent)); + } - if (!array) { - array = scope.$$watchers = []; + /** + * function used as an initial value for watchers. + * because it's unique we can easily tell it apart from other values + */ + function initWatchVal() {} + + function flushApplyAsync() { + while (applyAsyncQueue.length) { + try { + applyAsyncQueue.shift()(); + } catch (e) { + $exceptionHandler(e); } - // we use unshift since we use a while loop in $digest for speed. - // the while loop reads in reverse order. - array.unshift(watcher); + } + applyAsyncId = null; + } + + function scheduleApplyAsync() { + if (applyAsyncId === null) { + applyAsyncId = $browser.defer(function() { + $rootScope.$apply(flushApplyAsync); + }); + } + } + }]; +} + +/** + * @description + * Private service to sanitize uris for links and images. Used by $compile and $sanitize. + */ +function $$SanitizeUriProvider() { + var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/, + imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during a[href] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to a[href] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.aHrefSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + aHrefSanitizationWhitelist = regexp; + return this; + } + return aHrefSanitizationWhitelist; + }; + + + /** + * @description + * Retrieves or overrides the default regular expression that is used for whitelisting of safe + * urls during img[src] sanitization. + * + * The sanitization is a security measure aimed at prevent XSS attacks via html links. + * + * Any url about to be assigned to img[src] via data-binding is first normalized and turned into + * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` + * regular expression. If a match is found, the original url is written into the dom. Otherwise, + * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * + * @param {RegExp=} regexp New regexp to whitelist urls with. + * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for + * chaining otherwise. + */ + this.imgSrcSanitizationWhitelist = function(regexp) { + if (isDefined(regexp)) { + imgSrcSanitizationWhitelist = regexp; + return this; + } + return imgSrcSanitizationWhitelist; + }; + + this.$get = function() { + return function sanitizeUri(uri, isImage) { + var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; + var normalizedVal; + normalizedVal = urlResolve(uri).href; + if (normalizedVal !== '' && !normalizedVal.match(regex)) { + return 'unsafe:' + normalizedVal; + } + return uri; + }; + }; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +var $sceMinErr = minErr('$sce'); + +var SCE_CONTEXTS = { + HTML: 'html', + CSS: 'css', + URL: 'url', + // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a + // url. (e.g. ng-include, script src, templateUrl) + RESOURCE_URL: 'resourceUrl', + JS: 'js' +}; - return function deregisterWatch() { - arrayRemove(array, watcher); - lastDirtyWatch = null; - }; - }, +// Helper functions follow. - /** - * @ngdoc method - * @name $rootScope.Scope#$watchGroup - * @kind function - * - * @description - * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`. - * If any one expression in the collection changes the `listener` is executed. - * - * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every - * call to $digest() to see if any items changes. - * - The `listener` is called whenever any expression in the `watchExpressions` array changes. - * - * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually - * watched using {@link ng.$rootScope.Scope#$watch $watch()} - * - * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any - * expression in `watchExpressions` changes - * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching - * those of `watchExpression` - * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching - * those of `watchExpression` - * The `scope` refers to the current scope. - * @returns {function()} Returns a de-registration function for all listeners. - */ - $watchGroup: function(watchExpressions, listener) { - var oldValues = new Array(watchExpressions.length); - var newValues = new Array(watchExpressions.length); - var deregisterFns = []; - var self = this; - var changeReactionScheduled = false; - var firstRun = true; +function adjustMatcher(matcher) { + if (matcher === 'self') { + return matcher; + } else if (isString(matcher)) { + // Strings match exactly except for 2 wildcards - '*' and '**'. + // '*' matches any character except those from the set ':/.?&'. + // '**' matches any character (like .* in a RegExp). + // More than 2 *'s raises an error as it's ill defined. + if (matcher.indexOf('***') > -1) { + throw $sceMinErr('iwcard', + 'Illegal sequence *** in string matcher. String: {0}', matcher); + } + matcher = escapeForRegexp(matcher). + replace('\\*\\*', '.*'). + replace('\\*', '[^:/.?&;]*'); + return new RegExp('^' + matcher + '$'); + } else if (isRegExp(matcher)) { + // The only other type of matcher allowed is a Regexp. + // Match entire URL / disallow partial matches. + // Flags are reset (i.e. no global, ignoreCase or multiline) + return new RegExp('^' + matcher.source + '$'); + } else { + throw $sceMinErr('imatcher', + 'Matchers may only be "self", string patterns or RegExp objects'); + } +} - if (!watchExpressions.length) { - // No expressions means we call the listener ASAP - var shouldCall = true; - self.$evalAsync(function() { - if (shouldCall) listener(newValues, newValues, self); - }); - return function deregisterWatchGroup() { - shouldCall = false; - }; - } - if (watchExpressions.length === 1) { - // Special case size of one - return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { - newValues[0] = value; - oldValues[0] = oldValue; - listener(newValues, (value === oldValue) ? newValues : oldValues, scope); - }); - } +function adjustMatchers(matchers) { + var adjustedMatchers = []; + if (isDefined(matchers)) { + forEach(matchers, function(matcher) { + adjustedMatchers.push(adjustMatcher(matcher)); + }); + } + return adjustedMatchers; +} - forEach(watchExpressions, function(expr, i) { - var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) { - newValues[i] = value; - oldValues[i] = oldValue; - if (!changeReactionScheduled) { - changeReactionScheduled = true; - self.$evalAsync(watchGroupAction); - } - }); - deregisterFns.push(unwatchFn); - }); - function watchGroupAction() { - changeReactionScheduled = false; +/** + * @ngdoc service + * @name $sceDelegate + * @kind function + * + * @description + * + * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict + * Contextual Escaping (SCE)} services to AngularJS. + * + * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of + * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is + * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to + * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things + * work because `$sce` delegates to `$sceDelegate` for these operations. + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service. + * + * The default instance of `$sceDelegate` should work out of the box with little pain. While you + * can override it completely to change the behavior of `$sce`, the common case would + * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting + * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as + * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist + * $sceDelegateProvider.resourceUrlWhitelist} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + */ - if (firstRun) { - firstRun = false; - listener(newValues, newValues, self); - } else { - listener(newValues, oldValues, self); - } - } +/** + * @ngdoc provider + * @name $sceDelegateProvider + * @description + * + * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate + * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure + * that the URLs used for sourcing Angular templates are safe. Refer {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and + * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + * + * For the general details about this service in Angular, read the main page for {@link ng.$sce + * Strict Contextual Escaping (SCE)}. + * + * **Example**: Consider the following case. <a name="example"></a> + * + * - your app is hosted at url `http://myapp.example.com/` + * - but some of your templates are hosted on other domains you control such as + * `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc. + * - and you have an open redirect at `http://myapp.example.com/clickThru?...`. + * + * Here is what a secure configuration for this scenario might look like: + * + * ``` + * angular.module('myApp', []).config(function($sceDelegateProvider) { + * $sceDelegateProvider.resourceUrlWhitelist([ + * // Allow same origin resource loads. + * 'self', + * // Allow loading from our assets domain. Notice the difference between * and **. + * 'http://srv*.assets.example.com/**' + * ]); + * + * // The blacklist overrides the whitelist so the open redirect here is blocked. + * $sceDelegateProvider.resourceUrlBlacklist([ + * 'http://myapp.example.com/clickThru**' + * ]); + * }); + * ``` + */ - return function deregisterWatchGroup() { - while (deregisterFns.length) { - deregisterFns.shift()(); - } - }; - }, +function $SceDelegateProvider() { + this.SCE_CONTEXTS = SCE_CONTEXTS; + // Resource URLs can also be trusted by policy. + var resourceUrlWhitelist = ['self'], + resourceUrlBlacklist = []; - /** - * @ngdoc method - * @name $rootScope.Scope#$watchCollection - * @kind function - * - * @description - * Shallow watches the properties of an object and fires whenever any of the properties change - * (for arrays, this implies watching the array items; for object maps, this implies watching - * the properties). If a change is detected, the `listener` callback is fired. - * - * - The `obj` collection is observed via standard $watch operation and is examined on every - * call to $digest() to see if any items have been added, removed, or moved. - * - The `listener` is called whenever anything within the `obj` has changed. Examples include - * adding, removing, and moving items belonging to an object or array. - * - * - * # Example - * ```js - $scope.names = ['igor', 'matias', 'misko', 'james']; - $scope.dataCount = 4; + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlWhitelist + * @kind function + * + * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * Note: **an empty whitelist array will block all URLs**! + * + * @return {Array} the currently set whitelist array. + * + * The **default value** when no whitelist has been explicitly set is `['self']` allowing only + * same origin resource requests. + * + * @description + * Sets/Gets the whitelist of trusted resource URLs. + */ + this.resourceUrlWhitelist = function(value) { + if (arguments.length) { + resourceUrlWhitelist = adjustMatchers(value); + } + return resourceUrlWhitelist; + }; - $scope.$watchCollection('names', function(newNames, oldNames) { - $scope.dataCount = newNames.length; - }); + /** + * @ngdoc method + * @name $sceDelegateProvider#resourceUrlBlacklist + * @kind function + * + * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value + * provided. This must be an array or null. A snapshot of this array is used so further + * changes to the array are ignored. + * + * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items + * allowed in this array. + * + * The typical usage for the blacklist is to **block + * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as + * these would otherwise be trusted but actually return content from the redirected domain. + * + * Finally, **the blacklist overrides the whitelist** and has the final say. + * + * @return {Array} the currently set blacklist array. + * + * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there + * is no blacklist.) + * + * @description + * Sets/Gets the blacklist of trusted resource URLs. + */ - expect($scope.dataCount).toEqual(4); - $scope.$digest(); + this.resourceUrlBlacklist = function(value) { + if (arguments.length) { + resourceUrlBlacklist = adjustMatchers(value); + } + return resourceUrlBlacklist; + }; - //still at 4 ... no changes - expect($scope.dataCount).toEqual(4); + this.$get = ['$injector', function($injector) { - $scope.names.pop(); - $scope.$digest(); + var htmlSanitizer = function htmlSanitizer(html) { + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + }; - //now there's been a change - expect($scope.dataCount).toEqual(3); - * ``` - * - * - * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The - * expression value should evaluate to an object or an array which is observed on each - * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the - * collection will trigger a call to the `listener`. - * - * @param {function(newCollection, oldCollection, scope)} listener a callback function called - * when a change is detected. - * - The `newCollection` object is the newly modified data obtained from the `obj` expression - * - The `oldCollection` object is a copy of the former collection data. - * Due to performance considerations, the`oldCollection` value is computed only if the - * `listener` function declares two or more arguments. - * - The `scope` argument refers to the current scope. - * - * @returns {function()} Returns a de-registration function for this listener. When the - * de-registration function is executed, the internal watch operation is terminated. - */ - $watchCollection: function(obj, listener) { - $watchCollectionInterceptor.$stateful = true; + if ($injector.has('$sanitize')) { + htmlSanitizer = $injector.get('$sanitize'); + } - var self = this; - // the current value, updated on each dirty-check run - var newValue; - // a shallow copy of the newValue from the last dirty-check run, - // updated to match newValue during dirty-check run - var oldValue; - // a shallow copy of the newValue from when the last change happened - var veryOldValue; - // only track veryOldValue if the listener is asking for it - var trackVeryOldValue = (listener.length > 1); - var changeDetected = 0; - var changeDetector = $parse(obj, $watchCollectionInterceptor); - var internalArray = []; - var internalObject = {}; - var initRun = true; - var oldLength = 0; - function $watchCollectionInterceptor(_value) { - newValue = _value; - var newLength, key, bothNaN, newItem, oldItem; + function matchUrl(matcher, parsedUrl) { + if (matcher === 'self') { + return urlIsSameOrigin(parsedUrl); + } else { + // definitely a regex. See adjustMatchers() + return !!matcher.exec(parsedUrl.href); + } + } - // If the new value is undefined, then return undefined as the watch may be a one-time watch - if (isUndefined(newValue)) return; + function isResourceUrlAllowedByPolicy(url) { + var parsedUrl = urlResolve(url.toString()); + var i, n, allowed = false; + // Ensure that at least one item from the whitelist allows this url. + for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { + if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { + allowed = true; + break; + } + } + if (allowed) { + // Ensure that no item from the blacklist blocked this url. + for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { + if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { + allowed = false; + break; + } + } + } + return allowed; + } - if (!isObject(newValue)) { // if primitive - if (oldValue !== newValue) { - oldValue = newValue; - changeDetected++; - } - } else if (isArrayLike(newValue)) { - if (oldValue !== internalArray) { - // we are transitioning from something which was not an array into array. - oldValue = internalArray; - oldLength = oldValue.length = 0; - changeDetected++; - } + function generateHolderType(Base) { + var holderType = function TrustedValueHolderType(trustedValue) { + this.$$unwrapTrustedValue = function() { + return trustedValue; + }; + }; + if (Base) { + holderType.prototype = new Base(); + } + holderType.prototype.valueOf = function sceValueOf() { + return this.$$unwrapTrustedValue(); + }; + holderType.prototype.toString = function sceToString() { + return this.$$unwrapTrustedValue().toString(); + }; + return holderType; + } - newLength = newValue.length; + var trustedValueHolderBase = generateHolderType(), + byType = {}; - if (oldLength !== newLength) { - // if lengths do not match we need to trigger change notification - changeDetected++; - oldValue.length = oldLength = newLength; - } - // copy the items to oldValue and look for changes. - for (var i = 0; i < newLength; i++) { - oldItem = oldValue[i]; - newItem = newValue[i]; + byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); + byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); - bothNaN = (oldItem !== oldItem) && (newItem !== newItem); - if (!bothNaN && (oldItem !== newItem)) { - changeDetected++; - oldValue[i] = newItem; - } - } - } else { - if (oldValue !== internalObject) { - // we are transitioning from something which was not an object into object. - oldValue = internalObject = {}; - oldLength = 0; - changeDetected++; - } - // copy the items to oldValue and look for changes. - newLength = 0; - for (key in newValue) { - if (newValue.hasOwnProperty(key)) { - newLength++; - newItem = newValue[key]; - oldItem = oldValue[key]; + /** + * @ngdoc method + * @name $sceDelegate#trustAs + * + * @description + * Returns an object that is trusted by angular for use in specified strict + * contextual escaping contexts (such as ng-bind-html, ng-include, any src + * attribute interpolation, any dom event binding attribute interpolation + * such as for onclick, etc.) that uses the provided value. + * See {@link ng.$sce $sce} for enabling strict contextual escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ + function trustAs(type, trustedValue) { + var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (!Constructor) { + throw $sceMinErr('icontext', + 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', + type, trustedValue); + } + if (trustedValue === null || trustedValue === undefined || trustedValue === '') { + return trustedValue; + } + // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting + // mutable objects, we ensure here that the value passed in is actually a string. + if (typeof trustedValue !== 'string') { + throw $sceMinErr('itype', + 'Attempted to trust a non-string value in a content requiring a string: Context: {0}', + type); + } + return new Constructor(trustedValue); + } - if (key in oldValue) { - bothNaN = (oldItem !== oldItem) && (newItem !== newItem); - if (!bothNaN && (oldItem !== newItem)) { - changeDetected++; - oldValue[key] = newItem; - } - } else { - oldLength++; - oldValue[key] = newItem; - changeDetected++; - } - } - } - if (oldLength > newLength) { - // we used to have more keys, need to find them and destroy them. - changeDetected++; - for (key in oldValue) { - if (!newValue.hasOwnProperty(key)) { - oldLength--; - delete oldValue[key]; - } - } - } - } - return changeDetected; + /** + * @ngdoc method + * @name $sceDelegate#valueOf + * + * @description + * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. + * + * If the passed parameter is not a value that had been returned by {@link + * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is. + * + * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} + * call or anything else. + * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns + * `value` unchanged. + */ + function valueOf(maybeTrusted) { + if (maybeTrusted instanceof trustedValueHolderBase) { + return maybeTrusted.$$unwrapTrustedValue(); + } else { + return maybeTrusted; + } + } + + /** + * @ngdoc method + * @name $sceDelegate#getTrusted + * + * @description + * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and + * returns the originally supplied value if the queried context type is a supertype of the + * created type. If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} call. + * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs + * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. + */ + function getTrusted(type, maybeTrusted) { + if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') { + return maybeTrusted; + } + var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); + if (constructor && maybeTrusted instanceof constructor) { + return maybeTrusted.$$unwrapTrustedValue(); + } + // If we get here, then we may only take one of two actions. + // 1. sanitize the value for the requested type, or + // 2. throw an exception. + if (type === SCE_CONTEXTS.RESOURCE_URL) { + if (isResourceUrlAllowedByPolicy(maybeTrusted)) { + return maybeTrusted; + } else { + throw $sceMinErr('insecurl', + 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', + maybeTrusted.toString()); } + } else if (type === SCE_CONTEXTS.HTML) { + return htmlSanitizer(maybeTrusted); + } + throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); + } - function $watchCollectionAction() { - if (initRun) { - initRun = false; - listener(newValue, newValue, self); - } else { - listener(newValue, veryOldValue, self); - } + return { trustAs: trustAs, + getTrusted: getTrusted, + valueOf: valueOf }; + }]; +} - // make a copy for the next time a collection is changed - if (trackVeryOldValue) { - if (!isObject(newValue)) { - //primitive - veryOldValue = newValue; - } else if (isArrayLike(newValue)) { - veryOldValue = new Array(newValue.length); - for (var i = 0; i < newValue.length; i++) { - veryOldValue[i] = newValue[i]; - } - } else { // if object - veryOldValue = {}; - for (var key in newValue) { - if (hasOwnProperty.call(newValue, key)) { - veryOldValue[key] = newValue[key]; - } - } - } - } - } - return this.$watch(changeDetector, $watchCollectionAction); - }, +/** + * @ngdoc provider + * @name $sceProvider + * @description + * + * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service. + * - enable/disable Strict Contextual Escaping (SCE) in a module + * - override the default implementation with a custom delegate + * + * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. + */ - /** - * @ngdoc method - * @name $rootScope.Scope#$digest - * @kind function - * - * @description - * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and - * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change - * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} - * until no more listeners are firing. This means that it is possible to get into an infinite - * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of - * iterations exceeds 10. - * - * Usually, you don't call `$digest()` directly in - * {@link ng.directive:ngController controllers} or in - * {@link ng.$compileProvider#directive directives}. - * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within - * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`. - * - * If you want to be notified whenever `$digest()` is called, - * you can register a `watchExpression` function with - * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`. - * - * In unit tests, you may need to call `$digest()` to simulate the scope life cycle. - * - * # Example - * ```js - var scope = ...; - scope.name = 'misko'; - scope.counter = 0; +/* jshint maxlen: false*/ - expect(scope.counter).toEqual(0); - scope.$watch('name', function(newValue, oldValue) { - scope.counter = scope.counter + 1; - }); - expect(scope.counter).toEqual(0); +/** + * @ngdoc service + * @name $sce + * @kind function + * + * @description + * + * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS. + * + * # Strict Contextual Escaping + * + * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain + * contexts to result in a value that is marked as safe to use for that context. One example of + * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer + * to these contexts as privileged or SCE contexts. + * + * As of version 1.2, Angular ships with SCE enabled by default. + * + * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow + * one to execute arbitrary javascript by the use of the expression() syntax. Refer + * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them. + * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>` + * to the top of your HTML document. + * + * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for + * security vulnerabilities such as XSS, clickjacking, etc. a lot easier. + * + * Here's an example of a binding in a privileged context: + * + * ``` + * <input ng-model="userHtml" aria-label="User input"> + * <div ng-bind-html="userHtml"></div> + * ``` + * + * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE + * disabled, this application allows the user to render arbitrary HTML into the DIV. + * In a more realistic example, one may be rendering user comments, blog articles, etc. via + * bindings. (HTML is just one example of a context where rendering user controlled input creates + * security vulnerabilities.) + * + * For the case of HTML, you might use a library, either on the client side, or on the server side, + * to sanitize unsafe HTML before binding to the value and rendering it in the document. + * + * How would you ensure that every place that used these types of bindings was bound to a value that + * was sanitized by your library (or returned as safe for rendering by your server?) How can you + * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some + * properties/fields and forgot to update the binding to the sanitized value? + * + * To be secure by default, you want to ensure that any such bindings are disallowed unless you can + * determine that something explicitly says it's safe to use a value for binding in that + * context. You can then audit your code (a simple grep would do) to ensure that this is only done + * for those values that you can easily tell are safe - because they were received from your server, + * sanitized by your library, etc. You can organize your codebase to help with this - perhaps + * allowing only the files in a specific directory to do this. Ensuring that the internal API + * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task. + * + * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs} + * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to + * obtain values that will be accepted by SCE / privileged contexts. + * + * + * ## How does it work? + * + * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted + * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link + * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the + * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. + * + * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link + * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly + * simplified): + * + * ``` + * var ngBindHtmlDirective = ['$sce', function($sce) { + * return function(scope, element, attr) { + * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) { + * element.html(value || ''); + * }); + * }; + * }]; + * ``` + * + * ## Impact on loading templates + * + * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as + * `templateUrl`'s specified by {@link guide/directive directives}. + * + * By default, Angular only loads templates from the same domain and protocol as the application + * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or + * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist + * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. + * + * *Please note*: + * The browser's + * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) + * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) + * policy apply in addition to this and may further restrict whether the template is successfully + * loaded. This means that without the right CORS policy, loading templates from a different domain + * won't work on all browsers. Also, loading templates from `file://` URL does not work on some + * browsers. + * + * ## This feels like too much overhead + * + * It's important to remember that SCE only applies to interpolation expressions. + * + * If your expressions are constant literals, they're automatically trusted and you don't need to + * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g. + * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works. + * + * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them + * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here. + * + * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load + * templates in `ng-include` from your application's domain without having to even know about SCE. + * It blocks loading templates from other domains or loading templates over http from an https + * served document. You can change these by setting your own custom {@link + * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link + * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs. + * + * This significantly reduces the overhead. It is far easier to pay the small overhead and have an + * application that's secure and can be audited to verify that with much more ease than bolting + * security onto an application later. + * + * <a name="contexts"></a> + * ## What trusted context types are supported? + * + * | Context | Notes | + * |---------------------|----------------| + * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. | + * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | + * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. | + * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. | + * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | + * + * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a> + * + * Each element in these arrays must be one of the following: + * + * - **'self'** + * - The special **string**, `'self'`, can be used to match against all URLs of the **same + * domain** as the application document using the **same protocol**. + * - **String** (except the special value `'self'`) + * - The string is matched against the full *normalized / absolute URL* of the resource + * being tested (substring matches are not good enough.) + * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters + * match themselves. + * - `*`: matches zero or more occurrences of any character other than one of the following 6 + * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use + * in a whitelist. + * - `**`: matches zero or more occurrences of *any* character. As such, it's not + * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g. + * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might + * not have been the intention.) Its usage at the very end of the path is ok. (e.g. + * http://foo.example.com/templates/**). + * - **RegExp** (*see caveat below*) + * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax + * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to + * accidentally introduce a bug when one updates a complex expression (imho, all regexes should + * have good test coverage.). For instance, the use of `.` in the regex is correct only in a + * small number of cases. A `.` character in the regex used when matching the scheme or a + * subdomain could be matched against a `:` or literal `.` that was likely not intended. It + * is highly recommended to use the string patterns and only fall back to regular expressions + * if they as a last resort. + * - The regular expression must be an instance of RegExp (i.e. not a string.) It is + * matched against the **entire** *normalized / absolute URL* of the resource being tested + * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags + * present on the RegExp (such as multiline, global, ignoreCase) are ignored. + * - If you are generating your JavaScript from some other templating engine (not + * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), + * remember to escape your regular expression (and be aware that you might need more than + * one level of escaping depending on your templating engine and the way you interpolated + * the value.) Do make use of your platform's escaping mechanism as it might be good + * enough before coding your own. e.g. Ruby has + * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) + * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). + * Javascript lacks a similar built in function for escaping. Take a look at Google + * Closure library's [goog.string.regExpEscape(s)]( + * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962). + * + * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example. + * + * ## Show me an example using SCE. + * + * <example module="mySceApp" deps="angular-sanitize.js"> + * <file name="index.html"> + * <div ng-controller="AppController as myCtrl"> + * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br> + * <b>User comments</b><br> + * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when + * $sanitize is available. If $sanitize isn't available, this results in an error instead of an + * exploit. + * <div class="well"> + * <div ng-repeat="userComment in myCtrl.userComments"> + * <b>{{userComment.name}}</b>: + * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span> + * <br> + * </div> + * </div> + * </div> + * </file> + * + * <file name="script.js"> + * angular.module('mySceApp', ['ngSanitize']) + * .controller('AppController', ['$http', '$templateCache', '$sce', + * function($http, $templateCache, $sce) { + * var self = this; + * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { + * self.userComments = userComments; + * }); + * self.explicitlyTrustedHtml = $sce.trustAsHtml( + * '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' + + * 'sanitization."">Hover over this text.</span>'); + * }]); + * </file> + * + * <file name="test_data.json"> + * [ + * { "name": "Alice", + * "htmlComment": + * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>" + * }, + * { "name": "Bob", + * "htmlComment": "<i>Yes!</i> Am I the only other one?" + * } + * ] + * </file> + * + * <file name="protractor.js" type="protractor"> + * describe('SCE doc demo', function() { + * it('should sanitize untrusted values', function() { + * expect(element.all(by.css('.htmlComment')).first().getInnerHtml()) + * .toBe('<span>Is <i>anyone</i> reading this?</span>'); + * }); + * + * it('should NOT sanitize explicitly trusted values', function() { + * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe( + * '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' + + * 'sanitization."">Hover over this text.</span>'); + * }); + * }); + * </file> + * </example> + * + * + * + * ## Can I disable SCE completely? + * + * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits + * for little coding overhead. It will be much harder to take an SCE disabled application and + * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE + * for cases where you have a lot of existing code that was written before SCE was introduced and + * you're migrating them a module at a time. + * + * That said, here's how you can completely disable SCE: + * + * ``` + * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) { + * // Completely disable SCE. For demonstration purposes only! + * // Do not use in new projects. + * $sceProvider.enabled(false); + * }); + * ``` + * + */ +/* jshint maxlen: 100 */ - scope.$digest(); - // the listener is always called during the first $digest loop after it was registered - expect(scope.counter).toEqual(1); +function $SceProvider() { + var enabled = true; - scope.$digest(); - // but now it will not be called unless the value changes - expect(scope.counter).toEqual(1); + /** + * @ngdoc method + * @name $sceProvider#enabled + * @kind function + * + * @param {boolean=} value If provided, then enables/disables SCE. + * @return {boolean} true if SCE is enabled, false otherwise. + * + * @description + * Enables/disables SCE and returns the current value. + */ + this.enabled = function(value) { + if (arguments.length) { + enabled = !!value; + } + return enabled; + }; - scope.name = 'adam'; - scope.$digest(); - expect(scope.counter).toEqual(2); - * ``` - * - */ - $digest: function() { - var watch, value, last, - watchers, - length, - dirty, ttl = TTL, - next, current, target = this, - watchLog = [], - logIdx, logMsg, asyncTask; - beginPhase('$digest'); - // Check for changes to browser url that happened in sync before the call to $digest - $browser.$$checkUrlChange(); + /* Design notes on the default implementation for SCE. + * + * The API contract for the SCE delegate + * ------------------------------------- + * The SCE delegate object must provide the following 3 methods: + * + * - trustAs(contextEnum, value) + * This method is used to tell the SCE service that the provided value is OK to use in the + * contexts specified by contextEnum. It must return an object that will be accepted by + * getTrusted() for a compatible contextEnum and return this value. + * + * - valueOf(value) + * For values that were not produced by trustAs(), return them as is. For values that were + * produced by trustAs(), return the corresponding input value to trustAs. Basically, if + * trustAs is wrapping the given values into some type, this operation unwraps it when given + * such a value. + * + * - getTrusted(contextEnum, value) + * This function should return the a value that is safe to use in the context specified by + * contextEnum or throw and exception otherwise. + * + * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be + * opaque or wrapped in some holder object. That happens to be an implementation detail. For + * instance, an implementation could maintain a registry of all trusted objects by context. In + * such a case, trustAs() would return the same object that was passed in. getTrusted() would + * return the same object passed in if it was found in the registry under a compatible context or + * throw an exception otherwise. An implementation might only wrap values some of the time based + * on some criteria. getTrusted() might return a value and not throw an exception for special + * constants or objects even if not wrapped. All such implementations fulfill this contract. + * + * + * A note on the inheritance model for SCE contexts + * ------------------------------------------------ + * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This + * is purely an implementation details. + * + * The contract is simply this: + * + * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value) + * will also succeed. + * + * Inheritance happens to capture this in a natural way. In some future, we + * may not use inheritance anymore. That is OK because no code outside of + * sce.js and sceSpecs.js would need to be aware of this detail. + */ - if (this === $rootScope && applyAsyncId !== null) { - // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then - // cancel the scheduled $apply and flush the queue of expressions to be evaluated. - $browser.defer.cancel(applyAsyncId); - flushApplyAsync(); - } + this.$get = ['$parse', '$sceDelegate', function( + $parse, $sceDelegate) { + // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow + // the "expression(javascript expression)" syntax which is insecure. + if (enabled && msie < 8) { + throw $sceMinErr('iequirks', + 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' + + 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' + + 'document. See http://docs.angularjs.org/api/ng.$sce for more information.'); + } + + var sce = shallowCopy(SCE_CONTEXTS); + + /** + * @ngdoc method + * @name $sce#isEnabled + * @kind function + * + * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you + * have to do it at module config time on {@link ng.$sceProvider $sceProvider}. + * + * @description + * Returns a boolean indicating if SCE is enabled. + */ + sce.isEnabled = function() { + return enabled; + }; + sce.trustAs = $sceDelegate.trustAs; + sce.getTrusted = $sceDelegate.getTrusted; + sce.valueOf = $sceDelegate.valueOf; - lastDirtyWatch = null; + if (!enabled) { + sce.trustAs = sce.getTrusted = function(type, value) { return value; }; + sce.valueOf = identity; + } - do { // "while dirty" loop - dirty = false; - current = target; + /** + * @ngdoc method + * @name $sce#parseAs + * + * @description + * Converts Angular {@link guide/expression expression} into a function. This is like {@link + * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it + * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*, + * *result*)} + * + * @param {string} type The kind of SCE context in which this result will be used. + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ + sce.parseAs = function sceParseAs(type, expr) { + var parsed = $parse(expr); + if (parsed.literal && parsed.constant) { + return parsed; + } else { + return $parse(expr, function(value) { + return sce.getTrusted(type, value); + }); + } + }; - while (asyncQueue.length) { - try { - asyncTask = asyncQueue.shift(); - asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); - } catch (e) { - $exceptionHandler(e); - } - lastDirtyWatch = null; - } + /** + * @ngdoc method + * @name $sce#trustAs + * + * @description + * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, + * returns an object that is trusted by angular for use in specified strict contextual + * escaping contexts (such as ng-bind-html, ng-include, any src attribute + * interpolation, any dom event binding attribute interpolation such as for onclick, etc.) + * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual + * escaping. + * + * @param {string} type The kind of context in which this value is safe for use. e.g. url, + * resourceUrl, html, js and css. + * @param {*} value The value that that should be considered trusted/safe. + * @returns {*} A value that can be used to stand in for the provided `value` in places + * where Angular expects a $sce.trustAs() return value. + */ - traverseScopesLoop: - do { // "traverse the scopes" loop - if ((watchers = current.$$watchers)) { - // process our watches - length = watchers.length; - while (length--) { - try { - watch = watchers[length]; - // Most common watches are on primitives, in which case we can short - // circuit it with === operator, only when === fails do we use .equals - if (watch) { - if ((value = watch.get(current)) !== (last = watch.last) && - !(watch.eq - ? equals(value, last) - : (typeof value === 'number' && typeof last === 'number' - && isNaN(value) && isNaN(last)))) { - dirty = true; - lastDirtyWatch = watch; - watch.last = watch.eq ? copy(value, null) : value; - watch.fn(value, ((last === initWatchVal) ? value : last), current); - if (ttl < 5) { - logIdx = 4 - ttl; - if (!watchLog[logIdx]) watchLog[logIdx] = []; - watchLog[logIdx].push({ - msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp, - newVal: value, - oldVal: last - }); - } - } else if (watch === lastDirtyWatch) { - // If the most recently dirty watcher is now clean, short circuit since the remaining watchers - // have already been tested. - dirty = false; - break traverseScopesLoop; - } - } - } catch (e) { - $exceptionHandler(e); - } - } - } + /** + * @ngdoc method + * @name $sce#trustAsHtml + * + * @description + * Shorthand method. `$sce.trustAsHtml(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml + * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ - // Insanity Warning: scope depth-first traversal - // yes, this code is a bit crazy, but it works and we have tests to prove it! - // this piece should be kept in sync with the traversal in $broadcast - if (!(next = (current.$$childHead || - (current !== target && current.$$nextSibling)))) { - while (current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } - } while ((current = next)); + /** + * @ngdoc method + * @name $sce#trustAsUrl + * + * @description + * Shorthand method. `$sce.trustAsUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl + * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ - // `break traverseScopesLoop;` takes us to here + /** + * @ngdoc method + * @name $sce#trustAsResourceUrl + * + * @description + * Shorthand method. `$sce.trustAsResourceUrl(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the return + * value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ - if ((dirty || asyncQueue.length) && !(ttl--)) { - clearPhase(); - throw $rootScopeMinErr('infdig', - '{0} $digest() iterations reached. Aborting!\n' + - 'Watchers fired in the last 5 iterations: {1}', - TTL, watchLog); - } + /** + * @ngdoc method + * @name $sce#trustAsJs + * + * @description + * Shorthand method. `$sce.trustAsJs(value)` → + * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`} + * + * @param {*} value The value to trustAs. + * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs + * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives + * only accept expressions that are either literal constants or are the + * return value of {@link ng.$sce#trustAs $sce.trustAs}.) + */ - } while (dirty || asyncQueue.length); + /** + * @ngdoc method + * @name $sce#getTrusted + * + * @description + * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such, + * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the + * originally supplied value if the queried context type is a supertype of the created type. + * If this condition isn't satisfied, throws an exception. + * + * @param {string} type The kind of context in which this value is to be used. + * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`} + * call. + * @returns {*} The value the was originally provided to + * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context. + * Otherwise, throws an exception. + */ - clearPhase(); + /** + * @ngdoc method + * @name $sce#getTrustedHtml + * + * @description + * Shorthand method. `$sce.getTrustedHtml(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)` + */ - while (postDigestQueue.length) { - try { - postDigestQueue.shift()(); - } catch (e) { - $exceptionHandler(e); - } - } - }, + /** + * @ngdoc method + * @name $sce#getTrustedCss + * + * @description + * Shorthand method. `$sce.getTrustedCss(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)` + */ + /** + * @ngdoc method + * @name $sce#getTrustedUrl + * + * @description + * Shorthand method. `$sce.getTrustedUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)` + */ - /** - * @ngdoc event - * @name $rootScope.Scope#$destroy - * @eventType broadcast on scope being destroyed - * - * @description - * Broadcasted when a scope and its children are being destroyed. - * - * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to - * clean up DOM bindings before an element is removed from the DOM. - */ + /** + * @ngdoc method + * @name $sce#getTrustedResourceUrl + * + * @description + * Shorthand method. `$sce.getTrustedResourceUrl(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} + * + * @param {*} value The value to pass to `$sceDelegate.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` + */ - /** - * @ngdoc method - * @name $rootScope.Scope#$destroy - * @kind function - * - * @description - * Removes the current scope (and all of its children) from the parent scope. Removal implies - * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer - * propagate to the current scope and its children. Removal also implies that the current - * scope is eligible for garbage collection. - * - * The `$destroy()` is usually used by directives such as - * {@link ng.directive:ngRepeat ngRepeat} for managing the - * unrolling of the loop. - * - * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. - * Application code can register a `$destroy` event handler that will give it a chance to - * perform any necessary cleanup. - * - * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to - * clean up DOM bindings before an element is removed from the DOM. - */ - $destroy: function() { - // we can't destroy the root scope or a scope that has been already destroyed - if (this.$$destroyed) return; - var parent = this.$parent; + /** + * @ngdoc method + * @name $sce#getTrustedJs + * + * @description + * Shorthand method. `$sce.getTrustedJs(value)` → + * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} + * + * @param {*} value The value to pass to `$sce.getTrusted`. + * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)` + */ - this.$broadcast('$destroy'); - this.$$destroyed = true; - if (this === $rootScope) return; + /** + * @ngdoc method + * @name $sce#parseAsHtml + * + * @description + * Shorthand method. `$sce.parseAsHtml(expression string)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ - for (var eventName in this.$$listenerCount) { - decrementListenerCount(this, this.$$listenerCount[eventName], eventName); - } + /** + * @ngdoc method + * @name $sce#parseAsCss + * + * @description + * Shorthand method. `$sce.parseAsCss(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ - // sever all the references to parent scopes (after this cleanup, the current scope should - // not be retained by any of our references and should be eligible for garbage collection) - if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; - if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; - if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; + /** + * @ngdoc method + * @name $sce#parseAsUrl + * + * @description + * Shorthand method. `$sce.parseAsUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ - // Disable listeners, watchers and apply/digest methods - this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; - this.$on = this.$watch = this.$watchGroup = function() { return noop; }; - this.$$listeners = {}; + /** + * @ngdoc method + * @name $sce#parseAsResourceUrl + * + * @description + * Shorthand method. `$sce.parseAsResourceUrl(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ - // All of the code below is bogus code that works around V8's memory leak via optimized code - // and inline caches. - // - // see: - // - https://code.google.com/p/v8/issues/detail?id=2073#c26 - // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 - // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 + /** + * @ngdoc method + * @name $sce#parseAsJs + * + * @description + * Shorthand method. `$sce.parseAsJs(value)` → + * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`} + * + * @param {string} expression String expression to compile. + * @returns {function(context, locals)} a function which represents the compiled expression: + * + * * `context` – `{object}` – an object against which any expressions embedded in the strings + * are evaluated against (typically a scope object). + * * `locals` – `{object=}` – local variables context object, useful for overriding values in + * `context`. + */ - this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = - this.$$childTail = this.$root = this.$$watchers = null; - }, + // Shorthand delegations. + var parse = sce.parseAs, + getTrusted = sce.getTrusted, + trustAs = sce.trustAs; - /** - * @ngdoc method - * @name $rootScope.Scope#$eval - * @kind function - * - * @description - * Executes the `expression` on the current scope and returns the result. Any exceptions in - * the expression are propagated (uncaught). This is useful when evaluating Angular - * expressions. - * - * # Example - * ```js - var scope = ng.$rootScope.Scope(); - scope.a = 1; - scope.b = 2; + forEach(SCE_CONTEXTS, function(enumValue, name) { + var lName = lowercase(name); + sce[camelCase("parse_as_" + lName)] = function(expr) { + return parse(enumValue, expr); + }; + sce[camelCase("get_trusted_" + lName)] = function(value) { + return getTrusted(enumValue, value); + }; + sce[camelCase("trust_as_" + lName)] = function(value) { + return trustAs(enumValue, value); + }; + }); - expect(scope.$eval('a+b')).toEqual(3); - expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3); - * ``` - * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - * @param {(object)=} locals Local variables object, useful for overriding values in scope. - * @returns {*} The result of evaluating the expression. - */ - $eval: function(expr, locals) { - return $parse(expr)(this, locals); - }, + return sce; + }]; +} - /** - * @ngdoc method - * @name $rootScope.Scope#$evalAsync - * @kind function - * - * @description - * Executes the expression on the current scope at a later point in time. - * - * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only - * that: - * - * - it will execute after the function that scheduled the evaluation (preferably before DOM - * rendering). - * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after - * `expression` execution. - * - * Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle - * will be scheduled. However, it is encouraged to always call code that changes the model - * from within an `$apply` call. That includes code evaluated via `$evalAsync`. - * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - * @param {(object)=} locals Local variables object, useful for overriding values in scope. - */ - $evalAsync: function(expr, locals) { - // if we are outside of an $digest loop and this is the first time we are scheduling async - // task also schedule async auto-flush - if (!$rootScope.$$phase && !asyncQueue.length) { - $browser.defer(function() { - if (asyncQueue.length) { - $rootScope.$digest(); - } - }); +/** + * !!! This is an undocumented "private" service !!! + * + * @name $sniffer + * @requires $window + * @requires $document + * + * @property {boolean} history Does the browser support html5 history api ? + * @property {boolean} transitions Does the browser support CSS transition events ? + * @property {boolean} animations Does the browser support CSS animation events ? + * + * @description + * This is very simple implementation of testing browser's features. + */ +function $SnifferProvider() { + this.$get = ['$window', '$document', function($window, $document) { + var eventSupport = {}, + android = + toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), + boxee = /Boxee/i.test(($window.navigator || {}).userAgent), + document = $document[0] || {}, + vendorPrefix, + vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, + bodyStyle = document.body && document.body.style, + transitions = false, + animations = false, + match; + + if (bodyStyle) { + for (var prop in bodyStyle) { + if (match = vendorRegex.exec(prop)) { + vendorPrefix = match[0]; + vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); + break; } + } - asyncQueue.push({scope: this, expression: expr, locals: locals}); - }, + if (!vendorPrefix) { + vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit'; + } - $$postDigest: function(fn) { - postDigestQueue.push(fn); - }, + transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle)); + animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); - /** - * @ngdoc method - * @name $rootScope.Scope#$apply - * @kind function - * - * @description - * `$apply()` is used to execute an expression in angular from outside of the angular - * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). - * Because we are calling into the angular framework we need to perform proper scope life - * cycle of {@link ng.$exceptionHandler exception handling}, - * {@link ng.$rootScope.Scope#$digest executing watches}. - * - * ## Life cycle - * - * # Pseudo-Code of `$apply()` - * ```js - function $apply(expr) { - try { - return $eval(expr); - } catch (e) { - $exceptionHandler(e); - } finally { - $root.$digest(); - } - } - * ``` - * - * - * Scope's `$apply()` method transitions through the following stages: - * - * 1. The {@link guide/expression expression} is executed using the - * {@link ng.$rootScope.Scope#$eval $eval()} method. - * 2. Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the - * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. - * - * - * @param {(string|function())=} exp An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $apply: function(expr) { - try { - beginPhase('$apply'); - return this.$eval(expr); - } catch (e) { - $exceptionHandler(e); - } finally { - clearPhase(); - try { - $rootScope.$digest(); - } catch (e) { - $exceptionHandler(e); - throw e; - } - } - }, + if (android && (!transitions || !animations)) { + transitions = isString(bodyStyle.webkitTransition); + animations = isString(bodyStyle.webkitAnimation); + } + } - /** - * @ngdoc method - * @name $rootScope.Scope#$applyAsync - * @kind function - * - * @description - * Schedule the invocation of $apply to occur at a later time. The actual time difference - * varies across browsers, but is typically around ~10 milliseconds. - * - * This can be used to queue up multiple expressions which need to be evaluated in the same - * digest. - * - * @param {(string|function())=} exp An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with current `scope` parameter. - */ - $applyAsync: function(expr) { - var scope = this; - expr && applyAsyncQueue.push($applyAsyncExpression); - scheduleApplyAsync(); - function $applyAsyncExpression() { - scope.$eval(expr); + return { + // Android has history.pushState, but it does not update location correctly + // so let's not use the history API at all. + // http://code.google.com/p/android/issues/detail?id=17471 + // https://github.com/angular/angular.js/issues/904 + + // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has + // so let's not use the history API also + // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined + // jshint -W018 + history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), + // jshint +W018 + hasEvent: function(event) { + // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have + // it. In particular the event is not fired when backspace or delete key are pressed or + // when cut operation is performed. + // IE10+ implements 'input' event but it erroneously fires under various situations, + // e.g. when placeholder changes, or a form is focused. + if (event === 'input' && msie <= 11) return false; + + if (isUndefined(eventSupport[event])) { + var divElm = document.createElement('div'); + eventSupport[event] = 'on' + event in divElm; } + + return eventSupport[event]; }, + csp: csp(), + vendorPrefix: vendorPrefix, + transitions: transitions, + animations: animations, + android: android + }; + }]; +} - /** - * @ngdoc method - * @name $rootScope.Scope#$on - * @kind function - * - * @description - * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for - * discussion of event life cycle. - * - * The event listener function format is: `function(event, args...)`. The `event` object - * passed into the listener has the following attributes: - * - * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or - * `$broadcast`-ed. - * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the - * event propagates through the scope hierarchy, this property is set to null. - * - `name` - `{string}`: name of the event. - * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel - * further event propagation (available only for events that were `$emit`-ed). - * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag - * to true. - * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. - * - * @param {string} name Event name to listen on. - * @param {function(event, ...args)} listener Function to call when the event is emitted. - * @returns {function()} Returns a deregistration function for this listener. - */ - $on: function(name, listener) { - var namedListeners = this.$$listeners[name]; - if (!namedListeners) { - this.$$listeners[name] = namedListeners = []; - } - namedListeners.push(listener); +var $compileMinErr = minErr('$compile'); - var current = this; - do { - if (!current.$$listenerCount[name]) { - current.$$listenerCount[name] = 0; - } - current.$$listenerCount[name]++; - } while ((current = current.$parent)); +/** + * @ngdoc service + * @name $templateRequest + * + * @description + * The `$templateRequest` service runs security checks then downloads the provided template using + * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request + * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the + * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the + * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted + * when `tpl` is of type string and `$templateCache` has the matching entry. + * + * @param {string|TrustedResourceUrl} tpl The HTTP request template URL + * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty + * + * @return {Promise} a promise for the HTTP response data of the given URL. + * + * @property {number} totalPendingRequests total amount of pending template requests being downloaded. + */ +function $TemplateRequestProvider() { + this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) { + function handleRequestFn(tpl, ignoreRequestError) { + handleRequestFn.totalPendingRequests++; - var self = this; - return function() { - var indexOfListener = namedListeners.indexOf(listener); - if (indexOfListener !== -1) { - namedListeners[indexOfListener] = null; - decrementListenerCount(self, 1, name); - } - }; - }, + // We consider the template cache holds only trusted templates, so + // there's no need to go through whitelisting again for keys that already + // are included in there. This also makes Angular accept any script + // directive, no matter its name. However, we still need to unwrap trusted + // types. + if (!isString(tpl) || !$templateCache.get(tpl)) { + tpl = $sce.getTrustedResourceUrl(tpl); + } + var transformResponse = $http.defaults && $http.defaults.transformResponse; - /** - * @ngdoc method - * @name $rootScope.Scope#$emit - * @kind function - * - * @description - * Dispatches an event `name` upwards through the scope hierarchy notifying the - * registered {@link ng.$rootScope.Scope#$on} listeners. - * - * The event life cycle starts at the scope on which `$emit` was called. All - * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get - * notified. Afterwards, the event traverses upwards toward the root scope and calls all - * registered listeners along the way. The event will stop propagating if one of the listeners - * cancels it. - * - * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed - * onto the {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {string} name Event name to emit. - * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. - * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}). - */ - $emit: function(name, args) { - var empty = [], - namedListeners, - scope = this, - stopPropagation = false, - event = { - name: name, - targetScope: scope, - stopPropagation: function() {stopPropagation = true;}, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }, - listenerArgs = concat([event], arguments, 1), - i, length; + if (isArray(transformResponse)) { + transformResponse = transformResponse.filter(function(transformer) { + return transformer !== defaultHttpResponseTransform; + }); + } else if (transformResponse === defaultHttpResponseTransform) { + transformResponse = null; + } - do { - namedListeners = scope.$$listeners[name] || empty; - event.currentScope = scope; - for (i = 0, length = namedListeners.length; i < length; i++) { + var httpOptions = { + cache: $templateCache, + transformResponse: transformResponse + }; - // if listeners were deregistered, defragment the array - if (!namedListeners[i]) { - namedListeners.splice(i, 1); - i--; - length--; - continue; - } - try { - //allow all listeners attached to the current scope to run - namedListeners[i].apply(null, listenerArgs); - } catch (e) { - $exceptionHandler(e); + return $http.get(tpl, httpOptions) + ['finally'](function() { + handleRequestFn.totalPendingRequests--; + }) + .then(function(response) { + $templateCache.put(tpl, response.data); + return response.data; + }, handleError); + + function handleError(resp) { + if (!ignoreRequestError) { + throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})', + tpl, resp.status, resp.statusText); + } + return $q.reject(resp); + } + } + + handleRequestFn.totalPendingRequests = 0; + + return handleRequestFn; + }]; +} + +function $$TestabilityProvider() { + this.$get = ['$rootScope', '$browser', '$location', + function($rootScope, $browser, $location) { + + /** + * @name $testability + * + * @description + * The private $$testability service provides a collection of methods for use when debugging + * or by automated test and debugging tools. + */ + var testability = {}; + + /** + * @name $$testability#findBindings + * + * @description + * Returns an array of elements that are bound (via ng-bind or {{}}) + * to expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The binding expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. Filters and whitespace are ignored. + */ + testability.findBindings = function(element, expression, opt_exactMatch) { + var bindings = element.getElementsByClassName('ng-binding'); + var matches = []; + forEach(bindings, function(binding) { + var dataBinding = angular.element(binding).data('$binding'); + if (dataBinding) { + forEach(dataBinding, function(bindingName) { + if (opt_exactMatch) { + var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)'); + if (matcher.test(bindingName)) { + matches.push(binding); + } + } else { + if (bindingName.indexOf(expression) != -1) { + matches.push(binding); + } } - } - //if any listener on the current scope stops propagation, prevent bubbling - if (stopPropagation) { - event.currentScope = null; - return event; - } - //traverse upwards - scope = scope.$parent; - } while (scope); + }); + } + }); + return matches; + }; - event.currentScope = null; + /** + * @name $$testability#findModels + * + * @description + * Returns an array of elements that are two-way found via ng-model to + * expressions matching the input. + * + * @param {Element} element The element root to search from. + * @param {string} expression The model expression to match. + * @param {boolean} opt_exactMatch If true, only returns exact matches + * for the expression. + */ + testability.findModels = function(element, expression, opt_exactMatch) { + var prefixes = ['ng-', 'data-ng-', 'ng\\:']; + for (var p = 0; p < prefixes.length; ++p) { + var attributeEquals = opt_exactMatch ? '=' : '*='; + var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]'; + var elements = element.querySelectorAll(selector); + if (elements.length) { + return elements; + } + } + }; - return event; - }, + /** + * @name $$testability#getLocation + * + * @description + * Shortcut for getting the location in a browser agnostic way. Returns + * the path, search, and hash. (e.g. /path?a=b#hash) + */ + testability.getLocation = function() { + return $location.url(); + }; + + /** + * @name $$testability#setLocation + * + * @description + * Shortcut for navigating to a location without doing a full page reload. + * + * @param {string} url The location url (path, search and hash, + * e.g. /path?a=b#hash) to go to. + */ + testability.setLocation = function(url) { + if (url !== $location.url()) { + $location.url(url); + $rootScope.$digest(); + } + }; + /** + * @name $$testability#whenStable + * + * @description + * Calls the callback when $timeout and $http requests are completed. + * + * @param {function} callback + */ + testability.whenStable = function(callback) { + $browser.notifyWhenNoOutstandingRequests(callback); + }; - /** - * @ngdoc method - * @name $rootScope.Scope#$broadcast - * @kind function - * - * @description - * Dispatches an event `name` downwards to all child scopes (and their children) notifying the - * registered {@link ng.$rootScope.Scope#$on} listeners. - * - * The event life cycle starts at the scope on which `$broadcast` was called. All - * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get - * notified. Afterwards, the event propagates to all direct and indirect scopes of the current - * scope and calls all registered listeners along the way. The event cannot be canceled. - * - * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed - * onto the {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {string} name Event name to broadcast. - * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. - * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} - */ - $broadcast: function(name, args) { - var target = this, - current = target, - next = target, - event = { - name: name, - targetScope: target, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }; + return testability; + }]; +} - if (!target.$$listenerCount[name]) return event; +function $TimeoutProvider() { + this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', + function($rootScope, $browser, $q, $$q, $exceptionHandler) { - var listenerArgs = concat([event], arguments, 1), - listeners, i, length; + var deferreds = {}; - //down while you can, then up and next sibling or up and next sibling until back at root - while ((current = next)) { - event.currentScope = current; - listeners = current.$$listeners[name] || []; - for (i = 0, length = listeners.length; i < length; i++) { - // if listeners were deregistered, defragment the array - if (!listeners[i]) { - listeners.splice(i, 1); - i--; - length--; - continue; - } - try { - listeners[i].apply(null, listenerArgs); - } catch (e) { - $exceptionHandler(e); - } - } + /** + * @ngdoc service + * @name $timeout + * + * @description + * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch + * block and delegates any exceptions to + * {@link ng.$exceptionHandler $exceptionHandler} service. + * + * The return value of calling `$timeout` is a promise, which will be resolved when + * the delay has passed and the timeout function, if provided, is executed. + * + * To cancel a timeout request, call `$timeout.cancel(promise)`. + * + * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to + * synchronously flush the queue of deferred functions. + * + * If you only want a promise that will be resolved after some specified delay + * then you can call `$timeout` without the `fn` function. + * + * @param {function()=} fn A function, whose execution should be delayed. + * @param {number=} [delay=0] Delay in milliseconds. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @param {...*=} Pass additional parameters to the executed function. + * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this + * promise will be resolved with is the return value of the `fn` function. + * + */ + function timeout(fn, delay, invokeApply) { + if (!isFunction(fn)) { + invokeApply = delay; + delay = fn; + fn = noop; + } - // Insanity Warning: scope depth-first traversal - // yes, this code is a bit crazy, but it works and we have tests to prove it! - // this piece should be kept in sync with the traversal in $digest - // (though it differs due to having the extra check for $$listenerCount) - if (!(next = ((current.$$listenerCount[name] && current.$$childHead) || - (current !== target && current.$$nextSibling)))) { - while (current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } + var args = sliceArgs(arguments, 3), + skipApply = (isDefined(invokeApply) && !invokeApply), + deferred = (skipApply ? $$q : $q).defer(), + promise = deferred.promise, + timeoutId; + + timeoutId = $browser.defer(function() { + try { + deferred.resolve(fn.apply(null, args)); + } catch (e) { + deferred.reject(e); + $exceptionHandler(e); + } + finally { + delete deferreds[promise.$$timeoutId]; } - event.currentScope = null; - return event; + if (!skipApply) $rootScope.$apply(); + }, delay); + + promise.$$timeoutId = timeoutId; + deferreds[timeoutId] = deferred; + + return promise; + } + + + /** + * @ngdoc method + * @name $timeout#cancel + * + * @description + * Cancels a task associated with the `promise`. As a result of this, the promise will be + * resolved with a rejection. + * + * @param {Promise=} promise Promise returned by the `$timeout` function. + * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully + * canceled. + */ + timeout.cancel = function(promise) { + if (promise && promise.$$timeoutId in deferreds) { + deferreds[promise.$$timeoutId].reject('canceled'); + delete deferreds[promise.$$timeoutId]; + return $browser.defer.cancel(promise.$$timeoutId); } + return false; }; - var $rootScope = new Scope(); + return timeout; + }]; +} - //The internal queues. Expose them on the $rootScope for debugging/testing purposes. - var asyncQueue = $rootScope.$$asyncQueue = []; - var postDigestQueue = $rootScope.$$postDigestQueue = []; - var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; +// NOTE: The usage of window and document instead of $window and $document here is +// deliberate. This service depends on the specific behavior of anchor nodes created by the +// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and +// cause us to break tests. In addition, when the browser resolves a URL for XHR, it +// doesn't know about mocked locations and resolves URLs to the real document - which is +// exactly the behavior needed here. There is little value is mocking these out for this +// service. +var urlParsingNode = document.createElement("a"); +var originUrl = urlResolve(window.location.href); - return $rootScope; +/** + * + * Implementation Notes for non-IE browsers + * ---------------------------------------- + * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, + * results both in the normalizing and parsing of the URL. Normalizing means that a relative + * URL will be resolved into an absolute URL in the context of the application document. + * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related + * properties are all populated to reflect the normalized URL. This approach has wide + * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * + * Implementation Notes for IE + * --------------------------- + * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other + * browsers. However, the parsed components will not be set if the URL assigned did not specify + * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We + * work around that by performing the parsing in a 2nd step by taking a previously normalized + * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the + * properties such as protocol, hostname, port, etc. + * + * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one + * uses the inner HTML approach to assign the URL as part of an HTML snippet - + * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL. + * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. + * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that + * method and IE < 8 is unsupported. + * + * References: + * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * http://url.spec.whatwg.org/#urlutils + * https://github.com/angular/angular.js/pull/2902 + * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ + * + * @kind function + * @param {string} url The URL to be parsed. + * @description Normalizes and parses a URL. + * @returns {object} Returns the normalized URL as a dictionary. + * + * | member name | Description | + * |---------------|----------------| + * | href | A normalized version of the provided URL if it was not an absolute URL | + * | protocol | The protocol including the trailing colon | + * | host | The host and port (if the port is non-default) of the normalizedUrl | + * | search | The search params, minus the question mark | + * | hash | The hash string, minus the hash symbol + * | hostname | The hostname + * | port | The port, without ":" + * | pathname | The pathname, beginning with "/" + * + */ +function urlResolve(url) { + var href = url; - function beginPhase(phase) { - if ($rootScope.$$phase) { - throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase); - } + if (msie) { + // Normalize before parse. Refer Implementation Notes on why this is + // done in two steps on IE. + urlParsingNode.setAttribute("href", href); + href = urlParsingNode.href; + } - $rootScope.$$phase = phase; - } + urlParsingNode.setAttribute('href', href); - function clearPhase() { - $rootScope.$$phase = null; - } + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') + ? urlParsingNode.pathname + : '/' + urlParsingNode.pathname + }; +} +/** + * Parse a request URL and determine whether this is a same-origin request as the application document. + * + * @param {string|object} requestUrl The url of the request as a string that will be resolved + * or a parsed URL object. + * @returns {boolean} Whether the request is for the same origin as the application document. + */ +function urlIsSameOrigin(requestUrl) { + var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl; + return (parsed.protocol === originUrl.protocol && + parsed.host === originUrl.host); +} - function decrementListenerCount(current, count, name) { - do { - current.$$listenerCount[name] -= count; +/** + * @ngdoc service + * @name $window + * + * @description + * A reference to the browser's `window` object. While `window` + * is globally available in JavaScript, it causes testability problems, because + * it is a global variable. In angular we always refer to it through the + * `$window` service, so it may be overridden, removed or mocked for testing. + * + * Expressions, like the one defined for the `ngClick` directive in the example + * below, are evaluated with respect to the current scope. Therefore, there is + * no risk of inadvertently coding in a dependency on a global value in such an + * expression. + * + * @example + <example module="windowExample"> + <file name="index.html"> + <script> + angular.module('windowExample', []) + .controller('ExampleController', ['$scope', '$window', function($scope, $window) { + $scope.greeting = 'Hello, World!'; + $scope.doGreeting = function(greeting) { + $window.alert(greeting); + }; + }]); + </script> + <div ng-controller="ExampleController"> + <input type="text" ng-model="greeting" aria-label="greeting" /> + <button ng-click="doGreeting(greeting)">ALERT</button> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should display the greeting in the input box', function() { + element(by.model('greeting')).sendKeys('Hello, E2E Tests'); + // If we click the button it will block the test runner + // element(':button').click(); + }); + </file> + </example> + */ +function $WindowProvider() { + this.$get = valueFn(window); +} - if (current.$$listenerCount[name] === 0) { - delete current.$$listenerCount[name]; - } - } while ((current = current.$parent)); +/** + * @name $$cookieReader + * @requires $document + * + * @description + * This is a private service for reading cookies used by $http and ngCookies + * + * @return {Object} a key/value map of the current cookies + */ +function $$CookieReader($document) { + var rawDocument = $document[0] || {}; + var lastCookies = {}; + var lastCookieString = ''; + + function safeDecodeURIComponent(str) { + try { + return decodeURIComponent(str); + } catch (e) { + return str; } + } - /** - * function used as an initial value for watchers. - * because it's unique we can easily tell it apart from other values - */ - function initWatchVal() {} + return function() { + var cookieArray, cookie, i, index, name; + var currentCookieString = rawDocument.cookie || ''; - function flushApplyAsync() { - while (applyAsyncQueue.length) { - try { - applyAsyncQueue.shift()(); - } catch (e) { - $exceptionHandler(e); + if (currentCookieString !== lastCookieString) { + lastCookieString = currentCookieString; + cookieArray = lastCookieString.split('; '); + lastCookies = {}; + + for (i = 0; i < cookieArray.length; i++) { + cookie = cookieArray[i]; + index = cookie.indexOf('='); + if (index > 0) { //ignore nameless cookies + name = safeDecodeURIComponent(cookie.substring(0, index)); + // the first value that is seen for a cookie is the most + // specific one. values for the same cookie name that + // follow are for less specific paths. + if (lastCookies[name] === undefined) { + lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); + } } } - applyAsyncId = null; } + return lastCookies; + }; +} - function scheduleApplyAsync() { - if (applyAsyncId === null) { - applyAsyncId = $browser.defer(function() { - $rootScope.$apply(flushApplyAsync); - }); - } - } - }]; +$$CookieReader.$inject = ['$document']; + +function $$CookieReaderProvider() { + this.$get = $$CookieReader; } +/* global currencyFilter: true, + dateFilter: true, + filterFilter: true, + jsonFilter: true, + limitToFilter: true, + lowercaseFilter: true, + numberFilter: true, + orderByFilter: true, + uppercaseFilter: true, + */ + /** + * @ngdoc provider + * @name $filterProvider * @description - * Private service to sanitize uris for links and images. Used by $compile and $sanitize. + * + * Filters are just functions which transform input to an output. However filters need to be + * Dependency Injected. To achieve this a filter definition consists of a factory function which is + * annotated with dependencies and is responsible for creating a filter function. + * + * <div class="alert alert-warning"> + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + * </div> + * + * ```js + * // Filter registration + * function MyModule($provide, $filterProvider) { + * // create a service to demonstrate injection (not always needed) + * $provide.value('greet', function(name){ + * return 'Hello ' + name + '!'; + * }); + * + * // register a filter factory which uses the + * // greet service to demonstrate DI. + * $filterProvider.register('greet', function(greet){ + * // return the filter function which uses the greet service + * // to generate salutation + * return function(text) { + * // filters need to be forgiving so check input validity + * return text && greet(text) || text; + * }; + * }); + * } + * ``` + * + * The filter function is registered with the `$injector` under the filter name suffix with + * `Filter`. + * + * ```js + * it('should be the same instance', inject( + * function($filterProvider) { + * $filterProvider.register('reverse', function(){ + * return ...; + * }); + * }, + * function($filter, reverseFilter) { + * expect($filter('reverse')).toBe(reverseFilter); + * }); + * ``` + * + * + * For more information about how angular filters work, and how to create your own filters, see + * {@link guide/filter Filters} in the Angular Developer Guide. */ -function $$SanitizeUriProvider() { - var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/, - imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; + +/** + * @ngdoc service + * @name $filter + * @kind function + * @description + * Filters are used for formatting data displayed to the user. + * + * The general syntax in templates is as follows: + * + * {{ expression [| filter_name[:parameter_value] ... ] }} + * + * @param {String} name Name of the filter function to retrieve + * @return {Function} the filter function + * @example + <example name="$filter" module="filterExample"> + <file name="index.html"> + <div ng-controller="MainCtrl"> + <h3>{{ originalText }}</h3> + <h3>{{ filteredText }}</h3> + </div> + </file> + + <file name="script.js"> + angular.module('filterExample', []) + .controller('MainCtrl', function($scope, $filter) { + $scope.originalText = 'hello'; + $scope.filteredText = $filter('uppercase')($scope.originalText); + }); + </file> + </example> + */ +$FilterProvider.$inject = ['$provide']; +function $FilterProvider($provide) { + var suffix = 'Filter'; /** - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during a[href] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via html links. - * - * Any url about to be assigned to a[href] via data-binding is first normalized and turned into - * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` - * regular expression. If a match is found, the original url is written into the dom. Otherwise, - * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. + * @ngdoc method + * @name $filterProvider#register + * @param {string|Object} name Name of the filter function, or an object map of filters where + * the keys are the filter names and the values are the filter factories. * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. + * <div class="alert alert-warning"> + * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`. + * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace + * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores + * (`myapp_subsection_filterx`). + * </div> + * @returns {Object} Registered filter instance, or if a map of filters was provided then a map + * of the registered filter instances. */ - this.aHrefSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - aHrefSanitizationWhitelist = regexp; - return this; + function register(name, factory) { + if (isObject(name)) { + var filters = {}; + forEach(name, function(filter, key) { + filters[key] = register(key, filter); + }); + return filters; + } else { + return $provide.factory(name + suffix, factory); + } + } + this.register = register; + + this.$get = ['$injector', function($injector) { + return function(name) { + return $injector.get(name + suffix); + }; + }]; + + //////////////////////////////////////// + + /* global + currencyFilter: false, + dateFilter: false, + filterFilter: false, + jsonFilter: false, + limitToFilter: false, + lowercaseFilter: false, + numberFilter: false, + orderByFilter: false, + uppercaseFilter: false, + */ + + register('currency', currencyFilter); + register('date', dateFilter); + register('filter', filterFilter); + register('json', jsonFilter); + register('limitTo', limitToFilter); + register('lowercase', lowercaseFilter); + register('number', numberFilter); + register('orderBy', orderByFilter); + register('uppercase', uppercaseFilter); +} + +/** + * @ngdoc filter + * @name filter + * @kind function + * + * @description + * Selects a subset of items from `array` and returns it as a new array. + * + * @param {Array} array The source array. + * @param {string|Object|function()} expression The predicate to be used for selecting items from + * `array`. + * + * Can be one of: + * + * - `string`: The string is used for matching against the contents of the `array`. All strings or + * objects with string properties in `array` that match this string will be returned. This also + * applies to nested object properties. + * The predicate can be negated by prefixing the string with `!`. + * + * - `Object`: A pattern object can be used to filter specific properties on objects contained + * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items + * which have property `name` containing "M" and property `phone` containing "1". A special + * property name `$` can be used (as in `{$:"text"}`) to accept a match against any + * property of the object or its nested object properties. That's equivalent to the simple + * substring match with a `string` as described above. The predicate can be negated by prefixing + * the string with `!`. + * For example `{name: "!M"}` predicate will return an array of items which have property `name` + * not containing "M". + * + * Note that a named property will match properties on the same level only, while the special + * `$` property will match properties on the same level or deeper. E.g. an array item like + * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but + * **will** be matched by `{$: 'John'}`. + * + * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters. + * The function is called for each element of the array, with the element, its index, and + * the entire array itself as arguments. + * + * The final result is an array of those elements that the predicate returned true for. + * + * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in + * determining if the expected value (from the filter expression) and actual value (from + * the object in the array) should be considered a match. + * + * Can be one of: + * + * - `function(actual, expected)`: + * The function will be given the object value and the predicate value to compare and + * should return true if both values should be considered equal. + * + * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`. + * This is essentially strict comparison of expected and actual. + * + * - `false|undefined`: A short hand for a function which will look for a substring match in case + * insensitive way. + * + * Primitive values are converted to strings. Objects are not compared against primitives, + * unless they have a custom `toString` method (e.g. `Date` objects). + * + * @example + <example> + <file name="index.html"> + <div ng-init="friends = [{name:'John', phone:'555-1276'}, + {name:'Mary', phone:'800-BIG-MARY'}, + {name:'Mike', phone:'555-4321'}, + {name:'Adam', phone:'555-5678'}, + {name:'Julie', phone:'555-8765'}, + {name:'Juliette', phone:'555-5678'}]"></div> + + <label>Search: <input ng-model="searchText"></label> + <table id="searchTextResults"> + <tr><th>Name</th><th>Phone</th></tr> + <tr ng-repeat="friend in friends | filter:searchText"> + <td>{{friend.name}}</td> + <td>{{friend.phone}}</td> + </tr> + </table> + <hr> + <label>Any: <input ng-model="search.$"></label> <br> + <label>Name only <input ng-model="search.name"></label><br> + <label>Phone only <input ng-model="search.phone"></label><br> + <label>Equality <input type="checkbox" ng-model="strict"></label><br> + <table id="searchObjResults"> + <tr><th>Name</th><th>Phone</th></tr> + <tr ng-repeat="friendObj in friends | filter:search:strict"> + <td>{{friendObj.name}}</td> + <td>{{friendObj.phone}}</td> + </tr> + </table> + </file> + <file name="protractor.js" type="protractor"> + var expectFriendNames = function(expectedNames, key) { + element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { + arr.forEach(function(wd, i) { + expect(wd.getText()).toMatch(expectedNames[i]); + }); + }); + }; + + it('should search across all fields when filtering with a string', function() { + var searchText = element(by.model('searchText')); + searchText.clear(); + searchText.sendKeys('m'); + expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); + + searchText.clear(); + searchText.sendKeys('76'); + expectFriendNames(['John', 'Julie'], 'friend'); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + var searchAny = element(by.model('search.$')); + searchAny.clear(); + searchAny.sendKeys('i'); + expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); + }); + it('should use a equal comparison when comparator is true', function() { + var searchName = element(by.model('search.name')); + var strict = element(by.model('strict')); + searchName.clear(); + searchName.sendKeys('Julie'); + strict.click(); + expectFriendNames(['Julie'], 'friendObj'); + }); + </file> + </example> + */ +function filterFilter() { + return function(array, expression, comparator) { + if (!isArrayLike(array)) { + if (array == null) { + return array; + } else { + throw minErr('filter')('notarray', 'Expected array but received: {0}', array); + } } - return aHrefSanitizationWhitelist; - }; + var expressionType = getTypeForFilter(expression); + var predicateFn; + var matchAgainstAnyProp; - /** - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during img[src] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via html links. - * - * Any url about to be assigned to img[src] via data-binding is first normalized and turned into - * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` - * regular expression. If a match is found, the original url is written into the dom. Otherwise, - * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. - * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.imgSrcSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - imgSrcSanitizationWhitelist = regexp; - return this; + switch (expressionType) { + case 'function': + predicateFn = expression; + break; + case 'boolean': + case 'null': + case 'number': + case 'string': + matchAgainstAnyProp = true; + //jshint -W086 + case 'object': + //jshint +W086 + predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp); + break; + default: + return array; } - return imgSrcSanitizationWhitelist; - }; - this.$get = function() { - return function sanitizeUri(uri, isImage) { - var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; - var normalizedVal; - normalizedVal = urlResolve(uri).href; - if (normalizedVal !== '' && !normalizedVal.match(regex)) { - return 'unsafe:' + normalizedVal; - } - return uri; - }; + return Array.prototype.filter.call(array, predicateFn); }; } -var $sceMinErr = minErr('$sce'); +// Helper functions for `filterFilter` +function createPredicateFn(expression, comparator, matchAgainstAnyProp) { + var shouldMatchPrimitives = isObject(expression) && ('$' in expression); + var predicateFn; -var SCE_CONTEXTS = { - HTML: 'html', - CSS: 'css', - URL: 'url', - // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a - // url. (e.g. ng-include, script src, templateUrl) - RESOURCE_URL: 'resourceUrl', - JS: 'js' -}; + if (comparator === true) { + comparator = equals; + } else if (!isFunction(comparator)) { + comparator = function(actual, expected) { + if (isUndefined(actual)) { + // No substring matching against `undefined` + return false; + } + if ((actual === null) || (expected === null)) { + // No substring matching against `null`; only match against `null` + return actual === expected; + } + if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) { + // Should not compare primitives against objects, unless they have custom `toString` method + return false; + } -// Helper functions follow. + actual = lowercase('' + actual); + expected = lowercase('' + expected); + return actual.indexOf(expected) !== -1; + }; + } -function adjustMatcher(matcher) { - if (matcher === 'self') { - return matcher; - } else if (isString(matcher)) { - // Strings match exactly except for 2 wildcards - '*' and '**'. - // '*' matches any character except those from the set ':/.?&'. - // '**' matches any character (like .* in a RegExp). - // More than 2 *'s raises an error as it's ill defined. - if (matcher.indexOf('***') > -1) { - throw $sceMinErr('iwcard', - 'Illegal sequence *** in string matcher. String: {0}', matcher); + predicateFn = function(item) { + if (shouldMatchPrimitives && !isObject(item)) { + return deepCompare(item, expression.$, comparator, false); } - matcher = escapeForRegexp(matcher). - replace('\\*\\*', '.*'). - replace('\\*', '[^:/.?&;]*'); - return new RegExp('^' + matcher + '$'); - } else if (isRegExp(matcher)) { - // The only other type of matcher allowed is a Regexp. - // Match entire URL / disallow partial matches. - // Flags are reset (i.e. no global, ignoreCase or multiline) - return new RegExp('^' + matcher.source + '$'); - } else { - throw $sceMinErr('imatcher', - 'Matchers may only be "self", string patterns or RegExp objects'); - } + return deepCompare(item, expression, comparator, matchAgainstAnyProp); + }; + + return predicateFn; } +function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { + var actualType = getTypeForFilter(actual); + var expectedType = getTypeForFilter(expected); -function adjustMatchers(matchers) { - var adjustedMatchers = []; - if (isDefined(matchers)) { - forEach(matchers, function(matcher) { - adjustedMatchers.push(adjustMatcher(matcher)); + if ((expectedType === 'string') && (expected.charAt(0) === '!')) { + return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); + } else if (isArray(actual)) { + // In case `actual` is an array, consider it a match + // if ANY of it's items matches `expected` + return actual.some(function(item) { + return deepCompare(item, expected, comparator, matchAgainstAnyProp); }); } - return adjustedMatchers; + + switch (actualType) { + case 'object': + var key; + if (matchAgainstAnyProp) { + for (key in actual) { + if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) { + return true; + } + } + return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false); + } else if (expectedType === 'object') { + for (key in expected) { + var expectedVal = expected[key]; + if (isFunction(expectedVal) || isUndefined(expectedVal)) { + continue; + } + + var matchAnyProperty = key === '$'; + var actualVal = matchAnyProperty ? actual : actual[key]; + if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) { + return false; + } + } + return true; + } else { + return comparator(actual, expected); + } + break; + case 'function': + return false; + default: + return comparator(actual, expected); + } } +// Used for easily differentiating between `null` and actual `object` +function getTypeForFilter(val) { + return (val === null) ? 'null' : typeof val; +} /** - * @ngdoc service - * @name $sceDelegate + * @ngdoc filter + * @name currency * @kind function * * @description + * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default + * symbol for current locale is used. * - * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict - * Contextual Escaping (SCE)} services to AngularJS. - * - * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of - * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is - * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to - * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things - * work because `$sce` delegates to `$sceDelegate` for these operations. + * @param {number} amount Input to filter. + * @param {string=} symbol Currency symbol or identifier to be displayed. + * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale + * @returns {string} Formatted number. * - * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service. * - * The default instance of `$sceDelegate` should work out of the box with little pain. While you - * can override it completely to change the behavior of `$sce`, the common case would - * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting - * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as - * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist - * $sceDelegateProvider.resourceUrlWhitelist} and {@link - * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} + * @example + <example module="currencyExample"> + <file name="index.html"> + <script> + angular.module('currencyExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.amount = 1234.56; + }]); + </script> + <div ng-controller="ExampleController"> + <input type="number" ng-model="amount" aria-label="amount"> <br> + default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br> + custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span> + no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should init with 1234.56', function() { + expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); + expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235'); + }); + it('should update', function() { + if (browser.params.browser == 'safari') { + // Safari does not understand the minus key. See + // https://github.com/angular/protractor/issues/481 + return; + } + element(by.model('amount')).clear(); + element(by.model('amount')).sendKeys('-1234'); + expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)'); + expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)'); + expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)'); + }); + </file> + </example> */ +currencyFilter.$inject = ['$locale']; +function currencyFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(amount, currencySymbol, fractionSize) { + if (isUndefined(currencySymbol)) { + currencySymbol = formats.CURRENCY_SYM; + } + + if (isUndefined(fractionSize)) { + fractionSize = formats.PATTERNS[1].maxFrac; + } + + // if null or undefined pass it through + return (amount == null) + ? amount + : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize). + replace(/\u00A4/g, currencySymbol); + }; +} /** - * @ngdoc provider - * @name $sceDelegateProvider - * @description - * - * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate - * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure - * that the URLs used for sourcing Angular templates are safe. Refer {@link - * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and - * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} - * - * For the general details about this service in Angular, read the main page for {@link ng.$sce - * Strict Contextual Escaping (SCE)}. + * @ngdoc filter + * @name number + * @kind function * - * **Example**: Consider the following case. <a name="example"></a> + * @description + * Formats a number as text. * - * - your app is hosted at url `http://myapp.example.com/` - * - but some of your templates are hosted on other domains you control such as - * `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc. - * - and you have an open redirect at `http://myapp.example.com/clickThru?...`. + * If the input is null or undefined, it will just be returned. + * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned. + * If the input is not a number an empty string is returned. * - * Here is what a secure configuration for this scenario might look like: * - * ``` - * angular.module('myApp', []).config(function($sceDelegateProvider) { - * $sceDelegateProvider.resourceUrlWhitelist([ - * // Allow same origin resource loads. - * 'self', - * // Allow loading from our assets domain. Notice the difference between * and **. - * 'http://srv*.assets.example.com/**' - * ]); + * @param {number|string} number Number to format. + * @param {(number|string)=} fractionSize Number of decimal places to round the number to. + * If this is not provided then the fraction size is computed from the current locale's number + * formatting pattern. In the case of the default locale, it will be 3. + * @returns {string} Number rounded to decimalPlaces and places a “,†after each third digit. * - * // The blacklist overrides the whitelist so the open redirect here is blocked. - * $sceDelegateProvider.resourceUrlBlacklist([ - * 'http://myapp.example.com/clickThru**' - * ]); - * }); - * ``` + * @example + <example module="numberFilterExample"> + <file name="index.html"> + <script> + angular.module('numberFilterExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.val = 1234.56789; + }]); + </script> + <div ng-controller="ExampleController"> + <label>Enter number: <input ng-model='val'></label><br> + Default formatting: <span id='number-default'>{{val | number}}</span><br> + No fractions: <span>{{val | number:0}}</span><br> + Negative number: <span>{{-val | number:4}}</span> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should format numbers', function() { + expect(element(by.id('number-default')).getText()).toBe('1,234.568'); + expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); + }); + + it('should update', function() { + element(by.model('val')).clear(); + element(by.model('val')).sendKeys('3374.333'); + expect(element(by.id('number-default')).getText()).toBe('3,374.333'); + expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); + expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); + }); + </file> + </example> */ -function $SceDelegateProvider() { - this.SCE_CONTEXTS = SCE_CONTEXTS; - // Resource URLs can also be trusted by policy. - var resourceUrlWhitelist = ['self'], - resourceUrlBlacklist = []; +numberFilter.$inject = ['$locale']; +function numberFilter($locale) { + var formats = $locale.NUMBER_FORMATS; + return function(number, fractionSize) { - /** - * @ngdoc method - * @name $sceDelegateProvider#resourceUrlWhitelist - * @kind function - * - * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored. - * - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array. - * - * Note: **an empty whitelist array will block all URLs**! - * - * @return {Array} the currently set whitelist array. - * - * The **default value** when no whitelist has been explicitly set is `['self']` allowing only - * same origin resource requests. - * - * @description - * Sets/Gets the whitelist of trusted resource URLs. - */ - this.resourceUrlWhitelist = function(value) { - if (arguments.length) { - resourceUrlWhitelist = adjustMatchers(value); - } - return resourceUrlWhitelist; + // if null or undefined pass it through + return (number == null) + ? number + : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, + fractionSize); }; +} - /** - * @ngdoc method - * @name $sceDelegateProvider#resourceUrlBlacklist - * @kind function - * - * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored. - * - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array. - * - * The typical usage for the blacklist is to **block - * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as - * these would otherwise be trusted but actually return content from the redirected domain. - * - * Finally, **the blacklist overrides the whitelist** and has the final say. - * - * @return {Array} the currently set blacklist array. - * - * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there - * is no blacklist.) - * - * @description - * Sets/Gets the blacklist of trusted resource URLs. - */ +var DECIMAL_SEP = '.'; +function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { + if (isObject(number)) return ''; - this.resourceUrlBlacklist = function(value) { - if (arguments.length) { - resourceUrlBlacklist = adjustMatchers(value); + var isNegative = number < 0; + number = Math.abs(number); + + var isInfinity = number === Infinity; + if (!isInfinity && !isFinite(number)) return ''; + + var numStr = number + '', + formatedText = '', + hasExponent = false, + parts = []; + + if (isInfinity) formatedText = '\u221e'; + + if (!isInfinity && numStr.indexOf('e') !== -1) { + var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); + if (match && match[2] == '-' && match[3] > fractionSize + 1) { + number = 0; + } else { + formatedText = numStr; + hasExponent = true; } - return resourceUrlBlacklist; - }; + } - this.$get = ['$injector', function($injector) { + if (!isInfinity && !hasExponent) { + var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; - var htmlSanitizer = function htmlSanitizer(html) { - throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); - }; + // determine fractionSize if it is not specified + if (isUndefined(fractionSize)) { + fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); + } - if ($injector.has('$sanitize')) { - htmlSanitizer = $injector.get('$sanitize'); + // safely round numbers in JS without hitting imprecisions of floating-point arithmetics + // inspired by: + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round + number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize); + + var fraction = ('' + number).split(DECIMAL_SEP); + var whole = fraction[0]; + fraction = fraction[1] || ''; + + var i, pos = 0, + lgroup = pattern.lgSize, + group = pattern.gSize; + + if (whole.length >= (lgroup + group)) { + pos = whole.length - lgroup; + for (i = 0; i < pos; i++) { + if ((pos - i) % group === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + } + + for (i = pos; i < whole.length; i++) { + if ((whole.length - i) % lgroup === 0 && i !== 0) { + formatedText += groupSep; + } + formatedText += whole.charAt(i); + } + + // format fraction part. + while (fraction.length < fractionSize) { + fraction += '0'; + } + + if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); + } else { + if (fractionSize > 0 && number < 1) { + formatedText = number.toFixed(fractionSize); + number = parseFloat(formatedText); + } + } + + if (number === 0) { + isNegative = false; + } + + parts.push(isNegative ? pattern.negPre : pattern.posPre, + formatedText, + isNegative ? pattern.negSuf : pattern.posSuf); + return parts.join(''); +} + +function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while (num.length < digits) num = '0' + num; + if (trim) { + num = num.substr(num.length - digits); + } + return neg + num; +} + + +function dateGetter(name, size, offset, trim) { + offset = offset || 0; + return function(date) { + var value = date['get' + name](); + if (offset > 0 || value > -offset) { + value += offset; } + if (value === 0 && offset == -12) value = 12; + return padNumber(value, size, trim); + }; +} + +function dateStrGetter(name, shortForm) { + return function(date, formats) { + var value = date['get' + name](); + var get = uppercase(shortForm ? ('SHORT' + name) : name); + + return formats[get][value]; + }; +} +function timeZoneGetter(date, formats, offset) { + var zone = -1 * offset; + var paddedZone = (zone >= 0) ? "+" : ""; - function matchUrl(matcher, parsedUrl) { - if (matcher === 'self') { - return urlIsSameOrigin(parsedUrl); - } else { - // definitely a regex. See adjustMatchers() - return !!matcher.exec(parsedUrl.href); - } - } + paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + + padNumber(Math.abs(zone % 60), 2); - function isResourceUrlAllowedByPolicy(url) { - var parsedUrl = urlResolve(url.toString()); - var i, n, allowed = false; - // Ensure that at least one item from the whitelist allows this url. - for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { - if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { - allowed = true; - break; - } - } - if (allowed) { - // Ensure that no item from the blacklist blocked this url. - for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { - if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { - allowed = false; - break; - } - } - } - return allowed; - } + return paddedZone; +} - function generateHolderType(Base) { - var holderType = function TrustedValueHolderType(trustedValue) { - this.$$unwrapTrustedValue = function() { - return trustedValue; - }; - }; - if (Base) { - holderType.prototype = new Base(); - } - holderType.prototype.valueOf = function sceValueOf() { - return this.$$unwrapTrustedValue(); - }; - holderType.prototype.toString = function sceToString() { - return this.$$unwrapTrustedValue().toString(); - }; - return holderType; - } +function getFirstThursdayOfYear(year) { + // 0 = index of January + var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay(); + // 4 = index of Thursday (+1 to account for 1st = 5) + // 11 = index of *next* Thursday (+1 account for 1st = 12) + return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst); +} - var trustedValueHolderBase = generateHolderType(), - byType = {}; +function getThursdayThisWeek(datetime) { + return new Date(datetime.getFullYear(), datetime.getMonth(), + // 4 = index of Thursday + datetime.getDate() + (4 - datetime.getDay())); +} - byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); +function weekGetter(size) { + return function(date) { + var firstThurs = getFirstThursdayOfYear(date.getFullYear()), + thisThurs = getThursdayThisWeek(date); - /** - * @ngdoc method - * @name $sceDelegate#trustAs - * - * @description - * Returns an object that is trusted by angular for use in specified strict - * contextual escaping contexts (such as ng-bind-html, ng-include, any src - * attribute interpolation, any dom event binding attribute interpolation - * such as for onclick, etc.) that uses the provided value. - * See {@link ng.$sce $sce} for enabling strict contextual escaping. - * - * @param {string} type The kind of context in which this value is safe for use. e.g. url, - * resourceUrl, html, js and css. - * @param {*} value The value that that should be considered trusted/safe. - * @returns {*} A value that can be used to stand in for the provided `value` in places - * where Angular expects a $sce.trustAs() return value. - */ - function trustAs(type, trustedValue) { - var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null); - if (!Constructor) { - throw $sceMinErr('icontext', - 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', - type, trustedValue); - } - if (trustedValue === null || trustedValue === undefined || trustedValue === '') { - return trustedValue; - } - // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting - // mutable objects, we ensure here that the value passed in is actually a string. - if (typeof trustedValue !== 'string') { - throw $sceMinErr('itype', - 'Attempted to trust a non-string value in a content requiring a string: Context: {0}', - type); - } - return new Constructor(trustedValue); - } + var diff = +thisThurs - +firstThurs, + result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week - /** - * @ngdoc method - * @name $sceDelegate#valueOf - * - * @description - * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link - * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. - * - * If the passed parameter is not a value that had been returned by {@link - * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is. - * - * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} - * call or anything else. - * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns - * `value` unchanged. - */ - function valueOf(maybeTrusted) { - if (maybeTrusted instanceof trustedValueHolderBase) { - return maybeTrusted.$$unwrapTrustedValue(); - } else { - return maybeTrusted; - } - } + return padNumber(result, size); + }; +} - /** - * @ngdoc method - * @name $sceDelegate#getTrusted - * - * @description - * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and - * returns the originally supplied value if the queried context type is a supertype of the - * created type. If this condition isn't satisfied, throws an exception. - * - * @param {string} type The kind of context in which this value is to be used. - * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`} call. - * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception. - */ - function getTrusted(type, maybeTrusted) { - if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') { - return maybeTrusted; - } - var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); - if (constructor && maybeTrusted instanceof constructor) { - return maybeTrusted.$$unwrapTrustedValue(); - } - // If we get here, then we may only take one of two actions. - // 1. sanitize the value for the requested type, or - // 2. throw an exception. - if (type === SCE_CONTEXTS.RESOURCE_URL) { - if (isResourceUrlAllowedByPolicy(maybeTrusted)) { - return maybeTrusted; - } else { - throw $sceMinErr('insecurl', - 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', - maybeTrusted.toString()); - } - } else if (type === SCE_CONTEXTS.HTML) { - return htmlSanitizer(maybeTrusted); - } - throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); - } +function ampmGetter(date, formats) { + return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; +} - return { trustAs: trustAs, - getTrusted: getTrusted, - valueOf: valueOf }; - }]; +function eraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; } +function longEraGetter(date, formats) { + return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; +} -/** - * @ngdoc provider - * @name $sceProvider - * @description - * - * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service. - * - enable/disable Strict Contextual Escaping (SCE) in a module - * - override the default implementation with a custom delegate - * - * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. - */ +var DATE_FORMATS = { + yyyy: dateGetter('FullYear', 4), + yy: dateGetter('FullYear', 2, 0, true), + y: dateGetter('FullYear', 1), + MMMM: dateStrGetter('Month'), + MMM: dateStrGetter('Month', true), + MM: dateGetter('Month', 2, 1), + M: dateGetter('Month', 1, 1), + dd: dateGetter('Date', 2), + d: dateGetter('Date', 1), + HH: dateGetter('Hours', 2), + H: dateGetter('Hours', 1), + hh: dateGetter('Hours', 2, -12), + h: dateGetter('Hours', 1, -12), + mm: dateGetter('Minutes', 2), + m: dateGetter('Minutes', 1), + ss: dateGetter('Seconds', 2), + s: dateGetter('Seconds', 1), + // while ISO 8601 requires fractions to be prefixed with `.` or `,` + // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions + sss: dateGetter('Milliseconds', 3), + EEEE: dateStrGetter('Day'), + EEE: dateStrGetter('Day', true), + a: ampmGetter, + Z: timeZoneGetter, + ww: weekGetter(2), + w: weekGetter(1), + G: eraGetter, + GG: eraGetter, + GGG: eraGetter, + GGGG: longEraGetter +}; -/* jshint maxlen: false*/ +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/, + NUMBER_STRING = /^\-?\d+$/; /** - * @ngdoc service - * @name $sce + * @ngdoc filter + * @name date * @kind function * * @description + * Formats `date` to a string based on the requested `format`. * - * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS. - * - * # Strict Contextual Escaping - * - * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain - * contexts to result in a value that is marked as safe to use for that context. One example of - * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer - * to these contexts as privileged or SCE contexts. - * - * As of version 1.2, Angular ships with SCE enabled by default. - * - * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow - * one to execute arbitrary javascript by the use of the expression() syntax. Refer - * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them. - * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>` - * to the top of your HTML document. - * - * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for - * security vulnerabilities such as XSS, clickjacking, etc. a lot easier. - * - * Here's an example of a binding in a privileged context: - * - * ``` - * <input ng-model="userHtml"> - * <div ng-bind-html="userHtml"></div> - * ``` - * - * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE - * disabled, this application allows the user to render arbitrary HTML into the DIV. - * In a more realistic example, one may be rendering user comments, blog articles, etc. via - * bindings. (HTML is just one example of a context where rendering user controlled input creates - * security vulnerabilities.) - * - * For the case of HTML, you might use a library, either on the client side, or on the server side, - * to sanitize unsafe HTML before binding to the value and rendering it in the document. - * - * How would you ensure that every place that used these types of bindings was bound to a value that - * was sanitized by your library (or returned as safe for rendering by your server?) How can you - * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some - * properties/fields and forgot to update the binding to the sanitized value? - * - * To be secure by default, you want to ensure that any such bindings are disallowed unless you can - * determine that something explicitly says it's safe to use a value for binding in that - * context. You can then audit your code (a simple grep would do) to ensure that this is only done - * for those values that you can easily tell are safe - because they were received from your server, - * sanitized by your library, etc. You can organize your codebase to help with this - perhaps - * allowing only the files in a specific directory to do this. Ensuring that the internal API - * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task. - * - * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs} - * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to - * obtain values that will be accepted by SCE / privileged contexts. - * - * - * ## How does it work? - * - * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted - * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link - * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the - * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. - * - * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link - * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly - * simplified): - * - * ``` - * var ngBindHtmlDirective = ['$sce', function($sce) { - * return function(scope, element, attr) { - * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) { - * element.html(value || ''); - * }); - * }; - * }]; - * ``` - * - * ## Impact on loading templates - * - * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as - * `templateUrl`'s specified by {@link guide/directive directives}. - * - * By default, Angular only loads templates from the same domain and protocol as the application - * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl - * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or - * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist - * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. - * - * *Please note*: - * The browser's - * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) - * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) - * policy apply in addition to this and may further restrict whether the template is successfully - * loaded. This means that without the right CORS policy, loading templates from a different domain - * won't work on all browsers. Also, loading templates from `file://` URL does not work on some - * browsers. - * - * ## This feels like too much overhead - * - * It's important to remember that SCE only applies to interpolation expressions. - * - * If your expressions are constant literals, they're automatically trusted and you don't need to - * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g. - * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works. - * - * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them - * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here. - * - * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load - * templates in `ng-include` from your application's domain without having to even know about SCE. - * It blocks loading templates from other domains or loading templates over http from an https - * served document. You can change these by setting your own custom {@link - * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link - * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs. - * - * This significantly reduces the overhead. It is far easier to pay the small overhead and have an - * application that's secure and can be audited to verify that with much more ease than bolting - * security onto an application later. - * - * <a name="contexts"></a> - * ## What trusted context types are supported? - * - * | Context | Notes | - * |---------------------|----------------| - * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. | - * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | - * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. | - * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. | - * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | - * - * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a> - * - * Each element in these arrays must be one of the following: - * - * - **'self'** - * - The special **string**, `'self'`, can be used to match against all URLs of the **same - * domain** as the application document using the **same protocol**. - * - **String** (except the special value `'self'`) - * - The string is matched against the full *normalized / absolute URL* of the resource - * being tested (substring matches are not good enough.) - * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters - * match themselves. - * - `*`: matches zero or more occurrences of any character other than one of the following 6 - * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use - * in a whitelist. - * - `**`: matches zero or more occurrences of *any* character. As such, it's not - * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g. - * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might - * not have been the intention.) Its usage at the very end of the path is ok. (e.g. - * http://foo.example.com/templates/**). - * - **RegExp** (*see caveat below*) - * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax - * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to - * accidentally introduce a bug when one updates a complex expression (imho, all regexes should - * have good test coverage.). For instance, the use of `.` in the regex is correct only in a - * small number of cases. A `.` character in the regex used when matching the scheme or a - * subdomain could be matched against a `:` or literal `.` that was likely not intended. It - * is highly recommended to use the string patterns and only fall back to regular expressions - * if they as a last resort. - * - The regular expression must be an instance of RegExp (i.e. not a string.) It is - * matched against the **entire** *normalized / absolute URL* of the resource being tested - * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags - * present on the RegExp (such as multiline, global, ignoreCase) are ignored. - * - If you are generating your JavaScript from some other templating engine (not - * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), - * remember to escape your regular expression (and be aware that you might need more than - * one level of escaping depending on your templating engine and the way you interpolated - * the value.) Do make use of your platform's escaping mechanism as it might be good - * enough before coding your own. e.g. Ruby has - * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) - * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). - * Javascript lacks a similar built in function for escaping. Take a look at Google - * Closure library's [goog.string.regExpEscape(s)]( - * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962). - * - * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example. - * - * ## Show me an example using SCE. - * - * <example module="mySceApp" deps="angular-sanitize.js"> - * <file name="index.html"> - * <div ng-controller="AppController as myCtrl"> - * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br> - * <b>User comments</b><br> - * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when - * $sanitize is available. If $sanitize isn't available, this results in an error instead of an - * exploit. - * <div class="well"> - * <div ng-repeat="userComment in myCtrl.userComments"> - * <b>{{userComment.name}}</b>: - * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span> - * <br> - * </div> - * </div> - * </div> - * </file> - * - * <file name="script.js"> - * angular.module('mySceApp', ['ngSanitize']) - * .controller('AppController', ['$http', '$templateCache', '$sce', - * function($http, $templateCache, $sce) { - * var self = this; - * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { - * self.userComments = userComments; - * }); - * self.explicitlyTrustedHtml = $sce.trustAsHtml( - * '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' + - * 'sanitization."">Hover over this text.</span>'); - * }]); - * </file> - * - * <file name="test_data.json"> - * [ - * { "name": "Alice", - * "htmlComment": - * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>" - * }, - * { "name": "Bob", - * "htmlComment": "<i>Yes!</i> Am I the only other one?" - * } - * ] - * </file> - * - * <file name="protractor.js" type="protractor"> - * describe('SCE doc demo', function() { - * it('should sanitize untrusted values', function() { - * expect(element.all(by.css('.htmlComment')).first().getInnerHtml()) - * .toBe('<span>Is <i>anyone</i> reading this?</span>'); - * }); - * - * it('should NOT sanitize explicitly trusted values', function() { - * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe( - * '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' + - * 'sanitization."">Hover over this text.</span>'); - * }); - * }); - * </file> - * </example> - * + * `format` string can be composed of the following elements: * + * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) + * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) + * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) + * * `'MMMM'`: Month in year (January-December) + * * `'MMM'`: Month in year (Jan-Dec) + * * `'MM'`: Month in year, padded (01-12) + * * `'M'`: Month in year (1-12) + * * `'dd'`: Day in month, padded (01-31) + * * `'d'`: Day in month (1-31) + * * `'EEEE'`: Day in Week,(Sunday-Saturday) + * * `'EEE'`: Day in Week, (Sun-Sat) + * * `'HH'`: Hour in day, padded (00-23) + * * `'H'`: Hour in day (0-23) + * * `'hh'`: Hour in AM/PM, padded (01-12) + * * `'h'`: Hour in AM/PM, (1-12) + * * `'mm'`: Minute in hour, padded (00-59) + * * `'m'`: Minute in hour (0-59) + * * `'ss'`: Second in minute, padded (00-59) + * * `'s'`: Second in minute (0-59) + * * `'sss'`: Millisecond in second, padded (000-999) + * * `'a'`: AM/PM marker + * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) + * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year + * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year + * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD') + * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini') * - * ## Can I disable SCE completely? + * `format` string can also be one of the following predefined + * {@link guide/i18n localizable formats}: * - * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits - * for little coding overhead. It will be much harder to take an SCE disabled application and - * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE - * for cases where you have a lot of existing code that was written before SCE was introduced and - * you're migrating them a module at a time. + * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale + * (e.g. Sep 3, 2010 12:05:08 PM) + * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM) + * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale + * (e.g. Friday, September 3, 2010) + * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010) + * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) + * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) + * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM) + * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM) * - * That said, here's how you can completely disable SCE: + * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g. + * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence + * (e.g. `"h 'o''clock'"`). * - * ``` - * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) { - * // Completely disable SCE. For demonstration purposes only! - * // Do not use in new projects. - * $sceProvider.enabled(false); - * }); - * ``` + * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or + * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its + * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is + * specified in the string input, the time is considered to be in the local timezone. + * @param {string=} format Formatting rules (see Description). If not specified, + * `mediumDate` is used. + * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) + * If not specified, the timezone of the browser will be used. + * @returns {string} Formatted string or the input if input is not recognized as date/millis. * + * @example + <example> + <file name="index.html"> + <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>: + <span>{{1288323623006 | date:'medium'}}</span><br> + <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>: + <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br> + <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>: + <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br> + <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>: + <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br> + </file> + <file name="protractor.js" type="protractor"> + it('should format date', function() { + expect(element(by.binding("1288323623006 | date:'medium'")).getText()). + toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); + expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). + toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); + expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). + toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); + expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()). + toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/); + }); + </file> + </example> */ -/* jshint maxlen: 100 */ +dateFilter.$inject = ['$locale']; +function dateFilter($locale) { -function $SceProvider() { - var enabled = true; - /** - * @ngdoc method - * @name $sceProvider#enabled - * @kind function - * - * @param {boolean=} value If provided, then enables/disables SCE. - * @return {boolean} true if SCE is enabled, false otherwise. - * - * @description - * Enables/disables SCE and returns the current value. - */ - this.enabled = function(value) { - if (arguments.length) { - enabled = !!value; + var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; + // 1 2 3 4 5 6 7 8 9 10 11 + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8601_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0, + dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, + timeSetter = match[8] ? date.setUTCHours : date.setHours; + + if (match[9]) { + tzHour = toInt(match[9] + match[10]); + tzMin = toInt(match[9] + match[11]); + } + dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3])); + var h = toInt(match[4] || 0) - tzHour; + var m = toInt(match[5] || 0) - tzMin; + var s = toInt(match[6] || 0); + var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); + timeSetter.call(date, h, m, s, ms); + return date; } - return enabled; - }; + return string; + } - /* Design notes on the default implementation for SCE. - * - * The API contract for the SCE delegate - * ------------------------------------- - * The SCE delegate object must provide the following 3 methods: - * - * - trustAs(contextEnum, value) - * This method is used to tell the SCE service that the provided value is OK to use in the - * contexts specified by contextEnum. It must return an object that will be accepted by - * getTrusted() for a compatible contextEnum and return this value. - * - * - valueOf(value) - * For values that were not produced by trustAs(), return them as is. For values that were - * produced by trustAs(), return the corresponding input value to trustAs. Basically, if - * trustAs is wrapping the given values into some type, this operation unwraps it when given - * such a value. - * - * - getTrusted(contextEnum, value) - * This function should return the a value that is safe to use in the context specified by - * contextEnum or throw and exception otherwise. - * - * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be - * opaque or wrapped in some holder object. That happens to be an implementation detail. For - * instance, an implementation could maintain a registry of all trusted objects by context. In - * such a case, trustAs() would return the same object that was passed in. getTrusted() would - * return the same object passed in if it was found in the registry under a compatible context or - * throw an exception otherwise. An implementation might only wrap values some of the time based - * on some criteria. getTrusted() might return a value and not throw an exception for special - * constants or objects even if not wrapped. All such implementations fulfill this contract. - * - * - * A note on the inheritance model for SCE contexts - * ------------------------------------------------ - * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This - * is purely an implementation details. - * - * The contract is simply this: - * - * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value) - * will also succeed. - * - * Inheritance happens to capture this in a natural way. In some future, we - * may not use inheritance anymore. That is OK because no code outside of - * sce.js and sceSpecs.js would need to be aware of this detail. - */ + return function(date, format, timezone) { + var text = '', + parts = [], + fn, match; - this.$get = ['$parse', '$sceDelegate', function( - $parse, $sceDelegate) { - // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow - // the "expression(javascript expression)" syntax which is insecure. - if (enabled && msie < 8) { - throw $sceMinErr('iequirks', - 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' + - 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' + - 'document. See http://docs.angularjs.org/api/ng.$sce for more information.'); + format = format || 'mediumDate'; + format = $locale.DATETIME_FORMATS[format] || format; + if (isString(date)) { + date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date); } - var sce = shallowCopy(SCE_CONTEXTS); - - /** - * @ngdoc method - * @name $sce#isEnabled - * @kind function - * - * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you - * have to do it at module config time on {@link ng.$sceProvider $sceProvider}. - * - * @description - * Returns a boolean indicating if SCE is enabled. - */ - sce.isEnabled = function() { - return enabled; - }; - sce.trustAs = $sceDelegate.trustAs; - sce.getTrusted = $sceDelegate.getTrusted; - sce.valueOf = $sceDelegate.valueOf; + if (isNumber(date)) { + date = new Date(date); + } - if (!enabled) { - sce.trustAs = sce.getTrusted = function(type, value) { return value; }; - sce.valueOf = identity; + if (!isDate(date) || !isFinite(date.getTime())) { + return date; } - /** - * @ngdoc method - * @name $sce#parseAs - * - * @description - * Converts Angular {@link guide/expression expression} into a function. This is like {@link - * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it - * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*, - * *result*)} - * - * @param {string} type The kind of SCE context in which this result will be used. - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - */ - sce.parseAs = function sceParseAs(type, expr) { - var parsed = $parse(expr); - if (parsed.literal && parsed.constant) { - return parsed; + while (format) { + match = DATE_FORMATS_SPLIT.exec(format); + if (match) { + parts = concat(parts, match, 1); + format = parts.pop(); } else { - return $parse(expr, function(value) { - return sce.getTrusted(type, value); - }); + parts.push(format); + format = null; } - }; - - /** - * @ngdoc method - * @name $sce#trustAs - * - * @description - * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, - * returns an object that is trusted by angular for use in specified strict contextual - * escaping contexts (such as ng-bind-html, ng-include, any src attribute - * interpolation, any dom event binding attribute interpolation such as for onclick, etc.) - * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual - * escaping. - * - * @param {string} type The kind of context in which this value is safe for use. e.g. url, - * resource_url, html, js and css. - * @param {*} value The value that that should be considered trusted/safe. - * @returns {*} A value that can be used to stand in for the provided `value` in places - * where Angular expects a $sce.trustAs() return value. - */ - - /** - * @ngdoc method - * @name $sce#trustAsHtml - * - * @description - * Shorthand method. `$sce.trustAsHtml(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`} - * - * @param {*} value The value to trustAs. - * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml - * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives - * only accept expressions that are either literal constants or are the - * return value of {@link ng.$sce#trustAs $sce.trustAs}.) - */ - - /** - * @ngdoc method - * @name $sce#trustAsUrl - * - * @description - * Shorthand method. `$sce.trustAsUrl(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`} - * - * @param {*} value The value to trustAs. - * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl - * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives - * only accept expressions that are either literal constants or are the - * return value of {@link ng.$sce#trustAs $sce.trustAs}.) - */ - - /** - * @ngdoc method - * @name $sce#trustAsResourceUrl - * - * @description - * Shorthand method. `$sce.trustAsResourceUrl(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} - * - * @param {*} value The value to trustAs. - * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl - * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives - * only accept expressions that are either literal constants or are the return - * value of {@link ng.$sce#trustAs $sce.trustAs}.) - */ - - /** - * @ngdoc method - * @name $sce#trustAsJs - * - * @description - * Shorthand method. `$sce.trustAsJs(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`} - * - * @param {*} value The value to trustAs. - * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs - * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives - * only accept expressions that are either literal constants or are the - * return value of {@link ng.$sce#trustAs $sce.trustAs}.) - */ - - /** - * @ngdoc method - * @name $sce#getTrusted - * - * @description - * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such, - * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the - * originally supplied value if the queried context type is a supertype of the created type. - * If this condition isn't satisfied, throws an exception. - * - * @param {string} type The kind of context in which this value is to be used. - * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`} - * call. - * @returns {*} The value the was originally provided to - * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context. - * Otherwise, throws an exception. - */ - - /** - * @ngdoc method - * @name $sce#getTrustedHtml - * - * @description - * Shorthand method. `$sce.getTrustedHtml(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedCss - * - * @description - * Shorthand method. `$sce.getTrustedCss(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedUrl - * - * @description - * Shorthand method. `$sce.getTrustedUrl(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedResourceUrl - * - * @description - * Shorthand method. `$sce.getTrustedResourceUrl(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} - * - * @param {*} value The value to pass to `$sceDelegate.getTrusted`. - * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedJs - * - * @description - * Shorthand method. `$sce.getTrustedJs(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)` - */ - - /** - * @ngdoc method - * @name $sce#parseAsHtml - * - * @description - * Shorthand method. `$sce.parseAsHtml(expression string)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`} - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - */ + } - /** - * @ngdoc method - * @name $sce#parseAsCss - * - * @description - * Shorthand method. `$sce.parseAsCss(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`} - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - */ + var dateTimezoneOffset = date.getTimezoneOffset(); + if (timezone) { + dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset()); + date = convertTimezoneToLocal(date, timezone, true); + } + forEach(parts, function(value) { + fn = DATE_FORMATS[value]; + text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) + : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); + }); - /** - * @ngdoc method - * @name $sce#parseAsUrl - * - * @description - * Shorthand method. `$sce.parseAsUrl(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`} - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - */ + return text; + }; +} - /** - * @ngdoc method - * @name $sce#parseAsResourceUrl - * - * @description - * Shorthand method. `$sce.parseAsResourceUrl(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`} - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - */ - /** - * @ngdoc method - * @name $sce#parseAsJs - * - * @description - * Shorthand method. `$sce.parseAsJs(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`} - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - */ +/** + * @ngdoc filter + * @name json + * @kind function + * + * @description + * Allows you to convert a JavaScript object into JSON string. + * + * This filter is mostly useful for debugging. When using the double curly {{value}} notation + * the binding is automatically converted to JSON. + * + * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. + * @param {number=} spacing The number of spaces to use per indentation, defaults to 2. + * @returns {string} JSON string. + * + * + * @example + <example> + <file name="index.html"> + <pre id="default-spacing">{{ {'name':'value'} | json }}</pre> + <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre> + </file> + <file name="protractor.js" type="protractor"> + it('should jsonify filtered objects', function() { + expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); + }); + </file> + </example> + * + */ +function jsonFilter() { + return function(object, spacing) { + if (isUndefined(spacing)) { + spacing = 2; + } + return toJson(object, spacing); + }; +} - // Shorthand delegations. - var parse = sce.parseAs, - getTrusted = sce.getTrusted, - trustAs = sce.trustAs; - forEach(SCE_CONTEXTS, function(enumValue, name) { - var lName = lowercase(name); - sce[camelCase("parse_as_" + lName)] = function(expr) { - return parse(enumValue, expr); - }; - sce[camelCase("get_trusted_" + lName)] = function(value) { - return getTrusted(enumValue, value); - }; - sce[camelCase("trust_as_" + lName)] = function(value) { - return trustAs(enumValue, value); - }; - }); +/** + * @ngdoc filter + * @name lowercase + * @kind function + * @description + * Converts string to lowercase. + * @see angular.lowercase + */ +var lowercaseFilter = valueFn(lowercase); - return sce; - }]; -} /** - * !!! This is an undocumented "private" service !!! - * - * @name $sniffer - * @requires $window - * @requires $document - * - * @property {boolean} history Does the browser support html5 history api ? - * @property {boolean} transitions Does the browser support CSS transition events ? - * @property {boolean} animations Does the browser support CSS animation events ? - * + * @ngdoc filter + * @name uppercase + * @kind function * @description - * This is very simple implementation of testing browser's features. + * Converts string to uppercase. + * @see angular.uppercase */ -function $SnifferProvider() { - this.$get = ['$window', '$document', function($window, $document) { - var eventSupport = {}, - android = - int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), - boxee = /Boxee/i.test(($window.navigator || {}).userAgent), - document = $document[0] || {}, - vendorPrefix, - vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/, - bodyStyle = document.body && document.body.style, - transitions = false, - animations = false, - match; +var uppercaseFilter = valueFn(uppercase); - if (bodyStyle) { - for (var prop in bodyStyle) { - if (match = vendorRegex.exec(prop)) { - vendorPrefix = match[0]; - vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1); - break; - } - } +/** + * @ngdoc filter + * @name limitTo + * @kind function + * + * @description + * Creates a new array or string containing only a specified number of elements. The elements + * are taken from either the beginning or the end of the source array, string or number, as specified by + * the value and sign (positive or negative) of `limit`. If a number is used as input, it is + * converted to a string. + * + * @param {Array|string|number} input Source array, string or number to be limited. + * @param {string|number} limit The length of the returned array or string. If the `limit` number + * is positive, `limit` number of items from the beginning of the source array/string are copied. + * If the number is negative, `limit` number of items from the end of the source array/string + * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined, + * the input will be returned unchanged. + * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin` + * indicates an offset from the end of `input`. Defaults to `0`. + * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array + * had less than `limit` elements. + * + * @example + <example module="limitToExample"> + <file name="index.html"> + <script> + angular.module('limitToExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.numbers = [1,2,3,4,5,6,7,8,9]; + $scope.letters = "abcdefghi"; + $scope.longNumber = 2345432342; + $scope.numLimit = 3; + $scope.letterLimit = 3; + $scope.longNumberLimit = 3; + }]); + </script> + <div ng-controller="ExampleController"> + <label> + Limit {{numbers}} to: + <input type="number" step="1" ng-model="numLimit"> + </label> + <p>Output numbers: {{ numbers | limitTo:numLimit }}</p> + <label> + Limit {{letters}} to: + <input type="number" step="1" ng-model="letterLimit"> + </label> + <p>Output letters: {{ letters | limitTo:letterLimit }}</p> + <label> + Limit {{longNumber}} to: + <input type="number" step="1" ng-model="longNumberLimit"> + </label> + <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p> + </div> + </file> + <file name="protractor.js" type="protractor"> + var numLimitInput = element(by.model('numLimit')); + var letterLimitInput = element(by.model('letterLimit')); + var longNumberLimitInput = element(by.model('longNumberLimit')); + var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); + var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); + var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit')); - if (!vendorPrefix) { - vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit'; - } + it('should limit the number array to first three items', function() { + expect(numLimitInput.getAttribute('value')).toBe('3'); + expect(letterLimitInput.getAttribute('value')).toBe('3'); + expect(longNumberLimitInput.getAttribute('value')).toBe('3'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); + expect(limitedLetters.getText()).toEqual('Output letters: abc'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 234'); + }); - transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle)); - animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle)); + // There is a bug in safari and protractor that doesn't like the minus key + // it('should update the output when -3 is entered', function() { + // numLimitInput.clear(); + // numLimitInput.sendKeys('-3'); + // letterLimitInput.clear(); + // letterLimitInput.sendKeys('-3'); + // longNumberLimitInput.clear(); + // longNumberLimitInput.sendKeys('-3'); + // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); + // expect(limitedLetters.getText()).toEqual('Output letters: ghi'); + // expect(limitedLongNumber.getText()).toEqual('Output long number: 342'); + // }); - if (android && (!transitions || !animations)) { - transitions = isString(document.body.style.webkitTransition); - animations = isString(document.body.style.webkitAnimation); - } + it('should not exceed the maximum size of input array', function() { + numLimitInput.clear(); + numLimitInput.sendKeys('100'); + letterLimitInput.clear(); + letterLimitInput.sendKeys('100'); + longNumberLimitInput.clear(); + longNumberLimitInput.sendKeys('100'); + expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); + expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); + expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342'); + }); + </file> + </example> +*/ +function limitToFilter() { + return function(input, limit, begin) { + if (Math.abs(Number(limit)) === Infinity) { + limit = Number(limit); + } else { + limit = toInt(limit); } + if (isNaN(limit)) return input; + if (isNumber(input)) input = input.toString(); + if (!isArray(input) && !isString(input)) return input; - return { - // Android has history.pushState, but it does not update location correctly - // so let's not use the history API at all. - // http://code.google.com/p/android/issues/detail?id=17471 - // https://github.com/angular/angular.js/issues/904 - - // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has - // so let's not use the history API also - // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined - // jshint -W018 - history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee), - // jshint +W018 - hasEvent: function(event) { - // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have - // it. In particular the event is not fired when backspace or delete key are pressed or - // when cut operation is performed. - // IE10+ implements 'input' event but it erroneously fires under various situations, - // e.g. when placeholder changes, or a form is focused. - if (event === 'input' && msie <= 11) return false; - - if (isUndefined(eventSupport[event])) { - var divElm = document.createElement('div'); - eventSupport[event] = 'on' + event in divElm; - } + begin = (!begin || isNaN(begin)) ? 0 : toInt(begin); + begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin; - return eventSupport[event]; - }, - csp: csp(), - vendorPrefix: vendorPrefix, - transitions: transitions, - animations: animations, - android: android - }; - }]; + if (limit >= 0) { + return input.slice(begin, begin + limit); + } else { + if (begin === 0) { + return input.slice(limit, input.length); + } else { + return input.slice(Math.max(0, begin + limit), begin); + } + } + }; } -var $compileMinErr = minErr('$compile'); - /** - * @ngdoc service - * @name $templateRequest + * @ngdoc filter + * @name orderBy + * @kind function * * @description - * The `$templateRequest` service downloads the provided template using `$http` and, upon success, - * stores the contents inside of `$templateCache`. If the HTTP request fails or the response data - * of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted - * by setting the 2nd parameter of the function to true). + * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically + * for strings and numerically for numbers. Note: if you notice numbers are not being sorted + * as expected, make sure they are actually being saved as numbers and not strings. * - * @param {string} tpl The HTTP request template URL - * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty + * @param {Array} array The array to sort. + * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be + * used by the comparator to determine the order of elements. * - * @return {Promise} the HTTP Promise for the given. + * Can be one of: * - * @property {number} totalPendingRequests total amount of pending template requests being downloaded. + * - `function`: Getter function. The result of this function will be sorted using the + * `<`, `===`, `>` operator. + * - `string`: An Angular expression. The result of this expression is used to compare elements + * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by + * 3 first characters of a property called `name`). The result of a constant expression + * is interpreted as a property name to be used in comparisons (for example `"special name"` + * to sort object by the value of their `special name` property). An expression can be + * optionally prefixed with `+` or `-` to control ascending or descending sort order + * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array + * element itself is used to compare where sorting. + * - `Array`: An array of function or string predicates. The first predicate in the array + * is used for sorting, but when two items are equivalent, the next predicate is used. + * + * If the predicate is missing or empty then it defaults to `'+'`. + * + * @param {boolean=} reverse Reverse the order of the array. + * @returns {Array} Sorted copy of the source array. + * + * + * @example + * The example below demonstrates a simple ngRepeat, where the data is sorted + * by age in descending order (predicate is set to `'-age'`). + * `reverse` is not set, which means it defaults to `false`. + <example module="orderByExample"> + <file name="index.html"> + <script> + angular.module('orderByExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.friends = + [{name:'John', phone:'555-1212', age:10}, + {name:'Mary', phone:'555-9876', age:19}, + {name:'Mike', phone:'555-4321', age:21}, + {name:'Adam', phone:'555-5678', age:35}, + {name:'Julie', phone:'555-8765', age:29}]; + }]); + </script> + <div ng-controller="ExampleController"> + <table class="friend"> + <tr> + <th>Name</th> + <th>Phone Number</th> + <th>Age</th> + </tr> + <tr ng-repeat="friend in friends | orderBy:'-age'"> + <td>{{friend.name}}</td> + <td>{{friend.phone}}</td> + <td>{{friend.age}}</td> + </tr> + </table> + </div> + </file> + </example> + * + * The predicate and reverse parameters can be controlled dynamically through scope properties, + * as shown in the next example. + * @example + <example module="orderByExample"> + <file name="index.html"> + <script> + angular.module('orderByExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.friends = + [{name:'John', phone:'555-1212', age:10}, + {name:'Mary', phone:'555-9876', age:19}, + {name:'Mike', phone:'555-4321', age:21}, + {name:'Adam', phone:'555-5678', age:35}, + {name:'Julie', phone:'555-8765', age:29}]; + $scope.predicate = 'age'; + $scope.reverse = true; + $scope.order = function(predicate) { + $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false; + $scope.predicate = predicate; + }; + }]); + </script> + <style type="text/css"> + .sortorder:after { + content: '\25b2'; + } + .sortorder.reverse:after { + content: '\25bc'; + } + </style> + <div ng-controller="ExampleController"> + <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre> + <hr/> + [ <a href="" ng-click="predicate=''">unsorted</a> ] + <table class="friend"> + <tr> + <th> + <a href="" ng-click="order('name')">Name</a> + <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span> + </th> + <th> + <a href="" ng-click="order('phone')">Phone Number</a> + <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span> + </th> + <th> + <a href="" ng-click="order('age')">Age</a> + <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span> + </th> + </tr> + <tr ng-repeat="friend in friends | orderBy:predicate:reverse"> + <td>{{friend.name}}</td> + <td>{{friend.phone}}</td> + <td>{{friend.age}}</td> + </tr> + </table> + </div> + </file> + </example> + * + * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the + * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the + * desired parameters. + * + * Example: + * + * @example + <example module="orderByExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <table class="friend"> + <tr> + <th><a href="" ng-click="reverse=false;order('name', false)">Name</a> + (<a href="" ng-click="order('-name',false)">^</a>)</th> + <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th> + <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th> + </tr> + <tr ng-repeat="friend in friends"> + <td>{{friend.name}}</td> + <td>{{friend.phone}}</td> + <td>{{friend.age}}</td> + </tr> + </table> + </div> + </file> + + <file name="script.js"> + angular.module('orderByExample', []) + .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) { + var orderBy = $filter('orderBy'); + $scope.friends = [ + { name: 'John', phone: '555-1212', age: 10 }, + { name: 'Mary', phone: '555-9876', age: 19 }, + { name: 'Mike', phone: '555-4321', age: 21 }, + { name: 'Adam', phone: '555-5678', age: 35 }, + { name: 'Julie', phone: '555-8765', age: 29 } + ]; + $scope.order = function(predicate, reverse) { + $scope.friends = orderBy($scope.friends, predicate, reverse); + }; + $scope.order('-age',false); + }]); + </file> +</example> */ -function $TemplateRequestProvider() { - this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) { - function handleRequestFn(tpl, ignoreRequestError) { - handleRequestFn.totalPendingRequests++; +orderByFilter.$inject = ['$parse']; +function orderByFilter($parse) { + return function(array, sortPredicate, reverseOrder) { - var transformResponse = $http.defaults && $http.defaults.transformResponse; + if (!(isArrayLike(array))) return array; - if (isArray(transformResponse)) { - transformResponse = transformResponse.filter(function(transformer) { - return transformer !== defaultHttpResponseTransform; - }); - } else if (transformResponse === defaultHttpResponseTransform) { - transformResponse = null; - } + if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; } + if (sortPredicate.length === 0) { sortPredicate = ['+']; } - var httpOptions = { - cache: $templateCache, - transformResponse: transformResponse - }; + var predicates = processPredicates(sortPredicate, reverseOrder); - return $http.get(tpl, httpOptions) - ['finally'](function() { - handleRequestFn.totalPendingRequests--; + // The next three lines are a version of a Swartzian Transform idiom from Perl + // (sometimes called the Decorate-Sort-Undecorate idiom) + // See https://en.wikipedia.org/wiki/Schwartzian_transform + var compareValues = Array.prototype.map.call(array, getComparisonObject); + compareValues.sort(doComparison); + array = compareValues.map(function(item) { return item.value; }); + + return array; + + function getComparisonObject(value, index) { + return { + value: value, + predicateValues: predicates.map(function(predicate) { + return getPredicateValue(predicate.get(value), index); }) - .then(function(response) { - return response.data; - }, handleError); + }; + } - function handleError(resp) { - if (!ignoreRequestError) { - throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl); - } - return $q.reject(resp); + function doComparison(v1, v2) { + var result = 0; + for (var index=0, length = predicates.length; index < length; ++index) { + result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending; + if (result) break; } + return result; } + }; - handleRequestFn.totalPendingRequests = 0; - - return handleRequestFn; - }]; -} - -function $$TestabilityProvider() { - this.$get = ['$rootScope', '$browser', '$location', - function($rootScope, $browser, $location) { - - /** - * @name $testability - * - * @description - * The private $$testability service provides a collection of methods for use when debugging - * or by automated test and debugging tools. - */ - var testability = {}; + function processPredicates(sortPredicate, reverseOrder) { + reverseOrder = reverseOrder ? -1 : 1; + return sortPredicate.map(function(predicate) { + var descending = 1, get = identity; - /** - * @name $$testability#findBindings - * - * @description - * Returns an array of elements that are bound (via ng-bind or {{}}) - * to expressions matching the input. - * - * @param {Element} element The element root to search from. - * @param {string} expression The binding expression to match. - * @param {boolean} opt_exactMatch If true, only returns exact matches - * for the expression. Filters and whitespace are ignored. - */ - testability.findBindings = function(element, expression, opt_exactMatch) { - var bindings = element.getElementsByClassName('ng-binding'); - var matches = []; - forEach(bindings, function(binding) { - var dataBinding = angular.element(binding).data('$binding'); - if (dataBinding) { - forEach(dataBinding, function(bindingName) { - if (opt_exactMatch) { - var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)'); - if (matcher.test(bindingName)) { - matches.push(binding); - } - } else { - if (bindingName.indexOf(expression) != -1) { - matches.push(binding); - } - } - }); + if (isFunction(predicate)) { + get = predicate; + } else if (isString(predicate)) { + if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { + descending = predicate.charAt(0) == '-' ? -1 : 1; + predicate = predicate.substring(1); } - }); - return matches; - }; - - /** - * @name $$testability#findModels - * - * @description - * Returns an array of elements that are two-way found via ng-model to - * expressions matching the input. - * - * @param {Element} element The element root to search from. - * @param {string} expression The model expression to match. - * @param {boolean} opt_exactMatch If true, only returns exact matches - * for the expression. - */ - testability.findModels = function(element, expression, opt_exactMatch) { - var prefixes = ['ng-', 'data-ng-', 'ng\\:']; - for (var p = 0; p < prefixes.length; ++p) { - var attributeEquals = opt_exactMatch ? '=' : '*='; - var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]'; - var elements = element.querySelectorAll(selector); - if (elements.length) { - return elements; + if (predicate !== '') { + get = $parse(predicate); + if (get.constant) { + var key = get(); + get = function(value) { return value[key]; }; + } } } - }; + return { get: get, descending: descending * reverseOrder }; + }); + } - /** - * @name $$testability#getLocation - * - * @description - * Shortcut for getting the location in a browser agnostic way. Returns - * the path, search, and hash. (e.g. /path?a=b#hash) - */ - testability.getLocation = function() { - return $location.url(); - }; + function isPrimitive(value) { + switch (typeof value) { + case 'number': /* falls through */ + case 'boolean': /* falls through */ + case 'string': + return true; + default: + return false; + } + } - /** - * @name $$testability#setLocation - * - * @description - * Shortcut for navigating to a location without doing a full page reload. - * - * @param {string} url The location url (path, search and hash, - * e.g. /path?a=b#hash) to go to. - */ - testability.setLocation = function(url) { - if (url !== $location.url()) { - $location.url(url); - $rootScope.$digest(); + function objectValue(value, index) { + // If `valueOf` is a valid function use that + if (typeof value.valueOf === 'function') { + value = value.valueOf(); + if (isPrimitive(value)) return value; + } + // If `toString` is a valid function and not the one from `Object.prototype` use that + if (hasCustomToString(value)) { + value = value.toString(); + if (isPrimitive(value)) return value; + } + // We have a basic object so we use the position of the object in the collection + return index; + } + + function getPredicateValue(value, index) { + var type = typeof value; + if (value === null) { + type = 'string'; + value = 'null'; + } else if (type === 'string') { + value = value.toLowerCase(); + } else if (type === 'object') { + value = objectValue(value, index); + } + return { value: value, type: type }; + } + + function compare(v1, v2) { + var result = 0; + if (v1.type === v2.type) { + if (v1.value !== v2.value) { + result = v1.value < v2.value ? -1 : 1; } - }; + } else { + result = v1.type < v2.type ? -1 : 1; + } + return result; + } +} - /** - * @name $$testability#whenStable - * - * @description - * Calls the callback when $timeout and $http requests are completed. - * - * @param {function} callback - */ - testability.whenStable = function(callback) { - $browser.notifyWhenNoOutstandingRequests(callback); +function ngDirective(directive) { + if (isFunction(directive)) { + directive = { + link: directive }; - - return testability; - }]; + } + directive.restrict = directive.restrict || 'AC'; + return valueFn(directive); } -function $TimeoutProvider() { - this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', - function($rootScope, $browser, $q, $$q, $exceptionHandler) { - var deferreds = {}; +/** + * @ngdoc directive + * @name a + * @restrict E + * + * @description + * Modifies the default behavior of the html A tag so that the default action is prevented when + * the href attribute is empty. + * + * This change permits the easy creation of action links with the `ngClick` directive + * without changing the location or causing page reloads, e.g.: + * `<a href="" ng-click="list.addItem()">Add Item</a>` + */ +var htmlAnchorDirective = valueFn({ + restrict: 'E', + compile: function(element, attr) { + if (!attr.href && !attr.xlinkHref) { + return function(scope, element) { + // If the linked element is not an anchor tag anymore, do nothing + if (element[0].nodeName.toLowerCase() !== 'a') return; + // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. + var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? + 'xlink:href' : 'href'; + element.on('click', function(event) { + // if we have no href url, then don't navigate anywhere. + if (!element.attr(href)) { + event.preventDefault(); + } + }); + }; + } + } +}); - /** - * @ngdoc service - * @name $timeout - * - * @description - * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch - * block and delegates any exceptions to - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * The return value of registering a timeout function is a promise, which will be resolved when - * the timeout is reached and the timeout function is executed. - * - * To cancel a timeout request, call `$timeout.cancel(promise)`. - * - * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to - * synchronously flush the queue of deferred functions. - * - * @param {function()} fn A function, whose execution should be delayed. - * @param {number=} [delay=0] Delay in milliseconds. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. - * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this - * promise will be resolved with is the return value of the `fn` function. - * - */ - function timeout(fn, delay, invokeApply) { - var skipApply = (isDefined(invokeApply) && !invokeApply), - deferred = (skipApply ? $$q : $q).defer(), - promise = deferred.promise, - timeoutId; +/** + * @ngdoc directive + * @name ngHref + * @restrict A + * @priority 99 + * + * @description + * Using Angular markup like `{{hash}}` in an href attribute will + * make the link go to the wrong URL if the user clicks it before + * Angular has a chance to replace the `{{hash}}` markup with its + * value. Until Angular replaces the markup the link will be broken + * and will most likely return a 404 error. The `ngHref` directive + * solves this problem. + * + * The wrong way to write it: + * ```html + * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a> + * ``` + * + * The correct way to write it: + * ```html + * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a> + * ``` + * + * @element A + * @param {template} ngHref any string which can contain `{{}}` markup. + * + * @example + * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes + * in links and their different behaviors: + <example> + <file name="index.html"> + <input ng-model="value" /><br /> + <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br /> + <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br /> + <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br /> + <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br /> + <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br /> + <a id="link-6" ng-href="{{value}}">link</a> (link, change location) + </file> + <file name="protractor.js" type="protractor"> + it('should execute ng-click but not reload when href without value', function() { + element(by.id('link-1')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('1'); + expect(element(by.id('link-1')).getAttribute('href')).toBe(''); + }); - timeoutId = $browser.defer(function() { - try { - deferred.resolve(fn()); - } catch (e) { - deferred.reject(e); - $exceptionHandler(e); - } - finally { - delete deferreds[promise.$$timeoutId]; - } + it('should execute ng-click but not reload when href empty string', function() { + element(by.id('link-2')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('2'); + expect(element(by.id('link-2')).getAttribute('href')).toBe(''); + }); - if (!skipApply) $rootScope.$apply(); - }, delay); + it('should execute ng-click and change url when ng-href specified', function() { + expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); - promise.$$timeoutId = timeoutId; - deferreds[timeoutId] = deferred; + element(by.id('link-3')).click(); - return promise; - } + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/123$/); + }); + }, 5000, 'page should navigate to /123'); + }); - /** - * @ngdoc method - * @name $timeout#cancel - * - * @description - * Cancels a task associated with the `promise`. As a result of this, the promise will be - * resolved with a rejection. - * - * @param {Promise=} promise Promise returned by the `$timeout` function. - * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully - * canceled. - */ - timeout.cancel = function(promise) { - if (promise && promise.$$timeoutId in deferreds) { - deferreds[promise.$$timeoutId].reject('canceled'); - delete deferreds[promise.$$timeoutId]; - return $browser.defer.cancel(promise.$$timeoutId); - } - return false; - }; + it('should execute ng-click but not reload when href empty string and name specified', function() { + element(by.id('link-4')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('4'); + expect(element(by.id('link-4')).getAttribute('href')).toBe(''); + }); - return timeout; - }]; -} + it('should execute ng-click but not reload when no href but name specified', function() { + element(by.id('link-5')).click(); + expect(element(by.model('value')).getAttribute('value')).toEqual('5'); + expect(element(by.id('link-5')).getAttribute('href')).toBe(null); + }); -// NOTE: The usage of window and document instead of $window and $document here is -// deliberate. This service depends on the specific behavior of anchor nodes created by the -// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and -// cause us to break tests. In addition, when the browser resolves a URL for XHR, it -// doesn't know about mocked locations and resolves URLs to the real document - which is -// exactly the behavior needed here. There is little value is mocking these out for this -// service. -var urlParsingNode = document.createElement("a"); -var originUrl = urlResolve(window.location.href); + it('should only change url when only ng-href', function() { + element(by.model('value')).clear(); + element(by.model('value')).sendKeys('6'); + expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); + + element(by.id('link-6')).click(); + // At this point, we navigate away from an Angular page, so we need + // to use browser.driver to get the base webdriver. + browser.wait(function() { + return browser.driver.getCurrentUrl().then(function(url) { + return url.match(/\/6$/); + }); + }, 5000, 'page should navigate to /6'); + }); + </file> + </example> + */ /** + * @ngdoc directive + * @name ngSrc + * @restrict A + * @priority 99 * - * Implementation Notes for non-IE browsers - * ---------------------------------------- - * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, - * results both in the normalizing and parsing of the URL. Normalizing means that a relative - * URL will be resolved into an absolute URL in the context of the application document. - * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related - * properties are all populated to reflect the normalized URL. This approach has wide - * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See - * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * @description + * Using Angular markup like `{{hash}}` in a `src` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrc` directive solves this problem. * - * Implementation Notes for IE - * --------------------------- - * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other - * browsers. However, the parsed components will not be set if the URL assigned did not specify - * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We - * work around that by performing the parsing in a 2nd step by taking a previously normalized - * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the - * properties such as protocol, hostname, port, etc. + * The buggy way to write it: + * ```html + * <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/> + * ``` * - * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one - * uses the inner HTML approach to assign the URL as part of an HTML snippet - - * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL. - * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. - * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that - * method and IE < 8 is unsupported. + * The correct way to write it: + * ```html + * <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" /> + * ``` * - * References: - * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement - * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html - * http://url.spec.whatwg.org/#urlutils - * https://github.com/angular/angular.js/pull/2902 - * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ + * @element IMG + * @param {template} ngSrc any string which can contain `{{}}` markup. + */ + +/** + * @ngdoc directive + * @name ngSrcset + * @restrict A + * @priority 99 * - * @kind function - * @param {string} url The URL to be parsed. - * @description Normalizes and parses a URL. - * @returns {object} Returns the normalized URL as a dictionary. + * @description + * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't + * work right: The browser will fetch from the URL with the literal + * text `{{hash}}` until Angular replaces the expression inside + * `{{hash}}`. The `ngSrcset` directive solves this problem. * - * | member name | Description | - * |---------------|----------------| - * | href | A normalized version of the provided URL if it was not an absolute URL | - * | protocol | The protocol including the trailing colon | - * | host | The host and port (if the port is non-default) of the normalizedUrl | - * | search | The search params, minus the question mark | - * | hash | The hash string, minus the hash symbol - * | hostname | The hostname - * | port | The port, without ":" - * | pathname | The pathname, beginning with "/" + * The buggy way to write it: + * ```html + * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/> + * ``` + * + * The correct way to write it: + * ```html + * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" /> + * ``` * + * @element IMG + * @param {template} ngSrcset any string which can contain `{{}}` markup. */ -function urlResolve(url) { - var href = url; - - if (msie) { - // Normalize before parse. Refer Implementation Notes on why this is - // done in two steps on IE. - urlParsingNode.setAttribute("href", href); - href = urlParsingNode.href; - } - - urlParsingNode.setAttribute('href', href); - - // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils - return { - href: urlParsingNode.href, - protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', - host: urlParsingNode.host, - search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', - hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', - hostname: urlParsingNode.hostname, - port: urlParsingNode.port, - pathname: (urlParsingNode.pathname.charAt(0) === '/') - ? urlParsingNode.pathname - : '/' + urlParsingNode.pathname - }; -} /** - * Parse a request URL and determine whether this is a same-origin request as the application document. + * @ngdoc directive + * @name ngDisabled + * @restrict A + * @priority 100 * - * @param {string|object} requestUrl The url of the request as a string that will be resolved - * or a parsed URL object. - * @returns {boolean} Whether the request is for the same origin as the application document. + * @description + * + * This directive sets the `disabled` attribute on the element if the + * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy. + * + * A special directive is necessary because we cannot use interpolation inside the `disabled` + * attribute. The following example would make the button enabled on Chrome/Firefox + * but not on older IEs: + * + * ```html + * <!-- See below for an example of ng-disabled being used correctly --> + * <div ng-init="isDisabled = false"> + * <button disabled="{{isDisabled}}">Disabled</button> + * </div> + * ``` + * + * This is because the HTML specification does not require browsers to preserve the values of + * boolean attributes such as `disabled` (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * + * @example + <example> + <file name="index.html"> + <label>Click me to toggle: <input type="checkbox" ng-model="checked"></label><br/> + <button ng-model="button" ng-disabled="checked">Button</button> + </file> + <file name="protractor.js" type="protractor"> + it('should toggle button', function() { + expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy(); + }); + </file> + </example> + * + * @element INPUT + * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, + * then the `disabled` attribute will be set on the element */ -function urlIsSameOrigin(requestUrl) { - var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl; - return (parsed.protocol === originUrl.protocol && - parsed.host === originUrl.host); -} + /** - * @ngdoc service - * @name $window + * @ngdoc directive + * @name ngChecked + * @restrict A + * @priority 100 * * @description - * A reference to the browser's `window` object. While `window` - * is globally available in JavaScript, it causes testability problems, because - * it is a global variable. In angular we always refer to it through the - * `$window` service, so it may be overridden, removed or mocked for testing. + * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy. * - * Expressions, like the one defined for the `ngClick` directive in the example - * below, are evaluated with respect to the current scope. Therefore, there is - * no risk of inadvertently coding in a dependency on a global value in such an - * expression. + * Note that this directive should not be used together with {@link ngModel `ngModel`}, + * as this can lead to unexpected behavior. + * + * ### Why do we need `ngChecked`? * + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as checked. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngChecked` directive solves this problem for the `checked` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. * @example - <example module="windowExample"> - <file name="index.html"> - <script> - angular.module('windowExample', []) - .controller('ExampleController', ['$scope', '$window', function($scope, $window) { - $scope.greeting = 'Hello, World!'; - $scope.doGreeting = function(greeting) { - $window.alert(greeting); - }; - }]); - </script> - <div ng-controller="ExampleController"> - <input type="text" ng-model="greeting" /> - <button ng-click="doGreeting(greeting)">ALERT</button> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should display the greeting in the input box', function() { - element(by.model('greeting')).sendKeys('Hello, E2E Tests'); - // If we click the button it will block the test runner - // element(':button').click(); - }); - </file> - </example> + <example> + <file name="index.html"> + <label>Check me to check both: <input type="checkbox" ng-model="master"></label><br/> + <input id="checkSlave" type="checkbox" ng-checked="master" aria-label="Slave input"> + </file> + <file name="protractor.js" type="protractor"> + it('should check both checkBoxes', function() { + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy(); + element(by.model('master')).click(); + expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy(); + }); + </file> + </example> + * + * @element INPUT + * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, + * then the `checked` attribute will be set on the element */ -function $WindowProvider() { - this.$get = valueFn(window); -} -/* global currencyFilter: true, - dateFilter: true, - filterFilter: true, - jsonFilter: true, - limitToFilter: true, - lowercaseFilter: true, - numberFilter: true, - orderByFilter: true, - uppercaseFilter: true, - */ /** - * @ngdoc provider - * @name $filterProvider - * @description + * @ngdoc directive + * @name ngReadonly + * @restrict A + * @priority 100 * - * Filters are just functions which transform input to an output. However filters need to be - * Dependency Injected. To achieve this a filter definition consists of a factory function which is - * annotated with dependencies and is responsible for creating a filter function. + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as readonly. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngReadonly` directive solves this problem for the `readonly` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + <example> + <file name="index.html"> + <label>Check me to make text readonly: <input type="checkbox" ng-model="checked"></label><br/> + <input type="text" ng-readonly="checked" value="I'm Angular" aria-label="Readonly field" /> + </file> + <file name="protractor.js" type="protractor"> + it('should toggle readonly attr', function() { + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy(); + element(by.model('checked')).click(); + expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy(); + }); + </file> + </example> * - * ```js - * // Filter registration - * function MyModule($provide, $filterProvider) { - * // create a service to demonstrate injection (not always needed) - * $provide.value('greet', function(name){ - * return 'Hello ' + name + '!'; - * }); + * @element INPUT + * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, + * then special attribute "readonly" will be set on the element + */ + + +/** + * @ngdoc directive + * @name ngSelected + * @restrict A + * @priority 100 * - * // register a filter factory which uses the - * // greet service to demonstrate DI. - * $filterProvider.register('greet', function(greet){ - * // return the filter function which uses the greet service - * // to generate salutation - * return function(text) { - * // filters need to be forgiving so check input validity - * return text && greet(text) || text; - * }; - * }); - * } - * ``` + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as selected. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngSelected` directive solves this problem for the `selected` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. * - * The filter function is registered with the `$injector` under the filter name suffix with - * `Filter`. + * @example + <example> + <file name="index.html"> + <label>Check me to select: <input type="checkbox" ng-model="selected"></label><br/> + <select aria-label="ngSelected demo"> + <option>Hello!</option> + <option id="greet" ng-selected="selected">Greetings!</option> + </select> + </file> + <file name="protractor.js" type="protractor"> + it('should select Greetings!', function() { + expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); + element(by.model('selected')).click(); + expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); + }); + </file> + </example> * - * ```js - * it('should be the same instance', inject( - * function($filterProvider) { - * $filterProvider.register('reverse', function(){ - * return ...; - * }); - * }, - * function($filter, reverseFilter) { - * expect($filter('reverse')).toBe(reverseFilter); - * }); - * ``` + * @element OPTION + * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, + * then special attribute "selected" will be set on the element + */ + +/** + * @ngdoc directive + * @name ngOpen + * @restrict A + * @priority 100 * + * @description + * The HTML specification does not require browsers to preserve the values of boolean attributes + * such as open. (Their presence means true and their absence means false.) + * If we put an Angular interpolation expression into such an attribute then the + * binding information would be lost when the browser removes the attribute. + * The `ngOpen` directive solves this problem for the `open` attribute. + * This complementary directive is not removed by the browser and so provides + * a permanent reliable place to store the binding information. + * @example + <example> + <file name="index.html"> + <label>Check me check multiple: <input type="checkbox" ng-model="open"></label><br/> + <details id="details" ng-open="open"> + <summary>Show/Hide me</summary> + </details> + </file> + <file name="protractor.js" type="protractor"> + it('should toggle open', function() { + expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); + element(by.model('open')).click(); + expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); + }); + </file> + </example> * - * For more information about how angular filters work, and how to create your own filters, see - * {@link guide/filter Filters} in the Angular Developer Guide. + * @element DETAILS + * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, + * then special attribute "open" will be set on the element */ -/** - * @ngdoc service - * @name $filter - * @kind function - * @description - * Filters are used for formatting data displayed to the user. - * - * The general syntax in templates is as follows: - * - * {{ expression [| filter_name[:parameter_value] ... ] }} - * - * @param {String} name Name of the filter function to retrieve - * @return {Function} the filter function - * @example - <example name="$filter" module="filterExample"> - <file name="index.html"> - <div ng-controller="MainCtrl"> - <h3>{{ originalText }}</h3> - <h3>{{ filteredText }}</h3> - </div> - </file> +var ngAttributeAliasDirectives = {}; - <file name="script.js"> - angular.module('filterExample', []) - .controller('MainCtrl', function($scope, $filter) { - $scope.originalText = 'hello'; - $scope.filteredText = $filter('uppercase')($scope.originalText); - }); - </file> - </example> - */ -$FilterProvider.$inject = ['$provide']; -function $FilterProvider($provide) { - var suffix = 'Filter'; +// boolean attrs are evaluated +forEach(BOOLEAN_ATTR, function(propName, attrName) { + // binding to multiple is not supported + if (propName == "multiple") return; - /** - * @ngdoc method - * @name $filterProvider#register - * @param {string|Object} name Name of the filter function, or an object map of filters where - * the keys are the filter names and the values are the filter factories. - * @returns {Object} Registered filter instance, or if a map of filters was provided then a map - * of the registered filter instances. - */ - function register(name, factory) { - if (isObject(name)) { - var filters = {}; - forEach(name, function(filter, key) { - filters[key] = register(key, filter); - }); - return filters; - } else { - return $provide.factory(name + suffix, factory); - } + function defaultLinkFn(scope, element, attr) { + scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { + attr.$set(attrName, !!value); + }); } - this.register = register; - this.$get = ['$injector', function($injector) { - return function(name) { - return $injector.get(name + suffix); + var normalized = directiveNormalize('ng-' + attrName); + var linkFn = defaultLinkFn; + + if (propName === 'checked') { + linkFn = function(scope, element, attr) { + // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input + if (attr.ngModel !== attr[normalized]) { + defaultLinkFn(scope, element, attr); + } }; - }]; + } - //////////////////////////////////////// + ngAttributeAliasDirectives[normalized] = function() { + return { + restrict: 'A', + priority: 100, + link: linkFn + }; + }; +}); - /* global - currencyFilter: false, - dateFilter: false, - filterFilter: false, - jsonFilter: false, - limitToFilter: false, - lowercaseFilter: false, - numberFilter: false, - orderByFilter: false, - uppercaseFilter: false, - */ +// aliased input attrs are evaluated +forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { + ngAttributeAliasDirectives[ngAttr] = function() { + return { + priority: 100, + link: function(scope, element, attr) { + //special case ngPattern when a literal regular expression value + //is used as the expression (this way we don't have to watch anything). + if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") { + var match = attr.ngPattern.match(REGEX_STRING_REGEXP); + if (match) { + attr.$set("ngPattern", new RegExp(match[1], match[2])); + return; + } + } - register('currency', currencyFilter); - register('date', dateFilter); - register('filter', filterFilter); - register('json', jsonFilter); - register('limitTo', limitToFilter); - register('lowercase', lowercaseFilter); - register('number', numberFilter); - register('orderBy', orderByFilter); - register('uppercase', uppercaseFilter); + scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { + attr.$set(ngAttr, value); + }); + } + }; + }; +}); + +// ng-src, ng-srcset, ng-href are interpolated +forEach(['src', 'srcset', 'href'], function(attrName) { + var normalized = directiveNormalize('ng-' + attrName); + ngAttributeAliasDirectives[normalized] = function() { + return { + priority: 99, // it needs to run after the attributes are interpolated + link: function(scope, element, attr) { + var propName = attrName, + name = attrName; + + if (attrName === 'href' && + toString.call(element.prop('href')) === '[object SVGAnimatedString]') { + name = 'xlinkHref'; + attr.$attr[name] = 'xlink:href'; + propName = null; + } + + attr.$observe(normalized, function(value) { + if (!value) { + if (attrName === 'href') { + attr.$set(name, null); + } + return; + } + + attr.$set(name, value); + + // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist + // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need + // to set the property as well to achieve the desired effect. + // we use attr[attrName] value since $set can sanitize the url. + if (msie && propName) element.prop(propName, attr[name]); + }); + } + }; + }; +}); + +/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true + */ +var nullFormCtrl = { + $addControl: noop, + $$renameControl: nullFormRenameControl, + $removeControl: noop, + $setValidity: noop, + $setDirty: noop, + $setPristine: noop, + $setSubmitted: noop +}, +SUBMITTED_CLASS = 'ng-submitted'; + +function nullFormRenameControl(control, name) { + control.$name = name; } /** - * @ngdoc filter - * @name filter - * @kind function - * - * @description - * Selects a subset of items from `array` and returns it as a new array. - * - * @param {Array} array The source array. - * @param {string|Object|function()} expression The predicate to be used for selecting items from - * `array`. - * - * Can be one of: - * - * - `string`: The string is used for matching against the contents of the `array`. All strings or - * objects with string properties in `array` that match this string will be returned. This also - * applies to nested object properties. - * The predicate can be negated by prefixing the string with `!`. - * - * - `Object`: A pattern object can be used to filter specific properties on objects contained - * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items - * which have property `name` containing "M" and property `phone` containing "1". A special - * property name `$` can be used (as in `{$:"text"}`) to accept a match against any - * property of the object or its nested object properties. That's equivalent to the simple - * substring match with a `string` as described above. The predicate can be negated by prefixing - * the string with `!`. - * For example `{name: "!M"}` predicate will return an array of items which have property `name` - * not containing "M". + * @ngdoc type + * @name form.FormController * - * Note that a named property will match properties on the same level only, while the special - * `$` property will match properties on the same level or deeper. E.g. an array item like - * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but - * **will** be matched by `{$: 'John'}`. + * @property {boolean} $pristine True if user has not interacted with the form yet. + * @property {boolean} $dirty True if user has already interacted with the form. + * @property {boolean} $valid True if all of the containing forms and controls are valid. + * @property {boolean} $invalid True if at least one containing control or form is invalid. + * @property {boolean} $submitted True if user has submitted the form even if its invalid. * - * - `function(value, index)`: A predicate function can be used to write arbitrary filters. The - * function is called for each element of `array`. The final result is an array of those - * elements that the predicate returned true for. + * @property {Object} $error Is an object hash, containing references to controls or + * forms with failing validators, where: * - * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in - * determining if the expected value (from the filter expression) and actual value (from - * the object in the array) should be considered a match. + * - keys are validation tokens (error names), + * - values are arrays of controls or forms that have a failing validator for given error name. * - * Can be one of: + * Built-in validation tokens: * - * - `function(actual, expected)`: - * The function will be given the object value and the predicate value to compare and - * should return true if both values should be considered equal. + * - `email` + * - `max` + * - `maxlength` + * - `min` + * - `minlength` + * - `number` + * - `pattern` + * - `required` + * - `url` + * - `date` + * - `datetimelocal` + * - `time` + * - `week` + * - `month` * - * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`. - * This is essentially strict comparison of expected and actual. + * @description + * `FormController` keeps track of all its controls and nested forms as well as the state of them, + * such as being valid/invalid or dirty/pristine. * - * - `false|undefined`: A short hand for a function which will look for a substring match in case - * insensitive way. + * Each {@link ng.directive:form form} directive creates an instance + * of `FormController`. * - * @example - <example> - <file name="index.html"> - <div ng-init="friends = [{name:'John', phone:'555-1276'}, - {name:'Mary', phone:'800-BIG-MARY'}, - {name:'Mike', phone:'555-4321'}, - {name:'Adam', phone:'555-5678'}, - {name:'Julie', phone:'555-8765'}, - {name:'Juliette', phone:'555-5678'}]"></div> + */ +//asks for $scope to fool the BC controller module +FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate']; +function FormController(element, attrs, $scope, $animate, $interpolate) { + var form = this, + controls = []; - Search: <input ng-model="searchText"> - <table id="searchTextResults"> - <tr><th>Name</th><th>Phone</th></tr> - <tr ng-repeat="friend in friends | filter:searchText"> - <td>{{friend.name}}</td> - <td>{{friend.phone}}</td> - </tr> - </table> - <hr> - Any: <input ng-model="search.$"> <br> - Name only <input ng-model="search.name"><br> - Phone only <input ng-model="search.phone"><br> - Equality <input type="checkbox" ng-model="strict"><br> - <table id="searchObjResults"> - <tr><th>Name</th><th>Phone</th></tr> - <tr ng-repeat="friendObj in friends | filter:search:strict"> - <td>{{friendObj.name}}</td> - <td>{{friendObj.phone}}</td> - </tr> - </table> - </file> - <file name="protractor.js" type="protractor"> - var expectFriendNames = function(expectedNames, key) { - element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { - arr.forEach(function(wd, i) { - expect(wd.getText()).toMatch(expectedNames[i]); - }); - }); - }; + var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl; - it('should search across all fields when filtering with a string', function() { - var searchText = element(by.model('searchText')); - searchText.clear(); - searchText.sendKeys('m'); - expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); + // init state + form.$error = {}; + form.$$success = {}; + form.$pending = undefined; + form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope); + form.$dirty = false; + form.$pristine = true; + form.$valid = true; + form.$invalid = false; + form.$submitted = false; - searchText.clear(); - searchText.sendKeys('76'); - expectFriendNames(['John', 'Julie'], 'friend'); - }); + parentForm.$addControl(form); - it('should search in specific fields when filtering with a predicate object', function() { - var searchAny = element(by.model('search.$')); - searchAny.clear(); - searchAny.sendKeys('i'); - expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); - }); - it('should use a equal comparison when comparator is true', function() { - var searchName = element(by.model('search.name')); - var strict = element(by.model('strict')); - searchName.clear(); - searchName.sendKeys('Julie'); - strict.click(); - expectFriendNames(['Julie'], 'friendObj'); - }); - </file> - </example> - */ -function filterFilter() { - return function(array, expression, comparator) { - if (!isArray(array)) return array; + /** + * @ngdoc method + * @name form.FormController#$rollbackViewValue + * + * @description + * Rollback all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is typically needed by the reset button of + * a form that uses `ng-model-options` to pend updates. + */ + form.$rollbackViewValue = function() { + forEach(controls, function(control) { + control.$rollbackViewValue(); + }); + }; - var predicateFn; - var matchAgainstAnyProp; + /** + * @ngdoc method + * @name form.FormController#$commitViewValue + * + * @description + * Commit all form controls pending updates to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. This method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. + */ + form.$commitViewValue = function() { + forEach(controls, function(control) { + control.$commitViewValue(); + }); + }; - switch (typeof expression) { - case 'function': - predicateFn = expression; - break; - case 'boolean': - case 'number': - case 'string': - matchAgainstAnyProp = true; - //jshint -W086 - case 'object': - //jshint +W086 - predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp); - break; - default: - return array; - } + /** + * @ngdoc method + * @name form.FormController#$addControl + * + * @description + * Register a control with the form. + * + * Input elements using ngModelController do this automatically when they are linked. + */ + form.$addControl = function(control) { + // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored + // and not added to the scope. Now we throw an error. + assertNotHasOwnProperty(control.$name, 'input'); + controls.push(control); - return array.filter(predicateFn); + if (control.$name) { + form[control.$name] = control; + } }; -} - -// Helper functions for `filterFilter` -function createPredicateFn(expression, comparator, matchAgainstAnyProp) { - var shouldMatchPrimitives = isObject(expression) && ('$' in expression); - var predicateFn; - if (comparator === true) { - comparator = equals; - } else if (!isFunction(comparator)) { - comparator = function(actual, expected) { - if (isObject(actual) || isObject(expected)) { - // Prevent an object to be considered equal to a string like `'[object'` - return false; - } + // Private API: rename a form control + form.$$renameControl = function(control, newName) { + var oldName = control.$name; - actual = lowercase('' + actual); - expected = lowercase('' + expected); - return actual.indexOf(expected) !== -1; - }; - } + if (form[oldName] === control) { + delete form[oldName]; + } + form[newName] = control; + control.$name = newName; + }; - predicateFn = function(item) { - if (shouldMatchPrimitives && !isObject(item)) { - return deepCompare(item, expression.$, comparator, false); + /** + * @ngdoc method + * @name form.FormController#$removeControl + * + * @description + * Deregister a control from the form. + * + * Input elements using ngModelController do this automatically when they are destroyed. + */ + form.$removeControl = function(control) { + if (control.$name && form[control.$name] === control) { + delete form[control.$name]; } - return deepCompare(item, expression, comparator, matchAgainstAnyProp); + forEach(form.$pending, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$error, function(value, name) { + form.$setValidity(name, null, control); + }); + forEach(form.$$success, function(value, name) { + form.$setValidity(name, null, control); + }); + + arrayRemove(controls, control); }; - return predicateFn; -} -function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) { - var actualType = typeof actual; - var expectedType = typeof expected; + /** + * @ngdoc method + * @name form.FormController#$setValidity + * + * @description + * Sets the validity of a form control. + * + * This method will also propagate to parent forms. + */ + addSetValidityMethod({ + ctrl: this, + $element: element, + set: function(object, property, controller) { + var list = object[property]; + if (!list) { + object[property] = [controller]; + } else { + var index = list.indexOf(controller); + if (index === -1) { + list.push(controller); + } + } + }, + unset: function(object, property, controller) { + var list = object[property]; + if (!list) { + return; + } + arrayRemove(list, controller); + if (list.length === 0) { + delete object[property]; + } + }, + parentForm: parentForm, + $animate: $animate + }); + + /** + * @ngdoc method + * @name form.FormController#$setDirty + * + * @description + * Sets the form to a dirty state. + * + * This method can be called to add the 'ng-dirty' class and set the form to a dirty + * state (ng-dirty class). This method will also propagate to parent forms. + */ + form.$setDirty = function() { + $animate.removeClass(element, PRISTINE_CLASS); + $animate.addClass(element, DIRTY_CLASS); + form.$dirty = true; + form.$pristine = false; + parentForm.$setDirty(); + }; - if ((expectedType === 'string') && (expected.charAt(0) === '!')) { - return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp); - } else if (isArray(actual)) { - // In case `actual` is an array, consider it a match - // if ANY of it's items matches `expected` - return actual.some(function(item) { - return deepCompare(item, expected, comparator, matchAgainstAnyProp); + /** + * @ngdoc method + * @name form.FormController#$setPristine + * + * @description + * Sets the form to its pristine state. + * + * This method can be called to remove the 'ng-dirty' class and set the form to its pristine + * state (ng-pristine class). This method will also propagate to all the controls contained + * in this form. + * + * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after + * saving or resetting it. + */ + form.$setPristine = function() { + $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS); + form.$dirty = false; + form.$pristine = true; + form.$submitted = false; + forEach(controls, function(control) { + control.$setPristine(); }); - } + }; - switch (actualType) { - case 'object': - var key; - if (matchAgainstAnyProp) { - for (key in actual) { - if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) { - return true; - } - } - return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false); - } else if (expectedType === 'object') { - for (key in expected) { - var expectedVal = expected[key]; - if (isFunction(expectedVal)) { - continue; - } + /** + * @ngdoc method + * @name form.FormController#$setUntouched + * + * @description + * Sets the form to its untouched state. + * + * This method can be called to remove the 'ng-touched' class and set the form controls to their + * untouched state (ng-untouched class). + * + * Setting a form controls back to their untouched state is often useful when setting the form + * back to its pristine state. + */ + form.$setUntouched = function() { + forEach(controls, function(control) { + control.$setUntouched(); + }); + }; - var matchAnyProperty = key === '$'; - var actualVal = matchAnyProperty ? actual : actual[key]; - if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) { - return false; - } - } - return true; - } else { - return comparator(actual, expected); - } - break; - case 'function': - return false; - default: - return comparator(actual, expected); - } + /** + * @ngdoc method + * @name form.FormController#$setSubmitted + * + * @description + * Sets the form to its submitted state. + */ + form.$setSubmitted = function() { + $animate.addClass(element, SUBMITTED_CLASS); + form.$submitted = true; + parentForm.$setSubmitted(); + }; } /** - * @ngdoc filter - * @name currency - * @kind function + * @ngdoc directive + * @name ngForm + * @restrict EAC * * @description - * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default - * symbol for current locale is used. + * Nestable alias of {@link ng.directive:form `form`} directive. HTML + * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a + * sub-group of controls needs to be determined. * - * @param {number} amount Input to filter. - * @param {string=} symbol Currency symbol or identifier to be displayed. - * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale - * @returns {string} Formatted number. + * Note: the purpose of `ngForm` is to group controls, + * but not to be a replacement for the `<form>` tag with all of its capabilities + * (e.g. posting to the server, ...). * + * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into + * related scope, under this name. * - * @example - <example module="currencyExample"> - <file name="index.html"> - <script> - angular.module('currencyExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.amount = 1234.56; - }]); - </script> - <div ng-controller="ExampleController"> - <input type="number" ng-model="amount"> <br> - default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br> - custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span> - no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should init with 1234.56', function() { - expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); - expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56'); - expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235'); - }); - it('should update', function() { - if (browser.params.browser == 'safari') { - // Safari does not understand the minus key. See - // https://github.com/angular/protractor/issues/481 - return; - } - element(by.model('amount')).clear(); - element(by.model('amount')).sendKeys('-1234'); - expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)'); - expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)'); - expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)'); - }); - </file> - </example> */ -currencyFilter.$inject = ['$locale']; -function currencyFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(amount, currencySymbol, fractionSize) { - if (isUndefined(currencySymbol)) { - currencySymbol = formats.CURRENCY_SYM; - } - - if (isUndefined(fractionSize)) { - fractionSize = formats.PATTERNS[1].maxFrac; - } - // if null or undefined pass it through - return (amount == null) - ? amount - : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize). - replace(/\u00A4/g, currencySymbol); - }; -} - -/** - * @ngdoc filter - * @name number - * @kind function + /** + * @ngdoc directive + * @name form + * @restrict E * * @description - * Formats a number as text. + * Directive that instantiates + * {@link form.FormController FormController}. * - * If the input is not a number an empty string is returned. + * If the `name` attribute is specified, the form controller is published onto the current scope under + * this name. * - * @param {number|string} number Number to format. - * @param {(number|string)=} fractionSize Number of decimal places to round the number to. - * If this is not provided then the fraction size is computed from the current locale's number - * formatting pattern. In the case of the default locale, it will be 3. - * @returns {string} Number rounded to decimalPlaces and places a “,†after each third digit. + * # Alias: {@link ng.directive:ngForm `ngForm`} + * + * In Angular, forms can be nested. This means that the outer form is valid when all of the child + * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so + * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to + * `<form>` but can be nested. This allows you to have nested forms, which is very useful when + * using Angular validation directives in forms that are dynamically generated using the + * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name` + * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an + * `ngForm` directive and nest these in an outer `form` element. + * + * + * # CSS classes + * - `ng-valid` is set if the form is valid. + * - `ng-invalid` is set if the form is invalid. + * - `ng-pristine` is set if the form is pristine. + * - `ng-dirty` is set if the form is dirty. + * - `ng-submitted` is set if the form was submitted. + * + * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * + * + * # Submitting a form and preventing the default action + * + * Since the role of forms in client-side Angular applications is different than in classical + * roundtrip apps, it is desirable for the browser not to translate the form submission into a full + * page reload that sends the data to the server. Instead some javascript logic should be triggered + * to handle the form submission in an application-specific way. + * + * For this reason, Angular prevents the default action (form submission to the server) unless the + * `<form>` element has an `action` attribute specified. + * + * You can use one of the following two ways to specify what javascript method should be called when + * a form is submitted: + * + * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element + * - {@link ng.directive:ngClick ngClick} directive on the first + * button or input field of type submit (input[type=submit]) + * + * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit} + * or {@link ng.directive:ngClick ngClick} directives. + * This is because of the following form submission rules in the HTML specification: + * + * - If a form has only one input field then hitting enter in this field triggers form submit + * (`ngSubmit`) + * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter + * doesn't trigger submit + * - if a form has one or more input fields and one or more buttons or input[type=submit] then + * hitting enter in any of the input fields will trigger the click handler on the *first* button or + * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) + * + * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is + * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` + * to have access to the updated model. + * + * ## Animation Hooks + * + * Animations in ngForm are triggered when any of the associated CSS classes are added and removed. + * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any + * other validations that are performed within the form. Animations in ngForm are similar to how + * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well + * as JS animations. + * + * The following example shows a simple way to utilize CSS transitions to style a form element + * that has been rendered as invalid after it has been validated: + * + * <pre> + * //be sure to include ngAnimate as a module to hook into more + * //advanced animations + * .my-form { + * transition:0.5s linear all; + * background: white; + * } + * .my-form.ng-invalid { + * background: red; + * color:white; + * } + * </pre> * * @example - <example module="numberFilterExample"> - <file name="index.html"> + <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample"> + <file name="index.html"> <script> - angular.module('numberFilterExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.val = 1234.56789; + angular.module('formExample', []) + .controller('FormController', ['$scope', function($scope) { + $scope.userType = 'guest'; }]); </script> - <div ng-controller="ExampleController"> - Enter number: <input ng-model='val'><br> - Default formatting: <span id='number-default'>{{val | number}}</span><br> - No fractions: <span>{{val | number:0}}</span><br> - Negative number: <span>{{-val | number:4}}</span> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should format numbers', function() { - expect(element(by.id('number-default')).getText()).toBe('1,234.568'); - expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); - expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); - }); + <style> + .my-form { + -webkit-transition:all linear 0.5s; + transition:all linear 0.5s; + background: transparent; + } + .my-form.ng-invalid { + background: red; + } + </style> + <form name="myForm" ng-controller="FormController" class="my-form"> + userType: <input name="input" ng-model="userType" required> + <span class="error" ng-show="myForm.input.$error.required">Required!</span><br> + <code>userType = {{userType}}</code><br> + <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br> + <code>myForm.input.$error = {{myForm.input.$error}}</code><br> + <code>myForm.$valid = {{myForm.$valid}}</code><br> + <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br> + </form> + </file> + <file name="protractor.js" type="protractor"> + it('should initialize to model', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); - it('should update', function() { - element(by.model('val')).clear(); - element(by.model('val')).sendKeys('3374.333'); - expect(element(by.id('number-default')).getText()).toBe('3,374.333'); - expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); - expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); - }); - </file> - </example> - */ + expect(userType.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + it('should be invalid if empty', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + var userInput = element(by.model('userType')); -numberFilter.$inject = ['$locale']; -function numberFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(number, fractionSize) { + userInput.clear(); + userInput.sendKeys(''); - // if null or undefined pass it through - return (number == null) - ? number - : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, - fractionSize); - }; -} + expect(userType.getText()).toEqual('userType ='); + expect(valid.getText()).toContain('false'); + }); + </file> + </example> + * + * @param {string=} name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + */ +var formDirectiveFactory = function(isNgForm) { + return ['$timeout', function($timeout) { + var formDirective = { + name: 'form', + restrict: isNgForm ? 'EAC' : 'E', + controller: FormController, + compile: function ngFormCompile(formElement, attr) { + // Setup initial state of the control + formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); -var DECIMAL_SEP = '.'; -function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - if (!isFinite(number) || isObject(number)) return ''; + var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false); - var isNegative = number < 0; - number = Math.abs(number); - var numStr = number + '', - formatedText = '', - parts = []; + return { + pre: function ngFormPreLink(scope, formElement, attr, controller) { + // if `action` attr is not present on the form, prevent the default action (submission) + if (!('action' in attr)) { + // we can't use jq events because if a form is destroyed during submission the default + // action is not prevented. see #1238 + // + // IE 9 is not affected because it doesn't fire a submit event and try to do a full + // page reload if the form was destroyed by submission of the form via a click handler + // on a button in the form. Looks like an IE9 specific bug. + var handleFormSubmission = function(event) { + scope.$apply(function() { + controller.$commitViewValue(); + controller.$setSubmitted(); + }); - var hasExponent = false; - if (numStr.indexOf('e') !== -1) { - var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); - if (match && match[2] == '-' && match[3] > fractionSize + 1) { - number = 0; - } else { - formatedText = numStr; - hasExponent = true; - } - } + event.preventDefault(); + }; - if (!hasExponent) { - var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; + addEventListenerFn(formElement[0], 'submit', handleFormSubmission); - // determine fractionSize if it is not specified - if (isUndefined(fractionSize)) { - fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); - } + // unregister the preventDefault listener so that we don't not leak memory but in a + // way that will achieve the prevention of the default action. + formElement.on('$destroy', function() { + $timeout(function() { + removeEventListenerFn(formElement[0], 'submit', handleFormSubmission); + }, 0, false); + }); + } - // safely round numbers in JS without hitting imprecisions of floating-point arithmetics - // inspired by: - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round - number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize); + var parentFormCtrl = controller.$$parentForm; - var fraction = ('' + number).split(DECIMAL_SEP); - var whole = fraction[0]; - fraction = fraction[1] || ''; + if (nameAttr) { + setter(scope, controller.$name, controller, controller.$name); + attr.$observe(nameAttr, function(newValue) { + if (controller.$name === newValue) return; + setter(scope, controller.$name, undefined, controller.$name); + parentFormCtrl.$$renameControl(controller, newValue); + setter(scope, controller.$name, controller, controller.$name); + }); + } + formElement.on('$destroy', function() { + parentFormCtrl.$removeControl(controller); + if (nameAttr) { + setter(scope, attr[nameAttr], undefined, controller.$name); + } + extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards + }); + } + }; + } + }; - var i, pos = 0, - lgroup = pattern.lgSize, - group = pattern.gSize; + return formDirective; + }]; +}; - if (whole.length >= (lgroup + group)) { - pos = whole.length - lgroup; - for (i = 0; i < pos; i++) { - if ((pos - i) % group === 0 && i !== 0) { - formatedText += groupSep; - } - formatedText += whole.charAt(i); - } - } +var formDirective = formDirectiveFactory(); +var ngFormDirective = formDirectiveFactory(true); - for (i = pos; i < whole.length; i++) { - if ((whole.length - i) % lgroup === 0 && i !== 0) { - formatedText += groupSep; - } - formatedText += whole.charAt(i); - } +/* global VALID_CLASS: false, + INVALID_CLASS: false, + PRISTINE_CLASS: false, + DIRTY_CLASS: false, + UNTOUCHED_CLASS: false, + TOUCHED_CLASS: false, + $ngModelMinErr: false, +*/ - // format fraction part. - while (fraction.length < fractionSize) { - fraction += '0'; - } +// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 +var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; +var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; +var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; +var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; +var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; +var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; +var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; +var MONTH_REGEXP = /^(\d{4})-(\d\d)$/; +var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; + +var inputType = { + + /** + * @ngdoc input + * @name input[text] + * + * @description + * Standard HTML text input with angular data binding, inherited by most of the `input` elements. + * + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Adds `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + <example name="text-input-directive" module="textInputExample"> + <file name="index.html"> + <script> + angular.module('textInputExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.example = { + text: 'guest', + word: /^\s*\w*\s*$/ + }; + }]); + </script> + <form name="myForm" ng-controller="ExampleController"> + <label>Single word: + <input type="text" name="input" ng-model="example.text" + ng-pattern="example.word" required ng-trim="false"> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.pattern"> + Single word only!</span> + </div> + <tt>text = {{example.text}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var text = element(by.binding('example.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.text')); - if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); - } else { - if (fractionSize > 0 && number < 1) { - formatedText = number.toFixed(fractionSize); - number = parseFloat(formatedText); - } - } + it('should initialize to model', function() { + expect(text.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); - if (number === 0) { - isNegative = false; - } + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); - parts.push(isNegative ? pattern.negPre : pattern.posPre, - formatedText, - isNegative ? pattern.negSuf : pattern.posSuf); - return parts.join(''); -} + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); -function padNumber(num, digits, trim) { - var neg = ''; - if (num < 0) { - neg = '-'; - num = -num; - } - num = '' + num; - while (num.length < digits) num = '0' + num; - if (trim) - num = num.substr(num.length - digits); - return neg + num; -} + it('should be invalid if multi word', function() { + input.clear(); + input.sendKeys('hello world'); + expect(valid.getText()).toContain('false'); + }); + </file> + </example> + */ + 'text': textInputType, -function dateGetter(name, size, offset, trim) { - offset = offset || 0; - return function(date) { - var value = date['get' + name](); - if (offset > 0 || value > -offset) - value += offset; - if (value === 0 && offset == -12) value = 12; - return padNumber(value, size, trim); - }; -} + /** + * @ngdoc input + * @name input[date] + * + * @description + * Input with date validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601 + * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many + * modern browsers do not yet support this input type, it is important to provide cues to users on the + * expected input format via a placeholder or label. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO date string (yyyy-MM-dd). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO date string (yyyy-MM-dd). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="date-input-directive" module="dateInputExample"> + <file name="index.html"> + <script> + angular.module('dateInputExample', []) + .controller('DateController', ['$scope', function($scope) { + $scope.example = { + value: new Date(2013, 9, 22) + }; + }]); + </script> + <form name="myForm" ng-controller="DateController as dateCtrl"> + <label for="exampleInput">Pick a date in 2013:</label> + <input type="date" id="exampleInput" name="input" ng-model="example.value" + placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required /> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.date"> + Not a valid date!</span> + </div> + <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var value = element(by.binding('example.value | date: "yyyy-MM-dd"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); -function dateStrGetter(name, shortForm) { - return function(date, formats) { - var value = date['get' + name](); - var get = uppercase(shortForm ? ('SHORT' + name) : name); + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (see https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } - return formats[get][value]; - }; -} + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10-22'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); -function timeZoneGetter(date) { - var zone = -1 * date.getTimezoneOffset(); - var paddedZone = (zone >= 0) ? "+" : ""; + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); - paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + - padNumber(Math.abs(zone % 60), 2); + it('should be invalid if over max', function() { + setInput('2015-01-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + </file> + </example> + */ + 'date': createDateInputType('date', DATE_REGEXP, + createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']), + 'yyyy-MM-dd'), - return paddedZone; -} + /** + * @ngdoc input + * @name input[datetime-local] + * + * @description + * Input with datetime validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="datetimelocal-input-directive" module="dateExample"> + <file name="index.html"> + <script> + angular.module('dateExample', []) + .controller('DateController', ['$scope', function($scope) { + $scope.example = { + value: new Date(2010, 11, 28, 14, 57) + }; + }]); + </script> + <form name="myForm" ng-controller="DateController as dateCtrl"> + <label for="exampleInput">Pick a date between in 2013:</label> + <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value" + placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required /> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.datetimelocal"> + Not a valid date!</span> + </div> + <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); -function getFirstThursdayOfYear(year) { - // 0 = index of January - var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay(); - // 4 = index of Thursday (+1 to account for 1st = 5) - // 11 = index of *next* Thursday (+1 account for 1st = 12) - return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst); -} + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } -function getThursdayThisWeek(datetime) { - return new Date(datetime.getFullYear(), datetime.getMonth(), - // 4 = index of Thursday - datetime.getDate() + (4 - datetime.getDay())); -} + it('should initialize to model', function() { + expect(value.getText()).toContain('2010-12-28T14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); -function weekGetter(size) { - return function(date) { - var firstThurs = getFirstThursdayOfYear(date.getFullYear()), - thisThurs = getThursdayThisWeek(date); + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); - var diff = +thisThurs - +firstThurs, - result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week + it('should be invalid if over max', function() { + setInput('2015-01-01T23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + </file> + </example> + */ + 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP, + createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']), + 'yyyy-MM-ddTHH:mm:ss.sss'), - return padNumber(result, size); - }; -} + /** + * @ngdoc input + * @name input[time] + * + * @description + * Input with time validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a + * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO time format (HH:mm:ss). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a + * valid ISO time format (HH:mm:ss). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="time-input-directive" module="timeExample"> + <file name="index.html"> + <script> + angular.module('timeExample', []) + .controller('DateController', ['$scope', function($scope) { + $scope.example = { + value: new Date(1970, 0, 1, 14, 57, 0) + }; + }]); + </script> + <form name="myForm" ng-controller="DateController as dateCtrl"> + <label for="exampleInput">Pick a between 8am and 5pm:</label> + <input type="time" id="exampleInput" name="input" ng-model="example.value" + placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required /> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.time"> + Not a valid date!</span> + </div> + <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var value = element(by.binding('example.value | date: "HH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); -function ampmGetter(date, formats) { - return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; -} + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } -var DATE_FORMATS = { - yyyy: dateGetter('FullYear', 4), - yy: dateGetter('FullYear', 2, 0, true), - y: dateGetter('FullYear', 1), - MMMM: dateStrGetter('Month'), - MMM: dateStrGetter('Month', true), - MM: dateGetter('Month', 2, 1), - M: dateGetter('Month', 1, 1), - dd: dateGetter('Date', 2), - d: dateGetter('Date', 1), - HH: dateGetter('Hours', 2), - H: dateGetter('Hours', 1), - hh: dateGetter('Hours', 2, -12), - h: dateGetter('Hours', 1, -12), - mm: dateGetter('Minutes', 2), - m: dateGetter('Minutes', 1), - ss: dateGetter('Seconds', 2), - s: dateGetter('Seconds', 1), - // while ISO 8601 requires fractions to be prefixed with `.` or `,` - // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions - sss: dateGetter('Milliseconds', 3), - EEEE: dateStrGetter('Day'), - EEE: dateStrGetter('Day', true), - a: ampmGetter, - Z: timeZoneGetter, - ww: weekGetter(2), - w: weekGetter(1) -}; + it('should initialize to model', function() { + expect(value.getText()).toContain('14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); -var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/, - NUMBER_STRING = /^\-?\d+$/; + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); -/** - * @ngdoc filter - * @name date - * @kind function - * - * @description - * Formats `date` to a string based on the requested `format`. - * - * `format` string can be composed of the following elements: - * - * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) - * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) - * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) - * * `'MMMM'`: Month in year (January-December) - * * `'MMM'`: Month in year (Jan-Dec) - * * `'MM'`: Month in year, padded (01-12) - * * `'M'`: Month in year (1-12) - * * `'dd'`: Day in month, padded (01-31) - * * `'d'`: Day in month (1-31) - * * `'EEEE'`: Day in Week,(Sunday-Saturday) - * * `'EEE'`: Day in Week, (Sun-Sat) - * * `'HH'`: Hour in day, padded (00-23) - * * `'H'`: Hour in day (0-23) - * * `'hh'`: Hour in AM/PM, padded (01-12) - * * `'h'`: Hour in AM/PM, (1-12) - * * `'mm'`: Minute in hour, padded (00-59) - * * `'m'`: Minute in hour (0-59) - * * `'ss'`: Second in minute, padded (00-59) - * * `'s'`: Second in minute (0-59) - * * `'sss'`: Millisecond in second, padded (000-999) - * * `'a'`: AM/PM marker - * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) - * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year - * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year - * - * `format` string can also be one of the following predefined - * {@link guide/i18n localizable formats}: - * - * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale - * (e.g. Sep 3, 2010 12:05:08 PM) - * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM) - * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale - * (e.g. Friday, September 3, 2010) - * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010) - * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) - * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) - * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM) - * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM) - * - * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g. - * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence - * (e.g. `"h 'o''clock'"`). - * - * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or - * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its - * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is - * specified in the string input, the time is considered to be in the local timezone. - * @param {string=} format Formatting rules (see Description). If not specified, - * `mediumDate` is used. - * @param {string=} timezone Timezone to be used for formatting. Right now, only `'UTC'` is supported. - * If not specified, the timezone of the browser will be used. - * @returns {string} Formatted string or the input if input is not recognized as date/millis. - * - * @example - <example> - <file name="index.html"> - <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>: - <span>{{1288323623006 | date:'medium'}}</span><br> - <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>: - <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br> - <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>: - <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br> - <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>: - <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br> - </file> - <file name="protractor.js" type="protractor"> - it('should format date', function() { - expect(element(by.binding("1288323623006 | date:'medium'")).getText()). - toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); - expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). - toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); - expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). - toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); - expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()). - toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/); - }); - </file> + it('should be invalid if over max', function() { + setInput('23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + </file> </example> - */ -dateFilter.$inject = ['$locale']; -function dateFilter($locale) { + */ + 'time': createDateInputType('time', TIME_REGEXP, + createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']), + 'HH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[week] + * + * @description + * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support + * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * week format (yyyy-W##), for example: `2013-W02`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO week format (yyyy-W##). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO week format (yyyy-W##). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="week-input-directive" module="weekExample"> + <file name="index.html"> + <script> + angular.module('weekExample', []) + .controller('DateController', ['$scope', function($scope) { + $scope.example = { + value: new Date(2013, 0, 3) + }; + }]); + </script> + <form name="myForm" ng-controller="DateController as dateCtrl"> + <label>Pick a date between in 2013: + <input id="exampleInput" type="week" name="input" ng-model="example.value" + placeholder="YYYY-W##" min="2012-W32" + max="2013-W52" required /> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.week"> + Not a valid date!</span> + </div> + <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var value = element(by.binding('example.value | date: "yyyy-Www"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } - var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; - // 1 2 3 4 5 6 7 8 9 10 11 - function jsonStringToDate(string) { - var match; - if (match = string.match(R_ISO8601_STR)) { - var date = new Date(0), - tzHour = 0, - tzMin = 0, - dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, - timeSetter = match[8] ? date.setUTCHours : date.setHours; + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-W01'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); - if (match[9]) { - tzHour = int(match[9] + match[10]); - tzMin = int(match[9] + match[11]); - } - dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3])); - var h = int(match[4] || 0) - tzHour; - var m = int(match[5] || 0) - tzMin; - var s = int(match[6] || 0); - var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); - timeSetter.call(date, h, m, s, ms); - return date; - } - return string; - } + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + it('should be invalid if over max', function() { + setInput('2015-W01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + </file> + </example> + */ + 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'), - return function(date, format, timezone) { - var text = '', - parts = [], - fn, match; + /** + * @ngdoc input + * @name input[month] + * + * @description + * Input with month validation and transformation. In browsers that do not yet support + * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * month format (yyyy-MM), for example: `2009-01`. + * + * The model must always be a Date object, otherwise Angular will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * If the model is not set to the first of the month, the next view to model update will set it + * to the first of the month. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be + * a valid ISO month format (yyyy-MM). + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must + * be a valid ISO month format (yyyy-MM). + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="month-input-directive" module="monthExample"> + <file name="index.html"> + <script> + angular.module('monthExample', []) + .controller('DateController', ['$scope', function($scope) { + $scope.example = { + value: new Date(2013, 9, 1) + }; + }]); + </script> + <form name="myForm" ng-controller="DateController as dateCtrl"> + <label for="exampleInput">Pick a month in 2013:</label> + <input id="exampleInput" type="month" name="input" ng-model="example.value" + placeholder="yyyy-MM" min="2013-01" max="2013-12" required /> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.month"> + Not a valid month!</span> + </div> + <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var value = element(by.binding('example.value | date: "yyyy-MM"')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); - format = format || 'mediumDate'; - format = $locale.DATETIME_FORMATS[format] || format; - if (isString(date)) { - date = NUMBER_STRING.test(date) ? int(date) : jsonStringToDate(date); - } + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } - if (isNumber(date)) { - date = new Date(date); - } + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); - if (!isDate(date)) { - return date; - } + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); - while (format) { - match = DATE_FORMATS_SPLIT.exec(format); - if (match) { - parts = concat(parts, match, 1); - format = parts.pop(); - } else { - parts.push(format); - format = null; - } - } + it('should be invalid if over max', function() { + setInput('2015-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + </file> + </example> + */ + 'month': createDateInputType('month', MONTH_REGEXP, + createDateParser(MONTH_REGEXP, ['yyyy', 'MM']), + 'yyyy-MM'), - if (timezone && timezone === 'UTC') { - date = new Date(date.getTime()); - date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); - } - forEach(parts, function(value) { - fn = DATE_FORMATS[value]; - text += fn ? fn(date, $locale.DATETIME_FORMATS) - : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); - }); + /** + * @ngdoc input + * @name input[number] + * + * @description + * Text input with number validation and transformation. Sets the `number` validation + * error if not a valid number. + * + * <div class="alert alert-warning"> + * The model must always be of type `number` otherwise Angular will throw an error. + * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt} + * error docs for more information and an example of how to convert your model if necessary. + * </div> + * + * ## Issues with HTML5 constraint validation + * + * In browsers that follow the + * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29), + * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}. + * If a non-number is entered in the input, the browser will report the value as an empty string, + * which means the view / model values in `ngModel` and subsequently the scope value + * will also be an empty string. + * + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="number-input-directive" module="numberExample"> + <file name="index.html"> + <script> + angular.module('numberExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.example = { + value: 12 + }; + }]); + </script> + <form name="myForm" ng-controller="ExampleController"> + <label>Number: + <input type="number" name="input" ng-model="example.value" + min="0" max="99" required> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.number"> + Not valid number!</span> + </div> + <tt>value = {{example.value}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var value = element(by.binding('example.value')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); - return text; - }; -} + it('should initialize to model', function() { + expect(value.getText()).toContain('12'); + expect(valid.getText()).toContain('true'); + }); + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); -/** - * @ngdoc filter - * @name json - * @kind function - * - * @description - * Allows you to convert a JavaScript object into JSON string. - * - * This filter is mostly useful for debugging. When using the double curly {{value}} notation - * the binding is automatically converted to JSON. - * - * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. - * @param {number=} spacing The number of spaces to use per indentation, defaults to 2. - * @returns {string} JSON string. - * - * - * @example - <example> - <file name="index.html"> - <pre id="default-spacing">{{ {'name':'value'} | json }}</pre> - <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre> - </file> - <file name="protractor.js" type="protractor"> - it('should jsonify filtered objects', function() { - expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); - expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/); - }); - </file> - </example> - * - */ -function jsonFilter() { - return function(object, spacing) { - if (isUndefined(spacing)) { - spacing = 2; - } - return toJson(object, spacing); - }; -} + it('should be invalid if over max', function() { + input.clear(); + input.sendKeys('123'); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + </file> + </example> + */ + 'number': numberInputType, -/** - * @ngdoc filter - * @name lowercase - * @kind function - * @description - * Converts string to lowercase. - * @see angular.lowercase - */ -var lowercaseFilter = valueFn(lowercase); + /** + * @ngdoc input + * @name input[url] + * + * @description + * Text input with URL validation. Sets the `url` validation error key if the content is not a + * valid URL. + * + * <div class="alert alert-warning"> + * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex + * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify + * the built-in validators (see the {@link guide/forms Forms guide}) + * </div> + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="url-input-directive" module="urlExample"> + <file name="index.html"> + <script> + angular.module('urlExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.url = { + text: 'http://google.com' + }; + }]); + </script> + <form name="myForm" ng-controller="ExampleController"> + <label>URL: + <input type="url" name="input" ng-model="url.text" required> + <label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.url"> + Not valid url!</span> + </div> + <tt>text = {{url.text}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var text = element(by.binding('url.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('url.text')); + it('should initialize to model', function() { + expect(text.getText()).toContain('http://google.com'); + expect(valid.getText()).toContain('true'); + }); -/** - * @ngdoc filter - * @name uppercase - * @kind function - * @description - * Converts string to uppercase. - * @see angular.uppercase - */ -var uppercaseFilter = valueFn(uppercase); + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); -/** - * @ngdoc filter - * @name limitTo - * @kind function - * - * @description - * Creates a new array or string containing only a specified number of elements. The elements - * are taken from either the beginning or the end of the source array, string or number, as specified by - * the value and sign (positive or negative) of `limit`. If a number is used as input, it is - * converted to a string. - * - * @param {Array|string|number} input Source array, string or number to be limited. - * @param {string|number} limit The length of the returned array or string. If the `limit` number - * is positive, `limit` number of items from the beginning of the source array/string are copied. - * If the number is negative, `limit` number of items from the end of the source array/string - * are copied. The `limit` will be trimmed if it exceeds `array.length` - * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array - * had less than `limit` elements. - * - * @example - <example module="limitToExample"> - <file name="index.html"> - <script> - angular.module('limitToExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.numbers = [1,2,3,4,5,6,7,8,9]; - $scope.letters = "abcdefghi"; - $scope.longNumber = 2345432342; - $scope.numLimit = 3; - $scope.letterLimit = 3; - $scope.longNumberLimit = 3; - }]); - </script> - <div ng-controller="ExampleController"> - Limit {{numbers}} to: <input type="number" step="1" ng-model="numLimit"> - <p>Output numbers: {{ numbers | limitTo:numLimit }}</p> - Limit {{letters}} to: <input type="number" step="1" ng-model="letterLimit"> - <p>Output letters: {{ letters | limitTo:letterLimit }}</p> - Limit {{longNumber}} to: <input type="number" step="1" ng-model="longNumberLimit"> - <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p> - </div> - </file> - <file name="protractor.js" type="protractor"> - var numLimitInput = element(by.model('numLimit')); - var letterLimitInput = element(by.model('letterLimit')); - var longNumberLimitInput = element(by.model('longNumberLimit')); - var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); - var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); - var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit')); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); - it('should limit the number array to first three items', function() { - expect(numLimitInput.getAttribute('value')).toBe('3'); - expect(letterLimitInput.getAttribute('value')).toBe('3'); - expect(longNumberLimitInput.getAttribute('value')).toBe('3'); - expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); - expect(limitedLetters.getText()).toEqual('Output letters: abc'); - expect(limitedLongNumber.getText()).toEqual('Output long number: 234'); - }); + it('should be invalid if not url', function() { + input.clear(); + input.sendKeys('box'); - // There is a bug in safari and protractor that doesn't like the minus key - // it('should update the output when -3 is entered', function() { - // numLimitInput.clear(); - // numLimitInput.sendKeys('-3'); - // letterLimitInput.clear(); - // letterLimitInput.sendKeys('-3'); - // longNumberLimitInput.clear(); - // longNumberLimitInput.sendKeys('-3'); - // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); - // expect(limitedLetters.getText()).toEqual('Output letters: ghi'); - // expect(limitedLongNumber.getText()).toEqual('Output long number: 342'); - // }); + expect(valid.getText()).toContain('false'); + }); + </file> + </example> + */ + 'url': urlInputType, + + + /** + * @ngdoc input + * @name input[email] + * + * @description + * Text input with email validation. Sets the `email` validation error key if not a valid email + * address. + * + * <div class="alert alert-warning"> + * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex + * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can + * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide}) + * </div> + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="email-input-directive" module="emailExample"> + <file name="index.html"> + <script> + angular.module('emailExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.email = { + text: 'me@example.com' + }; + }]); + </script> + <form name="myForm" ng-controller="ExampleController"> + <label>Email: + <input type="email" name="input" ng-model="email.text" required> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.input.$error.required"> + Required!</span> + <span class="error" ng-show="myForm.input.$error.email"> + Not valid email!</span> + </div> + <tt>text = {{email.text}}</tt><br/> + <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> + <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + var text = element(by.binding('email.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('email.text')); - it('should not exceed the maximum size of input array', function() { - numLimitInput.clear(); - numLimitInput.sendKeys('100'); - letterLimitInput.clear(); - letterLimitInput.sendKeys('100'); - longNumberLimitInput.clear(); - longNumberLimitInput.sendKeys('100'); - expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); - expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); - expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342'); - }); - </file> - </example> -*/ -function limitToFilter() { - return function(input, limit) { - if (isNumber(input)) input = input.toString(); - if (!isArray(input) && !isString(input)) return input; + it('should initialize to model', function() { + expect(text.getText()).toContain('me@example.com'); + expect(valid.getText()).toContain('true'); + }); - if (Math.abs(Number(limit)) === Infinity) { - limit = Number(limit); - } else { - limit = int(limit); - } + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); - //NaN check on limit - if (limit) { - return limit > 0 ? input.slice(0, limit) : input.slice(limit); - } else { - return isString(input) ? "" : []; - } - }; -} + it('should be invalid if not email', function() { + input.clear(); + input.sendKeys('xxx'); -/** - * @ngdoc filter - * @name orderBy - * @kind function - * - * @description - * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically - * for strings and numerically for numbers. Note: if you notice numbers are not being sorted - * correctly, make sure they are actually being saved as numbers and not strings. - * - * @param {Array} array The array to sort. - * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be - * used by the comparator to determine the order of elements. - * - * Can be one of: - * - * - `function`: Getter function. The result of this function will be sorted using the - * `<`, `=`, `>` operator. - * - `string`: An Angular expression. The result of this expression is used to compare elements - * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by - * 3 first characters of a property called `name`). The result of a constant expression - * is interpreted as a property name to be used in comparisons (for example `"special name"` - * to sort object by the value of their `special name` property). An expression can be - * optionally prefixed with `+` or `-` to control ascending or descending sort order - * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array - * element itself is used to compare where sorting. - * - `Array`: An array of function or string predicates. The first predicate in the array - * is used for sorting, but when two items are equivalent, the next predicate is used. - * - * If the predicate is missing or empty then it defaults to `'+'`. - * - * @param {boolean=} reverse Reverse the order of the array. - * @returns {Array} Sorted copy of the source array. - * - * @example - <example module="orderByExample"> - <file name="index.html"> - <script> - angular.module('orderByExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.friends = - [{name:'John', phone:'555-1212', age:10}, - {name:'Mary', phone:'555-9876', age:19}, - {name:'Mike', phone:'555-4321', age:21}, - {name:'Adam', phone:'555-5678', age:35}, - {name:'Julie', phone:'555-8765', age:29}]; - $scope.predicate = '-age'; - }]); - </script> - <div ng-controller="ExampleController"> - <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre> - <hr/> - [ <a href="" ng-click="predicate=''">unsorted</a> ] - <table class="friend"> - <tr> - <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a> - (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th> - <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th> - <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th> - </tr> - <tr ng-repeat="friend in friends | orderBy:predicate:reverse"> - <td>{{friend.name}}</td> - <td>{{friend.phone}}</td> - <td>{{friend.age}}</td> - </tr> - </table> - </div> - </file> - </example> - * - * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the - * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the - * desired parameters. - * - * Example: - * - * @example - <example module="orderByExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <table class="friend"> - <tr> - <th><a href="" ng-click="reverse=false;order('name', false)">Name</a> - (<a href="" ng-click="order('-name',false)">^</a>)</th> - <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th> - <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th> - </tr> - <tr ng-repeat="friend in friends"> - <td>{{friend.name}}</td> - <td>{{friend.phone}}</td> - <td>{{friend.age}}</td> - </tr> - </table> - </div> - </file> + expect(valid.getText()).toContain('false'); + }); + </file> + </example> + */ + 'email': emailInputType, - <file name="script.js"> - angular.module('orderByExample', []) - .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) { - var orderBy = $filter('orderBy'); - $scope.friends = [ - { name: 'John', phone: '555-1212', age: 10 }, - { name: 'Mary', phone: '555-9876', age: 19 }, - { name: 'Mike', phone: '555-4321', age: 21 }, - { name: 'Adam', phone: '555-5678', age: 35 }, - { name: 'Julie', phone: '555-8765', age: 29 } - ]; - $scope.order = function(predicate, reverse) { - $scope.friends = orderBy($scope.friends, predicate, reverse); - }; - $scope.order('-age',false); - }]); - </file> -</example> - */ -orderByFilter.$inject = ['$parse']; -function orderByFilter($parse) { - return function(array, sortPredicate, reverseOrder) { - if (!(isArrayLike(array))) return array; - sortPredicate = isArray(sortPredicate) ? sortPredicate : [sortPredicate]; - if (sortPredicate.length === 0) { sortPredicate = ['+']; } - sortPredicate = sortPredicate.map(function(predicate) { - var descending = false, get = predicate || identity; - if (isString(predicate)) { - if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { - descending = predicate.charAt(0) == '-'; - predicate = predicate.substring(1); - } - if (predicate === '') { - // Effectively no predicate was passed so we compare identity - return reverseComparator(compare, descending); - } - get = $parse(predicate); - if (get.constant) { - var key = get(); - return reverseComparator(function(a, b) { - return compare(a[key], b[key]); - }, descending); - } - } - return reverseComparator(function(a, b) { - return compare(get(a),get(b)); - }, descending); - }); - return slice.call(array).sort(reverseComparator(comparator, reverseOrder)); - function comparator(o1, o2) { - for (var i = 0; i < sortPredicate.length; i++) { - var comp = sortPredicate[i](o1, o2); - if (comp !== 0) return comp; - } - return 0; - } - function reverseComparator(comp, descending) { - return descending - ? function(a, b) {return comp(b,a);} - : comp; - } + /** + * @ngdoc input + * @name input[radio] + * + * @description + * HTML radio button. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string} value The value to which the `ngModel` expression should be set when selected. + * Note that `value` only supports `string` values, i.e. the scope model needs to be a string, + * too. Use `ngValue` if you need complex models (`number`, `object`, ...). + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio + * is selected. Should be used instead of the `value` attribute if you need + * a non-string `ngModel` (`boolean`, `array`, ...). + * + * @example + <example name="radio-input-directive" module="radioExample"> + <file name="index.html"> + <script> + angular.module('radioExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.color = { + name: 'blue' + }; + $scope.specialValue = { + "id": "12345", + "value": "green" + }; + }]); + </script> + <form name="myForm" ng-controller="ExampleController"> + <label> + <input type="radio" ng-model="color.name" value="red"> + Red + </label><br/> + <label> + <input type="radio" ng-model="color.name" ng-value="specialValue"> + Green + </label><br/> + <label> + <input type="radio" ng-model="color.name" value="blue"> + Blue + </label><br/> + <tt>color = {{color.name | json}}</tt><br/> + </form> + Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. + </file> + <file name="protractor.js" type="protractor"> + it('should change state', function() { + var color = element(by.binding('color.name')); - function isPrimitive(value) { - switch (typeof value) { - case 'number': /* falls through */ - case 'boolean': /* falls through */ - case 'string': - return true; - default: - return false; - } - } + expect(color.getText()).toContain('blue'); - function objectToString(value) { - if (value === null) return 'null'; - if (typeof value.valueOf === 'function') { - value = value.valueOf(); - if (isPrimitive(value)) return value; - } - if (typeof value.toString === 'function') { - value = value.toString(); - if (isPrimitive(value)) return value; - } - return ''; - } + element.all(by.model('color.name')).get(0).click(); - function compare(v1, v2) { - var t1 = typeof v1; - var t2 = typeof v2; - if (t1 === t2 && t1 === "object") { - v1 = objectToString(v1); - v2 = objectToString(v2); - } - if (t1 === t2) { - if (t1 === "string") { - v1 = v1.toLowerCase(); - v2 = v2.toLowerCase(); - } - if (v1 === v2) return 0; - return v1 < v2 ? -1 : 1; - } else { - return t1 < t2 ? -1 : 1; - } - } - }; -} + expect(color.getText()).toContain('red'); + }); + </file> + </example> + */ + 'radio': radioInputType, -function ngDirective(directive) { - if (isFunction(directive)) { - directive = { - link: directive - }; - } - directive.restrict = directive.restrict || 'AC'; - return valueFn(directive); -} -/** - * @ngdoc directive - * @name a - * @restrict E - * - * @description - * Modifies the default behavior of the html A tag so that the default action is prevented when - * the href attribute is empty. - * - * This change permits the easy creation of action links with the `ngClick` directive - * without changing the location or causing page reloads, e.g.: - * `<a href="" ng-click="list.addItem()">Add Item</a>` - */ -var htmlAnchorDirective = valueFn({ - restrict: 'E', - compile: function(element, attr) { - if (!attr.href && !attr.xlinkHref && !attr.name) { - return function(scope, element) { - // If the linked element is not an anchor tag anymore, do nothing - if (element[0].nodeName.toLowerCase() !== 'a') return; + /** + * @ngdoc input + * @name input[checkbox] + * + * @description + * HTML checkbox. + * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {expression=} ngTrueValue The value to which the expression should be set when selected. + * @param {expression=} ngFalseValue The value to which the expression should be set when not selected. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + <example name="checkbox-input-directive" module="checkboxExample"> + <file name="index.html"> + <script> + angular.module('checkboxExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.checkboxModel = { + value1 : true, + value2 : 'YES' + }; + }]); + </script> + <form name="myForm" ng-controller="ExampleController"> + <label>Value1: + <input type="checkbox" ng-model="checkboxModel.value1"> + </label><br/> + <label>Value2: + <input type="checkbox" ng-model="checkboxModel.value2" + ng-true-value="'YES'" ng-false-value="'NO'"> + </label><br/> + <tt>value1 = {{checkboxModel.value1}}</tt><br/> + <tt>value2 = {{checkboxModel.value2}}</tt><br/> + </form> + </file> + <file name="protractor.js" type="protractor"> + it('should change state', function() { + var value1 = element(by.binding('checkboxModel.value1')); + var value2 = element(by.binding('checkboxModel.value2')); - // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. - var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? - 'xlink:href' : 'href'; - element.on('click', function(event) { - // if we have no href url, then don't navigate anywhere. - if (!element.attr(href)) { - event.preventDefault(); - } - }); - }; - } - } -}); + expect(value1.getText()).toContain('true'); + expect(value2.getText()).toContain('YES'); -/** - * @ngdoc directive - * @name ngHref - * @restrict A - * @priority 99 - * - * @description - * Using Angular markup like `{{hash}}` in an href attribute will - * make the link go to the wrong URL if the user clicks it before - * Angular has a chance to replace the `{{hash}}` markup with its - * value. Until Angular replaces the markup the link will be broken - * and will most likely return a 404 error. The `ngHref` directive - * solves this problem. - * - * The wrong way to write it: - * ```html - * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a> - * ``` - * - * The correct way to write it: - * ```html - * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a> - * ``` - * - * @element A - * @param {template} ngHref any string which can contain `{{}}` markup. - * - * @example - * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes - * in links and their different behaviors: - <example> - <file name="index.html"> - <input ng-model="value" /><br /> - <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br /> - <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br /> - <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br /> - <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br /> - <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br /> - <a id="link-6" ng-href="{{value}}">link</a> (link, change location) - </file> - <file name="protractor.js" type="protractor"> - it('should execute ng-click but not reload when href without value', function() { - element(by.id('link-1')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('1'); - expect(element(by.id('link-1')).getAttribute('href')).toBe(''); - }); + element(by.model('checkboxModel.value1')).click(); + element(by.model('checkboxModel.value2')).click(); - it('should execute ng-click but not reload when href empty string', function() { - element(by.id('link-2')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('2'); - expect(element(by.id('link-2')).getAttribute('href')).toBe(''); - }); + expect(value1.getText()).toContain('false'); + expect(value2.getText()).toContain('NO'); + }); + </file> + </example> + */ + 'checkbox': checkboxInputType, - it('should execute ng-click and change url when ng-href specified', function() { - expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); + 'hidden': noop, + 'button': noop, + 'submit': noop, + 'reset': noop, + 'file': noop +}; - element(by.id('link-3')).click(); +function stringBasedInputType(ctrl) { + ctrl.$formatters.push(function(value) { + return ctrl.$isEmpty(value) ? value : value.toString(); + }); +} - // At this point, we navigate away from an Angular page, so we need - // to use browser.driver to get the base webdriver. +function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); +} - browser.wait(function() { - return browser.driver.getCurrentUrl().then(function(url) { - return url.match(/\/123$/); - }); - }, 5000, 'page should navigate to /123'); - }); +function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { + var type = lowercase(element[0].type); - xit('should execute ng-click but not reload when href empty string and name specified', function() { - element(by.id('link-4')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('4'); - expect(element(by.id('link-4')).getAttribute('href')).toBe(''); - }); + // In composition mode, users are still inputing intermediate text buffer, + // hold the listener until composition is done. + // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent + if (!$sniffer.android) { + var composing = false; - it('should execute ng-click but not reload when no href but name specified', function() { - element(by.id('link-5')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('5'); - expect(element(by.id('link-5')).getAttribute('href')).toBe(null); - }); + element.on('compositionstart', function(data) { + composing = true; + }); - it('should only change url when only ng-href', function() { - element(by.model('value')).clear(); - element(by.model('value')).sendKeys('6'); - expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); + element.on('compositionend', function() { + composing = false; + listener(); + }); + } - element(by.id('link-6')).click(); + var listener = function(ev) { + if (timeout) { + $browser.defer.cancel(timeout); + timeout = null; + } + if (composing) return; + var value = element.val(), + event = ev && ev.type; - // At this point, we navigate away from an Angular page, so we need - // to use browser.driver to get the base webdriver. - browser.wait(function() { - return browser.driver.getCurrentUrl().then(function(url) { - return url.match(/\/6$/); - }); - }, 5000, 'page should navigate to /6'); - }); - </file> - </example> - */ + // By default we will trim the value + // If the attribute ng-trim exists we will avoid trimming + // If input type is 'password', the value is never trimmed + if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) { + value = trim(value); + } -/** - * @ngdoc directive - * @name ngSrc - * @restrict A - * @priority 99 - * - * @description - * Using Angular markup like `{{hash}}` in a `src` attribute doesn't - * work right: The browser will fetch from the URL with the literal - * text `{{hash}}` until Angular replaces the expression inside - * `{{hash}}`. The `ngSrc` directive solves this problem. - * - * The buggy way to write it: - * ```html - * <img src="http://www.gravatar.com/avatar/{{hash}}"/> - * ``` - * - * The correct way to write it: - * ```html - * <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/> - * ``` - * - * @element IMG - * @param {template} ngSrc any string which can contain `{{}}` markup. - */ + // If a control is suffering from bad input (due to native validators), browsers discard its + // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the + // control's value is the same empty value twice in a row. + if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) { + ctrl.$setViewValue(value, event); + } + }; -/** - * @ngdoc directive - * @name ngSrcset - * @restrict A - * @priority 99 - * - * @description - * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't - * work right: The browser will fetch from the URL with the literal - * text `{{hash}}` until Angular replaces the expression inside - * `{{hash}}`. The `ngSrcset` directive solves this problem. - * - * The buggy way to write it: - * ```html - * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/> - * ``` - * - * The correct way to write it: - * ```html - * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/> - * ``` - * - * @element IMG - * @param {template} ngSrcset any string which can contain `{{}}` markup. - */ + // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the + // input event on backspace, delete or cut + if ($sniffer.hasEvent('input')) { + element.on('input', listener); + } else { + var timeout; -/** - * @ngdoc directive - * @name ngDisabled - * @restrict A - * @priority 100 - * - * @description - * - * We shouldn't do this, because it will make the button enabled on Chrome/Firefox but not on IE8 and older IEs: - * ```html - * <div ng-init="scope = { isDisabled: false }"> - * <button disabled="{{scope.isDisabled}}">Disabled</button> - * </div> - * ``` - * - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as disabled. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngDisabled` directive solves this problem for the `disabled` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. - * - * @example - <example> - <file name="index.html"> - Click me to toggle: <input type="checkbox" ng-model="checked"><br/> - <button ng-model="button" ng-disabled="checked">Button</button> - </file> - <file name="protractor.js" type="protractor"> - it('should toggle button', function() { - expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy(); - element(by.model('checked')).click(); - expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy(); + var deferListener = function(ev, input, origValue) { + if (!timeout) { + timeout = $browser.defer(function() { + timeout = null; + if (!input || input.value !== origValue) { + listener(ev); + } }); - </file> - </example> - * - * @element INPUT - * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, - * then special attribute "disabled" will be set on the element - */ + } + }; + element.on('keydown', function(event) { + var key = event.keyCode; -/** - * @ngdoc directive - * @name ngChecked - * @restrict A - * @priority 100 - * - * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as checked. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngChecked` directive solves this problem for the `checked` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. - * @example - <example> - <file name="index.html"> - Check me to check both: <input type="checkbox" ng-model="master"><br/> - <input id="checkSlave" type="checkbox" ng-checked="master"> - </file> - <file name="protractor.js" type="protractor"> - it('should check both checkBoxes', function() { - expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy(); - element(by.model('master')).click(); - expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy(); - }); - </file> - </example> - * - * @element INPUT - * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, - * then special attribute "checked" will be set on the element - */ + // ignore + // command modifiers arrows + if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + deferListener(event, this, this.value); + }); -/** - * @ngdoc directive - * @name ngReadonly - * @restrict A - * @priority 100 - * - * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as readonly. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngReadonly` directive solves this problem for the `readonly` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. - * @example - <example> - <file name="index.html"> - Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/> - <input type="text" ng-readonly="checked" value="I'm Angular"/> - </file> - <file name="protractor.js" type="protractor"> - it('should toggle readonly attr', function() { - expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy(); - element(by.model('checked')).click(); - expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy(); - }); - </file> - </example> - * - * @element INPUT - * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, - * then special attribute "readonly" will be set on the element - */ + // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it + if ($sniffer.hasEvent('paste')) { + element.on('paste cut', deferListener); + } + } + // if user paste into input using mouse on older browser + // or form autocomplete on newer browser, we need "change" event to catch it + element.on('change', listener); -/** - * @ngdoc directive - * @name ngSelected - * @restrict A - * @priority 100 - * - * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as selected. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngSelected` directive solves this problem for the `selected` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. - * - * @example - <example> - <file name="index.html"> - Check me to select: <input type="checkbox" ng-model="selected"><br/> - <select> - <option>Hello!</option> - <option id="greet" ng-selected="selected">Greetings!</option> - </select> - </file> - <file name="protractor.js" type="protractor"> - it('should select Greetings!', function() { - expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); - element(by.model('selected')).click(); - expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); - }); - </file> - </example> - * - * @element OPTION - * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, - * then special attribute "selected" will be set on the element - */ + ctrl.$render = function() { + element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); + }; +} -/** - * @ngdoc directive - * @name ngOpen - * @restrict A - * @priority 100 - * - * @description - * The HTML specification does not require browsers to preserve the values of boolean attributes - * such as open. (Their presence means true and their absence means false.) - * If we put an Angular interpolation expression into such an attribute then the - * binding information would be lost when the browser removes the attribute. - * The `ngOpen` directive solves this problem for the `open` attribute. - * This complementary directive is not removed by the browser and so provides - * a permanent reliable place to store the binding information. - * @example - <example> - <file name="index.html"> - Check me check multiple: <input type="checkbox" ng-model="open"><br/> - <details id="details" ng-open="open"> - <summary>Show/Hide me</summary> - </details> - </file> - <file name="protractor.js" type="protractor"> - it('should toggle open', function() { - expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); - element(by.model('open')).click(); - expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); - }); - </file> - </example> - * - * @element DETAILS - * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, - * then special attribute "open" will be set on the element - */ +function weekParser(isoWeek, existingDate) { + if (isDate(isoWeek)) { + return isoWeek; + } -var ngAttributeAliasDirectives = {}; + if (isString(isoWeek)) { + WEEK_REGEXP.lastIndex = 0; + var parts = WEEK_REGEXP.exec(isoWeek); + if (parts) { + var year = +parts[1], + week = +parts[2], + hours = 0, + minutes = 0, + seconds = 0, + milliseconds = 0, + firstThurs = getFirstThursdayOfYear(year), + addDays = (week - 1) * 7; + if (existingDate) { + hours = existingDate.getHours(); + minutes = existingDate.getMinutes(); + seconds = existingDate.getSeconds(); + milliseconds = existingDate.getMilliseconds(); + } -// boolean attrs are evaluated -forEach(BOOLEAN_ATTR, function(propName, attrName) { - // binding to multiple is not supported - if (propName == "multiple") return; + return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); + } + } - var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = function() { - return { - restrict: 'A', - priority: 100, - link: function(scope, element, attr) { - scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { - attr.$set(attrName, !!value); - }); + return NaN; +} + +function createDateParser(regexp, mapping) { + return function(iso, date) { + var parts, map; + + if (isDate(iso)) { + return iso; + } + + if (isString(iso)) { + // When a date is JSON'ified to wraps itself inside of an extra + // set of double quotes. This makes the date parsing code unable + // to match the date string and parse it as a date. + if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') { + iso = iso.substring(1, iso.length - 1); } - }; - }; -}); + if (ISO_DATE_REGEXP.test(iso)) { + return new Date(iso); + } + regexp.lastIndex = 0; + parts = regexp.exec(iso); -// aliased input attrs are evaluated -forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { - ngAttributeAliasDirectives[ngAttr] = function() { - return { - priority: 100, - link: function(scope, element, attr) { - //special case ngPattern when a literal regular expression value - //is used as the expression (this way we don't have to watch anything). - if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") { - var match = attr.ngPattern.match(REGEX_STRING_REGEXP); - if (match) { - attr.$set("ngPattern", new RegExp(match[1], match[2])); - return; - } + if (parts) { + parts.shift(); + if (date) { + map = { + yyyy: date.getFullYear(), + MM: date.getMonth() + 1, + dd: date.getDate(), + HH: date.getHours(), + mm: date.getMinutes(), + ss: date.getSeconds(), + sss: date.getMilliseconds() / 1000 + }; + } else { + map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }; } - scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { - attr.$set(ngAttr, value); + forEach(parts, function(part, index) { + if (index < mapping.length) { + map[mapping[index]] = +part; + } }); + return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0); } - }; + } + + return NaN; }; -}); +} -// ng-src, ng-srcset, ng-href are interpolated -forEach(['src', 'srcset', 'href'], function(attrName) { - var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = function() { - return { - priority: 99, // it needs to run after the attributes are interpolated - link: function(scope, element, attr) { - var propName = attrName, - name = attrName; +function createDateInputType(type, regexp, parseDate, format) { + return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + var timezone = ctrl && ctrl.$options && ctrl.$options.timezone; + var previousDate; - if (attrName === 'href' && - toString.call(element.prop('href')) === '[object SVGAnimatedString]') { - name = 'xlinkHref'; - attr.$attr[name] = 'xlink:href'; - propName = null; + ctrl.$$parserName = type; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (regexp.test(value)) { + // Note: We cannot read ctrl.$modelValue, as there might be a different + // parser/formatter in the processing chain so that the model + // contains some different data format! + var parsedDate = parseDate(value, previousDate); + if (timezone) { + parsedDate = convertTimezoneToLocal(parsedDate, timezone); } + return parsedDate; + } + return undefined; + }); - attr.$observe(normalized, function(value) { - if (!value) { - if (attrName === 'href') { - attr.$set(name, null); - } - return; - } + ctrl.$formatters.push(function(value) { + if (value && !isDate(value)) { + throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value); + } + if (isValidDate(value)) { + previousDate = value; + if (previousDate && timezone) { + previousDate = convertTimezoneToLocal(previousDate, timezone, true); + } + return $filter('date')(value, format, timezone); + } else { + previousDate = null; + return ''; + } + }); - attr.$set(name, value); + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal; + }; + attr.$observe('min', function(val) { + minVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } - // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist - // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need - // to set the property as well to achieve the desired effect. - // we use attr[attrName] value since $set can sanitize the url. - if (msie && propName) element.prop(propName, attr[name]); - }); - } - }; - }; -}); + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal; + }; + attr.$observe('max', function(val) { + maxVal = parseObservedDateValue(val); + ctrl.$validate(); + }); + } -/* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true - */ -var nullFormCtrl = { - $addControl: noop, - $$renameControl: nullFormRenameControl, - $removeControl: noop, - $setValidity: noop, - $setDirty: noop, - $setPristine: noop, - $setSubmitted: noop -}, -SUBMITTED_CLASS = 'ng-submitted'; + function isValidDate(value) { + // Invalid Date: getTime() returns NaN + return value && !(value.getTime && value.getTime() !== value.getTime()); + } -function nullFormRenameControl(control, name) { - control.$name = name; + function parseObservedDateValue(val) { + return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined; + } + }; } -/** - * @ngdoc type - * @name form.FormController - * - * @property {boolean} $pristine True if user has not interacted with the form yet. - * @property {boolean} $dirty True if user has already interacted with the form. - * @property {boolean} $valid True if all of the containing forms and controls are valid. - * @property {boolean} $invalid True if at least one containing control or form is invalid. - * @property {boolean} $submitted True if user has submitted the form even if its invalid. - * - * @property {Object} $error Is an object hash, containing references to controls or - * forms with failing validators, where: - * - * - keys are validation tokens (error names), - * - values are arrays of controls or forms that have a failing validator for given error name. - * - * Built-in validation tokens: - * - * - `email` - * - `max` - * - `maxlength` - * - `min` - * - `minlength` - * - `number` - * - `pattern` - * - `required` - * - `url` - * - `date` - * - `datetimelocal` - * - `time` - * - `week` - * - `month` - * - * @description - * `FormController` keeps track of all its controls and nested forms as well as the state of them, - * such as being valid/invalid or dirty/pristine. - * - * Each {@link ng.directive:form form} directive creates an instance - * of `FormController`. - * - */ -//asks for $scope to fool the BC controller module -FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate']; -function FormController(element, attrs, $scope, $animate, $interpolate) { - var form = this, - controls = []; +function badInputChecker(scope, element, attr, ctrl) { + var node = element[0]; + var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); + if (nativeValidation) { + ctrl.$parsers.push(function(value) { + var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; + // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430): + // - also sets validity.badInput (should only be validity.typeMismatch). + // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email) + // - can ignore this case as we can still read out the erroneous email... + return validity.badInput && !validity.typeMismatch ? undefined : value; + }); + } +} - var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl; +function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { + badInputChecker(scope, element, attr, ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - // init state - form.$error = {}; - form.$$success = {}; - form.$pending = undefined; - form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope); - form.$dirty = false; - form.$pristine = true; - form.$valid = true; - form.$invalid = false; - form.$submitted = false; + ctrl.$$parserName = 'number'; + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (NUMBER_REGEXP.test(value)) return parseFloat(value); + return undefined; + }); - parentForm.$addControl(form); + ctrl.$formatters.push(function(value) { + if (!ctrl.$isEmpty(value)) { + if (!isNumber(value)) { + throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value); + } + value = value.toString(); + } + return value; + }); - /** - * @ngdoc method - * @name form.FormController#$rollbackViewValue - * - * @description - * Rollback all form controls pending updates to the `$modelValue`. - * - * Updates may be pending by a debounced event or because the input is waiting for a some future - * event defined in `ng-model-options`. This method is typically needed by the reset button of - * a form that uses `ng-model-options` to pend updates. - */ - form.$rollbackViewValue = function() { - forEach(controls, function(control) { - control.$rollbackViewValue(); + if (isDefined(attr.min) || attr.ngMin) { + var minVal; + ctrl.$validators.min = function(value) { + return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; + }; + + attr.$observe('min', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + minVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); }); - }; + } - /** - * @ngdoc method - * @name form.FormController#$commitViewValue - * - * @description - * Commit all form controls pending updates to the `$modelValue`. - * - * Updates may be pending by a debounced event or because the input is waiting for a some future - * event defined in `ng-model-options`. This method is rarely needed as `NgModelController` - * usually handles calling this in response to input events. - */ - form.$commitViewValue = function() { - forEach(controls, function(control) { - control.$commitViewValue(); + if (isDefined(attr.max) || attr.ngMax) { + var maxVal; + ctrl.$validators.max = function(value) { + return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; + }; + + attr.$observe('max', function(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val, 10); + } + maxVal = isNumber(val) && !isNaN(val) ? val : undefined; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); }); + } +} + +function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$$parserName = 'url'; + ctrl.$validators.url = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || URL_REGEXP.test(value); }; +} - /** - * @ngdoc method - * @name form.FormController#$addControl - * - * @description - * Register a control with the form. - * - * Input elements using ngModelController do this automatically when they are linked. - */ - form.$addControl = function(control) { - // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored - // and not added to the scope. Now we throw an error. - assertNotHasOwnProperty(control.$name, 'input'); - controls.push(control); +function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); - if (control.$name) { - form[control.$name] = control; - } + ctrl.$$parserName = 'email'; + ctrl.$validators.email = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); }; +} - // Private API: rename a form control - form.$$renameControl = function(control, newName) { - var oldName = control.$name; +function radioInputType(scope, element, attr, ctrl) { + // make the name unique, if not defined + if (isUndefined(attr.name)) { + element.attr('name', nextUid()); + } - if (form[oldName] === control) { - delete form[oldName]; + var listener = function(ev) { + if (element[0].checked) { + ctrl.$setViewValue(attr.value, ev && ev.type); } - form[newName] = control; - control.$name = newName; }; - /** - * @ngdoc method - * @name form.FormController#$removeControl - * - * @description - * Deregister a control from the form. - * - * Input elements using ngModelController do this automatically when they are destroyed. - */ - form.$removeControl = function(control) { - if (control.$name && form[control.$name] === control) { - delete form[control.$name]; - } - forEach(form.$pending, function(value, name) { - form.$setValidity(name, null, control); - }); - forEach(form.$error, function(value, name) { - form.$setValidity(name, null, control); - }); - forEach(form.$$success, function(value, name) { - form.$setValidity(name, null, control); - }); + element.on('click', listener); - arrayRemove(controls, control); + ctrl.$render = function() { + var value = attr.value; + element[0].checked = (value == ctrl.$viewValue); }; + attr.$observe('value', ctrl.$render); +} - /** - * @ngdoc method - * @name form.FormController#$setValidity - * - * @description - * Sets the validity of a form control. - * - * This method will also propagate to parent forms. - */ - addSetValidityMethod({ - ctrl: this, - $element: element, - set: function(object, property, controller) { - var list = object[property]; - if (!list) { - object[property] = [controller]; - } else { - var index = list.indexOf(controller); - if (index === -1) { - list.push(controller); - } - } - }, - unset: function(object, property, controller) { - var list = object[property]; - if (!list) { - return; - } - arrayRemove(list, controller); - if (list.length === 0) { - delete object[property]; - } - }, - parentForm: parentForm, - $animate: $animate - }); +function parseConstantExpr($parse, context, name, expression, fallback) { + var parseFn; + if (isDefined(expression)) { + parseFn = $parse(expression); + if (!parseFn.constant) { + throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' + + '`{1}`.', name, expression); + } + return parseFn(context); + } + return fallback; +} - /** - * @ngdoc method - * @name form.FormController#$setDirty - * - * @description - * Sets the form to a dirty state. - * - * This method can be called to add the 'ng-dirty' class and set the form to a dirty - * state (ng-dirty class). This method will also propagate to parent forms. - */ - form.$setDirty = function() { - $animate.removeClass(element, PRISTINE_CLASS); - $animate.addClass(element, DIRTY_CLASS); - form.$dirty = true; - form.$pristine = false; - parentForm.$setDirty(); - }; +function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true); + var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false); - /** - * @ngdoc method - * @name form.FormController#$setPristine - * - * @description - * Sets the form to its pristine state. - * - * This method can be called to remove the 'ng-dirty' class and set the form to its pristine - * state (ng-pristine class). This method will also propagate to all the controls contained - * in this form. - * - * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after - * saving or resetting it. - */ - form.$setPristine = function() { - $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS); - form.$dirty = false; - form.$pristine = true; - form.$submitted = false; - forEach(controls, function(control) { - control.$setPristine(); - }); + var listener = function(ev) { + ctrl.$setViewValue(element[0].checked, ev && ev.type); }; - /** - * @ngdoc method - * @name form.FormController#$setUntouched - * - * @description - * Sets the form to its untouched state. - * - * This method can be called to remove the 'ng-touched' class and set the form controls to their - * untouched state (ng-untouched class). - * - * Setting a form controls back to their untouched state is often useful when setting the form - * back to its pristine state. - */ - form.$setUntouched = function() { - forEach(controls, function(control) { - control.$setUntouched(); - }); + element.on('click', listener); + + ctrl.$render = function() { + element[0].checked = ctrl.$viewValue; }; - /** - * @ngdoc method - * @name form.FormController#$setSubmitted - * - * @description - * Sets the form to its submitted state. - */ - form.$setSubmitted = function() { - $animate.addClass(element, SUBMITTED_CLASS); - form.$submitted = true; - parentForm.$setSubmitted(); + // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false` + // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert + // it to a boolean. + ctrl.$isEmpty = function(value) { + return value === false; }; + + ctrl.$formatters.push(function(value) { + return equals(value, trueValue); + }); + + ctrl.$parsers.push(function(value) { + return value ? trueValue : falseValue; + }); } + /** * @ngdoc directive - * @name ngForm - * @restrict EAC + * @name textarea + * @restrict E * * @description - * Nestable alias of {@link ng.directive:form `form`} directive. HTML - * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a - * sub-group of controls needs to be determined. - * - * Note: the purpose of `ngForm` is to group controls, - * but not to be a replacement for the `<form>` tag with all of its capabilities - * (e.g. posting to the server, ...). - * - * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into - * related scope, under this name. + * HTML textarea element control with angular data-binding. The data-binding and validation + * properties of this element are exactly the same as those of the + * {@link ng.directive:input input element}. * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. */ - /** + +/** * @ngdoc directive - * @name form + * @name input * @restrict E * * @description - * Directive that instantiates - * {@link form.FormController FormController}. - * - * If the `name` attribute is specified, the form controller is published onto the current scope under - * this name. - * - * # Alias: {@link ng.directive:ngForm `ngForm`} - * - * In Angular forms can be nested. This means that the outer form is valid when all of the child - * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so - * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to - * `<form>` but can be nested. This allows you to have nested forms, which is very useful when - * using Angular validation directives in forms that are dynamically generated using the - * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name` - * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an - * `ngForm` directive and nest these in an outer `form` element. - * - * - * # CSS classes - * - `ng-valid` is set if the form is valid. - * - `ng-invalid` is set if the form is invalid. - * - `ng-pristine` is set if the form is pristine. - * - `ng-dirty` is set if the form is dirty. - * - `ng-submitted` is set if the form was submitted. + * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding, + * input state control, and validation. + * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers. * - * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * <div class="alert alert-warning"> + * **Note:** Not every feature offered is available for all input types. + * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`. + * </div> * + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {boolean=} ngRequired Sets `required` attribute if set to true + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match + * a RegExp found by evaluating the Angular expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.<br /> + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange Angular expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. * - * # Submitting a form and preventing the default action + * @example + <example name="input-directive" module="inputExample"> + <file name="index.html"> + <script> + angular.module('inputExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.user = {name: 'guest', last: 'visitor'}; + }]); + </script> + <div ng-controller="ExampleController"> + <form name="myForm"> + <label> + User name: + <input type="text" name="userName" ng-model="user.name" required> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.userName.$error.required"> + Required!</span> + </div> + <label> + Last name: + <input type="text" name="lastName" ng-model="user.last" + ng-minlength="3" ng-maxlength="10"> + </label> + <div role="alert"> + <span class="error" ng-show="myForm.lastName.$error.minlength"> + Too short!</span> + <span class="error" ng-show="myForm.lastName.$error.maxlength"> + Too long!</span> + </div> + </form> + <hr> + <tt>user = {{user}}</tt><br/> + <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/> + <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/> + <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/> + <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/> + <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/> + <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/> + </div> + </file> + <file name="protractor.js" type="protractor"> + var user = element(by.exactBinding('user')); + var userNameValid = element(by.binding('myForm.userName.$valid')); + var lastNameValid = element(by.binding('myForm.lastName.$valid')); + var lastNameError = element(by.binding('myForm.lastName.$error')); + var formValid = element(by.binding('myForm.$valid')); + var userNameInput = element(by.model('user.name')); + var userLastInput = element(by.model('user.last')); + + it('should initialize to model', function() { + expect(user.getText()).toContain('{"name":"guest","last":"visitor"}'); + expect(userNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if empty when required', function() { + userNameInput.clear(); + userNameInput.sendKeys(''); + + expect(user.getText()).toContain('{"last":"visitor"}'); + expect(userNameValid.getText()).toContain('false'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be valid if empty when min length is set', function() { + userLastInput.clear(); + userLastInput.sendKeys(''); + + expect(user.getText()).toContain('{"name":"guest","last":""}'); + expect(lastNameValid.getText()).toContain('true'); + expect(formValid.getText()).toContain('true'); + }); + + it('should be invalid if less than required min length', function() { + userLastInput.clear(); + userLastInput.sendKeys('xx'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('minlength'); + expect(formValid.getText()).toContain('false'); + }); + + it('should be invalid if longer than max length', function() { + userLastInput.clear(); + userLastInput.sendKeys('some ridiculously long name'); + + expect(user.getText()).toContain('{"name":"guest"}'); + expect(lastNameValid.getText()).toContain('false'); + expect(lastNameError.getText()).toContain('maxlength'); + expect(formValid.getText()).toContain('false'); + }); + </file> + </example> + */ +var inputDirective = ['$browser', '$sniffer', '$filter', '$parse', + function($browser, $sniffer, $filter, $parse) { + return { + restrict: 'E', + require: ['?ngModel'], + link: { + pre: function(scope, element, attr, ctrls) { + if (ctrls[0]) { + (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer, + $browser, $filter, $parse); + } + } + } + }; +}]; + + + +var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; +/** + * @ngdoc directive + * @name ngValue * - * Since the role of forms in client-side Angular applications is different than in classical - * roundtrip apps, it is desirable for the browser not to translate the form submission into a full - * page reload that sends the data to the server. Instead some javascript logic should be triggered - * to handle the form submission in an application-specific way. + * @description + * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`}, + * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to + * the bound value. * - * For this reason, Angular prevents the default action (form submission to the server) unless the - * `<form>` element has an `action` attribute specified. + * `ngValue` is useful when dynamically generating lists of radio buttons using + * {@link ngRepeat `ngRepeat`}, as shown below. * - * You can use one of the following two ways to specify what javascript method should be called when - * a form is submitted: + * Likewise, `ngValue` can be used to generate `<option>` elements for + * the {@link select `select`} element. In that case however, only strings are supported + * for the `value `attribute, so the resulting `ngModel` will always be a string. + * Support for `select` models with non-string values is available via `ngOptions`. * - * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element - * - {@link ng.directive:ngClick ngClick} directive on the first - * button or input field of type submit (input[type=submit]) + * @element input + * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute + * of the `input` element * - * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit} - * or {@link ng.directive:ngClick ngClick} directives. - * This is because of the following form submission rules in the HTML specification: + * @example + <example name="ngValue-directive" module="valueExample"> + <file name="index.html"> + <script> + angular.module('valueExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.names = ['pizza', 'unicorns', 'robots']; + $scope.my = { favorite: 'unicorns' }; + }]); + </script> + <form ng-controller="ExampleController"> + <h2>Which is your favorite?</h2> + <label ng-repeat="name in names" for="{{name}}"> + {{name}} + <input type="radio" + ng-model="my.favorite" + ng-value="name" + id="{{name}}" + name="favorite"> + </label> + <div>You chose {{my.favorite}}</div> + </form> + </file> + <file name="protractor.js" type="protractor"> + var favorite = element(by.binding('my.favorite')); + + it('should initialize to model', function() { + expect(favorite.getText()).toContain('unicorns'); + }); + it('should bind the values to the inputs', function() { + element.all(by.model('my.favorite')).get(0).click(); + expect(favorite.getText()).toContain('pizza'); + }); + </file> + </example> + */ +var ngValueDirective = function() { + return { + restrict: 'A', + priority: 100, + compile: function(tpl, tplAttr) { + if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { + return function ngValueConstantLink(scope, elm, attr) { + attr.$set('value', scope.$eval(attr.ngValue)); + }; + } else { + return function ngValueLink(scope, elm, attr) { + scope.$watch(attr.ngValue, function valueWatchAction(value) { + attr.$set('value', value); + }); + }; + } + } + }; +}; + +/** + * @ngdoc directive + * @name ngBind + * @restrict AC * - * - If a form has only one input field then hitting enter in this field triggers form submit - * (`ngSubmit`) - * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter - * doesn't trigger submit - * - if a form has one or more input fields and one or more buttons or input[type=submit] then - * hitting enter in any of the input fields will trigger the click handler on the *first* button or - * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) + * @description + * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element + * with the value of a given expression, and to update the text content when the value of that + * expression changes. * - * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is - * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` - * to have access to the updated model. + * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like + * `{{ expression }}` which is similar but less verbose. * - * ## Animation Hooks + * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily + * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an + * element attribute, it makes the bindings invisible to the user while the page is loading. * - * Animations in ngForm are triggered when any of the associated CSS classes are added and removed. - * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any - * other validations that are performed within the form. Animations in ngForm are similar to how - * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well - * as JS animations. + * An alternative solution to this problem would be using the + * {@link ng.directive:ngCloak ngCloak} directive. * - * The following example shows a simple way to utilize CSS transitions to style a form element - * that has been rendered as invalid after it has been validated: * - * <pre> - * //be sure to include ngAnimate as a module to hook into more - * //advanced animations - * .my-form { - * transition:0.5s linear all; - * background: white; - * } - * .my-form.ng-invalid { - * background: red; - * color:white; - * } - * </pre> + * @element ANY + * @param {expression} ngBind {@link guide/expression Expression} to evaluate. * * @example - <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample"> - <file name="index.html"> + * Enter a name in the Live Preview text box; the greeting below the text box changes instantly. + <example module="bindExample"> + <file name="index.html"> <script> - angular.module('formExample', []) - .controller('FormController', ['$scope', function($scope) { - $scope.userType = 'guest'; + angular.module('bindExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.name = 'Whirled'; }]); </script> - <style> - .my-form { - -webkit-transition:all linear 0.5s; - transition:all linear 0.5s; - background: transparent; - } - .my-form.ng-invalid { - background: red; - } - </style> - <form name="myForm" ng-controller="FormController" class="my-form"> - userType: <input name="input" ng-model="userType" required> - <span class="error" ng-show="myForm.input.$error.required">Required!</span><br> - <tt>userType = {{userType}}</tt><br> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br> - </form> - </file> - <file name="protractor.js" type="protractor"> - it('should initialize to model', function() { - var userType = element(by.binding('userType')); - var valid = element(by.binding('myForm.input.$valid')); + <div ng-controller="ExampleController"> + <label>Enter name: <input type="text" ng-model="name"></label><br> + Hello <span ng-bind="name"></span>! + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-bind', function() { + var nameInput = element(by.model('name')); - expect(userType.getText()).toContain('guest'); - expect(valid.getText()).toContain('true'); + expect(element(by.binding('name')).getText()).toBe('Whirled'); + nameInput.clear(); + nameInput.sendKeys('world'); + expect(element(by.binding('name')).getText()).toBe('world'); + }); + </file> + </example> + */ +var ngBindDirective = ['$compile', function($compile) { + return { + restrict: 'AC', + compile: function ngBindCompile(templateElement) { + $compile.$$addBindingClass(templateElement); + return function ngBindLink(scope, element, attr) { + $compile.$$addBindingInfo(element, attr.ngBind); + element = element[0]; + scope.$watch(attr.ngBind, function ngBindWatchAction(value) { + element.textContent = value === undefined ? '' : value; }); + }; + } + }; +}]; - it('should be invalid if empty', function() { - var userType = element(by.binding('userType')); - var valid = element(by.binding('myForm.input.$valid')); - var userInput = element(by.model('userType')); - - userInput.clear(); - userInput.sendKeys(''); - expect(userType.getText()).toEqual('userType ='); - expect(valid.getText()).toContain('false'); - }); - </file> - </example> +/** + * @ngdoc directive + * @name ngBindTemplate * - * @param {string=} name Name of the form. If specified, the form controller will be published into - * related scope, under this name. - */ -var formDirectiveFactory = function(isNgForm) { - return ['$timeout', function($timeout) { - var formDirective = { - name: 'form', - restrict: isNgForm ? 'EAC' : 'E', - controller: FormController, - compile: function ngFormCompile(formElement) { - // Setup initial state of the control - formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); - - return { - pre: function ngFormPreLink(scope, formElement, attr, controller) { - // if `action` attr is not present on the form, prevent the default action (submission) - if (!('action' in attr)) { - // we can't use jq events because if a form is destroyed during submission the default - // action is not prevented. see #1238 - // - // IE 9 is not affected because it doesn't fire a submit event and try to do a full - // page reload if the form was destroyed by submission of the form via a click handler - // on a button in the form. Looks like an IE9 specific bug. - var handleFormSubmission = function(event) { - scope.$apply(function() { - controller.$commitViewValue(); - controller.$setSubmitted(); - }); - - event.preventDefault(); - }; - - addEventListenerFn(formElement[0], 'submit', handleFormSubmission); - - // unregister the preventDefault listener so that we don't not leak memory but in a - // way that will achieve the prevention of the default action. - formElement.on('$destroy', function() { - $timeout(function() { - removeEventListenerFn(formElement[0], 'submit', handleFormSubmission); - }, 0, false); - }); - } - - var parentFormCtrl = controller.$$parentForm, - alias = controller.$name; - - if (alias) { - setter(scope, null, alias, controller, alias); - attr.$observe(attr.name ? 'name' : 'ngForm', function(newValue) { - if (alias === newValue) return; - setter(scope, null, alias, undefined, alias); - alias = newValue; - setter(scope, null, alias, controller, alias); - parentFormCtrl.$$renameControl(controller, alias); - }); - } - formElement.on('$destroy', function() { - parentFormCtrl.$removeControl(controller); - if (alias) { - setter(scope, null, alias, undefined, alias); - } - extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards - }); - } - }; - } - }; - - return formDirective; - }]; -}; - -var formDirective = formDirectiveFactory(); -var ngFormDirective = formDirectiveFactory(true); + * @description + * The `ngBindTemplate` directive specifies that the element + * text content should be replaced with the interpolation of the template + * in the `ngBindTemplate` attribute. + * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}` + * expressions. This directive is needed since some HTML elements + * (such as TITLE and OPTION) cannot contain SPAN elements. + * + * @element ANY + * @param {string} ngBindTemplate template of form + * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval. + * + * @example + * Try it here: enter text in text box and watch the greeting change. + <example module="bindExample"> + <file name="index.html"> + <script> + angular.module('bindExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.salutation = 'Hello'; + $scope.name = 'World'; + }]); + </script> + <div ng-controller="ExampleController"> + <label>Salutation: <input type="text" ng-model="salutation"></label><br> + <label>Name: <input type="text" ng-model="name"></label><br> + <pre ng-bind-template="{{salutation}} {{name}}!"></pre> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-bind', function() { + var salutationElem = element(by.binding('salutation')); + var salutationInput = element(by.model('salutation')); + var nameInput = element(by.model('name')); -/* global VALID_CLASS: false, - INVALID_CLASS: false, - PRISTINE_CLASS: false, - DIRTY_CLASS: false, - UNTOUCHED_CLASS: false, - TOUCHED_CLASS: false, - $ngModelMinErr: false, -*/ + expect(salutationElem.getText()).toBe('Hello World!'); -// Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 -var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/; -var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; -var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i; -var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; -var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/; -var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; -var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/; -var MONTH_REGEXP = /^(\d{4})-(\d\d)$/; -var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; + salutationInput.clear(); + salutationInput.sendKeys('Greetings'); + nameInput.clear(); + nameInput.sendKeys('user'); -var inputType = { + expect(salutationElem.getText()).toBe('Greetings user!'); + }); + </file> + </example> + */ +var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) { + return { + compile: function ngBindTemplateCompile(templateElement) { + $compile.$$addBindingClass(templateElement); + return function ngBindTemplateLink(scope, element, attr) { + var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate)); + $compile.$$addBindingInfo(element, interpolateFn.expressions); + element = element[0]; + attr.$observe('ngBindTemplate', function(value) { + element.textContent = value === undefined ? '' : value; + }); + }; + } + }; +}]; - /** - * @ngdoc input - * @name input[text] - * - * @description - * Standard HTML text input with angular data binding, inherited by most of the `input` elements. - * - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Adds `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match - * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. - * This parameter is ignored for input[type=password] controls, which will never trim the - * input. - * - * @example - <example name="text-input-directive" module="textInputExample"> - <file name="index.html"> - <script> - angular.module('textInputExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.example = { - text: 'guest', - word: /^\s*\w*\s*$/ - }; - }]); - </script> - <form name="myForm" ng-controller="ExampleController"> - Single word: <input type="text" name="input" ng-model="example.text" - ng-pattern="example.word" required ng-trim="false"> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.pattern"> - Single word only!</span> - <tt>text = {{example.text}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var text = element(by.binding('example.text')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.text')); +/** + * @ngdoc directive + * @name ngBindHtml + * + * @description + * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default, + * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service. + * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link + * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize} + * in your module's dependencies, you need to include "angular-sanitize.js" in your application. + * + * You may also bypass sanitization for values you know are safe. To do so, bind to + * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example + * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}. + * + * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you + * will have an exception (instead of an exploit.) + * + * @element ANY + * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate. + * + * @example - it('should initialize to model', function() { - expect(text.getText()).toContain('guest'); - expect(valid.getText()).toContain('true'); - }); + <example module="bindHtmlExample" deps="angular-sanitize.js"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <p ng-bind-html="myHTML"></p> + </div> + </file> - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); + <file name="script.js"> + angular.module('bindHtmlExample', ['ngSanitize']) + .controller('ExampleController', ['$scope', function($scope) { + $scope.myHTML = + 'I am an <code>HTML</code>string with ' + + '<a href="#">links!</a> and other <em>stuff</em>'; + }]); + </file> - expect(text.getText()).toEqual('text ='); - expect(valid.getText()).toContain('false'); - }); + <file name="protractor.js" type="protractor"> + it('should check ng-bind-html', function() { + expect(element(by.binding('myHTML')).getText()).toBe( + 'I am an HTMLstring with links! and other stuff'); + }); + </file> + </example> + */ +var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) { + return { + restrict: 'A', + compile: function ngBindHtmlCompile(tElement, tAttrs) { + var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml); + var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) { + return (value || '').toString(); + }); + $compile.$$addBindingClass(tElement); - it('should be invalid if multi word', function() { - input.clear(); - input.sendKeys('hello world'); + return function ngBindHtmlLink(scope, element, attr) { + $compile.$$addBindingInfo(element, attr.ngBindHtml); - expect(valid.getText()).toContain('false'); - }); - </file> - </example> - */ - 'text': textInputType, + scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() { + // we re-evaluate the expr because we want a TrustedValueHolderType + // for $sce, not a string + element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || ''); + }); + }; + } + }; +}]; - /** - * @ngdoc input - * @name input[date] - * - * @description - * Input with date validation and transformation. In browsers that do not yet support - * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601 - * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many - * modern browsers do not yet support this input type, it is important to provide cues to users on the - * expected input format via a placeholder or label. - * - * The model must always be a Date object, otherwise Angular will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a - * valid ISO date string (yyyy-MM-dd). - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be - * a valid ISO date string (yyyy-MM-dd). - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="date-input-directive" module="dateInputExample"> - <file name="index.html"> - <script> - angular.module('dateInputExample', []) - .controller('DateController', ['$scope', function($scope) { - $scope.example = { - value: new Date(2013, 9, 22) - }; - }]); - </script> - <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a date in 2013: - <input type="date" id="exampleInput" name="input" ng-model="example.value" - placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.date"> - Not a valid date!</span> - <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var value = element(by.binding('example.value | date: "yyyy-MM-dd"')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.value')); +/** + * @ngdoc directive + * @name ngChange + * + * @description + * Evaluate the given expression when the user changes the input. + * The expression is evaluated immediately, unlike the JavaScript onchange event + * which only triggers at the end of a change (usually, when the user leaves the + * form element or presses the return key). + * + * The `ngChange` expression is only evaluated when a change in the input value causes + * a new value to be committed to the model. + * + * It will not be evaluated: + * * if the value returned from the `$parsers` transformation pipeline has not changed + * * if the input has continued to be invalid since the model will stay `null` + * * if the model is changed programmatically and not by a change to the input value + * + * + * Note, this directive requires `ngModel` to be present. + * + * @element input + * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change + * in input value. + * + * @example + * <example name="ngChange-directive" module="changeExample"> + * <file name="index.html"> + * <script> + * angular.module('changeExample', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.counter = 0; + * $scope.change = function() { + * $scope.counter++; + * }; + * }]); + * </script> + * <div ng-controller="ExampleController"> + * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" /> + * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" /> + * <label for="ng-change-example2">Confirmed</label><br /> + * <tt>debug = {{confirmed}}</tt><br/> + * <tt>counter = {{counter}}</tt><br/> + * </div> + * </file> + * <file name="protractor.js" type="protractor"> + * var counter = element(by.binding('counter')); + * var debug = element(by.binding('confirmed')); + * + * it('should evaluate the expression if changing from view', function() { + * expect(counter.getText()).toContain('0'); + * + * element(by.id('ng-change-example1')).click(); + * + * expect(counter.getText()).toContain('1'); + * expect(debug.getText()).toContain('true'); + * }); + * + * it('should not evaluate the expression if changing from model', function() { + * element(by.id('ng-change-example2')).click(); - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (see https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } + * expect(counter.getText()).toContain('0'); + * expect(debug.getText()).toContain('true'); + * }); + * </file> + * </example> + */ +var ngChangeDirective = valueFn({ + restrict: 'A', + require: 'ngModel', + link: function(scope, element, attr, ctrl) { + ctrl.$viewChangeListeners.push(function() { + scope.$eval(attr.ngChange); + }); + } +}); - it('should initialize to model', function() { - expect(value.getText()).toContain('2013-10-22'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); +function classDirective(name, selector) { + name = 'ngClass' + name; + return ['$animate', function($animate) { + return { + restrict: 'AC', + link: function(scope, element, attr) { + var oldVal; - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); + scope.$watch(attr[name], ngClassWatchAction, true); - it('should be invalid if over max', function() { - setInput('2015-01-01'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); + attr.$observe('class', function(value) { + ngClassWatchAction(scope.$eval(attr[name])); }); - </file> - </example> - */ - 'date': createDateInputType('date', DATE_REGEXP, - createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']), - 'yyyy-MM-dd'), - /** - * @ngdoc input - * @name input[datetime-local] - * - * @description - * Input with datetime validation and transformation. In browsers that do not yet support - * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. - * - * The model must always be a Date object, otherwise Angular will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a - * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be - * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="datetimelocal-input-directive" module="dateExample"> - <file name="index.html"> - <script> - angular.module('dateExample', []) - .controller('DateController', ['$scope', function($scope) { - $scope.example = { - value: new Date(2010, 11, 28, 14, 57) - }; - }]); - </script> - <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a date between in 2013: - <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value" - placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.datetimelocal"> - Not a valid date!</span> - <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.value')); - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } + if (name !== 'ngClass') { + scope.$watch('$index', function($index, old$index) { + // jshint bitwise: false + var mod = $index & 1; + if (mod !== (old$index & 1)) { + var classes = arrayClasses(scope.$eval(attr[name])); + mod === selector ? + addClasses(classes) : + removeClasses(classes); + } + }); + } - it('should initialize to model', function() { - expect(value.getText()).toContain('2010-12-28T14:57:00'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); + function addClasses(classes) { + var newClasses = digestClassCounts(classes, 1); + attr.$addClass(newClasses); + } - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); + function removeClasses(classes) { + var newClasses = digestClassCounts(classes, -1); + attr.$removeClass(newClasses); + } - it('should be invalid if over max', function() { - setInput('2015-01-01T23:59:00'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - </file> - </example> - */ - 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP, - createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']), - 'yyyy-MM-ddTHH:mm:ss.sss'), + function digestClassCounts(classes, count) { + // Use createMap() to prevent class assumptions involving property + // names in Object.prototype + var classCounts = element.data('$classCounts') || createMap(); + var classesToUpdate = []; + forEach(classes, function(className) { + if (count > 0 || classCounts[className]) { + classCounts[className] = (classCounts[className] || 0) + count; + if (classCounts[className] === +(count > 0)) { + classesToUpdate.push(className); + } + } + }); + element.data('$classCounts', classCounts); + return classesToUpdate.join(' '); + } - /** - * @ngdoc input - * @name input[time] - * - * @description - * Input with time validation and transformation. In browsers that do not yet support - * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a - * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`. - * - * The model must always be a Date object, otherwise Angular will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a - * valid ISO time format (HH:mm:ss). - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a - * valid ISO time format (HH:mm:ss). - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="time-input-directive" module="timeExample"> - <file name="index.html"> - <script> - angular.module('timeExample', []) - .controller('DateController', ['$scope', function($scope) { - $scope.example = { - value: new Date(1970, 0, 1, 14, 57, 0) - }; - }]); - </script> - <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a between 8am and 5pm: - <input type="time" id="exampleInput" name="input" ng-model="example.value" - placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.time"> - Not a valid date!</span> - <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var value = element(by.binding('example.value | date: "HH:mm:ss"')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.value')); + function updateClasses(oldClasses, newClasses) { + var toAdd = arrayDifference(newClasses, oldClasses); + var toRemove = arrayDifference(oldClasses, newClasses); + toAdd = digestClassCounts(toAdd, 1); + toRemove = digestClassCounts(toRemove, -1); + if (toAdd && toAdd.length) { + $animate.addClass(element, toAdd); + } + if (toRemove && toRemove.length) { + $animate.removeClass(element, toRemove); + } + } - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); + function ngClassWatchAction(newVal) { + if (selector === true || scope.$index % 2 === selector) { + var newClasses = arrayClasses(newVal || []); + if (!oldVal) { + addClasses(newClasses); + } else if (!equals(newVal,oldVal)) { + var oldClasses = arrayClasses(oldVal); + updateClasses(oldClasses, newClasses); + } + } + oldVal = shallowCopy(newVal); + } } + }; - it('should initialize to model', function() { - expect(value.getText()).toContain('14:57:00'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); - - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - - it('should be invalid if over max', function() { - setInput('23:59:00'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - </file> - </example> - */ - 'time': createDateInputType('time', TIME_REGEXP, - createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']), - 'HH:mm:ss.sss'), + function arrayDifference(tokens1, tokens2) { + var values = []; - /** - * @ngdoc input - * @name input[week] - * - * @description - * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support - * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * week format (yyyy-W##), for example: `2013-W02`. - * - * The model must always be a Date object, otherwise Angular will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a - * valid ISO week format (yyyy-W##). - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be - * a valid ISO week format (yyyy-W##). - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="week-input-directive" module="weekExample"> - <file name="index.html"> - <script> - angular.module('weekExample', []) - .controller('DateController', ['$scope', function($scope) { - $scope.example = { - value: new Date(2013, 0, 3) - }; - }]); - </script> - <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a date between in 2013: - <input id="exampleInput" type="week" name="input" ng-model="example.value" - placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.week"> - Not a valid date!</span> - <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var value = element(by.binding('example.value | date: "yyyy-Www"')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.value')); + outer: + for (var i = 0; i < tokens1.length; i++) { + var token = tokens1[i]; + for (var j = 0; j < tokens2.length; j++) { + if (token == tokens2[j]) continue outer; + } + values.push(token); + } + return values; + } - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); + function arrayClasses(classVal) { + var classes = []; + if (isArray(classVal)) { + forEach(classVal, function(v) { + classes = classes.concat(arrayClasses(v)); + }); + return classes; + } else if (isString(classVal)) { + return classVal.split(' '); + } else if (isObject(classVal)) { + forEach(classVal, function(v, k) { + if (v) { + classes = classes.concat(k.split(' ')); + } + }); + return classes; } + return classVal; + } + }]; +} - it('should initialize to model', function() { - expect(value.getText()).toContain('2013-W01'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); +/** + * @ngdoc directive + * @name ngClass + * @restrict AC + * + * @description + * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding + * an expression that represents all classes to be added. + * + * The directive operates in three different ways, depending on which of three types the expression + * evaluates to: + * + * 1. If the expression evaluates to a string, the string should be one or more space-delimited class + * names. + * + * 2. If the expression evaluates to an object, then for each key-value pair of the + * object with a truthy value the corresponding key is used as a class name. + * + * 3. If the expression evaluates to an array, each element of the array should either be a string as in + * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array + * to give you more control over what CSS classes appear. See the code below for an example of this. + * + * + * The directive won't add duplicate classes if a particular class was already set. + * + * When the expression changes, the previously added classes are removed and only then are the + * new classes added. + * + * @animations + * **add** - happens just before the class is applied to the elements + * + * **remove** - happens just before the class is removed from the element + * + * @element ANY + * @param {expression} ngClass {@link guide/expression Expression} to eval. The result + * of the evaluation can be a string representing space delimited class + * names, an array, or a map of class names to boolean values. In the case of a map, the + * names of the properties whose values are truthy will be added as css classes to the + * element. + * + * @example Example that demonstrates basic bindings via ngClass directive. + <example> + <file name="index.html"> + <p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p> + <label> + <input type="checkbox" ng-model="deleted"> + deleted (apply "strike" class) + </label><br> + <label> + <input type="checkbox" ng-model="important"> + important (apply "bold" class) + </label><br> + <label> + <input type="checkbox" ng-model="error"> + error (apply "has-error" class) + </label> + <hr> + <p ng-class="style">Using String Syntax</p> + <input type="text" ng-model="style" + placeholder="Type: bold strike red" aria-label="Type: bold strike red"> + <hr> + <p ng-class="[style1, style2, style3]">Using Array Syntax</p> + <input ng-model="style1" + placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red"><br> + <input ng-model="style2" + placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 2"><br> + <input ng-model="style3" + placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 3"><br> + <hr> + <p ng-class="[style4, {orange: warning}]">Using Array and Map Syntax</p> + <input ng-model="style4" placeholder="Type: bold, strike" aria-label="Type: bold, strike"><br> + <label><input type="checkbox" ng-model="warning"> warning (apply "orange" class)</label> + </file> + <file name="style.css"> + .strike { + text-decoration: line-through; + } + .bold { + font-weight: bold; + } + .red { + color: red; + } + .has-error { + color: red; + background-color: yellow; + } + .orange { + color: orange; + } + </file> + <file name="protractor.js" type="protractor"> + var ps = element.all(by.css('p')); - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); + it('should let you toggle the class', function() { - it('should be invalid if over max', function() { - setInput('2015-W01'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - </file> - </example> - */ - 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'), + expect(ps.first().getAttribute('class')).not.toMatch(/bold/); + expect(ps.first().getAttribute('class')).not.toMatch(/has-error/); - /** - * @ngdoc input - * @name input[month] - * - * @description - * Input with month validation and transformation. In browsers that do not yet support - * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * month format (yyyy-MM), for example: `2009-01`. - * - * The model must always be a Date object, otherwise Angular will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * If the model is not set to the first of the month, the next view to model update will set it - * to the first of the month. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be - * a valid ISO month format (yyyy-MM). - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must - * be a valid ISO month format (yyyy-MM). - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="month-input-directive" module="monthExample"> - <file name="index.html"> - <script> - angular.module('monthExample', []) - .controller('DateController', ['$scope', function($scope) { - $scope.example = { - value: new Date(2013, 9, 1) - }; - }]); - </script> - <form name="myForm" ng-controller="DateController as dateCtrl"> - Pick a month in 2013: - <input id="exampleInput" type="month" name="input" ng-model="example.value" - placeholder="yyyy-MM" min="2013-01" max="2013-12" required /> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.month"> - Not a valid month!</span> - <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var value = element(by.binding('example.value | date: "yyyy-MM"')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.value')); + element(by.model('important')).click(); + expect(ps.first().getAttribute('class')).toMatch(/bold/); + + element(by.model('error')).click(); + expect(ps.first().getAttribute('class')).toMatch(/has-error/); + }); - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } + it('should let you toggle string example', function() { + expect(ps.get(1).getAttribute('class')).toBe(''); + element(by.model('style')).clear(); + element(by.model('style')).sendKeys('red'); + expect(ps.get(1).getAttribute('class')).toBe('red'); + }); - it('should initialize to model', function() { - expect(value.getText()).toContain('2013-10'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); + it('array example should have 3 classes', function() { + expect(ps.get(2).getAttribute('class')).toBe(''); + element(by.model('style1')).sendKeys('bold'); + element(by.model('style2')).sendKeys('strike'); + element(by.model('style3')).sendKeys('red'); + expect(ps.get(2).getAttribute('class')).toBe('bold strike red'); + }); - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); + it('array with map example should have 2 classes', function() { + expect(ps.last().getAttribute('class')).toBe(''); + element(by.model('style4')).sendKeys('bold'); + element(by.model('warning')).click(); + expect(ps.last().getAttribute('class')).toBe('bold orange'); + }); + </file> + </example> - it('should be invalid if over max', function() { - setInput('2015-01'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - </file> + ## Animations + + The example below demonstrates how to perform animations using ngClass. + + <example module="ngAnimate" deps="angular-animate.js" animations="true"> + <file name="index.html"> + <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'"> + <input id="clearbtn" type="button" value="clear" ng-click="myVar=''"> + <br> + <span class="base-class" ng-class="myVar">Sample Text</span> + </file> + <file name="style.css"> + .base-class { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + } + + .base-class.my-class { + color: red; + font-size:3em; + } + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-class', function() { + expect(element(by.css('.base-class')).getAttribute('class')).not. + toMatch(/my-class/); + + element(by.id('setbtn')).click(); + + expect(element(by.css('.base-class')).getAttribute('class')). + toMatch(/my-class/); + + element(by.id('clearbtn')).click(); + + expect(element(by.css('.base-class')).getAttribute('class')).not. + toMatch(/my-class/); + }); + </file> </example> - */ - 'month': createDateInputType('month', MONTH_REGEXP, - createDateParser(MONTH_REGEXP, ['yyyy', 'MM']), - 'yyyy-MM'), - /** - * @ngdoc input - * @name input[number] - * - * @description - * Text input with number validation and transformation. Sets the `number` validation - * error if not a valid number. - * - * The model must always be a number, otherwise Angular will throw an error. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match - * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="number-input-directive" module="numberExample"> - <file name="index.html"> - <script> - angular.module('numberExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.example = { - value: 12 - }; - }]); - </script> - <form name="myForm" ng-controller="ExampleController"> - Number: <input type="number" name="input" ng-model="example.value" - min="0" max="99" required> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.number"> - Not valid number!</span> - <tt>value = {{example.value}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var value = element(by.binding('example.value')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.value')); - it('should initialize to model', function() { - expect(value.getText()).toContain('12'); - expect(valid.getText()).toContain('true'); - }); + ## ngClass and pre-existing CSS3 Transitions/Animations + The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure. + Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder + any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure + to view the step by step details of {@link $animate#addClass $animate.addClass} and + {@link $animate#removeClass $animate.removeClass}. + */ +var ngClassDirective = classDirective('', true); - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('false'); - }); +/** + * @ngdoc directive + * @name ngClassOdd + * @restrict AC + * + * @description + * The `ngClassOdd` and `ngClassEven` directives work exactly as + * {@link ng.directive:ngClass ngClass}, except they work in + * conjunction with `ngRepeat` and take effect only on odd (even) rows. + * + * This directive can be applied only within the scope of an + * {@link ng.directive:ngRepeat ngRepeat}. + * + * @element ANY + * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result + * of the evaluation can be a string representing space delimited class names or an array. + * + * @example + <example> + <file name="index.html"> + <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']"> + <li ng-repeat="name in names"> + <span ng-class-odd="'odd'" ng-class-even="'even'"> + {{name}} + </span> + </li> + </ol> + </file> + <file name="style.css"> + .odd { + color: red; + } + .even { + color: blue; + } + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-class-odd and ng-class-even', function() { + expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). + toMatch(/odd/); + expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). + toMatch(/even/); + }); + </file> + </example> + */ +var ngClassOddDirective = classDirective('Odd', 0); - it('should be invalid if over max', function() { - input.clear(); - input.sendKeys('123'); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('false'); - }); - </file> - </example> - */ - 'number': numberInputType, +/** + * @ngdoc directive + * @name ngClassEven + * @restrict AC + * + * @description + * The `ngClassOdd` and `ngClassEven` directives work exactly as + * {@link ng.directive:ngClass ngClass}, except they work in + * conjunction with `ngRepeat` and take effect only on odd (even) rows. + * + * This directive can be applied only within the scope of an + * {@link ng.directive:ngRepeat ngRepeat}. + * + * @element ANY + * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The + * result of the evaluation can be a string representing space delimited class names or an array. + * + * @example + <example> + <file name="index.html"> + <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']"> + <li ng-repeat="name in names"> + <span ng-class-odd="'odd'" ng-class-even="'even'"> + {{name}} + </span> + </li> + </ol> + </file> + <file name="style.css"> + .odd { + color: red; + } + .even { + color: blue; + } + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-class-odd and ng-class-even', function() { + expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). + toMatch(/odd/); + expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). + toMatch(/even/); + }); + </file> + </example> + */ +var ngClassEvenDirective = classDirective('Even', 1); + +/** + * @ngdoc directive + * @name ngCloak + * @restrict AC + * + * @description + * The `ngCloak` directive is used to prevent the Angular html template from being briefly + * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this + * directive to avoid the undesirable flicker effect caused by the html template display. + * + * The directive can be applied to the `<body>` element, but the preferred usage is to apply + * multiple `ngCloak` directives to small portions of the page to permit progressive rendering + * of the browser view. + * + * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and + * `angular.min.js`. + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * + * ```css + * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { + * display: none !important; + * } + * ``` + * + * When this css rule is loaded by the browser, all html elements (including their children) that + * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive + * during the compilation of the template it deletes the `ngCloak` element attribute, making + * the compiled element visible. + * + * For the best result, the `angular.js` script must be loaded in the head section of the html + * document; alternatively, the css rule above must be included in the external stylesheet of the + * application. + * + * @element ANY + * + * @example + <example> + <file name="index.html"> + <div id="template1" ng-cloak>{{ 'hello' }}</div> + <div id="template2" class="ng-cloak">{{ 'world' }}</div> + </file> + <file name="protractor.js" type="protractor"> + it('should remove the template directive and css class', function() { + expect($('#template1').getAttribute('ng-cloak')). + toBeNull(); + expect($('#template2').getAttribute('ng-cloak')). + toBeNull(); + }); + </file> + </example> + * + */ +var ngCloakDirective = ngDirective({ + compile: function(element, attr) { + attr.$set('ngCloak', undefined); + element.removeClass('ng-cloak'); + } +}); + +/** + * @ngdoc directive + * @name ngController + * + * @description + * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular + * supports the principles behind the Model-View-Controller design pattern. + * + * MVC components in angular: + * + * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties + * are accessed through bindings. + * * View — The template (HTML with data bindings) that is rendered into the View. + * * Controller — The `ngController` directive specifies a Controller class; the class contains business + * logic behind the application to decorate the scope with functions and values + * + * Note that you can also attach controllers to the DOM by declaring it in a route definition + * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller + * again using `ng-controller` in the template itself. This will cause the controller to be attached + * and executed twice. + * + * @element ANY + * @scope + * @priority 500 + * @param {expression} ngController Name of a constructor function registered with the current + * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression} + * that on the current scope evaluates to a constructor function. + * + * The controller instance can be published into a scope property by specifying + * `ng-controller="as propertyName"`. + * + * If the current `$controllerProvider` is configured to use globals (via + * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may + * also be the name of a globally accessible constructor function (not recommended). + * + * @example + * Here is a simple form for editing user contact information. Adding, removing, clearing, and + * greeting are methods declared on the controller (see source tab). These methods can + * easily be called from the angular markup. Any changes to the data are automatically reflected + * in the View without the need for a manual update. + * + * Two different declaration styles are included below: + * + * * one binds methods and properties directly onto the controller using `this`: + * `ng-controller="SettingsController1 as settings"` + * * one injects `$scope` into the controller: + * `ng-controller="SettingsController2"` + * + * The second option is more common in the Angular community, and is generally used in boilerplates + * and in this guide. However, there are advantages to binding properties directly to the controller + * and avoiding scope. + * + * * Using `controller as` makes it obvious which controller you are accessing in the template when + * multiple controllers apply to an element. + * * If you are writing your controllers as classes you have easier access to the properties and + * methods, which will appear on the scope, from inside the controller code. + * * Since there is always a `.` in the bindings, you don't have to worry about prototypal + * inheritance masking primitives. + * + * This example demonstrates the `controller as` syntax. + * + * <example name="ngControllerAs" module="controllerAsExample"> + * <file name="index.html"> + * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings"> + * <label>Name: <input type="text" ng-model="settings.name"/></label> + * <button ng-click="settings.greet()">greet</button><br/> + * Contact: + * <ul> + * <li ng-repeat="contact in settings.contacts"> + * <select ng-model="contact.type" aria-label="Contact method" id="select_{{$index}}"> + * <option>phone</option> + * <option>email</option> + * </select> + * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" /> + * <button ng-click="settings.clearContact(contact)">clear</button> + * <button ng-click="settings.removeContact(contact)" aria-label="Remove">X</button> + * </li> + * <li><button ng-click="settings.addContact()">add</button></li> + * </ul> + * </div> + * </file> + * <file name="app.js"> + * angular.module('controllerAsExample', []) + * .controller('SettingsController1', SettingsController1); + * + * function SettingsController1() { + * this.name = "John Smith"; + * this.contacts = [ + * {type: 'phone', value: '408 555 1212'}, + * {type: 'email', value: 'john.smith@example.org'} ]; + * } + * + * SettingsController1.prototype.greet = function() { + * alert(this.name); + * }; + * + * SettingsController1.prototype.addContact = function() { + * this.contacts.push({type: 'email', value: 'yourname@example.org'}); + * }; + * + * SettingsController1.prototype.removeContact = function(contactToRemove) { + * var index = this.contacts.indexOf(contactToRemove); + * this.contacts.splice(index, 1); + * }; + * + * SettingsController1.prototype.clearContact = function(contact) { + * contact.type = 'phone'; + * contact.value = ''; + * }; + * </file> + * <file name="protractor.js" type="protractor"> + * it('should check controller as', function() { + * var container = element(by.id('ctrl-as-exmpl')); + * expect(container.element(by.model('settings.name')) + * .getAttribute('value')).toBe('John Smith'); + * + * var firstRepeat = + * container.element(by.repeater('contact in settings.contacts').row(0)); + * var secondRepeat = + * container.element(by.repeater('contact in settings.contacts').row(1)); + * + * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) + * .toBe('408 555 1212'); + * + * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) + * .toBe('john.smith@example.org'); + * + * firstRepeat.element(by.buttonText('clear')).click(); + * + * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) + * .toBe(''); + * + * container.element(by.buttonText('add')).click(); + * + * expect(container.element(by.repeater('contact in settings.contacts').row(2)) + * .element(by.model('contact.value')) + * .getAttribute('value')) + * .toBe('yourname@example.org'); + * }); + * </file> + * </example> + * + * This example demonstrates the "attach to `$scope`" style of controller. + * + * <example name="ngController" module="controllerExample"> + * <file name="index.html"> + * <div id="ctrl-exmpl" ng-controller="SettingsController2"> + * <label>Name: <input type="text" ng-model="name"/></label> + * <button ng-click="greet()">greet</button><br/> + * Contact: + * <ul> + * <li ng-repeat="contact in contacts"> + * <select ng-model="contact.type" id="select_{{$index}}"> + * <option>phone</option> + * <option>email</option> + * </select> + * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" /> + * <button ng-click="clearContact(contact)">clear</button> + * <button ng-click="removeContact(contact)">X</button> + * </li> + * <li>[ <button ng-click="addContact()">add</button> ]</li> + * </ul> + * </div> + * </file> + * <file name="app.js"> + * angular.module('controllerExample', []) + * .controller('SettingsController2', ['$scope', SettingsController2]); + * + * function SettingsController2($scope) { + * $scope.name = "John Smith"; + * $scope.contacts = [ + * {type:'phone', value:'408 555 1212'}, + * {type:'email', value:'john.smith@example.org'} ]; + * + * $scope.greet = function() { + * alert($scope.name); + * }; + * + * $scope.addContact = function() { + * $scope.contacts.push({type:'email', value:'yourname@example.org'}); + * }; + * + * $scope.removeContact = function(contactToRemove) { + * var index = $scope.contacts.indexOf(contactToRemove); + * $scope.contacts.splice(index, 1); + * }; + * + * $scope.clearContact = function(contact) { + * contact.type = 'phone'; + * contact.value = ''; + * }; + * } + * </file> + * <file name="protractor.js" type="protractor"> + * it('should check controller', function() { + * var container = element(by.id('ctrl-exmpl')); + * + * expect(container.element(by.model('name')) + * .getAttribute('value')).toBe('John Smith'); + * + * var firstRepeat = + * container.element(by.repeater('contact in contacts').row(0)); + * var secondRepeat = + * container.element(by.repeater('contact in contacts').row(1)); + * + * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) + * .toBe('408 555 1212'); + * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) + * .toBe('john.smith@example.org'); + * + * firstRepeat.element(by.buttonText('clear')).click(); + * + * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) + * .toBe(''); + * + * container.element(by.buttonText('add')).click(); + * + * expect(container.element(by.repeater('contact in contacts').row(2)) + * .element(by.model('contact.value')) + * .getAttribute('value')) + * .toBe('yourname@example.org'); + * }); + * </file> + *</example> + */ +var ngControllerDirective = [function() { + return { + restrict: 'A', + scope: true, + controller: '@', + priority: 500 + }; +}]; - /** - * @ngdoc input - * @name input[url] - * - * @description - * Text input with URL validation. Sets the `url` validation error key if the content is not a - * valid URL. - * - * <div class="alert alert-warning"> - * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex - * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify - * the built-in validators (see the {@link guide/forms Forms guide}) - * </div> - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match - * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="url-input-directive" module="urlExample"> +/** + * @ngdoc directive + * @name ngCsp + * + * @element html + * @description + * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support. + * + * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps. + * + * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things). + * For Angular to be CSP compatible there are only two things that we need to do differently: + * + * - don't use `Function` constructor to generate optimized value getters + * - don't inject custom stylesheet into the document + * + * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp` + * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will + * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will + * be raised. + * + * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically + * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}). + * To make those directives work in CSP mode, include the `angular-csp.css` manually. + * + * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This + * autodetection however triggers a CSP error to be logged in the console: + * + * ``` + * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of + * script in the following Content Security Policy directive: "default-src 'self'". Note that + * 'script-src' was not explicitly set, so 'default-src' is used as a fallback. + * ``` + * + * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp` + * directive on the root element of the application or on the `angular.js` script tag, whichever + * appears first in the html document. + * + * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.* + * + * @example + * This example shows how to apply the `ngCsp` directive to the `html` tag. + ```html + <!doctype html> + <html ng-app ng-csp> + ... + ... + </html> + ``` + * @example + // Note: the suffix `.csp` in the example name triggers + // csp mode in our http server! + <example name="example.csp" module="cspExample" ng-csp="true"> <file name="index.html"> - <script> - angular.module('urlExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.url = { - text: 'http://google.com' - }; - }]); - </script> - <form name="myForm" ng-controller="ExampleController"> - URL: <input type="url" name="input" ng-model="url.text" required> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.url"> - Not valid url!</span> - <tt>text = {{url.text}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/> - </form> + <div ng-controller="MainController as ctrl"> + <div> + <button ng-click="ctrl.inc()" id="inc">Increment</button> + <span id="counter"> + {{ctrl.counter}} + </span> + </div> + + <div> + <button ng-click="ctrl.evil()" id="evil">Evil</button> + <span id="evilError"> + {{ctrl.evilError}} + </span> + </div> + </div> + </file> + <file name="script.js"> + angular.module('cspExample', []) + .controller('MainController', function() { + this.counter = 0; + this.inc = function() { + this.counter++; + }; + this.evil = function() { + // jshint evil:true + try { + eval('1+2'); + } catch (e) { + this.evilError = e.message; + } + }; + }); </file> <file name="protractor.js" type="protractor"> - var text = element(by.binding('url.text')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('url.text')); + var util, webdriver; - it('should initialize to model', function() { - expect(text.getText()).toContain('http://google.com'); - expect(valid.getText()).toContain('true'); - }); + var incBtn = element(by.id('inc')); + var counter = element(by.id('counter')); + var evilBtn = element(by.id('evil')); + var evilError = element(by.id('evilError')); - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); + function getAndClearSevereErrors() { + return browser.manage().logs().get('browser').then(function(browserLog) { + return browserLog.filter(function(logEntry) { + return logEntry.level.value > webdriver.logging.Level.WARNING.value; + }); + }); + } - expect(text.getText()).toEqual('text ='); - expect(valid.getText()).toContain('false'); - }); + function clearErrors() { + getAndClearSevereErrors(); + } - it('should be invalid if not url', function() { - input.clear(); - input.sendKeys('box'); + function expectNoErrors() { + getAndClearSevereErrors().then(function(filteredLog) { + expect(filteredLog.length).toEqual(0); + if (filteredLog.length) { + console.log('browser console errors: ' + util.inspect(filteredLog)); + } + }); + } - expect(valid.getText()).toContain('false'); - }); - </file> - </example> - */ - 'url': urlInputType, + function expectError(regex) { + getAndClearSevereErrors().then(function(filteredLog) { + var found = false; + filteredLog.forEach(function(log) { + if (log.message.match(regex)) { + found = true; + } + }); + if (!found) { + throw new Error('expected an error that matches ' + regex); + } + }); + } + beforeEach(function() { + util = require('util'); + webdriver = require('protractor/node_modules/selenium-webdriver'); + }); - /** - * @ngdoc input - * @name input[email] - * - * @description - * Text input with email validation. Sets the `email` validation error key if not a valid email - * address. - * - * <div class="alert alert-warning"> - * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex - * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can - * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide}) - * </div> - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match - * a RegExp found by evaluating the Angular expression given in the attribute value. - * If the expression evaluates to a RegExp object then this is used directly. - * If the expression is a string then it will be converted to a RegExp after wrapping it in `^` and `$` - * characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="email-input-directive" module="emailExample"> - <file name="index.html"> - <script> - angular.module('emailExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.email = { - text: 'me@example.com' - }; - }]); - </script> - <form name="myForm" ng-controller="ExampleController"> - Email: <input type="email" name="input" ng-model="email.text" required> - <span class="error" ng-show="myForm.input.$error.required"> - Required!</span> - <span class="error" ng-show="myForm.input.$error.email"> - Not valid email!</span> - <tt>text = {{email.text}}</tt><br/> - <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/> - <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - var text = element(by.binding('email.text')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('email.text')); + // For now, we only test on Chrome, + // as Safari does not load the page with Protractor's injected scripts, + // and Firefox webdriver always disables content security policy (#6358) + if (browser.params.browser !== 'chrome') { + return; + } - it('should initialize to model', function() { - expect(text.getText()).toContain('me@example.com'); - expect(valid.getText()).toContain('true'); + it('should not report errors when the page is loaded', function() { + // clear errors so we are not dependent on previous tests + clearErrors(); + // Need to reload the page as the page is already loaded when + // we come here + browser.driver.getCurrentUrl().then(function(url) { + browser.get(url); + }); + expectNoErrors(); }); - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); - expect(text.getText()).toEqual('text ='); - expect(valid.getText()).toContain('false'); + it('should evaluate expressions', function() { + expect(counter.getText()).toEqual('0'); + incBtn.click(); + expect(counter.getText()).toEqual('1'); + expectNoErrors(); }); - it('should be invalid if not email', function() { - input.clear(); - input.sendKeys('xxx'); - - expect(valid.getText()).toContain('false'); + it('should throw and report an error when using "eval"', function() { + evilBtn.click(); + expect(evilError.getText()).toMatch(/Content Security Policy/); + expectError(/Content Security Policy/); }); </file> </example> - */ - 'email': emailInputType, - + */ - /** - * @ngdoc input - * @name input[radio] - * - * @description - * HTML radio button. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string} value The value to which the expression should be set when selected. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * @param {string} ngValue Angular expression which sets the value to which the expression should - * be set when selected. - * - * @example - <example name="radio-input-directive" module="radioExample"> - <file name="index.html"> - <script> - angular.module('radioExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.color = { - name: 'blue' - }; - $scope.specialValue = { - "id": "12345", - "value": "green" - }; - }]); - </script> - <form name="myForm" ng-controller="ExampleController"> - <input type="radio" ng-model="color.name" value="red"> Red <br/> - <input type="radio" ng-model="color.name" ng-value="specialValue"> Green <br/> - <input type="radio" ng-model="color.name" value="blue"> Blue <br/> - <tt>color = {{color.name | json}}</tt><br/> - </form> - Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. - </file> - <file name="protractor.js" type="protractor"> - it('should change state', function() { - var color = element(by.binding('color.name')); +// ngCsp is not implemented as a proper directive any more, because we need it be processed while we +// bootstrap the system (before $parse is instantiated), for this reason we just have +// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc - expect(color.getText()).toContain('blue'); +/** + * @ngdoc directive + * @name ngClick + * + * @description + * The ngClick directive allows you to specify custom behavior when + * an element is clicked. + * + * @element ANY + * @priority 0 + * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon + * click. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <button ng-click="count = count + 1" ng-init="count=0"> + Increment + </button> + <span> + count: {{count}} + </span> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-click', function() { + expect(element(by.binding('count')).getText()).toMatch('0'); + element(by.css('button')).click(); + expect(element(by.binding('count')).getText()).toMatch('1'); + }); + </file> + </example> + */ +/* + * A collection of directives that allows creation of custom event handlers that are defined as + * angular expressions and are compiled and executed within the current scope. + */ +var ngEventDirectives = {}; - element.all(by.model('color.name')).get(0).click(); +// For events that might fire synchronously during DOM manipulation +// we need to execute their event handlers asynchronously using $evalAsync, +// so that they are not executed in an inconsistent state. +var forceAsyncEvents = { + 'blur': true, + 'focus': true +}; +forEach( + 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '), + function(eventName) { + var directiveName = directiveNormalize('ng-' + eventName); + ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) { + return { + restrict: 'A', + compile: function($element, attr) { + // We expose the powerful $event object on the scope that provides access to the Window, + // etc. that isn't protected by the fast paths in $parse. We explicitly request better + // checks at the cost of speed since event handler expressions are not executed as + // frequently as regular change detection. + var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true); + return function ngEventHandler(scope, element) { + element.on(eventName, function(event) { + var callback = function() { + fn(scope, {$event:event}); + }; + if (forceAsyncEvents[eventName] && $rootScope.$$phase) { + scope.$evalAsync(callback); + } else { + scope.$apply(callback); + } + }); + }; + } + }; + }]; + } +); - expect(color.getText()).toContain('red'); - }); - </file> - </example> - */ - 'radio': radioInputType, +/** + * @ngdoc directive + * @name ngDblclick + * + * @description + * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event. + * + * @element ANY + * @priority 0 + * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon + * a dblclick. (The Event object is available as `$event`) + * + * @example + <example> + <file name="index.html"> + <button ng-dblclick="count = count + 1" ng-init="count=0"> + Increment (on double click) + </button> + count: {{count}} + </file> + </example> + */ - /** - * @ngdoc input - * @name input[checkbox] - * - * @description - * HTML checkbox. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {expression=} ngTrueValue The value to which the expression should be set when selected. - * @param {expression=} ngFalseValue The value to which the expression should be set when not selected. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - <example name="checkbox-input-directive" module="checkboxExample"> - <file name="index.html"> - <script> - angular.module('checkboxExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.checkboxModel = { - value1 : true, - value2 : 'YES' - }; - }]); - </script> - <form name="myForm" ng-controller="ExampleController"> - Value1: <input type="checkbox" ng-model="checkboxModel.value1"> <br/> - Value2: <input type="checkbox" ng-model="checkboxModel.value2" - ng-true-value="'YES'" ng-false-value="'NO'"> <br/> - <tt>value1 = {{checkboxModel.value1}}</tt><br/> - <tt>value2 = {{checkboxModel.value2}}</tt><br/> - </form> - </file> - <file name="protractor.js" type="protractor"> - it('should change state', function() { - var value1 = element(by.binding('checkboxModel.value1')); - var value2 = element(by.binding('checkboxModel.value2')); +/** + * @ngdoc directive + * @name ngMousedown + * + * @description + * The ngMousedown directive allows you to specify custom behavior on mousedown event. + * + * @element ANY + * @priority 0 + * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon + * mousedown. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <button ng-mousedown="count = count + 1" ng-init="count=0"> + Increment (on mouse down) + </button> + count: {{count}} + </file> + </example> + */ - expect(value1.getText()).toContain('true'); - expect(value2.getText()).toContain('YES'); - element(by.model('checkboxModel.value1')).click(); - element(by.model('checkboxModel.value2')).click(); +/** + * @ngdoc directive + * @name ngMouseup + * + * @description + * Specify custom behavior on mouseup event. + * + * @element ANY + * @priority 0 + * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon + * mouseup. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <button ng-mouseup="count = count + 1" ng-init="count=0"> + Increment (on mouse up) + </button> + count: {{count}} + </file> + </example> + */ - expect(value1.getText()).toContain('false'); - expect(value2.getText()).toContain('NO'); - }); - </file> - </example> - */ - 'checkbox': checkboxInputType, +/** + * @ngdoc directive + * @name ngMouseover + * + * @description + * Specify custom behavior on mouseover event. + * + * @element ANY + * @priority 0 + * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon + * mouseover. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <button ng-mouseover="count = count + 1" ng-init="count=0"> + Increment (when mouse is over) + </button> + count: {{count}} + </file> + </example> + */ - 'hidden': noop, - 'button': noop, - 'submit': noop, - 'reset': noop, - 'file': noop -}; -function stringBasedInputType(ctrl) { - ctrl.$formatters.push(function(value) { - return ctrl.$isEmpty(value) ? value : value.toString(); - }); -} +/** + * @ngdoc directive + * @name ngMouseenter + * + * @description + * Specify custom behavior on mouseenter event. + * + * @element ANY + * @priority 0 + * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon + * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <button ng-mouseenter="count = count + 1" ng-init="count=0"> + Increment (when mouse enters) + </button> + count: {{count}} + </file> + </example> + */ -function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); -} -function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { - var type = lowercase(element[0].type); +/** + * @ngdoc directive + * @name ngMouseleave + * + * @description + * Specify custom behavior on mouseleave event. + * + * @element ANY + * @priority 0 + * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon + * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <button ng-mouseleave="count = count + 1" ng-init="count=0"> + Increment (when mouse leaves) + </button> + count: {{count}} + </file> + </example> + */ - // In composition mode, users are still inputing intermediate text buffer, - // hold the listener until composition is done. - // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent - if (!$sniffer.android) { - var composing = false; - element.on('compositionstart', function(data) { - composing = true; - }); +/** + * @ngdoc directive + * @name ngMousemove + * + * @description + * Specify custom behavior on mousemove event. + * + * @element ANY + * @priority 0 + * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon + * mousemove. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <button ng-mousemove="count = count + 1" ng-init="count=0"> + Increment (when mouse moves) + </button> + count: {{count}} + </file> + </example> + */ - element.on('compositionend', function() { - composing = false; - listener(); - }); - } - var listener = function(ev) { - if (timeout) { - $browser.defer.cancel(timeout); - timeout = null; - } - if (composing) return; - var value = element.val(), - event = ev && ev.type; +/** + * @ngdoc directive + * @name ngKeydown + * + * @description + * Specify custom behavior on keydown event. + * + * @element ANY + * @priority 0 + * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon + * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) + * + * @example + <example> + <file name="index.html"> + <input ng-keydown="count = count + 1" ng-init="count=0"> + key down count: {{count}} + </file> + </example> + */ - // By default we will trim the value - // If the attribute ng-trim exists we will avoid trimming - // If input type is 'password', the value is never trimmed - if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) { - value = trim(value); - } - // If a control is suffering from bad input (due to native validators), browsers discard its - // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the - // control's value is the same empty value twice in a row. - if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) { - ctrl.$setViewValue(value, event); - } - }; +/** + * @ngdoc directive + * @name ngKeyup + * + * @description + * Specify custom behavior on keyup event. + * + * @element ANY + * @priority 0 + * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon + * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) + * + * @example + <example> + <file name="index.html"> + <p>Typing in the input box below updates the key count</p> + <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}} - // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the - // input event on backspace, delete or cut - if ($sniffer.hasEvent('input')) { - element.on('input', listener); - } else { - var timeout; + <p>Typing in the input box below updates the keycode</p> + <input ng-keyup="event=$event"> + <p>event keyCode: {{ event.keyCode }}</p> + <p>event altKey: {{ event.altKey }}</p> + </file> + </example> + */ - var deferListener = function(ev, input, origValue) { - if (!timeout) { - timeout = $browser.defer(function() { - timeout = null; - if (!input || input.value !== origValue) { - listener(ev); - } - }); - } - }; - element.on('keydown', function(event) { - var key = event.keyCode; +/** + * @ngdoc directive + * @name ngKeypress + * + * @description + * Specify custom behavior on keypress event. + * + * @element ANY + * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon + * keypress. ({@link guide/expression#-event- Event object is available as `$event`} + * and can be interrogated for keyCode, altKey, etc.) + * + * @example + <example> + <file name="index.html"> + <input ng-keypress="count = count + 1" ng-init="count=0"> + key press count: {{count}} + </file> + </example> + */ - // ignore - // command modifiers arrows - if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; - deferListener(event, this, this.value); - }); +/** + * @ngdoc directive + * @name ngSubmit + * + * @description + * Enables binding angular expressions to onsubmit events. + * + * Additionally it prevents the default action (which for form means sending the request to the + * server and reloading the current page), but only if the form does not contain `action`, + * `data-action`, or `x-action` attributes. + * + * <div class="alert alert-warning"> + * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and + * `ngSubmit` handlers together. See the + * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation} + * for a detailed discussion of when `ngSubmit` may be triggered. + * </div> + * + * @element form + * @priority 0 + * @param {expression} ngSubmit {@link guide/expression Expression} to eval. + * ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example module="submitExample"> + <file name="index.html"> + <script> + angular.module('submitExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.list = []; + $scope.text = 'hello'; + $scope.submit = function() { + if ($scope.text) { + $scope.list.push(this.text); + $scope.text = ''; + } + }; + }]); + </script> + <form ng-submit="submit()" ng-controller="ExampleController"> + Enter text and hit enter: + <input type="text" ng-model="text" name="text" /> + <input type="submit" id="submit" value="Submit" /> + <pre>list={{list}}</pre> + </form> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-submit', function() { + expect(element(by.binding('list')).getText()).toBe('list=[]'); + element(by.css('#submit')).click(); + expect(element(by.binding('list')).getText()).toContain('hello'); + expect(element(by.model('text')).getAttribute('value')).toBe(''); + }); + it('should ignore empty strings', function() { + expect(element(by.binding('list')).getText()).toBe('list=[]'); + element(by.css('#submit')).click(); + element(by.css('#submit')).click(); + expect(element(by.binding('list')).getText()).toContain('hello'); + }); + </file> + </example> + */ - // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it - if ($sniffer.hasEvent('paste')) { - element.on('paste cut', deferListener); - } - } +/** + * @ngdoc directive + * @name ngFocus + * + * @description + * Specify custom behavior on focus event. + * + * Note: As the `focus` event is executed synchronously when calling `input.focus()` + * AngularJS executes the expression using `scope.$evalAsync` if the event is fired + * during an `$apply` to ensure a consistent state. + * + * @element window, input, select, textarea, a + * @priority 0 + * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon + * focus. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ - // if user paste into input using mouse on older browser - // or form autocomplete on newer browser, we need "change" event to catch it - element.on('change', listener); +/** + * @ngdoc directive + * @name ngBlur + * + * @description + * Specify custom behavior on blur event. + * + * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when + * an element has lost focus. + * + * Note: As the `blur` event is executed synchronously also during DOM manipulations + * (e.g. removing a focussed input), + * AngularJS executes the expression using `scope.$evalAsync` if the event is fired + * during an `$apply` to ensure a consistent state. + * + * @element window, input, select, textarea, a + * @priority 0 + * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon + * blur. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + * See {@link ng.directive:ngClick ngClick} + */ - ctrl.$render = function() { - element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); - }; -} +/** + * @ngdoc directive + * @name ngCopy + * + * @description + * Specify custom behavior on copy event. + * + * @element window, input, select, textarea, a + * @priority 0 + * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon + * copy. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value"> + copied: {{copied}} + </file> + </example> + */ -function weekParser(isoWeek, existingDate) { - if (isDate(isoWeek)) { - return isoWeek; - } +/** + * @ngdoc directive + * @name ngCut + * + * @description + * Specify custom behavior on cut event. + * + * @element window, input, select, textarea, a + * @priority 0 + * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon + * cut. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value"> + cut: {{cut}} + </file> + </example> + */ - if (isString(isoWeek)) { - WEEK_REGEXP.lastIndex = 0; - var parts = WEEK_REGEXP.exec(isoWeek); - if (parts) { - var year = +parts[1], - week = +parts[2], - hours = 0, - minutes = 0, - seconds = 0, - milliseconds = 0, - firstThurs = getFirstThursdayOfYear(year), - addDays = (week - 1) * 7; +/** + * @ngdoc directive + * @name ngPaste + * + * @description + * Specify custom behavior on paste event. + * + * @element window, input, select, textarea, a + * @priority 0 + * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon + * paste. ({@link guide/expression#-event- Event object is available as `$event`}) + * + * @example + <example> + <file name="index.html"> + <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'> + pasted: {{paste}} + </file> + </example> + */ - if (existingDate) { - hours = existingDate.getHours(); - minutes = existingDate.getMinutes(); - seconds = existingDate.getSeconds(); - milliseconds = existingDate.getMilliseconds(); +/** + * @ngdoc directive + * @name ngIf + * @restrict A + * @multiElement + * + * @description + * The `ngIf` directive removes or recreates a portion of the DOM tree based on an + * {expression}. If the expression assigned to `ngIf` evaluates to a false + * value then the element is removed from the DOM, otherwise a clone of the + * element is reinserted into the DOM. + * + * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the + * element in the DOM rather than changing its visibility via the `display` css property. A common + * case when this difference is significant is when using css selectors that rely on an element's + * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes. + * + * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope + * is created when the element is restored. The scope created within `ngIf` inherits from + * its parent scope using + * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance). + * An important implication of this is if `ngModel` is used within `ngIf` to bind to + * a javascript primitive defined in the parent scope. In this case any modifications made to the + * variable within the child scope will override (hide) the value in the parent scope. + * + * Also, `ngIf` recreates elements using their compiled state. An example of this behavior + * is if an element's class attribute is directly modified after it's compiled, using something like + * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element + * the added class will be lost because the original compiled state is used to regenerate the element. + * + * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter` + * and `leave` effects. + * + * @animations + * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container + * leave - happens just before the `ngIf` contents are removed from the DOM + * + * @element ANY + * @scope + * @priority 600 + * @param {expression} ngIf If the {@link guide/expression expression} is falsy then + * the element is removed from the DOM tree. If it is truthy a copy of the compiled + * element is added to the DOM tree. + * + * @example + <example module="ngAnimate" deps="angular-animate.js" animations="true"> + <file name="index.html"> + <label>Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /></label><br/> + Show when checked: + <span ng-if="checked" class="animate-if"> + This is removed when the checkbox is unchecked. + </span> + </file> + <file name="animations.css"> + .animate-if { + background:white; + border:1px solid black; + padding:10px; } - return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); - } - } - - return NaN; -} - -function createDateParser(regexp, mapping) { - return function(iso, date) { - var parts, map; - - if (isDate(iso)) { - return iso; - } - - if (isString(iso)) { - // When a date is JSON'ified to wraps itself inside of an extra - // set of double quotes. This makes the date parsing code unable - // to match the date string and parse it as a date. - if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') { - iso = iso.substring(1, iso.length - 1); + .animate-if.ng-enter, .animate-if.ng-leave { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; } - if (ISO_DATE_REGEXP.test(iso)) { - return new Date(iso); + + .animate-if.ng-enter, + .animate-if.ng-leave.ng-leave-active { + opacity:0; } - regexp.lastIndex = 0; - parts = regexp.exec(iso); - if (parts) { - parts.shift(); - if (date) { - map = { - yyyy: date.getFullYear(), - MM: date.getMonth() + 1, - dd: date.getDate(), - HH: date.getHours(), - mm: date.getMinutes(), - ss: date.getSeconds(), - sss: date.getMilliseconds() / 1000 - }; - } else { - map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }; - } + .animate-if.ng-leave, + .animate-if.ng-enter.ng-enter-active { + opacity:1; + } + </file> + </example> + */ +var ngIfDirective = ['$animate', function($animate) { + return { + multiElement: true, + transclude: 'element', + priority: 600, + terminal: true, + restrict: 'A', + $$tlb: true, + link: function($scope, $element, $attr, ctrl, $transclude) { + var block, childScope, previousElements; + $scope.$watch($attr.ngIf, function ngIfWatchAction(value) { - forEach(parts, function(part, index) { - if (index < mapping.length) { - map[mapping[index]] = +part; + if (value) { + if (!childScope) { + $transclude(function(clone, newScope) { + childScope = newScope; + clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' '); + // Note: We only need the first/last node of the cloned nodes. + // However, we need to keep the reference to the jqlite wrapper as it might be changed later + // by a directive with templateUrl when its template arrives. + block = { + clone: clone + }; + $animate.enter(clone, $element.parent(), $element); + }); + } + } else { + if (previousElements) { + previousElements.remove(); + previousElements = null; + } + if (childScope) { + childScope.$destroy(); + childScope = null; + } + if (block) { + previousElements = getBlockNodes(block.clone); + $animate.leave(previousElements).then(function() { + previousElements = null; + }); + block = null; + } } }); - return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0); - } } - - return NaN; }; -} - -function createDateInputType(type, regexp, parseDate, format) { - return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) { - badInputChecker(scope, element, attr, ctrl); - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - var timezone = ctrl && ctrl.$options && ctrl.$options.timezone; - var previousDate; +}]; - ctrl.$$parserName = type; - ctrl.$parsers.push(function(value) { - if (ctrl.$isEmpty(value)) return null; - if (regexp.test(value)) { - // Note: We cannot read ctrl.$modelValue, as there might be a different - // parser/formatter in the processing chain so that the model - // contains some different data format! - var parsedDate = parseDate(value, previousDate); - if (timezone === 'UTC') { - parsedDate.setMinutes(parsedDate.getMinutes() - parsedDate.getTimezoneOffset()); - } - return parsedDate; +/** + * @ngdoc directive + * @name ngInclude + * @restrict ECA + * + * @description + * Fetches, compiles and includes an external HTML fragment. + * + * By default, the template URL is restricted to the same domain and protocol as the + * application document. This is done by calling {@link $sce#getTrustedResourceUrl + * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols + * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or + * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link + * ng.$sce Strict Contextual Escaping}. + * + * In addition, the browser's + * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) + * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) + * policy may further restrict whether the template is successfully loaded. + * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://` + * access on some browsers. + * + * @animations + * enter - animation is used to bring new content into the browser. + * leave - animation is used to animate existing content away. + * + * The enter and leave animation occur concurrently. + * + * @scope + * @priority 400 + * + * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant, + * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`. + * @param {string=} onload Expression to evaluate when a new partial is loaded. + * + * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll + * $anchorScroll} to scroll the viewport after the content is loaded. + * + * - If the attribute is not set, disable scrolling. + * - If the attribute is set without value, enable scrolling. + * - Otherwise enable scrolling only if the expression evaluates to truthy value. + * + * @example + <example module="includeExample" deps="angular-animate.js" animations="true"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <select ng-model="template" ng-options="t.name for t in templates"> + <option value="">(blank)</option> + </select> + url of the template: <code>{{template.url}}</code> + <hr/> + <div class="slide-animate-container"> + <div class="slide-animate" ng-include="template.url"></div> + </div> + </div> + </file> + <file name="script.js"> + angular.module('includeExample', ['ngAnimate']) + .controller('ExampleController', ['$scope', function($scope) { + $scope.templates = + [ { name: 'template1.html', url: 'template1.html'}, + { name: 'template2.html', url: 'template2.html'} ]; + $scope.template = $scope.templates[0]; + }]); + </file> + <file name="template1.html"> + Content of template1.html + </file> + <file name="template2.html"> + Content of template2.html + </file> + <file name="animations.css"> + .slide-animate-container { + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; } - return undefined; - }); - ctrl.$formatters.push(function(value) { - if (value && !isDate(value)) { - throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value); - } - if (isValidDate(value)) { - previousDate = value; - if (previousDate && timezone === 'UTC') { - var timezoneOffset = 60000 * previousDate.getTimezoneOffset(); - previousDate = new Date(previousDate.getTime() + timezoneOffset); - } - return $filter('date')(value, format, timezone); - } else { - previousDate = null; - return ''; + .slide-animate { + padding:10px; } - }); - - if (isDefined(attr.min) || attr.ngMin) { - var minVal; - ctrl.$validators.min = function(value) { - return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal; - }; - attr.$observe('min', function(val) { - minVal = parseObservedDateValue(val); - ctrl.$validate(); - }); - } - - if (isDefined(attr.max) || attr.ngMax) { - var maxVal; - ctrl.$validators.max = function(value) { - return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal; - }; - attr.$observe('max', function(val) { - maxVal = parseObservedDateValue(val); - ctrl.$validate(); - }); - } - - function isValidDate(value) { - // Invalid Date: getTime() returns NaN - return value && !(value.getTime && value.getTime() !== value.getTime()); - } - - function parseObservedDateValue(val) { - return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined; - } - }; -} - -function badInputChecker(scope, element, attr, ctrl) { - var node = element[0]; - var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); - if (nativeValidation) { - ctrl.$parsers.push(function(value) { - var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; - // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430): - // - also sets validity.badInput (should only be validity.typeMismatch). - // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email) - // - can ignore this case as we can still read out the erroneous email... - return validity.badInput && !validity.typeMismatch ? undefined : value; - }); - } -} - -function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { - badInputChecker(scope, element, attr, ctrl); - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - ctrl.$$parserName = 'number'; - ctrl.$parsers.push(function(value) { - if (ctrl.$isEmpty(value)) return null; - if (NUMBER_REGEXP.test(value)) return parseFloat(value); - return undefined; - }); + .slide-animate.ng-enter, .slide-animate.ng-leave { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - ctrl.$formatters.push(function(value) { - if (!ctrl.$isEmpty(value)) { - if (!isNumber(value)) { - throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value); + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + display:block; + padding:10px; } - value = value.toString(); - } - return value; - }); - - if (attr.min || attr.ngMin) { - var minVal; - ctrl.$validators.min = function(value) { - return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal; - }; - attr.$observe('min', function(val) { - if (isDefined(val) && !isNumber(val)) { - val = parseFloat(val, 10); + .slide-animate.ng-enter { + top:-50px; } - minVal = isNumber(val) && !isNaN(val) ? val : undefined; - // TODO(matsko): implement validateLater to reduce number of validations - ctrl.$validate(); - }); - } - - if (attr.max || attr.ngMax) { - var maxVal; - ctrl.$validators.max = function(value) { - return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal; - }; - - attr.$observe('max', function(val) { - if (isDefined(val) && !isNumber(val)) { - val = parseFloat(val, 10); + .slide-animate.ng-enter.ng-enter-active { + top:0; } - maxVal = isNumber(val) && !isNaN(val) ? val : undefined; - // TODO(matsko): implement validateLater to reduce number of validations - ctrl.$validate(); - }); - } -} - -function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { - // Note: no badInputChecker here by purpose as `url` is only a validation - // in browsers, i.e. we can always read out input.value even if it is not valid! - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); - ctrl.$$parserName = 'url'; - ctrl.$validators.url = function(modelValue, viewValue) { - var value = modelValue || viewValue; - return ctrl.$isEmpty(value) || URL_REGEXP.test(value); - }; -} + .slide-animate.ng-leave { + top:0; + } + .slide-animate.ng-leave.ng-leave-active { + top:50px; + } + </file> + <file name="protractor.js" type="protractor"> + var templateSelect = element(by.model('template')); + var includeElem = element(by.css('[ng-include]')); -function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { - // Note: no badInputChecker here by purpose as `url` is only a validation - // in browsers, i.e. we can always read out input.value even if it is not valid! - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); + it('should load template1.html', function() { + expect(includeElem.getText()).toMatch(/Content of template1.html/); + }); - ctrl.$$parserName = 'email'; - ctrl.$validators.email = function(modelValue, viewValue) { - var value = modelValue || viewValue; - return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); - }; -} + it('should load template2.html', function() { + if (browser.params.browser == 'firefox') { + // Firefox can't handle using selects + // See https://github.com/angular/protractor/issues/480 + return; + } + templateSelect.click(); + templateSelect.all(by.css('option')).get(2).click(); + expect(includeElem.getText()).toMatch(/Content of template2.html/); + }); -function radioInputType(scope, element, attr, ctrl) { - // make the name unique, if not defined - if (isUndefined(attr.name)) { - element.attr('name', nextUid()); - } + it('should change to blank', function() { + if (browser.params.browser == 'firefox') { + // Firefox can't handle using selects + return; + } + templateSelect.click(); + templateSelect.all(by.css('option')).get(0).click(); + expect(includeElem.isPresent()).toBe(false); + }); + </file> + </example> + */ - var listener = function(ev) { - if (element[0].checked) { - ctrl.$setViewValue(attr.value, ev && ev.type); - } - }; - element.on('click', listener); +/** + * @ngdoc event + * @name ngInclude#$includeContentRequested + * @eventType emit on the scope ngInclude was declared in + * @description + * Emitted every time the ngInclude content is requested. + * + * @param {Object} angularEvent Synthetic event object. + * @param {String} src URL of content to load. + */ - ctrl.$render = function() { - var value = attr.value; - element[0].checked = (value == ctrl.$viewValue); - }; - attr.$observe('value', ctrl.$render); -} +/** + * @ngdoc event + * @name ngInclude#$includeContentLoaded + * @eventType emit on the current ngInclude scope + * @description + * Emitted every time the ngInclude content is reloaded. + * + * @param {Object} angularEvent Synthetic event object. + * @param {String} src URL of content to load. + */ -function parseConstantExpr($parse, context, name, expression, fallback) { - var parseFn; - if (isDefined(expression)) { - parseFn = $parse(expression); - if (!parseFn.constant) { - throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' + - '`{1}`.', name, expression); - } - return parseFn(context); - } - return fallback; -} -function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { - var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true); - var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false); +/** + * @ngdoc event + * @name ngInclude#$includeContentError + * @eventType emit on the scope ngInclude was declared in + * @description + * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299) + * + * @param {Object} angularEvent Synthetic event object. + * @param {String} src URL of content to load. + */ +var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', + function($templateRequest, $anchorScroll, $animate) { + return { + restrict: 'ECA', + priority: 400, + terminal: true, + transclude: 'element', + controller: angular.noop, + compile: function(element, attr) { + var srcExp = attr.ngInclude || attr.src, + onloadExp = attr.onload || '', + autoScrollExp = attr.autoscroll; - var listener = function(ev) { - ctrl.$setViewValue(element[0].checked, ev && ev.type); - }; + return function(scope, $element, $attr, ctrl, $transclude) { + var changeCounter = 0, + currentScope, + previousElement, + currentElement; - element.on('click', listener); + var cleanupLastIncludeContent = function() { + if (previousElement) { + previousElement.remove(); + previousElement = null; + } + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + $animate.leave(currentElement).then(function() { + previousElement = null; + }); + previousElement = currentElement; + currentElement = null; + } + }; - ctrl.$render = function() { - element[0].checked = ctrl.$viewValue; - }; + scope.$watch(srcExp, function ngIncludeWatchAction(src) { + var afterAnimation = function() { + if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }; + var thisChangeId = ++changeCounter; - // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false` - // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert - // it to a boolean. - ctrl.$isEmpty = function(value) { - return value === false; - }; + if (src) { + //set the 2nd param to true to ignore the template request error so that the inner + //contents and scope can be cleaned up. + $templateRequest(src, true).then(function(response) { + if (thisChangeId !== changeCounter) return; + var newScope = scope.$new(); + ctrl.template = response; - ctrl.$formatters.push(function(value) { - return equals(value, trueValue); - }); + // Note: This will also link all children of ng-include that were contained in the original + // html. If that content contains controllers, ... they could pollute/change the scope. + // However, using ng-include on an element with additional content does not make sense... + // Note: We can't remove them in the cloneAttchFn of $transclude as that + // function is called before linking the content, which would apply child + // directives to non existing elements. + var clone = $transclude(newScope, function(clone) { + cleanupLastIncludeContent(); + $animate.enter(clone, null, $element).then(afterAnimation); + }); - ctrl.$parsers.push(function(value) { - return value ? trueValue : falseValue; - }); -} + currentScope = newScope; + currentElement = clone; + currentScope.$emit('$includeContentLoaded', src); + scope.$eval(onloadExp); + }, function() { + if (thisChangeId === changeCounter) { + cleanupLastIncludeContent(); + scope.$emit('$includeContentError', src); + } + }); + scope.$emit('$includeContentRequested', src); + } else { + cleanupLastIncludeContent(); + ctrl.template = null; + } + }); + }; + } + }; +}]; -/** - * @ngdoc directive - * @name textarea - * @restrict E - * - * @description - * HTML textarea element control with angular data-binding. The data-binding and validation - * properties of this element are exactly the same as those of the - * {@link ng.directive:input input element}. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any - * length. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. - */ +// This directive is called during the $transclude call of the first `ngInclude` directive. +// It will replace and compile the content of the element with the loaded template. +// We need this directive so that the element content is already filled when +// the link function of another directive on the same element as ngInclude +// is called. +var ngIncludeFillContentDirective = ['$compile', + function($compile) { + return { + restrict: 'ECA', + priority: -400, + require: 'ngInclude', + link: function(scope, $element, $attr, ctrl) { + if (/SVG/.test($element[0].toString())) { + // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not + // support innerHTML, so detect this here and try to generate the contents + // specially. + $element.empty(); + $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope, + function namespaceAdaptedClone(clone) { + $element.append(clone); + }, {futureParentElement: $element}); + return; + } + $element.html(ctrl.template); + $compile($element.contents())(scope); + } + }; + }]; /** * @ngdoc directive - * @name input - * @restrict E + * @name ngInit + * @restrict AC * * @description - * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding, - * input state control, and validation. - * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers. + * The `ngInit` directive allows you to evaluate an expression in the + * current scope. * + * <div class="alert alert-danger"> + * The only appropriate use of `ngInit` is for aliasing special properties of + * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you + * should use {@link guide/controller controllers} rather than `ngInit` + * to initialize values on a scope. + * </div> * <div class="alert alert-warning"> - * **Note:** Not every feature offered is available for all input types. - * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`. + * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make + * sure you have parenthesis for correct precedence: + * <pre class="prettyprint"> + * `<div ng-init="test1 = (data | orderBy:'name')"></div>` + * </pre> * </div> * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {boolean=} ngRequired Sets `required` attribute if set to true - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any - * length. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input. - * This parameter is ignored for input[type=password] controls, which will never trim the - * input. + * @priority 450 + * + * @element ANY + * @param {expression} ngInit {@link guide/expression Expression} to eval. * * @example - <example name="input-directive" module="inputExample"> - <file name="index.html"> - <script> - angular.module('inputExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.user = {name: 'guest', last: 'visitor'}; - }]); - </script> - <div ng-controller="ExampleController"> - <form name="myForm"> - User name: <input type="text" name="userName" ng-model="user.name" required> - <span class="error" ng-show="myForm.userName.$error.required"> - Required!</span><br> - Last name: <input type="text" name="lastName" ng-model="user.last" - ng-minlength="3" ng-maxlength="10"> - <span class="error" ng-show="myForm.lastName.$error.minlength"> - Too short!</span> - <span class="error" ng-show="myForm.lastName.$error.maxlength"> - Too long!</span><br> - </form> - <hr> - <tt>user = {{user}}</tt><br/> - <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br> - <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br> - <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br> - <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br> - <tt>myForm.$valid = {{myForm.$valid}}</tt><br> - <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br> - <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br> - <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br> + <example module="initExample"> + <file name="index.html"> + <script> + angular.module('initExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.list = [['a', 'b'], ['c', 'd']]; + }]); + </script> + <div ng-controller="ExampleController"> + <div ng-repeat="innerList in list" ng-init="outerIndex = $index"> + <div ng-repeat="value in innerList" ng-init="innerIndex = $index"> + <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span> </div> - </file> - <file name="protractor.js" type="protractor"> - var user = element(by.exactBinding('user')); - var userNameValid = element(by.binding('myForm.userName.$valid')); - var lastNameValid = element(by.binding('myForm.lastName.$valid')); - var lastNameError = element(by.binding('myForm.lastName.$error')); - var formValid = element(by.binding('myForm.$valid')); - var userNameInput = element(by.model('user.name')); - var userLastInput = element(by.model('user.last')); - - it('should initialize to model', function() { - expect(user.getText()).toContain('{"name":"guest","last":"visitor"}'); - expect(userNameValid.getText()).toContain('true'); - expect(formValid.getText()).toContain('true'); - }); - - it('should be invalid if empty when required', function() { - userNameInput.clear(); - userNameInput.sendKeys(''); - - expect(user.getText()).toContain('{"last":"visitor"}'); - expect(userNameValid.getText()).toContain('false'); - expect(formValid.getText()).toContain('false'); - }); - - it('should be valid if empty when min length is set', function() { - userLastInput.clear(); - userLastInput.sendKeys(''); - - expect(user.getText()).toContain('{"name":"guest","last":""}'); - expect(lastNameValid.getText()).toContain('true'); - expect(formValid.getText()).toContain('true'); - }); - - it('should be invalid if less than required min length', function() { - userLastInput.clear(); - userLastInput.sendKeys('xx'); - - expect(user.getText()).toContain('{"name":"guest"}'); - expect(lastNameValid.getText()).toContain('false'); - expect(lastNameError.getText()).toContain('minlength'); - expect(formValid.getText()).toContain('false'); - }); - - it('should be invalid if longer than max length', function() { - userLastInput.clear(); - userLastInput.sendKeys('some ridiculously long name'); - - expect(user.getText()).toContain('{"name":"guest"}'); - expect(lastNameValid.getText()).toContain('false'); - expect(lastNameError.getText()).toContain('maxlength'); - expect(formValid.getText()).toContain('false'); - }); - </file> - </example> + </div> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should alias index positions', function() { + var elements = element.all(by.css('.example-init')); + expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;'); + expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;'); + expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;'); + expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;'); + }); + </file> + </example> */ -var inputDirective = ['$browser', '$sniffer', '$filter', '$parse', - function($browser, $sniffer, $filter, $parse) { - return { - restrict: 'E', - require: ['?ngModel'], - link: { - pre: function(scope, element, attr, ctrls) { - if (ctrls[0]) { - (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer, - $browser, $filter, $parse); - } +var ngInitDirective = ngDirective({ + priority: 450, + compile: function() { + return { + pre: function(scope, element, attrs) { + scope.$eval(attrs.ngInit); } - } - }; -}]; - - + }; + } +}); -var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; /** * @ngdoc directive - * @name ngValue + * @name ngList * * @description - * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`}, - * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to - * the bound value. + * Text input that converts between a delimited string and an array of strings. The default + * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom + * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`. * - * `ngValue` is useful when dynamically generating lists of radio buttons using - * {@link ngRepeat `ngRepeat`}, as shown below. + * The behaviour of the directive is affected by the use of the `ngTrim` attribute. + * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each + * list item is respected. This implies that the user of the directive is responsible for + * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a + * tab or newline character. + * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected + * when joining the list items back together) and whitespace around each list item is stripped + * before it is added to the model. * - * Likewise, `ngValue` can be used to generate `<option>` elements for - * the {@link select `select`} element. In that case however, only strings are supported - * for the `value `attribute, so the resulting `ngModel` will always be a string. - * Support for `select` models with non-string values is available via `ngOptions`. + * ### Example with Validation * - * @element input - * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute - * of the `input` element + * <example name="ngList-directive" module="listExample"> + * <file name="app.js"> + * angular.module('listExample', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.names = ['morpheus', 'neo', 'trinity']; + * }]); + * </file> + * <file name="index.html"> + * <form name="myForm" ng-controller="ExampleController"> + * <label>List: <input name="namesInput" ng-model="names" ng-list required></label> + * <span role="alert"> + * <span class="error" ng-show="myForm.namesInput.$error.required"> + * Required!</span> + * </span> + * <br> + * <tt>names = {{names}}</tt><br/> + * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/> + * <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/> + * <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> + * <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> + * </form> + * </file> + * <file name="protractor.js" type="protractor"> + * var listInput = element(by.model('names')); + * var names = element(by.exactBinding('names')); + * var valid = element(by.binding('myForm.namesInput.$valid')); + * var error = element(by.css('span.error')); * - * @example - <example name="ngValue-directive" module="valueExample"> - <file name="index.html"> - <script> - angular.module('valueExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.names = ['pizza', 'unicorns', 'robots']; - $scope.my = { favorite: 'unicorns' }; - }]); - </script> - <form ng-controller="ExampleController"> - <h2>Which is your favorite?</h2> - <label ng-repeat="name in names" for="{{name}}"> - {{name}} - <input type="radio" - ng-model="my.favorite" - ng-value="name" - id="{{name}}" - name="favorite"> - </label> - <div>You chose {{my.favorite}}</div> - </form> - </file> - <file name="protractor.js" type="protractor"> - var favorite = element(by.binding('my.favorite')); - - it('should initialize to model', function() { - expect(favorite.getText()).toContain('unicorns'); - }); - it('should bind the values to the inputs', function() { - element.all(by.model('my.favorite')).get(0).click(); - expect(favorite.getText()).toContain('pizza'); - }); - </file> - </example> + * it('should initialize to model', function() { + * expect(names.getText()).toContain('["morpheus","neo","trinity"]'); + * expect(valid.getText()).toContain('true'); + * expect(error.getCssValue('display')).toBe('none'); + * }); + * + * it('should be invalid if empty', function() { + * listInput.clear(); + * listInput.sendKeys(''); + * + * expect(names.getText()).toContain(''); + * expect(valid.getText()).toContain('false'); + * expect(error.getCssValue('display')).not.toBe('none'); + * }); + * </file> + * </example> + * + * ### Example - splitting on whitespace + * <example name="ngList-directive-newlines"> + * <file name="index.html"> + * <textarea ng-model="list" ng-list=" " ng-trim="false"></textarea> + * <pre>{{ list | json }}</pre> + * </file> + * <file name="protractor.js" type="protractor"> + * it("should split the text by newlines", function() { + * var listInput = element(by.model('list')); + * var output = element(by.binding('list | json')); + * listInput.sendKeys('abc\ndef\nghi'); + * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]'); + * }); + * </file> + * </example> + * + * @element input + * @param {string=} ngList optional delimiter that should be used to split the value. */ -var ngValueDirective = function() { +var ngListDirective = function() { return { restrict: 'A', priority: 100, - compile: function(tpl, tplAttr) { - if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { - return function ngValueConstantLink(scope, elm, attr) { - attr.$set('value', scope.$eval(attr.ngValue)); - }; - } else { - return function ngValueLink(scope, elm, attr) { - scope.$watch(attr.ngValue, function valueWatchAction(value) { - attr.$set('value', value); + require: 'ngModel', + link: function(scope, element, attr, ctrl) { + // We want to control whitespace trimming so we use this convoluted approach + // to access the ngList attribute, which doesn't pre-trim the attribute + var ngList = element.attr(attr.$attr.ngList) || ', '; + var trimValues = attr.ngTrim !== 'false'; + var separator = trimValues ? trim(ngList) : ngList; + + var parse = function(viewValue) { + // If the viewValue is invalid (say required but empty) it will be `undefined` + if (isUndefined(viewValue)) return; + + var list = []; + + if (viewValue) { + forEach(viewValue.split(separator), function(value) { + if (value) list.push(trimValues ? trim(value) : value); }); - }; - } + } + + return list; + }; + + ctrl.$parsers.push(parse); + ctrl.$formatters.push(function(value) { + if (isArray(value)) { + return value.join(ngList); + } + + return undefined; + }); + + // Override the standard $isEmpty because an empty array means the input is empty. + ctrl.$isEmpty = function(value) { + return !value || !value.length; + }; } }; }; +/* global VALID_CLASS: true, + INVALID_CLASS: true, + PRISTINE_CLASS: true, + DIRTY_CLASS: true, + UNTOUCHED_CLASS: true, + TOUCHED_CLASS: true, +*/ + +var VALID_CLASS = 'ng-valid', + INVALID_CLASS = 'ng-invalid', + PRISTINE_CLASS = 'ng-pristine', + DIRTY_CLASS = 'ng-dirty', + UNTOUCHED_CLASS = 'ng-untouched', + TOUCHED_CLASS = 'ng-touched', + PENDING_CLASS = 'ng-pending'; + + +var $ngModelMinErr = new minErr('ngModel'); + /** - * @ngdoc directive - * @name ngBind - * @restrict AC + * @ngdoc type + * @name ngModel.NgModelController + * + * @property {string} $viewValue Actual string value in the view. + * @property {*} $modelValue The value in the model that the control is bound to. + * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever + the control reads value from the DOM. The functions are called in array order, each passing + its return value through to the next. The last return value is forwarded to the + {@link ngModel.NgModelController#$validators `$validators`} collection. + +Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue +`$viewValue`}. + +Returning `undefined` from a parser means a parse error occurred. In that case, +no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel` +will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`} +is set to `true`. The parse error is stored in `ngModel.$error.parse`. + + * + * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever + the model value changes. The functions are called in reverse array order, each passing the value through to the + next. The last return value is used as the actual DOM value. + Used to format / convert values for display in the control. + * ```js + * function formatter(value) { + * if (value) { + * return value.toUpperCase(); + * } + * } + * ngModel.$formatters.push(formatter); + * ``` + * + * @property {Object.<string, function>} $validators A collection of validators that are applied + * whenever the model value changes. The key value within the object refers to the name of the + * validator while the function refers to the validation operation. The validation operation is + * provided with the model value as an argument and must return a true or false value depending + * on the response of that validation. + * + * ```js + * ngModel.$validators.validCharacters = function(modelValue, viewValue) { + * var value = modelValue || viewValue; + * return /[0-9]+/.test(value) && + * /[a-z]+/.test(value) && + * /[A-Z]+/.test(value) && + * /\W+/.test(value); + * }; + * ``` + * + * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to + * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided + * is expected to return a promise when it is run during the model validation process. Once the promise + * is delivered then the validation status will be set to true when fulfilled and false when rejected. + * When the asynchronous validators are triggered, each of the validators will run in parallel and the model + * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator + * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators + * will only run once all synchronous validators have passed. + * + * Please note that if $http is used then it is important that the server returns a success HTTP response code + * in order to fulfill the validation and a status level of `4xx` in order to reject the validation. + * + * ```js + * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { + * var value = modelValue || viewValue; + * + * // Lookup user by username + * return $http.get('/api/users/' + value). + * then(function resolved() { + * //username exists, this means validation fails + * return $q.reject('exists'); + * }, function rejected() { + * //username does not exist, therefore this validation passes + * return true; + * }); + * }; + * ``` + * + * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the + * view value has changed. It is called with no arguments, and its return value is ignored. + * This can be used in place of additional $watches against the model value. + * + * @property {Object} $error An object hash with all failing validator ids as keys. + * @property {Object} $pending An object hash with all pending validator ids as keys. * - * @description - * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element - * with the value of a given expression, and to update the text content when the value of that - * expression changes. + * @property {boolean} $untouched True if control has not lost focus yet. + * @property {boolean} $touched True if control has lost focus. + * @property {boolean} $pristine True if user has not interacted with the control yet. + * @property {boolean} $dirty True if user has already interacted with the control. + * @property {boolean} $valid True if there is no error. + * @property {boolean} $invalid True if at least one error on the control. + * @property {string} $name The name attribute of the control. * - * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like - * `{{ expression }}` which is similar but less verbose. + * @description * - * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily - * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an - * element attribute, it makes the bindings invisible to the user while the page is loading. + * `NgModelController` provides API for the {@link ngModel `ngModel`} directive. + * The controller contains services for data-binding, validation, CSS updates, and value formatting + * and parsing. It purposefully does not contain any logic which deals with DOM rendering or + * listening to DOM events. + * Such DOM related logic should be provided by other directives which make use of + * `NgModelController` for data-binding to control elements. + * Angular provides this DOM logic for most {@link input `input`} elements. + * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example + * custom control example} that uses `ngModelController` to bind to `contenteditable` elements. * - * An alternative solution to this problem would be using the - * {@link ng.directive:ngCloak ngCloak} directive. + * @example + * ### Custom Control Example + * This example shows how to use `NgModelController` with a custom control to achieve + * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) + * collaborate together to achieve the desired result. * + * `contenteditable` is an HTML5 attribute, which tells the browser to let the element + * contents be edited in place by the user. * - * @element ANY - * @param {expression} ngBind {@link guide/expression Expression} to evaluate. + * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize} + * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`). + * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks + * that content using the `$sce` service. * - * @example - * Enter a name in the Live Preview text box; the greeting below the text box changes instantly. - <example module="bindExample"> - <file name="index.html"> - <script> - angular.module('bindExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.name = 'Whirled'; - }]); - </script> - <div ng-controller="ExampleController"> - Enter name: <input type="text" ng-model="name"><br> - Hello <span ng-bind="name"></span>! - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-bind', function() { - var nameInput = element(by.model('name')); + * <example name="NgModelController" module="customControl" deps="angular-sanitize.js"> + <file name="style.css"> + [contenteditable] { + border: 1px solid black; + background-color: white; + min-height: 20px; + } - expect(element(by.binding('name')).getText()).toBe('Whirled'); - nameInput.clear(); - nameInput.sendKeys('world'); - expect(element(by.binding('name')).getText()).toBe('world'); - }); - </file> - </example> - */ -var ngBindDirective = ['$compile', function($compile) { - return { - restrict: 'AC', - compile: function ngBindCompile(templateElement) { - $compile.$$addBindingClass(templateElement); - return function ngBindLink(scope, element, attr) { - $compile.$$addBindingInfo(element, attr.ngBind); - element = element[0]; - scope.$watch(attr.ngBind, function ngBindWatchAction(value) { - element.textContent = value === undefined ? '' : value; - }); - }; - } - }; -}]; + .ng-invalid { + border: 1px solid red; + } + + </file> + <file name="script.js"> + angular.module('customControl', ['ngSanitize']). + directive('contenteditable', ['$sce', function($sce) { + return { + restrict: 'A', // only activate on element attribute + require: '?ngModel', // get a hold of NgModelController + link: function(scope, element, attrs, ngModel) { + if (!ngModel) return; // do nothing if no ng-model + // Specify how UI should be updated + ngModel.$render = function() { + element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); + }; -/** - * @ngdoc directive - * @name ngBindTemplate - * - * @description - * The `ngBindTemplate` directive specifies that the element - * text content should be replaced with the interpolation of the template - * in the `ngBindTemplate` attribute. - * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}` - * expressions. This directive is needed since some HTML elements - * (such as TITLE and OPTION) cannot contain SPAN elements. + // Listen for change events to enable binding + element.on('blur keyup change', function() { + scope.$evalAsync(read); + }); + read(); // initialize + + // Write data to the model + function read() { + var html = element.html(); + // When we clear the content editable the browser leaves a <br> behind + // If strip-br attribute is provided then we strip this out + if ( attrs.stripBr && html == '<br>' ) { + html = ''; + } + ngModel.$setViewValue(html); + } + } + }; + }]); + </file> + <file name="index.html"> + <form name="myForm"> + <div contenteditable + name="myWidget" ng-model="userContent" + strip-br="true" + required>Change me!</div> + <span ng-show="myForm.myWidget.$error.required">Required!</span> + <hr> + <textarea ng-model="userContent" aria-label="Dynamic textarea"></textarea> + </form> + </file> + <file name="protractor.js" type="protractor"> + it('should data-bind and become invalid', function() { + if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') { + // SafariDriver can't handle contenteditable + // and Firefox driver can't clear contenteditables very well + return; + } + var contentEditable = element(by.css('[contenteditable]')); + var content = 'Change me!'; + + expect(contentEditable.getText()).toEqual(content); + + contentEditable.clear(); + contentEditable.sendKeys(protractor.Key.BACK_SPACE); + expect(contentEditable.getText()).toEqual(''); + expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/); + }); + </file> + * </example> * - * @element ANY - * @param {string} ngBindTemplate template of form - * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval. * - * @example - * Try it here: enter text in text box and watch the greeting change. - <example module="bindExample"> - <file name="index.html"> - <script> - angular.module('bindExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.salutation = 'Hello'; - $scope.name = 'World'; - }]); - </script> - <div ng-controller="ExampleController"> - Salutation: <input type="text" ng-model="salutation"><br> - Name: <input type="text" ng-model="name"><br> - <pre ng-bind-template="{{salutation}} {{name}}!"></pre> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-bind', function() { - var salutationElem = element(by.binding('salutation')); - var salutationInput = element(by.model('salutation')); - var nameInput = element(by.model('name')); + */ +var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate', + function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) { + this.$viewValue = Number.NaN; + this.$modelValue = Number.NaN; + this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity. + this.$validators = {}; + this.$asyncValidators = {}; + this.$parsers = []; + this.$formatters = []; + this.$viewChangeListeners = []; + this.$untouched = true; + this.$touched = false; + this.$pristine = true; + this.$dirty = false; + this.$valid = true; + this.$invalid = false; + this.$error = {}; // keep invalid keys here + this.$$success = {}; // keep valid keys here + this.$pending = undefined; // keep pending keys here + this.$name = $interpolate($attr.name || '', false)($scope); - expect(salutationElem.getText()).toBe('Hello World!'); - salutationInput.clear(); - salutationInput.sendKeys('Greetings'); - nameInput.clear(); - nameInput.sendKeys('user'); + var parsedNgModel = $parse($attr.ngModel), + parsedNgModelAssign = parsedNgModel.assign, + ngModelGet = parsedNgModel, + ngModelSet = parsedNgModelAssign, + pendingDebounce = null, + parserValid, + ctrl = this; - expect(salutationElem.getText()).toBe('Greetings user!'); - }); - </file> - </example> - */ -var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) { - return { - compile: function ngBindTemplateCompile(templateElement) { - $compile.$$addBindingClass(templateElement); - return function ngBindTemplateLink(scope, element, attr) { - var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate)); - $compile.$$addBindingInfo(element, interpolateFn.expressions); - element = element[0]; - attr.$observe('ngBindTemplate', function(value) { - element.textContent = value === undefined ? '' : value; - }); + this.$$setOptions = function(options) { + ctrl.$options = options; + if (options && options.getterSetter) { + var invokeModelGetter = $parse($attr.ngModel + '()'), + invokeModelSetter = $parse($attr.ngModel + '($$$p)'); + + ngModelGet = function($scope) { + var modelValue = parsedNgModel($scope); + if (isFunction(modelValue)) { + modelValue = invokeModelGetter($scope); + } + return modelValue; + }; + ngModelSet = function($scope, newValue) { + if (isFunction(parsedNgModel($scope))) { + invokeModelSetter($scope, {$$$p: ctrl.$modelValue}); + } else { + parsedNgModelAssign($scope, ctrl.$modelValue); + } }; + } else if (!parsedNgModel.assign) { + throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}", + $attr.ngModel, startingTag($element)); } }; -}]; + /** + * @ngdoc method + * @name ngModel.NgModelController#$render + * + * @description + * Called when the view needs to be updated. It is expected that the user of the ng-model + * directive will implement this method. + * + * The `$render()` method is invoked in the following situations: + * + * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last + * committed value then `$render()` is called to update the input control. + * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and + * the `$viewValue` are different from last time. + * + * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of + * `$modelValue` and `$viewValue` are actually different from their previous value. If `$modelValue` + * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be + * invoked if you only change a property on the objects. + */ + this.$render = noop; -/** - * @ngdoc directive - * @name ngBindHtml - * - * @description - * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default, - * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service. - * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link - * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize} - * in your module's dependencies, you need to include "angular-sanitize.js" in your application. - * - * You may also bypass sanitization for values you know are safe. To do so, bind to - * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example - * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}. - * - * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you - * will have an exception (instead of an exploit.) - * - * @element ANY - * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate. - * - * @example + /** + * @ngdoc method + * @name ngModel.NgModelController#$isEmpty + * + * @description + * This is called when we need to determine if the value of an input is empty. + * + * For instance, the required directive does this to work out if the input has data or not. + * + * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. + * + * You can override this for input directives whose concept of being empty is different from the + * default. The `checkboxInputType` directive does this because in its case a value of `false` + * implies empty. + * + * @param {*} value The value of the input to check for emptiness. + * @returns {boolean} True if `value` is "empty". + */ + this.$isEmpty = function(value) { + return isUndefined(value) || value === '' || value === null || value !== value; + }; - <example module="bindHtmlExample" deps="angular-sanitize.js"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <p ng-bind-html="myHTML"></p> - </div> - </file> + var parentForm = $element.inheritedData('$formController') || nullFormCtrl, + currentValidationRunId = 0; - <file name="script.js"> - angular.module('bindHtmlExample', ['ngSanitize']) - .controller('ExampleController', ['$scope', function($scope) { - $scope.myHTML = - 'I am an <code>HTML</code>string with ' + - '<a href="#">links!</a> and other <em>stuff</em>'; - }]); - </file> + /** + * @ngdoc method + * @name ngModel.NgModelController#$setValidity + * + * @description + * Change the validity state, and notify the form. + * + * This method can be called within $parsers/$formatters or a custom validation implementation. + * However, in most cases it should be sufficient to use the `ngModel.$validators` and + * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically. + * + * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned + * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` + * (for unfulfilled `$asyncValidators`), so that it is available for data-binding. + * The `validationErrorKey` should be in camelCase and will get converted into dash-case + * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` + * class and can be bound to as `{{someForm.someControl.$error.myError}}` . + * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined), + * or skipped (null). Pending is used for unfulfilled `$asyncValidators`. + * Skipped is used by Angular when validators do not run because of parse errors and + * when `$asyncValidators` do not run because any of the `$validators` failed. + */ + addSetValidityMethod({ + ctrl: this, + $element: $element, + set: function(object, property) { + object[property] = true; + }, + unset: function(object, property) { + delete object[property]; + }, + parentForm: parentForm, + $animate: $animate + }); - <file name="protractor.js" type="protractor"> - it('should check ng-bind-html', function() { - expect(element(by.binding('myHTML')).getText()).toBe( - 'I am an HTMLstring with links! and other stuff'); - }); - </file> - </example> - */ -var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) { - return { - restrict: 'A', - compile: function ngBindHtmlCompile(tElement, tAttrs) { - var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml); - var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) { - return (value || '').toString(); - }); - $compile.$$addBindingClass(tElement); + /** + * @ngdoc method + * @name ngModel.NgModelController#$setPristine + * + * @description + * Sets the control to its pristine state. + * + * This method can be called to remove the `ng-dirty` class and set the control to its pristine + * state (`ng-pristine` class). A model is considered to be pristine when the control + * has not been changed from when first compiled. + */ + this.$setPristine = function() { + ctrl.$dirty = false; + ctrl.$pristine = true; + $animate.removeClass($element, DIRTY_CLASS); + $animate.addClass($element, PRISTINE_CLASS); + }; - return function ngBindHtmlLink(scope, element, attr) { - $compile.$$addBindingInfo(element, attr.ngBindHtml); + /** + * @ngdoc method + * @name ngModel.NgModelController#$setDirty + * + * @description + * Sets the control to its dirty state. + * + * This method can be called to remove the `ng-pristine` class and set the control to its dirty + * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed + * from when first compiled. + */ + this.$setDirty = function() { + ctrl.$dirty = true; + ctrl.$pristine = false; + $animate.removeClass($element, PRISTINE_CLASS); + $animate.addClass($element, DIRTY_CLASS); + parentForm.$setDirty(); + }; - scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() { - // we re-evaluate the expr because we want a TrustedValueHolderType - // for $sce, not a string - element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || ''); - }); - }; - } + /** + * @ngdoc method + * @name ngModel.NgModelController#$setUntouched + * + * @description + * Sets the control to its untouched state. + * + * This method can be called to remove the `ng-touched` class and set the control to its + * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched + * by default, however this function can be used to restore that state if the model has + * already been touched by the user. + */ + this.$setUntouched = function() { + ctrl.$touched = false; + ctrl.$untouched = true; + $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setTouched + * + * @description + * Sets the control to its touched state. + * + * This method can be called to remove the `ng-untouched` class and set the control to its + * touched state (`ng-touched` class). A model is considered to be touched when the user has + * first focused the control element and then shifted focus away from the control (blur event). + */ + this.$setTouched = function() { + ctrl.$touched = true; + ctrl.$untouched = false; + $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$rollbackViewValue + * + * @description + * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`, + * which may be caused by a pending debounced event or because the input is waiting for a some + * future event. + * + * If you have an input that uses `ng-model-options` to set up debounced events or events such + * as blur you can have a situation where there is a period when the `$viewValue` + * is out of synch with the ngModel's `$modelValue`. + * + * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue` + * programmatically before these debounced/future events have resolved/occurred, because Angular's + * dirty checking mechanism is not able to tell whether the model has actually changed or not. + * + * The `$rollbackViewValue()` method should be called before programmatically changing the model of an + * input which may have such events pending. This is important in order to make sure that the + * input field will be updated with the new model value and any pending operations are cancelled. + * + * <example name="ng-model-cancel-update" module="cancel-update-example"> + * <file name="app.js"> + * angular.module('cancel-update-example', []) + * + * .controller('CancelUpdateController', ['$scope', function($scope) { + * $scope.resetWithCancel = function(e) { + * if (e.keyCode == 27) { + * $scope.myForm.myInput1.$rollbackViewValue(); + * $scope.myValue = ''; + * } + * }; + * $scope.resetWithoutCancel = function(e) { + * if (e.keyCode == 27) { + * $scope.myValue = ''; + * } + * }; + * }]); + * </file> + * <file name="index.html"> + * <div ng-controller="CancelUpdateController"> + * <p>Try typing something in each input. See that the model only updates when you + * blur off the input. + * </p> + * <p>Now see what happens if you start typing then press the Escape key</p> + * + * <form name="myForm" ng-model-options="{ updateOn: 'blur' }"> + * <p id="inputDescription1">With $rollbackViewValue()</p> + * <input name="myInput1" aria-describedby="inputDescription1" ng-model="myValue" + * ng-keydown="resetWithCancel($event)"><br/> + * myValue: "{{ myValue }}" + * + * <p id="inputDescription2">Without $rollbackViewValue()</p> + * <input name="myInput2" aria-describedby="inputDescription2" ng-model="myValue" + * ng-keydown="resetWithoutCancel($event)"><br/> + * myValue: "{{ myValue }}" + * </form> + * </div> + * </file> + * </example> + */ + this.$rollbackViewValue = function() { + $timeout.cancel(pendingDebounce); + ctrl.$viewValue = ctrl.$$lastCommittedViewValue; + ctrl.$render(); }; -}]; - -/** - * @ngdoc directive - * @name ngChange - * - * @description - * Evaluate the given expression when the user changes the input. - * The expression is evaluated immediately, unlike the JavaScript onchange event - * which only triggers at the end of a change (usually, when the user leaves the - * form element or presses the return key). - * - * The `ngChange` expression is only evaluated when a change in the input value causes - * a new value to be committed to the model. - * - * It will not be evaluated: - * * if the value returned from the `$parsers` transformation pipeline has not changed - * * if the input has continued to be invalid since the model will stay `null` - * * if the model is changed programmatically and not by a change to the input value - * - * - * Note, this directive requires `ngModel` to be present. - * - * @element input - * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change - * in input value. - * - * @example - * <example name="ngChange-directive" module="changeExample"> - * <file name="index.html"> - * <script> - * angular.module('changeExample', []) - * .controller('ExampleController', ['$scope', function($scope) { - * $scope.counter = 0; - * $scope.change = function() { - * $scope.counter++; - * }; - * }]); - * </script> - * <div ng-controller="ExampleController"> - * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" /> - * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" /> - * <label for="ng-change-example2">Confirmed</label><br /> - * <tt>debug = {{confirmed}}</tt><br/> - * <tt>counter = {{counter}}</tt><br/> - * </div> - * </file> - * <file name="protractor.js" type="protractor"> - * var counter = element(by.binding('counter')); - * var debug = element(by.binding('confirmed')); - * - * it('should evaluate the expression if changing from view', function() { - * expect(counter.getText()).toContain('0'); - * - * element(by.id('ng-change-example1')).click(); - * - * expect(counter.getText()).toContain('1'); - * expect(debug.getText()).toContain('true'); - * }); - * - * it('should not evaluate the expression if changing from model', function() { - * element(by.id('ng-change-example2')).click(); - * expect(counter.getText()).toContain('0'); - * expect(debug.getText()).toContain('true'); - * }); - * </file> - * </example> - */ -var ngChangeDirective = valueFn({ - restrict: 'A', - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - ctrl.$viewChangeListeners.push(function() { - scope.$eval(attr.ngChange); - }); - } -}); + /** + * @ngdoc method + * @name ngModel.NgModelController#$validate + * + * @description + * Runs each of the registered validators (first synchronous validators and then + * asynchronous validators). + * If the validity changes to invalid, the model will be set to `undefined`, + * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. + * If the validity changes to valid, it will set the model to the last available valid + * `$modelValue`, i.e. either the last parsed value or the last value set from the scope. + */ + this.$validate = function() { + // ignore $validate before model is initialized + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + return; + } -function classDirective(name, selector) { - name = 'ngClass' + name; - return ['$animate', function($animate) { - return { - restrict: 'AC', - link: function(scope, element, attr) { - var oldVal; + var viewValue = ctrl.$$lastCommittedViewValue; + // Note: we use the $$rawModelValue as $modelValue might have been + // set to undefined during a view -> model update that found validation + // errors. We can't parse the view here, since that could change + // the model although neither viewValue nor the model on the scope changed + var modelValue = ctrl.$$rawModelValue; - scope.$watch(attr[name], ngClassWatchAction, true); + var prevValid = ctrl.$valid; + var prevModelValue = ctrl.$modelValue; - attr.$observe('class', function(value) { - ngClassWatchAction(scope.$eval(attr[name])); - }); + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + ctrl.$$runValidators(modelValue, viewValue, function(allValid) { + // If there was no change in validity, don't update the model + // This prevents changing an invalid modelValue to undefined + if (!allowInvalid && prevValid !== allValid) { + // Note: Don't check ctrl.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + ctrl.$modelValue = allValid ? modelValue : undefined; - if (name !== 'ngClass') { - scope.$watch('$index', function($index, old$index) { - // jshint bitwise: false - var mod = $index & 1; - if (mod !== (old$index & 1)) { - var classes = arrayClasses(scope.$eval(attr[name])); - mod === selector ? - addClasses(classes) : - removeClasses(classes); - } - }); + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); } + } + }); - function addClasses(classes) { - var newClasses = digestClassCounts(classes, 1); - attr.$addClass(newClasses); - } + }; - function removeClasses(classes) { - var newClasses = digestClassCounts(classes, -1); - attr.$removeClass(newClasses); - } + this.$$runValidators = function(modelValue, viewValue, doneCallback) { + currentValidationRunId++; + var localValidationRunId = currentValidationRunId; - function digestClassCounts(classes, count) { - var classCounts = element.data('$classCounts') || {}; - var classesToUpdate = []; - forEach(classes, function(className) { - if (count > 0 || classCounts[className]) { - classCounts[className] = (classCounts[className] || 0) + count; - if (classCounts[className] === +(count > 0)) { - classesToUpdate.push(className); - } - } + // check parser error + if (!processParseErrors()) { + validationDone(false); + return; + } + if (!processSyncValidators()) { + validationDone(false); + return; + } + processAsyncValidators(); + + function processParseErrors() { + var errorKey = ctrl.$$parserName || 'parse'; + if (parserValid === undefined) { + setValidity(errorKey, null); + } else { + if (!parserValid) { + forEach(ctrl.$validators, function(v, name) { + setValidity(name, null); + }); + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); }); - element.data('$classCounts', classCounts); - return classesToUpdate.join(' '); } + // Set the parse error last, to prevent unsetting it, should a $validators key == parserName + setValidity(errorKey, parserValid); + return parserValid; + } + return true; + } - function updateClasses(oldClasses, newClasses) { - var toAdd = arrayDifference(newClasses, oldClasses); - var toRemove = arrayDifference(oldClasses, newClasses); - toAdd = digestClassCounts(toAdd, 1); - toRemove = digestClassCounts(toRemove, -1); - if (toAdd && toAdd.length) { - $animate.addClass(element, toAdd); - } - if (toRemove && toRemove.length) { - $animate.removeClass(element, toRemove); - } - } + function processSyncValidators() { + var syncValidatorsValid = true; + forEach(ctrl.$validators, function(validator, name) { + var result = validator(modelValue, viewValue); + syncValidatorsValid = syncValidatorsValid && result; + setValidity(name, result); + }); + if (!syncValidatorsValid) { + forEach(ctrl.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + return false; + } + return true; + } - function ngClassWatchAction(newVal) { - if (selector === true || scope.$index % 2 === selector) { - var newClasses = arrayClasses(newVal || []); - if (!oldVal) { - addClasses(newClasses); - } else if (!equals(newVal,oldVal)) { - var oldClasses = arrayClasses(oldVal); - updateClasses(oldClasses, newClasses); - } - } - oldVal = shallowCopy(newVal); + function processAsyncValidators() { + var validatorPromises = []; + var allValid = true; + forEach(ctrl.$asyncValidators, function(validator, name) { + var promise = validator(modelValue, viewValue); + if (!isPromiseLike(promise)) { + throw $ngModelMinErr("$asyncValidators", + "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); } + setValidity(name, undefined); + validatorPromises.push(promise.then(function() { + setValidity(name, true); + }, function(error) { + allValid = false; + setValidity(name, false); + })); + }); + if (!validatorPromises.length) { + validationDone(true); + } else { + $q.all(validatorPromises).then(function() { + validationDone(allValid); + }, noop); } - }; - - function arrayDifference(tokens1, tokens2) { - var values = []; + } - outer: - for (var i = 0; i < tokens1.length; i++) { - var token = tokens1[i]; - for (var j = 0; j < tokens2.length; j++) { - if (token == tokens2[j]) continue outer; - } - values.push(token); + function setValidity(name, isValid) { + if (localValidationRunId === currentValidationRunId) { + ctrl.$setValidity(name, isValid); } - return values; } - function arrayClasses(classVal) { - if (isArray(classVal)) { - return classVal; - } else if (isString(classVal)) { - return classVal.split(' '); - } else if (isObject(classVal)) { - var classes = []; - forEach(classVal, function(v, k) { - if (v) { - classes = classes.concat(k.split(' ')); - } - }); - return classes; + function validationDone(allValid) { + if (localValidationRunId === currentValidationRunId) { + + doneCallback(allValid); } - return classVal; } - }]; -} + }; -/** - * @ngdoc directive - * @name ngClass - * @restrict AC - * - * @description - * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding - * an expression that represents all classes to be added. - * - * The directive operates in three different ways, depending on which of three types the expression - * evaluates to: - * - * 1. If the expression evaluates to a string, the string should be one or more space-delimited class - * names. - * - * 2. If the expression evaluates to an array, each element of the array should be a string that is - * one or more space-delimited class names. - * - * 3. If the expression evaluates to an object, then for each key-value pair of the - * object with a truthy value the corresponding key is used as a class name. - * - * The directive won't add duplicate classes if a particular class was already set. - * - * When the expression changes, the previously added classes are removed and only then the - * new classes are added. - * - * @animations - * **add** - happens just before the class is applied to the elements - * - * **remove** - happens just before the class is removed from the element - * - * @element ANY - * @param {expression} ngClass {@link guide/expression Expression} to eval. The result - * of the evaluation can be a string representing space delimited class - * names, an array, or a map of class names to boolean values. In the case of a map, the - * names of the properties whose values are truthy will be added as css classes to the - * element. - * - * @example Example that demonstrates basic bindings via ngClass directive. - <example> - <file name="index.html"> - <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p> - <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br> - <input type="checkbox" ng-model="important"> important (apply "bold" class)<br> - <input type="checkbox" ng-model="error"> error (apply "red" class) - <hr> - <p ng-class="style">Using String Syntax</p> - <input type="text" ng-model="style" placeholder="Type: bold strike red"> - <hr> - <p ng-class="[style1, style2, style3]">Using Array Syntax</p> - <input ng-model="style1" placeholder="Type: bold, strike or red"><br> - <input ng-model="style2" placeholder="Type: bold, strike or red"><br> - <input ng-model="style3" placeholder="Type: bold, strike or red"><br> - </file> - <file name="style.css"> - .strike { - text-decoration: line-through; - } - .bold { - font-weight: bold; - } - .red { - color: red; - } - </file> - <file name="protractor.js" type="protractor"> - var ps = element.all(by.css('p')); + /** + * @ngdoc method + * @name ngModel.NgModelController#$commitViewValue + * + * @description + * Commit a pending update to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. this method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. + */ + this.$commitViewValue = function() { + var viewValue = ctrl.$viewValue; - it('should let you toggle the class', function() { + $timeout.cancel(pendingDebounce); - expect(ps.first().getAttribute('class')).not.toMatch(/bold/); - expect(ps.first().getAttribute('class')).not.toMatch(/red/); + // If the view value has not changed then we should just exit, except in the case where there is + // a native validator on the element. In this case the validation state may have changed even though + // the viewValue has stayed empty. + if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) { + return; + } + ctrl.$$lastCommittedViewValue = viewValue; - element(by.model('important')).click(); - expect(ps.first().getAttribute('class')).toMatch(/bold/); + // change to dirty + if (ctrl.$pristine) { + this.$setDirty(); + } + this.$$parseAndValidate(); + }; - element(by.model('error')).click(); - expect(ps.first().getAttribute('class')).toMatch(/red/); - }); + this.$$parseAndValidate = function() { + var viewValue = ctrl.$$lastCommittedViewValue; + var modelValue = viewValue; + parserValid = isUndefined(modelValue) ? undefined : true; - it('should let you toggle string example', function() { - expect(ps.get(1).getAttribute('class')).toBe(''); - element(by.model('style')).clear(); - element(by.model('style')).sendKeys('red'); - expect(ps.get(1).getAttribute('class')).toBe('red'); - }); + if (parserValid) { + for (var i = 0; i < ctrl.$parsers.length; i++) { + modelValue = ctrl.$parsers[i](modelValue); + if (isUndefined(modelValue)) { + parserValid = false; + break; + } + } + } + if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { + // ctrl.$modelValue has not been touched yet... + ctrl.$modelValue = ngModelGet($scope); + } + var prevModelValue = ctrl.$modelValue; + var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + ctrl.$$rawModelValue = modelValue; - it('array example should have 3 classes', function() { - expect(ps.last().getAttribute('class')).toBe(''); - element(by.model('style1')).sendKeys('bold'); - element(by.model('style2')).sendKeys('strike'); - element(by.model('style3')).sendKeys('red'); - expect(ps.last().getAttribute('class')).toBe('bold strike red'); - }); - </file> - </example> + if (allowInvalid) { + ctrl.$modelValue = modelValue; + writeToModelIfNeeded(); + } - ## Animations + // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. + // This can happen if e.g. $setViewValue is called from inside a parser + ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { + if (!allowInvalid) { + // Note: Don't check ctrl.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + ctrl.$modelValue = allValid ? modelValue : undefined; + writeToModelIfNeeded(); + } + }); - The example below demonstrates how to perform animations using ngClass. + function writeToModelIfNeeded() { + if (ctrl.$modelValue !== prevModelValue) { + ctrl.$$writeModelToScope(); + } + } + }; - <example module="ngAnimate" deps="angular-animate.js" animations="true"> - <file name="index.html"> - <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'"> - <input id="clearbtn" type="button" value="clear" ng-click="myVar=''"> - <br> - <span class="base-class" ng-class="myVar">Sample Text</span> - </file> - <file name="style.css"> - .base-class { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - } + this.$$writeModelToScope = function() { + ngModelSet($scope, ctrl.$modelValue); + forEach(ctrl.$viewChangeListeners, function(listener) { + try { + listener(); + } catch (e) { + $exceptionHandler(e); + } + }); + }; + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setViewValue + * + * @description + * Update the view value. + * + * This method should be called when an input directive want to change the view value; typically, + * this is done from within a DOM event handler. + * + * For example {@link ng.directive:input input} calls it when the value of the input changes and + * {@link ng.directive:select select} calls it when an option is selected. + * + * If the new `value` is an object (rather than a string or a number), we should make a copy of the + * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep + * watch of objects, it only looks for a change of identity. If you only change the property of + * the object then ngModel will not realise that the object has changed and will not invoke the + * `$parsers` and `$validators` pipelines. + * + * For this reason, you should not change properties of the copy once it has been passed to + * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly. + * + * When this method is called, the new `value` will be staged for committing through the `$parsers` + * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged + * value sent directly for processing, finally to be applied to `$modelValue` and then the + * **expression** specified in the `ng-model` attribute. + * + * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called. + * + * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn` + * and the `default` trigger is not listed, all those actions will remain pending until one of the + * `updateOn` events is triggered on the DOM element. + * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions} + * directive is used with a custom debounce for this particular event. + * + * Note that calling this function does not trigger a `$digest`. + * + * @param {string} value Value from the view. + * @param {string} trigger Event that triggered the update. + */ + this.$setViewValue = function(value, trigger) { + ctrl.$viewValue = value; + if (!ctrl.$options || ctrl.$options.updateOnDefault) { + ctrl.$$debounceViewValueCommit(trigger); + } + }; + + this.$$debounceViewValueCommit = function(trigger) { + var debounceDelay = 0, + options = ctrl.$options, + debounce; + + if (options && isDefined(options.debounce)) { + debounce = options.debounce; + if (isNumber(debounce)) { + debounceDelay = debounce; + } else if (isNumber(debounce[trigger])) { + debounceDelay = debounce[trigger]; + } else if (isNumber(debounce['default'])) { + debounceDelay = debounce['default']; + } + } - .base-class.my-class { - color: red; - font-size:3em; - } - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-class', function() { - expect(element(by.css('.base-class')).getAttribute('class')).not. - toMatch(/my-class/); + $timeout.cancel(pendingDebounce); + if (debounceDelay) { + pendingDebounce = $timeout(function() { + ctrl.$commitViewValue(); + }, debounceDelay); + } else if ($rootScope.$$phase) { + ctrl.$commitViewValue(); + } else { + $scope.$apply(function() { + ctrl.$commitViewValue(); + }); + } + }; - element(by.id('setbtn')).click(); + // model -> value + // Note: we cannot use a normal scope.$watch as we want to detect the following: + // 1. scope value is 'a' + // 2. user enters 'b' + // 3. ng-change kicks in and reverts scope value to 'a' + // -> scope value did not change since the last digest as + // ng-change executes in apply phase + // 4. view should be changed back to 'a' + $scope.$watch(function ngModelWatch() { + var modelValue = ngModelGet($scope); - expect(element(by.css('.base-class')).getAttribute('class')). - toMatch(/my-class/); + // if scope model value and ngModel value are out of sync + // TODO(perf): why not move this to the action fn? + if (modelValue !== ctrl.$modelValue && + // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator + (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue) + ) { + ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; + parserValid = undefined; - element(by.id('clearbtn')).click(); + var formatters = ctrl.$formatters, + idx = formatters.length; - expect(element(by.css('.base-class')).getAttribute('class')).not. - toMatch(/my-class/); - }); - </file> - </example> + var viewValue = modelValue; + while (idx--) { + viewValue = formatters[idx](viewValue); + } + if (ctrl.$viewValue !== viewValue) { + ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; + ctrl.$render(); + ctrl.$$runValidators(modelValue, viewValue, noop); + } + } - ## ngClass and pre-existing CSS3 Transitions/Animations - The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure. - Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder - any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure - to view the step by step details of {@link ng.$animate#addClass $animate.addClass} and - {@link ng.$animate#removeClass $animate.removeClass}. - */ -var ngClassDirective = classDirective('', true); + return modelValue; + }); +}]; -/** - * @ngdoc directive - * @name ngClassOdd - * @restrict AC - * - * @description - * The `ngClassOdd` and `ngClassEven` directives work exactly as - * {@link ng.directive:ngClass ngClass}, except they work in - * conjunction with `ngRepeat` and take effect only on odd (even) rows. - * - * This directive can be applied only within the scope of an - * {@link ng.directive:ngRepeat ngRepeat}. - * - * @element ANY - * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result - * of the evaluation can be a string representing space delimited class names or an array. - * - * @example - <example> - <file name="index.html"> - <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']"> - <li ng-repeat="name in names"> - <span ng-class-odd="'odd'" ng-class-even="'even'"> - {{name}} - </span> - </li> - </ol> - </file> - <file name="style.css"> - .odd { - color: red; - } - .even { - color: blue; - } - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-class-odd and ng-class-even', function() { - expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). - toMatch(/odd/); - expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). - toMatch(/even/); - }); - </file> - </example> - */ -var ngClassOddDirective = classDirective('Odd', 0); /** * @ngdoc directive - * @name ngClassEven - * @restrict AC - * - * @description - * The `ngClassOdd` and `ngClassEven` directives work exactly as - * {@link ng.directive:ngClass ngClass}, except they work in - * conjunction with `ngRepeat` and take effect only on odd (even) rows. - * - * This directive can be applied only within the scope of an - * {@link ng.directive:ngRepeat ngRepeat}. - * - * @element ANY - * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The - * result of the evaluation can be a string representing space delimited class names or an array. + * @name ngModel * - * @example - <example> - <file name="index.html"> - <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']"> - <li ng-repeat="name in names"> - <span ng-class-odd="'odd'" ng-class-even="'even'"> - {{name}} - </span> - </li> - </ol> - </file> - <file name="style.css"> - .odd { - color: red; - } - .even { - color: blue; - } - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-class-odd and ng-class-even', function() { - expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')). - toMatch(/odd/); - expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')). - toMatch(/even/); - }); - </file> - </example> - */ -var ngClassEvenDirective = classDirective('Even', 1); - -/** - * @ngdoc directive - * @name ngCloak - * @restrict AC + * @element input + * @priority 1 * * @description - * The `ngCloak` directive is used to prevent the Angular html template from being briefly - * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this - * directive to avoid the undesirable flicker effect caused by the html template display. - * - * The directive can be applied to the `<body>` element, but the preferred usage is to apply - * multiple `ngCloak` directives to small portions of the page to permit progressive rendering - * of the browser view. - * - * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and - * `angular.min.js`. - * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a + * property on the scope using {@link ngModel.NgModelController NgModelController}, + * which is created and exposed by this directive. * - * ```css - * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { - * display: none !important; - * } - * ``` + * `ngModel` is responsible for: * - * When this css rule is loaded by the browser, all html elements (including their children) that - * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive - * during the compilation of the template it deletes the `ngCloak` element attribute, making - * the compiled element visible. + * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` + * require. + * - Providing validation behavior (i.e. required, number, email, url). + * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors). + * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations. + * - Registering the control with its parent {@link ng.directive:form form}. * - * For the best result, the `angular.js` script must be loaded in the head section of the html - * document; alternatively, the css rule above must be included in the external stylesheet of the - * application. + * Note: `ngModel` will try to bind to the property given by evaluating the expression on the + * current scope. If the property doesn't already exist on this scope, it will be created + * implicitly and added to the scope. * - * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they - * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css - * class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below. + * For best practices on using `ngModel`, see: * - * @element ANY + * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) * - * @example - <example> - <file name="index.html"> - <div id="template1" ng-cloak>{{ 'hello' }}</div> - <div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div> - </file> - <file name="protractor.js" type="protractor"> - it('should remove the template directive and css class', function() { - expect($('#template1').getAttribute('ng-cloak')). - toBeNull(); - expect($('#template2').getAttribute('ng-cloak')). - toBeNull(); - }); - </file> - </example> + * For basic examples, how to use `ngModel`, see: * - */ -var ngCloakDirective = ngDirective({ - compile: function(element, attr) { - attr.$set('ngCloak', undefined); - element.removeClass('ng-cloak'); - } -}); - -/** - * @ngdoc directive - * @name ngController + * - {@link ng.directive:input input} + * - {@link input[text] text} + * - {@link input[checkbox] checkbox} + * - {@link input[radio] radio} + * - {@link input[number] number} + * - {@link input[email] email} + * - {@link input[url] url} + * - {@link input[date] date} + * - {@link input[datetime-local] datetime-local} + * - {@link input[time] time} + * - {@link input[month] month} + * - {@link input[week] week} + * - {@link ng.directive:select select} + * - {@link ng.directive:textarea textarea} * - * @description - * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular - * supports the principles behind the Model-View-Controller design pattern. + * # CSS classes + * The following CSS classes are added and removed on the associated input/select/textarea element + * depending on the validity of the model. * - * MVC components in angular: + * - `ng-valid`: the model is valid + * - `ng-invalid`: the model is invalid + * - `ng-valid-[key]`: for each valid key added by `$setValidity` + * - `ng-invalid-[key]`: for each invalid key added by `$setValidity` + * - `ng-pristine`: the control hasn't been interacted with yet + * - `ng-dirty`: the control has been interacted with + * - `ng-touched`: the control has been blurred + * - `ng-untouched`: the control hasn't been blurred + * - `ng-pending`: any `$asyncValidators` are unfulfilled * - * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties - * are accessed through bindings. - * * View — The template (HTML with data bindings) that is rendered into the View. - * * Controller — The `ngController` directive specifies a Controller class; the class contains business - * logic behind the application to decorate the scope with functions and values + * Keep in mind that ngAnimate can detect each of these classes when added and removed. * - * Note that you can also attach controllers to the DOM by declaring it in a route definition - * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller - * again using `ng-controller` in the template itself. This will cause the controller to be attached - * and executed twice. + * ## Animation Hooks * - * @element ANY - * @scope - * @priority 500 - * @param {expression} ngController Name of a constructor function registered with the current - * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression} - * that on the current scope evaluates to a constructor function. + * Animations within models are triggered when any of the associated CSS classes are added and removed + * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`, + * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself. + * The animations that are triggered within ngModel are similar to how they work in ngClass and + * animations can be hooked into using CSS transitions, keyframes as well as JS animations. * - * The controller instance can be published into a scope property by specifying - * `ng-controller="as propertyName"`. + * The following example shows a simple way to utilize CSS transitions to style an input element + * that has been rendered as invalid after it has been validated: * - * If the current `$controllerProvider` is configured to use globals (via - * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may - * also be the name of a globally accessible constructor function (not recommended). + * <pre> + * //be sure to include ngAnimate as a module to hook into more + * //advanced animations + * .my-input { + * transition:0.5s linear all; + * background: white; + * } + * .my-input.ng-invalid { + * background: red; + * color:white; + * } + * </pre> * * @example - * Here is a simple form for editing user contact information. Adding, removing, clearing, and - * greeting are methods declared on the controller (see source tab). These methods can - * easily be called from the angular markup. Any changes to the data are automatically reflected - * in the View without the need for a manual update. - * - * Two different declaration styles are included below: - * - * * one binds methods and properties directly onto the controller using `this`: - * `ng-controller="SettingsController1 as settings"` - * * one injects `$scope` into the controller: - * `ng-controller="SettingsController2"` - * - * The second option is more common in the Angular community, and is generally used in boilerplates - * and in this guide. However, there are advantages to binding properties directly to the controller - * and avoiding scope. - * - * * Using `controller as` makes it obvious which controller you are accessing in the template when - * multiple controllers apply to an element. - * * If you are writing your controllers as classes you have easier access to the properties and - * methods, which will appear on the scope, from inside the controller code. - * * Since there is always a `.` in the bindings, you don't have to worry about prototypal - * inheritance masking primitives. - * - * This example demonstrates the `controller as` syntax. - * - * <example name="ngControllerAs" module="controllerAsExample"> - * <file name="index.html"> - * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings"> - * Name: <input type="text" ng-model="settings.name"/> - * [ <a href="" ng-click="settings.greet()">greet</a> ]<br/> - * Contact: - * <ul> - * <li ng-repeat="contact in settings.contacts"> - * <select ng-model="contact.type"> - * <option>phone</option> - * <option>email</option> - * </select> - * <input type="text" ng-model="contact.value"/> - * [ <a href="" ng-click="settings.clearContact(contact)">clear</a> - * | <a href="" ng-click="settings.removeContact(contact)">X</a> ] - * </li> - * <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li> - * </ul> - * </div> - * </file> - * <file name="app.js"> - * angular.module('controllerAsExample', []) - * .controller('SettingsController1', SettingsController1); - * - * function SettingsController1() { - * this.name = "John Smith"; - * this.contacts = [ - * {type: 'phone', value: '408 555 1212'}, - * {type: 'email', value: 'john.smith@example.org'} ]; - * } - * - * SettingsController1.prototype.greet = function() { - * alert(this.name); - * }; - * - * SettingsController1.prototype.addContact = function() { - * this.contacts.push({type: 'email', value: 'yourname@example.org'}); - * }; - * - * SettingsController1.prototype.removeContact = function(contactToRemove) { - * var index = this.contacts.indexOf(contactToRemove); - * this.contacts.splice(index, 1); - * }; - * - * SettingsController1.prototype.clearContact = function(contact) { - * contact.type = 'phone'; - * contact.value = ''; - * }; - * </file> - * <file name="protractor.js" type="protractor"> - * it('should check controller as', function() { - * var container = element(by.id('ctrl-as-exmpl')); - * expect(container.element(by.model('settings.name')) - * .getAttribute('value')).toBe('John Smith'); - * - * var firstRepeat = - * container.element(by.repeater('contact in settings.contacts').row(0)); - * var secondRepeat = - * container.element(by.repeater('contact in settings.contacts').row(1)); - * - * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) - * .toBe('408 555 1212'); - * - * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) - * .toBe('john.smith@example.org'); - * - * firstRepeat.element(by.linkText('clear')).click(); - * - * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) - * .toBe(''); - * - * container.element(by.linkText('add')).click(); - * - * expect(container.element(by.repeater('contact in settings.contacts').row(2)) - * .element(by.model('contact.value')) - * .getAttribute('value')) - * .toBe('yourname@example.org'); - * }); - * </file> + * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample"> + <file name="index.html"> + <script> + angular.module('inputExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.val = '1'; + }]); + </script> + <style> + .my-input { + -webkit-transition:all linear 0.5s; + transition:all linear 0.5s; + background: transparent; + } + .my-input.ng-invalid { + color:white; + background: red; + } + </style> + <p id="inputDescription"> + Update input to see transitions when valid/invalid. + Integer is a valid value. + </p> + <form name="testForm" ng-controller="ExampleController"> + <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" + aria-describedby="inputDescription" /> + </form> + </file> * </example> * - * This example demonstrates the "attach to `$scope`" style of controller. - * - * <example name="ngController" module="controllerExample"> - * <file name="index.html"> - * <div id="ctrl-exmpl" ng-controller="SettingsController2"> - * Name: <input type="text" ng-model="name"/> - * [ <a href="" ng-click="greet()">greet</a> ]<br/> - * Contact: - * <ul> - * <li ng-repeat="contact in contacts"> - * <select ng-model="contact.type"> - * <option>phone</option> - * <option>email</option> - * </select> - * <input type="text" ng-model="contact.value"/> - * [ <a href="" ng-click="clearContact(contact)">clear</a> - * | <a href="" ng-click="removeContact(contact)">X</a> ] - * </li> - * <li>[ <a href="" ng-click="addContact()">add</a> ]</li> - * </ul> - * </div> - * </file> - * <file name="app.js"> - * angular.module('controllerExample', []) - * .controller('SettingsController2', ['$scope', SettingsController2]); - * - * function SettingsController2($scope) { - * $scope.name = "John Smith"; - * $scope.contacts = [ - * {type:'phone', value:'408 555 1212'}, - * {type:'email', value:'john.smith@example.org'} ]; - * - * $scope.greet = function() { - * alert($scope.name); - * }; - * - * $scope.addContact = function() { - * $scope.contacts.push({type:'email', value:'yourname@example.org'}); - * }; - * - * $scope.removeContact = function(contactToRemove) { - * var index = $scope.contacts.indexOf(contactToRemove); - * $scope.contacts.splice(index, 1); - * }; - * - * $scope.clearContact = function(contact) { - * contact.type = 'phone'; - * contact.value = ''; - * }; - * } - * </file> - * <file name="protractor.js" type="protractor"> - * it('should check controller', function() { - * var container = element(by.id('ctrl-exmpl')); - * - * expect(container.element(by.model('name')) - * .getAttribute('value')).toBe('John Smith'); - * - * var firstRepeat = - * container.element(by.repeater('contact in contacts').row(0)); - * var secondRepeat = - * container.element(by.repeater('contact in contacts').row(1)); + * ## Binding to a getter/setter * - * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) - * .toBe('408 555 1212'); - * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value')) - * .toBe('john.smith@example.org'); + * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a + * function that returns a representation of the model when called with zero arguments, and sets + * the internal state of a model when called with an argument. It's sometimes useful to use this + * for models that have an internal representation that's different from what the model exposes + * to the view. * - * firstRepeat.element(by.linkText('clear')).click(); + * <div class="alert alert-success"> + * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more + * frequently than other parts of your code. + * </div> * - * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value')) - * .toBe(''); + * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that + * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to + * a `<form>`, which will enable this behavior for all `<input>`s within it. See + * {@link ng.directive:ngModelOptions `ngModelOptions`} for more. * - * container.element(by.linkText('add')).click(); + * The following example shows how to use `ngModel` with a getter/setter: * - * expect(container.element(by.repeater('contact in contacts').row(2)) - * .element(by.model('contact.value')) - * .getAttribute('value')) - * .toBe('yourname@example.org'); - * }); - * </file> - *</example> - + * @example + * <example name="ngModel-getter-setter" module="getterSetterExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ getterSetter: true }" /> + </label> + </form> + <pre>user.name = <span ng-bind="user.name()"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('getterSetterExample', []) + .controller('ExampleController', ['$scope', function($scope) { + var _name = 'Brian'; + $scope.user = { + name: function(newName) { + // Note that newName can be undefined for two reasons: + // 1. Because it is called as a getter and thus called with no arguments + // 2. Because the property should actually be set to undefined. This happens e.g. if the + // input is invalid + return arguments.length ? (_name = newName) : _name; + } + }; + }]); + </file> + * </example> */ -var ngControllerDirective = [function() { +var ngModelDirective = ['$rootScope', function($rootScope) { return { restrict: 'A', - scope: true, - controller: '@', - priority: 500 + require: ['ngModel', '^?form', '^?ngModelOptions'], + controller: NgModelController, + // Prelink needs to run before any input directive + // so that we can set the NgModelOptions in NgModelController + // before anyone else uses it. + priority: 1, + compile: function ngModelCompile(element) { + // Setup initial state of the control + element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); + + return { + pre: function ngModelPreLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0], + formCtrl = ctrls[1] || nullFormCtrl; + + modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options); + + // notify others, especially parent forms + formCtrl.$addControl(modelCtrl); + + attr.$observe('name', function(newValue) { + if (modelCtrl.$name !== newValue) { + formCtrl.$$renameControl(modelCtrl, newValue); + } + }); + + scope.$on('$destroy', function() { + formCtrl.$removeControl(modelCtrl); + }); + }, + post: function ngModelPostLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0]; + if (modelCtrl.$options && modelCtrl.$options.updateOn) { + element.on(modelCtrl.$options.updateOn, function(ev) { + modelCtrl.$$debounceViewValueCommit(ev && ev.type); + }); + } + + element.on('blur', function(ev) { + if (modelCtrl.$touched) return; + + if ($rootScope.$$phase) { + scope.$evalAsync(modelCtrl.$setTouched); + } else { + scope.$apply(modelCtrl.$setTouched); + } + }); + } + }; + } }; }]; +var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; + /** * @ngdoc directive - * @name ngCsp + * @name ngModelOptions * - * @element html * @description - * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support. - * - * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps. - * - * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things). - * For Angular to be CSP compatible there are only two things that we need to do differently: - * - * - don't use `Function` constructor to generate optimized value getters - * - don't inject custom stylesheet into the document - * - * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp` - * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will - * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will - * be raised. + * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of + * events that will trigger a model update and/or a debouncing delay so that the actual update only + * takes place when a timer expires; this timer will be reset after another change takes place. * - * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically - * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}). - * To make those directives work in CSP mode, include the `angular-csp.css` manually. + * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might + * be different from the value in the actual model. This means that if you update the model you + * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in + * order to make sure it is synchronized with the model and that any debounced action is canceled. * - * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This - * autodetection however triggers a CSP error to be logged in the console: + * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`} + * method is by making sure the input is placed inside a form that has a `name` attribute. This is + * important because `form` controllers are published to the related scope under the name in their + * `name` attribute. * - * ``` - * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of - * script in the following Content Security Policy directive: "default-src 'self'". Note that - * 'script-src' was not explicitly set, so 'default-src' is used as a fallback. - * ``` + * Any pending changes will take place immediately when an enclosing form is submitted via the + * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` + * to have access to the updated model. * - * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp` - * directive on the root element of the application or on the `angular.js` script tag, whichever - * appears first in the html document. + * `ngModelOptions` has an effect on the element it's declared on and its descendants. * - * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.* + * @param {Object} ngModelOptions options to apply to the current model. Valid keys are: + * - `updateOn`: string specifying which event should the input be bound to. You can set several + * events using an space delimited list. There is a special event called `default` that + * matches the default events belonging of the control. + * - `debounce`: integer value which contains the debounce model update value in milliseconds. A + * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a + * custom value for each event. For example: + * `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"` + * - `allowInvalid`: boolean value which indicates that the model can be set with values that did + * not validate correctly instead of the default behavior of setting the model to undefined. + * - `getterSetter`: boolean value which determines whether or not to treat functions bound to + `ngModel` as getters/setters. + * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for + * `<input type="date">`, `<input type="time">`, ... . It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) + * If not specified, the timezone of the browser will be used. * * @example - * This example shows how to apply the `ngCsp` directive to the `html` tag. - ```html - <!doctype html> - <html ng-app ng-csp> - ... - ... - </html> - ``` - * @example - // Note: the suffix `.csp` in the example name triggers - // csp mode in our http server! - <example name="example.csp" module="cspExample" ng-csp="true"> - <file name="index.html"> - <div ng-controller="MainController as ctrl"> - <div> - <button ng-click="ctrl.inc()" id="inc">Increment</button> - <span id="counter"> - {{ctrl.counter}} - </span> - </div> - <div> - <button ng-click="ctrl.evil()" id="evil">Evil</button> - <span id="evilError"> - {{ctrl.evilError}} - </span> - </div> - </div> - </file> - <file name="script.js"> - angular.module('cspExample', []) - .controller('MainController', function() { - this.counter = 0; - this.inc = function() { - this.counter++; - }; - this.evil = function() { - // jshint evil:true - try { - eval('1+2'); - } catch (e) { - this.evilError = e.message; - } - }; - }); - </file> - <file name="protractor.js" type="protractor"> - var util, webdriver; + The following example shows how to override immediate updates. Changes on the inputs within the + form will update the model only when the control loses focus (blur event). If `escape` key is + pressed while the input field is focused, the value is reset to the value in the current model. - var incBtn = element(by.id('inc')); - var counter = element(by.id('counter')); - var evilBtn = element(by.id('evil')); - var evilError = element(by.id('evilError')); + <example name="ngModelOptions-directive-blur" module="optionsExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ updateOn: 'blur' }" + ng-keyup="cancel($event)" /> + </label><br /> + <label>Other data: + <input type="text" ng-model="user.data" /> + </label><br /> + </form> + <pre>user.name = <span ng-bind="user.name"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('optionsExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.user = { name: 'say', data: '' }; - function getAndClearSevereErrors() { - return browser.manage().logs().get('browser').then(function(browserLog) { - return browserLog.filter(function(logEntry) { - return logEntry.level.value > webdriver.logging.Level.WARNING.value; - }); - }); - } + $scope.cancel = function(e) { + if (e.keyCode == 27) { + $scope.userForm.userName.$rollbackViewValue(); + } + }; + }]); + </file> + <file name="protractor.js" type="protractor"> + var model = element(by.binding('user.name')); + var input = element(by.model('user.name')); + var other = element(by.model('user.data')); - function clearErrors() { - getAndClearSevereErrors(); - } + it('should allow custom events', function() { + input.sendKeys(' hello'); + input.click(); + expect(model.getText()).toEqual('say'); + other.click(); + expect(model.getText()).toEqual('say hello'); + }); - function expectNoErrors() { - getAndClearSevereErrors().then(function(filteredLog) { - expect(filteredLog.length).toEqual(0); - if (filteredLog.length) { - console.log('browser console errors: ' + util.inspect(filteredLog)); - } - }); - } + it('should $rollbackViewValue when model changes', function() { + input.sendKeys(' hello'); + expect(input.getAttribute('value')).toEqual('say hello'); + input.sendKeys(protractor.Key.ESCAPE); + expect(input.getAttribute('value')).toEqual('say'); + other.click(); + expect(model.getText()).toEqual('say'); + }); + </file> + </example> - function expectError(regex) { - getAndClearSevereErrors().then(function(filteredLog) { - var found = false; - filteredLog.forEach(function(log) { - if (log.message.match(regex)) { - found = true; - } - }); - if (!found) { - throw new Error('expected an error that matches ' + regex); - } - }); - } + This one shows how to debounce model changes. Model will be updated only 1 sec after last change. + If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty. - beforeEach(function() { - util = require('util'); - webdriver = require('protractor/node_modules/selenium-webdriver'); - }); + <example name="ngModelOptions-directive-debounce" module="optionsExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ debounce: 1000 }" /> + </label> + <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button> + <br /> + </form> + <pre>user.name = <span ng-bind="user.name"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('optionsExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.user = { name: 'say' }; + }]); + </file> + </example> - // For now, we only test on Chrome, - // as Safari does not load the page with Protractor's injected scripts, - // and Firefox webdriver always disables content security policy (#6358) - if (browser.params.browser !== 'chrome') { - return; - } + This one shows how to bind to getter/setters: - it('should not report errors when the page is loaded', function() { - // clear errors so we are not dependent on previous tests - clearErrors(); - // Need to reload the page as the page is already loaded when - // we come here - browser.driver.getCurrentUrl().then(function(url) { - browser.get(url); - }); - expectNoErrors(); - }); + <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <form name="userForm"> + <label>Name: + <input type="text" name="userName" + ng-model="user.name" + ng-model-options="{ getterSetter: true }" /> + </label> + </form> + <pre>user.name = <span ng-bind="user.name()"></span></pre> + </div> + </file> + <file name="app.js"> + angular.module('getterSetterExample', []) + .controller('ExampleController', ['$scope', function($scope) { + var _name = 'Brian'; + $scope.user = { + name: function(newName) { + // Note that newName can be undefined for two reasons: + // 1. Because it is called as a getter and thus called with no arguments + // 2. Because the property should actually be set to undefined. This happens e.g. if the + // input is invalid + return arguments.length ? (_name = newName) : _name; + } + }; + }]); + </file> + </example> + */ +var ngModelOptionsDirective = function() { + return { + restrict: 'A', + controller: ['$scope', '$attrs', function($scope, $attrs) { + var that = this; + this.$options = copy($scope.$eval($attrs.ngModelOptions)); + // Allow adding/overriding bound events + if (this.$options.updateOn !== undefined) { + this.$options.updateOnDefault = false; + // extract "default" pseudo-event from list of events that can trigger a model update + this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() { + that.$options.updateOnDefault = true; + return ' '; + })); + } else { + this.$options.updateOnDefault = true; + } + }] + }; +}; - it('should evaluate expressions', function() { - expect(counter.getText()).toEqual('0'); - incBtn.click(); - expect(counter.getText()).toEqual('1'); - expectNoErrors(); - }); - it('should throw and report an error when using "eval"', function() { - evilBtn.click(); - expect(evilError.getText()).toMatch(/Content Security Policy/); - expectError(/Content Security Policy/); - }); - </file> - </example> - */ -// ngCsp is not implemented as a proper directive any more, because we need it be processed while we -// bootstrap the system (before $parse is instantiated), for this reason we just have -// the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc +// helper methods +function addSetValidityMethod(context) { + var ctrl = context.ctrl, + $element = context.$element, + classCache = {}, + set = context.set, + unset = context.unset, + parentForm = context.parentForm, + $animate = context.$animate; -/** - * @ngdoc directive - * @name ngClick - * - * @description - * The ngClick directive allows you to specify custom behavior when - * an element is clicked. - * - * @element ANY - * @priority 0 - * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon - * click. ({@link guide/expression#-event- Event object is available as `$event`}) - * - * @example - <example> - <file name="index.html"> - <button ng-click="count = count + 1" ng-init="count=0"> - Increment - </button> - <span> - count: {{count}} - </span> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-click', function() { - expect(element(by.binding('count')).getText()).toMatch('0'); - element(by.css('button')).click(); - expect(element(by.binding('count')).getText()).toMatch('1'); - }); - </file> - </example> - */ -/* - * A collection of directives that allows creation of custom event handlers that are defined as - * angular expressions and are compiled and executed within the current scope. - */ -var ngEventDirectives = {}; + classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS)); -// For events that might fire synchronously during DOM manipulation -// we need to execute their event handlers asynchronously using $evalAsync, -// so that they are not executed in an inconsistent state. -var forceAsyncEvents = { - 'blur': true, - 'focus': true -}; -forEach( - 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '), - function(eventName) { - var directiveName = directiveNormalize('ng-' + eventName); - ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) { - return { - restrict: 'A', - compile: function($element, attr) { - // We expose the powerful $event object on the scope that provides access to the Window, - // etc. that isn't protected by the fast paths in $parse. We explicitly request better - // checks at the cost of speed since event handler expressions are not executed as - // frequently as regular change detection. - var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true); - return function ngEventHandler(scope, element) { - element.on(eventName, function(event) { - var callback = function() { - fn(scope, {$event:event}); - }; - if (forceAsyncEvents[eventName] && $rootScope.$$phase) { - scope.$evalAsync(callback); - } else { - scope.$apply(callback); - } - }); - }; - } - }; - }]; + ctrl.$setValidity = setValidity; + + function setValidity(validationErrorKey, state, controller) { + if (state === undefined) { + createAndSet('$pending', validationErrorKey, controller); + } else { + unsetAndCleanup('$pending', validationErrorKey, controller); + } + if (!isBoolean(state)) { + unset(ctrl.$error, validationErrorKey, controller); + unset(ctrl.$$success, validationErrorKey, controller); + } else { + if (state) { + unset(ctrl.$error, validationErrorKey, controller); + set(ctrl.$$success, validationErrorKey, controller); + } else { + set(ctrl.$error, validationErrorKey, controller); + unset(ctrl.$$success, validationErrorKey, controller); + } + } + if (ctrl.$pending) { + cachedToggleClass(PENDING_CLASS, true); + ctrl.$valid = ctrl.$invalid = undefined; + toggleValidationCss('', null); + } else { + cachedToggleClass(PENDING_CLASS, false); + ctrl.$valid = isObjectEmpty(ctrl.$error); + ctrl.$invalid = !ctrl.$valid; + toggleValidationCss('', ctrl.$valid); + } + + // re-read the state as the set/unset methods could have + // combined state in ctrl.$error[validationError] (used for forms), + // where setting/unsetting only increments/decrements the value, + // and does not replace it. + var combinedState; + if (ctrl.$pending && ctrl.$pending[validationErrorKey]) { + combinedState = undefined; + } else if (ctrl.$error[validationErrorKey]) { + combinedState = false; + } else if (ctrl.$$success[validationErrorKey]) { + combinedState = true; + } else { + combinedState = null; + } + + toggleValidationCss(validationErrorKey, combinedState); + parentForm.$setValidity(validationErrorKey, combinedState, ctrl); + } + + function createAndSet(name, value, controller) { + if (!ctrl[name]) { + ctrl[name] = {}; + } + set(ctrl[name], value, controller); + } + + function unsetAndCleanup(name, value, controller) { + if (ctrl[name]) { + unset(ctrl[name], value, controller); + } + if (isObjectEmpty(ctrl[name])) { + ctrl[name] = undefined; + } + } + + function cachedToggleClass(className, switchValue) { + if (switchValue && !classCache[className]) { + $animate.addClass($element, className); + classCache[className] = true; + } else if (!switchValue && classCache[className]) { + $animate.removeClass($element, className); + classCache[className] = false; + } + } + + function toggleValidationCss(validationErrorKey, isValid) { + validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; + + cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true); + cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false); + } +} + +function isObjectEmpty(obj) { + if (obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; + } + } } -); + return true; +} /** * @ngdoc directive - * @name ngDblclick + * @name ngNonBindable + * @restrict AC + * @priority 1000 * * @description - * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event. + * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current + * DOM element. This is useful if the element contains what appears to be Angular directives and + * bindings but which should be ignored by Angular. This could be the case if you have a site that + * displays snippets of code, for instance. * * @element ANY - * @priority 0 - * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon - * a dblclick. (The Event object is available as `$event`) * * @example - <example> - <file name="index.html"> - <button ng-dblclick="count = count + 1" ng-init="count=0"> - Increment (on double click) - </button> - count: {{count}} - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngMousedown - * - * @description - * The ngMousedown directive allows you to specify custom behavior on mousedown event. - * - * @element ANY - * @priority 0 - * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon - * mousedown. ({@link guide/expression#-event- Event object is available as `$event`}) + * In this example there are two locations where a simple interpolation binding (`{{}}`) is present, + * but the one wrapped in `ngNonBindable` is left alone. * * @example - <example> - <file name="index.html"> - <button ng-mousedown="count = count + 1" ng-init="count=0"> - Increment (on mouse down) - </button> - count: {{count}} - </file> - </example> + <example> + <file name="index.html"> + <div>Normal: {{1 + 2}}</div> + <div ng-non-bindable>Ignored: {{1 + 2}}</div> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-non-bindable', function() { + expect(element(by.binding('1 + 2')).getText()).toContain('3'); + expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/); + }); + </file> + </example> */ +var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); +/* global jqLiteRemove */ -/** - * @ngdoc directive - * @name ngMouseup - * - * @description - * Specify custom behavior on mouseup event. - * - * @element ANY - * @priority 0 - * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon - * mouseup. ({@link guide/expression#-event- Event object is available as `$event`}) - * - * @example - <example> - <file name="index.html"> - <button ng-mouseup="count = count + 1" ng-init="count=0"> - Increment (on mouse up) - </button> - count: {{count}} - </file> - </example> - */ +var ngOptionsMinErr = minErr('ngOptions'); /** * @ngdoc directive - * @name ngMouseover + * @name ngOptions + * @restrict A * * @description - * Specify custom behavior on mouseover event. * - * @element ANY - * @priority 0 - * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon - * mouseover. ({@link guide/expression#-event- Event object is available as `$event`}) + * The `ngOptions` attribute can be used to dynamically generate a list of `<option>` + * elements for the `<select>` element using the array or object obtained by evaluating the + * `ngOptions` comprehension expression. * - * @example - <example> - <file name="index.html"> - <button ng-mouseover="count = count + 1" ng-init="count=0"> - Increment (when mouse is over) - </button> - count: {{count}} - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngMouseenter + * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a + * similar result. However, `ngOptions` provides some benefits such as reducing memory and + * increasing speed by not creating a new scope for each repeated instance, as well as providing + * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the + * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound + * to a non-string value. This is because an option element can only be bound to string values at + * present. * - * @description - * Specify custom behavior on mouseenter event. + * When an item in the `<select>` menu is selected, the array element or object property + * represented by the selected option will be bound to the model identified by the `ngModel` + * directive. * - * @element ANY - * @priority 0 - * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon - * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`}) + * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can + * be nested into the `<select>` element. This element will then represent the `null` or "not selected" + * option. See example below for demonstration. * - * @example - <example> - <file name="index.html"> - <button ng-mouseenter="count = count + 1" ng-init="count=0"> - Increment (when mouse enters) - </button> - count: {{count}} - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngMouseleave + * ## Complex Models (objects or collections) * - * @description - * Specify custom behavior on mouseleave event. + * **Note:** By default, `ngModel` watches the model by reference, not value. This is important when + * binding any input directive to a model that is an object or a collection. * - * @element ANY - * @priority 0 - * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon - * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`}) + * Since this is a common situation for `ngOptions` the directive additionally watches the model using + * `$watchCollection` when the select has the `multiple` attribute or when there is a `track by` clause in + * the options expression. This allows ngOptions to trigger a re-rendering of the options even if the actual + * object/collection has not changed identity but only a property on the object or an item in the collection + * changes. * - * @example - <example> - <file name="index.html"> - <button ng-mouseleave="count = count + 1" ng-init="count=0"> - Increment (when mouse leaves) - </button> - count: {{count}} - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngMousemove + * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection + * if the model is an array). This means that changing a property deeper inside the object/collection that the + * first level will not trigger a re-rendering. * - * @description - * Specify custom behavior on mousemove event. * - * @element ANY - * @priority 0 - * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon - * mousemove. ({@link guide/expression#-event- Event object is available as `$event`}) + * ## `select` **`as`** * - * @example - <example> - <file name="index.html"> - <button ng-mousemove="count = count + 1" ng-init="count=0"> - Increment (when mouse moves) - </button> - count: {{count}} - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngKeydown + * Using `select` **`as`** will bind the result of the `select` expression to the model, but + * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources) + * or property name (for object data sources) of the value within the collection. If a **`track by`** expression + * is used, the result of that expression will be set as the value of the `option` and `select` elements. * - * @description - * Specify custom behavior on keydown event. * - * @element ANY - * @priority 0 - * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon - * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) + * ### `select` **`as`** and **`track by`** * - * @example - <example> - <file name="index.html"> - <input ng-keydown="count = count + 1" ng-init="count=0"> - key down count: {{count}} - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngKeyup + * <div class="alert alert-warning"> + * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together. + * </div> * - * @description - * Specify custom behavior on keyup event. + * Consider the following example: * - * @element ANY - * @priority 0 - * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon - * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) + * ```html + * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"> + * ``` * - * @example - <example> - <file name="index.html"> - <p>Typing in the input box below updates the key count</p> - <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}} - - <p>Typing in the input box below updates the keycode</p> - <input ng-keyup="event=$event"> - <p>event keyCode: {{ event.keyCode }}</p> - <p>event altKey: {{ event.altKey }}</p> - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngKeypress + * ```js + * $scope.values = [{ + * id: 1, + * label: 'aLabel', + * subItem: { name: 'aSubItem' } + * }, { + * id: 2, + * label: 'bLabel', + * subItem: { name: 'bSubItem' } + * }]; * - * @description - * Specify custom behavior on keypress event. + * $scope.selected = { name: 'aSubItem' }; + * ``` * - * @element ANY - * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon - * keypress. ({@link guide/expression#-event- Event object is available as `$event`} - * and can be interrogated for keyCode, altKey, etc.) + * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element + * of the data source (to `item` in this example). To calculate whether an element is selected, we do the + * following: * - * @example - <example> - <file name="index.html"> - <input ng-keypress="count = count + 1" ng-init="count=0"> - key press count: {{count}} - </file> - </example> - */ - - -/** - * @ngdoc directive - * @name ngSubmit + * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]` + * 2. Apply **`track by`** to the already selected value in `ngModel`. + * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected + * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to + * a wrong object, the selected element can't be found, `<select>` is always reset to the "not + * selected" option. * - * @description - * Enables binding angular expressions to onsubmit events. * - * Additionally it prevents the default action (which for form means sending the request to the - * server and reloading the current page), but only if the form does not contain `action`, - * `data-action`, or `x-action` attributes. + * @param {string} ngModel Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required The control is considered valid only if value is entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {comprehension_expression=} ngOptions in one of the following forms: * - * <div class="alert alert-warning"> - * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and - * `ngSubmit` handlers together. See the - * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation} - * for a detailed discussion of when `ngSubmit` may be triggered. - * </div> + * * for array data sources: + * * `label` **`for`** `value` **`in`** `array` + * * `select` **`as`** `label` **`for`** `value` **`in`** `array` + * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` + * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` + * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` + * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` + * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr` + * (for including a filter with `track by`) + * * for object data sources: + * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object` + * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object` + * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object` + * * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object` + * * `select` **`as`** `label` **`group by`** `group` + * **`for` `(`**`key`**`,`** `value`**`) in`** `object` + * * `select` **`as`** `label` **`disable when`** `disable` + * **`for` `(`**`key`**`,`** `value`**`) in`** `object` * - * @element form - * @priority 0 - * @param {expression} ngSubmit {@link guide/expression Expression} to eval. - * ({@link guide/expression#-event- Event object is available as `$event`}) + * Where: + * + * * `array` / `object`: an expression which evaluates to an array / object to iterate over. + * * `value`: local variable which will refer to each item in the `array` or each property value + * of `object` during iteration. + * * `key`: local variable which will refer to a property name in `object` during iteration. + * * `label`: The result of this expression will be the label for `<option>` element. The + * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`). + * * `select`: The result of this expression will be bound to the model of the parent `<select>` + * element. If not specified, `select` expression will default to `value`. + * * `group`: The result of this expression will be used to group options using the `<optgroup>` + * DOM element. + * * `disable`: The result of this expression will be used to disable the rendered `<option>` + * element. Return `true` to disable. + * * `trackexpr`: Used when working with an array of objects. The result of this expression will be + * used to identify the objects in the array. The `trackexpr` will most likely refer to the + * `value` variable (e.g. `value.propertyName`). With this the selection is preserved + * even when the options are recreated (e.g. reloaded from the server). * * @example - <example module="submitExample"> - <file name="index.html"> - <script> - angular.module('submitExample', []) + <example module="selectExample"> + <file name="index.html"> + <script> + angular.module('selectExample', []) .controller('ExampleController', ['$scope', function($scope) { - $scope.list = []; - $scope.text = 'hello'; - $scope.submit = function() { - if ($scope.text) { - $scope.list.push(this.text); - $scope.text = ''; - } - }; + $scope.colors = [ + {name:'black', shade:'dark'}, + {name:'white', shade:'light', notAnOption: true}, + {name:'red', shade:'dark'}, + {name:'blue', shade:'dark', notAnOption: true}, + {name:'yellow', shade:'light', notAnOption: false} + ]; + $scope.myColor = $scope.colors[2]; // red }]); - </script> - <form ng-submit="submit()" ng-controller="ExampleController"> - Enter text and hit enter: - <input type="text" ng-model="text" name="text" /> - <input type="submit" id="submit" value="Submit" /> - <pre>list={{list}}</pre> - </form> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-submit', function() { - expect(element(by.binding('list')).getText()).toBe('list=[]'); - element(by.css('#submit')).click(); - expect(element(by.binding('list')).getText()).toContain('hello'); - expect(element(by.model('text')).getAttribute('value')).toBe(''); - }); - it('should ignore empty strings', function() { - expect(element(by.binding('list')).getText()).toBe('list=[]'); - element(by.css('#submit')).click(); - element(by.css('#submit')).click(); - expect(element(by.binding('list')).getText()).toContain('hello'); - }); - </file> - </example> + </script> + <div ng-controller="ExampleController"> + <ul> + <li ng-repeat="color in colors"> + <label>Name: <input ng-model="color.name"></label> + <label><input type="checkbox" ng-model="color.notAnOption"> Disabled?</label> + <button ng-click="colors.splice($index, 1)" aria-label="Remove">X</button> + </li> + <li> + <button ng-click="colors.push({})">add</button> + </li> + </ul> + <hr/> + <label>Color (null not allowed): + <select ng-model="myColor" ng-options="color.name for color in colors"></select> + </label><br/> + <label>Color (null allowed): + <span class="nullable"> + <select ng-model="myColor" ng-options="color.name for color in colors"> + <option value="">-- choose color --</option> + </select> + </span></label><br/> + + <label>Color grouped by shade: + <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors"> + </select> + </label><br/> + + <label>Color grouped by shade, with some disabled: + <select ng-model="myColor" + ng-options="color.name group by color.shade disable when color.notAnOption for color in colors"> + </select> + </label><br/> + + + + Select <button ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</button>. + <br/> + <hr/> + Currently selected: {{ {selected_color:myColor} }} + <div style="border:solid 1px black; height:20px" + ng-style="{'background-color':myColor.name}"> + </div> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should check ng-options', function() { + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red'); + element.all(by.model('myColor')).first().click(); + element.all(by.css('select[ng-model="myColor"] option')).first().click(); + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black'); + element(by.css('.nullable select[ng-model="myColor"]')).click(); + element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click(); + expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null'); + }); + </file> + </example> */ -/** - * @ngdoc directive - * @name ngFocus - * - * @description - * Specify custom behavior on focus event. - * - * Note: As the `focus` event is executed synchronously when calling `input.focus()` - * AngularJS executes the expression using `scope.$evalAsync` if the event is fired - * during an `$apply` to ensure a consistent state. - * - * @element window, input, select, textarea, a - * @priority 0 - * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon - * focus. ({@link guide/expression#-event- Event object is available as `$event`}) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ +// jshint maxlen: false +// //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999 +var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/; + // 1: value expression (valueFn) + // 2: label expression (displayFn) + // 3: group by expression (groupByFn) + // 4: disable when expression (disableWhenFn) + // 5: array item variable name + // 6: object item key variable name + // 7: object item value variable name + // 8: collection expression + // 9: track by expression +// jshint maxlen: 100 + + +var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { + + function parseOptionsExpression(optionsExp, selectElement, scope) { + + var match = optionsExp.match(NG_OPTIONS_REGEXP); + if (!(match)) { + throw ngOptionsMinErr('iexp', + "Expected expression in form of " + + "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + + " but got '{0}'. Element: {1}", + optionsExp, startingTag(selectElement)); + } + + // Extract the parts from the ngOptions expression + + // The variable name for the value of the item in the collection + var valueName = match[5] || match[7]; + // The variable name for the key of the item in the collection + var keyName = match[6]; + + // An expression that generates the viewValue for an option if there is a label expression + var selectAs = / as /.test(match[0]) && match[1]; + // An expression that is used to track the id of each object in the options collection + var trackBy = match[9]; + // An expression that generates the viewValue for an option if there is no label expression + var valueFn = $parse(match[2] ? match[1] : valueName); + var selectAsFn = selectAs && $parse(selectAs); + var viewValueFn = selectAsFn || valueFn; + var trackByFn = trackBy && $parse(trackBy); + + // Get the value by which we are going to track the option + // if we have a trackFn then use that (passing scope and locals) + // otherwise just hash the given viewValue + var getTrackByValueFn = trackBy ? + function(value, locals) { return trackByFn(scope, locals); } : + function getHashOfValue(value) { return hashKey(value); }; + var getTrackByValue = function(value, key) { + return getTrackByValueFn(value, getLocals(value, key)); + }; + + var displayFn = $parse(match[2] || match[1]); + var groupByFn = $parse(match[3] || ''); + var disableWhenFn = $parse(match[4] || ''); + var valuesFn = $parse(match[8]); + + var locals = {}; + var getLocals = keyName ? function(value, key) { + locals[keyName] = key; + locals[valueName] = value; + return locals; + } : function(value) { + locals[valueName] = value; + return locals; + }; + + + function Option(selectValue, viewValue, label, group, disabled) { + this.selectValue = selectValue; + this.viewValue = viewValue; + this.label = label; + this.group = group; + this.disabled = disabled; + } + + function getOptionValuesKeys(optionValues) { + var optionValuesKeys; + + if (!keyName && isArrayLike(optionValues)) { + optionValuesKeys = optionValues; + } else { + // if object, extract keys, in enumeration order, unsorted + optionValuesKeys = []; + for (var itemKey in optionValues) { + if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') { + optionValuesKeys.push(itemKey); + } + } + } + return optionValuesKeys; + } + + return { + trackBy: trackBy, + getTrackByValue: getTrackByValue, + getWatchables: $parse(valuesFn, function(optionValues) { + // Create a collection of things that we would like to watch (watchedArray) + // so that they can all be watched using a single $watchCollection + // that only runs the handler once if anything changes + var watchedArray = []; + optionValues = optionValues || []; + + var optionValuesKeys = getOptionValuesKeys(optionValues); + var optionValuesLength = optionValuesKeys.length; + for (var index = 0; index < optionValuesLength; index++) { + var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index]; + var value = optionValues[key]; + + var locals = getLocals(optionValues[key], key); + var selectValue = getTrackByValueFn(optionValues[key], locals); + watchedArray.push(selectValue); + + // Only need to watch the displayFn if there is a specific label expression + if (match[2] || match[1]) { + var label = displayFn(scope, locals); + watchedArray.push(label); + } + + // Only need to watch the disableWhenFn if there is a specific disable expression + if (match[4]) { + var disableWhen = disableWhenFn(scope, locals); + watchedArray.push(disableWhen); + } + } + return watchedArray; + }), + + getOptions: function() { + + var optionItems = []; + var selectValueMap = {}; + + // The option values were already computed in the `getWatchables` fn, + // which must have been called to trigger `getOptions` + var optionValues = valuesFn(scope) || []; + var optionValuesKeys = getOptionValuesKeys(optionValues); + var optionValuesLength = optionValuesKeys.length; + + for (var index = 0; index < optionValuesLength; index++) { + var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index]; + var value = optionValues[key]; + var locals = getLocals(value, key); + var viewValue = viewValueFn(scope, locals); + var selectValue = getTrackByValueFn(viewValue, locals); + var label = displayFn(scope, locals); + var group = groupByFn(scope, locals); + var disabled = disableWhenFn(scope, locals); + var optionItem = new Option(selectValue, viewValue, label, group, disabled); + + optionItems.push(optionItem); + selectValueMap[selectValue] = optionItem; + } + + return { + items: optionItems, + selectValueMap: selectValueMap, + getOptionFromViewValue: function(value) { + return selectValueMap[getTrackByValue(value)]; + }, + getViewValueFromOption: function(option) { + // If the viewValue could be an object that may be mutated by the application, + // we need to make a copy and not return the reference to the value on the option. + return trackBy ? angular.copy(option.viewValue) : option.viewValue; + } + }; + } + }; + } + + + // we can't just jqLite('<option>') since jqLite is not smart enough + // to create it in <select> and IE barfs otherwise. + var optionTemplate = document.createElement('option'), + optGroupTemplate = document.createElement('optgroup'); + + return { + restrict: 'A', + terminal: true, + require: ['select', '?ngModel'], + link: function(scope, selectElement, attr, ctrls) { + + // if ngModel is not defined, we don't need to do anything + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; + + var selectCtrl = ctrls[0]; + var multiple = attr.multiple; + + // The emptyOption allows the application developer to provide their own custom "empty" + // option when the viewValue does not match any of the option values. + var emptyOption; + for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) { + if (children[i].value === '') { + emptyOption = children.eq(i); + break; + } + } + + var providedEmptyOption = !!emptyOption; + + var unknownOption = jqLite(optionTemplate.cloneNode(false)); + unknownOption.val('?'); + + var options; + var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope); + + + var renderEmptyOption = function() { + if (!providedEmptyOption) { + selectElement.prepend(emptyOption); + } + selectElement.val(''); + emptyOption.prop('selected', true); // needed for IE + emptyOption.attr('selected', true); + }; + + var removeEmptyOption = function() { + if (!providedEmptyOption) { + emptyOption.remove(); + } + }; + + + var renderUnknownOption = function() { + selectElement.prepend(unknownOption); + selectElement.val('?'); + unknownOption.prop('selected', true); // needed for IE + unknownOption.attr('selected', true); + }; + + var removeUnknownOption = function() { + unknownOption.remove(); + }; + + + // Update the controller methods for multiple selectable options + if (!multiple) { + + selectCtrl.writeValue = function writeNgOptionsValue(value) { + var option = options.getOptionFromViewValue(value); + + if (option && !option.disabled) { + if (selectElement[0].value !== option.selectValue) { + removeUnknownOption(); + removeEmptyOption(); + + selectElement[0].value = option.selectValue; + option.element.selected = true; + option.element.setAttribute('selected', 'selected'); + } + } else { + if (value === null || providedEmptyOption) { + removeUnknownOption(); + renderEmptyOption(); + } else { + removeEmptyOption(); + renderUnknownOption(); + } + } + }; + + selectCtrl.readValue = function readNgOptionsValue() { + + var selectedOption = options.selectValueMap[selectElement.val()]; + + if (selectedOption && !selectedOption.disabled) { + removeEmptyOption(); + removeUnknownOption(); + return options.getViewValueFromOption(selectedOption); + } + return null; + }; + + // If we are using `track by` then we must watch the tracked value on the model + // since ngModel only watches for object identity change + if (ngOptions.trackBy) { + scope.$watch( + function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); }, + function() { ngModelCtrl.$render(); } + ); + } + + } else { + + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; + + + selectCtrl.writeValue = function writeNgOptionsMultiple(value) { + options.items.forEach(function(option) { + option.element.selected = false; + }); + + if (value) { + value.forEach(function(item) { + var option = options.getOptionFromViewValue(item); + if (option && !option.disabled) option.element.selected = true; + }); + } + }; + -/** - * @ngdoc directive - * @name ngBlur - * - * @description - * Specify custom behavior on blur event. - * - * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when - * an element has lost focus. - * - * Note: As the `blur` event is executed synchronously also during DOM manipulations - * (e.g. removing a focussed input), - * AngularJS executes the expression using `scope.$evalAsync` if the event is fired - * during an `$apply` to ensure a consistent state. - * - * @element window, input, select, textarea, a - * @priority 0 - * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon - * blur. ({@link guide/expression#-event- Event object is available as `$event`}) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ + selectCtrl.readValue = function readNgOptionsMultiple() { + var selectedValues = selectElement.val() || [], + selections = []; -/** - * @ngdoc directive - * @name ngCopy - * - * @description - * Specify custom behavior on copy event. - * - * @element window, input, select, textarea, a - * @priority 0 - * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon - * copy. ({@link guide/expression#-event- Event object is available as `$event`}) - * - * @example - <example> - <file name="index.html"> - <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value"> - copied: {{copied}} - </file> - </example> - */ + forEach(selectedValues, function(value) { + var option = options.selectValueMap[value]; + if (!option.disabled) selections.push(options.getViewValueFromOption(option)); + }); -/** - * @ngdoc directive - * @name ngCut - * - * @description - * Specify custom behavior on cut event. - * - * @element window, input, select, textarea, a - * @priority 0 - * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon - * cut. ({@link guide/expression#-event- Event object is available as `$event`}) - * - * @example - <example> - <file name="index.html"> - <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value"> - cut: {{cut}} - </file> - </example> - */ + return selections; + }; -/** - * @ngdoc directive - * @name ngPaste - * - * @description - * Specify custom behavior on paste event. - * - * @element window, input, select, textarea, a - * @priority 0 - * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon - * paste. ({@link guide/expression#-event- Event object is available as `$event`}) - * - * @example - <example> - <file name="index.html"> - <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'> - pasted: {{paste}} - </file> - </example> - */ + // If we are using `track by` then we must watch these tracked values on the model + // since ngModel only watches for object identity change + if (ngOptions.trackBy) { -/** - * @ngdoc directive - * @name ngIf - * @restrict A - * - * @description - * The `ngIf` directive removes or recreates a portion of the DOM tree based on an - * {expression}. If the expression assigned to `ngIf` evaluates to a false - * value then the element is removed from the DOM, otherwise a clone of the - * element is reinserted into the DOM. - * - * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the - * element in the DOM rather than changing its visibility via the `display` css property. A common - * case when this difference is significant is when using css selectors that rely on an element's - * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes. - * - * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope - * is created when the element is restored. The scope created within `ngIf` inherits from - * its parent scope using - * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance). - * An important implication of this is if `ngModel` is used within `ngIf` to bind to - * a javascript primitive defined in the parent scope. In this case any modifications made to the - * variable within the child scope will override (hide) the value in the parent scope. - * - * Also, `ngIf` recreates elements using their compiled state. An example of this behavior - * is if an element's class attribute is directly modified after it's compiled, using something like - * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element - * the added class will be lost because the original compiled state is used to regenerate the element. - * - * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter` - * and `leave` effects. - * - * @animations - * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container - * leave - happens just before the `ngIf` contents are removed from the DOM - * - * @element ANY - * @scope - * @priority 600 - * @param {expression} ngIf If the {@link guide/expression expression} is falsy then - * the element is removed from the DOM tree. If it is truthy a copy of the compiled - * element is added to the DOM tree. - * - * @example - <example module="ngAnimate" deps="angular-animate.js" animations="true"> - <file name="index.html"> - Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/> - Show when checked: - <span ng-if="checked" class="animate-if"> - This is removed when the checkbox is unchecked. - </span> - </file> - <file name="animations.css"> - .animate-if { - background:white; - border:1px solid black; - padding:10px; + scope.$watchCollection(function() { + if (isArray(ngModelCtrl.$viewValue)) { + return ngModelCtrl.$viewValue.map(function(value) { + return ngOptions.getTrackByValue(value); + }); + } + }, function() { + ngModelCtrl.$render(); + }); + + } } - .animate-if.ng-enter, .animate-if.ng-leave { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + + if (providedEmptyOption) { + + // we need to remove it before calling selectElement.empty() because otherwise IE will + // remove the label from the element. wtf? + emptyOption.remove(); + + // compile the element since there might be bindings in it + $compile(emptyOption)(scope); + + // remove the class, which is added automatically because we recompile the element and it + // becomes the compilation root + emptyOption.removeClass('ng-scope'); + } else { + emptyOption = jqLite(optionTemplate.cloneNode(false)); } - .animate-if.ng-enter, - .animate-if.ng-leave.ng-leave-active { - opacity:0; + // We need to do this here to ensure that the options object is defined + // when we first hit it in writeNgOptionsValue + updateOptions(); + + // We will re-render the option elements if the option values or labels change + scope.$watchCollection(ngOptions.getWatchables, updateOptions); + + // ------------------------------------------------------------------ // + + + function updateOptionElement(option, element) { + option.element = element; + element.disabled = option.disabled; + if (option.value !== element.value) element.value = option.selectValue; + if (option.label !== element.label) { + element.label = option.label; + element.textContent = option.label; + } } - .animate-if.ng-leave, - .animate-if.ng-enter.ng-enter-active { - opacity:1; + function addOrReuseElement(parent, current, type, templateElement) { + var element; + // Check whether we can reuse the next element + if (current && lowercase(current.nodeName) === type) { + // The next element is the right type so reuse it + element = current; + } else { + // The next element is not the right type so create a new one + element = templateElement.cloneNode(false); + if (!current) { + // There are no more elements so just append it to the select + parent.appendChild(element); + } else { + // The next element is not a group so insert the new one + parent.insertBefore(element, current); + } + } + return element; } - </file> - </example> - */ -var ngIfDirective = ['$animate', function($animate) { - return { - multiElement: true, - transclude: 'element', - priority: 600, - terminal: true, - restrict: 'A', - $$tlb: true, - link: function($scope, $element, $attr, ctrl, $transclude) { - var block, childScope, previousElements; - $scope.$watch($attr.ngIf, function ngIfWatchAction(value) { - if (value) { - if (!childScope) { - $transclude(function(clone, newScope) { - childScope = newScope; - clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' '); - // Note: We only need the first/last node of the cloned nodes. - // However, we need to keep the reference to the jqlite wrapper as it might be changed later - // by a directive with templateUrl when its template arrives. - block = { - clone: clone - }; - $animate.enter(clone, $element.parent(), $element); - }); + + function removeExcessElements(current) { + var next; + while (current) { + next = current.nextSibling; + jqLiteRemove(current); + current = next; + } + } + + + function skipEmptyAndUnknownOptions(current) { + var emptyOption_ = emptyOption && emptyOption[0]; + var unknownOption_ = unknownOption && unknownOption[0]; + + if (emptyOption_ || unknownOption_) { + while (current && + (current === emptyOption_ || + current === unknownOption_)) { + current = current.nextSibling; + } + } + return current; + } + + + function updateOptions() { + + var previousValue = options && selectCtrl.readValue(); + + options = ngOptions.getOptions(); + + var groupMap = {}; + var currentElement = selectElement[0].firstChild; + + // Ensure that the empty option is always there if it was explicitly provided + if (providedEmptyOption) { + selectElement.prepend(emptyOption); + } + + currentElement = skipEmptyAndUnknownOptions(currentElement); + + options.items.forEach(function updateOption(option) { + var group; + var groupElement; + var optionElement; + + if (option.group) { + + // This option is to live in a group + // See if we have already created this group + group = groupMap[option.group]; + + if (!group) { + + // We have not already created this group + groupElement = addOrReuseElement(selectElement[0], + currentElement, + 'optgroup', + optGroupTemplate); + // Move to the next element + currentElement = groupElement.nextSibling; + + // Update the label on the group element + groupElement.label = option.group; + + // Store it for use later + group = groupMap[option.group] = { + groupElement: groupElement, + currentOptionElement: groupElement.firstChild + }; + } + + // So now we have a group for this option we add the option to the group + optionElement = addOrReuseElement(group.groupElement, + group.currentOptionElement, + 'option', + optionTemplate); + updateOptionElement(option, optionElement); + // Move to the next element + group.currentOptionElement = optionElement.nextSibling; + } else { - if (previousElements) { - previousElements.remove(); - previousElements = null; - } - if (childScope) { - childScope.$destroy(); - childScope = null; - } - if (block) { - previousElements = getBlockNodes(block.clone); - $animate.leave(previousElements).then(function() { - previousElements = null; - }); - block = null; - } + + // This option is not in a group + optionElement = addOrReuseElement(selectElement[0], + currentElement, + 'option', + optionTemplate); + updateOptionElement(option, optionElement); + // Move to the next element + currentElement = optionElement.nextSibling; } }); + + + // Now remove all excess options and group + Object.keys(groupMap).forEach(function(key) { + removeExcessElements(groupMap[key].currentOptionElement); + }); + removeExcessElements(currentElement); + + ngModelCtrl.$render(); + + // Check to see if the value has changed due to the update to the options + if (!ngModelCtrl.$isEmpty(previousValue)) { + var nextValue = selectCtrl.readValue(); + if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) { + ngModelCtrl.$setViewValue(nextValue); + ngModelCtrl.$render(); + } + } + + } + } }; }]; /** * @ngdoc directive - * @name ngInclude - * @restrict ECA + * @name ngPluralize + * @restrict EA * * @description - * Fetches, compiles and includes an external HTML fragment. + * `ngPluralize` is a directive that displays messages according to en-US localization rules. + * These rules are bundled with angular.js, but can be overridden + * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive + * by specifying the mappings between + * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) + * and the strings to be displayed. * - * By default, the template URL is restricted to the same domain and protocol as the - * application document. This is done by calling {@link $sce#getTrustedResourceUrl - * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols - * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or - * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link - * ng.$sce Strict Contextual Escaping}. + * # Plural categories and explicit number rules + * There are two + * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) + * in Angular's default en-US locale: "one" and "other". * - * In addition, the browser's - * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) - * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) - * policy may further restrict whether the template is successfully loaded. - * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://` - * access on some browsers. + * While a plural category may match many numbers (for example, in en-US locale, "other" can match + * any number that is not 1), an explicit number rule can only match one number. For example, the + * explicit number rule for "3" matches the number 3. There are examples of plural categories + * and explicit number rules throughout the rest of this documentation. * - * @animations - * enter - animation is used to bring new content into the browser. - * leave - animation is used to animate existing content away. + * # Configuring ngPluralize + * You configure ngPluralize by providing 2 attributes: `count` and `when`. + * You can also provide an optional attribute, `offset`. * - * The enter and leave animation occur concurrently. + * The value of the `count` attribute can be either a string or an {@link guide/expression + * Angular expression}; these are evaluated on the current scope for its bound value. * - * @scope - * @priority 400 + * The `when` attribute specifies the mappings between plural categories and the actual + * string to be displayed. The value of the attribute should be a JSON object. * - * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant, - * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`. - * @param {string=} onload Expression to evaluate when a new partial is loaded. + * The following example shows how to configure ngPluralize: * - * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll - * $anchorScroll} to scroll the viewport after the content is loaded. + * ```html + * <ng-pluralize count="personCount" + when="{'0': 'Nobody is viewing.', + * 'one': '1 person is viewing.', + * 'other': '{} people are viewing.'}"> + * </ng-pluralize> + *``` * - * - If the attribute is not set, disable scrolling. - * - If the attribute is set without value, enable scrolling. - * - Otherwise enable scrolling only if the expression evaluates to truthy value. + * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not + * specify this rule, 0 would be matched to the "other" category and "0 people are viewing" + * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for + * other numbers, for example 12, so that instead of showing "12 people are viewing", you can + * show "a dozen people are viewing". + * + * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted + * into pluralized strings. In the previous example, Angular will replace `{}` with + * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder + * for <span ng-non-bindable>{{numberExpression}}</span>. + * + * If no rule is defined for a category, then an empty string is displayed and a warning is generated. + * Note that some locales define more categories than `one` and `other`. For example, fr-fr defines `few` and `many`. + * + * # Configuring ngPluralize with offset + * The `offset` attribute allows further customization of pluralized text, which can result in + * a better user experience. For example, instead of the message "4 people are viewing this document", + * you might display "John, Kate and 2 others are viewing this document". + * The offset attribute allows you to offset a number by any desired value. + * Let's take a look at an example: + * + * ```html + * <ng-pluralize count="personCount" offset=2 + * when="{'0': 'Nobody is viewing.', + * '1': '{{person1}} is viewing.', + * '2': '{{person1}} and {{person2}} are viewing.', + * 'one': '{{person1}}, {{person2}} and one other person are viewing.', + * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}"> + * </ng-pluralize> + * ``` + * + * Notice that we are still using two plural categories(one, other), but we added + * three explicit number rules 0, 1 and 2. + * When one person, perhaps John, views the document, "John is viewing" will be shown. + * When three people view the document, no explicit number rule is found, so + * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category. + * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing" + * is shown. + * + * Note that when you specify offsets, you must provide explicit number rules for + * numbers from 0 up to and including the offset. If you use an offset of 3, for example, + * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for + * plural categories "one" and "other". + * + * @param {string|expression} count The variable to be bound to. + * @param {string} when The mapping between plural category to its corresponding strings. + * @param {number=} offset Offset to deduct from the total number. * * @example - <example module="includeExample" deps="angular-animate.js" animations="true"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <select ng-model="template" ng-options="t.name for t in templates"> - <option value="">(blank)</option> - </select> - url of the template: <code>{{template.url}}</code> - <hr/> - <div class="slide-animate-container"> - <div class="slide-animate" ng-include="template.url"></div> - </div> - </div> - </file> - <file name="script.js"> - angular.module('includeExample', ['ngAnimate']) - .controller('ExampleController', ['$scope', function($scope) { - $scope.templates = - [ { name: 'template1.html', url: 'template1.html'}, - { name: 'template2.html', url: 'template2.html'} ]; - $scope.template = $scope.templates[0]; - }]); - </file> - <file name="template1.html"> - Content of template1.html - </file> - <file name="template2.html"> - Content of template2.html - </file> - <file name="animations.css"> - .slide-animate-container { - position:relative; - background:white; - border:1px solid black; - height:40px; - overflow:hidden; - } - - .slide-animate { - padding:10px; - } - - .slide-animate.ng-enter, .slide-animate.ng-leave { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - - position:absolute; - top:0; - left:0; - right:0; - bottom:0; - display:block; - padding:10px; - } + <example module="pluralizeExample"> + <file name="index.html"> + <script> + angular.module('pluralizeExample', []) + .controller('ExampleController', ['$scope', function($scope) { + $scope.person1 = 'Igor'; + $scope.person2 = 'Misko'; + $scope.personCount = 1; + }]); + </script> + <div ng-controller="ExampleController"> + <label>Person 1:<input type="text" ng-model="person1" value="Igor" /></label><br/> + <label>Person 2:<input type="text" ng-model="person2" value="Misko" /></label><br/> + <label>Number of People:<input type="text" ng-model="personCount" value="1" /></label><br/> - .slide-animate.ng-enter { - top:-50px; - } - .slide-animate.ng-enter.ng-enter-active { - top:0; - } + <!--- Example with simple pluralization rules for en locale ---> + Without Offset: + <ng-pluralize count="personCount" + when="{'0': 'Nobody is viewing.', + 'one': '1 person is viewing.', + 'other': '{} people are viewing.'}"> + </ng-pluralize><br> - .slide-animate.ng-leave { - top:0; - } - .slide-animate.ng-leave.ng-leave-active { - top:50px; - } - </file> - <file name="protractor.js" type="protractor"> - var templateSelect = element(by.model('template')); - var includeElem = element(by.css('[ng-include]')); + <!--- Example with offset ---> + With Offset(2): + <ng-pluralize count="personCount" offset=2 + when="{'0': 'Nobody is viewing.', + '1': '{{person1}} is viewing.', + '2': '{{person1}} and {{person2}} are viewing.', + 'one': '{{person1}}, {{person2}} and one other person are viewing.', + 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}"> + </ng-pluralize> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should show correct pluralized string', function() { + var withoutOffset = element.all(by.css('ng-pluralize')).get(0); + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var countInput = element(by.model('personCount')); - it('should load template1.html', function() { - expect(includeElem.getText()).toMatch(/Content of template1.html/); - }); + expect(withoutOffset.getText()).toEqual('1 person is viewing.'); + expect(withOffset.getText()).toEqual('Igor is viewing.'); - it('should load template2.html', function() { - if (browser.params.browser == 'firefox') { - // Firefox can't handle using selects - // See https://github.com/angular/protractor/issues/480 - return; - } - templateSelect.click(); - templateSelect.all(by.css('option')).get(2).click(); - expect(includeElem.getText()).toMatch(/Content of template2.html/); - }); + countInput.clear(); + countInput.sendKeys('0'); - it('should change to blank', function() { - if (browser.params.browser == 'firefox') { - // Firefox can't handle using selects - return; - } - templateSelect.click(); - templateSelect.all(by.css('option')).get(0).click(); - expect(includeElem.isPresent()).toBe(false); - }); - </file> - </example> - */ + expect(withoutOffset.getText()).toEqual('Nobody is viewing.'); + expect(withOffset.getText()).toEqual('Nobody is viewing.'); + countInput.clear(); + countInput.sendKeys('2'); -/** - * @ngdoc event - * @name ngInclude#$includeContentRequested - * @eventType emit on the scope ngInclude was declared in - * @description - * Emitted every time the ngInclude content is requested. - * - * @param {Object} angularEvent Synthetic event object. - * @param {String} src URL of content to load. - */ + expect(withoutOffset.getText()).toEqual('2 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor and Misko are viewing.'); + countInput.clear(); + countInput.sendKeys('3'); -/** - * @ngdoc event - * @name ngInclude#$includeContentLoaded - * @eventType emit on the current ngInclude scope - * @description - * Emitted every time the ngInclude content is reloaded. - * - * @param {Object} angularEvent Synthetic event object. - * @param {String} src URL of content to load. - */ + expect(withoutOffset.getText()).toEqual('3 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.'); + countInput.clear(); + countInput.sendKeys('4'); -/** - * @ngdoc event - * @name ngInclude#$includeContentError - * @eventType emit on the scope ngInclude was declared in - * @description - * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299) - * - * @param {Object} angularEvent Synthetic event object. - * @param {String} src URL of content to load. + expect(withoutOffset.getText()).toEqual('4 people are viewing.'); + expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.'); + }); + it('should show data-bound names', function() { + var withOffset = element.all(by.css('ng-pluralize')).get(1); + var personCount = element(by.model('personCount')); + var person1 = element(by.model('person1')); + var person2 = element(by.model('person2')); + personCount.clear(); + personCount.sendKeys('4'); + person1.clear(); + person1.sendKeys('Di'); + person2.clear(); + person2.sendKeys('Vojta'); + expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.'); + }); + </file> + </example> */ -var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce', - function($templateRequest, $anchorScroll, $animate, $sce) { - return { - restrict: 'ECA', - priority: 400, - terminal: true, - transclude: 'element', - controller: angular.noop, - compile: function(element, attr) { - var srcExp = attr.ngInclude || attr.src, - onloadExp = attr.onload || '', - autoScrollExp = attr.autoscroll; - - return function(scope, $element, $attr, ctrl, $transclude) { - var changeCounter = 0, - currentScope, - previousElement, - currentElement; +var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) { + var BRACE = /{}/g, + IS_WHEN = /^when(Minus)?(.+)$/; - var cleanupLastIncludeContent = function() { - if (previousElement) { - previousElement.remove(); - previousElement = null; - } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; - } - if (currentElement) { - $animate.leave(currentElement).then(function() { - previousElement = null; - }); - previousElement = currentElement; - currentElement = null; - } - }; + return { + link: function(scope, element, attr) { + var numberExp = attr.count, + whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs + offset = attr.offset || 0, + whens = scope.$eval(whenExp) || {}, + whensExpFns = {}, + startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol, + watchRemover = angular.noop, + lastCount; - scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) { - var afterAnimation = function() { - if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { - $anchorScroll(); - } - }; - var thisChangeId = ++changeCounter; + forEach(attr, function(expression, attributeName) { + var tmpMatch = IS_WHEN.exec(attributeName); + if (tmpMatch) { + var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]); + whens[whenKey] = element.attr(attr.$attr[attributeName]); + } + }); + forEach(whens, function(expression, key) { + whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement)); - if (src) { - //set the 2nd param to true to ignore the template request error so that the inner - //contents and scope can be cleaned up. - $templateRequest(src, true).then(function(response) { - if (thisChangeId !== changeCounter) return; - var newScope = scope.$new(); - ctrl.template = response; + }); - // Note: This will also link all children of ng-include that were contained in the original - // html. If that content contains controllers, ... they could pollute/change the scope. - // However, using ng-include on an element with additional content does not make sense... - // Note: We can't remove them in the cloneAttchFn of $transclude as that - // function is called before linking the content, which would apply child - // directives to non existing elements. - var clone = $transclude(newScope, function(clone) { - cleanupLastIncludeContent(); - $animate.enter(clone, null, $element).then(afterAnimation); - }); + scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) { + var count = parseFloat(newVal); + var countIsNaN = isNaN(count); - currentScope = newScope; - currentElement = clone; + if (!countIsNaN && !(count in whens)) { + // If an explicit number rule such as 1, 2, 3... is defined, just use it. + // Otherwise, check it against pluralization rules in $locale service. + count = $locale.pluralCat(count - offset); + } - currentScope.$emit('$includeContentLoaded', src); - scope.$eval(onloadExp); - }, function() { - if (thisChangeId === changeCounter) { - cleanupLastIncludeContent(); - scope.$emit('$includeContentError', src); - } - }); - scope.$emit('$includeContentRequested', src); + // If both `count` and `lastCount` are NaN, we don't need to re-register a watch. + // In JS `NaN !== NaN`, so we have to exlicitly check. + if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) { + watchRemover(); + var whenExpFn = whensExpFns[count]; + if (isUndefined(whenExpFn)) { + if (newVal != null) { + $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp); + } + watchRemover = noop; + updateElementText(); } else { - cleanupLastIncludeContent(); - ctrl.template = null; + watchRemover = scope.$watch(whenExpFn, updateElementText); } - }); - }; - } - }; -}]; - -// This directive is called during the $transclude call of the first `ngInclude` directive. -// It will replace and compile the content of the element with the loaded template. -// We need this directive so that the element content is already filled when -// the link function of another directive on the same element as ngInclude -// is called. -var ngIncludeFillContentDirective = ['$compile', - function($compile) { - return { - restrict: 'ECA', - priority: -400, - require: 'ngInclude', - link: function(scope, $element, $attr, ctrl) { - if (/SVG/.test($element[0].toString())) { - // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not - // support innerHTML, so detect this here and try to generate the contents - // specially. - $element.empty(); - $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope, - function namespaceAdaptedClone(clone) { - $element.append(clone); - }, {futureParentElement: $element}); - return; + lastCount = count; } + }); - $element.html(ctrl.template); - $compile($element.contents())(scope); + function updateElementText(newText) { + element.text(newText || ''); } - }; - }]; + } + }; +}]; /** * @ngdoc directive - * @name ngInit - * @restrict AC + * @name ngRepeat + * @multiElement * * @description - * The `ngInit` directive allows you to evaluate an expression in the - * current scope. + * The `ngRepeat` directive instantiates a template once per item from a collection. Each template + * instance gets its own scope, where the given loop variable is set to the current collection item, + * and `$index` is set to the item index or key. * - * <div class="alert alert-error"> - * The only appropriate use of `ngInit` is for aliasing special properties of - * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you - * should use {@link guide/controller controllers} rather than `ngInit` - * to initialize values on a scope. - * </div> - * <div class="alert alert-warning"> - * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make - * sure you have parenthesis for correct precedence: - * <pre class="prettyprint"> - * `<div ng-init="test1 = (data | orderBy:'name')"></div>` - * </pre> - * </div> + * Special properties are exposed on the local scope of each template instance, including: * - * @priority 450 + * | Variable | Type | Details | + * |-----------|-----------------|-----------------------------------------------------------------------------| + * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) | + * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. | + * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. | + * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. | + * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). | + * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). | * - * @element ANY - * @param {expression} ngInit {@link guide/expression Expression} to eval. + * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}. + * This may be useful when, for instance, nesting ngRepeats. * - * @example - <example module="initExample"> - <file name="index.html"> - <script> - angular.module('initExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.list = [['a', 'b'], ['c', 'd']]; - }]); - </script> - <div ng-controller="ExampleController"> - <div ng-repeat="innerList in list" ng-init="outerIndex = $index"> - <div ng-repeat="value in innerList" ng-init="innerIndex = $index"> - <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span> - </div> - </div> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should alias index positions', function() { - var elements = element.all(by.css('.example-init')); - expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;'); - expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;'); - expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;'); - expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;'); - }); - </file> - </example> - */ -var ngInitDirective = ngDirective({ - priority: 450, - compile: function() { - return { - pre: function(scope, element, attrs) { - scope.$eval(attrs.ngInit); - } - }; - } -}); - -/** - * @ngdoc directive - * @name ngList * - * @description - * Text input that converts between a delimited string and an array of strings. The default - * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom - * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`. + * # Iterating over object properties * - * The behaviour of the directive is affected by the use of the `ngTrim` attribute. - * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each - * list item is respected. This implies that the user of the directive is responsible for - * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a - * tab or newline character. - * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected - * when joining the list items back together) and whitespace around each list item is stripped - * before it is added to the model. + * It is possible to get `ngRepeat` to iterate over the properties of an object using the following + * syntax: * - * ### Example with Validation + * ```js + * <div ng-repeat="(key, value) in myObj"> ... </div> + * ``` * - * <example name="ngList-directive" module="listExample"> - * <file name="app.js"> - * angular.module('listExample', []) - * .controller('ExampleController', ['$scope', function($scope) { - * $scope.names = ['morpheus', 'neo', 'trinity']; - * }]); - * </file> - * <file name="index.html"> - * <form name="myForm" ng-controller="ExampleController"> - * List: <input name="namesInput" ng-model="names" ng-list required> - * <span class="error" ng-show="myForm.namesInput.$error.required"> - * Required!</span> - * <br> - * <tt>names = {{names}}</tt><br/> - * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/> - * <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/> - * <tt>myForm.$valid = {{myForm.$valid}}</tt><br/> - * <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/> - * </form> - * </file> - * <file name="protractor.js" type="protractor"> - * var listInput = element(by.model('names')); - * var names = element(by.exactBinding('names')); - * var valid = element(by.binding('myForm.namesInput.$valid')); - * var error = element(by.css('span.error')); + * You need to be aware that the JavaScript specification does not define the order of keys + * returned for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive + * used to sort the keys alphabetically.) * - * it('should initialize to model', function() { - * expect(names.getText()).toContain('["morpheus","neo","trinity"]'); - * expect(valid.getText()).toContain('true'); - * expect(error.getCssValue('display')).toBe('none'); - * }); + * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser + * when running `for key in myObj`. It seems that browsers generally follow the strategy of providing + * keys in the order in which they were defined, although there are exceptions when keys are deleted + * and reinstated. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues * - * it('should be invalid if empty', function() { - * listInput.clear(); - * listInput.sendKeys(''); + * If this is not desired, the recommended workaround is to convert your object into an array + * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could + * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter) + * or implement a `$watch` on the object yourself. * - * expect(names.getText()).toContain(''); - * expect(valid.getText()).toContain('false'); - * expect(error.getCssValue('display')).not.toBe('none'); - * }); - * </file> - * </example> * - * ### Example - splitting on whitespace - * <example name="ngList-directive-newlines"> - * <file name="index.html"> - * <textarea ng-model="list" ng-list=" " ng-trim="false"></textarea> - * <pre>{{ list | json }}</pre> - * </file> - * <file name="protractor.js" type="protractor"> - * it("should split the text by newlines", function() { - * var listInput = element(by.model('list')); - * var output = element(by.binding('list | json')); - * listInput.sendKeys('abc\ndef\nghi'); - * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]'); - * }); - * </file> - * </example> + * # Tracking and Duplicates * - * @element input - * @param {string=} ngList optional delimiter that should be used to split the value. - */ -var ngListDirective = function() { - return { - restrict: 'A', - priority: 100, - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - // We want to control whitespace trimming so we use this convoluted approach - // to access the ngList attribute, which doesn't pre-trim the attribute - var ngList = element.attr(attr.$attr.ngList) || ', '; - var trimValues = attr.ngTrim !== 'false'; - var separator = trimValues ? trim(ngList) : ngList; - - var parse = function(viewValue) { - // If the viewValue is invalid (say required but empty) it will be `undefined` - if (isUndefined(viewValue)) return; - - var list = []; - - if (viewValue) { - forEach(viewValue.split(separator), function(value) { - if (value) list.push(trimValues ? trim(value) : value); - }); - } - - return list; - }; - - ctrl.$parsers.push(parse); - ctrl.$formatters.push(function(value) { - if (isArray(value)) { - return value.join(ngList); - } - - return undefined; - }); - - // Override the standard $isEmpty because an empty array means the input is empty. - ctrl.$isEmpty = function(value) { - return !value || !value.length; - }; - } - }; -}; - -/* global VALID_CLASS: true, - INVALID_CLASS: true, - PRISTINE_CLASS: true, - DIRTY_CLASS: true, - UNTOUCHED_CLASS: true, - TOUCHED_CLASS: true, -*/ - -var VALID_CLASS = 'ng-valid', - INVALID_CLASS = 'ng-invalid', - PRISTINE_CLASS = 'ng-pristine', - DIRTY_CLASS = 'ng-dirty', - UNTOUCHED_CLASS = 'ng-untouched', - TOUCHED_CLASS = 'ng-touched', - PENDING_CLASS = 'ng-pending'; - - -var $ngModelMinErr = new minErr('ngModel'); - -/** - * @ngdoc type - * @name ngModel.NgModelController + * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM: * - * @property {string} $viewValue Actual string value in the view. - * @property {*} $modelValue The value in the model that the control is bound to. - * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever - the control reads value from the DOM. The functions are called in array order, each passing - its return value through to the next. The last return value is forwarded to the - {@link ngModel.NgModelController#$validators `$validators`} collection. - -Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue -`$viewValue`}. - -Returning `undefined` from a parser means a parse error occurred. In that case, -no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel` -will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`} -is set to `true`. The parse error is stored in `ngModel.$error.parse`. - + * * When an item is added, a new instance of the template is added to the DOM. + * * When an item is removed, its template instance is removed from the DOM. + * * When items are reordered, their respective templates are reordered in the DOM. * - * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever - the model value changes. The functions are called in reverse array order, each passing the value through to the - next. The last return value is used as the actual DOM value. - Used to format / convert values for display in the control. - * ```js - * function formatter(value) { - * if (value) { - * return value.toUpperCase(); - * } - * } - * ngModel.$formatters.push(formatter); + * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when + * there are duplicates, it is not possible to maintain a one-to-one mapping between collection + * items and DOM elements. + * + * If you do need to repeat duplicate items, you can substitute the default tracking behavior + * with your own using the `track by` expression. + * + * For example, you may track items by the index of each item in the collection, using the + * special scope property `$index`: + * ```html + * <div ng-repeat="n in [42, 42, 43, 43] track by $index"> + * {{n}} + * </div> + * ``` + * + * You may use arbitrary expressions in `track by`, including references to custom functions + * on the scope: + * ```html + * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)"> + * {{n}} + * </div> + * ``` + * + * If you are working with objects that have an identifier property, you can track + * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat` + * will not have to rebuild the DOM elements for items it has already rendered, even if the + * JavaScript objects in the collection have been substituted for new ones: + * ```html + * <div ng-repeat="model in collection track by model.id"> + * {{model.name}} + * </div> + * ``` + * + * When no `track by` expression is provided, it is equivalent to tracking by the built-in + * `$id` function, which tracks items by their identity: + * ```html + * <div ng-repeat="obj in collection track by $id(obj)"> + * {{obj.prop}} + * </div> + * ``` + * + * <div class="alert alert-warning"> + * **Note:** `track by` must always be the last expression: + * </div> + * ``` + * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id"> + * {{model.name}} + * </div> + * ``` + * + * # Special repeat start and end points + * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending + * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively. + * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on) + * up to and including the ending HTML tag where **ng-repeat-end** is placed. + * + * The example below makes use of this feature: + * ```html + * <header ng-repeat-start="item in items"> + * Header {{ item }} + * </header> + * <div class="body"> + * Body {{ item }} + * </div> + * <footer ng-repeat-end> + * Footer {{ item }} + * </footer> + * ``` + * + * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to: + * ```html + * <header> + * Header A + * </header> + * <div class="body"> + * Body A + * </div> + * <footer> + * Footer A + * </footer> + * <header> + * Header B + * </header> + * <div class="body"> + * Body B + * </div> + * <footer> + * Footer B + * </footer> * ``` * - * @property {Object.<string, function>} $validators A collection of validators that are applied - * whenever the model value changes. The key value within the object refers to the name of the - * validator while the function refers to the validation operation. The validation operation is - * provided with the model value as an argument and must return a true or false value depending - * on the response of that validation. + * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such + * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**). + * + * @animations + * **.enter** - when a new item is added to the list or when an item is revealed after a filter * - * ```js - * ngModel.$validators.validCharacters = function(modelValue, viewValue) { - * var value = modelValue || viewValue; - * return /[0-9]+/.test(value) && - * /[a-z]+/.test(value) && - * /[A-Z]+/.test(value) && - * /\W+/.test(value); - * }; - * ``` + * **.leave** - when an item is removed from the list or when an item is filtered out * - * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to - * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided - * is expected to return a promise when it is run during the model validation process. Once the promise - * is delivered then the validation status will be set to true when fulfilled and false when rejected. - * When the asynchronous validators are triggered, each of the validators will run in parallel and the model - * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator - * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators - * will only run once all synchronous validators have passed. + * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered * - * Please note that if $http is used then it is important that the server returns a success HTTP response code - * in order to fulfill the validation and a status level of `4xx` in order to reject the validation. + * @element ANY + * @scope + * @priority 1000 + * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These + * formats are currently supported: * - * ```js - * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { - * var value = modelValue || viewValue; + * * `variable in expression` – where variable is the user defined loop variable and `expression` + * is a scope expression giving the collection to enumerate. * - * // Lookup user by username - * return $http.get('/api/users/' + value). - * then(function resolved() { - * //username exists, this means validation fails - * return $q.reject('exists'); - * }, function rejected() { - * //username does not exist, therefore this validation passes - * return true; - * }); - * }; - * ``` + * For example: `album in artist.albums`. * - * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the - * view value has changed. It is called with no arguments, and its return value is ignored. - * This can be used in place of additional $watches against the model value. + * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers, + * and `expression` is the scope expression giving the collection to enumerate. * - * @property {Object} $error An object hash with all failing validator ids as keys. - * @property {Object} $pending An object hash with all pending validator ids as keys. + * For example: `(name, age) in {'adam':10, 'amalie':12}`. * - * @property {boolean} $untouched True if control has not lost focus yet. - * @property {boolean} $touched True if control has lost focus. - * @property {boolean} $pristine True if user has not interacted with the control yet. - * @property {boolean} $dirty True if user has already interacted with the control. - * @property {boolean} $valid True if there is no error. - * @property {boolean} $invalid True if at least one error on the control. - * @property {string} $name The name attribute of the control. + * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression + * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression + * is specified, ng-repeat associates elements by identity. It is an error to have + * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are + * mapped to the same DOM element, which is not possible.) * - * @description + * Note that the tracking expression must come last, after any filters, and the alias expression. * - * `NgModelController` provides API for the {@link ngModel `ngModel`} directive. - * The controller contains services for data-binding, validation, CSS updates, and value formatting - * and parsing. It purposefully does not contain any logic which deals with DOM rendering or - * listening to DOM events. - * Such DOM related logic should be provided by other directives which make use of - * `NgModelController` for data-binding to control elements. - * Angular provides this DOM logic for most {@link input `input`} elements. - * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example - * custom control example} that uses `ngModelController` to bind to `contenteditable` elements. + * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements + * will be associated by item identity in the array. * - * @example - * ### Custom Control Example - * This example shows how to use `NgModelController` with a custom control to achieve - * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) - * collaborate together to achieve the desired result. + * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique + * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements + * with the corresponding item in the array by identity. Moving the same object in array would move the DOM + * element in the same way in the DOM. * - * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element - * contents be edited in place by the user. This will not work on older browsers. + * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this + * case the object identity does not matter. Two objects are considered equivalent as long as their `id` + * property is same. * - * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize} - * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`). - * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks - * that content using the `$sce` service. + * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter + * to items in conjunction with a tracking expression. * - * <example name="NgModelController" module="customControl" deps="angular-sanitize.js"> - <file name="style.css"> - [contenteditable] { - border: 1px solid black; - background-color: white; - min-height: 20px; + * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the + * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message + * when a filter is active on the repeater, but the filtered result set is empty. + * + * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after + * the items have been processed through the filter. + * + * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end + * (and not as operator, inside an expression). + * + * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` . + * + * @example + * This example initializes the scope to a list of names and + * then uses `ngRepeat` to display every person: + <example module="ngAnimate" deps="angular-animate.js" animations="true"> + <file name="index.html"> + <div ng-init="friends = [ + {name:'John', age:25, gender:'boy'}, + {name:'Jessie', age:30, gender:'girl'}, + {name:'Johanna', age:28, gender:'girl'}, + {name:'Joy', age:15, gender:'girl'}, + {name:'Mary', age:28, gender:'girl'}, + {name:'Peter', age:95, gender:'boy'}, + {name:'Sebastian', age:50, gender:'boy'}, + {name:'Erika', age:27, gender:'girl'}, + {name:'Patrick', age:40, gender:'boy'}, + {name:'Samantha', age:60, gender:'girl'} + ]"> + I have {{friends.length}} friends. They are: + <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" /> + <ul class="example-animate-container"> + <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results"> + [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. + </li> + <li class="animate-repeat" ng-if="results.length == 0"> + <strong>No results found...</strong> + </li> + </ul> + </div> + </file> + <file name="animations.css"> + .example-animate-container { + background:white; + border:1px solid black; + list-style:none; + margin:0; + padding:0 10px; } - .ng-invalid { - border: 1px solid red; + .animate-repeat { + line-height:40px; + list-style:none; + box-sizing:border-box; } - </file> - <file name="script.js"> - angular.module('customControl', ['ngSanitize']). - directive('contenteditable', ['$sce', function($sce) { - return { - restrict: 'A', // only activate on element attribute - require: '?ngModel', // get a hold of NgModelController - link: function(scope, element, attrs, ngModel) { - if (!ngModel) return; // do nothing if no ng-model - - // Specify how UI should be updated - ngModel.$render = function() { - element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); - }; - - // Listen for change events to enable binding - element.on('blur keyup change', function() { - scope.$evalAsync(read); - }); - read(); // initialize - - // Write data to the model - function read() { - var html = element.html(); - // When we clear the content editable the browser leaves a <br> behind - // If strip-br attribute is provided then we strip this out - if ( attrs.stripBr && html == '<br>' ) { - html = ''; - } - ngModel.$setViewValue(html); - } - } - }; - }]); - </file> - <file name="index.html"> - <form name="myForm"> - <div contenteditable - name="myWidget" ng-model="userContent" - strip-br="true" - required>Change me!</div> - <span ng-show="myForm.myWidget.$error.required">Required!</span> - <hr> - <textarea ng-model="userContent"></textarea> - </form> - </file> - <file name="protractor.js" type="protractor"> - it('should data-bind and become invalid', function() { - if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') { - // SafariDriver can't handle contenteditable - // and Firefox driver can't clear contenteditables very well - return; + .animate-repeat.ng-move, + .animate-repeat.ng-enter, + .animate-repeat.ng-leave { + -webkit-transition:all linear 0.5s; + transition:all linear 0.5s; } - var contentEditable = element(by.css('[contenteditable]')); - var content = 'Change me!'; - expect(contentEditable.getText()).toEqual(content); + .animate-repeat.ng-leave.ng-leave-active, + .animate-repeat.ng-move, + .animate-repeat.ng-enter { + opacity:0; + max-height:0; + } - contentEditable.clear(); - contentEditable.sendKeys(protractor.Key.BACK_SPACE); - expect(contentEditable.getText()).toEqual(''); - expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/); - }); + .animate-repeat.ng-leave, + .animate-repeat.ng-move.ng-move-active, + .animate-repeat.ng-enter.ng-enter-active { + opacity:1; + max-height:40px; + } </file> - * </example> - * - * - */ -var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate', - function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) { - this.$viewValue = Number.NaN; - this.$modelValue = Number.NaN; - this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity. - this.$validators = {}; - this.$asyncValidators = {}; - this.$parsers = []; - this.$formatters = []; - this.$viewChangeListeners = []; - this.$untouched = true; - this.$touched = false; - this.$pristine = true; - this.$dirty = false; - this.$valid = true; - this.$invalid = false; - this.$error = {}; // keep invalid keys here - this.$$success = {}; // keep valid keys here - this.$pending = undefined; // keep pending keys here - this.$name = $interpolate($attr.name || '', false)($scope); - - - var parsedNgModel = $parse($attr.ngModel), - parsedNgModelAssign = parsedNgModel.assign, - ngModelGet = parsedNgModel, - ngModelSet = parsedNgModelAssign, - pendingDebounce = null, - ctrl = this; - - this.$$setOptions = function(options) { - ctrl.$options = options; - if (options && options.getterSetter) { - var invokeModelGetter = $parse($attr.ngModel + '()'), - invokeModelSetter = $parse($attr.ngModel + '($$$p)'); - - ngModelGet = function($scope) { - var modelValue = parsedNgModel($scope); - if (isFunction(modelValue)) { - modelValue = invokeModelGetter($scope); - } - return modelValue; - }; - ngModelSet = function($scope, newValue) { - if (isFunction(parsedNgModel($scope))) { - invokeModelSetter($scope, {$$$p: ctrl.$modelValue}); - } else { - parsedNgModelAssign($scope, ctrl.$modelValue); - } - }; - } else if (!parsedNgModel.assign) { - throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}", - $attr.ngModel, startingTag($element)); - } - }; - - /** - * @ngdoc method - * @name ngModel.NgModelController#$render - * - * @description - * Called when the view needs to be updated. It is expected that the user of the ng-model - * directive will implement this method. - * - * The `$render()` method is invoked in the following situations: - * - * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last - * committed value then `$render()` is called to update the input control. - * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and - * the `$viewValue` are different to last time. - * - * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of - * `$modelValue` and `$viewValue` are actually different to their previous value. If `$modelValue` - * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be - * invoked if you only change a property on the objects. - */ - this.$render = noop; - - /** - * @ngdoc method - * @name ngModel.NgModelController#$isEmpty - * - * @description - * This is called when we need to determine if the value of an input is empty. - * - * For instance, the required directive does this to work out if the input has data or not. - * - * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. - * - * You can override this for input directives whose concept of being empty is different to the - * default. The `checkboxInputType` directive does this because in its case a value of `false` - * implies empty. - * - * @param {*} value The value of the input to check for emptiness. - * @returns {boolean} True if `value` is "empty". - */ - this.$isEmpty = function(value) { - return isUndefined(value) || value === '' || value === null || value !== value; - }; - - var parentForm = $element.inheritedData('$formController') || nullFormCtrl, - currentValidationRunId = 0; - - /** - * @ngdoc method - * @name ngModel.NgModelController#$setValidity - * - * @description - * Change the validity state, and notify the form. - * - * This method can be called within $parsers/$formatters or a custom validation implementation. - * However, in most cases it should be sufficient to use the `ngModel.$validators` and - * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically. - * - * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned - * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` - * (for unfulfilled `$asyncValidators`), so that it is available for data-binding. - * The `validationErrorKey` should be in camelCase and will get converted into dash-case - * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` - * class and can be bound to as `{{someForm.someControl.$error.myError}}` . - * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined), - * or skipped (null). Pending is used for unfulfilled `$asyncValidators`. - * Skipped is used by Angular when validators do not run because of parse errors and - * when `$asyncValidators` do not run because any of the `$validators` failed. - */ - addSetValidityMethod({ - ctrl: this, - $element: $element, - set: function(object, property) { - object[property] = true; - }, - unset: function(object, property) { - delete object[property]; - }, - parentForm: parentForm, - $animate: $animate - }); - - /** - * @ngdoc method - * @name ngModel.NgModelController#$setPristine - * - * @description - * Sets the control to its pristine state. - * - * This method can be called to remove the `ng-dirty` class and set the control to its pristine - * state (`ng-pristine` class). A model is considered to be pristine when the control - * has not been changed from when first compiled. - */ - this.$setPristine = function() { - ctrl.$dirty = false; - ctrl.$pristine = true; - $animate.removeClass($element, DIRTY_CLASS); - $animate.addClass($element, PRISTINE_CLASS); - }; + <file name="protractor.js" type="protractor"> + var friends = element.all(by.repeater('friend in friends')); - /** - * @ngdoc method - * @name ngModel.NgModelController#$setDirty - * - * @description - * Sets the control to its dirty state. - * - * This method can be called to remove the `ng-pristine` class and set the control to its dirty - * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed - * from when first compiled. - */ - this.$setDirty = function() { - ctrl.$dirty = true; - ctrl.$pristine = false; - $animate.removeClass($element, PRISTINE_CLASS); - $animate.addClass($element, DIRTY_CLASS); - parentForm.$setDirty(); - }; + it('should render initial data set', function() { + expect(friends.count()).toBe(10); + expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.'); + expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.'); + expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.'); + expect(element(by.binding('friends.length')).getText()) + .toMatch("I have 10 friends. They are:"); + }); - /** - * @ngdoc method - * @name ngModel.NgModelController#$setUntouched - * - * @description - * Sets the control to its untouched state. - * - * This method can be called to remove the `ng-touched` class and set the control to its - * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched - * by default, however this function can be used to restore that state if the model has - * already been touched by the user. - */ - this.$setUntouched = function() { - ctrl.$touched = false; - ctrl.$untouched = true; - $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS); - }; + it('should update repeater when filter predicate changes', function() { + expect(friends.count()).toBe(10); - /** - * @ngdoc method - * @name ngModel.NgModelController#$setTouched - * - * @description - * Sets the control to its touched state. - * - * This method can be called to remove the `ng-untouched` class and set the control to its - * touched state (`ng-touched` class). A model is considered to be touched when the user has - * first focused the control element and then shifted focus away from the control (blur event). - */ - this.$setTouched = function() { - ctrl.$touched = true; - ctrl.$untouched = false; - $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS); - }; + element(by.model('q')).sendKeys('ma'); - /** - * @ngdoc method - * @name ngModel.NgModelController#$rollbackViewValue - * - * @description - * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`, - * which may be caused by a pending debounced event or because the input is waiting for a some - * future event. - * - * If you have an input that uses `ng-model-options` to set up debounced events or events such - * as blur you can have a situation where there is a period when the `$viewValue` - * is out of synch with the ngModel's `$modelValue`. - * - * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue` - * programmatically before these debounced/future events have resolved/occurred, because Angular's - * dirty checking mechanism is not able to tell whether the model has actually changed or not. - * - * The `$rollbackViewValue()` method should be called before programmatically changing the model of an - * input which may have such events pending. This is important in order to make sure that the - * input field will be updated with the new model value and any pending operations are cancelled. - * - * <example name="ng-model-cancel-update" module="cancel-update-example"> - * <file name="app.js"> - * angular.module('cancel-update-example', []) - * - * .controller('CancelUpdateController', ['$scope', function($scope) { - * $scope.resetWithCancel = function(e) { - * if (e.keyCode == 27) { - * $scope.myForm.myInput1.$rollbackViewValue(); - * $scope.myValue = ''; - * } - * }; - * $scope.resetWithoutCancel = function(e) { - * if (e.keyCode == 27) { - * $scope.myValue = ''; - * } - * }; - * }]); - * </file> - * <file name="index.html"> - * <div ng-controller="CancelUpdateController"> - * <p>Try typing something in each input. See that the model only updates when you - * blur off the input. - * </p> - * <p>Now see what happens if you start typing then press the Escape key</p> - * - * <form name="myForm" ng-model-options="{ updateOn: 'blur' }"> - * <p>With $rollbackViewValue()</p> - * <input name="myInput1" ng-model="myValue" ng-keydown="resetWithCancel($event)"><br/> - * myValue: "{{ myValue }}" - * - * <p>Without $rollbackViewValue()</p> - * <input name="myInput2" ng-model="myValue" ng-keydown="resetWithoutCancel($event)"><br/> - * myValue: "{{ myValue }}" - * </form> - * </div> - * </file> - * </example> - */ - this.$rollbackViewValue = function() { - $timeout.cancel(pendingDebounce); - ctrl.$viewValue = ctrl.$$lastCommittedViewValue; - ctrl.$render(); - }; + expect(friends.count()).toBe(2); + expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.'); + expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.'); + }); + </file> + </example> + */ +var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { + var NG_REMOVED = '$$NG_REMOVED'; + var ngRepeatMinErr = minErr('ngRepeat'); - /** - * @ngdoc method - * @name ngModel.NgModelController#$validate - * - * @description - * Runs each of the registered validators (first synchronous validators and then - * asynchronous validators). - * If the validity changes to invalid, the model will be set to `undefined`, - * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. - * If the validity changes to valid, it will set the model to the last available valid - * modelValue, i.e. either the last parsed value or the last value set from the scope. - */ - this.$validate = function() { - // ignore $validate before model is initialized - if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { - return; - } + var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) { + // TODO(perf): generate setters to shave off ~40ms or 1-1.5% + scope[valueIdentifier] = value; + if (keyIdentifier) scope[keyIdentifier] = key; + scope.$index = index; + scope.$first = (index === 0); + scope.$last = (index === (arrayLength - 1)); + scope.$middle = !(scope.$first || scope.$last); + // jshint bitwise: false + scope.$odd = !(scope.$even = (index&1) === 0); + // jshint bitwise: true + }; - var viewValue = ctrl.$$lastCommittedViewValue; - // Note: we use the $$rawModelValue as $modelValue might have been - // set to undefined during a view -> model update that found validation - // errors. We can't parse the view here, since that could change - // the model although neither viewValue nor the model on the scope changed - var modelValue = ctrl.$$rawModelValue; + var getBlockStart = function(block) { + return block.clone[0]; + }; - // Check if the there's a parse error, so we don't unset it accidentially - var parserName = ctrl.$$parserName || 'parse'; - var parserValid = ctrl.$error[parserName] ? false : undefined; + var getBlockEnd = function(block) { + return block.clone[block.clone.length - 1]; + }; - var prevValid = ctrl.$valid; - var prevModelValue = ctrl.$modelValue; - var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; + return { + restrict: 'A', + multiElement: true, + transclude: 'element', + priority: 1000, + terminal: true, + $$tlb: true, + compile: function ngRepeatCompile($element, $attr) { + var expression = $attr.ngRepeat; + var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' '); - ctrl.$$runValidators(parserValid, modelValue, viewValue, function(allValid) { - // If there was no change in validity, don't update the model - // This prevents changing an invalid modelValue to undefined - if (!allowInvalid && prevValid !== allValid) { - // Note: Don't check ctrl.$valid here, as we could have - // external validators (e.g. calculated on the server), - // that just call $setValidity and need the model value - // to calculate their validity. - ctrl.$modelValue = allValid ? modelValue : undefined; + var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); - if (ctrl.$modelValue !== prevModelValue) { - ctrl.$$writeModelToScope(); - } + if (!match) { + throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", + expression); } - }); - - }; - this.$$runValidators = function(parseValid, modelValue, viewValue, doneCallback) { - currentValidationRunId++; - var localValidationRunId = currentValidationRunId; + var lhs = match[1]; + var rhs = match[2]; + var aliasAs = match[3]; + var trackByExp = match[4]; - // check parser error - if (!processParseErrors(parseValid)) { - validationDone(false); - return; - } - if (!processSyncValidators()) { - validationDone(false); - return; - } - processAsyncValidators(); + match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); - function processParseErrors(parseValid) { - var errorKey = ctrl.$$parserName || 'parse'; - if (parseValid === undefined) { - setValidity(errorKey, null); - } else { - setValidity(errorKey, parseValid); - if (!parseValid) { - forEach(ctrl.$validators, function(v, name) { - setValidity(name, null); - }); - forEach(ctrl.$asyncValidators, function(v, name) { - setValidity(name, null); - }); - return false; - } + if (!match) { + throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.", + lhs); } - return true; - } + var valueIdentifier = match[3] || match[1]; + var keyIdentifier = match[2]; - function processSyncValidators() { - var syncValidatorsValid = true; - forEach(ctrl.$validators, function(validator, name) { - var result = validator(modelValue, viewValue); - syncValidatorsValid = syncValidatorsValid && result; - setValidity(name, result); - }); - if (!syncValidatorsValid) { - forEach(ctrl.$asyncValidators, function(v, name) { - setValidity(name, null); - }); - return false; + if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) || + /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) { + throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.", + aliasAs); } - return true; - } - function processAsyncValidators() { - var validatorPromises = []; - var allValid = true; - forEach(ctrl.$asyncValidators, function(validator, name) { - var promise = validator(modelValue, viewValue); - if (!isPromiseLike(promise)) { - throw $ngModelMinErr("$asyncValidators", - "Expected asynchronous validator to return a promise but got '{0}' instead.", promise); - } - setValidity(name, undefined); - validatorPromises.push(promise.then(function() { - setValidity(name, true); - }, function(error) { - allValid = false; - setValidity(name, false); - })); - }); - if (!validatorPromises.length) { - validationDone(true); + var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn; + var hashFnLocals = {$id: hashKey}; + + if (trackByExp) { + trackByExpGetter = $parse(trackByExp); } else { - $q.all(validatorPromises).then(function() { - validationDone(allValid); - }, noop); + trackByIdArrayFn = function(key, value) { + return hashKey(value); + }; + trackByIdObjFn = function(key) { + return key; + }; } - } - function setValidity(name, isValid) { - if (localValidationRunId === currentValidationRunId) { - ctrl.$setValidity(name, isValid); - } - } + return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) { - function validationDone(allValid) { - if (localValidationRunId === currentValidationRunId) { + if (trackByExpGetter) { + trackByIdExpFn = function(key, value, index) { + // assign key, value, and $index to the locals so that they can be used in hash functions + if (keyIdentifier) hashFnLocals[keyIdentifier] = key; + hashFnLocals[valueIdentifier] = value; + hashFnLocals.$index = index; + return trackByExpGetter($scope, hashFnLocals); + }; + } - doneCallback(allValid); - } - } - }; + // Store a list of elements from previous run. This is a hash where key is the item from the + // iterator, and the value is objects with following properties. + // - scope: bound scope + // - element: previous element. + // - index: position + // + // We are using no-proto object so that we don't need to guard against inherited props via + // hasOwnProperty. + var lastBlockMap = createMap(); - /** - * @ngdoc method - * @name ngModel.NgModelController#$commitViewValue - * - * @description - * Commit a pending update to the `$modelValue`. - * - * Updates may be pending by a debounced event or because the input is waiting for a some future - * event defined in `ng-model-options`. this method is rarely needed as `NgModelController` - * usually handles calling this in response to input events. - */ - this.$commitViewValue = function() { - var viewValue = ctrl.$viewValue; + //watch props + $scope.$watchCollection(rhs, function ngRepeatAction(collection) { + var index, length, + previousNode = $element[0], // node that cloned nodes should be inserted after + // initialized to the comment node anchor + nextNode, + // Same as lastBlockMap but it has the current state. It will become the + // lastBlockMap on the next iteration. + nextBlockMap = createMap(), + collectionLength, + key, value, // key/value of iteration + trackById, + trackByIdFn, + collectionKeys, + block, // last object information {scope, element, id} + nextBlockOrder, + elementsToRemove; - $timeout.cancel(pendingDebounce); + if (aliasAs) { + $scope[aliasAs] = collection; + } - // If the view value has not changed then we should just exit, except in the case where there is - // a native validator on the element. In this case the validation state may have changed even though - // the viewValue has stayed empty. - if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) { - return; - } - ctrl.$$lastCommittedViewValue = viewValue; + if (isArrayLike(collection)) { + collectionKeys = collection; + trackByIdFn = trackByIdExpFn || trackByIdArrayFn; + } else { + trackByIdFn = trackByIdExpFn || trackByIdObjFn; + // if object, extract keys, in enumeration order, unsorted + collectionKeys = []; + for (var itemKey in collection) { + if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') { + collectionKeys.push(itemKey); + } + } + } - // change to dirty - if (ctrl.$pristine) { - this.$setDirty(); - } - this.$$parseAndValidate(); - }; + collectionLength = collectionKeys.length; + nextBlockOrder = new Array(collectionLength); - this.$$parseAndValidate = function() { - var viewValue = ctrl.$$lastCommittedViewValue; - var modelValue = viewValue; - var parserValid = isUndefined(modelValue) ? undefined : true; + // locate existing items + for (index = 0; index < collectionLength; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + trackById = trackByIdFn(key, value, index); + if (lastBlockMap[trackById]) { + // found previously seen block + block = lastBlockMap[trackById]; + delete lastBlockMap[trackById]; + nextBlockMap[trackById] = block; + nextBlockOrder[index] = block; + } else if (nextBlockMap[trackById]) { + // if collision detected. restore lastBlockMap and throw an error + forEach(nextBlockOrder, function(block) { + if (block && block.scope) lastBlockMap[block.id] = block; + }); + throw ngRepeatMinErr('dupes', + "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}", + expression, trackById, value); + } else { + // new never before seen block + nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined}; + nextBlockMap[trackById] = true; + } + } - if (parserValid) { - for (var i = 0; i < ctrl.$parsers.length; i++) { - modelValue = ctrl.$parsers[i](modelValue); - if (isUndefined(modelValue)) { - parserValid = false; - break; - } - } - } - if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) { - // ctrl.$modelValue has not been touched yet... - ctrl.$modelValue = ngModelGet($scope); - } - var prevModelValue = ctrl.$modelValue; - var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid; - ctrl.$$rawModelValue = modelValue; + // remove leftover items + for (var blockKey in lastBlockMap) { + block = lastBlockMap[blockKey]; + elementsToRemove = getBlockNodes(block.clone); + $animate.leave(elementsToRemove); + if (elementsToRemove[0].parentNode) { + // if the element was not removed yet because of pending animation, mark it as deleted + // so that we can ignore it later + for (index = 0, length = elementsToRemove.length; index < length; index++) { + elementsToRemove[index][NG_REMOVED] = true; + } + } + block.scope.$destroy(); + } - if (allowInvalid) { - ctrl.$modelValue = modelValue; - writeToModelIfNeeded(); - } + // we are not using forEach for perf reasons (trying to avoid #call) + for (index = 0; index < collectionLength; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + block = nextBlockOrder[index]; - // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. - // This can happen if e.g. $setViewValue is called from inside a parser - ctrl.$$runValidators(parserValid, modelValue, ctrl.$$lastCommittedViewValue, function(allValid) { - if (!allowInvalid) { - // Note: Don't check ctrl.$valid here, as we could have - // external validators (e.g. calculated on the server), - // that just call $setValidity and need the model value - // to calculate their validity. - ctrl.$modelValue = allValid ? modelValue : undefined; - writeToModelIfNeeded(); - } - }); + if (block.scope) { + // if we have already seen this object, then we need to reuse the + // associated scope/element - function writeToModelIfNeeded() { - if (ctrl.$modelValue !== prevModelValue) { - ctrl.$$writeModelToScope(); - } - } - }; + nextNode = previousNode; - this.$$writeModelToScope = function() { - ngModelSet($scope, ctrl.$modelValue); - forEach(ctrl.$viewChangeListeners, function(listener) { - try { - listener(); - } catch (e) { - $exceptionHandler(e); - } - }); - }; + // skip nodes that are already pending removal via leave animation + do { + nextNode = nextNode.nextSibling; + } while (nextNode && nextNode[NG_REMOVED]); - /** - * @ngdoc method - * @name ngModel.NgModelController#$setViewValue - * - * @description - * Update the view value. - * - * This method should be called when an input directive want to change the view value; typically, - * this is done from within a DOM event handler. - * - * For example {@link ng.directive:input input} calls it when the value of the input changes and - * {@link ng.directive:select select} calls it when an option is selected. - * - * If the new `value` is an object (rather than a string or a number), we should make a copy of the - * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep - * watch of objects, it only looks for a change of identity. If you only change the property of - * the object then ngModel will not realise that the object has changed and will not invoke the - * `$parsers` and `$validators` pipelines. - * - * For this reason, you should not change properties of the copy once it has been passed to - * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly. - * - * When this method is called, the new `value` will be staged for committing through the `$parsers` - * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged - * value sent directly for processing, finally to be applied to `$modelValue` and then the - * **expression** specified in the `ng-model` attribute. - * - * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called. - * - * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn` - * and the `default` trigger is not listed, all those actions will remain pending until one of the - * `updateOn` events is triggered on the DOM element. - * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions} - * directive is used with a custom debounce for this particular event. - * - * Note that calling this function does not trigger a `$digest`. - * - * @param {string} value Value from the view. - * @param {string} trigger Event that triggered the update. - */ - this.$setViewValue = function(value, trigger) { - ctrl.$viewValue = value; - if (!ctrl.$options || ctrl.$options.updateOnDefault) { - ctrl.$$debounceViewValueCommit(trigger); + if (getBlockStart(block) != nextNode) { + // existing item which got moved + $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode)); + } + previousNode = getBlockEnd(block); + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + } else { + // new item which we don't know about + $transclude(function ngRepeatTransclude(clone, scope) { + block.scope = scope; + // http://jsperf.com/clone-vs-createcomment + var endNode = ngRepeatEndComment.cloneNode(false); + clone[clone.length++] = endNode; + + // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper? + $animate.enter(clone, null, jqLite(previousNode)); + previousNode = endNode; + // Note: We only need the first/last node of the cloned nodes. + // However, we need to keep the reference to the jqlite wrapper as it might be changed later + // by a directive with templateUrl when its template arrives. + block.clone = clone; + nextBlockMap[block.id] = block; + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + }); + } + } + lastBlockMap = nextBlockMap; + }); + }; } }; +}]; - this.$$debounceViewValueCommit = function(trigger) { - var debounceDelay = 0, - options = ctrl.$options, - debounce; - - if (options && isDefined(options.debounce)) { - debounce = options.debounce; - if (isNumber(debounce)) { - debounceDelay = debounce; - } else if (isNumber(debounce[trigger])) { - debounceDelay = debounce[trigger]; - } else if (isNumber(debounce['default'])) { - debounceDelay = debounce['default']; +var NG_HIDE_CLASS = 'ng-hide'; +var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; +/** + * @ngdoc directive + * @name ngShow + * @multiElement + * + * @description + * The `ngShow` directive shows or hides the given HTML element based on the expression + * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding + * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined + * in AngularJS and sets the display style to none (using an !important flag). + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * + * ```html + * <!-- when $scope.myValue is truthy (element is visible) --> + * <div ng-show="myValue"></div> + * + * <!-- when $scope.myValue is falsy (element is hidden) --> + * <div ng-show="myValue" class="ng-hide"></div> + * ``` + * + * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class + * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed + * from the element causing the element not to appear hidden. + * + * ## Why is !important used? + * + * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector + * can be easily overridden by heavier selectors. For example, something as simple + * as changing the display style on a HTML list item would make hidden elements appear visible. + * This also becomes a bigger issue when dealing with CSS frameworks. + * + * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector + * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the + * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. + * + * ### Overriding `.ng-hide` + * + * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change + * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide` + * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope + * with extra animation classes that can be added. + * + * ```css + * .ng-hide:not(.ng-hide-animate) { + * /* this is just another form of hiding an element */ + * display: block!important; + * position: absolute; + * top: -9999px; + * left: -9999px; + * } + * ``` + * + * By default you don't need to override in CSS anything and the animations will work around the display style. + * + * ## A note about animations with `ngShow` + * + * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression + * is true and false. This system works like the animation system present with ngClass except that + * you must also include the !important flag to override the display property + * so that you can perform an animation when the element is hidden during the time of the animation. + * + * ```css + * // + * //a working example can be found at the bottom of this page + * // + * .my-element.ng-hide-add, .my-element.ng-hide-remove { + * /* this is required as of 1.3x to properly + * apply all styling in a show/hide animation */ + * transition: 0s linear all; + * } + * + * .my-element.ng-hide-add-active, + * .my-element.ng-hide-remove-active { + * /* the transition is defined in the active class */ + * transition: 1s linear all; + * } + * + * .my-element.ng-hide-add { ... } + * .my-element.ng-hide-add.ng-hide-add-active { ... } + * .my-element.ng-hide-remove { ... } + * .my-element.ng-hide-remove.ng-hide-remove-active { ... } + * ``` + * + * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display + * property to block during animation states--ngAnimate will handle the style toggling automatically for you. + * + * @animations + * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible + * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden + * + * @element ANY + * @param {expression} ngShow If the {@link guide/expression expression} is truthy + * then the element is shown or hidden respectively. + * + * @example + <example module="ngAnimate" deps="angular-animate.js" animations="true"> + <file name="index.html"> + Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngHide"><br/> + <div> + Show: + <div class="check-element animate-show" ng-show="checked"> + <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked. + </div> + </div> + <div> + Hide: + <div class="check-element animate-show" ng-hide="checked"> + <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked. + </div> + </div> + </file> + <file name="glyphicons.css"> + @import url(../../components/bootstrap-3.1.1/css/bootstrap.css); + </file> + <file name="animations.css"> + .animate-show { + line-height: 20px; + opacity: 1; + padding: 10px; + border: 1px solid black; + background: white; } - } - $timeout.cancel(pendingDebounce); - if (debounceDelay) { - pendingDebounce = $timeout(function() { - ctrl.$commitViewValue(); - }, debounceDelay); - } else if ($rootScope.$$phase) { - ctrl.$commitViewValue(); - } else { - $scope.$apply(function() { - ctrl.$commitViewValue(); - }); - } - }; + .animate-show.ng-hide-add.ng-hide-add-active, + .animate-show.ng-hide-remove.ng-hide-remove-active { + -webkit-transition: all linear 0.5s; + transition: all linear 0.5s; + } - // model -> value - // Note: we cannot use a normal scope.$watch as we want to detect the following: - // 1. scope value is 'a' - // 2. user enters 'b' - // 3. ng-change kicks in and reverts scope value to 'a' - // -> scope value did not change since the last digest as - // ng-change executes in apply phase - // 4. view should be changed back to 'a' - $scope.$watch(function ngModelWatch() { - var modelValue = ngModelGet($scope); + .animate-show.ng-hide { + line-height: 0; + opacity: 0; + padding: 0 10px; + } - // if scope model value and ngModel value are out of sync - // TODO(perf): why not move this to the action fn? - if (modelValue !== ctrl.$modelValue) { - ctrl.$modelValue = ctrl.$$rawModelValue = modelValue; + .check-element { + padding: 10px; + border: 1px solid black; + background: white; + } + </file> + <file name="protractor.js" type="protractor"> + var thumbsUp = element(by.css('span.glyphicon-thumbs-up')); + var thumbsDown = element(by.css('span.glyphicon-thumbs-down')); - var formatters = ctrl.$formatters, - idx = formatters.length; + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); - var viewValue = modelValue; - while (idx--) { - viewValue = formatters[idx](viewValue); - } - if (ctrl.$viewValue !== viewValue) { - ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue; - ctrl.$render(); + element(by.model('checked')).click(); - ctrl.$$runValidators(undefined, modelValue, viewValue, noop); - } + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); + </file> + </example> + */ +var ngShowDirective = ['$animate', function($animate) { + return { + restrict: 'A', + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngShow, function ngShowWatchAction(value) { + // we're adding a temporary, animation-specific class for ng-hide since this way + // we can control when the element is actually displayed on screen without having + // to have a global/greedy CSS selector that breaks when other animations are run. + // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845 + $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); } - - return modelValue; - }); + }; }]; /** * @ngdoc directive - * @name ngModel - * - * @element input - * @priority 1 + * @name ngHide + * @multiElement * * @description - * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a - * property on the scope using {@link ngModel.NgModelController NgModelController}, - * which is created and exposed by this directive. - * - * `ngModel` is responsible for: + * The `ngHide` directive shows or hides the given HTML element based on the expression + * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding + * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined + * in AngularJS and sets the display style to none (using an !important flag). + * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). * - * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` - * require. - * - Providing validation behavior (i.e. required, number, email, url). - * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors). - * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations. - * - Registering the control with its parent {@link ng.directive:form form}. + * ```html + * <!-- when $scope.myValue is truthy (element is hidden) --> + * <div ng-hide="myValue" class="ng-hide"></div> * - * Note: `ngModel` will try to bind to the property given by evaluating the expression on the - * current scope. If the property doesn't already exist on this scope, it will be created - * implicitly and added to the scope. + * <!-- when $scope.myValue is falsy (element is visible) --> + * <div ng-hide="myValue"></div> + * ``` * - * For best practices on using `ngModel`, see: + * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class + * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed + * from the element causing the element not to appear hidden. * - * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) + * ## Why is !important used? * - * For basic examples, how to use `ngModel`, see: + * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector + * can be easily overridden by heavier selectors. For example, something as simple + * as changing the display style on a HTML list item would make hidden elements appear visible. + * This also becomes a bigger issue when dealing with CSS frameworks. * - * - {@link ng.directive:input input} - * - {@link input[text] text} - * - {@link input[checkbox] checkbox} - * - {@link input[radio] radio} - * - {@link input[number] number} - * - {@link input[email] email} - * - {@link input[url] url} - * - {@link input[date] date} - * - {@link input[datetime-local] datetime-local} - * - {@link input[time] time} - * - {@link input[month] month} - * - {@link input[week] week} - * - {@link ng.directive:select select} - * - {@link ng.directive:textarea textarea} + * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector + * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the + * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. * - * # CSS classes - * The following CSS classes are added and removed on the associated input/select/textarea element - * depending on the validity of the model. + * ### Overriding `.ng-hide` * - * - `ng-valid`: the model is valid - * - `ng-invalid`: the model is invalid - * - `ng-valid-[key]`: for each valid key added by `$setValidity` - * - `ng-invalid-[key]`: for each invalid key added by `$setValidity` - * - `ng-pristine`: the control hasn't been interacted with yet - * - `ng-dirty`: the control has been interacted with - * - `ng-touched`: the control has been blurred - * - `ng-untouched`: the control hasn't been blurred - * - `ng-pending`: any `$asyncValidators` are unfulfilled + * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change + * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide` + * class in CSS: * - * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * ```css + * .ng-hide { + * /* this is just another form of hiding an element */ + * display: block!important; + * position: absolute; + * top: -9999px; + * left: -9999px; + * } + * ``` * - * ## Animation Hooks + * By default you don't need to override in CSS anything and the animations will work around the display style. * - * Animations within models are triggered when any of the associated CSS classes are added and removed - * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`, - * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself. - * The animations that are triggered within ngModel are similar to how they work in ngClass and - * animations can be hooked into using CSS transitions, keyframes as well as JS animations. + * ## A note about animations with `ngHide` * - * The following example shows a simple way to utilize CSS transitions to style an input element - * that has been rendered as invalid after it has been validated: + * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression + * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide` + * CSS class is added and removed for you instead of your own CSS class. * - * <pre> - * //be sure to include ngAnimate as a module to hook into more - * //advanced animations - * .my-input { - * transition:0.5s linear all; - * background: white; - * } - * .my-input.ng-invalid { - * background: red; - * color:white; + * ```css + * // + * //a working example can be found at the bottom of this page + * // + * .my-element.ng-hide-add, .my-element.ng-hide-remove { + * transition: 0.5s linear all; * } - * </pre> + * + * .my-element.ng-hide-add { ... } + * .my-element.ng-hide-add.ng-hide-add-active { ... } + * .my-element.ng-hide-remove { ... } + * .my-element.ng-hide-remove.ng-hide-remove-active { ... } + * ``` + * + * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display + * property to block during animation states--ngAnimate will handle the style toggling automatically for you. + * + * @animations + * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden + * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible + * + * @element ANY + * @param {expression} ngHide If the {@link guide/expression expression} is truthy then + * the element is shown or hidden respectively. * * @example - * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample"> + <example module="ngAnimate" deps="angular-animate.js" animations="true"> + <file name="index.html"> + Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow"><br/> + <div> + Show: + <div class="check-element animate-hide" ng-show="checked"> + <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked. + </div> + </div> + <div> + Hide: + <div class="check-element animate-hide" ng-hide="checked"> + <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked. + </div> + </div> + </file> + <file name="glyphicons.css"> + @import url(../../components/bootstrap-3.1.1/css/bootstrap.css); + </file> + <file name="animations.css"> + .animate-hide { + -webkit-transition: all linear 0.5s; + transition: all linear 0.5s; + line-height: 20px; + opacity: 1; + padding: 10px; + border: 1px solid black; + background: white; + } + + .animate-hide.ng-hide { + line-height: 0; + opacity: 0; + padding: 0 10px; + } + + .check-element { + padding: 10px; + border: 1px solid black; + background: white; + } + </file> + <file name="protractor.js" type="protractor"> + var thumbsUp = element(by.css('span.glyphicon-thumbs-up')); + var thumbsDown = element(by.css('span.glyphicon-thumbs-down')); + + it('should check ng-show / ng-hide', function() { + expect(thumbsUp.isDisplayed()).toBeFalsy(); + expect(thumbsDown.isDisplayed()).toBeTruthy(); + + element(by.model('checked')).click(); + + expect(thumbsUp.isDisplayed()).toBeTruthy(); + expect(thumbsDown.isDisplayed()).toBeFalsy(); + }); + </file> + </example> + */ +var ngHideDirective = ['$animate', function($animate) { + return { + restrict: 'A', + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngHide, function ngHideWatchAction(value) { + // The comment inside of the ngShowDirective explains why we add and + // remove a temporary class for the show/hide animation + $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); + } + }; +}]; + +/** + * @ngdoc directive + * @name ngStyle + * @restrict AC + * + * @description + * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally. + * + * @element ANY + * @param {expression} ngStyle + * + * {@link guide/expression Expression} which evals to an + * object whose keys are CSS style names and values are corresponding values for those CSS + * keys. + * + * Since some CSS style names are not valid keys for an object, they must be quoted. + * See the 'background-color' style in the example below. + * + * @example + <example> <file name="index.html"> - <script> - angular.module('inputExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.val = '1'; - }]); - </script> - <style> - .my-input { - -webkit-transition:all linear 0.5s; - transition:all linear 0.5s; - background: transparent; - } - .my-input.ng-invalid { - color:white; - background: red; - } - </style> - Update input to see transitions when valid/invalid. - Integer is a valid value. - <form name="testForm" ng-controller="ExampleController"> - <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input" /> - </form> + <input type="button" value="set color" ng-click="myStyle={color:'red'}"> + <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}"> + <input type="button" value="clear" ng-click="myStyle={}"> + <br/> + <span ng-style="myStyle">Sample Text</span> + <pre>myStyle={{myStyle}}</pre> </file> - * </example> + <file name="style.css"> + span { + color: black; + } + </file> + <file name="protractor.js" type="protractor"> + var colorSpan = element(by.css('span')); + + it('should check ng-style', function() { + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + element(by.css('input[value=\'set color\']')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)'); + element(by.css('input[value=clear]')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + }); + </file> + </example> + */ +var ngStyleDirective = ngDirective(function(scope, element, attr) { + scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { + if (oldStyles && (newStyles !== oldStyles)) { + forEach(oldStyles, function(val, style) { element.css(style, '');}); + } + if (newStyles) element.css(newStyles); + }, true); +}); + +/** + * @ngdoc directive + * @name ngSwitch + * @restrict EA * - * ## Binding to a getter/setter + * @description + * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression. + * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location + * as specified in the template. * - * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a - * function that returns a representation of the model when called with zero arguments, and sets - * the internal state of a model when called with an argument. It's sometimes useful to use this - * for models that have an internal representation that's different than what the model exposes - * to the view. + * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it + * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element + * matches the value obtained from the evaluated expression. In other words, you define a container element + * (where you place the directive), place an expression on the **`on="..."` attribute** + * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place + * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on + * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default + * attribute is displayed. * - * <div class="alert alert-success"> - * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more - * frequently than other parts of your code. + * <div class="alert alert-info"> + * Be aware that the attribute values to match against cannot be expressions. They are interpreted + * as literal string values to match against. + * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the + * value of the expression `$scope.someVal`. * </div> + + * @animations + * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container + * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM * - * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that - * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to - * a `<form>`, which will enable this behavior for all `<input>`s within it. See - * {@link ng.directive:ngModelOptions `ngModelOptions`} for more. + * @usage + * + * ``` + * <ANY ng-switch="expression"> + * <ANY ng-switch-when="matchValue1">...</ANY> + * <ANY ng-switch-when="matchValue2">...</ANY> + * <ANY ng-switch-default>...</ANY> + * </ANY> + * ``` + * + * + * @scope + * @priority 1200 + * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>. + * On child elements add: + * + * * `ngSwitchWhen`: the case statement to match against. If match then this + * case will be displayed. If the same match appears multiple times, all the + * elements will be displayed. + * * `ngSwitchDefault`: the default case when no other case match. If there + * are multiple default cases, all of them will be displayed when no other + * case match. * - * The following example shows how to use `ngModel` with a getter/setter: * * @example - * <example name="ngModel-getter-setter" module="getterSetterExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ getterSetter: true }" /> - </form> - <pre>user.name = <span ng-bind="user.name()"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('getterSetterExample', []) - .controller('ExampleController', ['$scope', function($scope) { - var _name = 'Brian'; - $scope.user = { - name: function(newName) { - if (angular.isDefined(newName)) { - _name = newName; - } - return _name; - } - }; - }]); - </file> - * </example> + <example module="switchExample" deps="angular-animate.js" animations="true"> + <file name="index.html"> + <div ng-controller="ExampleController"> + <select ng-model="selection" ng-options="item for item in items"> + </select> + <code>selection={{selection}}</code> + <hr/> + <div class="animate-switch-container" + ng-switch on="selection"> + <div class="animate-switch" ng-switch-when="settings">Settings Div</div> + <div class="animate-switch" ng-switch-when="home">Home Span</div> + <div class="animate-switch" ng-switch-default>default</div> + </div> + </div> + </file> + <file name="script.js"> + angular.module('switchExample', ['ngAnimate']) + .controller('ExampleController', ['$scope', function($scope) { + $scope.items = ['settings', 'home', 'other']; + $scope.selection = $scope.items[0]; + }]); + </file> + <file name="animations.css"> + .animate-switch-container { + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .animate-switch { + padding:10px; + } + + .animate-switch.ng-animate { + -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + } + + .animate-switch.ng-leave.ng-leave-active, + .animate-switch.ng-enter { + top:-50px; + } + .animate-switch.ng-leave, + .animate-switch.ng-enter.ng-enter-active { + top:0; + } + </file> + <file name="protractor.js" type="protractor"> + var switchElem = element(by.css('[ng-switch]')); + var select = element(by.model('selection')); + + it('should start in settings', function() { + expect(switchElem.getText()).toMatch(/Settings Div/); + }); + it('should change to home', function() { + select.all(by.css('option')).get(1).click(); + expect(switchElem.getText()).toMatch(/Home Span/); + }); + it('should select default', function() { + select.all(by.css('option')).get(2).click(); + expect(switchElem.getText()).toMatch(/default/); + }); + </file> + </example> */ -var ngModelDirective = ['$rootScope', function($rootScope) { +var ngSwitchDirective = ['$animate', function($animate) { return { - restrict: 'A', - require: ['ngModel', '^?form', '^?ngModelOptions'], - controller: NgModelController, - // Prelink needs to run before any input directive - // so that we can set the NgModelOptions in NgModelController - // before anyone else uses it. - priority: 1, - compile: function ngModelCompile(element) { - // Setup initial state of the control - element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); + require: 'ngSwitch', - return { - pre: function ngModelPreLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0], - formCtrl = ctrls[1] || nullFormCtrl; + // asks for $scope to fool the BC controller module + controller: ['$scope', function ngSwitchController() { + this.cases = {}; + }], + link: function(scope, element, attr, ngSwitchController) { + var watchExpr = attr.ngSwitch || attr.on, + selectedTranscludes = [], + selectedElements = [], + previousLeaveAnimations = [], + selectedScopes = []; - modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options); + var spliceFactory = function(array, index) { + return function() { array.splice(index, 1); }; + }; - // notify others, especially parent forms - formCtrl.$addControl(modelCtrl); + scope.$watch(watchExpr, function ngSwitchWatchAction(value) { + var i, ii; + for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) { + $animate.cancel(previousLeaveAnimations[i]); + } + previousLeaveAnimations.length = 0; - attr.$observe('name', function(newValue) { - if (modelCtrl.$name !== newValue) { - formCtrl.$$renameControl(modelCtrl, newValue); - } - }); + for (i = 0, ii = selectedScopes.length; i < ii; ++i) { + var selected = getBlockNodes(selectedElements[i].clone); + selectedScopes[i].$destroy(); + var promise = previousLeaveAnimations[i] = $animate.leave(selected); + promise.then(spliceFactory(previousLeaveAnimations, i)); + } - scope.$on('$destroy', function() { - formCtrl.$removeControl(modelCtrl); - }); - }, - post: function ngModelPostLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0]; - if (modelCtrl.$options && modelCtrl.$options.updateOn) { - element.on(modelCtrl.$options.updateOn, function(ev) { - modelCtrl.$$debounceViewValueCommit(ev && ev.type); - }); - } + selectedElements.length = 0; + selectedScopes.length = 0; - element.on('blur', function(ev) { - if (modelCtrl.$touched) return; + if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) { + forEach(selectedTranscludes, function(selectedTransclude) { + selectedTransclude.transclude(function(caseElement, selectedScope) { + selectedScopes.push(selectedScope); + var anchor = selectedTransclude.element; + caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: '); + var block = { clone: caseElement }; - if ($rootScope.$$phase) { - scope.$evalAsync(modelCtrl.$setTouched); - } else { - scope.$apply(modelCtrl.$setTouched); - } + selectedElements.push(block); + $animate.enter(caseElement, anchor.parent(), anchor); + }); }); } - }; + }); } }; }]; -var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; +var ngSwitchWhenDirective = ngDirective({ + transclude: 'element', + priority: 1200, + require: '^ngSwitch', + multiElement: true, + link: function(scope, element, attrs, ctrl, $transclude) { + ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []); + ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element }); + } +}); + +var ngSwitchDefaultDirective = ngDirective({ + transclude: 'element', + priority: 1200, + require: '^ngSwitch', + multiElement: true, + link: function(scope, element, attr, ctrl, $transclude) { + ctrl.cases['?'] = (ctrl.cases['?'] || []); + ctrl.cases['?'].push({ transclude: $transclude, element: element }); + } +}); /** * @ngdoc directive - * @name ngModelOptions + * @name ngTransclude + * @restrict EAC * * @description - * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of - * events that will trigger a model update and/or a debouncing delay so that the actual update only - * takes place when a timer expires; this timer will be reset after another change takes place. + * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion. * - * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might - * be different than the value in the actual model. This means that if you update the model you - * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in - * order to make sure it is synchronized with the model and that any debounced action is canceled. + * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted. * - * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`} - * method is by making sure the input is placed inside a form that has a `name` attribute. This is - * important because `form` controllers are published to the related scope under the name in their - * `name` attribute. + * @element ANY * - * Any pending changes will take place immediately when an enclosing form is submitted via the - * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` - * to have access to the updated model. + * @example + <example module="transcludeExample"> + <file name="index.html"> + <script> + angular.module('transcludeExample', []) + .directive('pane', function(){ + return { + restrict: 'E', + transclude: true, + scope: { title:'@' }, + template: '<div style="border: 1px solid black;">' + + '<div style="background-color: gray">{{title}}</div>' + + '<ng-transclude></ng-transclude>' + + '</div>' + }; + }) + .controller('ExampleController', ['$scope', function($scope) { + $scope.title = 'Lorem Ipsum'; + $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...'; + }]); + </script> + <div ng-controller="ExampleController"> + <input ng-model="title" aria-label="title"> <br/> + <textarea ng-model="text" aria-label="text"></textarea> <br/> + <pane title="{{title}}">{{text}}</pane> + </div> + </file> + <file name="protractor.js" type="protractor"> + it('should have transcluded', function() { + var titleElement = element(by.model('title')); + titleElement.clear(); + titleElement.sendKeys('TITLE'); + var textElement = element(by.model('text')); + textElement.clear(); + textElement.sendKeys('TEXT'); + expect(element(by.binding('title')).getText()).toEqual('TITLE'); + expect(element(by.binding('text')).getText()).toEqual('TEXT'); + }); + </file> + </example> * - * `ngModelOptions` has an effect on the element it's declared on and its descendants. + */ +var ngTranscludeDirective = ngDirective({ + restrict: 'EAC', + link: function($scope, $element, $attrs, controller, $transclude) { + if (!$transclude) { + throw minErr('ngTransclude')('orphan', + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + + $transclude(function(clone) { + $element.empty(); + $element.append(clone); + }); + } +}); + +/** + * @ngdoc directive + * @name script + * @restrict E * - * @param {Object} ngModelOptions options to apply to the current model. Valid keys are: - * - `updateOn`: string specifying which event should the input be bound to. You can set several - * events using an space delimited list. There is a special event called `default` that - * matches the default events belonging of the control. - * - `debounce`: integer value which contains the debounce model update value in milliseconds. A - * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a - * custom value for each event. For example: - * `ng-model-options="{ updateOn: 'default blur', debounce: {'default': 500, 'blur': 0} }"` - * - `allowInvalid`: boolean value which indicates that the model can be set with values that did - * not validate correctly instead of the default behavior of setting the model to undefined. - * - `getterSetter`: boolean value which determines whether or not to treat functions bound to - `ngModel` as getters/setters. - * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for - * `<input type="date">`, `<input type="time">`, ... . Right now, the only supported value is `'UTC'`, - * otherwise the default timezone of the browser will be used. + * @description + * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the + * template can be used by {@link ng.directive:ngInclude `ngInclude`}, + * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the + * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be + * assigned through the element's `id`, which can then be used as a directive's `templateUrl`. + * + * @param {string} type Must be set to `'text/ng-template'`. + * @param {string} id Cache name of the template. * * @example - - The following example shows how to override immediate updates. Changes on the inputs within the - form will update the model only when the control loses focus (blur event). If `escape` key is - pressed while the input field is focused, the value is reset to the value in the current model. - - <example name="ngModelOptions-directive-blur" module="optionsExample"> + <example> <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ updateOn: 'blur' }" - ng-keyup="cancel($event)" /><br /> - - Other data: - <input type="text" ng-model="user.data" /><br /> - </form> - <pre>user.name = <span ng-bind="user.name"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('optionsExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.user = { name: 'say', data: '' }; + <script type="text/ng-template" id="/tpl.html"> + Content of the template. + </script> - $scope.cancel = function(e) { - if (e.keyCode == 27) { - $scope.userForm.userName.$rollbackViewValue(); - } - }; - }]); + <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a> + <div id="tpl-content" ng-include src="currentTpl"></div> </file> <file name="protractor.js" type="protractor"> - var model = element(by.binding('user.name')); - var input = element(by.model('user.name')); - var other = element(by.model('user.data')); - - it('should allow custom events', function() { - input.sendKeys(' hello'); - input.click(); - expect(model.getText()).toEqual('say'); - other.click(); - expect(model.getText()).toEqual('say hello'); - }); - - it('should $rollbackViewValue when model changes', function() { - input.sendKeys(' hello'); - expect(input.getAttribute('value')).toEqual('say hello'); - input.sendKeys(protractor.Key.ESCAPE); - expect(input.getAttribute('value')).toEqual('say'); - other.click(); - expect(model.getText()).toEqual('say'); + it('should load template defined inside script tag', function() { + element(by.css('#tpl-link')).click(); + expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); }); </file> </example> - - This one shows how to debounce model changes. Model will be updated only 1 sec after last change. - If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty. - - <example name="ngModelOptions-directive-debounce" module="optionsExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ debounce: 1000 }" /> - <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button><br /> - </form> - <pre>user.name = <span ng-bind="user.name"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('optionsExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.user = { name: 'say' }; - }]); - </file> - </example> - - This one shows how to bind to getter/setters: - - <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <form name="userForm"> - Name: - <input type="text" name="userName" - ng-model="user.name" - ng-model-options="{ getterSetter: true }" /> - </form> - <pre>user.name = <span ng-bind="user.name()"></span></pre> - </div> - </file> - <file name="app.js"> - angular.module('getterSetterExample', []) - .controller('ExampleController', ['$scope', function($scope) { - var _name = 'Brian'; - $scope.user = { - name: function(newName) { - return angular.isDefined(newName) ? (_name = newName) : _name; - } - }; - }]); - </file> - </example> */ -var ngModelOptionsDirective = function() { +var scriptDirective = ['$templateCache', function($templateCache) { return { - restrict: 'A', - controller: ['$scope', '$attrs', function($scope, $attrs) { - var that = this; - this.$options = $scope.$eval($attrs.ngModelOptions); - // Allow adding/overriding bound events - if (this.$options.updateOn !== undefined) { - this.$options.updateOnDefault = false; - // extract "default" pseudo-event from list of events that can trigger a model update - this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() { - that.$options.updateOnDefault = true; - return ' '; - })); - } else { - this.$options.updateOnDefault = true; + restrict: 'E', + terminal: true, + compile: function(element, attr) { + if (attr.type == 'text/ng-template') { + var templateUrl = attr.id, + text = element[0].text; + + $templateCache.put(templateUrl, text); } - }] + } }; -}; +}]; +var noopNgModelController = { $setViewValue: noop, $render: noop }; +/** + * @ngdoc type + * @name select.SelectController + * @description + * The controller for the `<select>` directive. This provides support for reading + * and writing the selected value(s) of the control and also coordinates dynamically + * added `<option>` elements, perhaps by an `ngRepeat` directive. + */ +var SelectController = + ['$element', '$scope', '$attrs', function($element, $scope, $attrs) { -// helper methods -function addSetValidityMethod(context) { - var ctrl = context.ctrl, - $element = context.$element, - classCache = {}, - set = context.set, - unset = context.unset, - parentForm = context.parentForm, - $animate = context.$animate; + var self = this, + optionsMap = new HashMap(); - classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS)); + // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors + self.ngModelCtrl = noopNgModelController; - ctrl.$setValidity = setValidity; + // The "unknown" option is one that is prepended to the list if the viewValue + // does not match any of the options. When it is rendered the value of the unknown + // option is '? XXX ?' where XXX is the hashKey of the value that is not known. + // + // We can't just jqLite('<option>') since jqLite is not smart enough + // to create it in <select> and IE barfs otherwise. + self.unknownOption = jqLite(document.createElement('option')); + self.renderUnknownOption = function(val) { + var unknownVal = '? ' + hashKey(val) + ' ?'; + self.unknownOption.val(unknownVal); + $element.prepend(self.unknownOption); + $element.val(unknownVal); + }; - function setValidity(validationErrorKey, state, controller) { - if (state === undefined) { - createAndSet('$pending', validationErrorKey, controller); - } else { - unsetAndCleanup('$pending', validationErrorKey, controller); - } - if (!isBoolean(state)) { - unset(ctrl.$error, validationErrorKey, controller); - unset(ctrl.$$success, validationErrorKey, controller); - } else { - if (state) { - unset(ctrl.$error, validationErrorKey, controller); - set(ctrl.$$success, validationErrorKey, controller); - } else { - set(ctrl.$error, validationErrorKey, controller); - unset(ctrl.$$success, validationErrorKey, controller); - } - } - if (ctrl.$pending) { - cachedToggleClass(PENDING_CLASS, true); - ctrl.$valid = ctrl.$invalid = undefined; - toggleValidationCss('', null); - } else { - cachedToggleClass(PENDING_CLASS, false); - ctrl.$valid = isObjectEmpty(ctrl.$error); - ctrl.$invalid = !ctrl.$valid; - toggleValidationCss('', ctrl.$valid); - } + $scope.$on('$destroy', function() { + // disable unknown option so that we don't do work when the whole select is being destroyed + self.renderUnknownOption = noop; + }); - // re-read the state as the set/unset methods could have - // combined state in ctrl.$error[validationError] (used for forms), - // where setting/unsetting only increments/decrements the value, - // and does not replace it. - var combinedState; - if (ctrl.$pending && ctrl.$pending[validationErrorKey]) { - combinedState = undefined; - } else if (ctrl.$error[validationErrorKey]) { - combinedState = false; - } else if (ctrl.$$success[validationErrorKey]) { - combinedState = true; - } else { - combinedState = null; - } + self.removeUnknownOption = function() { + if (self.unknownOption.parent()) self.unknownOption.remove(); + }; - toggleValidationCss(validationErrorKey, combinedState); - parentForm.$setValidity(validationErrorKey, combinedState, ctrl); - } - function createAndSet(name, value, controller) { - if (!ctrl[name]) { - ctrl[name] = {}; - } - set(ctrl[name], value, controller); - } + // Read the value of the select control, the implementation of this changes depending + // upon whether the select can have multiple values and whether ngOptions is at work. + self.readValue = function readSingleValue() { + self.removeUnknownOption(); + return $element.val(); + }; - function unsetAndCleanup(name, value, controller) { - if (ctrl[name]) { - unset(ctrl[name], value, controller); - } - if (isObjectEmpty(ctrl[name])) { - ctrl[name] = undefined; - } - } - function cachedToggleClass(className, switchValue) { - if (switchValue && !classCache[className]) { - $animate.addClass($element, className); - classCache[className] = true; - } else if (!switchValue && classCache[className]) { - $animate.removeClass($element, className); - classCache[className] = false; + // Write the value to the select control, the implementation of this changes depending + // upon whether the select can have multiple values and whether ngOptions is at work. + self.writeValue = function writeSingleValue(value) { + if (self.hasOption(value)) { + self.removeUnknownOption(); + $element.val(value); + if (value === '') self.emptyOption.prop('selected', true); // to make IE9 happy + } else { + if (value == null && self.emptyOption) { + self.removeUnknownOption(); + $element.val(''); + } else { + self.renderUnknownOption(value); + } } - } - - function toggleValidationCss(validationErrorKey, isValid) { - validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; + }; - cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true); - cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false); - } -} -function isObjectEmpty(obj) { - if (obj) { - for (var prop in obj) { - return false; + // Tell the select control that an option, with the given value, has been added + self.addOption = function(value, element) { + assertNotHasOwnProperty(value, '"option value"'); + if (value === '') { + self.emptyOption = element; } - } - return true; -} - -/** - * @ngdoc directive - * @name ngNonBindable - * @restrict AC - * @priority 1000 - * - * @description - * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current - * DOM element. This is useful if the element contains what appears to be Angular directives and - * bindings but which should be ignored by Angular. This could be the case if you have a site that - * displays snippets of code, for instance. - * - * @element ANY - * - * @example - * In this example there are two locations where a simple interpolation binding (`{{}}`) is present, - * but the one wrapped in `ngNonBindable` is left alone. - * - * @example - <example> - <file name="index.html"> - <div>Normal: {{1 + 2}}</div> - <div ng-non-bindable>Ignored: {{1 + 2}}</div> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-non-bindable', function() { - expect(element(by.binding('1 + 2')).getText()).toContain('3'); - expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/); - }); - </file> - </example> - */ -var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); + var count = optionsMap.get(value) || 0; + optionsMap.put(value, count + 1); + }; + + // Tell the select control that an option, with the given value, has been removed + self.removeOption = function(value) { + var count = optionsMap.get(value); + if (count) { + if (count === 1) { + optionsMap.remove(value); + if (value === '') { + self.emptyOption = undefined; + } + } else { + optionsMap.put(value, count - 1); + } + } + }; + + // Check whether the select control has an option matching the given value + self.hasOption = function(value) { + return !!optionsMap.get(value); + }; +}]; /** * @ngdoc directive - * @name ngPluralize - * @restrict EA + * @name select + * @restrict E * * @description - * `ngPluralize` is a directive that displays messages according to en-US localization rules. - * These rules are bundled with angular.js, but can be overridden - * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive - * by specifying the mappings between - * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) - * and the strings to be displayed. - * - * # Plural categories and explicit number rules - * There are two - * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html) - * in Angular's default en-US locale: "one" and "other". - * - * While a plural category may match many numbers (for example, in en-US locale, "other" can match - * any number that is not 1), an explicit number rule can only match one number. For example, the - * explicit number rule for "3" matches the number 3. There are examples of plural categories - * and explicit number rules throughout the rest of this documentation. - * - * # Configuring ngPluralize - * You configure ngPluralize by providing 2 attributes: `count` and `when`. - * You can also provide an optional attribute, `offset`. - * - * The value of the `count` attribute can be either a string or an {@link guide/expression - * Angular expression}; these are evaluated on the current scope for its bound value. - * - * The `when` attribute specifies the mappings between plural categories and the actual - * string to be displayed. The value of the attribute should be a JSON object. - * - * The following example shows how to configure ngPluralize: - * - * ```html - * <ng-pluralize count="personCount" - when="{'0': 'Nobody is viewing.', - * 'one': '1 person is viewing.', - * 'other': '{} people are viewing.'}"> - * </ng-pluralize> - *``` + * HTML `SELECT` element with angular data-binding. * - * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not - * specify this rule, 0 would be matched to the "other" category and "0 people are viewing" - * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for - * other numbers, for example 12, so that instead of showing "12 people are viewing", you can - * show "a dozen people are viewing". + * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions + * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits such as reducing + * memory and increasing speed by not creating a new scope for each repeated instance, as well as providing + * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the + * comprehension expression. * - * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted - * into pluralized strings. In the previous example, Angular will replace `{}` with - * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder - * for <span ng-non-bindable>{{numberExpression}}</span>. + * When an item in the `<select>` menu is selected, the array element or object property + * represented by the selected option will be bound to the model identified by the `ngModel` + * directive. * - * # Configuring ngPluralize with offset - * The `offset` attribute allows further customization of pluralized text, which can result in - * a better user experience. For example, instead of the message "4 people are viewing this document", - * you might display "John, Kate and 2 others are viewing this document". - * The offset attribute allows you to offset a number by any desired value. - * Let's take a look at an example: + * If the viewValue contains a value that doesn't match any of the options then the control + * will automatically add an "unknown" option, which it then removes when this is resolved. * - * ```html - * <ng-pluralize count="personCount" offset=2 - * when="{'0': 'Nobody is viewing.', - * '1': '{{person1}} is viewing.', - * '2': '{{person1}} and {{person2}} are viewing.', - * 'one': '{{person1}}, {{person2}} and one other person are viewing.', - * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}"> - * </ng-pluralize> - * ``` + * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can + * be nested into the `<select>` element. This element will then represent the `null` or "not selected" + * option. See example below for demonstration. * - * Notice that we are still using two plural categories(one, other), but we added - * three explicit number rules 0, 1 and 2. - * When one person, perhaps John, views the document, "John is viewing" will be shown. - * When three people view the document, no explicit number rule is found, so - * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category. - * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing" - * is shown. + * <div class="alert alert-info"> + * The value of a `select` directive used without `ngOptions` is always a string. + * When the model needs to be bound to a non-string value, you must either explictly convert it + * using a directive (see example below) or use `ngOptions` to specify the set of options. + * This is because an option element can only be bound to string values at present. + * </div> * - * Note that when you specify offsets, you must provide explicit number rules for - * numbers from 0 up to and including the offset. If you use an offset of 3, for example, - * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for - * plural categories "one" and "other". + * ### Example (binding `select` to a non-string value) * - * @param {string|expression} count The variable to be bound to. - * @param {string} when The mapping between plural category to its corresponding strings. - * @param {number=} offset Offset to deduct from the total number. + * <example name="select-with-non-string-options" module="nonStringSelect"> + * <file name="index.html"> + * <select ng-model="model.id" convert-to-number> + * <option value="0">Zero</option> + * <option value="1">One</option> + * <option value="2">Two</option> + * </select> + * {{ model }} + * </file> + * <file name="app.js"> + * angular.module('nonStringSelect', []) + * .run(function($rootScope) { + * $rootScope.model = { id: 2 }; + * }) + * .directive('convertToNumber', function() { + * return { + * require: 'ngModel', + * link: function(scope, element, attrs, ngModel) { + * ngModel.$parsers.push(function(val) { + * return parseInt(val, 10); + * }); + * ngModel.$formatters.push(function(val) { + * return '' + val; + * }); + * } + * }; + * }); + * </file> + * <file name="protractor.js" type="protractor"> + * it('should initialize to model', function() { + * var select = element(by.css('select')); + * expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two'); + * }); + * </file> + * </example> * - * @example - <example module="pluralizeExample"> - <file name="index.html"> - <script> - angular.module('pluralizeExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.person1 = 'Igor'; - $scope.person2 = 'Misko'; - $scope.personCount = 1; - }]); - </script> - <div ng-controller="ExampleController"> - Person 1:<input type="text" ng-model="person1" value="Igor" /><br/> - Person 2:<input type="text" ng-model="person2" value="Misko" /><br/> - Number of People:<input type="text" ng-model="personCount" value="1" /><br/> + */ +var selectDirective = function() { - <!--- Example with simple pluralization rules for en locale ---> - Without Offset: - <ng-pluralize count="personCount" - when="{'0': 'Nobody is viewing.', - 'one': '1 person is viewing.', - 'other': '{} people are viewing.'}"> - </ng-pluralize><br> + return { + restrict: 'E', + require: ['select', '?ngModel'], + controller: SelectController, + link: function(scope, element, attr, ctrls) { - <!--- Example with offset ---> - With Offset(2): - <ng-pluralize count="personCount" offset=2 - when="{'0': 'Nobody is viewing.', - '1': '{{person1}} is viewing.', - '2': '{{person1}} and {{person2}} are viewing.', - 'one': '{{person1}}, {{person2}} and one other person are viewing.', - 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}"> - </ng-pluralize> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should show correct pluralized string', function() { - var withoutOffset = element.all(by.css('ng-pluralize')).get(0); - var withOffset = element.all(by.css('ng-pluralize')).get(1); - var countInput = element(by.model('personCount')); + // if ngModel is not defined, we don't need to do anything + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; - expect(withoutOffset.getText()).toEqual('1 person is viewing.'); - expect(withOffset.getText()).toEqual('Igor is viewing.'); + var selectCtrl = ctrls[0]; - countInput.clear(); - countInput.sendKeys('0'); + selectCtrl.ngModelCtrl = ngModelCtrl; - expect(withoutOffset.getText()).toEqual('Nobody is viewing.'); - expect(withOffset.getText()).toEqual('Nobody is viewing.'); + // We delegate rendering to the `writeValue` method, which can be changed + // if the select can have multiple selected values or if the options are being + // generated by `ngOptions` + ngModelCtrl.$render = function() { + selectCtrl.writeValue(ngModelCtrl.$viewValue); + }; - countInput.clear(); - countInput.sendKeys('2'); + // When the selected item(s) changes we delegate getting the value of the select control + // to the `readValue` method, which can be changed if the select can have multiple + // selected values or if the options are being generated by `ngOptions` + element.on('change', function() { + scope.$apply(function() { + ngModelCtrl.$setViewValue(selectCtrl.readValue()); + }); + }); - expect(withoutOffset.getText()).toEqual('2 people are viewing.'); - expect(withOffset.getText()).toEqual('Igor and Misko are viewing.'); + // If the select allows multiple values then we need to modify how we read and write + // values from and to the control; also what it means for the value to be empty and + // we have to add an extra watch since ngModel doesn't work well with arrays - it + // doesn't trigger rendering if only an item in the array changes. + if (attr.multiple) { + + // Read value now needs to check each option to see if it is selected + selectCtrl.readValue = function readMultipleValue() { + var array = []; + forEach(element.find('option'), function(option) { + if (option.selected) { + array.push(option.value); + } + }); + return array; + }; - countInput.clear(); - countInput.sendKeys('3'); + // Write value now needs to set the selected property of each matching option + selectCtrl.writeValue = function writeMultipleValue(value) { + var items = new HashMap(value); + forEach(element.find('option'), function(option) { + option.selected = isDefined(items.get(option.value)); + }); + }; - expect(withoutOffset.getText()).toEqual('3 people are viewing.'); - expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.'); + // we have to do it on each watch since ngModel watches reference, but + // we need to work of an array, so we need to see if anything was inserted/removed + var lastView, lastViewRef = NaN; + scope.$watch(function selectMultipleWatch() { + if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { + lastView = shallowCopy(ngModelCtrl.$viewValue); + ngModelCtrl.$render(); + } + lastViewRef = ngModelCtrl.$viewValue; + }); - countInput.clear(); - countInput.sendKeys('4'); + // If we are a multiple select then value is now a collection + // so the meaning of $isEmpty changes + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; - expect(withoutOffset.getText()).toEqual('4 people are viewing.'); - expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.'); - }); - it('should show data-bound names', function() { - var withOffset = element.all(by.css('ng-pluralize')).get(1); - var personCount = element(by.model('personCount')); - var person1 = element(by.model('person1')); - var person2 = element(by.model('person2')); - personCount.clear(); - personCount.sendKeys('4'); - person1.clear(); - person1.sendKeys('Di'); - person2.clear(); - person2.sendKeys('Vojta'); - expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.'); - }); - </file> - </example> - */ -var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) { - var BRACE = /{}/g, - IS_WHEN = /^when(Minus)?(.+)$/; + } + } + }; +}; + + +// The option directive is purely designed to communicate the existence (or lack of) +// of dynamically created (and destroyed) option elements to their containing select +// directive via its controller. +var optionDirective = ['$interpolate', function($interpolate) { + + function chromeHack(optionElement) { + // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 + // Adding an <option selected="selected"> element to a <select required="required"> should + // automatically select the new element + if (optionElement[0].hasAttribute('selected')) { + optionElement[0].selected = true; + } + } return { - restrict: 'EA', - link: function(scope, element, attr) { - var numberExp = attr.count, - whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs - offset = attr.offset || 0, - whens = scope.$eval(whenExp) || {}, - whensExpFns = {}, - startSymbol = $interpolate.startSymbol(), - endSymbol = $interpolate.endSymbol(), - braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol, - watchRemover = angular.noop, - lastCount; + restrict: 'E', + priority: 100, + compile: function(element, attr) { - forEach(attr, function(expression, attributeName) { - var tmpMatch = IS_WHEN.exec(attributeName); - if (tmpMatch) { - var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]); - whens[whenKey] = element.attr(attr.$attr[attributeName]); + // If the value attribute is not defined then we fall back to the + // text content of the option element, which may be interpolated + if (isUndefined(attr.value)) { + var interpolateFn = $interpolate(element.text(), true); + if (!interpolateFn) { + attr.$set('value', element.text()); } - }); - forEach(whens, function(expression, key) { - whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement)); + } + + return function(scope, element, attr) { + + // This is an optimization over using ^^ since we don't want to have to search + // all the way to the root of the DOM for every single option element + var selectCtrlName = '$selectController', + parent = element.parent(), + selectCtrl = parent.data(selectCtrlName) || + parent.parent().data(selectCtrlName); // in case we are in optgroup + + // Only update trigger option updates if this is an option within a `select` + // that also has `ngModel` attached + if (selectCtrl && selectCtrl.ngModelCtrl) { + + if (interpolateFn) { + scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) { + attr.$set('value', newVal); + if (oldVal !== newVal) { + selectCtrl.removeOption(oldVal); + } + selectCtrl.addOption(newVal, element); + selectCtrl.ngModelCtrl.$render(); + chromeHack(element); + }); + } else { + selectCtrl.addOption(attr.value, element); + selectCtrl.ngModelCtrl.$render(); + chromeHack(element); + } + + element.on('$destroy', function() { + selectCtrl.removeOption(attr.value); + selectCtrl.ngModelCtrl.$render(); + }); + } + }; + } + }; +}]; + +var styleDirective = valueFn({ + restrict: 'E', + terminal: false +}); + +var requiredDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + attr.required = true; // force truthy in case we are on non input element + + ctrl.$validators.required = function(modelValue, viewValue) { + return !attr.required || !ctrl.$isEmpty(viewValue); + }; + attr.$observe('required', function() { + ctrl.$validate(); }); + } + }; +}; - scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) { - var count = parseFloat(newVal); - var countIsNaN = isNaN(count); - if (!countIsNaN && !(count in whens)) { - // If an explicit number rule such as 1, 2, 3... is defined, just use it. - // Otherwise, check it against pluralization rules in $locale service. - count = $locale.pluralCat(count - offset); +var patternDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var regexp, patternExp = attr.ngPattern || attr.pattern; + attr.$observe('pattern', function(regex) { + if (isString(regex) && regex.length > 0) { + regex = new RegExp('^' + regex + '$'); } - // If both `count` and `lastCount` are NaN, we don't need to re-register a watch. - // In JS `NaN !== NaN`, so we have to exlicitly check. - if ((count !== lastCount) && !(countIsNaN && isNaN(lastCount))) { - watchRemover(); - watchRemover = scope.$watch(whensExpFns[count], updateElementText); - lastCount = count; + if (regex && !regex.test) { + throw minErr('ngPattern')('noregexp', + 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp, + regex, startingTag(elm)); } + + regexp = regex || undefined; + ctrl.$validate(); }); - function updateElementText(newText) { - element.text(newText || ''); - } + ctrl.$validators.pattern = function(value) { + return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value); + }; } }; -}]; +}; -/** - * @ngdoc directive - * @name ngRepeat - * - * @description - * The `ngRepeat` directive instantiates a template once per item from a collection. Each template - * instance gets its own scope, where the given loop variable is set to the current collection item, - * and `$index` is set to the item index or key. - * - * Special properties are exposed on the local scope of each template instance, including: - * - * | Variable | Type | Details | - * |-----------|-----------------|-----------------------------------------------------------------------------| - * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) | - * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. | - * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. | - * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. | - * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). | - * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). | - * - * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}. - * This may be useful when, for instance, nesting ngRepeats. - * - * # Iterating over object properties - * - * It is possible to get `ngRepeat` to iterate over the properties of an object using the following - * syntax: - * - * ```js - * <div ng-repeat="(key, value) in myObj"> ... </div> - * ``` - * - * You need to be aware that the JavaScript specification does not define what order - * it will return the keys for an object. In order to have a guaranteed deterministic order - * for the keys, Angular versions up to and including 1.3 **sort the keys alphabetically**. - * - * If this is not desired, the recommended workaround is to convert your object into an array - * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could - * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter) - * or implement a `$watch` on the object yourself. - * - * In version 1.4 we will remove the sorting, since it seems that browsers generally follow the - * strategy of providing keys in the order in which they were defined, although there are exceptions - * when keys are deleted and reinstated. - * - * - * # Special repeat start and end points - * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending - * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively. - * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on) - * up to and including the ending HTML tag where **ng-repeat-end** is placed. - * - * The example below makes use of this feature: - * ```html - * <header ng-repeat-start="item in items"> - * Header {{ item }} - * </header> - * <div class="body"> - * Body {{ item }} - * </div> - * <footer ng-repeat-end> - * Footer {{ item }} - * </footer> - * ``` - * - * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to: - * ```html - * <header> - * Header A - * </header> - * <div class="body"> - * Body A - * </div> - * <footer> - * Footer A - * </footer> - * <header> - * Header B - * </header> - * <div class="body"> - * Body B - * </div> - * <footer> - * Footer B - * </footer> - * ``` - * - * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such - * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**). - * - * @animations - * **.enter** - when a new item is added to the list or when an item is revealed after a filter - * - * **.leave** - when an item is removed from the list or when an item is filtered out - * - * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered - * - * @element ANY - * @scope - * @priority 1000 - * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These - * formats are currently supported: - * - * * `variable in expression` – where variable is the user defined loop variable and `expression` - * is a scope expression giving the collection to enumerate. - * - * For example: `album in artist.albums`. - * - * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers, - * and `expression` is the scope expression giving the collection to enumerate. - * - * For example: `(name, age) in {'adam':10, 'amalie':12}`. - * - * * `variable in expression track by tracking_expression` – You can also provide an optional tracking function - * which can be used to associate the objects in the collection with the DOM elements. If no tracking function - * is specified the ng-repeat associates elements by identity in the collection. It is an error to have - * more than one tracking function to resolve to the same key. (This would mean that two distinct objects are - * mapped to the same DOM element, which is not possible.) Filters should be applied to the expression, - * before specifying a tracking expression. - * - * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements - * will be associated by item identity in the array. - * - * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique - * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements - * with the corresponding item in the array by identity. Moving the same object in array would move the DOM - * element in the same way in the DOM. - * - * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this - * case the object identity does not matter. Two objects are considered equivalent as long as their `id` - * property is same. - * - * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter - * to items in conjunction with a tracking expression. - * - * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the - * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message - * when a filter is active on the repeater, but the filtered result set is empty. - * - * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after - * the items have been processed through the filter. - * - * @example - * This example initializes the scope to a list of names and - * then uses `ngRepeat` to display every person: - <example module="ngAnimate" deps="angular-animate.js" animations="true"> - <file name="index.html"> - <div ng-init="friends = [ - {name:'John', age:25, gender:'boy'}, - {name:'Jessie', age:30, gender:'girl'}, - {name:'Johanna', age:28, gender:'girl'}, - {name:'Joy', age:15, gender:'girl'}, - {name:'Mary', age:28, gender:'girl'}, - {name:'Peter', age:95, gender:'boy'}, - {name:'Sebastian', age:50, gender:'boy'}, - {name:'Erika', age:27, gender:'girl'}, - {name:'Patrick', age:40, gender:'boy'}, - {name:'Samantha', age:60, gender:'girl'} - ]"> - I have {{friends.length}} friends. They are: - <input type="search" ng-model="q" placeholder="filter friends..." /> - <ul class="example-animate-container"> - <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results"> - [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. - </li> - <li class="animate-repeat" ng-if="results.length == 0"> - <strong>No results found...</strong> - </li> - </ul> - </div> - </file> - <file name="animations.css"> - .example-animate-container { - background:white; - border:1px solid black; - list-style:none; - margin:0; - padding:0 10px; - } - .animate-repeat { - line-height:40px; - list-style:none; - box-sizing:border-box; - } +var maxlengthDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var maxlength = -1; + attr.$observe('maxlength', function(value) { + var intVal = toInt(value); + maxlength = isNaN(intVal) ? -1 : intVal; + ctrl.$validate(); + }); + ctrl.$validators.maxlength = function(modelValue, viewValue) { + return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength); + }; + } + }; +}; + +var minlengthDirective = function() { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var minlength = 0; + attr.$observe('minlength', function(value) { + minlength = toInt(value) || 0; + ctrl.$validate(); + }); + ctrl.$validators.minlength = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength; + }; + } + }; +}; - .animate-repeat.ng-move, - .animate-repeat.ng-enter, - .animate-repeat.ng-leave { - -webkit-transition:all linear 0.5s; - transition:all linear 0.5s; - } + if (window.angular.bootstrap) { + //AngularJS is already loaded, so we can return here... + console.log('WARNING: Tried to load angular more than once.'); + return; + } - .animate-repeat.ng-leave.ng-leave-active, - .animate-repeat.ng-move, - .animate-repeat.ng-enter { - opacity:0; - max-height:0; - } + //try to bind to jquery now so that one can write jqLite(document).ready() + //but we will rebind on bootstrap again. + bindJQuery(); - .animate-repeat.ng-leave, - .animate-repeat.ng-move.ng-move-active, - .animate-repeat.ng-enter.ng-enter-active { - opacity:1; - max-height:40px; - } - </file> - <file name="protractor.js" type="protractor"> - var friends = element.all(by.repeater('friend in friends')); + publishExternalAPI(angular); - it('should render initial data set', function() { - expect(friends.count()).toBe(10); - expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.'); - expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.'); - expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.'); - expect(element(by.binding('friends.length')).getText()) - .toMatch("I have 10 friends. They are:"); - }); + jqLite(document).ready(function() { + angularInit(document, bootstrap); + }); - it('should update repeater when filter predicate changes', function() { - expect(friends.count()).toBe(10); +})(window, document); - element(by.model('q')).sendKeys('ma'); +!window.angular.$$csp() && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); +/*! + * ionic.bundle.js is a concatenation of: + * ionic.js, angular.js, angular-animate.js, + * angular-sanitize.js, angular-ui-router.js, + * and ionic-angular.js + */ - expect(friends.count()).toBe(2); - expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.'); - expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.'); - }); - </file> - </example> +/** + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT */ -var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { - var NG_REMOVED = '$$NG_REMOVED'; - var ngRepeatMinErr = minErr('ngRepeat'); +(function(window, angular, undefined) {'use strict'; - var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) { - // TODO(perf): generate setters to shave off ~40ms or 1-1.5% - scope[valueIdentifier] = value; - if (keyIdentifier) scope[keyIdentifier] = key; - scope.$index = index; - scope.$first = (index === 0); - scope.$last = (index === (arrayLength - 1)); - scope.$middle = !(scope.$first || scope.$last); - // jshint bitwise: false - scope.$odd = !(scope.$even = (index&1) === 0); - // jshint bitwise: true - }; +/* jshint ignore:start */ +var noop = angular.noop; +var extend = angular.extend; +var jqLite = angular.element; +var forEach = angular.forEach; +var isArray = angular.isArray; +var isString = angular.isString; +var isObject = angular.isObject; +var isUndefined = angular.isUndefined; +var isDefined = angular.isDefined; +var isFunction = angular.isFunction; +var isElement = angular.isElement; - var getBlockStart = function(block) { - return block.clone[0]; - }; +var ELEMENT_NODE = 1; +var COMMENT_NODE = 8; - var getBlockEnd = function(block) { - return block.clone[block.clone.length - 1]; - }; +var NG_ANIMATE_CLASSNAME = 'ng-animate'; +var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren'; +var isPromiseLike = function(p) { + return p && p.then ? true : false; +} - return { - restrict: 'A', - multiElement: true, - transclude: 'element', - priority: 1000, - terminal: true, - $$tlb: true, - compile: function ngRepeatCompile($element, $attr) { - var expression = $attr.ngRepeat; - var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' '); +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required")); + } + return arg; +} - var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} - if (!match) { - throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", - expression); - } +function packageStyles(options) { + var styles = {}; + if (options && (options.to || options.from)) { + styles.to = options.to; + styles.from = options.from; + } + return styles; +} - var lhs = match[1]; - var rhs = match[2]; - var aliasAs = match[3]; - var trackByExp = match[4]; +function pendClasses(classes, fix, isPrefix) { + var className = ''; + classes = isArray(classes) + ? classes + : classes && isString(classes) && classes.length + ? classes.split(/\s+/) + : []; + forEach(classes, function(klass, i) { + if (klass && klass.length > 0) { + className += (i > 0) ? ' ' : ''; + className += isPrefix ? fix + klass + : klass + fix; + } + }); + return className; +} - match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); +function removeFromArray(arr, val) { + var index = arr.indexOf(val); + if (val >= 0) { + arr.splice(index, 1); + } +} - if (!match) { - throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.", - lhs); - } - var valueIdentifier = match[3] || match[1]; - var keyIdentifier = match[2]; +function stripCommentsFromElement(element) { + if (element instanceof jqLite) { + switch (element.length) { + case 0: + return []; + break; - if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) || - /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) { - throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.", - aliasAs); - } + case 1: + // there is no point of stripping anything if the element + // is the only element within the jqLite wrapper. + // (it's important that we retain the element instance.) + if (element[0].nodeType === ELEMENT_NODE) { + return element; + } + break; - var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn; - var hashFnLocals = {$id: hashKey}; + default: + return jqLite(extractElementNode(element)); + break; + } + } - if (trackByExp) { - trackByExpGetter = $parse(trackByExp); - } else { - trackByIdArrayFn = function(key, value) { - return hashKey(value); - }; - trackByIdObjFn = function(key) { - return key; - }; - } + if (element.nodeType === ELEMENT_NODE) { + return jqLite(element); + } +} - return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) { +function extractElementNode(element) { + if (!element[0]) return element; + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType == ELEMENT_NODE) { + return elm; + } + } +} - if (trackByExpGetter) { - trackByIdExpFn = function(key, value, index) { - // assign key, value, and $index to the locals so that they can be used in hash functions - if (keyIdentifier) hashFnLocals[keyIdentifier] = key; - hashFnLocals[valueIdentifier] = value; - hashFnLocals.$index = index; - return trackByExpGetter($scope, hashFnLocals); - }; - } +function $$addClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.addClass(elm, className); + }); +} - // Store a list of elements from previous run. This is a hash where key is the item from the - // iterator, and the value is objects with following properties. - // - scope: bound scope - // - element: previous element. - // - index: position - // - // We are using no-proto object so that we don't need to guard against inherited props via - // hasOwnProperty. - var lastBlockMap = createMap(); +function $$removeClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.removeClass(elm, className); + }); +} - //watch props - $scope.$watchCollection(rhs, function ngRepeatAction(collection) { - var index, length, - previousNode = $element[0], // node that cloned nodes should be inserted after - // initialized to the comment node anchor - nextNode, - // Same as lastBlockMap but it has the current state. It will become the - // lastBlockMap on the next iteration. - nextBlockMap = createMap(), - collectionLength, - key, value, // key/value of iteration - trackById, - trackByIdFn, - collectionKeys, - block, // last object information {scope, element, id} - nextBlockOrder, - elementsToRemove; +function applyAnimationClassesFactory($$jqLite) { + return function(element, options) { + if (options.addClass) { + $$addClass($$jqLite, element, options.addClass); + options.addClass = null; + } + if (options.removeClass) { + $$removeClass($$jqLite, element, options.removeClass); + options.removeClass = null; + } + } +} - if (aliasAs) { - $scope[aliasAs] = collection; - } +function prepareAnimationOptions(options) { + options = options || {}; + if (!options.$$prepared) { + var domOperation = options.domOperation || noop; + options.domOperation = function() { + options.$$domOperationFired = true; + domOperation(); + domOperation = noop; + }; + options.$$prepared = true; + } + return options; +} - if (isArrayLike(collection)) { - collectionKeys = collection; - trackByIdFn = trackByIdExpFn || trackByIdArrayFn; - } else { - trackByIdFn = trackByIdExpFn || trackByIdObjFn; - // if object, extract keys, sort them and use to determine order of iteration over obj props - collectionKeys = []; - for (var itemKey in collection) { - if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') { - collectionKeys.push(itemKey); - } - } - collectionKeys.sort(); - } +function applyAnimationStyles(element, options) { + applyAnimationFromStyles(element, options); + applyAnimationToStyles(element, options); +} - collectionLength = collectionKeys.length; - nextBlockOrder = new Array(collectionLength); +function applyAnimationFromStyles(element, options) { + if (options.from) { + element.css(options.from); + options.from = null; + } +} - // locate existing items - for (index = 0; index < collectionLength; index++) { - key = (collection === collectionKeys) ? index : collectionKeys[index]; - value = collection[key]; - trackById = trackByIdFn(key, value, index); - if (lastBlockMap[trackById]) { - // found previously seen block - block = lastBlockMap[trackById]; - delete lastBlockMap[trackById]; - nextBlockMap[trackById] = block; - nextBlockOrder[index] = block; - } else if (nextBlockMap[trackById]) { - // if collision detected. restore lastBlockMap and throw an error - forEach(nextBlockOrder, function(block) { - if (block && block.scope) lastBlockMap[block.id] = block; - }); - throw ngRepeatMinErr('dupes', - "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}", - expression, trackById, value); - } else { - // new never before seen block - nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined}; - nextBlockMap[trackById] = true; - } - } +function applyAnimationToStyles(element, options) { + if (options.to) { + element.css(options.to); + options.to = null; + } +} - // remove leftover items - for (var blockKey in lastBlockMap) { - block = lastBlockMap[blockKey]; - elementsToRemove = getBlockNodes(block.clone); - $animate.leave(elementsToRemove); - if (elementsToRemove[0].parentNode) { - // if the element was not removed yet because of pending animation, mark it as deleted - // so that we can ignore it later - for (index = 0, length = elementsToRemove.length; index < length; index++) { - elementsToRemove[index][NG_REMOVED] = true; - } - } - block.scope.$destroy(); - } +function mergeAnimationOptions(element, target, newOptions) { + var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || ''); + var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || ''); + var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove); - // we are not using forEach for perf reasons (trying to avoid #call) - for (index = 0; index < collectionLength; index++) { - key = (collection === collectionKeys) ? index : collectionKeys[index]; - value = collection[key]; - block = nextBlockOrder[index]; + extend(target, newOptions); - if (block.scope) { - // if we have already seen this object, then we need to reuse the - // associated scope/element + if (classes.addClass) { + target.addClass = classes.addClass; + } else { + target.addClass = null; + } - nextNode = previousNode; + if (classes.removeClass) { + target.removeClass = classes.removeClass; + } else { + target.removeClass = null; + } - // skip nodes that are already pending removal via leave animation - do { - nextNode = nextNode.nextSibling; - } while (nextNode && nextNode[NG_REMOVED]); + return target; +} - if (getBlockStart(block) != nextNode) { - // existing item which got moved - $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode)); - } - previousNode = getBlockEnd(block); - updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); - } else { - // new item which we don't know about - $transclude(function ngRepeatTransclude(clone, scope) { - block.scope = scope; - // http://jsperf.com/clone-vs-createcomment - var endNode = ngRepeatEndComment.cloneNode(false); - clone[clone.length++] = endNode; +function resolveElementClasses(existing, toAdd, toRemove) { + var ADD_CLASS = 1; + var REMOVE_CLASS = -1; - // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper? - $animate.enter(clone, null, jqLite(previousNode)); - previousNode = endNode; - // Note: We only need the first/last node of the cloned nodes. - // However, we need to keep the reference to the jqlite wrapper as it might be changed later - // by a directive with templateUrl when its template arrives. - block.clone = clone; - nextBlockMap[block.id] = block; - updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); - }); - } - } - lastBlockMap = nextBlockMap; - }); - }; - } + var flags = {}; + existing = splitClassesToLookup(existing); + + toAdd = splitClassesToLookup(toAdd); + forEach(toAdd, function(value, key) { + flags[key] = ADD_CLASS; + }); + + toRemove = splitClassesToLookup(toRemove); + forEach(toRemove, function(value, key) { + flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS; + }); + + var classes = { + addClass: '', + removeClass: '' }; -}]; -var NG_HIDE_CLASS = 'ng-hide'; -var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; -/** - * @ngdoc directive - * @name ngShow - * - * @description - * The `ngShow` directive shows or hides the given HTML element based on the expression - * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding - * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined - * in AngularJS and sets the display style to none (using an !important flag). - * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). - * - * ```html - * <!-- when $scope.myValue is truthy (element is visible) --> - * <div ng-show="myValue"></div> - * - * <!-- when $scope.myValue is falsy (element is hidden) --> - * <div ng-show="myValue" class="ng-hide"></div> - * ``` - * - * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class - * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed - * from the element causing the element not to appear hidden. - * - * ## Why is !important used? - * - * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector - * can be easily overridden by heavier selectors. For example, something as simple - * as changing the display style on a HTML list item would make hidden elements appear visible. - * This also becomes a bigger issue when dealing with CSS frameworks. - * - * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector - * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the - * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. - * - * ### Overriding `.ng-hide` - * - * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change - * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide` - * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope - * with extra animation classes that can be added. - * - * ```css - * .ng-hide:not(.ng-hide-animate) { - * /* this is just another form of hiding an element */ - * display: block!important; - * position: absolute; - * top: -9999px; - * left: -9999px; - * } - * ``` - * - * By default you don't need to override in CSS anything and the animations will work around the display style. - * - * ## A note about animations with `ngShow` - * - * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression - * is true and false. This system works like the animation system present with ngClass except that - * you must also include the !important flag to override the display property - * so that you can perform an animation when the element is hidden during the time of the animation. - * - * ```css - * // - * //a working example can be found at the bottom of this page - * // - * .my-element.ng-hide-add, .my-element.ng-hide-remove { - * /* this is required as of 1.3x to properly - * apply all styling in a show/hide animation */ - * transition: 0s linear all; - * } - * - * .my-element.ng-hide-add-active, - * .my-element.ng-hide-remove-active { - * /* the transition is defined in the active class */ - * transition: 1s linear all; - * } - * - * .my-element.ng-hide-add { ... } - * .my-element.ng-hide-add.ng-hide-add-active { ... } - * .my-element.ng-hide-remove { ... } - * .my-element.ng-hide-remove.ng-hide-remove-active { ... } - * ``` - * - * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display - * property to block during animation states--ngAnimate will handle the style toggling automatically for you. - * - * @animations - * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible - * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden - * - * @element ANY - * @param {expression} ngShow If the {@link guide/expression expression} is truthy - * then the element is shown or hidden respectively. - * - * @example - <example module="ngAnimate" deps="angular-animate.js" animations="true"> - <file name="index.html"> - Click me: <input type="checkbox" ng-model="checked"><br/> - <div> - Show: - <div class="check-element animate-show" ng-show="checked"> - <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked. - </div> - </div> - <div> - Hide: - <div class="check-element animate-show" ng-hide="checked"> - <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked. - </div> - </div> - </file> - <file name="glyphicons.css"> - @import url(../../components/bootstrap-3.1.1/css/bootstrap.css); - </file> - <file name="animations.css"> - .animate-show { - line-height: 20px; - opacity: 1; - padding: 10px; - border: 1px solid black; - background: white; + forEach(flags, function(val, klass) { + var prop, allow; + if (val === ADD_CLASS) { + prop = 'addClass'; + allow = !existing[klass]; + } else if (val === REMOVE_CLASS) { + prop = 'removeClass'; + allow = existing[klass]; + } + if (allow) { + if (classes[prop].length) { + classes[prop] += ' '; } + classes[prop] += klass; + } + }); - .animate-show.ng-hide-add.ng-hide-add-active, - .animate-show.ng-hide-remove.ng-hide-remove-active { - -webkit-transition: all linear 0.5s; - transition: all linear 0.5s; - } + function splitClassesToLookup(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } - .animate-show.ng-hide { - line-height: 0; - opacity: 0; - padding: 0 10px; + var obj = {}; + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; } + }); + return obj; + } - .check-element { - padding: 10px; - border: 1px solid black; - background: white; - } - </file> - <file name="protractor.js" type="protractor"> - var thumbsUp = element(by.css('span.glyphicon-thumbs-up')); - var thumbsDown = element(by.css('span.glyphicon-thumbs-down')); + return classes; +} - it('should check ng-show / ng-hide', function() { - expect(thumbsUp.isDisplayed()).toBeFalsy(); - expect(thumbsDown.isDisplayed()).toBeTruthy(); +function getDomNode(element) { + return (element instanceof angular.element) ? element[0] : element; +} - element(by.model('checked')).click(); +var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) { + var tickQueue = []; + var cancelFn; - expect(thumbsUp.isDisplayed()).toBeTruthy(); - expect(thumbsDown.isDisplayed()).toBeFalsy(); - }); - </file> - </example> - */ -var ngShowDirective = ['$animate', function($animate) { - return { - restrict: 'A', - multiElement: true, - link: function(scope, element, attr) { - scope.$watch(attr.ngShow, function ngShowWatchAction(value) { - // we're adding a temporary, animation-specific class for ng-hide since this way - // we can control when the element is actually displayed on screen without having - // to have a global/greedy CSS selector that breaks when other animations are run. - // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845 - $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, { - tempClasses: NG_HIDE_IN_PROGRESS_CLASS - }); + function scheduler(tasks) { + // we make a copy since RAFScheduler mutates the state + // of the passed in array variable and this would be difficult + // to track down on the outside code + tickQueue.push([].concat(tasks)); + nextTick(); + } + + /* waitUntilQuiet does two things: + * 1. It will run the FINAL `fn` value only when an uncancelled RAF has passed through + * 2. It will delay the next wave of tasks from running until the quiet `fn` has run. + * + * The motivation here is that animation code can request more time from the scheduler + * before the next wave runs. This allows for certain DOM properties such as classes to + * be resolved in time for the next animation to run. + */ + scheduler.waitUntilQuiet = function(fn) { + if (cancelFn) cancelFn(); + + cancelFn = $$rAF(function() { + cancelFn = null; + fn(); + nextTick(); + }); + }; + + return scheduler; + + function nextTick() { + if (!tickQueue.length) return; + + var updatedQueue = []; + for (var i = 0; i < tickQueue.length; i++) { + var innerQueue = tickQueue[i]; + runNextTask(innerQueue); + if (innerQueue.length) { + updatedQueue.push(innerQueue); + } + } + tickQueue = updatedQueue; + + if (!cancelFn) { + $$rAF(function() { + if (!cancelFn) nextTick(); }); } - }; + } + + function runNextTask(tasks) { + var nextTask = tasks.shift(); + nextTask(); + } }]; +var $$AnimateChildrenDirective = [function() { + return function(scope, element, attrs) { + var val = attrs.ngAnimateChildren; + if (angular.isString(val) && val.length === 0) { //empty attribute + element.data(NG_ANIMATE_CHILDREN_DATA, true); + } else { + attrs.$observe('ngAnimateChildren', function(value) { + value = value === 'on' || value === 'true'; + element.data(NG_ANIMATE_CHILDREN_DATA, value); + }); + } + }; +}]; /** - * @ngdoc directive - * @name ngHide + * @ngdoc service + * @name $animateCss + * @kind object * * @description - * The `ngHide` directive shows or hides the given HTML element based on the expression - * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding - * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined - * in AngularJS and sets the display style to none (using an !important flag). - * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}). + * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes + * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT + * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or + * directives to create more complex animations that can be purely driven using CSS code. + * + * Note that only browsers that support CSS transitions and/or keyframe animations are capable of + * rendering animations triggered via `$animateCss` (bad news for IE9 and lower). + * + * ## Usage + * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that + * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however, + * any automatic control over cancelling animations and/or preventing animations from being run on + * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to + * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger + * the CSS animation. + * + * The example below shows how we can create a folding animation on an element using `ng-if`: * * ```html - * <!-- when $scope.myValue is truthy (element is hidden) --> - * <div ng-hide="myValue" class="ng-hide"></div> + * <!-- notice the `fold-animation` CSS class --> + * <div ng-if="onOff" class="fold-animation"> + * This element will go BOOM + * </div> + * <button ng-click="onOff=true">Fold In</button> + * ``` * - * <!-- when $scope.myValue is falsy (element is visible) --> - * <div ng-hide="myValue"></div> + * Now we create the **JavaScript animation** that will trigger the CSS transition: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); * ``` * - * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class - * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed - * from the element causing the element not to appear hidden. + * ## More Advanced Uses * - * ## Why is !important used? + * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks + * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code. * - * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector - * can be easily overridden by heavier selectors. For example, something as simple - * as changing the display style on a HTML list item would make hidden elements appear visible. - * This also becomes a bigger issue when dealing with CSS frameworks. + * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation, + * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with + * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order + * to provide a working animation that will run in CSS. * - * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector - * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the - * styling to change how to hide an element then it is just a matter of using !important in their own CSS code. + * The example below showcases a more advanced version of the `.fold-animation` from the example above: * - * ### Overriding `.ng-hide` + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * addClass: 'red large-text pulse-twice', + * easing: 'ease-out', + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` * - * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change - * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide` - * class in CSS: + * Since we're adding/removing CSS classes then the CSS transition will also pick those up: * * ```css - * .ng-hide { - * /* this is just another form of hiding an element */ - * display: block!important; - * position: absolute; - * top: -9999px; - * left: -9999px; + * /* since a hardcoded duration value of 1 was provided in the JavaScript animation code, + * the CSS classes below will be transitioned despite them being defined as regular CSS classes */ + * .red { background:red; } + * .large-text { font-size:20px; } + * + * /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */ + * .pulse-twice { + * animation: 0.5s pulse linear 2; + * -webkit-animation: 0.5s pulse linear 2; + * } + * + * @keyframes pulse { + * from { transform: scale(0.5); } + * to { transform: scale(1.5); } + * } + * + * @-webkit-keyframes pulse { + * from { -webkit-transform: scale(0.5); } + * to { -webkit-transform: scale(1.5); } * } * ``` * - * By default you don't need to override in CSS anything and the animations will work around the display style. + * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen. * - * ## A note about animations with `ngHide` + * ## How the Options are handled * - * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression - * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide` - * CSS class is added and removed for you instead of your own CSS class. + * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation + * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline + * styles using the `from` and `to` properties. + * + * ```js + * var animator = $animateCss(element, { + * from: { background:'red' }, + * to: { background:'blue' } + * }); + * animator.start(); + * ``` * * ```css - * // - * //a working example can be found at the bottom of this page - * // - * .my-element.ng-hide-add, .my-element.ng-hide-remove { - * transition: 0.5s linear all; + * .rotating-animation { + * animation:0.5s rotate linear; + * -webkit-animation:0.5s rotate linear; * } * - * .my-element.ng-hide-add { ... } - * .my-element.ng-hide-add.ng-hide-add-active { ... } - * .my-element.ng-hide-remove { ... } - * .my-element.ng-hide-remove.ng-hide-remove-active { ... } + * @keyframes rotate { + * from { transform: rotate(0deg); } + * to { transform: rotate(360deg); } + * } + * + * @-webkit-keyframes rotate { + * from { -webkit-transform: rotate(0deg); } + * to { -webkit-transform: rotate(360deg); } + * } * ``` * - * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display - * property to block during animation states--ngAnimate will handle the style toggling automatically for you. + * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is + * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition + * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition + * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied + * and spread across the transition and keyframe animation. * - * @animations - * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden - * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible + * ## What is returned * - * @element ANY - * @param {expression} ngHide If the {@link guide/expression expression} is truthy then - * the element is shown or hidden respectively. + * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually + * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are + * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties: * - * @example - <example module="ngAnimate" deps="angular-animate.js" animations="true"> - <file name="index.html"> - Click me: <input type="checkbox" ng-model="checked"><br/> - <div> - Show: - <div class="check-element animate-hide" ng-show="checked"> - <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked. - </div> - </div> - <div> - Hide: - <div class="check-element animate-hide" ng-hide="checked"> - <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked. - </div> - </div> - </file> - <file name="glyphicons.css"> - @import url(../../components/bootstrap-3.1.1/css/bootstrap.css); - </file> - <file name="animations.css"> - .animate-hide { - -webkit-transition: all linear 0.5s; - transition: all linear 0.5s; - line-height: 20px; - opacity: 1; - padding: 10px; - border: 1px solid black; - background: white; - } + * ```js + * var animator = $animateCss(element, { ... }); + * ``` + * + * Now what do the contents of our `animator` variable look like: + * + * ```js + * { + * // starts the animation + * start: Function, + * + * // ends (aborts) the animation + * end: Function + * } + * ``` + * + * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends. + * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and stlyes may have been + * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties + * and that changing them will not reconfigure the parameters of the animation. + * + * ### runner.done() vs runner.then() + * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the + * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**. + * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()` + * unless you really need a digest to kick off afterwards. + * + * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss + * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code). + * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works. + * + * @param {DOMElement} element the element that will be animated + * @param {object} options the animation-related options that will be applied during the animation + * + * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied + * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.) + * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both). + * * `transition` - The raw CSS transition style that will be used (e.g. `1s linear all`). + * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`). + * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation. + * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition. + * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation. + * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation. + * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0` + * is provided then the animation will be skipped entirely. + * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is + * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value + * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same + * CSS delay value. + * * `stagger` - A numeric time value representing the delay between successively animated elements + * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.}) + * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a + * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`) + * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occuring on the classes being added and removed.) + * + * @return {object} an object with start and end methods and details about the animation. + * + * * `start` - The method to start the animation. This will return a `Promise` when called. + * * `end` - This method will cancel the animation and remove all applied CSS classes and styles. + */ + +// Detect proper transitionend/animationend event names. +var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; + +// If unprefixed events are not supported but webkit-prefixed are, use the latter. +// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. +// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` +// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. +// Register both events in case `window.onanimationend` is not supported because of that, +// do the same for `transitionend` as Safari is likely to exhibit similar behavior. +// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit +// therefore there is no reason to test anymore for other vendor prefixes: +// http://caniuse.com/#search=transition +if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { + CSS_PREFIX = '-webkit-'; + TRANSITION_PROP = 'WebkitTransition'; + TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; +} else { + TRANSITION_PROP = 'transition'; + TRANSITIONEND_EVENT = 'transitionend'; +} + +if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { + CSS_PREFIX = '-webkit-'; + ANIMATION_PROP = 'WebkitAnimation'; + ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; +} else { + ANIMATION_PROP = 'animation'; + ANIMATIONEND_EVENT = 'animationend'; +} + +var DURATION_KEY = 'Duration'; +var PROPERTY_KEY = 'Property'; +var DELAY_KEY = 'Delay'; +var TIMING_KEY = 'TimingFunction'; +var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; +var ANIMATION_PLAYSTATE_KEY = 'PlayState'; +var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; +var CLOSING_TIME_BUFFER = 1.5; +var ONE_SECOND = 1000; +var BASE_TEN = 10; + +var SAFE_FAST_FORWARD_DURATION_VALUE = 9999; + +var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY; +var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY; + +var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY; +var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY; + +var DETECT_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + transitionProperty: TRANSITION_PROP + PROPERTY_KEY, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP, + animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY +}; - .animate-hide.ng-hide { - line-height: 0; - opacity: 0; - padding: 0 10px; +var DETECT_STAGGER_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP +}; + +function computeCssStyles($window, element, properties) { + var styles = Object.create(null); + var detectedStyles = $window.getComputedStyle(element) || {}; + forEach(properties, function(formalStyleName, actualStyleName) { + var val = detectedStyles[formalStyleName]; + if (val) { + var c = val.charAt(0); + + // only numerical-based values have a negative sign or digit as the first value + if (c === '-' || c === '+' || c >= 0) { + val = parseMaxTime(val); } - .check-element { - padding: 10px; - border: 1px solid black; - background: white; + // by setting this to null in the event that the delay is not set or is set directly as 0 + // then we can still allow for zegative values to be used later on and not mistake this + // value for being greater than any other negative value. + if (val === 0) { + val = null; } - </file> - <file name="protractor.js" type="protractor"> - var thumbsUp = element(by.css('span.glyphicon-thumbs-up')); - var thumbsDown = element(by.css('span.glyphicon-thumbs-down')); + styles[actualStyleName] = val; + } + }); - it('should check ng-show / ng-hide', function() { - expect(thumbsUp.isDisplayed()).toBeFalsy(); - expect(thumbsDown.isDisplayed()).toBeTruthy(); + return styles; +} - element(by.model('checked')).click(); +function parseMaxTime(str) { + var maxValue = 0; + var values = str.split(/\s*,\s*/); + forEach(values, function(value) { + // it's always safe to consider only second values and omit `ms` values since + // getComputedStyle will always handle the conversion for us + if (value.charAt(value.length - 1) == 's') { + value = value.substring(0, value.length - 1); + } + value = parseFloat(value) || 0; + maxValue = maxValue ? Math.max(value, maxValue) : value; + }); + return maxValue; +} - expect(thumbsUp.isDisplayed()).toBeTruthy(); - expect(thumbsDown.isDisplayed()).toBeFalsy(); - }); - </file> - </example> - */ -var ngHideDirective = ['$animate', function($animate) { +function truthyTimingValue(val) { + return val === 0 || val != null; +} + +function getCssTransitionDurationStyle(duration, applyOnlyDuration) { + var style = TRANSITION_PROP; + var value = duration + 's'; + if (applyOnlyDuration) { + style += DURATION_KEY; + } else { + value += ' linear all'; + } + return [style, value]; +} + +function getCssKeyframeDurationStyle(duration) { + return [ANIMATION_DURATION_PROP, duration + 's']; +} + +function getCssDelayStyle(delay, isKeyframeAnimation) { + var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP; + return [prop, delay + 's']; +} + +function blockTransitions(node, duration) { + // we use a negative delay value since it performs blocking + // yet it doesn't kill any existing transitions running on the + // same element which makes this safe for class-based animations + var value = duration ? '-' + duration + 's' : ''; + applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]); + return [TRANSITION_DELAY_PROP, value]; +} + +function blockKeyframeAnimations(node, applyBlock) { + var value = applyBlock ? 'paused' : ''; + var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY; + applyInlineStyle(node, [key, value]); + return [key, value]; +} + +function applyInlineStyle(node, styleTuple) { + var prop = styleTuple[0]; + var value = styleTuple[1]; + node.style[prop] = value; +} + +function createLocalCacheLookup() { + var cache = Object.create(null); return { - restrict: 'A', - multiElement: true, - link: function(scope, element, attr) { - scope.$watch(attr.ngHide, function ngHideWatchAction(value) { - // The comment inside of the ngShowDirective explains why we add and - // remove a temporary class for the show/hide animation - $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, { - tempClasses: NG_HIDE_IN_PROGRESS_CLASS - }); - }); + flush: function() { + cache = Object.create(null); + }, + + count: function(key) { + var entry = cache[key]; + return entry ? entry.total : 0; + }, + + get: function(key) { + var entry = cache[key]; + return entry && entry.value; + }, + + put: function(key, value) { + if (!cache[key]) { + cache[key] = { total: 1, value: value }; + } else { + cache[key].total++; + } } }; -}]; +} -/** - * @ngdoc directive - * @name ngStyle - * @restrict AC - * - * @description - * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally. - * - * @element ANY - * @param {expression} ngStyle - * - * {@link guide/expression Expression} which evals to an - * object whose keys are CSS style names and values are corresponding values for those CSS - * keys. - * - * Since some CSS style names are not valid keys for an object, they must be quoted. - * See the 'background-color' style in the example below. - * - * @example - <example> - <file name="index.html"> - <input type="button" value="set color" ng-click="myStyle={color:'red'}"> - <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}"> - <input type="button" value="clear" ng-click="myStyle={}"> - <br/> - <span ng-style="myStyle">Sample Text</span> - <pre>myStyle={{myStyle}}</pre> - </file> - <file name="style.css"> - span { - color: black; - } - </file> - <file name="protractor.js" type="protractor"> - var colorSpan = element(by.css('span')); +var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { + var gcsLookup = createLocalCacheLookup(); + var gcsStaggerLookup = createLocalCacheLookup(); - it('should check ng-style', function() { - expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); - element(by.css('input[value=\'set color\']')).click(); - expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)'); - element(by.css('input[value=clear]')).click(); - expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); - }); - </file> - </example> - */ -var ngStyleDirective = ngDirective(function(scope, element, attr) { - scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { - if (oldStyles && (newStyles !== oldStyles)) { - forEach(oldStyles, function(val, style) { element.css(style, '');}); + this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', + '$document', '$sniffer', '$$rAFScheduler', + function($window, $$jqLite, $$AnimateRunner, $timeout, + $document, $sniffer, $$rAFScheduler) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + var parentCounter = 0; + function gcsHashFn(node, extraClasses) { + var KEY = "$$ngAnimateParentKey"; + var parentNode = node.parentNode; + var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter); + return parentID + '-' + node.getAttribute('class') + '-' + extraClasses; } - if (newStyles) element.css(newStyles); - }); -}); -/** - * @ngdoc directive - * @name ngSwitch - * @restrict EA - * - * @description - * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression. - * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location - * as specified in the template. - * - * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it - * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element - * matches the value obtained from the evaluated expression. In other words, you define a container element - * (where you place the directive), place an expression on the **`on="..."` attribute** - * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place - * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on - * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default - * attribute is displayed. - * - * <div class="alert alert-info"> - * Be aware that the attribute values to match against cannot be expressions. They are interpreted - * as literal string values to match against. - * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the - * value of the expression `$scope.someVal`. - * </div> + function computeCachedCssStyles(node, className, cacheKey, properties) { + var timings = gcsLookup.get(cacheKey); - * @animations - * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container - * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM - * - * @usage - * - * ``` - * <ANY ng-switch="expression"> - * <ANY ng-switch-when="matchValue1">...</ANY> - * <ANY ng-switch-when="matchValue2">...</ANY> - * <ANY ng-switch-default>...</ANY> - * </ANY> - * ``` - * - * - * @scope - * @priority 1200 - * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>. - * On child elements add: - * - * * `ngSwitchWhen`: the case statement to match against. If match then this - * case will be displayed. If the same match appears multiple times, all the - * elements will be displayed. - * * `ngSwitchDefault`: the default case when no other case match. If there - * are multiple default cases, all of them will be displayed when no other - * case match. - * - * - * @example - <example module="switchExample" deps="angular-animate.js" animations="true"> - <file name="index.html"> - <div ng-controller="ExampleController"> - <select ng-model="selection" ng-options="item for item in items"> - </select> - <tt>selection={{selection}}</tt> - <hr/> - <div class="animate-switch-container" - ng-switch on="selection"> - <div class="animate-switch" ng-switch-when="settings">Settings Div</div> - <div class="animate-switch" ng-switch-when="home">Home Span</div> - <div class="animate-switch" ng-switch-default>default</div> - </div> - </div> - </file> - <file name="script.js"> - angular.module('switchExample', ['ngAnimate']) - .controller('ExampleController', ['$scope', function($scope) { - $scope.items = ['settings', 'home', 'other']; - $scope.selection = $scope.items[0]; - }]); - </file> - <file name="animations.css"> - .animate-switch-container { - position:relative; - background:white; - border:1px solid black; - height:40px; - overflow:hidden; + if (!timings) { + timings = computeCssStyles($window, node, properties); + if (timings.animationIterationCount === 'infinite') { + timings.animationIterationCount = 1; + } + } + + // we keep putting this in multiple times even though the value and the cacheKey are the same + // because we're keeping an interal tally of how many duplicate animations are detected. + gcsLookup.put(cacheKey, timings); + return timings; + } + + function computeCachedCssStaggerStyles(node, className, cacheKey, properties) { + var stagger; + + // if we have one or more existing matches of matching elements + // containing the same parent + CSS styles (which is how cacheKey works) + // then staggering is possible + if (gcsLookup.count(cacheKey) > 0) { + stagger = gcsStaggerLookup.get(cacheKey); + + if (!stagger) { + var staggerClassName = pendClasses(className, '-stagger'); + + $$jqLite.addClass(node, staggerClassName); + + stagger = computeCssStyles($window, node, properties); + + // force the conversion of a null value to zero incase not set + stagger.animationDuration = Math.max(stagger.animationDuration, 0); + stagger.transitionDuration = Math.max(stagger.transitionDuration, 0); + + $$jqLite.removeClass(node, staggerClassName); + + gcsStaggerLookup.put(cacheKey, stagger); + } + } + + return stagger || {}; + } + + var bod = getDomNode($document).body; + var rafWaitQueue = []; + function waitUntilQuiet(callback) { + rafWaitQueue.push(callback); + $$rAFScheduler.waitUntilQuiet(function() { + gcsLookup.flush(); + gcsStaggerLookup.flush(); + + //the line below will force the browser to perform a repaint so + //that all the animated elements within the animation frame will + //be properly updated and drawn on screen. This is required to + //ensure that the preparation animation is properly flushed so that + //the active state picks up from there. DO NOT REMOVE THIS LINE. + //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH + //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND + //WILL TAKE YEARS AWAY FROM YOUR LIFE. + var width = bod.offsetWidth + 1; + + // we use a for loop to ensure that if the queue is changed + // during this looping then it will consider new requests + for (var i = 0; i < rafWaitQueue.length; i++) { + rafWaitQueue[i](width); + } + rafWaitQueue.length = 0; + }); + } + + return init; + + function computeTimings(node, className, cacheKey) { + var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES); + var aD = timings.animationDelay; + var tD = timings.transitionDelay; + timings.maxDelay = aD && tD + ? Math.max(aD, tD) + : (aD || tD); + timings.maxDuration = Math.max( + timings.animationDuration * timings.animationIterationCount, + timings.transitionDuration); + + return timings; + } + + function init(element, options) { + var node = getDomNode(element); + if (!node || !node.parentNode) { + return closeAndReturnNoopAnimator(); + } + + options = prepareAnimationOptions(options); + + var temporaryStyles = []; + var classes = element.attr('class'); + var styles = packageStyles(options); + var animationClosed; + var animationPaused; + var animationCompleted; + var runner; + var runnerHost; + var maxDelay; + var maxDelayTime; + var maxDuration; + var maxDurationTime; + + if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) { + return closeAndReturnNoopAnimator(); + } + + var method = options.event && isArray(options.event) + ? options.event.join(' ') + : options.event; + + var isStructural = method && options.structural; + var structuralClassName = ''; + var addRemoveClassName = ''; + + if (isStructural) { + structuralClassName = pendClasses(method, 'ng-', true); + } else if (method) { + structuralClassName = method; + } + + if (options.addClass) { + addRemoveClassName += pendClasses(options.addClass, '-add'); + } + + if (options.removeClass) { + if (addRemoveClassName.length) { + addRemoveClassName += ' '; + } + addRemoveClassName += pendClasses(options.removeClass, '-remove'); + } + + // there may be a situation where a structural animation is combined together + // with CSS classes that need to resolve before the animation is computed. + // However this means that there is no explicit CSS code to block the animation + // from happening (by setting 0s none in the class name). If this is the case + // we need to apply the classes before the first rAF so we know to continue if + // there actually is a detected transition or keyframe animation + if (options.applyClassesEarly && addRemoveClassName.length) { + applyAnimationClasses(element, options); + addRemoveClassName = ''; + } + + var setupClasses = [structuralClassName, addRemoveClassName].join(' ').trim(); + var fullClassName = classes + ' ' + setupClasses; + var activeClasses = pendClasses(setupClasses, '-active'); + var hasToStyles = styles.to && Object.keys(styles.to).length > 0; + var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0; + + // there is no way we can trigger an animation if no styles and + // no classes are being applied which would then trigger a transition, + // unless there a is raw keyframe value that is applied to the element. + if (!containsKeyframeAnimation + && !hasToStyles + && !setupClasses) { + return closeAndReturnNoopAnimator(); + } + + var cacheKey, stagger; + if (options.stagger > 0) { + var staggerVal = parseFloat(options.stagger); + stagger = { + transitionDelay: staggerVal, + animationDelay: staggerVal, + transitionDuration: 0, + animationDuration: 0 + }; + } else { + cacheKey = gcsHashFn(node, fullClassName); + stagger = computeCachedCssStaggerStyles(node, setupClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES); + } + + $$jqLite.addClass(element, setupClasses); + + var applyOnlyDuration; + + if (options.transitionStyle) { + var transitionStyle = [TRANSITION_PROP, options.transitionStyle]; + applyInlineStyle(node, transitionStyle); + temporaryStyles.push(transitionStyle); + } + + if (options.duration >= 0) { + applyOnlyDuration = node.style[TRANSITION_PROP].length > 0; + var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration); + + // we set the duration so that it will be picked up by getComputedStyle later + applyInlineStyle(node, durationStyle); + temporaryStyles.push(durationStyle); + } + + if (options.keyframeStyle) { + var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle]; + applyInlineStyle(node, keyframeStyle); + temporaryStyles.push(keyframeStyle); + } + + var itemIndex = stagger + ? options.staggerIndex >= 0 + ? options.staggerIndex + : gcsLookup.count(cacheKey) + : 0; + + var isFirst = itemIndex === 0; + + // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY + // without causing any combination of transitions to kick in. By adding a negative delay value + // it forces the setup class' transition to end immediately. We later then remove the negative + // transition delay to allow for the transition to naturally do it's thing. The beauty here is + // that if there is no transition defined then nothing will happen and this will also allow + // other transitions to be stacked on top of each other without any chopping them out. + if (isFirst) { + blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE); + } + + var timings = computeTimings(node, fullClassName, cacheKey); + var relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + var flags = {}; + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty == 'all'; + flags.applyTransitionDuration = hasToStyles && ( + (flags.hasTransitions && !flags.hasTransitionAll) + || (flags.hasAnimations && !flags.hasTransitions)); + flags.applyAnimationDuration = options.duration && flags.hasAnimations; + flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); + flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; + flags.recalculateTimingStyles = addRemoveClassName.length > 0; + + if (flags.applyTransitionDuration || flags.applyAnimationDuration) { + maxDuration = options.duration ? parseFloat(options.duration) : maxDuration; + + if (flags.applyTransitionDuration) { + flags.hasTransitions = true; + timings.transitionDuration = maxDuration; + applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0; + temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration)); + } + + if (flags.applyAnimationDuration) { + flags.hasAnimations = true; + timings.animationDuration = maxDuration; + temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration)); + } + } + + if (maxDuration === 0 && !flags.recalculateTimingStyles) { + return closeAndReturnNoopAnimator(); + } + + // we need to recalculate the delay value since we used a pre-emptive negative + // delay value and the delay value is required for the final event checking. This + // property will ensure that this will happen after the RAF phase has passed. + if (options.duration == null && timings.transitionDuration > 0) { + flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst; + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + if (!options.skipBlocking) { + flags.blockTransition = timings.transitionDuration > 0; + flags.blockKeyframeAnimation = timings.animationDuration > 0 && + stagger.animationDelay > 0 && + stagger.animationDuration === 0; + } + + applyAnimationFromStyles(element, options); + if (!flags.blockTransition) { + blockTransitions(node, false); + } + + applyBlocking(maxDuration); + + // TODO(matsko): for 1.5 change this code to have an animator object for better debugging + return { + $$willAnimate: true, + end: endFn, + start: function() { + if (animationClosed) return; + + runnerHost = { + end: endFn, + cancel: cancelFn, + resume: null, //this will be set during the start() phase + pause: null + }; + + runner = new $$AnimateRunner(runnerHost); + + waitUntilQuiet(start); + + // we don't have access to pause/resume the animation + // since it hasn't run yet. AnimateRunner will therefore + // set noop functions for resume and pause and they will + // later be overridden once the animation is triggered + return runner; + } + }; + + function endFn() { + close(); + } + + function cancelFn() { + close(true); + } + + function close(rejected) { // jshint ignore:line + // if the promise has been called already then we shouldn't close + // the animation again + if (animationClosed || (animationCompleted && animationPaused)) return; + animationClosed = true; + animationPaused = false; + + $$jqLite.removeClass(element, setupClasses); + $$jqLite.removeClass(element, activeClasses); + + blockKeyframeAnimations(node, false); + blockTransitions(node, false); + + forEach(temporaryStyles, function(entry) { + // There is only one way to remove inline style properties entirely from elements. + // By using `removeProperty` this works, but we need to convert camel-cased CSS + // styles down to hyphenated values. + node.style[entry[0]] = ''; + }); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + + // the reason why we have this option is to allow a synchronous closing callback + // that is fired as SOON as the animation ends (when the CSS is removed) or if + // the animation never takes off at all. A good example is a leave animation since + // the element must be removed just after the animation is over or else the element + // will appear on screen for one animation frame causing an overbearing flicker. + if (options.onDone) { + options.onDone(); + } + + // if the preparation function fails then the promise is not setup + if (runner) { + runner.complete(!rejected); + } + } + + function applyBlocking(duration) { + if (flags.blockTransition) { + blockTransitions(node, duration); + } + + if (flags.blockKeyframeAnimation) { + blockKeyframeAnimations(node, !!duration); + } + } + + function closeAndReturnNoopAnimator() { + runner = new $$AnimateRunner({ + end: endFn, + cancel: cancelFn + }); + + close(); + + return { + $$willAnimate: false, + start: function() { + return runner; + }, + end: endFn + }; + } + + function start() { + if (animationClosed) return; + if (!node.parentNode) { + close(); + return; + } + + var startTime, events = []; + + // even though we only pause keyframe animations here the pause flag + // will still happen when transitions are used. Only the transition will + // not be paused since that is not possible. If the animation ends when + // paused then it will not complete until unpaused or cancelled. + var playPause = function(playAnimation) { + if (!animationCompleted) { + animationPaused = !playAnimation; + if (timings.animationDuration) { + var value = blockKeyframeAnimations(node, animationPaused); + animationPaused + ? temporaryStyles.push(value) + : removeFromArray(temporaryStyles, value); + } + } else if (animationPaused && playAnimation) { + animationPaused = false; + close(); + } + }; + + // checking the stagger duration prevents an accidently cascade of the CSS delay style + // being inherited from the parent. If the transition duration is zero then we can safely + // rely that the delay value is an intential stagger delay style. + var maxStagger = itemIndex > 0 + && ((timings.transitionDuration && stagger.transitionDuration === 0) || + (timings.animationDuration && stagger.animationDuration === 0)) + && Math.max(stagger.animationDelay, stagger.transitionDelay); + if (maxStagger) { + $timeout(triggerAnimationStart, + Math.floor(maxStagger * itemIndex * ONE_SECOND), + false); + } else { + triggerAnimationStart(); + } + + // this will decorate the existing promise runner with pause/resume methods + runnerHost.resume = function() { + playPause(true); + }; + + runnerHost.pause = function() { + playPause(false); + }; + + function triggerAnimationStart() { + // just incase a stagger animation kicks in when the animation + // itself was cancelled entirely + if (animationClosed) return; + + applyBlocking(false); + + forEach(temporaryStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[key] = value; + }); + + applyAnimationClasses(element, options); + $$jqLite.addClass(element, activeClasses); + + if (flags.recalculateTimingStyles) { + fullClassName = node.className + ' ' + setupClasses; + cacheKey = gcsHashFn(node, fullClassName); + + timings = computeTimings(node, fullClassName, cacheKey); + relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + if (maxDuration === 0) { + close(); + return; + } + + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + } + + if (flags.applyTransitionDelay || flags.applyAnimationDelay) { + relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay) + ? parseFloat(options.delay) + : relativeDelay; + + maxDelay = Math.max(relativeDelay, 0); + + var delayStyle; + if (flags.applyTransitionDelay) { + timings.transitionDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + + if (flags.applyAnimationDelay) { + timings.animationDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay, true); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + + if (options.easing) { + var easeProp, easeVal = options.easing; + if (flags.hasTransitions) { + easeProp = TRANSITION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + if (flags.hasAnimations) { + easeProp = ANIMATION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + } + + if (timings.transitionDuration) { + events.push(TRANSITIONEND_EVENT); + } + + if (timings.animationDuration) { + events.push(ANIMATIONEND_EVENT); + } + + startTime = Date.now(); + element.on(events.join(' '), onAnimationProgress); + $timeout(onAnimationExpired, maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime); + + applyAnimationToStyles(element, options); + } + + function onAnimationExpired() { + // although an expired animation is a failed animation, getting to + // this outcome is very easy if the CSS code screws up. Therefore we + // should still continue normally as if the animation completed correctly. + close(); + } + + function onAnimationProgress(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); + + /* Firefox (or possibly just Gecko) likes to not round values up + * when a ms measurement is used for the animation */ + var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); + + /* $manualTimeStamp is a mocked timeStamp value which is set + * within browserTrigger(). This is only here so that tests can + * mock animations properly. Real events fallback to event.timeStamp, + * or, if they don't, then a timeStamp is automatically created for them. + * We're checking to see if the timeStamp surpasses the expected delay, + * but we're using elapsedTime instead of the timeStamp on the 2nd + * pre-condition since animations sometimes close off early */ + if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { + // we set this flag to ensure that if the transition is paused then, when resumed, + // the animation will automatically close itself since transitions cannot be paused. + animationCompleted = true; + close(); + } + } } + } + }]; +}]; - .animate-switch { - padding:10px; +var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateCssDriver'); + + var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim'; + var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor'; + + var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out'; + var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in'; + + this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$document', '$sniffer', + function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $document, $sniffer) { + + // only browsers that support these properties can render animations + if (!$sniffer.animations && !$sniffer.transitions) return noop; + + var bodyNode = getDomNode($document).body; + var rootNode = getDomNode($rootElement); + + var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode); + + return function initDriverFn(animationDetails) { + return animationDetails.from && animationDetails.to + ? prepareFromToAnchorAnimation(animationDetails.from, + animationDetails.to, + animationDetails.classes, + animationDetails.anchors) + : prepareRegularAnimation(animationDetails); + }; + + function filterCssClasses(classes) { + //remove all the `ng-` stuff + return classes.replace(/\bng-\S+\b/g, ''); + } + + function getUniqueValues(a, b) { + if (isString(a)) a = a.split(' '); + if (isString(b)) b = b.split(' '); + return a.filter(function(val) { + return b.indexOf(val) === -1; + }).join(' '); + } + + function prepareAnchoredAnimation(classes, outAnchor, inAnchor) { + var clone = jqLite(getDomNode(outAnchor).cloneNode(true)); + var startingClasses = filterCssClasses(getClassVal(clone)); + + outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + + clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME); + + rootBodyElement.append(clone); + + var animatorIn, animatorOut = prepareOutAnimation(); + + // the user may not end up using the `out` animation and + // only making use of the `in` animation or vice-versa. + // In either case we should allow this and not assume the + // animation is over unless both animations are not used. + if (!animatorOut) { + animatorIn = prepareInAnimation(); + if (!animatorIn) { + return end(); + } } - .animate-switch.ng-animate { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + var startingAnimator = animatorOut || animatorIn; - position:absolute; - top:0; - left:0; - right:0; - bottom:0; + return { + start: function() { + var runner; + + var currentAnimation = startingAnimator.start(); + currentAnimation.done(function() { + currentAnimation = null; + if (!animatorIn) { + animatorIn = prepareInAnimation(); + if (animatorIn) { + currentAnimation = animatorIn.start(); + currentAnimation.done(function() { + currentAnimation = null; + end(); + runner.complete(); + }); + return currentAnimation; + } + } + // in the event that there is no `in` animation + end(); + runner.complete(); + }); + + runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn + }); + + return runner; + + function endFn() { + if (currentAnimation) { + currentAnimation.end(); + } + } + } + }; + + function calculateAnchorStyles(anchor) { + var styles = {}; + + var coords = getDomNode(anchor).getBoundingClientRect(); + + // we iterate directly since safari messes up and doesn't return + // all the keys for the coods object when iterated + forEach(['width','height','top','left'], function(key) { + var value = coords[key]; + switch (key) { + case 'top': + value += bodyNode.scrollTop; + break; + case 'left': + value += bodyNode.scrollLeft; + break; + } + styles[key] = Math.floor(value) + 'px'; + }); + return styles; } - .animate-switch.ng-leave.ng-leave-active, - .animate-switch.ng-enter { - top:-50px; + function prepareOutAnimation() { + var animator = $animateCss(clone, { + addClass: NG_OUT_ANCHOR_CLASS_NAME, + delay: true, + from: calculateAnchorStyles(outAnchor) + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; } - .animate-switch.ng-leave, - .animate-switch.ng-enter.ng-enter-active { - top:0; + + function getClassVal(element) { + return element.attr('class') || ''; } - </file> - <file name="protractor.js" type="protractor"> - var switchElem = element(by.css('[ng-switch]')); - var select = element(by.model('selection')); - it('should start in settings', function() { - expect(switchElem.getText()).toMatch(/Settings Div/); - }); - it('should change to home', function() { - select.all(by.css('option')).get(1).click(); - expect(switchElem.getText()).toMatch(/Home Span/); - }); - it('should select default', function() { - select.all(by.css('option')).get(2).click(); - expect(switchElem.getText()).toMatch(/default/); + function prepareInAnimation() { + var endingClasses = filterCssClasses(getClassVal(inAnchor)); + var toAdd = getUniqueValues(endingClasses, startingClasses); + var toRemove = getUniqueValues(startingClasses, endingClasses); + + var animator = $animateCss(clone, { + to: calculateAnchorStyles(inAnchor), + addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd, + removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove, + delay: true + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } + + function end() { + clone.remove(); + outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + } + } + + function prepareFromToAnchorAnimation(from, to, classes, anchors) { + var fromAnimation = prepareRegularAnimation(from); + var toAnimation = prepareRegularAnimation(to); + + var anchorAnimations = []; + forEach(anchors, function(anchor) { + var outElement = anchor['out']; + var inElement = anchor['in']; + var animator = prepareAnchoredAnimation(classes, outElement, inElement); + if (animator) { + anchorAnimations.push(animator); + } }); - </file> - </example> - */ -var ngSwitchDirective = ['$animate', function($animate) { - return { - restrict: 'EA', - require: 'ngSwitch', - // asks for $scope to fool the BC controller module - controller: ['$scope', function ngSwitchController() { - this.cases = {}; - }], - link: function(scope, element, attr, ngSwitchController) { - var watchExpr = attr.ngSwitch || attr.on, - selectedTranscludes = [], - selectedElements = [], - previousLeaveAnimations = [], - selectedScopes = []; + // no point in doing anything when there are no elements to animate + if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return; - var spliceFactory = function(array, index) { - return function() { array.splice(index, 1); }; + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + forEach(anchorAnimations, function(animation) { + animationRunners.push(animation.start()); + }); + + var runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn // CSS-driven animations cannot be cancelled, only ended + }); + + $$AnimateRunner.all(animationRunners, function(status) { + runner.complete(status); + }); + + return runner; + + function endFn() { + forEach(animationRunners, function(runner) { + runner.end(); + }); + } + } }; + } - scope.$watch(watchExpr, function ngSwitchWatchAction(value) { - var i, ii; - for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) { - $animate.cancel(previousLeaveAnimations[i]); + function prepareRegularAnimation(animationDetails) { + var element = animationDetails.element; + var options = animationDetails.options || {}; + + if (animationDetails.structural) { + // structural animations ensure that the CSS classes are always applied + // before the detection starts. + options.structural = options.applyClassesEarly = true; + + // we special case the leave animation since we want to ensure that + // the element is removed as soon as the animation is over. Otherwise + // a flicker might appear or the element may not be removed at all + options.event = animationDetails.event; + if (options.event === 'leave') { + options.onDone = options.domOperation; } - previousLeaveAnimations.length = 0; + } else { + options.event = null; + } - for (i = 0, ii = selectedScopes.length; i < ii; ++i) { - var selected = getBlockNodes(selectedElements[i].clone); - selectedScopes[i].$destroy(); - var promise = previousLeaveAnimations[i] = $animate.leave(selected); - promise.then(spliceFactory(previousLeaveAnimations, i)); + var animator = $animateCss(element, options); + + // the driver lookup code inside of $$animation attempts to spawn a + // driver one by one until a driver returns a.$$willAnimate animator object. + // $animateCss will always return an object, however, it will pass in + // a flag as a hint as to whether an animation was detected or not + return animator.$$willAnimate ? animator : null; + } + }]; +}]; + +// TODO(matsko): use caching here to speed things up for detection +// TODO(matsko): add documentation +// by the time... + +var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) { + this.$get = ['$injector', '$$AnimateRunner', '$$rAFMutex', '$$jqLite', + function($injector, $$AnimateRunner, $$rAFMutex, $$jqLite) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + // $animateJs(element, 'enter'); + return function(element, event, classes, options) { + // the `classes` argument is optional and if it is not used + // then the classes will be resolved from the element's className + // property as well as options.addClass/options.removeClass. + if (arguments.length === 3 && isObject(classes)) { + options = classes; + classes = null; + } + + options = prepareAnimationOptions(options); + if (!classes) { + classes = element.attr('class') || ''; + if (options.addClass) { + classes += ' ' + options.addClass; + } + if (options.removeClass) { + classes += ' ' + options.removeClass; + } + } + + var classesToAdd = options.addClass; + var classesToRemove = options.removeClass; + + // the lookupAnimations function returns a series of animation objects that are + // matched up with one or more of the CSS classes. These animation objects are + // defined via the module.animation factory function. If nothing is detected then + // we don't return anything which then makes $animation query the next driver. + var animations = lookupAnimations(classes); + var before, after; + if (animations.length) { + var afterFn, beforeFn; + if (event == 'leave') { + beforeFn = 'leave'; + afterFn = 'afterLeave'; // TODO(matsko): get rid of this + } else { + beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + afterFn = event; } - selectedElements.length = 0; - selectedScopes.length = 0; + if (event !== 'enter' && event !== 'move') { + before = packageAnimations(element, event, options, animations, beforeFn); + } + after = packageAnimations(element, event, options, animations, afterFn); + } - if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) { - forEach(selectedTranscludes, function(selectedTransclude) { - selectedTransclude.transclude(function(caseElement, selectedScope) { - selectedScopes.push(selectedScope); - var anchor = selectedTransclude.element; - caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: '); - var block = { clone: caseElement }; + // no matching animations + if (!before && !after) return; - selectedElements.push(block); - $animate.enter(caseElement, anchor.parent(), anchor); + function applyOptions() { + options.domOperation(); + applyAnimationClasses(element, options); + } + + return { + start: function() { + var closeActiveAnimations; + var chain = []; + + if (before) { + chain.push(function(fn) { + closeActiveAnimations = before(fn); + }); + } + + if (chain.length) { + chain.push(function(fn) { + applyOptions(); + fn(true); + }); + } else { + applyOptions(); + } + + if (after) { + chain.push(function(fn) { + closeActiveAnimations = after(fn); }); + } + + var animationClosed = false; + var runner = new $$AnimateRunner({ + end: function() { + endAnimations(); + }, + cancel: function() { + endAnimations(true); + } }); + + $$AnimateRunner.chain(chain, onComplete); + return runner; + + function onComplete(success) { + animationClosed = true; + applyOptions(); + applyAnimationStyles(element, options); + runner.complete(success); + } + + function endAnimations(cancelled) { + if (!animationClosed) { + (closeActiveAnimations || noop)(cancelled); + onComplete(cancelled); + } + } } - }); - } - }; -}]; + }; -var ngSwitchWhenDirective = ngDirective({ - transclude: 'element', - priority: 1200, - require: '^ngSwitch', - multiElement: true, - link: function(scope, element, attrs, ctrl, $transclude) { - ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []); - ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element }); - } -}); + function executeAnimationFn(fn, element, event, options, onDone) { + var args; + switch (event) { + case 'animate': + args = [element, options.from, options.to, onDone]; + break; -var ngSwitchDefaultDirective = ngDirective({ - transclude: 'element', - priority: 1200, - require: '^ngSwitch', - multiElement: true, - link: function(scope, element, attr, ctrl, $transclude) { - ctrl.cases['?'] = (ctrl.cases['?'] || []); - ctrl.cases['?'].push({ transclude: $transclude, element: element }); - } -}); + case 'setClass': + args = [element, classesToAdd, classesToRemove, onDone]; + break; -/** - * @ngdoc directive - * @name ngTransclude - * @restrict EAC - * - * @description - * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion. - * - * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted. - * - * @element ANY - * - * @example - <example module="transcludeExample"> - <file name="index.html"> - <script> - angular.module('transcludeExample', []) - .directive('pane', function(){ - return { - restrict: 'E', - transclude: true, - scope: { title:'@' }, - template: '<div style="border: 1px solid black;">' + - '<div style="background-color: gray">{{title}}</div>' + - '<ng-transclude></ng-transclude>' + - '</div>' - }; - }) - .controller('ExampleController', ['$scope', function($scope) { - $scope.title = 'Lorem Ipsum'; - $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...'; - }]); - </script> - <div ng-controller="ExampleController"> - <input ng-model="title"> <br/> - <textarea ng-model="text"></textarea> <br/> - <pane title="{{title}}">{{text}}</pane> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should have transcluded', function() { - var titleElement = element(by.model('title')); - titleElement.clear(); - titleElement.sendKeys('TITLE'); - var textElement = element(by.model('text')); - textElement.clear(); - textElement.sendKeys('TEXT'); - expect(element(by.binding('title')).getText()).toEqual('TITLE'); - expect(element(by.binding('text')).getText()).toEqual('TEXT'); - }); - </file> - </example> - * - */ -var ngTranscludeDirective = ngDirective({ - restrict: 'EAC', - link: function($scope, $element, $attrs, controller, $transclude) { - if (!$transclude) { - throw minErr('ngTransclude')('orphan', - 'Illegal use of ngTransclude directive in the template! ' + - 'No parent directive that requires a transclusion found. ' + - 'Element: {0}', - startingTag($element)); - } + case 'addClass': + args = [element, classesToAdd, onDone]; + break; - $transclude(function(clone) { - $element.empty(); - $element.append(clone); - }); - } -}); + case 'removeClass': + args = [element, classesToRemove, onDone]; + break; -/** - * @ngdoc directive - * @name script - * @restrict E - * - * @description - * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the - * template can be used by {@link ng.directive:ngInclude `ngInclude`}, - * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the - * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be - * assigned through the element's `id`, which can then be used as a directive's `templateUrl`. - * - * @param {string} type Must be set to `'text/ng-template'`. - * @param {string} id Cache name of the template. - * - * @example - <example> - <file name="index.html"> - <script type="text/ng-template" id="/tpl.html"> - Content of the template. - </script> + default: + args = [element, onDone]; + break; + } - <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a> - <div id="tpl-content" ng-include src="currentTpl"></div> - </file> - <file name="protractor.js" type="protractor"> - it('should load template defined inside script tag', function() { - element(by.css('#tpl-link')).click(); - expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); - }); - </file> - </example> - */ -var scriptDirective = ['$templateCache', function($templateCache) { - return { - restrict: 'E', - terminal: true, - compile: function(element, attr) { - if (attr.type == 'text/ng-template') { - var templateUrl = attr.id, - text = element[0].text; + args.push(options); - $templateCache.put(templateUrl, text); + var value = fn.apply(fn, args); + if (value) { + if (isFunction(value.start)) { + value = value.start(); + } + + if (value instanceof $$AnimateRunner) { + value.done(onDone); + } else if (isFunction(value)) { + // optional onEnd / onCancel callback + return value; + } + } + + return noop; } - } - }; -}]; -var ngOptionsMinErr = minErr('ngOptions'); -/** - * @ngdoc directive - * @name select - * @restrict E - * - * @description - * HTML `SELECT` element with angular data-binding. - * - * # `ngOptions` - * - * The `ngOptions` attribute can be used to dynamically generate a list of `<option>` - * elements for the `<select>` element using the array or object obtained by evaluating the - * `ngOptions` comprehension expression. - * - * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a - * similar result. However, `ngOptions` provides some benefits such as reducing memory and - * increasing speed by not creating a new scope for each repeated instance, as well as providing - * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the - * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound - * to a non-string value. This is because an option element can only be bound to string values at - * present. - * - * When an item in the `<select>` menu is selected, the array element or object property - * represented by the selected option will be bound to the model identified by the `ngModel` - * directive. - * - * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can - * be nested into the `<select>` element. This element will then represent the `null` or "not selected" - * option. See example below for demonstration. - * - * <div class="alert alert-warning"> - * **Note:** `ngModel` compares by reference, not value. This is important when binding to an - * array of objects. See an example [in this jsfiddle](http://jsfiddle.net/qWzTb/). - * </div> - * - * ## `select` **`as`** - * - * Using `select` **`as`** will bind the result of the `select` expression to the model, but - * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources) - * or property name (for object data sources) of the value within the collection. If a **`track by`** expression - * is used, the result of that expression will be set as the value of the `option` and `select` elements. - * - * - * ### `select` **`as`** and **`track by`** - * - * <div class="alert alert-warning"> - * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together. - * </div> - * - * Consider the following example: - * - * ```html - * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected"> - * ``` - * - * ```js - * $scope.values = [{ - * id: 1, - * label: 'aLabel', - * subItem: { name: 'aSubItem' } - * }, { - * id: 2, - * label: 'bLabel', - * subItem: { name: 'bSubItem' } - * }]; - * - * $scope.selected = { name: 'aSubItem' }; - * ``` - * - * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element - * of the data source (to `item` in this example). To calculate whether an element is selected, we do the - * following: - * - * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]` - * 2. Apply **`track by`** to the already selected value in `ngModel`. - * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected - * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to - * a wrong object, the selected element can't be found, `<select>` is always reset to the "not - * selected" option. - * - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required The control is considered valid only if value is entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {comprehension_expression=} ngOptions in one of the following forms: - * - * * for array data sources: - * * `label` **`for`** `value` **`in`** `array` - * * `select` **`as`** `label` **`for`** `value` **`in`** `array` - * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` - * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr` - * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr` - * (for including a filter with `track by`) - * * for object data sources: - * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object` - * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object` - * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object` - * * `select` **`as`** `label` **`group by`** `group` - * **`for` `(`**`key`**`,`** `value`**`) in`** `object` - * - * Where: - * - * * `array` / `object`: an expression which evaluates to an array / object to iterate over. - * * `value`: local variable which will refer to each item in the `array` or each property value - * of `object` during iteration. - * * `key`: local variable which will refer to a property name in `object` during iteration. - * * `label`: The result of this expression will be the label for `<option>` element. The - * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`). - * * `select`: The result of this expression will be bound to the model of the parent `<select>` - * element. If not specified, `select` expression will default to `value`. - * * `group`: The result of this expression will be used to group options using the `<optgroup>` - * DOM element. - * * `trackexpr`: Used when working with an array of objects. The result of this expression will be - * used to identify the objects in the array. The `trackexpr` will most likely refer to the - * `value` variable (e.g. `value.propertyName`). With this the selection is preserved - * even when the options are recreated (e.g. reloaded from the server). - * - * @example - <example module="selectExample"> - <file name="index.html"> - <script> - angular.module('selectExample', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.colors = [ - {name:'black', shade:'dark'}, - {name:'white', shade:'light'}, - {name:'red', shade:'dark'}, - {name:'blue', shade:'dark'}, - {name:'yellow', shade:'light'} - ]; - $scope.myColor = $scope.colors[2]; // red - }]); - </script> - <div ng-controller="ExampleController"> - <ul> - <li ng-repeat="color in colors"> - Name: <input ng-model="color.name"> - [<a href ng-click="colors.splice($index, 1)">X</a>] - </li> - <li> - [<a href ng-click="colors.push({})">add</a>] - </li> - </ul> - <hr/> - Color (null not allowed): - <select ng-model="myColor" ng-options="color.name for color in colors"></select><br> + function groupEventedAnimations(element, event, options, animations, fnName) { + var operations = []; + forEach(animations, function(ani) { + var animation = ani[fnName]; + if (!animation) return; - Color (null allowed): - <span class="nullable"> - <select ng-model="myColor" ng-options="color.name for color in colors"> - <option value="">-- choose color --</option> - </select> - </span><br/> + // note that all of these animations will run in parallel + operations.push(function() { + var runner; + var endProgressCb; + + var resolved = false; + var onAnimationComplete = function(rejected) { + if (!resolved) { + resolved = true; + (endProgressCb || noop)(rejected); + runner.complete(!rejected); + } + }; + + runner = new $$AnimateRunner({ + end: function() { + onAnimationComplete(); + }, + cancel: function() { + onAnimationComplete(true); + } + }); + + endProgressCb = executeAnimationFn(animation, element, event, options, function(result) { + var cancelled = result === false; + onAnimationComplete(cancelled); + }); + + return runner; + }); + }); + + return operations; + } + + function packageAnimations(element, event, options, animations, fnName) { + var operations = groupEventedAnimations(element, event, options, animations, fnName); + if (operations.length === 0) { + var a,b; + if (fnName === 'beforeSetClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass'); + } else if (fnName === 'setClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass'); + } + + if (a) { + operations = operations.concat(a); + } + if (b) { + operations = operations.concat(b); + } + } + + if (operations.length === 0) return; + + // TODO(matsko): add documentation + return function startAnimation(callback) { + var runners = []; + if (operations.length) { + forEach(operations, function(animateFn) { + runners.push(animateFn()); + }); + } + + runners.length ? $$AnimateRunner.all(runners, callback) : callback(); + + return function endFn(reject) { + forEach(runners, function(runner) { + reject ? runner.cancel() : runner.end(); + }); + }; + }; + } + }; + + function lookupAnimations(classes) { + classes = isArray(classes) ? classes : classes.split(' '); + var matches = [], flagMap = {}; + for (var i=0; i < classes.length; i++) { + var klass = classes[i], + animationFactory = $animateProvider.$$registeredAnimations[klass]; + if (animationFactory && !flagMap[klass]) { + matches.push($injector.get(animationFactory)); + flagMap[klass] = true; + } + } + return matches; + } + }]; +}]; - Color grouped by shade: - <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors"> - </select><br/> +var $$AnimateJsDriverProvider = ['$$animationProvider', function($$animationProvider) { + $$animationProvider.drivers.push('$$animateJsDriver'); + this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) { + return function initDriverFn(animationDetails) { + if (animationDetails.from && animationDetails.to) { + var fromAnimation = prepareAnimation(animationDetails.from); + var toAnimation = prepareAnimation(animationDetails.to); + if (!fromAnimation && !toAnimation) return; + return { + start: function() { + var animationRunners = []; - Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br> - <hr/> - Currently selected: {{ {selected_color:myColor} }} - <div style="border:solid 1px black; height:20px" - ng-style="{'background-color':myColor.name}"> - </div> - </div> - </file> - <file name="protractor.js" type="protractor"> - it('should check ng-options', function() { - expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red'); - element.all(by.model('myColor')).first().click(); - element.all(by.css('select[ng-model="myColor"] option')).first().click(); - expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black'); - element(by.css('.nullable select[ng-model="myColor"]')).click(); - element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click(); - expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null'); - }); - </file> - </example> - */ + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } -var ngOptionsDirective = valueFn({ - restrict: 'A', - terminal: true -}); + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } -// jshint maxlen: false -var selectDirective = ['$compile', '$parse', function($compile, $parse) { - //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888 - var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/, - nullModelCtrl = {$setViewValue: noop}; -// jshint maxlen: 100 + $$AnimateRunner.all(animationRunners, done); - return { - restrict: 'E', - require: ['select', '?ngModel'], - controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) { - var self = this, - optionsMap = {}, - ngModelCtrl = nullModelCtrl, - nullOption, - unknownOption; + var runner = new $$AnimateRunner({ + end: endFnFactory(), + cancel: endFnFactory() + }); + return runner; - self.databound = $attrs.ngModel; + function endFnFactory() { + return function() { + forEach(animationRunners, function(runner) { + // at this point we cannot cancel animations for groups just yet. 1.5+ + runner.end(); + }); + }; + } + function done(status) { + runner.complete(status); + } + } + }; + } else { + return prepareAnimation(animationDetails); + } + }; - self.init = function(ngModelCtrl_, nullOption_, unknownOption_) { - ngModelCtrl = ngModelCtrl_; - nullOption = nullOption_; - unknownOption = unknownOption_; - }; + function prepareAnimation(animationDetails) { + // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations + var element = animationDetails.element; + var event = animationDetails.event; + var options = animationDetails.options; + var classes = animationDetails.classes; + return $$animateJs(element, event, classes, options); + } + }]; +}]; +var NG_ANIMATE_ATTR_NAME = 'data-ng-animate'; +var NG_ANIMATE_PIN_DATA = '$ngAnimatePin'; +var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { + var PRE_DIGEST_STATE = 1; + var RUNNING_STATE = 2; - self.addOption = function(value, element) { - assertNotHasOwnProperty(value, '"option value"'); - optionsMap[value] = true; + var rules = this.rules = { + skip: [], + cancel: [], + join: [] + }; - if (ngModelCtrl.$viewValue == value) { - $element.val(value); - if (unknownOption.parent()) unknownOption.remove(); - } - // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459 - // Adding an <option selected="selected"> element to a <select required="required"> should - // automatically select the new element - if (element && element[0].hasAttribute('selected')) { - element[0].selected = true; - } - }; + function isAllowed(ruleType, element, currentAnimation, previousAnimation) { + return rules[ruleType].some(function(fn) { + return fn(element, currentAnimation, previousAnimation); + }); + } + function hasAnimationClasses(options, and) { + options = options || {}; + var a = (options.addClass || '').length > 0; + var b = (options.removeClass || '').length > 0; + return and ? a && b : a || b; + } - self.removeOption = function(value) { - if (this.hasOption(value)) { - delete optionsMap[value]; - if (ngModelCtrl.$viewValue === value) { - this.renderUnknownOption(value); - } - } - }; + rules.join.push(function(element, newAnimation, currentAnimation) { + // if the new animation is class-based then we can just tack that on + return !newAnimation.structural && hasAnimationClasses(newAnimation.options); + }); + rules.skip.push(function(element, newAnimation, currentAnimation) { + // there is no need to animate anything if no classes are being added and + // there is no structural animation that will be triggered + return !newAnimation.structural && !hasAnimationClasses(newAnimation.options); + }); - self.renderUnknownOption = function(val) { - var unknownVal = '? ' + hashKey(val) + ' ?'; - unknownOption.val(unknownVal); - $element.prepend(unknownOption); - $element.val(unknownVal); - unknownOption.prop('selected', true); // needed for IE - }; + rules.skip.push(function(element, newAnimation, currentAnimation) { + // why should we trigger a new structural animation if the element will + // be removed from the DOM anyway? + return currentAnimation.event == 'leave' && newAnimation.structural; + }); + rules.skip.push(function(element, newAnimation, currentAnimation) { + // if there is a current animation then skip the class-based animation + return currentAnimation.structural && !newAnimation.structural; + }); - self.hasOption = function(value) { - return optionsMap.hasOwnProperty(value); - }; + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // there can never be two structural animations running at the same time + return currentAnimation.structural && newAnimation.structural; + }); - $scope.$on('$destroy', function() { - // disable unknown option so that we don't do work when the whole select is being destroyed - self.renderUnknownOption = noop; - }); - }], + rules.cancel.push(function(element, newAnimation, currentAnimation) { + // if the previous animation is already running, but the new animation will + // be triggered, but the new animation is structural + return currentAnimation.state === RUNNING_STATE && newAnimation.structural; + }); - link: function(scope, element, attr, ctrls) { - // if ngModel is not defined, we don't need to do anything - if (!ctrls[1]) return; - - var selectCtrl = ctrls[0], - ngModelCtrl = ctrls[1], - multiple = attr.multiple, - optionsExp = attr.ngOptions, - nullOption = false, // if false, user will not be able to select it (used by ngOptions) - emptyOption, - renderScheduled = false, - // we can't just jqLite('<option>') since jqLite is not smart enough - // to create it in <select> and IE barfs otherwise. - optionTemplate = jqLite(document.createElement('option')), - optGroupTemplate =jqLite(document.createElement('optgroup')), - unknownOption = optionTemplate.clone(); - - // find "null" option - for (var i = 0, children = element.children(), ii = children.length; i < ii; i++) { - if (children[i].value === '') { - emptyOption = nullOption = children.eq(i); - break; - } - } + rules.cancel.push(function(element, newAnimation, currentAnimation) { + var nO = newAnimation.options; + var cO = currentAnimation.options; - selectCtrl.init(ngModelCtrl, nullOption, unknownOption); + // if the exact same CSS class is added/removed then it's safe to cancel it + return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass); + }); - // required validator - if (multiple) { - ngModelCtrl.$isEmpty = function(value) { - return !value || value.length === 0; - }; + this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap', + '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', + function($$rAF, $rootScope, $rootElement, $document, $$HashMap, + $$animation, $$AnimateRunner, $templateRequest, $$jqLite) { + + var activeAnimationsLookup = new $$HashMap(); + var disabledElementsLookup = new $$HashMap(); + + var animationsEnabled = null; + + // Wait until all directive and route-related templates are downloaded and + // compiled. The $templateRequest.totalPendingRequests variable keeps track of + // all of the remote templates being currently downloaded. If there are no + // templates currently downloading then the watcher will still fire anyway. + var deregisterWatch = $rootScope.$watch( + function() { return $templateRequest.totalPendingRequests === 0; }, + function(isEmpty) { + if (!isEmpty) return; + deregisterWatch(); + + // Now that all templates have been downloaded, $animate will wait until + // the post digest queue is empty before enabling animations. By having two + // calls to $postDigest calls we can ensure that the flag is enabled at the + // very end of the post digest queue. Since all of the animations in $animate + // use $postDigest, it's important that the code below executes at the end. + // This basically means that the page is fully downloaded and compiled before + // any animations are triggered. + $rootScope.$$postDigest(function() { + $rootScope.$$postDigest(function() { + // we check for null directly in the event that the application already called + // .enabled() with whatever arguments that it provided it with + if (animationsEnabled === null) { + animationsEnabled = true; + } + }); + }); } + ); - if (optionsExp) setupAsOptions(scope, element, ngModelCtrl); - else if (multiple) setupAsMultiple(scope, element, ngModelCtrl); - else setupAsSingle(scope, element, ngModelCtrl, selectCtrl); + var bodyElement = jqLite($document[0].body); + var callbackRegistry = {}; - //////////////////////////// + // remember that the classNameFilter is set during the provider/config + // stage therefore we can optimize here and setup a helper function + var classNameFilter = $animateProvider.classNameFilter(); + var isAnimatableClassName = !classNameFilter + ? function() { return true; } + : function(className) { + return classNameFilter.test(className); + }; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + function normalizeAnimationOptions(element, options) { + return mergeAnimationOptions(element, options, {}); + } - function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) { - ngModelCtrl.$render = function() { - var viewValue = ngModelCtrl.$viewValue; + function findCallbacks(element, event) { + var targetNode = getDomNode(element); - if (selectCtrl.hasOption(viewValue)) { - if (unknownOption.parent()) unknownOption.remove(); - selectElement.val(viewValue); - if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy - } else { - if (isUndefined(viewValue) && emptyOption) { - selectElement.val(''); - } else { - selectCtrl.renderUnknownOption(viewValue); - } + var matches = []; + var entries = callbackRegistry[event]; + if (entries) { + forEach(entries, function(entry) { + if (entry.node.contains(targetNode)) { + matches.push(entry.callback); } - }; - - selectElement.on('change', function() { - scope.$apply(function() { - if (unknownOption.parent()) unknownOption.remove(); - ngModelCtrl.$setViewValue(selectElement.val()); - }); }); } - function setupAsMultiple(scope, selectElement, ctrl) { - var lastView; - ctrl.$render = function() { - var items = new HashMap(ctrl.$viewValue); - forEach(selectElement.find('option'), function(option) { - option.selected = isDefined(items.get(option.value)); - }); - }; + return matches; + } - // we have to do it on each watch since ngModel watches reference, but - // we need to work of an array, so we need to see if anything was inserted/removed - scope.$watch(function selectMultipleWatch() { - if (!equals(lastView, ctrl.$viewValue)) { - lastView = shallowCopy(ctrl.$viewValue); - ctrl.$render(); - } + function triggerCallback(event, element, phase, data) { + $$rAF(function() { + forEach(findCallbacks(element, event), function(callback) { + callback(element, phase, data); }); + }); + } - selectElement.on('change', function() { - scope.$apply(function() { - var array = []; - forEach(selectElement.find('option'), function(option) { - if (option.selected) { - array.push(option.value); - } - }); - ctrl.$setViewValue(array); - }); + return { + on: function(event, container, callback) { + var node = extractElementNode(container); + callbackRegistry[event] = callbackRegistry[event] || []; + callbackRegistry[event].push({ + node: node, + callback: callback }); - } + }, - function setupAsOptions(scope, selectElement, ctrl) { - var match; + off: function(event, container, callback) { + var entries = callbackRegistry[event]; + if (!entries) return; - if (!(match = optionsExp.match(NG_OPTIONS_REGEXP))) { - throw ngOptionsMinErr('iexp', - "Expected expression in form of " + - "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" + - " but got '{0}'. Element: {1}", - optionsExp, startingTag(selectElement)); + callbackRegistry[event] = arguments.length === 1 + ? null + : filterFromRegistry(entries, container, callback); + + function filterFromRegistry(list, matchContainer, matchCallback) { + var containerNode = extractElementNode(matchContainer); + return list.filter(function(entry) { + var isMatch = entry.node === containerNode && + (!matchCallback || entry.callback === matchCallback); + return !isMatch; + }); } + }, + + pin: function(element, parentElement) { + assertArg(isElement(element), 'element', 'not an element'); + assertArg(isElement(parentElement), 'parentElement', 'not an element'); + element.data(NG_ANIMATE_PIN_DATA, parentElement); + }, - var displayFn = $parse(match[2] || match[1]), - valueName = match[4] || match[6], - selectAs = / as /.test(match[0]) && match[1], - selectAsFn = selectAs ? $parse(selectAs) : null, - keyName = match[5], - groupByFn = $parse(match[3] || ''), - valueFn = $parse(match[2] ? match[1] : valueName), - valuesFn = $parse(match[7]), - track = match[8], - trackFn = track ? $parse(match[8]) : null, - trackKeysCache = {}, - // This is an array of array of existing option groups in DOM. - // We try to reuse these if possible - // - optionGroupsCache[0] is the options with no option group - // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element - optionGroupsCache = [[{element: selectElement, label:''}]], - //re-usable object to represent option's locals - locals = {}; + push: function(element, event, options, domOperation) { + options = options || {}; + options.domOperation = domOperation; + return queueAnimation(element, event, options); + }, - if (nullOption) { - // compile the element since there might be bindings in it - $compile(nullOption)(scope); + // this method has four signatures: + // () - global getter + // (bool) - global setter + // (element) - element getter + // (element, bool) - element setter<F37> + enabled: function(element, bool) { + var argCount = arguments.length; + + if (argCount === 0) { + // () - Global getter + bool = !!animationsEnabled; + } else { + var hasElement = isElement(element); - // remove the class, which is added automatically because we recompile the element and it - // becomes the compilation root - nullOption.removeClass('ng-scope'); + if (!hasElement) { + // (bool) - Global setter + bool = animationsEnabled = !!element; + } else { + var node = getDomNode(element); + var recordExists = disabledElementsLookup.get(node); - // we need to remove it before calling selectElement.empty() because otherwise IE will - // remove the label from the element. wtf? - nullOption.remove(); + if (argCount === 1) { + // (element) - Element getter + bool = !recordExists; + } else { + // (element, bool) - Element setter + bool = !!bool; + if (!bool) { + disabledElementsLookup.put(node, true); + } else if (recordExists) { + disabledElementsLookup.remove(node); + } + } + } } - // clear contents, we'll add what's needed based on the model - selectElement.empty(); + return bool; + } + }; - selectElement.on('change', selectionChanged); + function queueAnimation(element, event, options) { + var node, parent; + element = stripCommentsFromElement(element); + if (element) { + node = getDomNode(element); + parent = element.parent(); + } - ctrl.$render = render; + options = prepareAnimationOptions(options); - scope.$watchCollection(valuesFn, scheduleRendering); - scope.$watchCollection(getLabels, scheduleRendering); + // we create a fake runner with a working promise. + // These methods will become available after the digest has passed + var runner = new $$AnimateRunner(); - if (multiple) { - scope.$watchCollection(function() { return ctrl.$modelValue; }, scheduleRendering); - } + // there are situations where a directive issues an animation for + // a jqLite wrapper that contains only comment nodes... If this + // happens then there is no way we can perform an animation + if (!node) { + close(); + return runner; + } - // ------------------------------------------------------------------ // + if (isArray(options.addClass)) { + options.addClass = options.addClass.join(' '); + } - function callExpression(exprFn, key, value) { - locals[valueName] = value; - if (keyName) locals[keyName] = key; - return exprFn(scope, locals); - } + if (isArray(options.removeClass)) { + options.removeClass = options.removeClass.join(' '); + } - function selectionChanged() { - scope.$apply(function() { - var collection = valuesFn(scope) || []; - var viewValue; - if (multiple) { - viewValue = []; - forEach(selectElement.val(), function(selectedKey) { - selectedKey = trackFn ? trackKeysCache[selectedKey] : selectedKey; - viewValue.push(getViewValue(selectedKey, collection[selectedKey])); - }); - } else { - var selectedKey = trackFn ? trackKeysCache[selectElement.val()] : selectElement.val(); - viewValue = getViewValue(selectedKey, collection[selectedKey]); - } - ctrl.$setViewValue(viewValue); - render(); - }); - } + if (options.from && !isObject(options.from)) { + options.from = null; + } + + if (options.to && !isObject(options.to)) { + options.to = null; + } + + var className = [node.className, options.addClass, options.removeClass].join(' '); + if (!isAnimatableClassName(className)) { + close(); + return runner; + } + + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // this is a hard disable of all animations for the application or on + // the element itself, therefore there is no need to continue further + // past this point if not enabled + var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node); + var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {}; + var hasExistingAnimation = !!existingAnimation.state; + + // there is no point in traversing the same collection of parent ancestors if a followup + // animation will be run on the same element that already did all that checking work + if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state != PRE_DIGEST_STATE)) { + skipAnimations = !areAnimationsAllowed(element, parent, event); + } + + if (skipAnimations) { + close(); + return runner; + } + + if (isStructural) { + closeChildAnimations(element); + } + + var newAnimation = { + structural: isStructural, + element: element, + event: event, + close: close, + options: options, + runner: runner + }; - function getViewValue(key, value) { - if (key === '?') { - return undefined; - } else if (key === '') { - return null; + if (hasExistingAnimation) { + var skipAnimationFlag = isAllowed('skip', element, newAnimation, existingAnimation); + if (skipAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + close(); + return runner; } else { - var viewValueFn = selectAsFn ? selectAsFn : valueFn; - return callExpression(viewValueFn, key, value); - } - } - - function getLabels() { - var values = valuesFn(scope); - var toDisplay; - if (values && isArray(values)) { - toDisplay = new Array(values.length); - for (var i = 0, ii = values.length; i < ii; i++) { - toDisplay[i] = callExpression(displayFn, i, values[i]); - } - return toDisplay; - } else if (values) { - // TODO: Add a test for this case - toDisplay = {}; - for (var prop in values) { - if (values.hasOwnProperty(prop)) { - toDisplay[prop] = callExpression(displayFn, prop, values[prop]); - } + mergeAnimationOptions(element, existingAnimation.options, options); + return existingAnimation.runner; + } + } + + var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation); + if (cancelAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + // this will end the animation right away and it is safe + // to do so since the animation is already running and the + // runner callback code will run in async + existingAnimation.runner.end(); + } else if (existingAnimation.structural) { + // this means that the animation is queued into a digest, but + // hasn't started yet. Therefore it is safe to run the close + // method which will call the runner methods in async. + existingAnimation.close(); + } else { + // this will merge the existing animation options into this new follow-up animation + mergeAnimationOptions(element, newAnimation.options, existingAnimation.options); + } + } else { + // a joined animation means that this animation will take over the existing one + // so an example would involve a leave animation taking over an enter. Then when + // the postDigest kicks in the enter will be ignored. + var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation); + if (joinAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + normalizeAnimationOptions(element, options); + } else { + event = newAnimation.event = existingAnimation.event; + options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options); + return runner; } } - return toDisplay; } + } else { + // normalization in this case means that it removes redundant CSS classes that + // already exist (addClass) or do not exist (removeClass) on the element + normalizeAnimationOptions(element, options); + } - function createIsSelectedFn(viewValue) { - var selectedSet; - if (multiple) { - if (trackFn && isArray(viewValue)) { + // when the options are merged and cleaned up we may end up not having to do + // an animation at all, therefore we should check this before issuing a post + // digest callback. Structural animations will always run no matter what. + var isValidAnimation = newAnimation.structural; + if (!isValidAnimation) { + // animate (from/to) can be quickly checked first, otherwise we check if any classes are present + isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0) + || hasAnimationClasses(newAnimation.options); + } - selectedSet = new HashMap([]); - for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) { - // tracking by key - selectedSet.put(callExpression(trackFn, null, viewValue[trackIndex]), true); - } - } else { - selectedSet = new HashMap(viewValue); - } - } else if (trackFn) { - viewValue = callExpression(trackFn, null, viewValue); + if (!isValidAnimation) { + close(); + clearElementAnimationState(element); + return runner; + } + + if (isStructural) { + closeParentClassBasedAnimations(parent); + } + + // the counter keeps track of cancelled animations + var counter = (existingAnimation.counter || 0) + 1; + newAnimation.counter = counter; + + markElementAnimationState(element, PRE_DIGEST_STATE, newAnimation); + + $rootScope.$$postDigest(function() { + var animationDetails = activeAnimationsLookup.get(node); + var animationCancelled = !animationDetails; + animationDetails = animationDetails || {}; + + // if addClass/removeClass is called before something like enter then the + // registered parent element may not be present. The code below will ensure + // that a final value for parent element is obtained + var parentElement = element.parent() || []; + + // animate/structural/class-based animations all have requirements. Otherwise there + // is no point in performing an animation. The parent node must also be set. + var isValidAnimation = parentElement.length > 0 + && (animationDetails.event === 'animate' + || animationDetails.structural + || hasAnimationClasses(animationDetails.options)); + + // this means that the previous animation was cancelled + // even if the follow-up animation is the same event + if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) { + // if another animation did not take over then we need + // to make sure that the domOperation and options are + // handled accordingly + if (animationCancelled) { + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); } - return function isSelected(key, value) { - var compareValueFn; - if (trackFn) { - compareValueFn = trackFn; - } else if (selectAsFn) { - compareValueFn = selectAsFn; - } else { - compareValueFn = valueFn; - } + // if the event changed from something like enter to leave then we do + // it, otherwise if it's the same then the end result will be the same too + if (animationCancelled || (isStructural && animationDetails.event !== event)) { + options.domOperation(); + runner.end(); + } - if (multiple) { - return isDefined(selectedSet.remove(callExpression(compareValueFn, key, value))); - } else { - return viewValue === callExpression(compareValueFn, key, value); - } - }; + // in the event that the element animation was not cancelled or a follow-up animation + // isn't allowed to animate from here then we need to clear the state of the element + // so that any future animations won't read the expired animation data. + if (!isValidAnimation) { + clearElementAnimationState(element); + } + + return; } - function scheduleRendering() { - if (!renderScheduled) { - scope.$$postDigest(render); - renderScheduled = true; - } + // this combined multiple class to addClass / removeClass into a setClass event + // so long as a structural event did not take over the animation + event = !animationDetails.structural && hasAnimationClasses(animationDetails.options, true) + ? 'setClass' + : animationDetails.event; + + if (animationDetails.structural) { + closeParentClassBasedAnimations(parentElement); } - /** - * A new labelMap is created with each render. - * This function is called for each existing option with added=false, - * and each new option with added=true. - * - Labels that are passed to this method twice, - * (once with added=true and once with added=false) will end up with a value of 0, and - * will cause no change to happen to the corresponding option. - * - Labels that are passed to this method only once with added=false will end up with a - * value of -1 and will eventually be passed to selectCtrl.removeOption() - * - Labels that are passed to this method only once with added=true will end up with a - * value of 1 and will eventually be passed to selectCtrl.addOption() - */ - function updateLabelMap(labelMap, label, added) { - labelMap[label] = labelMap[label] || 0; - labelMap[label] += (added ? 1 : -1); - } - - function render() { - renderScheduled = false; - - // Temporary location for the option groups before we render them - var optionGroups = {'':[]}, - optionGroupNames = [''], - optionGroupName, - optionGroup, - option, - existingParent, existingOptions, existingOption, - viewValue = ctrl.$viewValue, - values = valuesFn(scope) || [], - keys = keyName ? sortedKeys(values) : values, - key, - value, - groupLength, length, - groupIndex, index, - labelMap = {}, - selected, - isSelected = createIsSelectedFn(viewValue), - anySelected = false, - lastElement, - element, - label, - optionId; - - trackKeysCache = {}; - - // We now build up the list of options we need (we merge later) - for (index = 0; length = keys.length, index < length; index++) { - key = index; - if (keyName) { - key = keys[index]; - if (key.charAt(0) === '$') continue; - } - value = values[key]; - - optionGroupName = callExpression(groupByFn, key, value) || ''; - if (!(optionGroup = optionGroups[optionGroupName])) { - optionGroup = optionGroups[optionGroupName] = []; - optionGroupNames.push(optionGroupName); - } - - selected = isSelected(key, value); - anySelected = anySelected || selected; - - label = callExpression(displayFn, key, value); // what will be seen by the user - - // doing displayFn(scope, locals) || '' overwrites zero values - label = isDefined(label) ? label : ''; - optionId = trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index); - if (trackFn) { - trackKeysCache[optionId] = key; - } - - optionGroup.push({ - // either the index into array or key from object - id: optionId, - label: label, - selected: selected // determine if we should be selected - }); - } - if (!multiple) { - if (nullOption || viewValue === null) { - // insert null option if we have a placeholder, or the model is null - optionGroups[''].unshift({id:'', label:'', selected:!anySelected}); - } else if (!anySelected) { - // option could not be found, we have to insert the undefined item - optionGroups[''].unshift({id:'?', label:'', selected:true}); - } + markElementAnimationState(element, RUNNING_STATE); + var realRunner = $$animation(element, event, animationDetails.options); + realRunner.done(function(status) { + close(!status); + var animationDetails = activeAnimationsLookup.get(node); + if (animationDetails && animationDetails.counter === counter) { + clearElementAnimationState(getDomNode(element)); } + notifyProgress(runner, event, 'close', {}); + }); + + // this will update the runner's flow-control events based on + // the `realRunner` object. + runner.setHost(realRunner); + notifyProgress(runner, event, 'start', {}); + }); - // Now we need to update the list of DOM nodes to match the optionGroups we computed above - for (groupIndex = 0, groupLength = optionGroupNames.length; - groupIndex < groupLength; - groupIndex++) { - // current option group name or '' if no group - optionGroupName = optionGroupNames[groupIndex]; + return runner; - // list of options for that group. (first item has the parent) - optionGroup = optionGroups[optionGroupName]; + function notifyProgress(runner, event, phase, data) { + triggerCallback(event, element, phase, data); + runner.progress(event, phase, data); + } - if (optionGroupsCache.length <= groupIndex) { - // we need to grow the optionGroups - existingParent = { - element: optGroupTemplate.clone().attr('label', optionGroupName), - label: optionGroup.label - }; - existingOptions = [existingParent]; - optionGroupsCache.push(existingOptions); - selectElement.append(existingParent.element); - } else { - existingOptions = optionGroupsCache[groupIndex]; - existingParent = existingOptions[0]; // either SELECT (no group) or OPTGROUP element + function close(reject) { // jshint ignore:line + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + runner.complete(!reject); + } + } - // update the OPTGROUP label if not the same. - if (existingParent.label != optionGroupName) { - existingParent.element.attr('label', existingParent.label = optionGroupName); - } + function closeChildAnimations(element) { + var node = getDomNode(element); + var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']'); + forEach(children, function(child) { + var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME)); + var animationDetails = activeAnimationsLookup.get(child); + switch (state) { + case RUNNING_STATE: + animationDetails.runner.end(); + /* falls through */ + case PRE_DIGEST_STATE: + if (animationDetails) { + activeAnimationsLookup.remove(child); } + break; + } + }); + } - lastElement = null; // start at the beginning - for (index = 0, length = optionGroup.length; index < length; index++) { - option = optionGroup[index]; - if ((existingOption = existingOptions[index + 1])) { - // reuse elements - lastElement = existingOption.element; - if (existingOption.label !== option.label) { - updateLabelMap(labelMap, existingOption.label, false); - updateLabelMap(labelMap, option.label, true); - lastElement.text(existingOption.label = option.label); - lastElement.prop('label', existingOption.label); - } - if (existingOption.id !== option.id) { - lastElement.val(existingOption.id = option.id); - } - // lastElement.prop('selected') provided by jQuery has side-effects - if (lastElement[0].selected !== option.selected) { - lastElement.prop('selected', (existingOption.selected = option.selected)); - if (msie) { - // See #7692 - // The selected item wouldn't visually update on IE without this. - // Tested on Win7: IE9, IE10 and IE11. Future IEs should be tested as well - lastElement.prop('selected', existingOption.selected); - } - } - } else { - // grow elements + function clearElementAnimationState(element) { + var node = getDomNode(element); + node.removeAttribute(NG_ANIMATE_ATTR_NAME); + activeAnimationsLookup.remove(node); + } - // if it's a null option - if (option.id === '' && nullOption) { - // put back the pre-compiled element - element = nullOption; - } else { - // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but - // in this version of jQuery on some browser the .text() returns a string - // rather then the element. - (element = optionTemplate.clone()) - .val(option.id) - .prop('selected', option.selected) - .attr('selected', option.selected) - .prop('label', option.label) - .text(option.label); - } + function isMatchingElement(nodeOrElmA, nodeOrElmB) { + return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB); + } - existingOptions.push(existingOption = { - element: element, - label: option.label, - id: option.id, - selected: option.selected - }); - updateLabelMap(labelMap, option.label, true); - if (lastElement) { - lastElement.after(element); - } else { - existingParent.element.append(element); - } - lastElement = element; - } - } - // remove any excessive OPTIONs in a group - index++; // increment since the existingOptions[0] is parent element not OPTION - while (existingOptions.length > index) { - option = existingOptions.pop(); - updateLabelMap(labelMap, option.label, false); - option.element.remove(); - } + function closeParentClassBasedAnimations(startingElement) { + var parentNode = getDomNode(startingElement); + do { + if (!parentNode || parentNode.nodeType !== ELEMENT_NODE) break; + + var animationDetails = activeAnimationsLookup.get(parentNode); + if (animationDetails) { + examineParentAnimation(parentNode, animationDetails); + } + + parentNode = parentNode.parentNode; + } while (true); + + // since animations are detected from CSS classes, we need to flush all parent + // class-based animations so that the parent classes are all present for child + // animations to properly function (otherwise any CSS selectors may not work) + function examineParentAnimation(node, animationDetails) { + // enter/leave/move always have priority + if (animationDetails.structural || !hasAnimationClasses(animationDetails.options)) return; + + if (animationDetails.state === RUNNING_STATE) { + animationDetails.runner.end(); + } + clearElementAnimationState(node); + } + } + + function areAnimationsAllowed(element, parentElement, event) { + var bodyElementDetected = false; + var rootElementDetected = false; + var parentAnimationDetected = false; + var animateChildren; + + var parentHost = element.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; + } + + while (parentElement && parentElement.length) { + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + } + + var parentNode = parentElement[0]; + if (parentNode.nodeType !== ELEMENT_NODE) { + // no point in inspecting the #document element + break; + } + + var details = activeAnimationsLookup.get(parentNode) || {}; + // either an enter, leave or move animation will commence + // therefore we can't allow any animations to take place + // but if a parent animation is class-based then that's ok + if (!parentAnimationDetected) { + parentAnimationDetected = details.structural || disabledElementsLookup.get(parentNode); + } + + if (isUndefined(animateChildren) || animateChildren === true) { + var value = parentElement.data(NG_ANIMATE_CHILDREN_DATA); + if (isDefined(value)) { + animateChildren = value; } - // remove any excessive OPTGROUPs from select - while (optionGroupsCache.length > groupIndex) { - // remove all the labels in the option group - optionGroup = optionGroupsCache.pop(); - for (index = 1; index < optionGroup.length; ++index) { - updateLabelMap(labelMap, optionGroup[index].label, false); + } + + // there is no need to continue traversing at this point + if (parentAnimationDetected && animateChildren === false) break; + + if (!rootElementDetected) { + // angular doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootElementDetected = isMatchingElement(parentElement, $rootElement); + if (!rootElementDetected) { + parentHost = parentElement.data(NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentElement = parentHost; } - optionGroup[0].element.remove(); } - forEach(labelMap, function(count, label) { - if (count > 0) { - selectCtrl.addOption(label); - } else if (count < 0) { - selectCtrl.removeOption(label); - } - }); } + + if (!bodyElementDetected) { + // we also need to ensure that the element is or will be apart of the body element + // otherwise it is pointless to even issue an animation to be rendered + bodyElementDetected = isMatchingElement(parentElement, bodyElement); + } + + parentElement = parentElement.parent(); } + + var allowAnimation = !parentAnimationDetected || animateChildren; + return allowAnimation && rootElementDetected && bodyElementDetected; } - }; + + function markElementAnimationState(element, state, details) { + details = details || {}; + details.state = state; + + var node = getDomNode(element); + node.setAttribute(NG_ANIMATE_ATTR_NAME, state); + + var oldValue = activeAnimationsLookup.get(node); + var newValue = oldValue + ? extend(oldValue, details) + : details; + activeAnimationsLookup.put(node, newValue); + } + }]; }]; -var optionDirective = ['$interpolate', function($interpolate) { - var nullSelectCtrl = { - addOption: noop, - removeOption: noop +var $$rAFMutexFactory = ['$$rAF', function($$rAF) { + return function() { + var passed = false; + $$rAF(function() { + passed = true; + }); + return function(fn) { + passed ? fn() : $$rAF(fn); + }; }; +}]; - return { - restrict: 'E', - priority: 100, - compile: function(element, attr) { - if (isUndefined(attr.value)) { - var interpolateFn = $interpolate(element.text(), true); - if (!interpolateFn) { - attr.$set('value', element.text()); +var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) { + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + AnimateRunner.chain = function(chain, callback) { + var index = 0; + + next(); + function next() { + if (index === chain.length) { + callback(true); + return; + } + + chain[index](function(response) { + if (response === false) { + callback(false); + return; } + index++; + next(); + }); + } + }; + + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); } + } + }; - return function(scope, element, attr) { - var selectCtrlName = '$selectController', - parent = element.parent(), - selectCtrl = parent.data(selectCtrlName) || - parent.parent().data(selectCtrlName); // in case we are in optgroup + function AnimateRunner(host) { + this.setHost(host); - if (!selectCtrl || !selectCtrl.databound) { - selectCtrl = nullSelectCtrl; - } + this._doneCallbacks = []; + this._runInAnimationFrame = $$rAFMutex(); + this._state = 0; + } - if (interpolateFn) { - scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) { - attr.$set('value', newVal); - if (oldVal !== newVal) { - selectCtrl.removeOption(oldVal); - } - selectCtrl.addOption(newVal, element); + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); }); - } else { - selectCtrl.addOption(attr.value, element); - } + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, - element.on('$destroy', function() { - selectCtrl.removeOption(attr.value); + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._runInAnimationFrame(function() { + self._resolve(response); }); - }; + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } } }; + + return AnimateRunner; }]; -var styleDirective = valueFn({ - restrict: 'E', - terminal: false -}); +var $$AnimationProvider = ['$animateProvider', function($animateProvider) { + var NG_ANIMATE_REF_ATTR = 'ng-animate-ref'; -var requiredDirective = function() { - return { - restrict: 'A', - require: '?ngModel', - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; - attr.required = true; // force truthy in case we are on non input element + var drivers = this.drivers = []; - ctrl.$validators.required = function(modelValue, viewValue) { - return !attr.required || !ctrl.$isEmpty(viewValue); - }; + var RUNNER_STORAGE_KEY = '$$animationRunner'; - attr.$observe('required', function() { - ctrl.$validate(); - }); - } - }; -}; + function setRunner(element, runner) { + element.data(RUNNER_STORAGE_KEY, runner); + } + function removeRunner(element) { + element.removeData(RUNNER_STORAGE_KEY); + } -var patternDirective = function() { - return { - restrict: 'A', - require: '?ngModel', - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; + function getRunner(element) { + return element.data(RUNNER_STORAGE_KEY); + } - var regexp, patternExp = attr.ngPattern || attr.pattern; - attr.$observe('pattern', function(regex) { - if (isString(regex) && regex.length > 0) { - regex = new RegExp('^' + regex + '$'); - } + this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$rAFScheduler', + function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$rAFScheduler) { - if (regex && !regex.test) { - throw minErr('ngPattern')('noregexp', - 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp, - regex, startingTag(elm)); - } + var animationQueue = []; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); - regexp = regex || undefined; - ctrl.$validate(); + var totalPendingClassBasedAnimations = 0; + var totalActiveClassBasedAnimations = 0; + var classBasedAnimationsQueue = []; + + // TODO(matsko): document the signature in a better way + return function(element, event, options) { + options = prepareAnimationOptions(options); + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // there is no animation at the current moment, however + // these runner methods will get later updated with the + // methods leading into the driver's end/cancel methods + // for now they just stop the animation from starting + var runner = new $$AnimateRunner({ + end: function() { close(); }, + cancel: function() { close(true); } }); - ctrl.$validators.pattern = function(value) { - return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value); - }; - } - }; -}; + if (!drivers.length) { + close(); + return runner; + } + setRunner(element, runner); -var maxlengthDirective = function() { - return { - restrict: 'A', - require: '?ngModel', - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; + var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass)); + var tempClasses = options.tempClasses; + if (tempClasses) { + classes += ' ' + tempClasses; + options.tempClasses = null; + } - var maxlength = -1; - attr.$observe('maxlength', function(value) { - var intVal = int(value); - maxlength = isNaN(intVal) ? -1 : intVal; - ctrl.$validate(); + var classBasedIndex; + if (!isStructural) { + classBasedIndex = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations += 1; + } + + animationQueue.push({ + // this data is used by the postDigest code and passed into + // the driver step function + element: element, + classes: classes, + event: event, + classBasedIndex: classBasedIndex, + structural: isStructural, + options: options, + beforeStart: beforeStart, + close: close }); - ctrl.$validators.maxlength = function(modelValue, viewValue) { - return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength); - }; - } - }; -}; -var minlengthDirective = function() { - return { - restrict: 'A', - require: '?ngModel', - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; + element.on('$destroy', handleDestroyedElement); - var minlength = 0; - attr.$observe('minlength', function(value) { - minlength = int(value) || 0; - ctrl.$validate(); + // we only want there to be one function called within the post digest + // block. This way we can group animations for all the animations that + // were apart of the same postDigest flush call. + if (animationQueue.length > 1) return runner; + + $rootScope.$$postDigest(function() { + totalActiveClassBasedAnimations = totalPendingClassBasedAnimations; + totalPendingClassBasedAnimations = 0; + classBasedAnimationsQueue.length = 0; + + var animations = []; + forEach(animationQueue, function(entry) { + // the element was destroyed early on which removed the runner + // form its storage. This means we can't animate this element + // at all and it already has been closed due to destruction. + if (getRunner(entry.element)) { + animations.push(entry); + } + }); + + // now any future animations will be in another postDigest + animationQueue.length = 0; + + forEach(groupAnimations(animations), function(animationEntry) { + if (animationEntry.structural) { + triggerAnimationStart(); + } else { + classBasedAnimationsQueue.push({ + node: getDomNode(animationEntry.element), + fn: triggerAnimationStart + }); + + if (animationEntry.classBasedIndex === totalActiveClassBasedAnimations - 1) { + // we need to sort each of the animations in order of parent to child + // relationships. This ensures that the child classes are applied at the + // right time. + classBasedAnimationsQueue = classBasedAnimationsQueue.sort(function(a,b) { + return b.node.contains(a.node); + }).map(function(entry) { + return entry.fn; + }); + + $$rAFScheduler(classBasedAnimationsQueue); + } + } + + function triggerAnimationStart() { + // it's important that we apply the `ng-animate` CSS class and the + // temporary classes before we do any driver invoking since these + // CSS classes may be required for proper CSS detection. + animationEntry.beforeStart(); + + var startAnimationFn, closeFn = animationEntry.close; + + // in the event that the element was removed before the digest runs or + // during the RAF sequencing then we should not trigger the animation. + var targetElement = animationEntry.anchors + ? (animationEntry.from.element || animationEntry.to.element) + : animationEntry.element; + + if (getRunner(targetElement) && getDomNode(targetElement).parentNode) { + var operation = invokeFirstDriver(animationEntry); + if (operation) { + startAnimationFn = operation.start; + } + } + + if (!startAnimationFn) { + closeFn(); + } else { + var animationRunner = startAnimationFn(); + animationRunner.done(function(status) { + closeFn(!status); + }); + updateAnimationRunners(animationEntry, animationRunner); + } + } + }); }); - ctrl.$validators.minlength = function(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength; - }; - } - }; -}; - if (window.angular.bootstrap) { - //AngularJS is already loaded, so we can return here... - console.log('WARNING: Tried to load angular more than once.'); - return; - } + return runner; - //try to bind to jquery now so that one can write jqLite(document).ready() - //but we will rebind on bootstrap again. - bindJQuery(); + // TODO(matsko): change to reference nodes + function getAnchorNodes(node) { + var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']'; + var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) + ? [node] + : node.querySelectorAll(SELECTOR); + var anchors = []; + forEach(items, function(node) { + var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); + if (attr && attr.length) { + anchors.push(node); + } + }); + return anchors; + } + + function groupAnimations(animations) { + var preparedAnimations = []; + var refLookup = {}; + forEach(animations, function(animation, index) { + var element = animation.element; + var node = getDomNode(element); + var event = animation.event; + var enterOrMove = ['enter', 'move'].indexOf(event) >= 0; + var anchorNodes = animation.structural ? getAnchorNodes(node) : []; + + if (anchorNodes.length) { + var direction = enterOrMove ? 'to' : 'from'; + + forEach(anchorNodes, function(anchor) { + var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); + refLookup[key] = refLookup[key] || {}; + refLookup[key][direction] = { + animationID: index, + element: jqLite(anchor) + }; + }); + } else { + preparedAnimations.push(animation); + } + }); - publishExternalAPI(angular); + var usedIndicesLookup = {}; + var anchorGroups = {}; + forEach(refLookup, function(operations, key) { + var from = operations.from; + var to = operations.to; + + if (!from || !to) { + // only one of these is set therefore we can't have an + // anchor animation since all three pieces are required + var index = from ? from.animationID : to.animationID; + var indexKey = index.toString(); + if (!usedIndicesLookup[indexKey]) { + usedIndicesLookup[indexKey] = true; + preparedAnimations.push(animations[index]); + } + return; + } - jqLite(document).ready(function() { - angularInit(document, bootstrap); - }); + var fromAnimation = animations[from.animationID]; + var toAnimation = animations[to.animationID]; + var lookupKey = from.animationID.toString(); + if (!anchorGroups[lookupKey]) { + var group = anchorGroups[lookupKey] = { + structural: true, + beforeStart: function() { + fromAnimation.beforeStart(); + toAnimation.beforeStart(); + }, + close: function() { + fromAnimation.close(); + toAnimation.close(); + }, + classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), + from: fromAnimation, + to: toAnimation, + anchors: [] // TODO(matsko): change to reference nodes + }; -})(window, document); + // the anchor animations require that the from and to elements both have at least + // one shared CSS class which effictively marries the two elements together to use + // the same animation driver and to properly sequence the anchor animation. + if (group.classes.length) { + preparedAnimations.push(group); + } else { + preparedAnimations.push(fromAnimation); + preparedAnimations.push(toAnimation); + } + } -!window.angular.$$csp() && window.angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>'); + anchorGroups[lookupKey].anchors.push({ + 'out': from.element, 'in': to.element + }); + }); -/*! - * ionic.bundle.js is a concatenation of: - * ionic.js, angular.js, angular-animate.js, - * angular-sanitize.js, angular-ui-router.js, - * and ionic-angular.js - */ + return preparedAnimations; + } + + function cssClassesIntersection(a,b) { + a = a.split(' '); + b = b.split(' '); + var matches = []; + + for (var i = 0; i < a.length; i++) { + var aa = a[i]; + if (aa.substring(0,3) === 'ng-') continue; + + for (var j = 0; j < b.length; j++) { + if (aa === b[j]) { + matches.push(aa); + break; + } + } + } + + return matches.join(' '); + } + + function invokeFirstDriver(animationDetails) { + // we loop in reverse order since the more general drivers (like CSS and JS) + // may attempt more elements, but custom drivers are more particular + for (var i = drivers.length - 1; i >= 0; i--) { + var driverName = drivers[i]; + if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check + + var factory = $injector.get(driverName); + var driver = factory(animationDetails); + if (driver) { + return driver; + } + } + } + + function beforeStart() { + element.addClass(NG_ANIMATE_CLASSNAME); + if (tempClasses) { + $$jqLite.addClass(element, tempClasses); + } + } + + function updateAnimationRunners(animation, newRunner) { + if (animation.from && animation.to) { + update(animation.from.element); + update(animation.to.element); + } else { + update(animation.element); + } + + function update(element) { + getRunner(element).setHost(newRunner); + } + } + + function handleDestroyedElement() { + var runner = getRunner(element); + if (runner && (event !== 'leave' || !options.$$domOperationFired)) { + runner.end(); + } + } -/** - * @license AngularJS v1.3.13 - * (c) 2010-2014 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, angular, undefined) {'use strict'; + function close(rejected) { // jshint ignore:line + element.off('$destroy', handleDestroyedElement); + removeRunner(element); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + + if (tempClasses) { + $$jqLite.removeClass(element, tempClasses); + } + + element.removeClass(NG_ANIMATE_CLASSNAME); + runner.complete(!rejected); + } + }; + }]; +}]; -/* jshint maxlen: false */ +/* global angularAnimateModule: true, + + $$rAFMutexFactory, + $$rAFSchedulerFactory, + $$AnimateChildrenDirective, + $$AnimateRunnerFactory, + $$AnimateQueueProvider, + $$AnimationProvider, + $AnimateCssProvider, + $$AnimateCssDriverProvider, + $$AnimateJsProvider, + $$AnimateJsDriverProvider, +*/ /** * @ngdoc module * @name ngAnimate * @description * - * The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives. + * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via + * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app. * * <div doc-module-components="ngAnimate"></div> * * # Usage + * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based + * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For + * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within + * the HTML element that the animation will be triggered on. * - * To see animations in action, all that is required is to define the appropriate CSS classes - * or to register a JavaScript animation via the `myModule.animation()` function. The directives that support animation automatically are: - * `ngRepeat`, `ngInclude`, `ngIf`, `ngSwitch`, `ngShow`, `ngHide`, `ngView` and `ngClass`. Custom directives can take advantage of animation - * by using the `$animate` service. - * - * Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives: + * ## Directive Support + * The following directives are "animation aware": * * | Directive | Supported Animations | * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------| @@ -35003,216 +44690,130 @@ var minlengthDirective = function() { * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) | * | {@link module:ngMessages#animations ngMessage} | enter and leave | * - * You can find out more information about animations upon visiting each directive page. - * - * Below is an example of how to apply animations to a directive that supports animation hooks: - * - * ```html - * <style type="text/css"> - * .slide.ng-enter, .slide.ng-leave { - * -webkit-transition:0.5s linear all; - * transition:0.5s linear all; - * } + * (More information can be found by visiting each the documentation associated with each directive.) * - * .slide.ng-enter { } /* starting animations for enter */ - * .slide.ng-enter.ng-enter-active { } /* terminal animations for enter */ - * .slide.ng-leave { } /* starting animations for leave */ - * .slide.ng-leave.ng-leave-active { } /* terminal animations for leave */ - * </style> + * ## CSS-based Animations * - * <!-- - * the animate service will automatically add .ng-enter and .ng-leave to the element - * to trigger the CSS transition/animations - * --> - * <ANY class="slide" ng-include="..."></ANY> - * ``` + * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML + * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation. * - * Keep in mind that, by default, if an animation is running, any child elements cannot be animated - * until the parent element's animation has completed. This blocking feature can be overridden by - * placing the `ng-animate-children` attribute on a parent container tag. + * The example below shows how an `enter` animation can be made possible on a element using `ng-if`: * * ```html - * <div class="slide-animation" ng-if="on" ng-animate-children> - * <div class="fade-animation" ng-if="on"> - * <div class="explode-animation" ng-if="on"> - * ... - * </div> - * </div> + * <div ng-if="bool" class="fade"> + * Fade me in out * </div> + * <button ng-click="bool=true">Fade In!</button> + * <button ng-click="bool=false">Fade Out!</button> * ``` * - * When the `on` expression value changes and an animation is triggered then each of the elements within - * will all animate without the block being applied to child elements. - * - * ## Are animations run when the application starts? - * No they are not. When an application is bootstrapped Angular will disable animations from running to avoid - * a frenzy of animations from being triggered as soon as the browser has rendered the screen. For this to work, - * Angular will wait for two digest cycles until enabling animations. From there on, any animation-triggering - * layout changes in the application will trigger animations as normal. + * Notice the CSS class **fade**? We can now create the CSS transition code that references this class: * - * In addition, upon bootstrap, if the routing system or any directives or load remote data (via $http) then Angular - * will automatically extend the wait time to enable animations once **all** of the outbound HTTP requests - * are complete. - * - * ## CSS-defined Animations - * The animate service will automatically apply two CSS classes to the animated element and these two CSS classes - * are designed to contain the start and end CSS styling. Both CSS transitions and keyframe animations are supported - * and can be used to play along with this naming structure. - * - * The following code below demonstrates how to perform animations using **CSS transitions** with Angular: - * - * ```html - * <style type="text/css"> - * /* - * The animate class is apart of the element and the ng-enter class - * is attached to the element once the enter animation event is triggered - * */ - * .reveal-animation.ng-enter { - * -webkit-transition: 1s linear all; /* Safari/Chrome */ - * transition: 1s linear all; /* All other modern browsers and IE10+ */ - * - * /* The animation preparation code */ - * opacity: 0; + * ```css + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter { + * transition:0.5s linear all; + * opacity:0; * } * - * /* - * Keep in mind that you want to combine both CSS - * classes together to avoid any CSS-specificity - * conflicts - * */ - * .reveal-animation.ng-enter.ng-enter-active { - * /* The animation code itself */ - * opacity: 1; + * /* The finishing CSS styles for the enter animation */ + * .fade.ng-enter.ng-enter-active { + * opacity:1; * } - * </style> - * - * <div class="view-container"> - * <div ng-view class="reveal-animation"></div> - * </div> * ``` * - * The following code below demonstrates how to perform animations using **CSS animations** with Angular: - * - * ```html - * <style type="text/css"> - * .reveal-animation.ng-enter { - * -webkit-animation: enter_sequence 1s linear; /* Safari/Chrome */ - * animation: enter_sequence 1s linear; /* IE10+ and Future Browsers */ - * } - * @-webkit-keyframes enter_sequence { - * from { opacity:0; } - * to { opacity:1; } - * } - * @keyframes enter_sequence { - * from { opacity:0; } - * to { opacity:1; } - * } - * </style> - * - * <div class="view-container"> - * <div ng-view class="reveal-animation"></div> - * </div> - * ``` + * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two + * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition + * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards. * - * Both CSS3 animations and transitions can be used together and the animate service will figure out the correct duration and delay timing. - * - * Upon DOM mutation, the event class is added first (something like `ng-enter`), then the browser prepares itself to add - * the active class (in this case `ng-enter-active`) which then triggers the animation. The animation module will automatically - * detect the CSS code to determine when the animation ends. Once the animation is over then both CSS classes will be - * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end - * immediately resulting in a DOM element that is at its final state. This final state is when the DOM element - * has no CSS transition/animation classes applied to it. - * - * ### Structural transition animations - * - * Structural transitions (such as enter, leave and move) will always apply a `0s none` transition - * value to force the browser into rendering the styles defined in the setup (`.ng-enter`, `.ng-leave` - * or `.ng-move`) class. This means that any active transition animations operating on the element - * will be cut off to make way for the enter, leave or move animation. - * - * ### Class-based transition animations - * - * Class-based transitions refer to transition animations that are triggered when a CSS class is - * added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`, - * `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`). - * They are different when compared to structural animations since they **do not cancel existing - * animations** nor do they **block successive transitions** from rendering on the same element. - * This distinction allows for **multiple class-based transitions** to be performed on the same element. - * - * In addition to ngAnimate supporting the default (natural) functionality of class-based transition - * animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the - * developer in further styling the element throughout the transition animation. Earlier versions - * of ngAnimate may have caused natural CSS transitions to break and not render properly due to - * $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class - * (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of - * **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS - * class transitions are compatible with ngAnimate. - * - * There is, however, one special case when dealing with class-based transitions in ngAnimate. - * When rendering class-based transitions that make use of the setup and active CSS classes - * (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define - * the transition value **on the active CSS class** and not the setup class. + * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions: * * ```css - * .fade-add { - * /* remember to place a 0s transition here - * to ensure that the styles are applied instantly - * even if the element already has a transition style */ - * transition:0s linear all; - * - * /* starting CSS styles */ + * /* now the element will fade out before it is removed from the DOM */ + * .fade.ng-leave { + * transition:0.5s linear all; * opacity:1; * } - * .fade-add.fade-add-active { - * /* this will be the length of the animation */ - * transition:1s linear all; + * .fade.ng-leave.ng-leave-active { * opacity:0; * } * ``` * - * The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it - * has a duration of zero. This may not be required, however, incase the browser is unable to render - * the styling present in this CSS class instantly then it could be that the browser is attempting - * to perform an unnecessary transition. - * - * This workaround, however, does not apply to standard class-based transitions that are rendered - * when a CSS class containing a transition is applied to an element: + * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class: * * ```css - * /* this works as expected */ - * .fade { - * transition:1s linear all; - * opacity:0; + * /* there is no need to define anything inside of the destination + * CSS class since the keyframe will take charge of the animation */ + * .fade.ng-leave { + * animation: my_fade_animation 0.5s linear; + * -webkit-animation: my_fade_animation 0.5s linear; + * } + * + * @keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * + * @-webkit-keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } * } * ``` * - * Please keep this in mind when coding the CSS markup that will be used within class-based transitions. - * Also, try not to mix the two class-based animation flavors together since the CSS code may become - * overly complex. + * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element. * + * ### CSS Class-based Animations * - * ### Preventing Collisions With Third Party Libraries + * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different + * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added + * and removed. * - * Some third-party frameworks place animation duration defaults across many element or className - * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which - * is expecting actual animations on these elements and has to wait for their completion. + * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class: * - * You can prevent this unwanted behavior by using a prefix on all your animation classes: + * ```html + * <div ng-show="bool" class="fade"> + * Show and hide me + * </div> + * <button ng-click="bool=true">Toggle</button> * - * ```css - * /* prefixed with animate- */ - * .animate-fade-add.animate-fade-add-active { - * transition:1s linear all; + * <style> + * .fade.ng-hide { + * transition:0.5s linear all; * opacity:0; * } + * </style> * ``` * - * You then configure `$animate` to enforce this prefix: + * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since + * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest. * - * ```js - * $animateProvider.classNameFilter(/animate-/); - * ``` + * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation + * with CSS styles. + * + * ```html + * <div ng-class="{on:onOff}" class="highlight"> + * Highlight this box * </div> + * <button ng-click="onOff=!onOff">Toggle</button> + * + * <style> + * .highlight { + * transition:0.5s linear all; + * } + * .highlight.on-add { + * background:white; + * } + * .highlight.on { + * background:yellow; + * } + * .highlight.on-remove { + * background:black; + * } + * </style> + * ``` + * + * We can also make use of CSS keyframes by placing them within the CSS classes. + * * * ### CSS Staggering Animations * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a @@ -35224,18 +44825,15 @@ var minlengthDirective = function() { * ```css * .my-animation.ng-enter { * /* standard transition code */ - * -webkit-transition: 1s linear all; * transition: 1s linear all; * opacity:0; * } * .my-animation.ng-enter-stagger { * /* this will have a 100ms delay between each successive leave animation */ - * -webkit-transition-delay: 0.1s; * transition-delay: 0.1s; * - * /* in case the stagger doesn't work then these two values + * /* in case the stagger doesn't work then the duration value * must be set to 0 to avoid an accidental CSS inheritance */ - * -webkit-transition-duration: 0s; * transition-duration: 0s; * } * .my-animation.ng-enter.ng-enter-active { @@ -35247,7 +44845,7 @@ var minlengthDirective = function() { * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation - * will also be reset if more than 10ms has passed after the last animation has been fired. + * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired. * * The following code will issue the **ng-leave-stagger** event on the element provided: * @@ -35260,1843 +44858,547 @@ var minlengthDirective = function() { * $animate.leave(kids[3]); //stagger index=3 * $animate.leave(kids[4]); //stagger index=4 * - * $timeout(function() { + * window.requestAnimationFrame(function() { * //stagger has reset itself * $animate.leave(kids[5]); //stagger index=0 * $animate.leave(kids[6]); //stagger index=1 - * }, 100, false); - * ``` - * - * Stagger animations are currently only supported within CSS-defined animations. - * - * ## JavaScript-defined Animations - * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations on browsers that do not - * yet support CSS transitions/animations, then you can make use of JavaScript animations defined inside of your AngularJS module. - * - * ```js - * //!annotate="YourApp" Your AngularJS Module|Replace this or ngModule with the module that you used to define your application. - * var ngModule = angular.module('YourApp', ['ngAnimate']); - * ngModule.animation('.my-crazy-animation', function() { - * return { - * enter: function(element, done) { - * //run the animation here and call done when the animation is complete - * return function(cancelled) { - * //this (optional) function will be called when the animation - * //completes or when the animation is cancelled (the cancelled - * //flag will be set to true if cancelled). - * }; - * }, - * leave: function(element, done) { }, - * move: function(element, done) { }, - * - * //animation that can be triggered before the class is added - * beforeAddClass: function(element, className, done) { }, - * - * //animation that can be triggered after the class is added - * addClass: function(element, className, done) { }, * - * //animation that can be triggered before the class is removed - * beforeRemoveClass: function(element, className, done) { }, - * - * //animation that can be triggered after the class is removed - * removeClass: function(element, className, done) { } - * }; + * $scope.$digest(); * }); * ``` * - * JavaScript-defined animations are created with a CSS-like class selector and a collection of events which are set to run - * a javascript callback function. When an animation is triggered, $animate will look for a matching animation which fits - * the element's CSS class attribute value and then run the matching animation event function (if found). - * In other words, if the CSS classes present on the animated element match any of the JavaScript animations then the callback function will - * be executed. It should be also noted that only simple, single class selectors are allowed (compound class selectors are not supported). - * - * Within a JavaScript animation, an object containing various event callback animation functions is expected to be returned. - * As explained above, these callbacks are triggered based on the animation event. Therefore if an enter animation is run, - * and the JavaScript animation is found, then the enter callback will handle that animation (in addition to the CSS keyframe animation - * or transition code that is defined via a stylesheet). - * - * - * ### Applying Directive-specific Styles to an Animation - * In some cases a directive or service may want to provide `$animate` with extra details that the animation will - * include into its animation. Let's say for example we wanted to render an animation that animates an element - * towards the mouse coordinates as to where the user clicked last. By collecting the X/Y coordinates of the click - * (via the event parameter) we can set the `top` and `left` styles into an object and pass that into our function - * call to `$animate.addClass`. - * - * ```js - * canvas.on('click', function(e) { - * $animate.addClass(element, 'on', { - * to: { - * left : e.client.x + 'px', - * top : e.client.y + 'px' - * } - * }): - * }); - * ``` + * Stagger animations are currently only supported within CSS-defined animations. * - * Now when the animation runs, and a transition or keyframe animation is picked up, then the animation itself will - * also include and transition the styling of the `left` and `top` properties into its running animation. If we want - * to provide some starting animation values then we can do so by placing the starting animations styles into an object - * called `from` in the same object as the `to` animations. + * ### The `ng-animate` CSS class * - * ```js - * canvas.on('click', function(e) { - * $animate.addClass(element, 'on', { - * from: { - * position: 'absolute', - * left: '0px', - * top: '0px' - * }, - * to: { - * left : e.client.x + 'px', - * top : e.client.y + 'px' - * } - * }): - * }); - * ``` + * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation. + * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations). * - * Once the animation is complete or cancelled then the union of both the before and after styles are applied to the - * element. If `ngAnimate` is not present then the styles will be applied immediately. + * Therefore, animations can be applied to an element using this temporary class directly via CSS. * - */ - -angular.module('ngAnimate', ['ng']) - - /** - * @ngdoc provider - * @name $animateProvider - * @description - * - * The `$animateProvider` allows developers to register JavaScript animation event handlers directly inside of a module. - * When an animation is triggered, the $animate service will query the $animate service to find any animations that match - * the provided name value. - * - * Requires the {@link ngAnimate `ngAnimate`} module to be installed. - * - * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. - * - */ - .directive('ngAnimateChildren', function() { - var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren'; - return function(scope, element, attrs) { - var val = attrs.ngAnimateChildren; - if (angular.isString(val) && val.length === 0) { //empty attribute - element.data(NG_ANIMATE_CHILDREN, true); - } else { - scope.$watch(val, function(value) { - element.data(NG_ANIMATE_CHILDREN, !!value); - }); - } - }; - }) - - //this private service is only used within CSS-enabled animations - //IE8 + IE9 do not support rAF natively, but that is fine since they - //also don't support transitions and keyframes which means that the code - //below will never be used by the two browsers. - .factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) { - var bod = $document[0].body; - return function(fn) { - //the returned function acts as the cancellation function - return $$rAF(function() { - //the line below will force the browser to perform a repaint - //so that all the animated elements within the animation frame - //will be properly updated and drawn on screen. This is - //required to perform multi-class CSS based animations with - //Firefox. DO NOT REMOVE THIS LINE. - var a = bod.offsetWidth + 1; - fn(); - }); - }; - }]) - - .config(['$provide', '$animateProvider', function($provide, $animateProvider) { - var noop = angular.noop; - var forEach = angular.forEach; - var selectors = $animateProvider.$$selectors; - var isArray = angular.isArray; - var isString = angular.isString; - var isObject = angular.isObject; - - var ELEMENT_NODE = 1; - var NG_ANIMATE_STATE = '$$ngAnimateState'; - var NG_ANIMATE_CHILDREN = '$$ngAnimateChildren'; - var NG_ANIMATE_CLASS_NAME = 'ng-animate'; - var rootAnimateState = {running: true}; - - function extractElementNode(element) { - for (var i = 0; i < element.length; i++) { - var elm = element[i]; - if (elm.nodeType == ELEMENT_NODE) { - return elm; - } - } - } - - function prepareElement(element) { - return element && angular.element(element); - } - - function stripCommentsFromElement(element) { - return angular.element(extractElementNode(element)); - } - - function isMatchingElement(elm1, elm2) { - return extractElementNode(elm1) == extractElementNode(elm2); - } - var $$jqLite; - $provide.decorator('$animate', - ['$delegate', '$$q', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document', '$templateRequest', '$$jqLite', - function($delegate, $$q, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document, $templateRequest, $$$jqLite) { - - $$jqLite = $$$jqLite; - $rootElement.data(NG_ANIMATE_STATE, rootAnimateState); - - // Wait until all directive and route-related templates are downloaded and - // compiled. The $templateRequest.totalPendingRequests variable keeps track of - // all of the remote templates being currently downloaded. If there are no - // templates currently downloading then the watcher will still fire anyway. - var deregisterWatch = $rootScope.$watch( - function() { return $templateRequest.totalPendingRequests; }, - function(val, oldVal) { - if (val !== 0) return; - deregisterWatch(); - - // Now that all templates have been downloaded, $animate will wait until - // the post digest queue is empty before enabling animations. By having two - // calls to $postDigest calls we can ensure that the flag is enabled at the - // very end of the post digest queue. Since all of the animations in $animate - // use $postDigest, it's important that the code below executes at the end. - // This basically means that the page is fully downloaded and compiled before - // any animations are triggered. - $rootScope.$$postDigest(function() { - $rootScope.$$postDigest(function() { - rootAnimateState.running = false; - }); - }); - } - ); - - var globalAnimationCounter = 0; - var classNameFilter = $animateProvider.classNameFilter(); - var isAnimatableClassName = !classNameFilter - ? function() { return true; } - : function(className) { - return classNameFilter.test(className); - }; - - function classBasedAnimationsBlocked(element, setter) { - var data = element.data(NG_ANIMATE_STATE) || {}; - if (setter) { - data.running = true; - data.structural = true; - element.data(NG_ANIMATE_STATE, data); - } - return data.disabled || (data.running && data.structural); - } - - function runAnimationPostDigest(fn) { - var cancelFn, defer = $$q.defer(); - defer.promise.$$cancelFn = function() { - cancelFn && cancelFn(); - }; - $rootScope.$$postDigest(function() { - cancelFn = fn(function() { - defer.resolve(); - }); - }); - return defer.promise; - } - - function parseAnimateOptions(options) { - // some plugin code may still be passing in the callback - // function as the last param for the $animate methods so - // it's best to only allow string or array values for now - if (isObject(options)) { - if (options.tempClasses && isString(options.tempClasses)) { - options.tempClasses = options.tempClasses.split(/\s+/); - } - return options; - } - } - - function resolveElementClasses(element, cache, runningAnimations) { - runningAnimations = runningAnimations || {}; - - var lookup = {}; - forEach(runningAnimations, function(data, selector) { - forEach(selector.split(' '), function(s) { - lookup[s]=data; - }); - }); - - var hasClasses = Object.create(null); - forEach((element.attr('class') || '').split(/\s+/), function(className) { - hasClasses[className] = true; - }); - - var toAdd = [], toRemove = []; - forEach((cache && cache.classes) || [], function(status, className) { - var hasClass = hasClasses[className]; - var matchingAnimation = lookup[className] || {}; - - // When addClass and removeClass is called then $animate will check to - // see if addClass and removeClass cancel each other out. When there are - // more calls to removeClass than addClass then the count falls below 0 - // and then the removeClass animation will be allowed. Otherwise if the - // count is above 0 then that means an addClass animation will commence. - // Once an animation is allowed then the code will also check to see if - // there exists any on-going animation that is already adding or remvoing - // the matching CSS class. - if (status === false) { - //does it have the class or will it have the class - if (hasClass || matchingAnimation.event == 'addClass') { - toRemove.push(className); - } - } else if (status === true) { - //is the class missing or will it be removed? - if (!hasClass || matchingAnimation.event == 'removeClass') { - toAdd.push(className); - } - } - }); - - return (toAdd.length + toRemove.length) > 0 && [toAdd.join(' '), toRemove.join(' ')]; - } - - function lookup(name) { - if (name) { - var matches = [], - flagMap = {}, - classes = name.substr(1).split('.'); - - //the empty string value is the default animation - //operation which performs CSS transition and keyframe - //animations sniffing. This is always included for each - //element animation procedure if the browser supports - //transitions and/or keyframe animations. The default - //animation is added to the top of the list to prevent - //any previous animations from affecting the element styling - //prior to the element being animated. - if ($sniffer.transitions || $sniffer.animations) { - matches.push($injector.get(selectors[''])); - } - - for (var i=0; i < classes.length; i++) { - var klass = classes[i], - selectorFactoryName = selectors[klass]; - if (selectorFactoryName && !flagMap[klass]) { - matches.push($injector.get(selectorFactoryName)); - flagMap[klass] = true; - } - } - return matches; - } - } - - function animationRunner(element, animationEvent, className, options) { - //transcluded directives may sometimes fire an animation using only comment nodes - //best to catch this early on to prevent any animation operations from occurring - var node = element[0]; - if (!node) { - return; - } - - if (options) { - options.to = options.to || {}; - options.from = options.from || {}; - } - - var classNameAdd; - var classNameRemove; - if (isArray(className)) { - classNameAdd = className[0]; - classNameRemove = className[1]; - if (!classNameAdd) { - className = classNameRemove; - animationEvent = 'removeClass'; - } else if (!classNameRemove) { - className = classNameAdd; - animationEvent = 'addClass'; - } else { - className = classNameAdd + ' ' + classNameRemove; - } - } - - var isSetClassOperation = animationEvent == 'setClass'; - var isClassBased = isSetClassOperation - || animationEvent == 'addClass' - || animationEvent == 'removeClass' - || animationEvent == 'animate'; - - var currentClassName = element.attr('class'); - var classes = currentClassName + ' ' + className; - if (!isAnimatableClassName(classes)) { - return; - } - - var beforeComplete = noop, - beforeCancel = [], - before = [], - afterComplete = noop, - afterCancel = [], - after = []; - - var animationLookup = (' ' + classes).replace(/\s+/g,'.'); - forEach(lookup(animationLookup), function(animationFactory) { - var created = registerAnimation(animationFactory, animationEvent); - if (!created && isSetClassOperation) { - registerAnimation(animationFactory, 'addClass'); - registerAnimation(animationFactory, 'removeClass'); - } - }); - - function registerAnimation(animationFactory, event) { - var afterFn = animationFactory[event]; - var beforeFn = animationFactory['before' + event.charAt(0).toUpperCase() + event.substr(1)]; - if (afterFn || beforeFn) { - if (event == 'leave') { - beforeFn = afterFn; - //when set as null then animation knows to skip this phase - afterFn = null; - } - after.push({ - event: event, fn: afterFn - }); - before.push({ - event: event, fn: beforeFn - }); - return true; - } - } - - function run(fns, cancellations, allCompleteFn) { - var animations = []; - forEach(fns, function(animation) { - animation.fn && animations.push(animation); - }); - - var count = 0; - function afterAnimationComplete(index) { - if (cancellations) { - (cancellations[index] || noop)(); - if (++count < animations.length) return; - cancellations = null; - } - allCompleteFn(); - } - - //The code below adds directly to the array in order to work with - //both sync and async animations. Sync animations are when the done() - //operation is called right away. DO NOT REFACTOR! - forEach(animations, function(animation, index) { - var progress = function() { - afterAnimationComplete(index); - }; - switch (animation.event) { - case 'setClass': - cancellations.push(animation.fn(element, classNameAdd, classNameRemove, progress, options)); - break; - case 'animate': - cancellations.push(animation.fn(element, className, options.from, options.to, progress)); - break; - case 'addClass': - cancellations.push(animation.fn(element, classNameAdd || className, progress, options)); - break; - case 'removeClass': - cancellations.push(animation.fn(element, classNameRemove || className, progress, options)); - break; - default: - cancellations.push(animation.fn(element, progress, options)); - break; - } - }); - - if (cancellations && cancellations.length === 0) { - allCompleteFn(); - } - } - - return { - node: node, - event: animationEvent, - className: className, - isClassBased: isClassBased, - isSetClassOperation: isSetClassOperation, - applyStyles: function() { - if (options) { - element.css(angular.extend(options.from || {}, options.to || {})); - } - }, - before: function(allCompleteFn) { - beforeComplete = allCompleteFn; - run(before, beforeCancel, function() { - beforeComplete = noop; - allCompleteFn(); - }); - }, - after: function(allCompleteFn) { - afterComplete = allCompleteFn; - run(after, afterCancel, function() { - afterComplete = noop; - allCompleteFn(); - }); - }, - cancel: function() { - if (beforeCancel) { - forEach(beforeCancel, function(cancelFn) { - (cancelFn || noop)(true); - }); - beforeComplete(true); - } - if (afterCancel) { - forEach(afterCancel, function(cancelFn) { - (cancelFn || noop)(true); - }); - afterComplete(true); - } - } - }; - } - - /** - * @ngdoc service - * @name $animate - * @kind object - * - * @description - * The `$animate` service provides animation detection support while performing DOM operations (enter, leave and move) as well as during addClass and removeClass operations. - * When any of these operations are run, the $animate service - * will examine any JavaScript-defined animations (which are defined by using the $animateProvider provider object) - * as well as any CSS-defined animations against the CSS classes present on the element once the DOM operation is run. - * - * The `$animate` service is used behind the scenes with pre-existing directives and animation with these directives - * will work out of the box without any extra configuration. - * - * Requires the {@link ngAnimate `ngAnimate`} module to be installed. - * - * Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application. - * ## Callback Promises - * With AngularJS 1.3, each of the animation methods, on the `$animate` service, return a promise when called. The - * promise itself is then resolved once the animation has completed itself, has been cancelled or has been - * skipped due to animations being disabled. (Note that even if the animation is cancelled it will still - * call the resolve function of the animation.) - * - * ```js - * $animate.enter(element, container).then(function() { - * //...this is called once the animation is complete... - * }); - * ``` - * - * Also note that, due to the nature of the callback promise, if any Angular-specific code (like changing the scope, - * location of the page, etc...) is executed within the callback promise then be sure to wrap the code using - * `$scope.$apply(...)`; - * - * ```js - * $animate.leave(element).then(function() { - * $scope.$apply(function() { - * $location.path('/new-page'); - * }); - * }); - * ``` - * - * An animation can also be cancelled by calling the `$animate.cancel(promise)` method with the provided - * promise that was returned when the animation was started. - * - * ```js - * var promise = $animate.addClass(element, 'super-long-animation'); - * promise.then(function() { - * //this will still be called even if cancelled - * }); - * - * element.on('click', function() { - * //tooo lazy to wait for the animation to end - * $animate.cancel(promise); - * }); - * ``` - * - * (Keep in mind that the promise cancellation is unique to `$animate` since promises in - * general cannot be cancelled.) - * - */ - return { - /** - * @ngdoc method - * @name $animate#animate - * @kind function - * - * @description - * Performs an inline animation on the element which applies the provided `to` and `from` CSS styles to the element. - * If any detected CSS transition, keyframe or JavaScript matches the provided `className` value then the animation - * will take on the provided styles. For example, if a transition animation is set for the given className then the - * provided `from` and `to` styles will be applied alongside the given transition. If a JavaScript animation is - * detected then the provided styles will be given in as function paramters. - * - * ```js - * ngModule.animation('.my-inline-animation', function() { - * return { - * animate : function(element, className, from, to, done) { - * //styles - * } - * } - * }); - * ``` - * - * Below is a breakdown of each step that occurs during the `animate` animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------| - * | 1. `$animate.animate(...)` is called | `class="my-animation"` | - * | 2. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 3. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 4. the `className` class value is added to the element | `class="my-animation ng-animate className"` | - * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate className"` | - * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.className` class styling is applied right away| `class="my-animation ng-animate className"` | - * | 7. `$animate` applies the provided collection of `from` CSS styles to the element | `class="my-animation ng-animate className"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate className"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate className"` | - * | 10. the `className-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate className className-active"` | - * | 11. `$animate` applies the collection of `to` CSS styles to the element which are then handled by the transition | `class="my-animation ng-animate className className-active"` | - * | 12. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate className className-active"` | - * | 13. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 14. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the enter animation - * @param {object} from a collection of CSS styles that will be applied to the element at the start of the animation - * @param {object} to a collection of CSS styles that the element will animate towards - * @param {string=} className an optional CSS class that will be added to the element for the duration of the animation (the default class is `ng-inline-animate`) - * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - animate: function(element, from, to, className, options) { - className = className || 'ng-inline-animate'; - options = parseAnimateOptions(options) || {}; - options.from = to ? from : null; - options.to = to ? to : from; - - return runAnimationPostDigest(function(done) { - return performAnimation('animate', className, stripCommentsFromElement(element), null, null, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#enter - * @kind function - * - * @description - * Appends the element to the parentElement element that resides in the document and then runs the enter animation. Once - * the animation is started, the following CSS classes will be present on the element for the duration of the animation: - * - * Below is a breakdown of each step that occurs during enter animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------| - * | 1. `$animate.enter(...)` is called | `class="my-animation"` | - * | 2. element is inserted into the `parentElement` element or beside the `afterElement` element | `class="my-animation"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 5. the `.ng-enter` class is added to the element | `class="my-animation ng-animate ng-enter"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-enter"` | - * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-enter` class styling is applied right away | `class="my-animation ng-animate ng-enter"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-enter"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-enter"` | - * | 10. the `.ng-enter-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-enter ng-enter-active"` | - * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-enter ng-enter-active"` | - * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 13. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the enter animation - * @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation - * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation - * @param {object=} options an optional collection of options that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - enter: function(element, parentElement, afterElement, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - parentElement = prepareElement(parentElement); - afterElement = prepareElement(afterElement); - - classBasedAnimationsBlocked(element, true); - $delegate.enter(element, parentElement, afterElement); - return runAnimationPostDigest(function(done) { - return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#leave - * @kind function - * - * @description - * Runs the leave animation operation and, upon completion, removes the element from the DOM. Once - * the animation is started, the following CSS classes will be added for the duration of the animation: - * - * Below is a breakdown of each step that occurs during leave animation: - * - * | Animation Step | What the element class attribute looks like | - * |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------| - * | 1. `$animate.leave(...)` is called | `class="my-animation"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. the `.ng-leave` class is added to the element | `class="my-animation ng-animate ng-leave"` | - * | 5. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-leave"` | - * | 6. `$animate` blocks all CSS transitions on the element to ensure the `.ng-leave` class styling is applied right away | `class="my-animation ng-animate ng-leave"` | - * | 7. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-leave"` | - * | 8. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-leave"` | - * | 9. the `.ng-leave-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-leave ng-leave-active"` | - * | 10. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-leave ng-leave-active"` | - * | 11. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 12. The element is removed from the DOM | ... | - * | 13. The returned promise is resolved. | ... | - * - * @param {DOMElement} element the element that will be the focus of the leave animation - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - leave: function(element, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - - cancelChildAnimations(element); - classBasedAnimationsBlocked(element, true); - return runAnimationPostDigest(function(done) { - return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() { - $delegate.leave(element); - }, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#move - * @kind function - * - * @description - * Fires the move DOM operation. Just before the animation starts, the animate service will either append it into the parentElement container or - * add the element directly after the afterElement element if present. Then the move animation will be run. Once - * the animation is started, the following CSS classes will be added for the duration of the animation: - * - * Below is a breakdown of each step that occurs during move animation: - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------| - * | 1. `$animate.move(...)` is called | `class="my-animation"` | - * | 2. element is moved into the parentElement element or beside the afterElement element | `class="my-animation"` | - * | 3. `$animate` waits for the next digest to start the animation | `class="my-animation ng-animate"` | - * | 4. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 5. the `.ng-move` class is added to the element | `class="my-animation ng-animate ng-move"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate ng-move"` | - * | 7. `$animate` blocks all CSS transitions on the element to ensure the `.ng-move` class styling is applied right away | `class="my-animation ng-animate ng-move"` | - * | 8. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate ng-move"` | - * | 9. `$animate` removes the CSS transition block placed on the element | `class="my-animation ng-animate ng-move"` | - * | 10. the `.ng-move-active` class is added (this triggers the CSS transition/animation) | `class="my-animation ng-animate ng-move ng-move-active"` | - * | 11. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate ng-move ng-move-active"` | - * | 12. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 13. The returned promise is resolved. | `class="my-animation"` | - * - * @param {DOMElement} element the element that will be the focus of the move animation - * @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation - * @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - move: function(element, parentElement, afterElement, options) { - options = parseAnimateOptions(options); - element = angular.element(element); - parentElement = prepareElement(parentElement); - afterElement = prepareElement(afterElement); - - cancelChildAnimations(element); - classBasedAnimationsBlocked(element, true); - $delegate.move(element, parentElement, afterElement); - return runAnimationPostDigest(function(done) { - return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#addClass - * - * @description - * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class. - * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide - * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions - * or keyframes are defined on the -add-active or base CSS class). - * - * Below is a breakdown of each step that occurs during addClass animation: - * - * | Animation Step | What the element class attribute looks like | - * |--------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| - * | 1. `$animate.addClass(element, 'super')` is called | `class="my-animation"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate"` | - * | 3. the `.super-add` class is added to the element | `class="my-animation ng-animate super-add"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate super-add"` | - * | 5. the `.super` and `.super-add-active` classes are added (this triggers the CSS transition/animation) | `class="my-animation ng-animate super super-add super-add-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super super-add super-add-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super super-add super-add-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation super"` | - * | 9. The super class is kept on the element | `class="my-animation super"` | - * | 10. The returned promise is resolved. | `class="my-animation super"` | - * - * @param {DOMElement} element the element that will be animated - * @param {string} className the CSS class that will be added to the element and then animated - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - addClass: function(element, className, options) { - return this.setClass(element, className, [], options); - }, - - /** - * @ngdoc method - * @name $animate#removeClass - * - * @description - * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value - * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in - * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if - * no CSS transitions or keyframes are defined on the -remove or base CSS classes). - * - * Below is a breakdown of each step that occurs during removeClass animation: - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------| - * | 1. `$animate.removeClass(element, 'super')` is called | `class="my-animation super"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation super ng-animate"` | - * | 3. the `.super-remove` class is added to the element | `class="my-animation super ng-animate super-remove"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation super ng-animate super-remove"` | - * | 5. the `.super-remove-active` classes are added and `.super` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate super-remove super-remove-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation"` | - * | 9. The returned promise is resolved. | `class="my-animation"` | - * - * - * @param {DOMElement} element the element that will be animated - * @param {string} className the CSS class that will be animated and then removed from the element - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - removeClass: function(element, className, options) { - return this.setClass(element, [], className, options); - }, - - /** - * - * @ngdoc method - * @name $animate#setClass - * - * @description Adds and/or removes the given CSS classes to and from the element. - * Once complete, the `done()` callback will be fired (if provided). - * - * | Animation Step | What the element class attribute looks like | - * |----------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------| - * | 1. `$animate.setClass(element, 'on', 'off')` is called | `class="my-animation off"` | - * | 2. `$animate` runs the JavaScript-defined animations detected on the element | `class="my-animation ng-animate off"` | - * | 3. the `.on-add` and `.off-remove` classes are added to the element | `class="my-animation ng-animate on-add off-remove off"` | - * | 4. `$animate` waits for a single animation frame (this performs a reflow) | `class="my-animation ng-animate on-add off-remove off"` | - * | 5. the `.on`, `.on-add-active` and `.off-remove-active` classes are added and `.off` is removed (this triggers the CSS transition/animation) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 6. `$animate` scans the element styles to get the CSS transition/animation duration and delay | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 7. `$animate` waits for the animation to complete (via events and timeout) | `class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active"` | - * | 8. The animation ends and all generated CSS classes are removed from the element | `class="my-animation on"` | - * | 9. The returned promise is resolved. | `class="my-animation on"` | - * - * @param {DOMElement} element the element which will have its CSS classes changed - * removed from it - * @param {string} add the CSS classes which will be added to the element - * @param {string} remove the CSS class which will be removed from the element - * CSS classes have been set on the element - * @param {object=} options an optional collection of styles that will be picked up by the CSS transition/animation - * @return {Promise} the animation callback promise - */ - setClass: function(element, add, remove, options) { - options = parseAnimateOptions(options); - - var STORAGE_KEY = '$$animateClasses'; - element = angular.element(element); - element = stripCommentsFromElement(element); - - if (classBasedAnimationsBlocked(element)) { - return $delegate.$$setClassImmediately(element, add, remove, options); - } - - // we're using a combined array for both the add and remove - // operations since the ORDER OF addClass and removeClass matters - var classes, cache = element.data(STORAGE_KEY); - var hasCache = !!cache; - if (!cache) { - cache = {}; - cache.classes = {}; - } - classes = cache.classes; - - add = isArray(add) ? add : add.split(' '); - forEach(add, function(c) { - if (c && c.length) { - classes[c] = true; - } - }); - - remove = isArray(remove) ? remove : remove.split(' '); - forEach(remove, function(c) { - if (c && c.length) { - classes[c] = false; - } - }); - - if (hasCache) { - if (options && cache.options) { - cache.options = angular.extend(cache.options || {}, options); - } - - //the digest cycle will combine all the animations into one function - return cache.promise; - } else { - element.data(STORAGE_KEY, cache = { - classes: classes, - options: options - }); - } - - return cache.promise = runAnimationPostDigest(function(done) { - var parentElement = element.parent(); - var elementNode = extractElementNode(element); - var parentNode = elementNode.parentNode; - // TODO(matsko): move this code into the animationsDisabled() function once #8092 is fixed - if (!parentNode || parentNode['$$NG_REMOVED'] || elementNode['$$NG_REMOVED']) { - done(); - return; - } - - var cache = element.data(STORAGE_KEY); - element.removeData(STORAGE_KEY); - - var state = element.data(NG_ANIMATE_STATE) || {}; - var classes = resolveElementClasses(element, cache, state.active); - return !classes - ? done() - : performAnimation('setClass', classes, element, parentElement, null, function() { - if (classes[0]) $delegate.$$addClassImmediately(element, classes[0]); - if (classes[1]) $delegate.$$removeClassImmediately(element, classes[1]); - }, cache.options, done); - }); - }, - - /** - * @ngdoc method - * @name $animate#cancel - * @kind function - * - * @param {Promise} animationPromise The animation promise that is returned when an animation is started. - * - * @description - * Cancels the provided animation. - */ - cancel: function(promise) { - promise.$$cancelFn(); - }, - - /** - * @ngdoc method - * @name $animate#enabled - * @kind function - * - * @param {boolean=} value If provided then set the animation on or off. - * @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation - * @return {boolean} Current animation state. - * - * @description - * Globally enables/disables animations. - * - */ - enabled: function(value, element) { - switch (arguments.length) { - case 2: - if (value) { - cleanup(element); - } else { - var data = element.data(NG_ANIMATE_STATE) || {}; - data.disabled = true; - element.data(NG_ANIMATE_STATE, data); - } - break; - - case 1: - rootAnimateState.disabled = !value; - break; - - default: - value = !rootAnimateState.disabled; - break; - } - return !!value; - } - }; - - /* - all animations call this shared animation triggering function internally. - The animationEvent variable refers to the JavaScript animation event that will be triggered - and the className value is the name of the animation that will be applied within the - CSS code. Element, `parentElement` and `afterElement` are provided DOM elements for the animation - and the onComplete callback will be fired once the animation is fully complete. - */ - function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, options, doneCallback) { - var noopCancel = noop; - var runner = animationRunner(element, animationEvent, className, options); - if (!runner) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - closeAnimation(); - return noopCancel; - } - - animationEvent = runner.event; - className = runner.className; - var elementEvents = angular.element._data(runner.node); - elementEvents = elementEvents && elementEvents.events; - - if (!parentElement) { - parentElement = afterElement ? afterElement.parent() : element.parent(); - } - - //skip the animation if animations are disabled, a parent is already being animated, - //the element is not currently attached to the document body or then completely close - //the animation if any matching animations are not found at all. - //NOTE: IE8 + IE9 should close properly (run closeAnimation()) in case an animation was found. - if (animationsDisabled(element, parentElement)) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - closeAnimation(); - return noopCancel; - } - - var ngAnimateState = element.data(NG_ANIMATE_STATE) || {}; - var runningAnimations = ngAnimateState.active || {}; - var totalActiveAnimations = ngAnimateState.totalActive || 0; - var lastAnimation = ngAnimateState.last; - var skipAnimation = false; - - if (totalActiveAnimations > 0) { - var animationsToCancel = []; - if (!runner.isClassBased) { - if (animationEvent == 'leave' && runningAnimations['ng-leave']) { - skipAnimation = true; - } else { - //cancel all animations when a structural animation takes place - for (var klass in runningAnimations) { - animationsToCancel.push(runningAnimations[klass]); - } - ngAnimateState = {}; - cleanup(element, true); - } - } else if (lastAnimation.event == 'setClass') { - animationsToCancel.push(lastAnimation); - cleanup(element, className); - } else if (runningAnimations[className]) { - var current = runningAnimations[className]; - if (current.event == animationEvent) { - skipAnimation = true; - } else { - animationsToCancel.push(current); - cleanup(element, className); - } - } - - if (animationsToCancel.length > 0) { - forEach(animationsToCancel, function(operation) { - operation.cancel(); - }); - } - } - - if (runner.isClassBased - && !runner.isSetClassOperation - && animationEvent != 'animate' - && !skipAnimation) { - skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR - } - - if (skipAnimation) { - fireDOMOperation(); - fireBeforeCallbackAsync(); - fireAfterCallbackAsync(); - fireDoneCallbackAsync(); - return noopCancel; - } - - runningAnimations = ngAnimateState.active || {}; - totalActiveAnimations = ngAnimateState.totalActive || 0; - - if (animationEvent == 'leave') { - //there's no need to ever remove the listener since the element - //will be removed (destroyed) after the leave animation ends or - //is cancelled midway - element.one('$destroy', function(e) { - var element = angular.element(this); - var state = element.data(NG_ANIMATE_STATE); - if (state) { - var activeLeaveAnimation = state.active['ng-leave']; - if (activeLeaveAnimation) { - activeLeaveAnimation.cancel(); - cleanup(element, 'ng-leave'); - } - } - }); - } - - //the ng-animate class does nothing, but it's here to allow for - //parent animations to find and cancel child animations when needed - $$jqLite.addClass(element, NG_ANIMATE_CLASS_NAME); - if (options && options.tempClasses) { - forEach(options.tempClasses, function(className) { - $$jqLite.addClass(element, className); - }); - } - - var localAnimationCount = globalAnimationCounter++; - totalActiveAnimations++; - runningAnimations[className] = runner; - - element.data(NG_ANIMATE_STATE, { - last: runner, - active: runningAnimations, - index: localAnimationCount, - totalActive: totalActiveAnimations - }); - - //first we run the before animations and when all of those are complete - //then we perform the DOM operation and run the next set of animations - fireBeforeCallbackAsync(); - runner.before(function(cancelled) { - var data = element.data(NG_ANIMATE_STATE); - cancelled = cancelled || - !data || !data.active[className] || - (runner.isClassBased && data.active[className].event != animationEvent); - - fireDOMOperation(); - if (cancelled === true) { - closeAnimation(); - } else { - fireAfterCallbackAsync(); - runner.after(closeAnimation); - } - }); - - return runner.cancel; - - function fireDOMCallback(animationPhase) { - var eventName = '$animate:' + animationPhase; - if (elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) { - $$asyncCallback(function() { - element.triggerHandler(eventName, { - event: animationEvent, - className: className - }); - }); - } - } - - function fireBeforeCallbackAsync() { - fireDOMCallback('before'); - } - - function fireAfterCallbackAsync() { - fireDOMCallback('after'); - } - - function fireDoneCallbackAsync() { - fireDOMCallback('close'); - doneCallback(); - } - - //it is less complicated to use a flag than managing and canceling - //timeouts containing multiple callbacks. - function fireDOMOperation() { - if (!fireDOMOperation.hasBeenRun) { - fireDOMOperation.hasBeenRun = true; - domOperation(); - } - } - - function closeAnimation() { - if (!closeAnimation.hasBeenRun) { - if (runner) { //the runner doesn't exist if it fails to instantiate - runner.applyStyles(); - } - - closeAnimation.hasBeenRun = true; - if (options && options.tempClasses) { - forEach(options.tempClasses, function(className) { - $$jqLite.removeClass(element, className); - }); - } - - var data = element.data(NG_ANIMATE_STATE); - if (data) { - - /* only structural animations wait for reflow before removing an - animation, but class-based animations don't. An example of this - failing would be when a parent HTML tag has a ng-class attribute - causing ALL directives below to skip animations during the digest */ - if (runner && runner.isClassBased) { - cleanup(element, className); - } else { - $$asyncCallback(function() { - var data = element.data(NG_ANIMATE_STATE) || {}; - if (localAnimationCount == data.index) { - cleanup(element, className, animationEvent); - } - }); - element.data(NG_ANIMATE_STATE, data); - } - } - fireDoneCallbackAsync(); - } - } - } - - function cancelChildAnimations(element) { - var node = extractElementNode(element); - if (node) { - var nodes = angular.isFunction(node.getElementsByClassName) ? - node.getElementsByClassName(NG_ANIMATE_CLASS_NAME) : - node.querySelectorAll('.' + NG_ANIMATE_CLASS_NAME); - forEach(nodes, function(element) { - element = angular.element(element); - var data = element.data(NG_ANIMATE_STATE); - if (data && data.active) { - forEach(data.active, function(runner) { - runner.cancel(); - }); - } - }); - } - } - - function cleanup(element, className) { - if (isMatchingElement(element, $rootElement)) { - if (!rootAnimateState.disabled) { - rootAnimateState.running = false; - rootAnimateState.structural = false; - } - } else if (className) { - var data = element.data(NG_ANIMATE_STATE) || {}; - - var removeAnimations = className === true; - if (!removeAnimations && data.active && data.active[className]) { - data.totalActive--; - delete data.active[className]; - } - - if (removeAnimations || !data.totalActive) { - $$jqLite.removeClass(element, NG_ANIMATE_CLASS_NAME); - element.removeData(NG_ANIMATE_STATE); - } - } - } - - function animationsDisabled(element, parentElement) { - if (rootAnimateState.disabled) { - return true; - } - - if (isMatchingElement(element, $rootElement)) { - return rootAnimateState.running; - } - - var allowChildAnimations, parentRunningAnimation, hasParent; - do { - //the element did not reach the root element which means that it - //is not apart of the DOM. Therefore there is no reason to do - //any animations on it - if (parentElement.length === 0) break; - - var isRoot = isMatchingElement(parentElement, $rootElement); - var state = isRoot ? rootAnimateState : (parentElement.data(NG_ANIMATE_STATE) || {}); - if (state.disabled) { - return true; - } - - //no matter what, for an animation to work it must reach the root element - //this implies that the element is attached to the DOM when the animation is run - if (isRoot) { - hasParent = true; - } - - //once a flag is found that is strictly false then everything before - //it will be discarded and all child animations will be restricted - if (allowChildAnimations !== false) { - var animateChildrenFlag = parentElement.data(NG_ANIMATE_CHILDREN); - if (angular.isDefined(animateChildrenFlag)) { - allowChildAnimations = animateChildrenFlag; - } - } - - parentRunningAnimation = parentRunningAnimation || - state.running || - (state.last && !state.last.isClassBased); - } - while (parentElement = parentElement.parent()); - - return !hasParent || (!allowChildAnimations && parentRunningAnimation); - } - }]); - - $animateProvider.register('', ['$window', '$sniffer', '$timeout', '$$animateReflow', - function($window, $sniffer, $timeout, $$animateReflow) { - // Detect proper transitionend/animationend event names. - var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; - - // If unprefixed events are not supported but webkit-prefixed are, use the latter. - // Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. - // Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` - // but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. - // Register both events in case `window.onanimationend` is not supported because of that, - // do the same for `transitionend` as Safari is likely to exhibit similar behavior. - // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit - // therefore there is no reason to test anymore for other vendor prefixes: http://caniuse.com/#search=transition - if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { - CSS_PREFIX = '-webkit-'; - TRANSITION_PROP = 'WebkitTransition'; - TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; - } else { - TRANSITION_PROP = 'transition'; - TRANSITIONEND_EVENT = 'transitionend'; - } - - if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { - CSS_PREFIX = '-webkit-'; - ANIMATION_PROP = 'WebkitAnimation'; - ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; - } else { - ANIMATION_PROP = 'animation'; - ANIMATIONEND_EVENT = 'animationend'; - } - - var DURATION_KEY = 'Duration'; - var PROPERTY_KEY = 'Property'; - var DELAY_KEY = 'Delay'; - var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; - var ANIMATION_PLAYSTATE_KEY = 'PlayState'; - var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey'; - var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data'; - var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; - var CLOSING_TIME_BUFFER = 1.5; - var ONE_SECOND = 1000; - - var lookupCache = {}; - var parentCounter = 0; - var animationReflowQueue = []; - var cancelAnimationReflow; - function clearCacheAfterReflow() { - if (!cancelAnimationReflow) { - cancelAnimationReflow = $$animateReflow(function() { - animationReflowQueue = []; - cancelAnimationReflow = null; - lookupCache = {}; - }); - } - } - - function afterReflow(element, callback) { - if (cancelAnimationReflow) { - cancelAnimationReflow(); - } - animationReflowQueue.push(callback); - cancelAnimationReflow = $$animateReflow(function() { - forEach(animationReflowQueue, function(fn) { - fn(); + * ```css + * .zipper.ng-animate { + * transition:0.5s linear all; + * } + * .zipper.ng-enter { + * opacity:0; + * } + * .zipper.ng-enter.ng-enter-active { + * opacity:1; + * } + * .zipper.ng-leave { + * opacity:1; + * } + * .zipper.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove + * the CSS class once an animation has completed.) + * + * + * ## JavaScript-based Animations + * + * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared + * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the + * `module.animation()` module function we can register the ainmation. + * + * Let's see an example of a enter/leave animation using `ngRepeat`: + * + * ```html + * <div ng-repeat="item in items" class="slide"> + * {{ item }} + * </div> + * ``` + * + * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`: + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * // make note that other events (like addClass/removeClass) + * // have different function input parameters + * enter: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * + * // remember to call doneFn so that angular + * // knows that the animation has concluded + * }, + * + * move: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * }, + * + * leave: function(element, doneFn) { + * jQuery(element).fadeOut(1000, doneFn); + * } + * } + * }] + * ``` + * + * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as + * greensock.js and velocity.js. + * + * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define + * our animations inside of the same registered animation, however, the function input arguments are a bit different: + * + * ```html + * <div ng-class="color" class="colorful"> + * this box is moody + * </div> + * <button ng-click="color='red'">Change to red</button> + * <button ng-click="color='blue'">Change to blue</button> + * <button ng-click="color='green'">Change to green</button> + * ``` + * + * ```js + * myModule.animation('.colorful', [function() { + * return { + * addClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * removeClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * setClass: function(element, addedClass, removedClass, doneFn) { + * // do some cool animation and call the doneFn + * } + * } + * }] + * ``` + * + * ## CSS + JS Animations Together + * + * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular, + * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking + * charge of the animation**: + * + * ```html + * <div ng-if="bool" class="slide"> + * Slide in and out + * </div> + * ``` + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * enter: function(element, doneFn) { + * jQuery(element).slideIn(1000, doneFn); + * } + * } + * }] + * ``` + * + * ```css + * .slide.ng-enter { + * transition:0.5s linear all; + * transform:translateY(-100px); + * } + * .slide.ng-enter.ng-enter-active { + * transform:translateY(0); + * } + * ``` + * + * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the + * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from + * our own JS-based animation code: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { +* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`. + * var runner = $animateCss(element, { + * event: 'enter', + * structural: true + * }).start(); +* runner.done(doneFn); + * } + * } + * }] + * ``` + * + * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework. + * + * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or + * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that + * data into `$animateCss` directly: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var runner = $animateCss(element, { + * event: 'enter', + * addClass: 'maroon-setting', + * from: { height:0 }, + * to: { height: 200 } + * }).start(); + * + * runner.done(doneFn); + * } + * } + * }] + * ``` + * + * Now we can fill in the rest via our transition CSS code: + * + * ```css + * /* the transition tells ngAnimate to make the animation happen */ + * .slide.ng-enter { transition:0.5s linear all; } + * + * /* this extra CSS class will be absorbed into the transition + * since the $animateCss code is adding the class */ + * .maroon-setting { background:red; } + * ``` + * + * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over. + * + * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}. + * + * ## Animation Anchoring (via `ng-animate-ref`) + * + * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between + * structural areas of an application (like views) by pairing up elements using an attribute + * called `ng-animate-ref`. + * + * Let's say for example we have two views that are managed by `ng-view` and we want to show + * that there is a relationship between two components situated in within these views. By using the + * `ng-animate-ref` attribute we can identify that the two components are paired together and we + * can then attach an animation, which is triggered when the view changes. + * + * Say for example we have the following template code: + * + * ```html + * <!-- index.html --> + * <div ng-view class="view-animation"> + * </div> + * + * <!-- home.html --> + * <a href="#/banner-page"> + * <img src="./banner.jpg" class="banner" ng-animate-ref="banner"> + * </a> + * + * <!-- banner-page.html --> + * <img src="./banner.jpg" class="banner" ng-animate-ref="banner"> + * ``` + * + * Now, when the view changes (once the link is clicked), ngAnimate will examine the + * HTML contents to see if there is a match reference between any components in the view + * that is leaving and the view that is entering. It will scan both the view which is being + * removed (leave) and inserted (enter) to see if there are any paired DOM elements that + * contain a matching ref value. + * + * The two images match since they share the same ref value. ngAnimate will now create a + * transport element (which is a clone of the first image element) and it will then attempt + * to animate to the position of the second image element in the next view. For the animation to + * work a special CSS class called `ng-anchor` will be added to the transported element. + * + * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then + * ngAnimate will handle the entire transition for us as well as the addition and removal of + * any changes of CSS classes between the elements: + * + * ```css + * .banner.ng-anchor { + * /* this animation will last for 1 second since there are + * two phases to the animation (an `in` and an `out` phase) */ + * transition:0.5s linear all; + * } + * ``` + * + * We also **must** include animations for the views that are being entered and removed + * (otherwise anchoring wouldn't be possible since the new view would be inserted right away). + * + * ```css + * .view-animation.ng-enter, .view-animation.ng-leave { + * transition:0.5s linear all; + * position:fixed; + * left:0; + * top:0; + * width:100%; + * } + * .view-animation.ng-enter { + * transform:translateX(100%); + * } + * .view-animation.ng-leave, + * .view-animation.ng-enter.ng-enter-active { + * transform:translateX(0%); + * } + * .view-animation.ng-leave.ng-leave-active { + * transform:translateX(-100%); + * } + * ``` + * + * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur: + * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away + * from its origin. Once that animation is over then the `in` stage occurs which animates the + * element to its destination. The reason why there are two animations is to give enough time + * for the enter animation on the new element to be ready. + * + * The example above sets up a transition for both the in and out phases, but we can also target the out or + * in phases directly via `ng-anchor-out` and `ng-anchor-in`. + * + * ```css + * .banner.ng-anchor-out { + * transition: 0.5s linear all; + * + * /* the scale will be applied during the out animation, + * but will be animated away when the in animation runs */ + * transform: scale(1.2); + * } + * + * .banner.ng-anchor-in { + * transition: 1s linear all; + * } + * ``` + * + * + * + * + * ### Anchoring Demo + * + <example module="anchoringExample" + name="anchoringExample" + id="anchoringExample" + deps="angular-animate.js;angular-route.js" + animations="true"> + <file name="index.html"> + <a href="#/">Home</a> + <hr /> + <div class="view-container"> + <div ng-view class="view"></div> + </div> + </file> + <file name="script.js"> + angular.module('anchoringExample', ['ngAnimate', 'ngRoute']) + .config(['$routeProvider', function($routeProvider) { + $routeProvider.when('/', { + templateUrl: 'home.html', + controller: 'HomeController as home' }); - - animationReflowQueue = []; - cancelAnimationReflow = null; - lookupCache = {}; - }); - } - - var closingTimer = null; - var closingTimestamp = 0; - var animationElementQueue = []; - function animationCloseHandler(element, totalTime) { - var node = extractElementNode(element); - element = angular.element(node); - - //this item will be garbage collected by the closing - //animation timeout - animationElementQueue.push(element); - - //but it may not need to cancel out the existing timeout - //if the timestamp is less than the previous one - var futureTimestamp = Date.now() + totalTime; - if (futureTimestamp <= closingTimestamp) { - return; - } - - $timeout.cancel(closingTimer); - - closingTimestamp = futureTimestamp; - closingTimer = $timeout(function() { - closeAllAnimations(animationElementQueue); - animationElementQueue = []; - }, totalTime, false); - } - - function closeAllAnimations(elements) { - forEach(elements, function(element) { - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (elementData) { - forEach(elementData.closeAnimationFns, function(fn) { - fn(); - }); - } - }); - } - - function getElementAnimationDetails(element, cacheKey) { - var data = cacheKey ? lookupCache[cacheKey] : null; - if (!data) { - var transitionDuration = 0; - var transitionDelay = 0; - var animationDuration = 0; - var animationDelay = 0; - - //we want all the styles defined before and after - forEach(element, function(element) { - if (element.nodeType == ELEMENT_NODE) { - var elementStyles = $window.getComputedStyle(element) || {}; - - var transitionDurationStyle = elementStyles[TRANSITION_PROP + DURATION_KEY]; - transitionDuration = Math.max(parseMaxTime(transitionDurationStyle), transitionDuration); - - var transitionDelayStyle = elementStyles[TRANSITION_PROP + DELAY_KEY]; - transitionDelay = Math.max(parseMaxTime(transitionDelayStyle), transitionDelay); - - var animationDelayStyle = elementStyles[ANIMATION_PROP + DELAY_KEY]; - animationDelay = Math.max(parseMaxTime(elementStyles[ANIMATION_PROP + DELAY_KEY]), animationDelay); - - var aDuration = parseMaxTime(elementStyles[ANIMATION_PROP + DURATION_KEY]); - - if (aDuration > 0) { - aDuration *= parseInt(elementStyles[ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY], 10) || 1; - } - animationDuration = Math.max(aDuration, animationDuration); - } + $routeProvider.when('/profile/:id', { + templateUrl: 'profile.html', + controller: 'ProfileController as profile' }); - data = { - total: 0, - transitionDelay: transitionDelay, - transitionDuration: transitionDuration, - animationDelay: animationDelay, - animationDuration: animationDuration - }; - if (cacheKey) { - lookupCache[cacheKey] = data; - } - } - return data; - } - - function parseMaxTime(str) { - var maxValue = 0; - var values = isString(str) ? - str.split(/\s*,\s*/) : - []; - forEach(values, function(value) { - maxValue = Math.max(parseFloat(value) || 0, maxValue); - }); - return maxValue; - } - - function getCacheKey(element) { - var parentElement = element.parent(); - var parentID = parentElement.data(NG_ANIMATE_PARENT_KEY); - if (!parentID) { - parentElement.data(NG_ANIMATE_PARENT_KEY, ++parentCounter); - parentID = parentCounter; - } - return parentID + '-' + extractElementNode(element).getAttribute('class'); + }]) + .run(['$rootScope', function($rootScope) { + $rootScope.records = [ + { id:1, title: "Miss Beulah Roob" }, + { id:2, title: "Trent Morissette" }, + { id:3, title: "Miss Ava Pouros" }, + { id:4, title: "Rod Pouros" }, + { id:5, title: "Abdul Rice" }, + { id:6, title: "Laurie Rutherford Sr." }, + { id:7, title: "Nakia McLaughlin" }, + { id:8, title: "Jordon Blanda DVM" }, + { id:9, title: "Rhoda Hand" }, + { id:10, title: "Alexandrea Sauer" } + ]; + }]) + .controller('HomeController', [function() { + //empty + }]) + .controller('ProfileController', ['$rootScope', '$routeParams', function($rootScope, $routeParams) { + var index = parseInt($routeParams.id, 10); + var record = $rootScope.records[index - 1]; + + this.title = record.title; + this.id = record.id; + }]); + </file> + <file name="home.html"> + <h2>Welcome to the home page</h1> + <p>Please click on an element</p> + <a class="record" + ng-href="#/profile/{{ record.id }}" + ng-animate-ref="{{ record.id }}" + ng-repeat="record in records"> + {{ record.title }} + </a> + </file> + <file name="profile.html"> + <div class="profile record" ng-animate-ref="{{ profile.id }}"> + {{ profile.title }} + </div> + </file> + <file name="animations.css"> + .record { + display:block; + font-size:20px; } - - function animateSetup(animationEvent, element, className, styles) { - var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0; - - var cacheKey = getCacheKey(element); - var eventCacheKey = cacheKey + ' ' + className; - var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0; - - var stagger = {}; - if (itemIndex > 0) { - var staggerClassName = className + '-stagger'; - var staggerCacheKey = cacheKey + ' ' + staggerClassName; - var applyClasses = !lookupCache[staggerCacheKey]; - - applyClasses && $$jqLite.addClass(element, staggerClassName); - - stagger = getElementAnimationDetails(element, staggerCacheKey); - - applyClasses && $$jqLite.removeClass(element, staggerClassName); - } - - $$jqLite.addClass(element, className); - - var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {}; - var timings = getElementAnimationDetails(element, eventCacheKey); - var transitionDuration = timings.transitionDuration; - var animationDuration = timings.animationDuration; - - if (structural && transitionDuration === 0 && animationDuration === 0) { - $$jqLite.removeClass(element, className); - return false; - } - - var blockTransition = styles || (structural && transitionDuration > 0); - var blockAnimation = animationDuration > 0 && - stagger.animationDelay > 0 && - stagger.animationDuration === 0; - - var closeAnimationFns = formerData.closeAnimationFns || []; - element.data(NG_ANIMATE_CSS_DATA_KEY, { - stagger: stagger, - cacheKey: eventCacheKey, - running: formerData.running || 0, - itemIndex: itemIndex, - blockTransition: blockTransition, - closeAnimationFns: closeAnimationFns - }); - - var node = extractElementNode(element); - - if (blockTransition) { - blockTransitions(node, true); - if (styles) { - element.css(styles); - } - } - - if (blockAnimation) { - blockAnimations(node, true); - } - - return true; + .profile { + background:black; + color:white; + font-size:100px; } - - function animateRun(animationEvent, element, className, activeAnimationComplete, styles) { - var node = extractElementNode(element); - var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (node.getAttribute('class').indexOf(className) == -1 || !elementData) { - activeAnimationComplete(); - return; - } - - var activeClassName = ''; - var pendingClassName = ''; - forEach(className.split(' '), function(klass, i) { - var prefix = (i > 0 ? ' ' : '') + klass; - activeClassName += prefix + '-active'; - pendingClassName += prefix + '-pending'; - }); - - var style = ''; - var appliedStyles = []; - var itemIndex = elementData.itemIndex; - var stagger = elementData.stagger; - var staggerTime = 0; - if (itemIndex > 0) { - var transitionStaggerDelay = 0; - if (stagger.transitionDelay > 0 && stagger.transitionDuration === 0) { - transitionStaggerDelay = stagger.transitionDelay * itemIndex; - } - - var animationStaggerDelay = 0; - if (stagger.animationDelay > 0 && stagger.animationDuration === 0) { - animationStaggerDelay = stagger.animationDelay * itemIndex; - appliedStyles.push(CSS_PREFIX + 'animation-play-state'); - } - - staggerTime = Math.round(Math.max(transitionStaggerDelay, animationStaggerDelay) * 100) / 100; - } - - if (!staggerTime) { - $$jqLite.addClass(element, activeClassName); - if (elementData.blockTransition) { - blockTransitions(node, false); - } - } - - var eventCacheKey = elementData.cacheKey + ' ' + activeClassName; - var timings = getElementAnimationDetails(element, eventCacheKey); - var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration); - if (maxDuration === 0) { - $$jqLite.removeClass(element, activeClassName); - animateClose(element, className); - activeAnimationComplete(); - return; - } - - if (!staggerTime && styles && Object.keys(styles).length > 0) { - if (!timings.transitionDuration) { - element.css('transition', timings.animationDuration + 's linear all'); - appliedStyles.push('transition'); - } - element.css(styles); - } - - var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay); - var maxDelayTime = maxDelay * ONE_SECOND; - - if (appliedStyles.length > 0) { - //the element being animated may sometimes contain comment nodes in - //the jqLite object, so we're safe to use a single variable to house - //the styles since there is always only one element being animated - var oldStyle = node.getAttribute('style') || ''; - if (oldStyle.charAt(oldStyle.length - 1) !== ';') { - oldStyle += ';'; - } - node.setAttribute('style', oldStyle + ' ' + style); - } - - var startTime = Date.now(); - var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT; - var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER; - var totalTime = (staggerTime + animationTime) * ONE_SECOND; - - var staggerTimeout; - if (staggerTime > 0) { - $$jqLite.addClass(element, pendingClassName); - staggerTimeout = $timeout(function() { - staggerTimeout = null; - - if (timings.transitionDuration > 0) { - blockTransitions(node, false); - } - if (timings.animationDuration > 0) { - blockAnimations(node, false); - } - - $$jqLite.addClass(element, activeClassName); - $$jqLite.removeClass(element, pendingClassName); - - if (styles) { - if (timings.transitionDuration === 0) { - element.css('transition', timings.animationDuration + 's linear all'); - } - element.css(styles); - appliedStyles.push('transition'); - } - }, staggerTime * ONE_SECOND, false); - } - - element.on(css3AnimationEvents, onAnimationProgress); - elementData.closeAnimationFns.push(function() { - onEnd(); - activeAnimationComplete(); - }); - - elementData.running++; - animationCloseHandler(element, totalTime); - return onEnd; - - // This will automatically be called by $animate so - // there is no need to attach this internally to the - // timeout done method. - function onEnd() { - element.off(css3AnimationEvents, onAnimationProgress); - $$jqLite.removeClass(element, activeClassName); - $$jqLite.removeClass(element, pendingClassName); - if (staggerTimeout) { - $timeout.cancel(staggerTimeout); - } - animateClose(element, className); - var node = extractElementNode(element); - for (var i in appliedStyles) { - node.style.removeProperty(appliedStyles[i]); - } - } - - function onAnimationProgress(event) { - event.stopPropagation(); - var ev = event.originalEvent || event; - var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now(); - - /* Firefox (or possibly just Gecko) likes to not round values up - * when a ms measurement is used for the animation */ - var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); - - /* $manualTimeStamp is a mocked timeStamp value which is set - * within browserTrigger(). This is only here so that tests can - * mock animations properly. Real events fallback to event.timeStamp, - * or, if they don't, then a timeStamp is automatically created for them. - * We're checking to see if the timeStamp surpasses the expected delay, - * but we're using elapsedTime instead of the timeStamp on the 2nd - * pre-condition since animations sometimes close off early */ - if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { - activeAnimationComplete(); - } - } + .view-container { + position:relative; } - - function blockTransitions(node, bool) { - node.style[TRANSITION_PROP + PROPERTY_KEY] = bool ? 'none' : ''; + .view-container > .view.ng-animate { + position:absolute; + top:0; + left:0; + width:100%; + min-height:500px; } - - function blockAnimations(node, bool) { - node.style[ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY] = bool ? 'paused' : ''; + .view.ng-enter, .view.ng-leave, + .record.ng-anchor { + transition:0.5s linear all; } - - function animateBefore(animationEvent, element, className, styles) { - if (animateSetup(animationEvent, element, className, styles)) { - return function(cancelled) { - cancelled && animateClose(element, className); - }; - } + .view.ng-enter { + transform:translateX(100%); } - - function animateAfter(animationEvent, element, className, afterAnimationComplete, styles) { - if (element.data(NG_ANIMATE_CSS_DATA_KEY)) { - return animateRun(animationEvent, element, className, afterAnimationComplete, styles); - } else { - animateClose(element, className); - afterAnimationComplete(); - } + .view.ng-enter.ng-enter-active, .view.ng-leave { + transform:translateX(0%); } - - function animate(animationEvent, element, className, animationComplete, options) { - //If the animateSetup function doesn't bother returning a - //cancellation function then it means that there is no animation - //to perform at all - var preReflowCancellation = animateBefore(animationEvent, element, className, options.from); - if (!preReflowCancellation) { - clearCacheAfterReflow(); - animationComplete(); - return; - } - - //There are two cancellation functions: one is before the first - //reflow animation and the second is during the active state - //animation. The first function will take care of removing the - //data from the element which will not make the 2nd animation - //happen in the first place - var cancel = preReflowCancellation; - afterReflow(element, function() { - //once the reflow is complete then we point cancel to - //the new cancellation function which will remove all of the - //animation properties from the active animation - cancel = animateAfter(animationEvent, element, className, animationComplete, options.to); - }); - - return function(cancelled) { - (cancel || noop)(cancelled); - }; + .view.ng-leave.ng-leave-active { + transform:translateX(-100%); } - - function animateClose(element, className) { - $$jqLite.removeClass(element, className); - var data = element.data(NG_ANIMATE_CSS_DATA_KEY); - if (data) { - if (data.running) { - data.running--; - } - if (!data.running || data.running === 0) { - element.removeData(NG_ANIMATE_CSS_DATA_KEY); - } - } + .record.ng-anchor-out { + background:red; } + </file> + </example> + * + * ### How is the element transported? + * + * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting + * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element + * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The + * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match + * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied + * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class + * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element + * will become visible since the shim class will be removed. + * + * ### How is the morphing handled? + * + * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out + * what CSS classes differ between the starting element and the destination element. These different CSS classes + * will be added/removed on the anchor element and a transition will be applied (the transition that is provided + * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will + * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that + * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since + * the cloned element is placed inside of root element which is likely close to the body element). + * + * Note that if the root element is on the `<html>` element then the cloned node will be placed inside of body. + * + * + * ## Using $animate in your directive code + * + * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application? + * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's + * imagine we have a greeting box that shows and hides itself when the data changes + * + * ```html + * <greeting-box active="onOrOff">Hi there</greeting-box> + * ``` + * + * ```js + * ngModule.directive('greetingBox', ['$animate', function($animate) { + * return function(scope, element, attrs) { + * attrs.$observe('active', function(value) { + * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on'); + * }); + * }); + * }]); + * ``` + * + * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element + * in our HTML code then we can trigger a CSS or JS animation to happen. + * + * ```css + * /* normally we would create a CSS class to reference on the element */ + * greeting-box.on { transition:0.5s linear all; background:green; color:white; } + * ``` + * + * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's + * possible be sure to visit the {@link ng.$animate $animate service API page}. + * + * + * ### Preventing Collisions With Third Party Libraries + * + * Some third-party frameworks place animation duration defaults across many element or className + * selectors in order to make their code small and reuseable. This can lead to issues with ngAnimate, which + * is expecting actual animations on these elements and has to wait for their completion. + * + * You can prevent this unwanted behavior by using a prefix on all your animation classes: + * + * ```css + * /* prefixed with animate- */ + * .animate-fade-add.animate-fade-add-active { + * transition:1s linear all; + * opacity:0; + * } + * ``` + * + * You then configure `$animate` to enforce this prefix: + * + * ```js + * $animateProvider.classNameFilter(/animate-/); + * ``` + * + * This also may provide your application with a speed boost since only specific elements containing CSS class prefix + * will be evaluated for animation when any DOM changes occur in the application. + * + * ## Callbacks and Promises + * + * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger + * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has + * ended by chaining onto the returned promise that animation method returns. + * + * ```js + * // somewhere within the depths of the directive + * $animate.enter(element, parent).then(function() { + * //the animation has completed + * }); + * ``` + * + * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case + * anymore.) + * + * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering + * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view + * routing controller to hook into that: + * + * ```js + * ngModule.controller('HomePageController', ['$animate', function($animate) { + * $animate.on('enter', ngViewElement, function(element) { + * // the animation for this route has completed + * }]); + * }]) + * ``` + * + * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.) + */ - return { - animate: function(element, className, from, to, animationCompleted, options) { - options = options || {}; - options.from = from; - options.to = to; - return animate('animate', element, className, animationCompleted, options); - }, - - enter: function(element, animationCompleted, options) { - options = options || {}; - return animate('enter', element, 'ng-enter', animationCompleted, options); - }, - - leave: function(element, animationCompleted, options) { - options = options || {}; - return animate('leave', element, 'ng-leave', animationCompleted, options); - }, - - move: function(element, animationCompleted, options) { - options = options || {}; - return animate('move', element, 'ng-move', animationCompleted, options); - }, - - beforeSetClass: function(element, add, remove, animationCompleted, options) { - options = options || {}; - var className = suffixClasses(remove, '-remove') + ' ' + - suffixClasses(add, '-add'); - var cancellationMethod = animateBefore('setClass', element, className, options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; - } - clearCacheAfterReflow(); - animationCompleted(); - }, - - beforeAddClass: function(element, className, animationCompleted, options) { - options = options || {}; - var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; - } - clearCacheAfterReflow(); - animationCompleted(); - }, +/** + * @ngdoc service + * @name $animate + * @kind object + * + * @description + * The ngAnimate `$animate` service documentation is the same for the core `$animate` service. + * + * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}. + */ +angular.module('ngAnimate', []) + .directive('ngAnimateChildren', $$AnimateChildrenDirective) - beforeRemoveClass: function(element, className, animationCompleted, options) { - options = options || {}; - var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), options.from); - if (cancellationMethod) { - afterReflow(element, animationCompleted); - return cancellationMethod; - } - clearCacheAfterReflow(); - animationCompleted(); - }, + .factory('$$rAFMutex', $$rAFMutexFactory) + .factory('$$rAFScheduler', $$rAFSchedulerFactory) - setClass: function(element, add, remove, animationCompleted, options) { - options = options || {}; - remove = suffixClasses(remove, '-remove'); - add = suffixClasses(add, '-add'); - var className = remove + ' ' + add; - return animateAfter('setClass', element, className, animationCompleted, options.to); - }, + .factory('$$AnimateRunner', $$AnimateRunnerFactory) - addClass: function(element, className, animationCompleted, options) { - options = options || {}; - return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted, options.to); - }, + .provider('$$animateQueue', $$AnimateQueueProvider) + .provider('$$animation', $$AnimationProvider) - removeClass: function(element, className, animationCompleted, options) { - options = options || {}; - return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted, options.to); - } - }; + .provider('$animateCss', $AnimateCssProvider) + .provider('$$animateCssDriver', $$AnimateCssDriverProvider) - function suffixClasses(classes, suffix) { - var className = ''; - classes = isArray(classes) ? classes : classes.split(/\s+/); - forEach(classes, function(klass, i) { - if (klass && klass.length > 0) { - className += (i > 0 ? ' ' : '') + klass + suffix; - } - }); - return className; - } - }]); - }]); + .provider('$$animateJs', $$AnimateJsProvider) + .provider('$$animateJsDriver', $$AnimateJsDriverProvider); })(window, window.angular); @@ -37109,12 +45411,23 @@ angular.module('ngAnimate', ['ng']) */ /** - * @license AngularJS v1.3.13 - * (c) 2010-2014 Google, Inc. http://angularjs.org + * @license AngularJS v1.4.3 + * (c) 2010-2015 Google, Inc. http://angularjs.org * License: MIT */ (function(window, angular, undefined) {'use strict'; +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Any commits to this file should be reviewed with security in mind. * + * Changes to this file can potentially create security vulnerabilities. * + * An approval from 2 Core members with history of modifying * + * this file is required. * + * * + * Does the change somehow allow for arbitrary javascript to be executed? * + * Or allows for someone to change the prototype of built-in objects? * + * Or gives undesired access to variables likes document or window? * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + var $sanitizeMinErr = angular.$$minErr('$sanitize'); /** @@ -37310,10 +45623,11 @@ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a // SVG Elements // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements -var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," + - "desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," + - "line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," + - "stop,svg,switch,text,title,tspan,use"); +// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted. +// They can potentially allow for arbitrary javascript to be executed. See #11290 +var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," + + "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," + + "radialGradient,rect,stop,svg,switch,text,title,tspan,use"); // Special Elements (can contain anything) var specialElements = makeMap("script,style"); @@ -37331,36 +45645,37 @@ var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href"); var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + - 'scope,scrolling,shape,size,span,start,summary,target,title,type,' + + 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' + 'valign,value,vspace,width'); // SVG attributes (without "id" and "name" attributes) // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' + - 'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' + - 'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' + - 'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' + - 'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' + - 'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' + - 'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' + - 'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' + - 'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' + - 'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' + - 'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' + - 'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' + - 'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' + - 'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' + - 'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' + - 'zoomAndPan'); + 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' + + 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' + + 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' + + 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' + + 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' + + 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' + + 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' + + 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' + + 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' + + 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' + + 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' + + 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' + + 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' + + 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true); var validAttrs = angular.extend({}, uriAttrs, svgAttrs, htmlAttrs); -function makeMap(str) { +function makeMap(str, lowercaseKeys) { var obj = {}, items = str.split(','), i; - for (i = 0; i < items.length; i++) obj[items[i]] = true; + for (i = 0; i < items.length; i++) { + obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true; + } return obj; } @@ -37488,8 +45803,9 @@ function htmlParser(html, handler) { unary = voidElements[tagName] || !!unary; - if (!unary) + if (!unary) { stack.push(tagName); + } var attrs = {}; @@ -37508,11 +45824,12 @@ function htmlParser(html, handler) { function parseEndTag(tag, tagName) { var pos = 0, i; tagName = angular.lowercase(tagName); - if (tagName) + if (tagName) { // Find the closest opened tag of the same type - for (pos = stack.length - 1; pos >= 0; pos--) - if (stack[pos] == tagName) - break; + for (pos = stack.length - 1; pos >= 0; pos--) { + if (stack[pos] == tagName) break; + } + } if (pos >= 0) { // Close all the open elements, up the stack @@ -37526,7 +45843,6 @@ function htmlParser(html, handler) { } var hiddenPre=document.createElement("pre"); -var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; /** * decodes all entities into regular string * @param value @@ -37535,22 +45851,10 @@ var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; function decodeEntities(value) { if (!value) { return ''; } - // Note: IE8 does not preserve spaces at the start/end of innerHTML - // so we must capture them and reattach them afterward - var parts = spaceRe.exec(value); - var spaceBefore = parts[1]; - var spaceAfter = parts[3]; - var content = parts[2]; - if (content) { - hiddenPre.innerHTML=content.replace(/</g,"<"); - // innerText depends on styling as it doesn't display hidden elements. - // Therefore, it's better to use textContent not to cause unnecessary - // reflows. However, IE<9 don't support textContent so the innerText - // fallback is necessary. - content = 'textContent' in hiddenPre ? - hiddenPre.textContent : hiddenPre.innerText; - } - return spaceBefore + content + spaceAfter; + hiddenPre.innerHTML = value.replace(/</g,"<"); + // innerText depends on styling as it doesn't display hidden elements. + // Therefore, it's better to use textContent not to cause unnecessary reflows. + return hiddenPre.textContent; } /** @@ -37739,8 +46043,8 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); */ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { var LINKY_URL_REGEXP = - /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"â€â€™]/, - MAILTO_REGEXP = /^mailto:/; + /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"â€â€™]/i, + MAILTO_REGEXP = /^mailto:/i; return function(text, target) { if (!text) return text; @@ -42037,10 +50341,10 @@ angular.module('ui.router.state') */ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -42052,7 +50356,7 @@ angular.module('ui.router.state') (function() { /* eslint no-unused-vars:0 */ -var IonicModule = angular.module('ionic', ['ngAnimate', 'ngSanitize', 'ui.router']), +var IonicModule = angular.module('ionic', ['ngAnimate', 'ngSanitize', 'ui.router', 'ngIOS9UIWebViewPatch']), extend = angular.extend, forEach = angular.forEach, isDefined = angular.isDefined, @@ -42208,7 +50512,7 @@ function($rootScope, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicP element.remove(); // scope.cancel.$scope is defined near the bottom scope.cancel.$scope = sheetEl = null; - (done || noop)(); + (done || noop)(opts.buttons); }); }; @@ -42343,10 +50647,14 @@ jqLite.prototype.removeClass = function(cssClasses) { * For example, if `retain` is called three times, the backdrop will be shown until `release` * is called three times. * + * **Notes:** + * - The backdrop service will broadcast 'backdrop.shown' and 'backdrop.hidden' events from the root scope, + * this is useful for alerting native components not in html. + * * @usage * * ```js - * function MyController($scope, $ionicBackdrop, $timeout) { + * function MyController($scope, $ionicBackdrop, $timeout, $rootScope) { * //Show a backdrop for one second * $scope.action = function() { * $ionicBackdrop.retain(); @@ -42354,13 +50662,24 @@ jqLite.prototype.removeClass = function(cssClasses) { * $ionicBackdrop.release(); * }, 1000); * }; + * + * // Execute action on backdrop disappearing + * $scope.$on('backdrop.hidden', function() { + * // Execute action + * }); + * + * // Execute action on backdrop appearing + * $scope.$on('backdrop.shown', function() { + * // Execute action + * }); + * * } * ``` */ IonicModule .factory('$ionicBackdrop', [ - '$document', '$timeout', '$$rAF', -function($document, $timeout, $$rAF) { + '$document', '$timeout', '$$rAF', '$rootScope', +function($document, $timeout, $$rAF, $rootScope) { var el = jqLite('<div class="backdrop">'); var backdropHolds = 0; @@ -42392,6 +50711,7 @@ function($document, $timeout, $$rAF) { backdropHolds++; if (backdropHolds === 1) { el.addClass('visible'); + $rootScope.$broadcast('backdrop.shown'); $$rAF(function() { // If we're still at >0 backdropHolds after async... if (backdropHolds >= 1) el.addClass('active'); @@ -42401,6 +50721,7 @@ function($document, $timeout, $$rAF) { function release() { if (backdropHolds === 1) { el.removeClass('active'); + $rootScope.$broadcast('backdrop.hidden'); $timeout(function() { // If we're still at 0 backdropHolds after async... if (backdropHolds === 0) el.removeClass('visible'); @@ -42484,7 +50805,7 @@ IonicModule return { /** * @ngdoc method - * @name $ionicBody#add + * @name $ionicBody#addClass * @description Add a class to the document's body element. * @param {string} class Each argument will be added to the body element. * @returns {$ionicBody} The $ionicBody service so methods can be chained. @@ -43289,11 +51610,12 @@ function($rootScope, $state, $location, $window, $timeout, $ionicViewSwitcher, $ /** * @ngdoc method * @name $ionicHistory#clearCache + * @return promise * @description Removes all cached views within every {@link ionic.directive:ionNavView}. * This both removes the view element from the DOM, and destroy it's scope. */ clearCache: function(stateIds) { - $timeout(function() { + return $timeout(function() { $ionicNavViewDelegate._instances.forEach(function(instance) { instance.clearCache(stateIds); }); @@ -43582,9 +51904,9 @@ function($rootScope, $state, $location, $document, $ionicPlatform, $ionicHistory /** * @ngdoc method * @name $ionicConfigProvider#scrolling.jsScrolling - * @description Whether to use JS or Native scrolling. Defaults to JS scrolling. Setting this to - * `false` has the same effect as setting each `ion-content` to have `overflow-scroll='true'`. - * @param {boolean} value Defaults to `true` + * @description Whether to use JS or Native scrolling. Defaults to native scrolling. Setting this to + * `true` has the same effect as setting each `ion-content` to have `overflow-scroll='false'`. + * @param {boolean} value Defaults to `false` as of Ionic 1.2 * @returns {boolean} */ @@ -43859,8 +52181,11 @@ IonicModule tabs: { style: 'striped', position: 'top' - } + }, + scrolling: { + jsScrolling: false + } }); // Windows Phone @@ -44142,8 +52467,8 @@ IonicModule // http://blogs.msdn.com/b/msdn_answers/archive/2015/02/10/ // running-cordova-apps-on-windows-and-windows-phone-8-1-using-ionic-angularjs-and-other-frameworks.aspx .config(['$compileProvider', function($compileProvider) { - $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|tel|ftp|mailto|file|ghttps?|ms-appx|x-wmapp0):/); - $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|x-wmapp0):|data:image\//); + $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|sms|tel|geo|ftp|mailto|file|ghttps?|ms-appx-web|ms-appx|x-wmapp0):/); + $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|ms-appx-web|x-wmapp0):|data:image\//); }]); @@ -44230,7 +52555,9 @@ function($ionicLoadingConfig, $ionicBody, $ionicTemplateLoader, $ionicBackdrop, * @ngdoc method * @name $ionicLoading#show * @description Shows a loading indicator. If the indicator is already shown, - * it will set the options given and keep the indicator shown. + * it will set the options given and keep the indicator shown. Note: While this + * function still returns an $ionicLoading instance for backwards compatiblity, + * its use has been deprecated. * @param {object} opts The options for the loading indicator. Available properties: * - `{string=}` `template` The html content of the indicator. * - `{string=}` `templateUrl` The url of an html template to load as the content of the indicator. @@ -44325,12 +52652,15 @@ function($ionicLoadingConfig, $ionicBody, $ionicTemplateLoader, $ionicBackdrop, } self.element.removeClass('active'); $ionicBody.removeClass('loading-active'); - setTimeout(function() { + self.element.removeClass('visible'); + ionic.requestAnimationFrame(function() { !self.isShown && self.element.removeClass('visible'); - }, 200); + }); } $timeout.cancel(self.durationTimeout); self.isShown = false; + var loading = self.element.children(); + loading.html(""); }; return self; @@ -44567,10 +52897,18 @@ function($rootScope, $ionicBody, $compile, $timeout, $ionicPlatform, $ionicTempl self.scope.$parent && self.scope.$parent.$broadcast(self.viewType + '.shown', self); self.el.classList.add('active'); self.scope.$broadcast('$ionicHeader.align'); + self.scope.$broadcast('$ionicFooter.align'); }, 20); return $timeout(function() { if (!self._isShown) return; + self.$el.on('touchmove', function(e) { + //Don't allow scrolling while open by dragging on backdrop + var isInScroll = ionic.DomUtil.getParentOrSelfWithClass(e.target, 'scroll'); + if (!isInScroll) { + e.preventDefault(); + } + }); //After animating in, allow hide on backdrop click self.$el.on('click', function(e) { if (self.backdropClickToClose && e.target === self.el && stack.isHighest(self)) { @@ -44843,7 +53181,7 @@ IonicModule }) .provider('$ionicPlatform', function() { return { - $get: ['$q', function($q) { + $get: ['$q', '$ionicScrollDelegate', function($q, $ionicScrollDelegate) { var self = { /** @@ -44994,6 +53332,11 @@ IonicModule return q.promise; } }; + + window.addEventListener('statusTap', function() { + $ionicScrollDelegate.scrollTop(true); + }); + return self; }] }; @@ -45206,7 +53549,7 @@ function($ionicModal, $ionicPosition, $document, $window) { * controller (ionicPopover is built on top of $ionicPopover). */ fromTemplate: function(templateString, options) { - return $ionicModal.fromTemplate(templateString, ionic.Utils.extend(POPOVER_OPTIONS, options || {})); + return $ionicModal.fromTemplate(templateString, ionic.Utils.extend({}, POPOVER_OPTIONS, options)); }, /** * @ngdoc method @@ -45217,7 +53560,7 @@ function($ionicModal, $ionicPosition, $document, $window) { * an {@link ionic.controller:ionicPopover} controller (ionicPopover is built on top of $ionicPopover). */ fromTemplateUrl: function(url, options) { - return $ionicModal.fromTemplateUrl(url, ionic.Utils.extend(POPOVER_OPTIONS, options || {})); + return $ionicModal.fromTemplateUrl(url, ionic.Utils.extend({}, POPOVER_OPTIONS, options)); } }; @@ -45268,7 +53611,7 @@ var POPUP_TPL = * * // Triggered on a button click, or some other target * $scope.showPopup = function() { - * $scope.data = {} + * $scope.data = {}; * * // An elaborate, custom popup * var myPopup = $ionicPopup.show({ @@ -45292,19 +53635,23 @@ var POPUP_TPL = * } * ] * }); + * * myPopup.then(function(res) { * console.log('Tapped!', res); * }); + * * $timeout(function() { * myPopup.close(); //close the popup after 3 seconds for some reason * }, 3000); * }; + * * // A confirm dialog * $scope.showConfirm = function() { * var confirmPopup = $ionicPopup.confirm({ * title: 'Consume Ice Cream', * template: 'Are you sure you want to eat this ice cream?' * }); + * * confirmPopup.then(function(res) { * if(res) { * console.log('You are sure'); @@ -45320,6 +53667,7 @@ var POPUP_TPL = * title: 'Don\'t eat that!', * template: 'It might taste good' * }); + * * alertPopup.then(function(res) { * console.log('Thank you for not eating my delicious ice cream cone'); * }); @@ -45476,8 +53824,10 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB * cssClass: '', // String, The custom CSS class name * subTitle: '', // String (optional). The sub-title of the popup. * template: '', // String (optional). The html template to place in the popup body. - * templateUrl: '', // String (optional). The URL of an html template to place in the popup body. + * templateUrl: '', // String (optional). The URL of an html template to place in the popup body. * inputType: // String (default: 'text'). The type of input to use + * defaultText: // String (default: ''). The initial value placed into the input. + * maxLength: // Integer (default: null). Specify a maxlength attribute for the input. * inputPlaceholder: // String (default: ''). A placeholder to use for the input. * cancelText: // String (default: 'Cancel'. The text of the Cancel button. * cancelType: // String (default: 'button-default'). The type of the Cancel button. @@ -45521,7 +53871,7 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB subTitle: options.subTitle, cssClass: options.cssClass, $buttonTapped: function(button, event) { - var result = (button.onTap || noop)(event); + var result = (button.onTap || noop).apply(self, [event]); event = event.originalEvent || event; //jquery events if (!event.defaultPrevented) { @@ -45571,7 +53921,7 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB }; self.remove = function() { - if (self.removed || !$ionicModal.stack.isHighest(self)) return; + if (self.removed) return; self.hide(function() { self.element.remove(); @@ -45594,8 +53944,8 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB var showDelay = 0; if (popupStack.length > 0) { - popupStack[popupStack.length - 1].hide(); showDelay = config.stackPushDelay; + $timeout(popupStack[popupStack.length - 1].hide, showDelay, false); } else { //Add popup-open & backdrop if this is first popup $ionicBody.addClass('popup-open'); @@ -45628,6 +53978,8 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB popupStack.splice(index, 1); } + popup.remove(); + if (popupStack.length > 0) { popupStack[popupStack.length - 1].show(); } else { @@ -45643,7 +53995,6 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB ($ionicPopup._backButtonActionDone || noop)(); } - popup.remove(); return result; }); @@ -45688,14 +54039,21 @@ function($ionicTemplateLoader, $ionicBackdrop, $q, $timeout, $rootScope, $ionicB function showPrompt(opts) { var scope = $rootScope.$new(true); scope.data = {}; + scope.data.fieldtype = opts.inputType ? opts.inputType : 'text'; + scope.data.response = opts.defaultText ? opts.defaultText : ''; + scope.data.placeholder = opts.inputPlaceholder ? opts.inputPlaceholder : ''; + scope.data.maxlength = opts.maxLength ? parseInt(opts.maxLength) : ''; var text = ''; if (opts.template && /<[a-z][\s\S]*>/i.test(opts.template) === false) { text = '<span>' + opts.template + '</span>'; delete opts.template; } return showPopup(extend({ - template: text + '<input ng-model="data.response" type="' + (opts.inputType || 'text') + - '" placeholder="' + (opts.inputPlaceholder || '') + '">', + template: text + '<input ng-model="data.response" ' + + 'type="{{ data.fieldtype }}"' + + 'maxlength="{{ data.maxlength }}"' + + 'placeholder="{{ data.placeholder }}"' + + '>', scope: scope, buttons: [{ text: opts.cancelText || 'Cancel', @@ -45944,7 +54302,7 @@ IonicModule * @name $ionicScrollDelegate#freezeScroll * @description Does not allow this scroll view to scroll either x or y. * @param {boolean=} shouldFreeze Should this scroll view be prevented from scrolling or not. - * @returns {object} If the scroll view is being prevented from scrolling or not. + * @returns {boolean} If the scroll view is being prevented from scrolling or not. */ 'freezeScroll', /** @@ -46254,7 +54612,16 @@ IonicModule * @name $ionicTabsDelegate#selectedIndex * @returns `number` The index of the selected tab, or -1. */ - 'selectedIndex' + 'selectedIndex', + /** + * @ngdoc method + * @name $ionicTabsDelegate#showBar + * @description + * Set/get whether the {@link ionic.directive:ionTabs} is shown + * @param {boolean} show Whether to show the bar. + * @returns {boolean} Whether the bar is shown. + */ + 'showBar' /** * @ngdoc method * @name $ionicTabsDelegate#$getByHandle @@ -46267,7 +54634,6 @@ IonicModule */ ])); - // closure to keep things neat (function() { var templatesToCache = []; @@ -46688,8 +55054,9 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe if (renderStart && renderEnd) { // CSS "auto" transitioned, not manually transitioned // wait a frame so the styles apply before auto transitioning - $timeout(onReflow, 16); - + $timeout(function() { + ionic.requestAnimationFrame(onReflow); + }); } else if (!renderEnd) { // just the start of a manual transition // but it will not render the end of the transition @@ -46754,10 +55121,6 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe $timeout.cancel(enteringEle.data(DATA_FALLBACK_TIMER)); leavingEle && $timeout.cancel(leavingEle.data(DATA_FALLBACK_TIMER)); - // emit that the views have finished transitioning - // each parent nav-view will update which views are active and cached - switcher.emit('after', enteringData, leavingData); - // resolve that this one transition (there could be many w/ nested views) deferred && deferred.resolve(navViewCtrl); @@ -46765,6 +55128,10 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe // transition promises should be added to the services array of promises if (transitionId === transitionCounter) { $q.all(transitionPromises).then(ionicViewSwitcher.transitionEnd); + + // emit that the views have finished transitioning + // each parent nav-view will update which views are active and cached + switcher.emit('after', enteringData, leavingData); switcher.cleanup(enteringData); } @@ -46773,6 +55140,7 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe instance.triggerTransitionEnd(); }); + // remove any references that could cause memory issues nextTransition = nextDirection = enteringView = leavingView = enteringEle = leavingEle = null; } @@ -46988,6 +55356,82 @@ function($timeout, $document, $q, $ionicClickBlock, $ionicConfig, $ionicNavBarDe }]); +/** + * ================== angular-ios9-uiwebview.patch.js v1.1.1 ================== + * + * This patch works around iOS9 UIWebView regression that causes infinite digest + * errors in Angular. + * + * The patch can be applied to Angular 1.2.0 – 1.4.5. Newer versions of Angular + * have the workaround baked in. + * + * To apply this patch load/bundle this file with your application and add a + * dependency on the "ngIOS9UIWebViewPatch" module to your main app module. + * + * For example: + * + * ``` + * angular.module('myApp', ['ngRoute'])` + * ``` + * + * becomes + * + * ``` + * angular.module('myApp', ['ngRoute', 'ngIOS9UIWebViewPatch']) + * ``` + * + * + * More info: + * - https://openradar.appspot.com/22186109 + * - https://github.com/angular/angular.js/issues/12241 + * - https://github.com/driftyco/ionic/issues/4082 + * + * + * @license AngularJS + * (c) 2010-2015 Google, Inc. http://angularjs.org + * License: MIT + */ + +angular.module('ngIOS9UIWebViewPatch', ['ng']).config(['$provide', function($provide) { + 'use strict'; + + $provide.decorator('$browser', ['$delegate', '$window', function($delegate, $window) { + + if (isIOS9UIWebView($window.navigator.userAgent)) { + return applyIOS9Shim($delegate); + } + + return $delegate; + + function isIOS9UIWebView(userAgent) { + return /(iPhone|iPad|iPod).* OS 9_\d/.test(userAgent) && !/Version\/9\./.test(userAgent); + } + + function applyIOS9Shim(browser) { + var pendingLocationUrl = null; + var originalUrlFn = browser.url; + + browser.url = function() { + if (arguments.length) { + pendingLocationUrl = arguments[0]; + return originalUrlFn.apply(browser, arguments); + } + + return pendingLocationUrl || originalUrlFn.apply(browser, arguments); + }; + + window.addEventListener('popstate', clearPendingLocationUrl, false); + window.addEventListener('hashchange', clearPendingLocationUrl, false); + + function clearPendingLocationUrl() { + pendingLocationUrl = null; + } + + return browser; + } + }]); +}]); + /** * @private * Parts of Ionic requires that $scope data is attached to the element. @@ -47017,7 +55461,7 @@ function($provide) { //found nearest to body's scrollTop is set to scroll to an element //with that ID. $location.hash = function(value) { - if (isDefined(value)) { + if (isDefined(value) && value.length > 0) { $timeout(function() { var scroll = document.querySelector('.scroll-content'); if (scroll) { @@ -47510,13 +55954,15 @@ function($scope, $attrs, $element, $timeout) { }; var computedStyle = window.getComputedStyle(self.scrollEl) || {}; return { - left: computedStyle.overflowX === 'scroll' || - computedStyle.overflowX === 'auto' || - self.scrollEl.style['overflow-x'] === 'scroll' ? + left: maxValues.left && + (computedStyle.overflowX === 'scroll' || + computedStyle.overflowX === 'auto' || + self.scrollEl.style['overflow-x'] === 'scroll') ? calculateMaxValue(maxValues.left) : -1, - top: computedStyle.overflowY === 'scroll' || - computedStyle.overflowY === 'auto' || - self.scrollEl.style['overflow-y'] === 'scroll' ? + top: maxValues.top && + (computedStyle.overflowY === 'scroll' || + computedStyle.overflowY === 'auto' || + self.scrollEl.style['overflow-y'] === 'scroll' ) ? calculateMaxValue(maxValues.top) : -1 }; }; @@ -47548,18 +55994,20 @@ function($scope, $attrs, $element, $timeout) { * method to control specific ionList instances. * * @usage - * - * ````html + * ```html + * {% raw %} * <ion-content ng-controller="MyCtrl"> * <button class="button" ng-click="showDeleteButtons()"></button> * <ion-list> * <ion-item ng-repeat="i in items"> - * {% raw %}Hello, {{i}}!{% endraw %} + * Hello, {{i}}! * <ion-delete-button class="ion-minus-circled"></ion-delete-button> * </ion-item> * </ion-list> * </ion-content> + * {% endraw %} * ``` + * ```js * function MyCtrl($scope, $ionicListDelegate) { * $scope.showDeleteButtons = function() { @@ -48433,6 +56881,9 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate, if (viewLocals && viewLocals.$$controller) { viewLocals.$scope = viewScope; var controller = $controller(viewLocals.$$controller, viewLocals); + if (viewLocals.$$controllerAs) { + viewScope[viewLocals.$$controllerAs] = controller; + } $element.children().data('$ngControllerController', controller); } @@ -48711,13 +57162,31 @@ IonicModule $onPulling: '&onPulling' }); + function handleMousedown(e) { + e.touches = e.touches || [{ + screenX: e.screenX, + screenY: e.screenY + }]; + // Mouse needs this + startY = Math.floor(e.touches[0].screenY); + } + + function handleTouchstart(e) { + e.touches = e.touches || [{ + screenX: e.screenX, + screenY: e.screenY + }]; + + startY = e.touches[0].screenY; + } + function handleTouchend() { + // reset Y + startY = null; // if this wasn't an overscroll, get out immediately if (!canOverscroll && !isDragging) { return; } - // reset Y - startY = null; // the user has overscrolled but went back to native scrolling if (!isDragging) { dragOffset = 0; @@ -48741,23 +57210,35 @@ IonicModule } function handleTouchmove(e) { + e.touches = e.touches || [{ + screenX: e.screenX, + screenY: e.screenY + }]; + + // Force mouse events to have had a down event first + if (!startY && e.type == 'mousemove') { + return; + } + // if multitouch or regular scroll event, get out immediately if (!canOverscroll || e.touches.length > 1) { return; } //if this is a new drag, keep track of where we start if (startY === null) { - startY = parseInt(e.touches[0].screenY, 10); + startY = e.touches[0].screenY; } + deltaY = e.touches[0].screenY - startY; + + // how far have we dragged so far? // kitkat fix for touchcancel events http://updates.html5rocks.com/2014/05/A-More-Compatible-Smoother-Touch - if (ionic.Platform.isAndroid() && ionic.Platform.version() === 4.4 && scrollParent.scrollTop === 0) { + // Only do this if we're not on crosswalk + if (ionic.Platform.isAndroid() && ionic.Platform.version() === 4.4 && !ionic.Platform.isCrosswalk() && scrollParent.scrollTop === 0 && deltaY > 0) { isDragging = true; e.preventDefault(); } - // how far have we dragged so far? - deltaY = parseInt(e.touches[0].screenY, 10) - startY; // if we've dragged up and back down in to native scroll territory if (deltaY - dragOffset <= 0 || scrollParent.scrollTop !== 0) { @@ -48768,7 +57249,7 @@ IonicModule } if (isDragging) { - nativescroll(scrollParent, parseInt(deltaY - dragOffset, 10) * -1); + nativescroll(scrollParent, deltaY - dragOffset * -1); } // if we're not at overscroll 0 yet, 0 out @@ -48793,7 +57274,7 @@ IonicModule isDragging = true; // overscroll according to the user's drag so far - overscroll(parseInt((deltaY - dragOffset) / 3, 10)); + overscroll((deltaY - dragOffset) / 3); // update the icon accordingly if (!activated && lastOverscroll > ptrThreshold) { @@ -48889,7 +57370,7 @@ IonicModule // fraction based on the easing method easedT = easeOutCubic(time); - overscroll(parseInt((easedT * (Y - from)) + from, 10)); + overscroll(Math.floor((easedT * (Y - from)) + from)); if (time < 1) { ionic.requestAnimationFrame(scroll); @@ -48910,6 +57391,21 @@ IonicModule } + var touchStartEvent, touchMoveEvent, touchEndEvent; + if (window.navigator.pointerEnabled) { + touchStartEvent = 'pointerdown'; + touchMoveEvent = 'pointermove'; + touchEndEvent = 'pointerup'; + } else if (window.navigator.msPointerEnabled) { + touchStartEvent = 'MSPointerDown'; + touchMoveEvent = 'MSPointerMove'; + touchEndEvent = 'MSPointerUp'; + } else { + touchStartEvent = 'touchstart'; + touchMoveEvent = 'touchmove'; + touchEndEvent = 'touchend'; + } + self.init = function() { scrollParent = $element.parent().parent()[0]; scrollChild = $element.parent()[0]; @@ -48919,8 +57415,13 @@ IonicModule throw new Error('Refresher must be immediate child of ion-content or ion-scroll'); } - ionic.on('touchmove', handleTouchmove, scrollChild); - ionic.on('touchend', handleTouchend, scrollChild); + + ionic.on(touchStartEvent, handleTouchstart, scrollChild); + ionic.on(touchMoveEvent, handleTouchmove, scrollChild); + ionic.on(touchEndEvent, handleTouchend, scrollChild); + ionic.on('mousedown', handleMousedown, scrollChild); + ionic.on('mousemove', handleTouchmove, scrollChild); + ionic.on('mouseup', handleTouchend, scrollChild); ionic.on('scroll', handleScroll, scrollParent); // cleanup when done @@ -48928,8 +57429,12 @@ IonicModule }; function destroy() { - ionic.off('touchmove', handleTouchmove, scrollChild); - ionic.off('touchend', handleTouchend, scrollChild); + ionic.off(touchStartEvent, handleTouchstart, scrollChild); + ionic.off(touchMoveEvent, handleTouchmove, scrollChild); + ionic.off(touchEndEvent, handleTouchend, scrollChild); + ionic.off('mousedown', handleMousedown, scrollChild); + ionic.off('mousemove', handleTouchmove, scrollChild); + ionic.off('mouseup', handleTouchend, scrollChild); ionic.off('scroll', handleScroll, scrollParent); scrollParent = null; scrollChild = null; @@ -48965,7 +57470,13 @@ IonicModule function start() { // startCallback $element[0].classList.add('refreshing'); - $scope.$onRefresh(); + var q = $scope.$onRefresh(); + + if (q && q.then) { + q['finally'](function() { + $scope.$broadcast('scroll.refreshComplete'); + }); + } } function show() { @@ -49046,7 +57557,7 @@ function($scope, if (!isDefined(scrollViewOptions.bouncing)) { ionic.Platform.ready(function() { - if (scrollView.options) { + if (scrollView && scrollView.options) { scrollView.options.bouncing = true; if (ionic.Platform.isAndroid()) { // No bouncing by default on Android @@ -49100,12 +57611,18 @@ function($scope, self.scrollTop = function(shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.scrollTo(0, 0, !!shouldAnimate); }); }; self.scrollBottom = function(shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } var max = scrollView.getScrollMax(); scrollView.scrollTo(max.left, max.top, !!shouldAnimate); }); @@ -49113,30 +57630,45 @@ function($scope, self.scrollTo = function(left, top, shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.scrollTo(left, top, !!shouldAnimate); }); }; self.zoomTo = function(zoom, shouldAnimate, originLeft, originTop) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.zoomTo(zoom, !!shouldAnimate, originLeft, originTop); }); }; self.zoomBy = function(zoom, shouldAnimate, originLeft, originTop) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.zoomBy(zoom, !!shouldAnimate, originLeft, originTop); }); }; self.scrollBy = function(left, top, shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } scrollView.scrollBy(left, top, !!shouldAnimate); }); }; self.anchorScroll = function(shouldAnimate) { self.resize().then(function() { + if (!scrollView) { + return; + } var hash = $location.hash(); var elm = hash && $document[0].getElementById(hash); if (!(hash && elm)) { @@ -49155,6 +57687,7 @@ function($scope, }; self.freezeScroll = scrollView.freeze; + self.freezeScrollShut = scrollView.freezeShut; self.freezeAllScrolls = function(shouldFreeze) { for (var i = 0; i < $ionicScrollDelegate._instances.length; i++) { @@ -49336,9 +57869,10 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io // equal 0, otherwise remove the class from the body element $ionicBody.enableClass((percentage !== 0), 'menu-open'); - freezeAllScrolls(false); + self.content.setCanScroll(percentage == 0); }; + /* function freezeAllScrolls(shouldFreeze) { if (shouldFreeze && !self.isScrollFreeze) { $ionicScrollDelegate.freezeAllScrolls(shouldFreeze); @@ -49348,6 +57882,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io } self.isScrollFreeze = shouldFreeze; } + */ /** * Open the menu the given pixel amount. @@ -49480,14 +58015,15 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io self.close(); isAsideExposed = shouldExposeAside; - if (self.left && self.left.isEnabled) { + if ((self.left && self.left.isEnabled) && (self.right && self.right.isEnabled)) { + self.content.setMarginLeftAndRight(isAsideExposed ? self.left.width : 0, isAsideExposed ? self.right.width : 0); + } else if (self.left && self.left.isEnabled) { // set the left marget width if it should be exposed // otherwise set false so there's no left margin self.content.setMarginLeft(isAsideExposed ? self.left.width : 0); } else if (self.right && self.right.isEnabled) { self.content.setMarginRight(isAsideExposed ? self.right.width : 0); } - self.$scope.$emit('$ionicExposeAside', isAsideExposed); }; @@ -49497,8 +58033,6 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io // End a drag with the given event self._endDrag = function(e) { - freezeAllScrolls(false); - if (isAsideExposed) return; if (isDragging) { @@ -49536,7 +58070,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io if (isDragging) { self.openAmount(offsetX + (lastX - startX)); - freezeAllScrolls(true); + //self.content.setCanScroll(false); } }; @@ -49575,7 +58109,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io var menuEnabled = enableMenuWithBackViews ? true : !backView; if (!menuEnabled) { var currentView = $ionicHistory.currentView() || {}; - return backView.historyId !== currentView.historyId; + return (dragIsWithinBounds && (backView.historyId !== currentView.historyId)); } return ($scope.dragContent || self.isOpen()) && @@ -49615,12 +58149,10 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io deregisterBackButtonAction(); self.$scope = null; if (self.content) { + self.content.setCanScroll(true); self.content.element = null; self.content = null; } - - // ensure scrolls are unfrozen - freezeAllScrolls(false); }); self.initialize({ @@ -49966,6 +58498,10 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io var animations = { android: function(ele) { + var self = this; + + this.stop = false; + var rIndex = 0; var rotateCircle = 0; var startTime; @@ -49973,6 +58509,8 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io var circleEle = ele.querySelector('circle'); function run() { + if (self.stop) return; + var v = easeInOutCubic(Date.now() - startTime, 650); var scaleX = 1; var translateX = 0; @@ -50008,6 +58546,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io return function() { startTime = Date.now(); run(); + return self; }; } @@ -50028,7 +58567,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io '$attrs', '$ionicConfig', function($element, $attrs, $ionicConfig) { - var spinnerName; + var spinnerName, anim; this.init = function() { spinnerName = $attrs.icon || $ionicConfig.spinner.icon(); @@ -50051,7 +58590,11 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io }; this.start = function() { - animations[spinnerName] && animations[spinnerName]($element[0])(); + animations[spinnerName] && (anim = animations[spinnerName]($element[0])()); + }; + + this.stop = function() { + animations[spinnerName] && (anim.stop = true); }; }]); @@ -50096,6 +58639,7 @@ function($scope, $element, $ionicHistory) { var selectedTab = null; var previousSelectedTab = null; var selectedTabIndex; + var isVisible = true; self.tabs = []; self.selectedIndex = function() { @@ -50202,6 +58746,17 @@ function($scope, $element, $ionicHistory) { return false; }; + self.showBar = function(show) { + if (arguments.length) { + if (show) { + $element.removeClass('tabs-item-hide'); + } else { + $element.addClass('tabs-item-hide'); + } + isVisible = !!show; + } + return isVisible; + }; }]); IonicModule @@ -50368,7 +58923,7 @@ IonicModule '<div class="action-sheet" ng-class="{\'action-sheet-has-icons\': $actionSheetHasIcon}">' + '<div class="action-sheet-group action-sheet-options">' + '<div class="action-sheet-title" ng-if="titleText" ng-bind-html="titleText"></div>' + - '<button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-repeat="b in buttons" ng-bind-html="b.text"></button>' + + '<button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-class="b.className" ng-repeat="b in buttons" ng-bind-html="b.text"></button>' + '<button class="button destructive action-sheet-destructive" ng-if="destructiveText" ng-click="destructiveButtonClicked()" ng-bind-html="destructiveText"></button>' + '</div>' + '<div class="action-sheet-group action-sheet-cancel" ng-if="cancelText">' + @@ -50495,7 +59050,7 @@ IonicModule * <ion-scroll direction="x" class="available-scroller"> * <div class="photo" collection-repeat="photo in main.photos" * item-height="250" item-width="photo.width + 30"> - * <img ng-src="{{photo.src}}"> + * <img ng-src="{% raw %}{{photo.src}}{% endraw %}"> * </div> * </ion-scroll> * </ion-content> @@ -50777,17 +59332,15 @@ function CollectionRepeatDirective($ionicCollectionManager, $parse, $window, $$r // If it's a constant, it's either a percent or just a constant pixel number. if (isConstant) { - var intValue = parseInt(parsedValue()); - // For percents, store the percent getter on .getValue() if (attrValue.indexOf('%') > -1) { - var decimalValue = intValue / 100; + var decimalValue = parseFloat(parsedValue()) / 100; dimensionData.getValue = dimensionData === heightData ? function() { return Math.floor(decimalValue * scrollView.__clientHeight); } : function() { return Math.floor(decimalValue * scrollView.__clientWidth); }; } else { // For static constants, just store the static constant. - dimensionData.value = intValue; + dimensionData.value = parseInt(parsedValue()); } } else { @@ -50796,14 +59349,14 @@ function CollectionRepeatDirective($ionicCollectionManager, $parse, $window, $$r function heightGetter(scope, locals) { var result = parsedValue(scope, locals); if (result.charAt && result.charAt(result.length - 1) === '%') { - return Math.floor(parseInt(result) / 100 * scrollView.__clientHeight); + return Math.floor(parseFloat(result) / 100 * scrollView.__clientHeight); } return parseInt(result); } : function widthGetter(scope, locals) { var result = parsedValue(scope, locals); if (result.charAt && result.charAt(result.length - 1) === '%') { - return Math.floor(parseInt(result) / 100 * scrollView.__clientWidth); + return Math.floor(parseFloat(result) / 100 * scrollView.__clientWidth); } return parseInt(result); }; @@ -51462,7 +60015,7 @@ function RepeatManagerFactory($rootScope, $window, $$rAF) { * @param {string=} direction Which way to scroll. 'x' or 'y' or 'xy'. Default 'y'. * @param {boolean=} locking Whether to lock scrolling in one direction at a time. Useful to set to false when zoomed in or scrolling in two directions. Default true. * @param {boolean=} padding Whether to add padding to the content. - * of the content. Defaults to true on iOS, false on Android. + * Defaults to true on iOS, false on Android. * @param {boolean=} scroll Whether to allow scrolling of content. Defaults to true. * @param {boolean=} overflow-scroll Whether to use overflow-scrolling instead of * Ionic scroll. See {@link ionic.provider:$ionicConfigProvider} to set this as the global default. @@ -51504,13 +60057,12 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { element.addClass('scroll-content-false'); } - var nativeScrolling = attr.overflowScroll === "true" || !$ionicConfig.scrolling.jsScrolling(); + var nativeScrolling = attr.overflowScroll !== "false" && (attr.overflowScroll === "true" || !$ionicConfig.scrolling.jsScrolling()); // collection-repeat requires JS scrolling if (nativeScrolling) { nativeScrolling = !element[0].querySelector('[collection-repeat]'); } - return { pre: prelink }; function prelink($scope, $element, $attr) { var parentScope = $scope.$parent; @@ -51593,6 +60145,8 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { scrollViewOptions: scrollViewOptions }); + $scope.scrollCtrl = scrollCtrl; + $scope.$on('$destroy', function() { if (scrollViewOptions) { scrollViewOptions.scrollingComplete = noop; @@ -51641,7 +60195,6 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { * the most common use-case. However, for added flexibility, any valid media query could be added * as the value, such as `(min-width:600px)` or even multiple queries such as * `(min-width:750px) and (max-width:1200px)`. - * @usage * ```html * <ion-side-menus> @@ -51657,12 +60210,21 @@ function($timeout, $controller, $ionicBind, $ionicConfig) { * For a complete side menu example, see the * {@link ionic.directive:ionSideMenus} documentation. */ + IonicModule.directive('exposeAsideWhen', ['$window', function($window) { return { restrict: 'A', require: '^ionSideMenus', link: function($scope, $element, $attr, sideMenuCtrl) { + // Setup a match media query listener that triggers a ui change only when a change + // in media matching status occurs + var mq = $attr.exposeAsideWhen == 'large' ? '(min-width:768px)' : $attr.exposeAsideWhen; + var mql = $window.matchMedia(mq); + mql.addListener(function() { + onResize(); + }); + function checkAsideExpose() { var mq = $attr.exposeAsideWhen == 'large' ? '(min-width:768px)' : $attr.exposeAsideWhen; sideMenuCtrl.exposeAside($window.matchMedia(mq).matches); @@ -51679,18 +60241,10 @@ IonicModule.directive('exposeAsideWhen', ['$window', function($window) { }, 300, false); $scope.$evalAsync(checkAsideExpose); - - ionic.on('resize', onResize, $window); - - $scope.$on('$destroy', function() { - ionic.off('resize', onResize, $window); - }); - } }; }]); - var GESTURE_DIRECTIVES = 'onHold onTap onDoubleTap onTouch onRelease onDragStart onDrag onDragEnd onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeDown onSwipeLeft'.split(' '); GESTURE_DIRECTIVES.forEach(function(name) { @@ -51997,7 +60551,7 @@ function gestureDirective(directiveName) { IonicModule -.directive('ionHeaderBar', tapScrollToTopDirective()) +//.directive('ionHeaderBar', tapScrollToTopDirective()) /** * @ngdoc directive @@ -52074,7 +60628,7 @@ IonicModule */ .directive('ionFooterBar', headerFooterBarDirective(false)); -function tapScrollToTopDirective() { +function tapScrollToTopDirective() { //eslint-disable-line no-unused-vars return ['$ionicScrollDelegate', function($ionicScrollDelegate) { return { restrict: 'E', @@ -52161,6 +60715,12 @@ function headerFooterBarDirective(isHeader) { $scope.$watch('$hasTabs', function(val) { $element.toggleClass('has-tabs', !!val); }); + ctrl.align(); + $scope.$on('$ionicFooter.align', function() { + ionic.requestAnimationFrame(function() { + ctrl.align(); + }); + }); } } } @@ -52278,6 +60838,137 @@ IonicModule }; }]); +/** +* @ngdoc directive +* @name ionInput +* @parent ionic.directive:ionList +* @module ionic +* @restrict E +* Creates a text input group that can easily be focused +* +* @usage +* +* ```html +* <ion-list> +* <ion-input> +* <input type="text" placeholder="First Name"> +* <ion-input> +* +* <ion-input> +* <ion-label>Username</ion-label> +* <input type="text"> +* </ion-input> +* </ion-list> +* ``` +*/ + +var labelIds = -1; + +IonicModule +.directive('ionInput', [function() { + return { + restrict: 'E', + controller: ['$scope', '$element', function($scope, $element) { + this.$scope = $scope; + this.$element = $element; + + this.setInputAriaLabeledBy = function(id) { + var inputs = $element[0].querySelectorAll('input,textarea'); + inputs.length && inputs[0].setAttribute('aria-labelledby', id); + }; + + this.focus = function() { + var inputs = $element[0].querySelectorAll('input,textarea'); + inputs.length && inputs[0].focus(); + }; + }] + }; +}]); + +/** +* @ngdoc directive +* @name ionLabel +* @parent ionic.directive:ionList +* @module ionic +* @restrict E +* +* New in Ionic 1.2. It is strongly recommended that you use `<ion-label>` in place +* of any `<label>` elements for maximum cross-browser support and performance. +* +* Creates a label for a form input. +* +* @usage +* +* ```html +* <ion-list> +* <ion-input> +* <ion-label>Username</ion-label> +* <input type="text"> +* </ion-input> +* </ion-list> +* ``` +*/ +IonicModule +.directive('ionLabel', [function() { + return { + restrict: 'E', + require: '?^ionInput', + compile: function() { + + return function link($scope, $element, $attrs, ionInputCtrl) { + var element = $element[0]; + + $element.addClass('input-label'); + + $element.attr('aria-label', $element.text()); + var id = element.id || '_label-' + ++labelIds; + + if (!element.id) { + $element.attr('id', id); + } + + if (ionInputCtrl) { + + ionInputCtrl.setInputAriaLabeledBy(id); + + $element.on('click', function() { + ionInputCtrl.focus(); + }); + } + }; + } + }; +}]); + +/** + * Input label adds accessibility to <span class="input-label">. + */ +IonicModule +.directive('inputLabel', [function() { + return { + restrict: 'C', + require: '?^ionInput', + compile: function() { + + return function link($scope, $element, $attrs, ionInputCtrl) { + var element = $element[0]; + + $element.attr('aria-label', $element.text()); + var id = element.id || '_label-' + ++labelIds; + + if (!element.id) { + $element.attr('id', id); + } + + if (ionInputCtrl) { + ionInputCtrl.setInputAriaLabeledBy(id); + } + + }; + } + }; +}]); + /** * @ngdoc directive * @name ionItem @@ -52486,7 +61177,7 @@ var ITEM_TPL_OPTION_BUTTONS = * @description * Creates an option button inside a list item, that is visible when the item is swiped * to the left by the user. Swiped open option buttons can be hidden with -* {@link ionic.service:$ionicListDelegate#closeOptionButtons $ionicListDelegate#closeOptionButtons}. +* {@link ionic.service:$ionicListDelegate#closeOptionButtons $ionicListDelegate.closeOptionButtons}. * * Can be assigned any button class. * @@ -52667,7 +61358,7 @@ IonicModule } //for testing - var keyboardHeight = e.keyboardHeight || e.detail.keyboardHeight; + var keyboardHeight = e.keyboardHeight || (e.detail && e.detail.keyboardHeight); element.css('bottom', keyboardHeight + "px"); scrollCtrl = element.controller('$ionicScroll'); if (scrollCtrl) { @@ -52919,9 +61610,21 @@ function($timeout) { * ```html * <a menu-close href="#/home" class="item">Home</a> * ``` + * + * Note that if your destination state uses a resolve and that resolve asynchronously + * takes longer than a standard transition (300ms), you'll need to set the + * `nextViewOptions` manually as your resolve completes. + * + * ```js + * $ionicHistory.nextViewOptions({ + * historyRoot: true, + * disableAnimate: true, + * expire: 300 + * }); + * ``` */ IonicModule -.directive('menuClose', ['$ionicHistory', function($ionicHistory) { +.directive('menuClose', ['$ionicHistory', '$timeout', function($ionicHistory, $timeout) { return { restrict: 'AC', link: function($scope, $element) { @@ -52933,6 +61636,15 @@ IonicModule disableAnimate: true, expire: 300 }); + // if no transition in 300ms, reset nextViewOptions + // the expire should take care of it, but will be cancelled in some + // cases. This directive is an exception to the rules of history.js + $timeout( function() { + $ionicHistory.nextViewOptions({ + historyRoot: false, + disableAnimate: false + }); + }, 300); sideMenuCtrl.close(); } }); @@ -53497,7 +62209,7 @@ IonicModule * }); * }); * ``` - * Then on app start, $stateProvider will look at the url, see it matches the index state, + * Then on app start, $stateProvider will look at the url, see if it matches the index state, * and then try to load home.html into the `<ion-nav-view>`. * * Pages are loaded by the URLs given. One simple way to create templates in Angular is to put @@ -53755,7 +62467,7 @@ IonicModule * @description * The radio directive is no different than the HTML radio input, except it's styled differently. * - * Radio behaves like any [AngularJS radio](http://docs.angularjs.org/api/ng/input/input[radio]). + * Radio behaves like [AngularJS radio](http://docs.angularjs.org/api/ng/input/input[radio]). * * @usage * ```html @@ -53783,13 +62495,16 @@ IonicModule template: '<label class="item item-radio">' + '<input type="radio" name="radio-group">' + - '<div class="item-content disable-pointer-events" ng-transclude></div>' + - '<i class="radio-icon disable-pointer-events icon ion-checkmark"></i>' + + '<div class="radio-content">' + + '<div class="item-content disable-pointer-events" ng-transclude></div>' + + '<i class="radio-icon disable-pointer-events icon ion-checkmark"></i>' + + '</div>' + '</label>', compile: function(element, attr) { if (attr.icon) { - element.children().eq(2).removeClass('ion-checkmark').addClass(attr.icon); + var iconElm = element.find('i'); + iconElm.removeClass('ion-checkmark').addClass(attr.icon); } var input = element.find('input'); @@ -53976,12 +62691,13 @@ IonicModule '$timeout', '$controller', '$ionicBind', -function($timeout, $controller, $ionicBind) { + '$ionicConfig', +function($timeout, $controller, $ionicBind, $ionicConfig) { return { restrict: 'E', scope: true, controller: function() {}, - compile: function(element) { + compile: function(element, attr) { element.addClass('scroll-view ionic-scroll'); //We cannot transclude here because it breaks element.data() inheritance on compile @@ -53989,6 +62705,8 @@ function($timeout, $controller, $ionicBind) { innerElement.append(element.contents()); element.append(innerElement); + var nativeScrolling = attr.overflowScroll !== "false" && (attr.overflowScroll === "true" || !$ionicConfig.scrolling.jsScrolling()); + return { pre: prelink }; function prelink($scope, $element, $attr) { $ionicBind($scope, $attr, { @@ -54016,6 +62734,12 @@ function($timeout, $controller, $ionicBind) { if (!$scope.direction) { $scope.direction = 'y'; } var isPaging = $scope.$eval($scope.paging) === true; + if (nativeScrolling) { + $element.addClass('overflow-scroll'); + } + + $element.addClass('scroll-' + $scope.direction); + var scrollViewOptions = { el: $element[0], delegateHandle: $attr.delegateHandle, @@ -54029,8 +62753,10 @@ function($timeout, $controller, $ionicBind) { zooming: $scope.$eval($scope.zooming) === true, maxZoom: $scope.$eval($scope.maxZoom) || 3, minZoom: $scope.$eval($scope.minZoom) || 0.5, - preventDefault: true + preventDefault: true, + nativeScrolling: nativeScrolling }; + if (isPaging) { scrollViewOptions.speedMultiplier = 0.8; scrollViewOptions.bouncing = false; @@ -54241,6 +62967,22 @@ function($timeout, $ionicGesture, $window) { element: element[0], onDrag: function() {}, endDrag: function() {}, + setCanScroll: function(canScroll) { + var c = $element[0].querySelector('.scroll'); + + if (!c) { + return; + } + + var content = angular.element(c.parentElement); + if (!content) { + return; + } + + // freeze our scroll container if we have one + var scrollScope = content.scope(); + scrollScope.scrollCtrl && scrollScope.scrollCtrl.freezeScrollShut(!canScroll); + }, getTranslateX: function() { return $scope.sideMenuContentTranslateX || 0; }, @@ -54275,6 +63017,24 @@ function($timeout, $ionicGesture, $window) { // reset incase left gets grabby $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(0,0,0)'; }), + setMarginLeftAndRight: ionic.animationFrameThrottle(function(amountLeft, amountRight) { + amountLeft = amountLeft && parseInt(amountLeft, 10) || 0; + amountRight = amountRight && parseInt(amountRight, 10) || 0; + + var amount = amountLeft + amountRight; + + if (amount > 0) { + $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(' + amountLeft + 'px,0,0)'; + $element[0].style.width = ($window.innerWidth - amount) + 'px'; + content.offsetX = amountLeft; + } else { + $element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(0,0,0)'; + $element[0].style.width = ''; + content.offsetX = 0; + } + // reset incase left gets grabby + //$element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(0,0,0)'; + }), enableAnimation: function() { $scope.animationEnabled = true; $element[0].classList.add('menu-animated'); @@ -54290,9 +63050,7 @@ function($timeout, $ionicGesture, $window) { // add gesture handlers var gestureOpts = { stop_browser_behavior: false }; - if (ionic.DomUtil.getParentOrSelfWithClass($element[0], 'overflow-scroll')) { - gestureOpts.prevent_default_directions = ['left', 'right']; - } + gestureOpts.prevent_default_directions = ['left', 'right']; var contentTapGesture = $ionicGesture.on('tap', onContentTap, $element, gestureOpts); var dragRightGesture = $ionicGesture.on('dragright', onDragX, $element, gestureOpts); var dragLeftGesture = $ionicGesture.on('dragleft', onDragX, $element, gestureOpts); @@ -54364,21 +63122,18 @@ IonicModule * * ```html * <ion-side-menus> - * <!-- Center content --> - * <ion-side-menu-content ng-controller="ContentController"> - * </ion-side-menu-content> - * * <!-- Left menu --> * <ion-side-menu side="left"> * </ion-side-menu> * + * <ion-side-menu-content> + * <!-- Main content, usually <ion-nav-view> --> + * </ion-side-menu-content> + * * <!-- Right menu --> * <ion-side-menu side="right"> * </ion-side-menu> * - * <ion-side-menu-content> - * <!-- Main content, usually <ion-nav-view> --> - * </ion-side-menu-content> * </ion-side-menus> * ``` * ```js @@ -54436,6 +63191,8 @@ IonicModule * @ngdoc directive * @name ionSlideBox * @module ionic + * @deprecated will be removed in the next Ionic release in favor of the new ion-slides component. + * Don't depend on the internal behavior of this widget. * @delegate ionic.service:$ionicSlideBoxDelegate * @restrict E * @description @@ -54466,16 +63223,17 @@ IonicModule * @param {boolean=} show-pager Whether a pager should be shown for this slide box. Accepts expressions via `show-pager="{{shouldShow()}}"`. Defaults to true. * @param {expression=} pager-click Expression to call when a pager is clicked (if show-pager is true). Is passed the 'index' variable. * @param {expression=} on-slide-changed Expression called whenever the slide is changed. Is passed an '$index' variable. - * @param {expression=} active-slide Model to bind the current slide to. + * @param {expression=} active-slide Model to bind the current slide index to. */ IonicModule .directive('ionSlideBox', [ + '$animate', '$timeout', '$compile', '$ionicSlideBoxDelegate', '$ionicHistory', '$ionicScrollDelegate', -function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScrollDelegate) { +function($animate, $timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScrollDelegate) { return { restrict: 'E', replace: true, @@ -54488,12 +63246,14 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll pagerClick: '&', disableScroll: '@', onSlideChanged: '&', - activeSlide: '=?' + activeSlide: '=?', + bounce: '@' }, controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) { var _this = this; var continuous = $scope.$eval($scope.doesContinue) === true; + var bouncing = ($scope.$eval($scope.bounce) !== false); //Default to true var shouldAutoPlay = isDefined($attrs.autoPlay) ? !!$scope.autoPlay : false; var slideInterval = shouldAutoPlay ? $scope.$eval($scope.slideInterval) || 4000 : 0; @@ -54502,6 +63262,7 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll auto: slideInterval, continuous: continuous, startSlide: $scope.activeSlide, + bouncing: bouncing, slidesChanged: function() { $scope.currentSlide = slider.currentIndex(); @@ -54572,7 +63333,6 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll }; this.onPagerClick = function(index) { - void 0; $scope.pagerClick({index: index}); }; @@ -54586,6 +63346,9 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll '</div>', link: function($scope, $element, $attr) { + // Disable ngAnimate for slidebox and its children + $animate.enabled(false, $element); + // if showPager is undefined, show the pager if (!isDefined($attr.showPager)) { $scope.showPager = true; @@ -54593,6 +63356,7 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll } $attr.$observe('showPager', function(show) { + if (show === undefined) return; show = $scope.$eval(show); getPager().toggleClass('hide', !show); }); @@ -54613,7 +63377,7 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll .directive('ionSlide', function() { return { restrict: 'E', - require: '^ionSlideBox', + require: '?^ionSlideBox', compile: function(element) { element.addClass('slider-slide'); } @@ -54655,6 +63419,132 @@ function($timeout, $compile, $ionicSlideBoxDelegate, $ionicHistory, $ionicScroll }); + +/** + * @ngdoc directive + * @name ionSlides + * @module ionic + * @delegate ionic.service:$ionicSlideBoxDelegate + * @restrict E + * @description + * The Slides component is a powerful multi-page container where each page can be swiped or dragged between. + * + * Note: this is a new version of the Ionic Slide Box based on the [Swiper](http://www.idangero.us/swiper/#.Vmc1J-ODFBc) widget from + * [idangerous](http://www.idangero.us/). + * + *  + * + * @usage + * ```html + * <ion-slides on-slide-changed="slideHasChanged($index)"> + * <ion-slide-page> + * <div class="box blue"><h1>BLUE</h1></div> + * </ion-slide-page> + * <ion-slide-page> + * <div class="box yellow"><h1>YELLOW</h1></div> + * </ion-slide-page> + * <ion-slide-page> + * <div class="box pink"><h1>PINK</h1></div> + * </ion-slide-page> + * </ion-slides> + * ``` + * + * @param {string=} delegate-handle The handle used to identify this slideBox + * with {@link ionic.service:$ionicSlideBoxDelegate}. + * @param {object=} options to pass to the widget. See the full ist here: [http://www.idangero.us/swiper/api/](http://www.idangero.us/swiper/api/) + */ +IonicModule +.directive('ionSlides', [ + '$animate', + '$timeout', + '$compile', +function($animate, $timeout, $compile) { + return { + restrict: 'E', + transclude: true, + scope: { + options: '=', + slider: '=' + }, + template: '<div class="swiper-container">' + + '<div class="swiper-wrapper" ng-transclude>' + + '</div>' + + '<div ng-hide="!showPager" class="swiper-pagination"></div>' + + '</div>', + controller: ['$scope', '$element', function($scope, $element) { + var _this = this; + + this.update = function() { + $timeout(function() { + if (!_this.__slider) { + return; + } + + _this.__slider.update(); + if (_this._options.loop) { + _this.__slider.createLoop(); + } + + // Don't allow pager to show with > 10 slides + if (_this.__slider.slides.length > 10) { + $scope.showPager = false; + } + }); + }; + + this.rapidUpdate = ionic.debounce(function() { + _this.update(); + }, 50); + + this.getSlider = function() { + return _this.__slider; + }; + + var options = $scope.options || {}; + + var newOptions = angular.extend({ + pagination: '.swiper-pagination', + paginationClickable: true, + lazyLoading: true, + preloadImages: false + }, options); + + this._options = newOptions; + + $timeout(function() { + var slider = new ionic.views.Swiper($element.children()[0], newOptions, $scope, $compile); + + _this.__slider = slider; + $scope.slider = _this.__slider; + + $scope.$on('$destroy', function() { + slider.destroy(); + }); + }); + + }], + + + link: function($scope) { + $scope.showPager = true; + // Disable ngAnimate for slidebox and its children + //$animate.enabled(false, $element); + } + }; +}]) +.directive('ionSlidePage', [function() { + return { + restrict: 'E', + require: '?^ionSlides', + transclude: true, + replace: true, + template: '<div class="swiper-slide" ng-transclude></div>', + link: function($scope, $element, $attr, ionSlidesCtrl) { + ionSlidesCtrl.rapidUpdate(); + } + }; +}]); + /** * @ngdoc directive * @name ionSpinner @@ -54845,6 +63735,10 @@ IonicModule link: function($scope, $element, $attrs, ctrl) { var spinnerName = ctrl.init(); $element.addClass('spinner spinner-' + spinnerName); + + $element.on('$destroy', function onDestroy() { + ctrl.stop(); + }); } }; }); @@ -55144,7 +64038,7 @@ IonicModule * * @usage * ```html - * <ion-tabs class="tabs-positive tabs-icon-only"> + * <ion-tabs class="tabs-positive tabs-icon-top"> * * <ion-tab title="Home" icon-on="ion-ios-filing" icon-off="ion-ios-filing-outline"> * <!-- Tab 1 content --> @@ -55237,6 +64131,34 @@ function($ionicTabsDelegate, $ionicConfig) { }; }]); +/** +* @ngdoc directive +* @name ionTitle +* @module ionic +* @restrict E +* +* Used for titles in header and nav bars. New in 1.2 +* +* Identical to <div class="title"> but with future compatibility for Ionic 2 +* +* @usage +* +* ```html +* <ion-nav-bar> +* <ion-title>Hello</ion-title> +* <ion-nav-bar> +* ``` +*/ +IonicModule +.directive('ionTitle', [function() { + return { + restrict: 'E', + compile: function(element) { + element.addClass('title'); + } + }; +}]); + /** * @ngdoc directive * @name ionToggle diff --git a/www/lib/ionic/js/ionic.bundle.min.js b/www/lib/ionic/js/ionic.bundle.min.js index 6a20cc4422375610f2a733532c73e342da92b642..0d53dbcd0269a73da59d743eebd4fbaad2e096c6 100644 --- a/www/lib/ionic/js/ionic.bundle.min.js +++ b/www/lib/ionic/js/ionic.bundle.min.js @@ -6,10 +6,10 @@ */ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -19,9 +19,12 @@ * */ -!function(){function e(e,t,n){t!==!1?F.addEventListener(e,J[e],n):F.removeEventListener(e,J[e])}function t(e){var t=T(e.target),i=E(t);if(ionic.tap.requiresNativeClick(i)||$)return!1;var o=ionic.tap.pointerCoord(e);n("click",i,o.x,o.y),h(i)}function n(e,t,n,i){var o=document.createEvent("MouseEvents");o.initMouseEvent(e,!0,!0,window,1,0,0,n,i,!1,!1,!1,!1,0,null),o.isIonicTap=!0,t.dispatchEvent(o)}function i(e){return"submit"==e.target.type&&0===e.detail?null:ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)||!e.isIonicTap&&!ionic.tap.requiresNativeClick(e.target)?(e.stopPropagation(),ionic.tap.isLabelWithTextInput(e.target)||e.preventDefault(),!1):void 0}function o(t){return t.isIonicTap||_(t)?null:X?(t.stopPropagation(),ionic.tap.isTextInput(t.target)&&B===t.target||/^(select|option)$/i.test(t.target.tagName)||t.preventDefault(),!1):($=!1,U=ionic.tap.pointerCoord(t),e("mousemove"),void ionic.activator.start(t))}function r(n){return X?(n.stopPropagation(),n.preventDefault(),!1):_(n)||/^(select|option)$/i.test(n.target.tagName)?!1:(v(n)||t(n),e("mousemove",!1),ionic.activator.end(),void($=!1))}function s(t){return v(t)?(e("mousemove",!1),ionic.activator.end(),$=!0,!1):void 0}function a(t){if(!_(t)&&($=!1,d(),U=ionic.tap.pointerCoord(t),e(K),ionic.activator.start(t),ionic.Platform.isIOS()&&ionic.tap.isLabelWithTextInput(t.target))){var n=E(T(t.target));n!==Y&&t.preventDefault()}}function l(e){_(e)||(d(),v(e)||(t(e),/^(select|option)$/i.test(e.target.tagName)&&e.preventDefault()),B=e.target,u())}function c(t){return v(t)?($=!0,e(K,!1),ionic.activator.end(),!1):void 0}function u(){e(K,!1),ionic.activator.end(),$=!1}function d(){X=!0,clearTimeout(W),W=setTimeout(function(){X=!1},600)}function _(e){return e.isTapHandled?!0:(e.isTapHandled=!0,ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)?(e.preventDefault(),!0):void 0)}function h(e){q=null;var t=!1;"SELECT"==e.tagName?(n("mousedown",e,0,0),e.focus&&e.focus(),t=!0):g()===e?t=!0:/^(input|textarea)$/i.test(e.tagName)||e.isContentEditable?(t=!0,e.focus&&e.focus(),e.value=e.value,X&&(q=e)):f(),t&&(g(e),ionic.trigger("ionic.focusin",{target:e},!0))}function f(){var e=g();e&&(/^(input|textarea|select)$/i.test(e.tagName)||e.isContentEditable)&&e.blur(),g(null)}function p(e){X&&ionic.tap.isTextInput(g())&&ionic.tap.isTextInput(q)&&q!==e.target&&(q.focus(),q=null),ionic.scroll.isScrolling=!1}function m(){g(null)}function g(e){return arguments.length&&(Y=e),Y||document.activeElement}function v(e){if(!e||1!==e.target.nodeType||!U||0===U.x&&0===U.y)return!1;var t=ionic.tap.pointerCoord(e),n=!(!e.target.classList||!e.target.classList.contains||"function"!=typeof e.target.classList.contains),i=n&&e.target.classList.contains("button")?j:Z;return Math.abs(U.x-t.x)>i||Math.abs(U.y-t.y)>i}function T(e,t){for(var n=e,i=0;6>i&&n;i++){if("LABEL"===n.tagName)return n;n=n.parentElement}return t!==!1?e:void 0}function E(e){if(e&&"LABEL"===e.tagName){if(e.control)return e.control;if(e.querySelector){var t=e.querySelector("input,textarea,select");if(t)return t}}return e}function S(){ionic.keyboard.isInitialized||(V()?(window.addEventListener("native.keyboardshow",ue),window.addEventListener("native.keyboardhide",y)):document.body.addEventListener("focusout",y),document.body.addEventListener("ionic.focusin",ce),document.body.addEventListener("focusin",ce),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!0)}function b(e){clearTimeout(ne),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),ionic.keyboard.height=e.keyboardHeight,se?M(A,!0):M(I,!0)}function w(e){return clearTimeout(ne),e.target&&!e.target.readOnly&&ionic.tap.isKeyboardElement(e.target)&&(ee=ionic.DomUtil.getParentWithClass(e.target,le))?(Q=e.target,ee.classList.contains("overflow-scroll")||(document.body.scrollTop=0,ee.scrollTop=0,ionic.requestAnimationFrame(function(){document.body.scrollTop=0,ee.scrollTop=0}),window.navigator.msPointerEnabled?document.addEventListener("MSPointerMove",x,!1):document.addEventListener("touchmove",x,!1)),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),document.addEventListener("keydown",L,!1),void(ionic.keyboard.isOpen||V()?ionic.keyboard.isOpen&&I():M(I,!0))):void(Q=null)}function y(){clearTimeout(ne),(ionic.keyboard.isOpen||ionic.keyboard.isOpening)&&(ionic.keyboard.isClosing=!0,ionic.keyboard.isOpening=!1),ne=setTimeout(function(){ionic.requestAnimationFrame(function(){se?M(function(){A(),N()},!1):M(N,!1)})},50)}function D(){ionic.keyboard.isLandscape=!ionic.keyboard.isLandscape,ionic.Platform.isIOS()&&A(),ionic.Platform.isAndroid()&&(ionic.keyboard.isOpen&&V()?se=!0:M(A,!1))}function L(e){ionic.scroll.isScrolling&&x(e)}function x(e){"TEXTAREA"!==e.target.tagName&&e.preventDefault()}function M(e,t){clearInterval(te);var n,i=0,o=k(),r=o;return n=ionic.Platform.isAndroid()&&ionic.Platform.version()<4.4?30:ionic.Platform.isAndroid()?10:1,te=setInterval(function(){r=k(),(!(++i<n)||(O(r)||P(r))&&ionic.keyboard.height)&&(V()||(ionic.keyboard.height=Math.abs(o-window.innerHeight)),ionic.keyboard.isOpen=t,clearInterval(te),e())},50),n}function N(){clearTimeout(ne),ionic.keyboard.isOpen=!1,ionic.keyboard.isClosing=!1,Q&&ionic.trigger("resetScrollView",{target:Q},!0),ionic.requestAnimationFrame(function(){document.body.classList.remove(ae)}),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerMove",x):document.removeEventListener("touchmove",x),document.removeEventListener("keydown",L),ionic.Platform.isAndroid()&&(V()&&cordova.plugins.Keyboard.close(),Q&&Q.blur()),Q=null}function I(){ionic.keyboard.isOpen=!0,ionic.keyboard.isOpening=!1;var e={keyboardHeight:C(),viewportHeight:ie};if(Q){e.target=Q;var t=Q.getBoundingClientRect();e.elementTop=Math.round(t.top),e.elementBottom=Math.round(t.bottom),e.windowHeight=e.viewportHeight-e.keyboardHeight,e.isElementUnderKeyboard=e.elementBottom>e.windowHeight,ionic.trigger("scrollChildIntoView",e,!0)}return setTimeout(function(){document.body.classList.add(ae)},400),e}function C(){if(ionic.keyboard.height)return ionic.keyboard.height;if(ionic.Platform.isAndroid()){if(ionic.Platform.isFullScreen)return 275;var e=window.innerHeight;return ie>e?ie-e:0}return ionic.Platform.isIOS()?ionic.keyboard.isLandscape?206:ionic.Platform.isWebView()?260:216:275}function O(e){return!!(!ionic.keyboard.isLandscape&&oe&&Math.abs(oe-e)<2)}function P(e){return!!(ionic.keyboard.isLandscape&&re&&Math.abs(re-e)<2)}function A(){se=!1,ie=k(),ionic.keyboard.isLandscape&&!re?re=ie:ionic.keyboard.isLandscape||oe||(oe=ie),Q&&ionic.trigger("resetScrollView",{target:Q},!0),ionic.keyboard.isOpen&&ionic.tap.isTextInput(Q)&&I()}function G(){var e=k();e/window.innerWidth<1&&(ionic.keyboard.isLandscape=!0),ie=e,ionic.keyboard.isLandscape&&!re?re=ie:ionic.keyboard.isLandscape||oe||(oe=ie)}function k(){var e=window.innerHeight;return ionic.Platform.isAndroid()&&ionic.Platform.isFullScreen||!ionic.keyboard.isOpen&&!ionic.keyboard.isOpening||ionic.keyboard.isClosing?e:e+C()}function V(){return!!(window.cordova&&cordova.plugins&&cordova.plugins.Keyboard)}function R(){var e;for(e=0;e<document.head.children.length;e++)if("viewport"==document.head.children[e].name){de=document.head.children[e];break}if(de){var t,n=de.content.toLowerCase().replace(/\s+/g,"").split(",");for(e=0;e<n.length;e++)n[e]&&(t=n[e].split("="),_e[t[0]]=t.length>1?t[1]:"_");z()}}function z(){var e=_e.width,t=_e.height,n=ionic.Platform,i=n.version(),o="device-width",r="device-height",s=ionic.viewport.orientation();delete _e.height,_e.width=o,n.isIPad()?i>7?delete _e.width:n.isWebView()?90==s?_e.height="0":7==i&&(_e.height=r):7>i&&(_e.height="0"):n.isIOS()&&(n.isWebView()?i>7?delete _e.width:7>i?t&&(_e.height="0"):7==i&&(_e.height=r):7>i&&t&&(_e.height="0")),(e!==_e.width||t!==_e.height)&&H()}function H(){var e,t=[];for(e in _e)_e[e]&&t.push(e+("_"==_e[e]?"":"="+_e[e]));de.content=t.join(", ")}window.ionic=window.ionic||{},window.ionic.views={},window.ionic.version="1.0.1",function(e){e.DelegateService=function(e){function t(){return!0}if(e.indexOf("$getByHandle")>-1)throw new Error("Method '$getByHandle' is implicitly added to each delegate service. Do not list it as a method.");return["$log",function(n){function i(e,t){this._instances=e,this.handle=t}function o(){this._instances=[]}function r(e){return function(){var t,i=this.handle,o=arguments,r=0;return this._instances.forEach(function(n){if((!i||i==n.$$delegateHandle)&&n.$$filterFn(n)){r++;var s=n[e].apply(n,o);1===r&&(t=s)}}),!r&&i?n.warn('Delegate for handle "'+i+'" could not find a corresponding element with delegate-handle="'+i+'"! '+e+"() was not called!\nPossible cause: If you are calling "+e+'() immediately, and your element with delegate-handle="'+i+'" is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to '+e+"() and try again."):t}}return e.forEach(function(e){i.prototype[e]=r(e)}),o.prototype=i.prototype,o.prototype._registerInstance=function(e,n,i){var o=this._instances;return e.$$delegateHandle=n,e.$$filterFn=i||t,o.push(e),function(){var t=o.indexOf(e);-1!==t&&o.splice(t,1)}},o.prototype.$getByHandle=function(e){return new i(this._instances,e)},new o}]}}(window.ionic),function(e,t,n){function i(){r=!0;for(var e=0;e<o.length;e++)n.requestAnimationFrame(o[e]);o=[],t.removeEventListener("DOMContentLoaded",i)}var o=[],r="complete"===t.readyState||"interactive"===t.readyState;r||t.addEventListener("DOMContentLoaded",i),e._rAF=function(){return e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||function(t){e.setTimeout(t,16)}}();var s=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame;n.DomUtil={requestAnimationFrame:function(t){return e._rAF(t)},cancelAnimationFrame:function(e){s(e)},animationFrameThrottle:function(e){var t,i,o;return function(){t=arguments,o=this,i||(i=!0,n.requestAnimationFrame(function(){e.apply(o,t),i=!1}))}},contains:function(e,t){for(var n=t;n;){if(n===e)return!0;n=n.parentNode}},getPositionInParent:function(e){return{left:e.offsetLeft,top:e.offsetTop}},ready:function(e){r?n.requestAnimationFrame(e):o.push(e)},getTextBounds:function(n){if(t.createRange){var i=t.createRange();if(i.selectNodeContents(n),i.getBoundingClientRect){var o=i.getBoundingClientRect();if(o){var r=e.scrollX,s=e.scrollY;return{top:o.top+s,left:o.left+r,right:o.left+r+o.width,bottom:o.top+s+o.height,width:o.width,height:o.height}}}}return null},getChildIndex:function(e,t){if(t)for(var n,i=e.parentNode.children,o=0,r=0,s=i.length;s>o;o++)if(n=i[o],n.nodeName&&n.nodeName.toLowerCase()==t){if(n==e)return r;r++}return Array.prototype.slice.call(e.parentNode.children).indexOf(e)},swapNodes:function(e,t){t.parentNode.insertBefore(e,t)},elementIsDescendant:function(e,t,n){var i=e;do{if(i===t)return!0;i=i.parentNode}while(i&&i!==n);return!1},getParentWithClass:function(e,t,n){for(n=n||10;e.parentNode&&n--;){if(e.parentNode.classList&&e.parentNode.classList.contains(t))return e.parentNode;e=e.parentNode}return null},getParentOrSelfWithClass:function(e,t,n){for(n=n||10;e&&n--;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},rectContains:function(e,t,n,i,o,r){return n>e||e>o?!1:i>t||t>r?!1:!0},blurAll:function(){return t.activeElement&&t.activeElement!=t.body?(t.activeElement.blur(),t.activeElement):null},cachedAttr:function(e,t,n){if(e=e&&e.length&&e[0]||e,e&&e.setAttribute){var i="$attr-"+t;return arguments.length>2?e[i]!==n&&(e.setAttribute(t,n),e[i]=n):"undefined"==typeof e[i]&&(e[i]=e.getAttribute(t)),e[i]}},cachedStyles:function(e,t){if(e=e&&e.length&&e[0]||e,e&&e.style)for(var n in t)e["$style-"+n]!==t[n]&&(e.style[n]=e["$style-"+n]=t[n])}},n.requestAnimationFrame=n.DomUtil.requestAnimationFrame,n.cancelAnimationFrame=n.DomUtil.cancelAnimationFrame,n.animationFrameThrottle=n.DomUtil.animationFrameThrottle}(window,document,ionic),function(e){e.CustomEvent=function(){if("function"==typeof window.CustomEvent)return CustomEvent;var e=function(e,t){var n;t=t||{bubbles:!1,cancelable:!1,detail:void 0};try{n=document.createEvent("CustomEvent"),n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail)}catch(i){n=document.createEvent("Event");for(var o in t)n[o]=t[o];n.initEvent(e,t.bubbles,t.cancelable)}return n};return e.prototype=window.Event.prototype,e}(),e.EventController={VIRTUALIZED_EVENTS:["tap","swipe","swiperight","swipeleft","drag","hold","release"],trigger:function(t,n,i,o){var r=new e.CustomEvent(t,{detail:n,bubbles:!!i,cancelable:!!o});n&&n.target&&n.target.dispatchEvent&&n.target.dispatchEvent(r)||window.dispatchEvent(r)},on:function(t,n,i){for(var o=i||window,r=0,s=this.VIRTUALIZED_EVENTS.length;s>r;r++)if(t==this.VIRTUALIZED_EVENTS[r]){var a=new e.Gesture(i);return a.on(t,n),a}o.addEventListener(t,n)},off:function(e,t,n){n.removeEventListener(e,t)},onGesture:function(t,n,i,o){var r=new e.Gesture(i,o);return r.on(t,n),r},offGesture:function(e,t,n){e&&e.off(t,n)},handlePopState:function(){}},e.on=function(){e.EventController.on.apply(e.EventController,arguments)},e.off=function(){e.EventController.off.apply(e.EventController,arguments)},e.trigger=e.EventController.trigger,e.onGesture=function(){return e.EventController.onGesture.apply(e.EventController.onGesture,arguments)},e.offGesture=function(){return e.EventController.offGesture.apply(e.EventController.offGesture,arguments)}}(window.ionic),function(e){function t(){if(!e.Gestures.READY){e.Gestures.event.determineEventTypes();for(var t in e.Gestures.gestures)e.Gestures.gestures.hasOwnProperty(t)&&e.Gestures.detection.register(e.Gestures.gestures[t]);e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_MOVE,e.Gestures.detection.detect),e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_END,e.Gestures.detection.detect),e.Gestures.READY=!0}}e.Gesture=function(t,n){return new e.Gestures.Instance(t,n||{})},e.Gestures={},e.Gestures.defaults={stop_browser_behavior:"disable-user-behavior"},e.Gestures.HAS_POINTEREVENTS=window.navigator.pointerEnabled||window.navigator.msPointerEnabled,e.Gestures.HAS_TOUCHEVENTS="ontouchstart"in window,e.Gestures.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android|silk/i,e.Gestures.NO_MOUSEEVENTS=e.Gestures.HAS_TOUCHEVENTS&&window.navigator.userAgent.match(e.Gestures.MOBILE_REGEX),e.Gestures.EVENT_TYPES={},e.Gestures.DIRECTION_DOWN="down",e.Gestures.DIRECTION_LEFT="left",e.Gestures.DIRECTION_UP="up",e.Gestures.DIRECTION_RIGHT="right",e.Gestures.POINTER_MOUSE="mouse",e.Gestures.POINTER_TOUCH="touch",e.Gestures.POINTER_PEN="pen",e.Gestures.EVENT_START="start",e.Gestures.EVENT_MOVE="move",e.Gestures.EVENT_END="end",e.Gestures.DOCUMENT=window.document,e.Gestures.plugins={},e.Gestures.READY=!1,e.Gestures.Instance=function(n,i){var o=this;return null===n?this:(t(),this.element=n,this.enabled=!0,this.options=e.Gestures.utils.extend(e.Gestures.utils.extend({},e.Gestures.defaults),i||{}),this.options.stop_browser_behavior&&e.Gestures.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),e.Gestures.event.onTouch(n,e.Gestures.EVENT_START,function(t){o.enabled&&e.Gestures.detection.startDetect(o,t)}),this)},e.Gestures.Instance.prototype={on:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.addEventListener(n[i],t,!1);return this},off:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.removeEventListener(n[i],t,!1);return this},trigger:function(t,n){var i=e.Gestures.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=n;var o=this.element;return e.Gestures.utils.hasParent(n.target,o)&&(o=n.target),o.dispatchEvent(i),this},enable:function(e){return this.enabled=e,this}};var n=null,i=!1,o=!1;e.Gestures.event={bindDom:function(e,t,n){for(var i=t.split(" "),o=0;o<i.length;o++)e.addEventListener(i[o],n,!1)},onTouch:function(t,r,s){var a=this;this.bindDom(t,e.Gestures.EVENT_TYPES[r],function(l){var c=l.type.toLowerCase();if(!c.match(/mouse/)||!o){c.match(/touch/)||c.match(/pointerdown/)||c.match(/mouse/)&&1===l.which?i=!0:c.match(/mouse/)&&1!==l.which&&(i=!1),c.match(/touch|pointer/)&&(o=!0);var u=0;i&&(e.Gestures.HAS_POINTEREVENTS&&r!=e.Gestures.EVENT_END?u=e.Gestures.PointerEvent.updatePointer(r,l):c.match(/touch/)?u=l.touches.length:o||(u=c.match(/up/)?0:1),u>0&&r==e.Gestures.EVENT_END?r=e.Gestures.EVENT_MOVE:u||(r=e.Gestures.EVENT_END),(u||null===n)&&(n=l),s.call(e.Gestures.detection,a.collectEventData(t,r,a.getTouchList(n,r),l)),e.Gestures.HAS_POINTEREVENTS&&r==e.Gestures.EVENT_END&&(u=e.Gestures.PointerEvent.updatePointer(r,l))),u||(n=null,i=!1,o=!1,e.Gestures.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getEvents():e.Gestures.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_START]=t[0],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_MOVE]=t[1],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_END]=t[2]},getTouchList:function(t){return e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getTouchList():t.touches?t.touches:(t.identifier=1,[t])},collectEventData:function(t,n,i,o){var r=e.Gestures.POINTER_TOUCH;return(o.type.match(/mouse/)||e.Gestures.PointerEvent.matchType(e.Gestures.POINTER_MOUSE,o))&&(r=e.Gestures.POINTER_MOUSE),{center:e.Gestures.utils.getCenter(i),timeStamp:(new Date).getTime(),target:o.target,touches:i,eventType:n,pointerType:r,srcEvent:o,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return e.Gestures.detection.stopDetect()}}}},e.Gestures.PointerEvent={pointers:{},getTouchList:function(){var e=this,t=[];return Object.keys(e.pointers).sort().forEach(function(n){t.push(e.pointers[n])}),t},updatePointer:function(t,n){return t==e.Gestures.EVENT_END?this.pointers={}:(n.identifier=n.pointerId,this.pointers[n.pointerId]=n),Object.keys(this.pointers).length},matchType:function(t,n){if(!n.pointerType)return!1;var i={};return i[e.Gestures.POINTER_MOUSE]=n.pointerType==n.MSPOINTER_TYPE_MOUSE||n.pointerType==e.Gestures.POINTER_MOUSE,i[e.Gestures.POINTER_TOUCH]=n.pointerType==n.MSPOINTER_TYPE_TOUCH||n.pointerType==e.Gestures.POINTER_TOUCH,i[e.Gestures.POINTER_PEN]=n.pointerType==n.MSPOINTER_TYPE_PEN||n.pointerType==e.Gestures.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},e.Gestures.utils={extend:function(e,t,n){for(var i in t)void 0!==e[i]&&n||(e[i]=t[i]);return e},hasParent:function(e,t){for(;e;){if(e==t)return!0;e=e.parentNode}return!1},getCenter:function(e){for(var t=[],n=[],i=0,o=e.length;o>i;i++)t.push(e[i].pageX),n.push(e[i].pageY);return{pageX:(Math.min.apply(Math,t)+Math.max.apply(Math,t))/2,pageY:(Math.min.apply(Math,n)+Math.max.apply(Math,n))/2}},getVelocity:function(e,t,n){return{x:Math.abs(t/e)||0,y:Math.abs(n/e)||0}},getAngle:function(e,t){var n=t.pageY-e.pageY,i=t.pageX-e.pageX;return 180*Math.atan2(n,i)/Math.PI},getDirection:function(t,n){var i=Math.abs(t.pageX-n.pageX),o=Math.abs(t.pageY-n.pageY);return i>=o?t.pageX-n.pageX>0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT:t.pageY-n.pageY>0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN},getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},getScale:function(e,t){return e.length>=2&&t.length>=2?this.getDistance(t[0],t[1])/this.getDistance(e[0],e[1]):1},getRotation:function(e,t){return e.length>=2&&t.length>=2?this.getAngle(t[1],t[0])-this.getAngle(e[1],e[0]):0},isVertical:function(t){return t==e.Gestures.DIRECTION_UP||t==e.Gestures.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(e,t){e&&e.classList&&(e.classList.add(t),e.onselectstart=function(){return!1})}},e.Gestures.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,n){this.current||(this.stopped=!1,this.current={inst:t,startEvent:e.Gestures.utils.extend({},n),lastEvent:!1,name:""},this.detect(n))},detect:function(t){if(!this.current||this.stopped)return null;t=this.extendEventData(t);for(var n=this.current.inst.options,i=0,o=this.gestures.length;o>i;i++){var r=this.gestures[i];if(!this.stopped&&n[r.name]!==!1&&r.handler.call(r,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==e.Gestures.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t},stopDetect:function(){this.previous=e.Gestures.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var n=this.current.startEvent;if(n&&(t.touches.length!=n.touches.length||t.touches===n.touches)){n.touches=[];for(var i=0,o=t.touches.length;o>i;i++)n.touches.push(e.Gestures.utils.extend({},t.touches[i]))}var r=t.timeStamp-n.timeStamp,s=t.center.pageX-n.center.pageX,a=t.center.pageY-n.center.pageY,l=e.Gestures.utils.getVelocity(r,s,a);return e.Gestures.utils.extend(t,{deltaTime:r,deltaX:s,deltaY:a,velocityX:l.x,velocityY:l.y,distance:e.Gestures.utils.getDistance(n.center,t.center),angle:e.Gestures.utils.getAngle(n.center,t.center),direction:e.Gestures.utils.getDirection(n.center,t.center),scale:e.Gestures.utils.getScale(n.touches,t.touches),rotation:e.Gestures.utils.getRotation(n.touches,t.touches),startEvent:n}),t},register:function(t){var n=t.defaults||{};return void 0===n[t.name]&&(n[t.name]=!0),e.Gestures.utils.extend(e.Gestures.defaults,n,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(e,t){return e.index<t.index?-1:e.index>t.index?1:0}),this.gestures}},e.Gestures.gestures=e.Gestures.gestures||{},e.Gestures.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,n){switch(t.eventType){case e.Gestures.EVENT_START:clearTimeout(this.timer),e.Gestures.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==e.Gestures.detection.current.name&&(e.tap.cancelClick(),n.trigger("hold",t))},n.options.hold_timeout);break;case e.Gestures.EVENT_MOVE:t.distance>n.options.hold_threshold&&clearTimeout(this.timer);break;case e.Gestures.EVENT_END:clearTimeout(this.timer)}}},e.Gestures.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END&&"touchcancel"!=t.srcEvent.type){var i=e.Gestures.detection.previous,o=!1;if(t.deltaTime>n.options.tap_max_touchtime||t.distance>n.options.tap_max_distance)return;i&&"tap"==i.name&&t.timeStamp-i.lastEvent.timeStamp<n.options.doubletap_interval&&t.distance<n.options.doubletap_distance&&(n.trigger("doubletap",t),o=!0),(!o||n.options.tap_always)&&(e.Gestures.detection.current.name="tap",n.trigger("tap",t))}}},e.Gestures.gestures.Swipe={name:"swipe",index:40,defaults:{swipe_max_touches:1,swipe_velocity:.4},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END){if(n.options.swipe_max_touches>0&&t.touches.length>n.options.swipe_max_touches)return;(t.velocityX>n.options.swipe_velocity||t.velocityY>n.options.swipe_velocity)&&(n.trigger(this.name,t),n.trigger(this.name+t.direction,t))}}},e.Gestures.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,correct_for_drag_min_distance:!0,drag_max_touches:1,drag_block_horizontal:!0,drag_block_vertical:!0,drag_lock_to_axis:!1,drag_lock_min_distance:25,prevent_default_directions:[]},triggered:!1,handler:function(t,n){if("touchstart"==t.srcEvent.type||"touchend"==t.srcEvent.type?this.preventedFirstMove=!1:this.preventedFirstMove||"touchmove"!=t.srcEvent.type||((0===n.options.prevent_default_directions.length||-1!=n.options.prevent_default_directions.indexOf(t.direction))&&t.srcEvent.preventDefault(),this.preventedFirstMove=!0),e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(n.options.drag_max_touches>0&&t.touches.length>n.options.drag_max_touches))switch(t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:if(t.distance<n.options.drag_min_distance&&e.Gestures.detection.current.name!=this.name)return;if(e.Gestures.detection.current.name!=this.name&&(e.Gestures.detection.current.name=this.name,n.options.correct_for_drag_min_distance)){var i=Math.abs(n.options.drag_min_distance/t.distance);e.Gestures.detection.current.startEvent.center.pageX+=t.deltaX*i,e.Gestures.detection.current.startEvent.center.pageY+=t.deltaY*i,t=e.Gestures.detection.extendEventData(t)}(e.Gestures.detection.current.lastEvent.drag_locked_to_axis||n.options.drag_lock_to_axis&&n.options.drag_lock_min_distance<=t.distance)&&(t.drag_locked_to_axis=!0);var o=e.Gestures.detection.current.lastEvent.direction;t.drag_locked_to_axis&&o!==t.direction&&(e.Gestures.utils.isVertical(o)?t.direction=t.deltaY<0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN:t.direction=t.deltaX<0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT),this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),n.trigger(this.name+t.direction,t),(n.options.drag_block_vertical&&e.Gestures.utils.isVertical(t.direction)||n.options.drag_block_horizontal&&!e.Gestures.utils.isVertical(t.direction))&&t.preventDefault();break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,n){if(e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(t.touches.length<2))switch(n.options.transform_always_block&&t.preventDefault(),t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:var i=Math.abs(1-t.scale),o=Math.abs(t.rotation);if(i<n.options.transform_min_scale&&o<n.options.transform_min_rotation)return;e.Gestures.detection.current.name=this.name,this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),o>n.options.transform_min_rotation&&n.trigger("rotate",t),i>n.options.transform_min_scale&&(n.trigger("pinch",t),n.trigger("pinch"+(t.scale<1?"in":"out"),t));break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Touch={name:"touch",index:-(1/0),defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,n){return n.options.prevent_mouseevents&&t.pointerType==e.Gestures.POINTER_MOUSE?void t.stopDetect():(n.options.prevent_default&&t.preventDefault(),void(t.eventType==e.Gestures.EVENT_START&&n.trigger(this.name,t)))}},e.Gestures.gestures.Release={name:"release",index:1/0,handler:function(t,n){t.eventType==e.Gestures.EVENT_END&&n.trigger(this.name,t)}}}(window.ionic),function(e,t,n){function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=new RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null===n?"":decodeURIComponent(n[1].replace(/\+/g," "))}function o(){d.isWebView()?t.addEventListener("deviceready",r,!1):r(),s&&e.removeEventListener("load",o,!1)}function r(){d.isReady=!0,d.detect();for(var e=0;e<f.length;e++)f[e]();f=[],n.trigger("platformready",{target:t}),u(function(){t.body.classList.add("platform-ready")})}var s,a="ios",l="android",c="windowsphone",u=n.requestAnimationFrame,d=n.Platform={navigator:e.navigator,isReady:!1,isFullScreen:!1,platforms:null,grade:null,ua:navigator.userAgent,ready:function(e){d.isReady?e():f.push(e)},detect:function(){d._checkPlatforms(),u(function(){for(var e=0;e<d.platforms.length;e++)t.body.classList.add("platform-"+d.platforms[e])})},setGrade:function(e){var n=d.grade;d.grade=e,u(function(){n&&t.body.classList.remove("grade-"+n),t.body.classList.add("grade-"+e)})},device:function(){return e.device||{}},_checkPlatforms:function(){d.platforms=[];var t="a";d.isWebView()?(d.platforms.push("webview"),e.cordova||e.PhoneGap||e.phonegap?d.platforms.push("cordova"):e.forge&&d.platforms.push("trigger")):d.platforms.push("browser"),d.isIPad()&&d.platforms.push("ipad");var n=d.platform();if(n){d.platforms.push(n);var i=d.version();if(i){var o=i.toString();o.indexOf(".")>0?o=o.replace(".","_"):o+="_0",d.platforms.push(n+o.split("_")[0]),d.platforms.push(n+o),d.isAndroid()&&4.4>i?t=4>i?"c":"b":d.isWindowsPhone()&&(t="b")}}d.setGrade(t)},isWebView:function(){return!!(e.cordova||e.PhoneGap||e.phonegap||e.forge)},isIPad:function(){return/iPad/i.test(d.navigator.platform)?!0:/iPad/i.test(d.ua)},isIOS:function(){return d.is(a)},isAndroid:function(){return d.is(l)},isWindowsPhone:function(){return d.is(c)},platform:function(){return null===_&&d.setPlatform(d.device().platform),_},setPlatform:function(e){_="undefined"!=typeof e&&null!==e&&e.length?e.toLowerCase():i("ionicplatform")?i("ionicplatform"):d.ua.indexOf("Android")>0?l:/iPhone|iPad|iPod/.test(d.ua)?a:d.ua.indexOf("Windows Phone")>-1?c:d.navigator.platform&&navigator.platform.toLowerCase().split(" ")[0]||""},version:function(){return null===h&&d.setVersion(d.device().version),h},setVersion:function(e){if("undefined"!=typeof e&&null!==e&&(e=e.split("."),e=parseFloat(e[0]+"."+(e.length>1?e[1]:0)),!isNaN(e)))return void(h=e);h=0;var t=d.platform(),n={android:/Android (\d+).(\d+)?/,ios:/OS (\d+)_(\d+)?/,windowsphone:/Windows Phone (\d+).(\d+)?/};n[t]&&(e=d.ua.match(n[t]),e&&e.length>2&&(h=parseFloat(e[1]+"."+e[2])))},is:function(e){if(e=e.toLowerCase(),d.platforms)for(var t=0;t<d.platforms.length;t++)if(d.platforms[t]===e)return!0;var n=d.platform();return n?n===e.toLowerCase():d.ua.toLowerCase().indexOf(e)>=0},exitApp:function(){d.ready(function(){navigator.app&&navigator.app.exitApp&&navigator.app.exitApp()})},showStatusBar:function(n){d._showStatusBar=n,d.ready(function(){u(function(){d._showStatusBar?(e.StatusBar&&e.StatusBar.show(),t.body.classList.remove("status-bar-hide")):(e.StatusBar&&e.StatusBar.hide(),t.body.classList.add("status-bar-hide"))})})},fullScreen:function(e,i){d.isFullScreen=e!==!1,n.DomUtil.ready(function(){u(function(){d.isFullScreen?t.body.classList.add("fullscreen"):t.body.classList.remove("fullscreen")}),d.showStatusBar(i===!0)})}},_=null,h=null,f=[];"complete"===t.readyState?o():(s=!0,e.addEventListener("load",o,!1))}(this,document,ionic),function(e,t){"use strict";t.CSS={},function(){var n,i=["webkitTransform","transform","-webkit-transform","webkit-transform","-moz-transform","moz-transform","MozTransform","mozTransform","msTransform"];for(n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSFORM=i[n];break}for(i=["webkitTransition","mozTransition","msTransition","transition"],n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSITION=i[n];break}var o=t.CSS.TRANSITION.indexOf("webkit")>-1;t.CSS.TRANSITION_DURATION=(o?"-webkit-":"")+"transition-duration",t.CSS.TRANSITIONEND=(o?"webkitTransitionEnd ":"")+"transitionend"}(),"classList"in e.documentElement||!Object.defineProperty||"undefined"==typeof HTMLElement||Object.defineProperty(HTMLElement.prototype,"classList",{get:function(){function e(e){return function(){var n,i=t.className.split(/\s+/);for(n=0;n<arguments.length;n++)e(i,i.indexOf(arguments[n]),arguments[n]);t.className=i.join(" ")}}var t=this;return{add:e(function(e,t,n){~t||e.push(n)}),remove:e(function(e,t){~t&&e.splice(t,1)}),toggle:e(function(e,t,n){~t?e.splice(t,1):e.push(n)}),contains:function(e){return!!~t.className.split(/\s+/).indexOf(e)},item:function(e){return t.className.split(/\s+/)[e]||null}}}})}(document,ionic);var F,Y,X,W,$,U,q,B,K="touchmove",Z=12,j=50,J={ -click:i,mousedown:o,mouseup:r,mousemove:s,touchstart:a,touchend:l,touchcancel:u,touchmove:c,pointerdown:a,pointerup:l,pointercancel:u,pointermove:c,MSPointerDown:a,MSPointerUp:l,MSPointerCancel:u,MSPointerMove:c,focusin:p,focusout:m};ionic.tap={register:function(t){return F=t,e("click",!0,!0),e("mouseup"),e("mousedown"),window.navigator.pointerEnabled?(e("pointerdown"),e("pointerup"),e("pointcancel"),K="pointermove"):window.navigator.msPointerEnabled?(e("MSPointerDown"),e("MSPointerUp"),e("MSPointerCancel"),K="MSPointerMove"):(e("touchstart"),e("touchend"),e("touchcancel")),e("focusin"),e("focusout"),function(){for(var t in J)e(t,!1);F=null,Y=null,X=!1,$=!1,U=null}},ignoreScrollStart:function(e){return e.defaultPrevented||/^(file|range)$/i.test(e.target.type)||"true"==(e.target.dataset?e.target.dataset.preventScroll:e.target.getAttribute("data-prevent-scroll"))||!!/^(object|embed)$/i.test(e.target.tagName)||ionic.tap.isElementTapDisabled(e.target)},isTextInput:function(e){return!!e&&("TEXTAREA"==e.tagName||"true"===e.contentEditable||"INPUT"==e.tagName&&!/^(radio|checkbox|range|file|submit|reset|color|image|button)$/i.test(e.type))},isDateInput:function(e){return!!e&&"INPUT"==e.tagName&&/^(date|time|datetime-local|month|week)$/i.test(e.type)},isKeyboardElement:function(e){return!ionic.Platform.isIOS()||ionic.Platform.isIPad()?ionic.tap.isTextInput(e)&&!ionic.tap.isDateInput(e):ionic.tap.isTextInput(e)||!!e&&"SELECT"==e.tagName},isLabelWithTextInput:function(e){var t=T(e,!1);return!!t&&ionic.tap.isTextInput(E(t))},containsOrIsTextInput:function(e){return ionic.tap.isTextInput(e)||ionic.tap.isLabelWithTextInput(e)},cloneFocusedInput:function(e){ionic.tap.hasCheckedClone||(ionic.tap.hasCheckedClone=!0,ionic.requestAnimationFrame(function(){var t=e.querySelector(":focus");if(ionic.tap.isTextInput(t)&&!ionic.tap.isDateInput(t)){var n=t.cloneNode(!0);n.value=t.value,n.classList.add("cloned-text-input"),n.readOnly=!0,t.isContentEditable&&(n.contentEditable=t.contentEditable,n.innerHTML=t.innerHTML),t.parentElement.insertBefore(n,t),t.classList.add("previous-input-focus"),n.scrollTop=t.scrollTop}}))},hasCheckedClone:!1,removeClonedInputs:function(e){ionic.tap.hasCheckedClone=!1,ionic.requestAnimationFrame(function(){var t,n=e.querySelectorAll(".cloned-text-input"),i=e.querySelectorAll(".previous-input-focus");for(t=0;t<n.length;t++)n[t].parentElement.removeChild(n[t]);for(t=0;t<i.length;t++)i[t].classList.remove("previous-input-focus"),i[t].style.top="",ionic.keyboard.isOpen&&!ionic.keyboard.isClosing&&i[t].focus()})},requiresNativeClick:function(e){return!e||e.disabled||/^(file|range)$/i.test(e.type)||/^(object|video)$/i.test(e.tagName)||ionic.tap.isLabelContainingFileInput(e)?!0:ionic.tap.isElementTapDisabled(e)},isLabelContainingFileInput:function(e){var t=T(e);if("LABEL"!==t.tagName)return!1;var n=t.querySelector("input[type=file]");return n&&n.disabled===!1?!0:!1},isElementTapDisabled:function(e){if(e&&1===e.nodeType)for(var t=e;t;){if("true"==(t.dataset?t.dataset.tapDisabled:t.getAttribute("data-tap-disabled")))return!0;t=t.parentElement}return!1},setTolerance:function(e,t){Z=e,j=t},cancelClick:function(){$=!0},pointerCoord:function(e){var t={x:0,y:0};if(e){var n=e.touches&&e.touches.length?e.touches:[e],i=e.changedTouches&&e.changedTouches[0]||n[0];i&&(t.x=i.clientX||i.pageX||0,t.y=i.clientY||i.pageY||0)}return t}},ionic.DomUtil.ready(function(){var e="undefined"!=typeof angular?angular:null;(!e||e&&!e.scenario)&&ionic.tap.register(document)}),function(e,t){"use strict";function n(){r={},t.requestAnimationFrame(o)}function i(){for(var e in r)r[e]&&(r[e].classList.add(l),s[e]=r[e]);r={}}function o(){if(t.transition&&t.transition.isActive)return void setTimeout(o,400);for(var e in s)s[e]&&(s[e].classList.remove(l),delete s[e])}var r={},s={},a=0,l="activated";t.activator={start:function(e){var n=t.tap.pointerCoord(e).x;n>0&&30>n||t.requestAnimationFrame(function(){if(!(t.scroll&&t.scroll.isScrolling||t.tap.requiresNativeClick(e.target))){for(var n,o=e.target,s=0;6>s&&(o&&1===o.nodeType);s++){if(n&&o.classList&&o.classList.contains("item")){n=o;break}if("A"==o.tagName||"BUTTON"==o.tagName||o.hasAttribute("ng-click")){n=o;break}if(o.classList.contains("button")){n=o;break}if("ION-CONTENT"==o.tagName||o.classList&&o.classList.contains("pane")||"BODY"==o.tagName)break;o=o.parentElement}n&&(r[a]=n,t.requestAnimationFrame(i),a=a>29?0:a+1)}})},end:function(){setTimeout(n,200)}}}(document,ionic),function(e){var t=0;e.Utils={arrayMove:function(e,t,n){if(n>=e.length)for(var i=n-e.length;i--+1;)e.push(void 0);return e.splice(n,0,e.splice(t,1)[0]),e},proxy:function(e,t){var n=Array.prototype.slice.call(arguments,2);return function(){return e.apply(t,n.concat(Array.prototype.slice.call(arguments)))}},debounce:function(e,t,n){var i,o,r,s,a;return function(){r=this,o=arguments,s=new Date;var l=function(){var c=new Date-s;t>c?i=setTimeout(l,t-c):(i=null,n||(a=e.apply(r,o)))},c=n&&!i;return i||(i=setTimeout(l,t)),c&&(a=e.apply(r,o)),a}},throttle:function(e,t,n){var i,o,r,s=null,a=0;n||(n={});var l=function(){a=n.leading===!1?0:Date.now(),s=null,r=e.apply(i,o)};return function(){var c=Date.now();a||n.leading!==!1||(a=c);var u=t-(c-a);return i=this,o=arguments,0>=u?(clearTimeout(s),s=null,a=c,r=e.apply(i,o)):s||n.trailing===!1||(s=setTimeout(l,u)),r}},inherit:function(t,n){var i,o=this;i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return o.apply(this,arguments)},e.extend(i,o,n);var r=function(){this.constructor=i};return r.prototype=o.prototype,i.prototype=new r,t&&e.extend(i.prototype,t),i.__super__=o.prototype,i},extend:function(e){for(var t=Array.prototype.slice.call(arguments,1),n=0;n<t.length;n++){var i=t[n];if(i)for(var o in i)e[o]=i[o]}return e},nextUid:function(){return"ion"+t++},disconnectScope:function(e){if(e&&e.$root!==e){var t=e.$parent;e.$$disconnected=!0,e.$broadcast("$ionic.disconnectScope",e),t.$$childHead===e&&(t.$$childHead=e.$$nextSibling),t.$$childTail===e&&(t.$$childTail=e.$$prevSibling),e.$$prevSibling&&(e.$$prevSibling.$$nextSibling=e.$$nextSibling),e.$$nextSibling&&(e.$$nextSibling.$$prevSibling=e.$$prevSibling),e.$$nextSibling=e.$$prevSibling=null}},reconnectScope:function(e){if(e&&e.$root!==e&&e.$$disconnected){var t=e.$parent;e.$$disconnected=!1,e.$broadcast("$ionic.reconnectScope",e),e.$$prevSibling=t.$$childTail,t.$$childHead?(t.$$childTail.$$nextSibling=e,t.$$childTail=e):t.$$childHead=t.$$childTail=e}},isScopeDisconnected:function(e){for(var t=e;t;){if(t.$$disconnected)return!0;t=t.$parent}return!1}},e.inherit=e.Utils.inherit,e.extend=e.Utils.extend,e.throttle=e.Utils.throttle,e.proxy=e.Utils.proxy,e.debounce=e.Utils.debounce}(window.ionic);var Q,ee,te,ne,ie=0,oe=0,re=0,se=!1,ae="keyboard-open",le="scroll-content",ce=ionic.debounce(w,200,!0),ue=ionic.debounce(b,100,!0);ionic.keyboard={isOpen:!1,isClosing:!1,isOpening:!1,height:0,isLandscape:!1,isInitialized:!1,hide:function(){V()&&cordova.plugins.Keyboard.close(),Q&&Q.blur()},show:function(){V()&&cordova.plugins.Keyboard.show()},disable:function(){V()?(window.removeEventListener("native.keyboardshow",ue),window.removeEventListener("native.keyboardhide",y)):document.body.removeEventListener("focusout",y),document.body.removeEventListener("ionic.focusin",ce),document.body.removeEventListener("focusin",ce),window.removeEventListener("orientationchange",D),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!1},enable:function(){S()}},ie=k(),ionic.Platform.ready(function(){G(),window.addEventListener("orientationchange",D),setTimeout(G,999),window.navigator.msPointerEnabled?document.addEventListener("MSPointerDown",S,!1):document.addEventListener("touchstart",S,!1)});var de,_e={};ionic.viewport={orientation:function(){return window.innerWidth>window.innerHeight?90:0}},ionic.Platform.ready(function(){R(),window.addEventListener("orientationchange",function(){setTimeout(z,1e3)},!1)}),function(e){"use strict";e.views.View=function(){this.initialize.apply(this,arguments)},e.views.View.inherit=e.inherit,e.extend(e.views.View.prototype,{initialize:function(){}})}(window.ionic);var he={effect:{}};!function(e){var t=Date.now||function(){return+new Date},n=60,i=1e3,o={},r=1;he.effect.Animate={requestAnimationFrame:function(){var t=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame,n=!!t;if(t&&!/requestAnimationFrame\(\)\s*\{\s*\[native code\]\s*\}/i.test(t.toString())&&(n=!1),n)return function(e,n){t(e,n)};var i=60,o={},r=0,s=1,a=null,l=+new Date;return function(e){var t=s++;return o[t]=e,r++,null===a&&(a=setInterval(function(){var e=+new Date,t=o;o={},r=0;for(var n in t)t.hasOwnProperty(n)&&(t[n](e),l=e);e-l>2500&&(clearInterval(a),a=null)},1e3/i)),t}}(),stop:function(e){var t=null!=o[e];return t&&(o[e]=null),t},isRunning:function(e){return null!=o[e]},start:function(e,s,a,l,c,u){var d=t(),_=d,h=0,f=0,p=r++;if(u||(u=document.body),p%20===0){var m={};for(var g in o)m[g]=!0;o=m}var v=function(r){var m=r!==!0,g=t();if(!o[p]||s&&!s(p))return o[p]=null,void(a&&a(n-f/((g-d)/i),p,!1));if(m)for(var T=Math.round((g-_)/(i/n))-1,E=0;E<Math.min(T,4);E++)v(!0),f++;l&&(h=(g-d)/l,h>1&&(h=1));var S=c?c(h):h;e(S,g,m)!==!1&&1!==h||!m?m&&(_=g,he.effect.Animate.requestAnimationFrame(v,u)):(o[p]=null,a&&a(n-f/((g-d)/i),p,1===h||null==l))};return o[p]=!0,he.effect.Animate.requestAnimationFrame(v,u),p}}}(this),function(e){var t=function(){},n=function(e){return Math.pow(e-1,3)+1},i=function(e){return(e/=.5)<1?.5*Math.pow(e,3):.5*(Math.pow(e-2,3)+2)};e.views.Scroll=e.views.View.inherit({initialize:function(n){var i=this;i.__container=n.el,i.__content=n.el.firstElementChild,setTimeout(function(){i.__container&&i.__content&&(i.__container.scrollTop=0,i.__content.scrollTop=0)}),i.options={scrollingX:!1,scrollbarX:!0,scrollingY:!0,scrollbarY:!0,startX:0,startY:0,wheelDampen:6,minScrollbarSizeX:5,minScrollbarSizeY:5,scrollbarsFade:!0,scrollbarFadeDelay:300,scrollbarResizeFadeDelay:1e3,animating:!0,animationDuration:250,decelVelocityThreshold:4,decelVelocityThresholdPaging:4,bouncing:!0,locking:!0,paging:!1,snapping:!1,zooming:!1,minZoom:.5,maxZoom:3,speedMultiplier:1,deceleration:.97,preventDefault:!1,scrollingComplete:t,penetrationDeceleration:.03,penetrationAcceleration:.08,scrollEventInterval:10,freeze:!1,getContentWidth:function(){return Math.max(i.__content.scrollWidth,i.__content.offsetWidth)},getContentHeight:function(){return Math.max(i.__content.scrollHeight,i.__content.offsetHeight+2*i.__content.offsetTop)}};for(var o in n)i.options[o]=n[o];i.hintResize=e.debounce(function(){i.resize()},1e3,!0),i.onScroll=function(){e.scroll.isScrolling?(clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)):setTimeout(i.setScrollStart,50)},i.freeze=function(e){return arguments.length&&(i.options.freeze=e),i.options.freeze},i.setScrollStart=function(){e.scroll.isScrolling=Math.abs(e.scroll.lastTop-i.__scrollTop)>1,clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)},i.setScrollStop=function(){e.scroll.isScrolling=!1,e.scroll.lastTop=i.__scrollTop},i.triggerScrollEvent=e.throttle(function(){i.onScroll(),e.trigger("scroll",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.options.scrollEventInterval),i.triggerScrollEndEvent=function(){e.trigger("scrollend",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.__scrollLeft=i.options.startX,i.__scrollTop=i.options.startY,i.__callback=i.getRenderFn(),i.__initEventHandlers(),i.__createScrollbars()},run:function(){this.resize(),this.__fadeScrollbars("out",this.options.scrollbarResizeFadeDelay)},__isSingleTouch:!1,__isTracking:!1,__didDecelerationComplete:!1,__isGesturing:!1,__isDragging:!1,__isDecelerating:!1,__isAnimating:!1,__clientLeft:0,__clientTop:0,__clientWidth:0,__clientHeight:0,__contentWidth:0,__contentHeight:0,__snapWidth:100,__snapHeight:100,__refreshHeight:null,__refreshActive:!1,__refreshActivate:null,__refreshDeactivate:null,__refreshStart:null,__zoomLevel:1,__scrollLeft:0,__scrollTop:0,__maxScrollLeft:0,__maxScrollTop:0,__scheduledLeft:0,__scheduledTop:0,__scheduledZoom:0,__lastTouchLeft:null,__lastTouchTop:null,__lastTouchMove:null,__positions:null,__minDecelerationScrollLeft:null,__minDecelerationScrollTop:null,__maxDecelerationScrollLeft:null,__maxDecelerationScrollTop:null,__decelerationVelocityX:null,__decelerationVelocityY:null,__transformProperty:null,__perspectiveProperty:null,__indicatorX:null,__indicatorY:null,__scrollbarFadeTimeout:null,__didWaitForSize:null,__sizerTimeout:null,__initEventHandlers:function(){function t(e){return e.touches&&e.touches.length?e.touches:[{pageX:e.pageX,pageY:e.pageY}]}var n,i=this,o=i.__container;if(i.scrollChildIntoView=function(t){var r=o.getBoundingClientRect().bottom;n=o.offsetHeight;var s=i.isShrunkForKeyboard,a=o.parentNode.classList.contains("modal"),l=a&&window.innerWidth>=680;if(!s){if(e.Platform.isIOS()||e.Platform.isFullScreen||l){var c=t.detail.viewportHeight-r,u=Math.max(0,t.detail.keyboardHeight-c);e.requestAnimationFrame(function(){n-=u,o.style.height=n+"px",o.style.overflow="visible",i.resize()})}i.isShrunkForKeyboard=!0}t.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){o.scrollTop=0,i.isShrunkForKeyboard&&!s&&(r=o.getBoundingClientRect().bottom);var a=.5*n,l=(t.detail.elementBottom+t.detail.elementTop)/2,c=l-r,u=c+a;u>0&&(e.Platform.isIOS()&&e.tap.cloneFocusedInput(o,i),i.scrollBy(0,u,!0),i.onScroll())}),t.stopPropagation()},i.resetScrollView=function(){i.isShrunkForKeyboard&&(i.isShrunkForKeyboard=!1,o.style.height="",o.style.overflow=""),i.resize()},o.addEventListener("scrollChildIntoView",i.scrollChildIntoView),document.addEventListener("resetScrollView",i.resetScrollView),i.touchStart=function(n){if(i.startCoordinates=e.tap.pointerCoord(n),!e.tap.ignoreScrollStart(n)){if(i.__isDown=!0,e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName)return void(i.__hasStarted=!1);i.__isSelectable=!0,i.__enableScrollY=!0,i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),n.preventDefault()}},i.touchMove=function(n){if(!(i.options.freeze||!i.__isDown||!i.__isDown&&n.defaultPrevented||"TEXTAREA"===n.target.tagName&&n.target.parentElement.querySelector(":focus"))){if(!i.__hasStarted&&(e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName))return i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),void n.preventDefault();if(i.startCoordinates){var r=e.tap.pointerCoord(n);i.__isSelectable&&e.tap.isTextInput(n.target)&&Math.abs(i.startCoordinates.x-r.x)>20&&(i.__enableScrollY=!1,i.__isSelectable=!0),i.__enableScrollY&&Math.abs(i.startCoordinates.y-r.y)>10&&(i.__isSelectable=!1,e.tap.cloneFocusedInput(o,i))}i.doTouchMove(t(n),n.timeStamp,n.scale),i.__isDown=!0}},i.touchMoveBubble=function(e){i.__isDown&&i.options.preventDefault&&e.preventDefault()},i.touchEnd=function(t){i.__isDown&&(i.doTouchEnd(t,t.timeStamp),i.__isDown=!1,i.__hasStarted=!1,i.__isSelectable=!0,i.__enableScrollY=!0,i.__isDragging||i.__isDecelerating||i.__isAnimating||e.tap.removeClonedInputs(o,i))},i.mouseWheel=e.animationFrameThrottle(function(t){var n=e.DomUtil.getParentOrSelfWithClass(t.target,"ionic-scroll");i.options.freeze||n!==i.__container||(i.hintResize(),i.scrollBy((t.wheelDeltaX||t.deltaX||0)/i.options.wheelDampen,(-t.wheelDeltaY||t.deltaY||0)/i.options.wheelDampen),i.__fadeScrollbars("in"),clearTimeout(i.__wheelHideBarTimeout),i.__wheelHideBarTimeout=setTimeout(function(){i.__fadeScrollbars("out")},100))}),"ontouchstart"in window)o.addEventListener("touchstart",i.touchStart,!1),i.options.preventDefault&&o.addEventListener("touchmove",i.touchMoveBubble,!1),document.addEventListener("touchmove",i.touchMove,!1),document.addEventListener("touchend",i.touchEnd,!1),document.addEventListener("touchcancel",i.touchEnd,!1);else if(window.navigator.pointerEnabled)o.addEventListener("pointerdown",i.touchStart,!1),i.options.preventDefault&&o.addEventListener("pointermove",i.touchMoveBubble,!1),document.addEventListener("pointermove",i.touchMove,!1),document.addEventListener("pointerup",i.touchEnd,!1),document.addEventListener("pointercancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else if(window.navigator.msPointerEnabled)o.addEventListener("MSPointerDown",i.touchStart,!1),i.options.preventDefault&&o.addEventListener("MSPointerMove",i.touchMoveBubble,!1),document.addEventListener("MSPointerMove",i.touchMove,!1),document.addEventListener("MSPointerUp",i.touchEnd,!1),document.addEventListener("MSPointerCancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else{var r=!1;i.mouseDown=function(n){e.tap.ignoreScrollStart(n)||"SELECT"===n.target.tagName||(i.doTouchStart(t(n),n.timeStamp),e.tap.isTextInput(n.target)||n.preventDefault(),r=!0)},i.mouseMove=function(e){i.options.freeze||!r||!r&&e.defaultPrevented||(i.doTouchMove(t(e),e.timeStamp),r=!0)},i.mouseMoveBubble=function(e){r&&i.options.preventDefault&&e.preventDefault()},i.mouseUp=function(e){r&&(i.doTouchEnd(e,e.timeStamp),r=!1)},o.addEventListener("mousedown",i.mouseDown,!1),i.options.preventDefault&&o.addEventListener("mousemove",i.mouseMoveBubble,!1),document.addEventListener("mousemove",i.mouseMove,!1),document.addEventListener("mouseup",i.mouseUp,!1),document.addEventListener("mousewheel",i.mouseWheel,!1),document.addEventListener("wheel",i.mouseWheel,!1)}},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("touchstart",n.touchStart),i.removeEventListener("touchmove",n.touchMoveBubble),document.removeEventListener("touchmove",n.touchMove),document.removeEventListener("touchend",n.touchEnd),document.removeEventListener("touchcancel",n.touchEnd),i.removeEventListener("pointerdown",n.touchStart),i.removeEventListener("pointermove",n.touchMoveBubble),document.removeEventListener("pointermove",n.touchMove),document.removeEventListener("pointerup",n.touchEnd),document.removeEventListener("pointercancel",n.touchEnd),i.removeEventListener("MSPointerDown",n.touchStart),i.removeEventListener("MSPointerMove",n.touchMoveBubble),document.removeEventListener("MSPointerMove",n.touchMove),document.removeEventListener("MSPointerUp",n.touchEnd),document.removeEventListener("MSPointerCancel",n.touchEnd),i.removeEventListener("mousedown",n.mouseDown),i.removeEventListener("mousemove",n.mouseMoveBubble),document.removeEventListener("mousemove",n.mouseMove),document.removeEventListener("mouseup",n.mouseUp),document.removeEventListener("mousewheel",n.mouseWheel),document.removeEventListener("wheel",n.mouseWheel),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),document.removeEventListener("resetScrollView",n.resetScrollView),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.__callback=n.scrollChildIntoView=n.resetScrollView=t,n.mouseMove=n.mouseDown=n.mouseUp=n.mouseWheel=n.touchStart=n.touchMove=n.touchEnd=n.touchCancel=t,n.resize=n.scrollTo=n.zoomTo=n.__scrollingComplete=t,i=null},__createScrollbar:function(e){var t=document.createElement("div"),n=document.createElement("div");return n.className="scroll-bar-indicator scroll-bar-fade-out","h"==e?t.className="scroll-bar scroll-bar-h":t.className="scroll-bar scroll-bar-v",t.appendChild(n),t},__createScrollbars:function(){var e,t,n=this;n.options.scrollingX&&(e={el:n.__createScrollbar("h"),sizeRatio:1},e.indicator=e.el.children[0],n.options.scrollbarX&&n.__container.appendChild(e.el),n.__indicatorX=e),n.options.scrollingY&&(t={el:n.__createScrollbar("v"),sizeRatio:1},t.indicator=t.el.children[0],n.options.scrollbarY&&n.__container.appendChild(t.el),n.__indicatorY=t)},__resizeScrollbars:function(){var t=this;if(t.__indicatorX){var n=Math.max(Math.round(t.__clientWidth*t.__clientWidth/t.__contentWidth),20);n>t.__contentWidth&&(n=0),n!==t.__indicatorX.size&&e.requestAnimationFrame(function(){t.__indicatorX.indicator.style.width=n+"px"}),t.__indicatorX.size=n,t.__indicatorX.minScale=t.options.minScrollbarSizeX/n,t.__indicatorX.maxPos=t.__clientWidth-n,t.__indicatorX.sizeRatio=t.__maxScrollLeft?t.__indicatorX.maxPos/t.__maxScrollLeft:1}if(t.__indicatorY){var i=Math.max(Math.round(t.__clientHeight*t.__clientHeight/t.__contentHeight),20);i>t.__contentHeight&&(i=0),i!==t.__indicatorY.size&&e.requestAnimationFrame(function(){t.__indicatorY&&(t.__indicatorY.indicator.style.height=i+"px")}),t.__indicatorY.size=i,t.__indicatorY.minScale=t.options.minScrollbarSizeY/i,t.__indicatorY.maxPos=t.__clientHeight-i,t.__indicatorY.sizeRatio=t.__maxScrollTop?t.__indicatorY.maxPos/t.__maxScrollTop:1}},__repositionScrollbars:function(){var e,t,n,i,o,r,s=this,a=0,l=0;if(s.__indicatorX){s.__indicatorY&&(a=10),o=Math.round(s.__indicatorX.sizeRatio*s.__scrollLeft)||0,n=s.__scrollLeft-(s.__maxScrollLeft-a),s.__scrollLeft<0?(t=Math.max(s.__indicatorX.minScale,(s.__indicatorX.size-Math.abs(s.__scrollLeft))/s.__indicatorX.size),o=0,s.__indicatorX.indicator.style[s.__transformOriginProperty]="left center"):n>0?(t=Math.max(s.__indicatorX.minScale,(s.__indicatorX.size-n)/s.__indicatorX.size),o=s.__indicatorX.maxPos-a,s.__indicatorX.indicator.style[s.__transformOriginProperty]="right center"):(o=Math.min(s.__maxScrollLeft,Math.max(0,o)),t=1);var c="translate3d("+o+"px, 0, 0) scaleX("+t+")";s.__indicatorX.transformProp!==c&&(s.__indicatorX.indicator.style[s.__transformProperty]=c,s.__indicatorX.transformProp=c)}if(s.__indicatorY){r=Math.round(s.__indicatorY.sizeRatio*s.__scrollTop)||0,s.__indicatorX&&(l=10),i=s.__scrollTop-(s.__maxScrollTop-l),s.__scrollTop<0?(e=Math.max(s.__indicatorY.minScale,(s.__indicatorY.size-Math.abs(s.__scrollTop))/s.__indicatorY.size),r=0,"center top"!==s.__indicatorY.originProp&&(s.__indicatorY.indicator.style[s.__transformOriginProperty]="center top",s.__indicatorY.originProp="center top")):i>0?(e=Math.max(s.__indicatorY.minScale,(s.__indicatorY.size-i)/s.__indicatorY.size),r=s.__indicatorY.maxPos-l,"center bottom"!==s.__indicatorY.originProp&&(s.__indicatorY.indicator.style[s.__transformOriginProperty]="center bottom",s.__indicatorY.originProp="center bottom")):(r=Math.min(s.__maxScrollTop,Math.max(0,r)),e=1);var u="translate3d(0,"+r+"px, 0) scaleY("+e+")";s.__indicatorY.transformProp!==u&&(s.__indicatorY.indicator.style[s.__transformProperty]=u,s.__indicatorY.transformProp=u)}},__fadeScrollbars:function(e,t){var n=this;if(n.options.scrollbarsFade){var i="scroll-bar-fade-out";n.options.scrollbarsFade===!0&&(clearTimeout(n.__scrollbarFadeTimeout),"in"==e?(n.__indicatorX&&n.__indicatorX.indicator.classList.remove(i),n.__indicatorY&&n.__indicatorY.indicator.classList.remove(i)):n.__scrollbarFadeTimeout=setTimeout(function(){n.__indicatorX&&n.__indicatorX.indicator.classList.add(i),n.__indicatorY&&n.__indicatorY.indicator.classList.add(i)},t||n.options.scrollbarFadeDelay))}},__scrollingComplete:function(){this.options.scrollingComplete(),e.tap.removeClonedInputs(this.__container,this),this.__fadeScrollbars("out")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},getRenderFn:function(){var e,t=this,n=t.__content,i=document.documentElement.style;"MozAppearance"in i?e="gecko":"WebkitAppearance"in i?e="webkit":"string"==typeof navigator.cpuClass&&(e="trident");var o,r={trident:"ms",gecko:"Moz",webkit:"Webkit",presto:"O"}[e],s=document.createElement("div"),a=r+"Perspective",l=r+"Transform",c=r+"TransformOrigin";return t.__perspectiveProperty=l,t.__transformProperty=l,t.__transformOriginProperty=c,s.style[a]!==o?function(e,i,o,r){var s="translate3d("+-e+"px,"+-i+"px,0) scale("+o+")";s!==t.contentTransform&&(n.style[l]=s,t.contentTransform=s),t.__repositionScrollbars(),r||t.triggerScrollEvent()}:s.style[l]!==o?function(e,i,o,r){n.style[l]="translate("+-e+"px,"+-i+"px) scale("+o+")",t.__repositionScrollbars(),r||t.triggerScrollEvent()}:function(e,i,o,r){n.style.marginLeft=e?-e/o+"px":"",n.style.marginTop=i?-i/o+"px":"",n.style.zoom=o||"",t.__repositionScrollbars(),r||t.triggerScrollEvent()}},setDimensions:function(e,t,n,i,o){var r=this;(e||t||n||i)&&(e===+e&&(r.__clientWidth=e),t===+t&&(r.__clientHeight=t),n===+n&&(r.__contentWidth=n),i===+i&&(r.__contentHeight=i),r.__computeScrollMax(),r.__resizeScrollbars(),o||r.scrollTo(r.__scrollLeft,r.__scrollTop,!0,null,!0))},setPosition:function(e,t){this.__clientLeft=e||0,this.__clientTop=t||0},setSnapSize:function(e,t){this.__snapWidth=e,this.__snapHeight=t},activatePullToRefresh:function(t,n){var i=this;i.__refreshHeight=t,i.__refreshActivate=function(){e.requestAnimationFrame(n.activate)},i.__refreshDeactivate=function(){e.requestAnimationFrame(n.deactivate)},i.__refreshStart=function(){e.requestAnimationFrame(n.start)},i.__refreshShow=function(){e.requestAnimationFrame(n.show)},i.__refreshHide=function(){e.requestAnimationFrame(n.hide)},i.__refreshTail=function(){e.requestAnimationFrame(n.tail)},i.__refreshTailTime=100,i.__minSpinTime=600},triggerPullToRefresh:function(){this.__publish(this.__scrollLeft,-this.__refreshHeight,this.__zoomLevel,!0);var e=new Date;this.refreshStartTime=e.getTime(),this.__refreshStart&&this.__refreshStart()},finishPullToRefresh:function(){var e=this,t=new Date,n=0;e.refreshStartTime+e.__minSpinTime>t.getTime()&&(n=e.refreshStartTime+e.__minSpinTime-t.getTime()),setTimeout(function(){e.__refreshTail&&e.__refreshTail(),setTimeout(function(){e.__refreshActive=!1,e.__refreshDeactivate&&e.__refreshDeactivate(),e.__refreshHide&&e.__refreshHide(),e.scrollTo(e.__scrollLeft,e.__scrollTop,!0)},e.__refreshTailTime)},n)},getValues:function(){return{left:this.__scrollLeft,top:this.__scrollTop,zoom:this.__zoomLevel}},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},zoomTo:function(e,t,n,i){var o=this;if(!o.options.zooming)throw new Error("Zooming is not enabled!");o.__isDecelerating&&(he.effect.Animate.stop(o.__isDecelerating),o.__isDecelerating=!1);var r=o.__zoomLevel;null==n&&(n=o.__clientWidth/2),null==i&&(i=o.__clientHeight/2),e=Math.max(Math.min(e,o.options.maxZoom),o.options.minZoom),o.__computeScrollMax(e);var s=(n+o.__scrollLeft)*e/r-n,a=(i+o.__scrollTop)*e/r-i;s>o.__maxScrollLeft?s=o.__maxScrollLeft:0>s&&(s=0),a>o.__maxScrollTop?a=o.__maxScrollTop:0>a&&(a=0),o.__publish(s,a,e,t)},zoomBy:function(e,t,n,i){this.zoomTo(this.__zoomLevel*e,t,n,i)},scrollTo:function(e,t,n,i,o){var r=this;if(r.__isDecelerating&&(he.effect.Animate.stop(r.__isDecelerating),r.__isDecelerating=!1),null!=i&&i!==r.__zoomLevel){if(!r.options.zooming)throw new Error("Zooming is not enabled!");e*=i,t*=i,r.__computeScrollMax(i)}else i=r.__zoomLevel;r.options.scrollingX?r.options.paging?e=Math.round(e/r.__clientWidth)*r.__clientWidth:r.options.snapping&&(e=Math.round(e/r.__snapWidth)*r.__snapWidth):e=r.__scrollLeft,r.options.scrollingY?r.options.paging?t=Math.round(t/r.__clientHeight)*r.__clientHeight:r.options.snapping&&(t=Math.round(t/r.__snapHeight)*r.__snapHeight):t=r.__scrollTop,e=Math.max(Math.min(r.__maxScrollLeft,e),0),t=Math.max(Math.min(r.__maxScrollTop,t),0),e===r.__scrollLeft&&t===r.__scrollTop&&(n=!1),r.__publish(e,t,i,n,o)},scrollBy:function(e,t,n){var i=this,o=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,r=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(o+(e||0),r+(t||0),n)},doMouseZoom:function(e,t,n,i){var o=e>0?.97:1.03;return this.zoomTo(this.__zoomLevel*o,!1,n-this.__clientLeft,i-this.__clientTop)},doTouchStart:function(e,t){var n=this;n.__decStopped=!(!n.__isDecelerating&&!n.__isAnimating),n.hintResize(),t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now()),n.__interruptedAnimation=!0,n.__isDecelerating&&(he.effect.Animate.stop(n.__isDecelerating),n.__isDecelerating=!1,n.__interruptedAnimation=!0),n.__isAnimating&&(he.effect.Animate.stop(n.__isAnimating),n.__isAnimating=!1,n.__interruptedAnimation=!0);var i,o,r=1===e.length;r?(i=e[0].pageX,o=e[0].pageY):(i=Math.abs(e[0].pageX+e[1].pageX)/2,o=Math.abs(e[0].pageY+e[1].pageY)/2),n.__initialTouchLeft=i,n.__initialTouchTop=o,n.__initialTouches=e,n.__zoomLevelStart=n.__zoomLevel,n.__lastTouchLeft=i,n.__lastTouchTop=o,n.__lastTouchMove=t,n.__lastScale=1,n.__enableScrollX=!r&&n.options.scrollingX,n.__enableScrollY=!r&&n.options.scrollingY,n.__isTracking=!0,n.__didDecelerationComplete=!1,n.__isDragging=!r,n.__isSingleTouch=r,n.__positions=[]},doTouchMove:function(e,t,n){t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now());var i=this;if(i.__isTracking){var o,r;2===e.length?(o=Math.abs(e[0].pageX+e[1].pageX)/2,r=Math.abs(e[0].pageY+e[1].pageY)/2,!n&&i.options.zooming&&(n=i.__getScale(i.__initialTouches,e))):(o=e[0].pageX,r=e[0].pageY);var s=i.__positions;if(i.__isDragging){i.__decStopped=!1;var a=o-i.__lastTouchLeft,l=r-i.__lastTouchTop,c=i.__scrollLeft,u=i.__scrollTop,d=i.__zoomLevel;if(null!=n&&i.options.zooming){var _=d;if(d=d/i.__lastScale*n,d=Math.max(Math.min(d,i.options.maxZoom),i.options.minZoom),_!==d){var h=o-i.__clientLeft,f=r-i.__clientTop;c=(h+c)*d/_-h,u=(f+u)*d/_-f,i.__computeScrollMax(d)}}if(i.__enableScrollX){c-=a*i.options.speedMultiplier;var p=i.__maxScrollLeft;(c>p||0>c)&&(i.options.bouncing?c+=a/2*i.options.speedMultiplier:c=c>p?p:0)}if(i.__enableScrollY){u-=l*i.options.speedMultiplier;var m=i.__maxScrollTop;u>m||0>u?i.options.bouncing||i.__refreshHeight&&0>u?(u+=l/2*i.options.speedMultiplier,i.__enableScrollX||null==i.__refreshHeight||(0>u?(i.__refreshHidden=!1,i.__refreshShow()):(i.__refreshHide(),i.__refreshHidden=!0),!i.__refreshActive&&u<=-i.__refreshHeight?(i.__refreshActive=!0,i.__refreshActivate&&i.__refreshActivate()):i.__refreshActive&&u>-i.__refreshHeight&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate()))):u=u>m?m:0:i.__refreshHeight&&!i.__refreshHidden&&(i.__refreshHide(),i.__refreshHidden=!0)}s.length>60&&s.splice(0,30),s.push(c,u,t),i.__publish(c,u,d)}else{var g=i.options.locking?3:0,v=5,T=Math.abs(o-i.__initialTouchLeft),E=Math.abs(r-i.__initialTouchTop);i.__enableScrollX=i.options.scrollingX&&T>=g,i.__enableScrollY=i.options.scrollingY&&E>=g,s.push(i.__scrollLeft,i.__scrollTop,t),i.__isDragging=(i.__enableScrollX||i.__enableScrollY)&&(T>=v||E>=v),i.__isDragging&&(i.__interruptedAnimation=!1,i.__fadeScrollbars("in"))}i.__lastTouchLeft=o,i.__lastTouchTop=r,i.__lastTouchMove=t,i.__lastScale=n}},doTouchEnd:function(t,n){n instanceof Date&&(n=n.valueOf()),"number"!=typeof n&&(n=Date.now());var i=this;if(i.__isTracking){if(i.__isTracking=!1,i.__isDragging)if(i.__isDragging=!1,i.__isSingleTouch&&i.options.animating&&n-i.__lastTouchMove<=100){for(var o=i.__positions,r=o.length-1,s=r,a=r;a>0&&o[a]>i.__lastTouchMove-100;a-=3)s=a;if(s!==r){var l=o[r]-o[s],c=i.__scrollLeft-o[s-2],u=i.__scrollTop-o[s-1];i.__decelerationVelocityX=c/l*(1e3/60),i.__decelerationVelocityY=u/l*(1e3/60);var d=i.options.paging||i.options.snapping?i.options.decelVelocityThresholdPaging:i.options.decelVelocityThreshold;(Math.abs(i.__decelerationVelocityX)>d||Math.abs(i.__decelerationVelocityY)>d)&&(i.__refreshActive||i.__startDeceleration(n))}else i.__scrollingComplete()}else n-i.__lastTouchMove>100&&i.__scrollingComplete();else i.__decStopped&&(t.isTapHandled=!0,i.__decStopped=!1);if(!i.__isDecelerating)if(i.__refreshActive&&i.__refreshStart){i.__publish(i.__scrollLeft,-i.__refreshHeight,i.__zoomLevel,!0);var _=new Date;i.refreshStartTime=_.getTime(),i.__refreshStart&&i.__refreshStart(),e.Platform.isAndroid()||i.__startDeceleration()}else(i.__interruptedAnimation||i.__isDragging)&&i.__scrollingComplete(),i.scrollTo(i.__scrollLeft,i.__scrollTop,!0,i.__zoomLevel),i.__refreshActive&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate());i.__positions.length=0}},__publish:function(e,t,o,r,s){var a=this,l=a.__isAnimating;if(l&&(he.effect.Animate.stop(l),a.__isAnimating=!1),r&&a.options.animating){a.__scheduledLeft=e,a.__scheduledTop=t, -a.__scheduledZoom=o;var c=a.__scrollLeft,u=a.__scrollTop,d=a.__zoomLevel,_=e-c,h=t-u,f=o-d,p=function(e,t,n){n&&(a.__scrollLeft=c+_*e,a.__scrollTop=u+h*e,a.__zoomLevel=d+f*e,a.__callback&&a.__callback(a.__scrollLeft,a.__scrollTop,a.__zoomLevel,s))},m=function(e){return a.__isAnimating===e},g=function(e,t,n){t===a.__isAnimating&&(a.__isAnimating=!1),(a.__didDecelerationComplete||n)&&a.__scrollingComplete(),a.options.zooming&&a.__computeScrollMax()};a.__isAnimating=he.effect.Animate.start(p,m,g,a.options.animationDuration,l?n:i)}else a.__scheduledLeft=a.__scrollLeft=e,a.__scheduledTop=a.__scrollTop=t,a.__scheduledZoom=a.__zoomLevel=o,a.__callback&&a.__callback(e,t,o,s),a.options.zooming&&a.__computeScrollMax()},__computeScrollMax:function(e){var t=this;null==e&&(e=t.__zoomLevel),t.__maxScrollLeft=Math.max(t.__contentWidth*e-t.__clientWidth,0),t.__maxScrollTop=Math.max(t.__contentHeight*e-t.__clientHeight,0),t.__didWaitForSize||t.__maxScrollLeft||t.__maxScrollTop||(t.__didWaitForSize=!0,t.__waitForSize())},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__startDeceleration:function(){var e=this;if(e.options.paging){var t=Math.max(Math.min(e.__scrollLeft,e.__maxScrollLeft),0),n=Math.max(Math.min(e.__scrollTop,e.__maxScrollTop),0),i=e.__clientWidth,o=e.__clientHeight;e.__minDecelerationScrollLeft=Math.floor(t/i)*i,e.__minDecelerationScrollTop=Math.floor(n/o)*o,e.__maxDecelerationScrollLeft=Math.ceil(t/i)*i,e.__maxDecelerationScrollTop=Math.ceil(n/o)*o}else e.__minDecelerationScrollLeft=0,e.__minDecelerationScrollTop=0,e.__maxDecelerationScrollLeft=e.__maxScrollLeft,e.__maxDecelerationScrollTop=e.__maxScrollTop,e.__refreshActive&&(e.__minDecelerationScrollTop=-1*e.__refreshHeight);var r=function(t,n,i){e.__stepThroughDeceleration(i)};e.__minVelocityToKeepDecelerating=e.options.snapping?4:.1;var s=function(){var t=Math.abs(e.__decelerationVelocityX)>=e.__minVelocityToKeepDecelerating||Math.abs(e.__decelerationVelocityY)>=e.__minVelocityToKeepDecelerating;return t||(e.__didDecelerationComplete=!0,e.options.bouncing&&!e.__refreshActive&&e.scrollTo(Math.min(Math.max(e.__scrollLeft,0),e.__maxScrollLeft),Math.min(Math.max(e.__scrollTop,0),e.__maxScrollTop),e.__refreshActive)),t},a=function(){e.__isDecelerating=!1,e.__didDecelerationComplete&&e.__scrollingComplete(),e.options.paging&&e.scrollTo(e.__scrollLeft,e.__scrollTop,e.options.snapping)};e.__isDecelerating=he.effect.Animate.start(r,s,a)},__stepThroughDeceleration:function(e){var t=this,n=t.__scrollLeft+t.__decelerationVelocityX,i=t.__scrollTop+t.__decelerationVelocityY;if(!t.options.bouncing){var o=Math.max(Math.min(t.__maxDecelerationScrollLeft,n),t.__minDecelerationScrollLeft);o!==n&&(n=o,t.__decelerationVelocityX=0);var r=Math.max(Math.min(t.__maxDecelerationScrollTop,i),t.__minDecelerationScrollTop);r!==i&&(i=r,t.__decelerationVelocityY=0)}if(e?t.__publish(n,i,t.__zoomLevel):(t.__scrollLeft=n,t.__scrollTop=i),!t.options.paging){var s=t.options.deceleration;t.__decelerationVelocityX*=s,t.__decelerationVelocityY*=s}if(t.options.bouncing){var a=0,l=0,c=t.options.penetrationDeceleration,u=t.options.penetrationAcceleration;if(n<t.__minDecelerationScrollLeft?a=t.__minDecelerationScrollLeft-n:n>t.__maxDecelerationScrollLeft&&(a=t.__maxDecelerationScrollLeft-n),i<t.__minDecelerationScrollTop?l=t.__minDecelerationScrollTop-i:i>t.__maxDecelerationScrollTop&&(l=t.__maxDecelerationScrollTop-i),0!==a){var d=a*t.__decelerationVelocityX<=t.__minDecelerationScrollLeft;d&&(t.__decelerationVelocityX+=a*c);var _=Math.abs(t.__decelerationVelocityX)<=t.__minVelocityToKeepDecelerating;(!d||_)&&(t.__decelerationVelocityX=a*u)}if(0!==l){var h=l*t.__decelerationVelocityY<=t.__minDecelerationScrollTop;h&&(t.__decelerationVelocityY+=l*c);var f=Math.abs(t.__decelerationVelocityY)<=t.__minVelocityToKeepDecelerating;(!h||f)&&(t.__decelerationVelocityY=l*u)}}},__getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},__getScale:function(e,t){return e.length>=2&&t.length>=2?this.__getDistance(t[0],t[1])/this.__getDistance(e[0],e[1]):1}}),e.scroll={isScrolling:!1,lastTop:0}}(ionic),function(e){var t=function(){},n=function(e){};e.views.ScrollNative=e.views.View.inherit({initialize:function(n){var i=this;i.__container=i.el=n.el,i.__content=n.el.firstElementChild,i.isNative=!0,i.__scrollTop=i.el.scrollTop,i.__scrollLeft=i.el.scrollLeft,i.__clientHeight=i.__content.clientHeight,i.__clientWidth=i.__content.clientWidth,i.__maxScrollTop=Math.max(i.__contentHeight-i.__clientHeight,0),i.__maxScrollLeft=Math.max(i.__contentWidth-i.__clientWidth,0),i.options={freeze:!1,getContentWidth:function(){return Math.max(i.__content.scrollWidth,i.__content.offsetWidth)},getContentHeight:function(){return Math.max(i.__content.scrollHeight,i.__content.offsetHeight+2*i.__content.offsetTop)}};for(var o in n)i.options[o]=n[o];i.onScroll=function(){e.scroll.isScrolling||(e.scroll.isScrolling=!0),clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(function(){e.scroll.isScrolling=!1},80)},i.freeze=t,i.__initEventHandlers()},__callback:function(){n("__callback")},zoomTo:function(){n("zoomTo")},zoomBy:function(){n("zoomBy")},activatePullToRefresh:function(){n("activatePullToRefresh")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},run:function(){this.resize()},getValues:function(){var e=this;return e.update(),{left:e.__scrollLeft,top:e.__scrollTop,zoom:1}},update:function(){var e=this;e.__scrollLeft=e.el.scrollLeft,e.__scrollTop=e.el.scrollTop},setDimensions:function(e,t,n,i){var o=this;(e||t||n||i)&&(e===+e&&(o.__clientWidth=e),t===+t&&(o.__clientHeight=t),n===+n&&(o.__contentWidth=n),i===+i&&(o.__contentHeight=i),o.__computeScrollMax())},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},scrollBy:function(e,t,n){var i=this;i.update();var o=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,r=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(o+(e||0),r+(t||0),n)},scrollTo:function(t,n,i){function o(t,n){function i(e){return--e*e*e+1}function o(){var u=Date.now(),d=Math.min(1,(u-s)/a),_=i(d);l!=t&&(r.el.scrollTop=parseInt(_*(t-l)+l,10)),c!=n&&(r.el.scrollLeft=parseInt(_*(n-c)+c,10)),1>d?e.requestAnimationFrame(o):(e.tap.removeClonedInputs(r.__container,r),r.resize())}var s=Date.now(),a=250,l=r.el.scrollTop,c=r.el.scrollLeft;return l===t&&c===n?void r.resize():void e.requestAnimationFrame(o)}var r=this;return i?void o(n,t):(r.el.scrollTop=n,r.el.scrollLeft=t,void r.resize())},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__computeScrollMax:function(){var e=this;e.__maxScrollLeft=Math.max(e.__contentWidth-e.__clientWidth,0),e.__maxScrollTop=Math.max(e.__contentHeight-e.__clientHeight,0),e.__didWaitForSize||e.__maxScrollLeft||e.__maxScrollTop||(e.__didWaitForSize=!0,e.__waitForSize())},__initEventHandlers:function(){var t,n=this,i=n.__container;n.scrollChildIntoView=function(o){var r=i.getBoundingClientRect().bottom;t=i.offsetHeight;var s=n.isShrunkForKeyboard,a=i.parentNode.classList.contains("modal"),l=a&&window.innerWidth>=680;if(!s){if(e.Platform.isIOS()||e.Platform.isFullScreen||l){var c=o.detail.viewportHeight-r,u=Math.max(0,o.detail.keyboardHeight-c);e.requestAnimationFrame(function(){t-=u,i.style.height=t+"px",n.resize()})}n.isShrunkForKeyboard=!0}o.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){n.isShrunkForKeyboard&&!s&&(r=i.getBoundingClientRect().bottom);var a=.5*t,l=(o.detail.elementBottom+o.detail.elementTop)/2,c=l-r,u=c+a;u>0&&(e.Platform.isIOS()?setTimeout(function(){e.tap.cloneFocusedInput(i,n),n.scrollBy(0,u,!0),n.onScroll()},32):(n.scrollBy(0,u,!0),n.onScroll()))}),o.stopPropagation()},n.resetScrollView=function(){n.isShrunkForKeyboard&&(n.isShrunkForKeyboard=!1,i.style.height=""),n.resize()},i.addEventListener("scroll",n.onScroll),i.addEventListener("scrollChildIntoView",n.scrollChildIntoView),document.addEventListener("resetScrollView",n.resetScrollView)},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("resetScrollView",n.resetScrollView),i.removeEventListener("scroll",n.onScroll),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),i.removeEventListener("resetScrollView",n.resetScrollView),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.resize=n.scrollTo=n.onScroll=n.resetScrollView=t,n.scrollChildIntoView=t,i=null}})}(ionic),function(e){"use strict";var t="item",n="item-content",i="item-sliding",o="item-options",r="item-placeholder",s="item-reordering",a="item-reorder",l=function(){};l.prototype={start:function(){},drag:function(){},end:function(){},isSameItem:function(){return!1}};var c=function(e){this.dragThresholdX=e.dragThresholdX||10,this.el=e.el,this.item=e.item,this.canSwipe=e.canSwipe};c.prototype=new l,c.prototype.start=function(r){var s,a,l,c;this.canSwipe()&&(s=r.target.classList.contains(n)?r.target:r.target.classList.contains(t)?r.target.querySelector("."+n):e.DomUtil.getParentWithClass(r.target,n),s&&(s.classList.remove(i),l=parseFloat(s.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])||0,a=s.parentNode.querySelector("."+o),a&&(a.classList.remove("invisible"),c=a.offsetWidth,this._currentDrag={buttons:a,buttonsWidth:c,content:s,startOffsetX:l})))},c.prototype.isSameItem=function(e){return e._lastDrag&&this._currentDrag?this._currentDrag.content==e._lastDrag.content:!1},c.prototype.clean=function(t){function n(){i.buttons&&i.buttons.classList.add("invisible")}var i=this._lastDrag;i&&i.content&&(i.content.style[e.CSS.TRANSITION]="",i.content.style[e.CSS.TRANSFORM]="",t?(i.content.style[e.CSS.TRANSITION]="none",n(),e.requestAnimationFrame(function(){i.content.style[e.CSS.TRANSITION]=""})):e.requestAnimationFrame(function(){setTimeout(n,250)}))},c.prototype.drag=e.animationFrameThrottle(function(t){var n;if(this._currentDrag&&(!this._isDragging&&(Math.abs(t.gesture.deltaX)>this.dragThresholdX||Math.abs(this._currentDrag.startOffsetX)>0)&&(this._isDragging=!0),this._isDragging)){n=this._currentDrag.buttonsWidth;var i=Math.min(0,this._currentDrag.startOffsetX+t.gesture.deltaX);-n>i&&(i=Math.min(-n,-n+.4*(t.gesture.deltaX+n))),this._currentDrag.content.$$ionicOptionsOpen=0!==i,this._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+i+"px, 0, 0)",this._currentDrag.content.style[e.CSS.TRANSITION]="none"}}),c.prototype.end=function(t,n){var i=this;if(!i._currentDrag)return void(n&&n());var o=-i._currentDrag.buttonsWidth;t.gesture.deltaX>-(i._currentDrag.buttonsWidth/2)&&("left"==t.gesture.direction&&Math.abs(t.gesture.velocityX)<.3?o=0:"right"==t.gesture.direction&&(o=0)),e.requestAnimationFrame(function(){if(0===o){i._currentDrag.content.style[e.CSS.TRANSFORM]="";var t=i._currentDrag.buttons;setTimeout(function(){t&&t.classList.add("invisible")},250)}else i._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+o+"px,0,0)";i._currentDrag.content.style[e.CSS.TRANSITION]="",i._lastDrag||(i._lastDrag={}),e.extend(i._lastDrag,i._currentDrag),i._currentDrag&&(i._currentDrag.buttons=null,i._currentDrag.content=null),i._currentDrag=null,n&&n()})};var u=function(e){var t=this;if(t.dragThresholdY=e.dragThresholdY||0,t.onReorder=e.onReorder,t.listEl=e.listEl,t.el=t.item=e.el,t.scrollEl=e.scrollEl,t.scrollView=e.scrollView,t.listElTrueTop=0,t.listEl.offsetParent){var n=t.listEl;do t.listElTrueTop+=n.offsetTop,n=n.offsetParent;while(n)}};u.prototype=new l,u.prototype._moveElement=function(t){var n=t.gesture.center.pageY+this.scrollView.getValues().top-this._currentDrag.elementHeight/2-this.listElTrueTop;this.el.style[e.CSS.TRANSFORM]="translate3d(0, "+n+"px, 0)"},u.prototype.deregister=function(){this.listEl=this.el=this.scrollEl=this.scrollView=null},u.prototype.start=function(t){var n=e.DomUtil.getChildIndex(this.el,this.el.nodeName.toLowerCase()),i=this.el.scrollHeight,o=this.el.cloneNode(!0);o.classList.add(r),this.el.parentNode.insertBefore(o,this.el),this.el.classList.add(s),this._currentDrag={elementHeight:i,startIndex:n,placeholder:o,scrollHeight:scroll,list:o.parentNode},this._moveElement(t)},u.prototype.drag=e.animationFrameThrottle(function(t){var n=this;if(this._currentDrag){var i=0,o=t.gesture.center.pageY,r=this.listElTrueTop;if(this.scrollView){var s=this.scrollView.__container;i=this.scrollView.getValues().top;var a=s.offsetTop,l=a-o+this._currentDrag.elementHeight/2,c=o+this._currentDrag.elementHeight/2-a-s.offsetHeight;t.gesture.deltaY<0&&l>0&&i>0&&(this.scrollView.scrollBy(null,-l),e.requestAnimationFrame(function(){n.drag(t)})),t.gesture.deltaY>0&&c>0&&i<this.scrollView.getScrollMax().top&&(this.scrollView.scrollBy(null,c),e.requestAnimationFrame(function(){n.drag(t)}))}!this._isDragging&&Math.abs(t.gesture.deltaY)>this.dragThresholdY&&(this._isDragging=!0),this._isDragging&&(this._moveElement(t),this._currentDrag.currentY=i+o-r)}}),u.prototype._getReorderIndex=function(){for(var e,t=this,n=Array.prototype.slice.call(t._currentDrag.placeholder.parentNode.children).filter(function(e){return e.nodeName===t.el.nodeName&&e!==t.el}),i=t._currentDrag.currentY,o=0,r=n.length;r>o;o++)if(e=n[o],o===r-1){if(i>e.offsetTop)return o}else if(0===o){if(i<e.offsetTop+e.offsetHeight)return o}else if(i>e.offsetTop-e.offsetHeight/2&&i<e.offsetTop+e.offsetHeight)return o;return t._currentDrag.startIndex},u.prototype.end=function(t,n){if(!this._currentDrag)return void(n&&n());var i=this._currentDrag.placeholder,o=this._getReorderIndex();this.el.classList.remove(s),this.el.style[e.CSS.TRANSFORM]="",i.parentNode.insertBefore(this.el,i),i.parentNode.removeChild(i),this.onReorder&&this.onReorder(this.el,this._currentDrag.startIndex,o),this._currentDrag={placeholder:null,content:null},this._currentDrag=null,n&&n()},e.views.ListView=e.views.View.inherit({initialize:function(t){var n=this;t=e.extend({onReorder:function(){},virtualRemoveThreshold:-200,virtualAddThreshold:200,canSwipe:function(){return!0}},t),e.extend(n,t),!n.itemHeight&&n.listEl&&(n.itemHeight=n.listEl.children[0]&&parseInt(n.listEl.children[0].style.height,10)),n.onRefresh=t.onRefresh||function(){},n.onRefreshOpening=t.onRefreshOpening||function(){},n.onRefreshHolding=t.onRefreshHolding||function(){};var i={};e.DomUtil.getParentOrSelfWithClass(n.el,"overflow-scroll")&&(i.prevent_default_directions=["left","right"]),window.ionic.onGesture("release",function(e){n._handleEndDrag(e)},n.el,i),window.ionic.onGesture("drag",function(e){n._handleDrag(e)},n.el,i),n._initDrag()},deregister:function(){this.el=this.listEl=this.scrollEl=this.scrollView=null,this.isScrollFreeze&&self.scrollView.freeze(!1)},stopRefreshing:function(){var e=this.el.querySelector(".list-refresher");e.style.height="0"},didScroll:function(e){var t=this;if(t.isVirtual){var n=t.itemHeight,i=e.target.scrollHeight,o=t.el.parentNode.offsetHeight,r=Math.max(0,e.scrollTop+t.virtualRemoveThreshold),s=Math.min(i,Math.abs(e.scrollTop)+o+t.virtualAddThreshold),a=parseInt(Math.abs(r/n),10),l=parseInt(Math.abs(s/n),10);t._virtualItemsToRemove=Array.prototype.slice.call(t.listEl.children,0,a),t.renderViewport&&t.renderViewport(r,s,a,l)}},didStopScrolling:function(){if(this.isVirtual)for(var e=0;e<this._virtualItemsToRemove.length;e++)this.didHideItem&&this.didHideItem(e)},clearDragEffects:function(e){this._lastDragOp&&(this._lastDragOp.clean&&this._lastDragOp.clean(e),this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=null)},_initDrag:function(){this._lastDragOp&&this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=this._dragOp,this._dragOp=null},_getItem:function(e){for(;e;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},_startDrag:function(t){var n=this;n._isDragging=!1;var i,o=n._lastDragOp;n._didDragUpOrDown&&o instanceof c&&o.clean&&o.clean(),!e.DomUtil.getParentOrSelfWithClass(t.target,a)||"up"!=t.gesture.direction&&"down"!=t.gesture.direction?!n._didDragUpOrDown&&("left"==t.gesture.direction||"right"==t.gesture.direction)&&Math.abs(t.gesture.deltaX)>5&&(i=n._getItem(t.target),i&&i.querySelector(".item-options")&&(n._dragOp=new c({el:n.el,item:i,canSwipe:n.canSwipe}),n._dragOp.start(t),t.preventDefault(),n.isScrollFreeze=n.scrollView.freeze(!0))):(i=n._getItem(t.target),i&&(n._dragOp=new u({listEl:n.el,el:i,scrollEl:n.scrollEl,scrollView:n.scrollView,onReorder:function(e,t,i){n.onReorder&&n.onReorder(e,t,i)}}),n._dragOp.start(t),t.preventDefault())),o&&n._dragOp&&!n._dragOp.isSameItem(o)&&t.defaultPrevented&&o.clean&&o.clean()},_handleEndDrag:function(e){var t=this;t.scrollView&&(t.isScrollFreeze=t.scrollView.freeze(!1)),t._didDragUpOrDown=!1,t._dragOp&&t._dragOp.end(e,function(){t._initDrag()})},_handleDrag:function(e){var t=this;Math.abs(e.gesture.deltaY)>5&&(t._didDragUpOrDown=!0),t.isDragging||t._dragOp||t._startDrag(e),t._dragOp&&(e.gesture.srcEvent.preventDefault(),t._dragOp.drag(e))}})}(ionic),function(e){"use strict";e.views.Modal=e.views.View.inherit({initialize:function(t){t=e.extend({focusFirstInput:!1,unfocusOnHide:!0,focusFirstDelay:600,backdropClickToClose:!0,hardwareBackButtonClose:!0},t),e.extend(this,t),this.el=t.el},show:function(){var e=this;e.focusFirstInput&&window.setTimeout(function(){var t=e.el.querySelector("input, textarea");t&&t.focus&&t.focus()},e.focusFirstDelay)},hide:function(){if(this.unfocusOnHide){var e=this.el.querySelectorAll("input, textarea");window.setTimeout(function(){for(var t=0;t<e.length;t++)e[t].blur&&e[t].blur()})}}})}(ionic),function(e){"use strict";e.views.SideMenu=e.views.View.inherit({initialize:function(e){this.el=e.el,this.isEnabled="undefined"==typeof e.isEnabled?!0:e.isEnabled,this.setWidth(e.width)},getFullWidth:function(){return this.width},setWidth:function(e){this.width=e,this.el.style.width=e+"px"},setIsEnabled:function(e){this.isEnabled=e},bringUp:function(){"0"!==this.el.style.zIndex&&(this.el.style.zIndex="0")},pushDown:function(){"-1"!==this.el.style.zIndex&&(this.el.style.zIndex="-1")}}),e.views.SideMenuContent=e.views.View.inherit({initialize:function(t){e.extend(this,{animationClass:"menu-animated",onDrag:function(){},onEndDrag:function(){}},t),e.onGesture("drag",e.proxy(this._onDrag,this),this.el),e.onGesture("release",e.proxy(this._onEndDrag,this),this.el)},_onDrag:function(e){this.onDrag&&this.onDrag(e)},_onEndDrag:function(e){this.onEndDrag&&this.onEndDrag(e)},disableAnimation:function(){this.el.classList.remove(this.animationClass)},enableAnimation:function(){this.el.classList.add(this.animationClass)},getTranslateX:function(){return parseFloat(this.el.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])},setTranslateX:e.animationFrameThrottle(function(t){this.el.style[e.CSS.TRANSFORM]="translate3d("+t+"px, 0, 0)"})})}(ionic),function(e){"use strict";e.views.Slider=e.views.View.inherit({initialize:function(e){function t(){if(p.offsetWidth){m=E.children,T=m.length,m.length<2&&(e.continuous=!1),f.transitions&&e.continuous&&m.length<3&&(E.appendChild(m[0].cloneNode(!0)),E.appendChild(E.children[1].cloneNode(!0)),m=E.children),g=new Array(m.length),v=p.offsetWidth||p.getBoundingClientRect().width,E.style.width=m.length*v+"px";for(var t=m.length;t--;){var n=m[t];n.style.width=v+"px",n.setAttribute("data-index",t),f.transitions&&(n.style.left=t*-v+"px",s(t,S>t?-v:t>S?v:0,0))}e.continuous&&f.transitions&&(s(o(S-1),-v,0),s(o(S+1),v,0)),f.transitions||(E.style.left=S*-v+"px"),p.style.visibility="visible",e.slidesChanged&&e.slidesChanged()}}function n(t){e.continuous?r(S-1,t):S&&r(S-1,t)}function i(t){e.continuous?r(S+1,t):S<m.length-1&&r(S+1,t)}function o(e){return(m.length+e%m.length)%m.length}function r(t,n){if(S!=t){if(f.transitions){var i=Math.abs(S-t)/(S-t);if(e.continuous){var r=i;i=-g[o(t)]/v,i!==r&&(t=-i*m.length+t)}for(var a=Math.abs(S-t)-1;a--;)s(o((t>S?t:S)-a-1),v*i,0);t=o(t),s(S,v*i,n||b),s(t,0,n||b),e.continuous&&s(o(t-i),-(v*i),0)}else t=o(t),l(S*-v,t*-v,n||b);S=t,h(e.callback&&e.callback(S,m[S]))}}function s(e,t,n){a(e,t,n),g[e]=t}function a(e,t,n){var i=m[e],o=i&&i.style;o&&(o.webkitTransitionDuration=o.MozTransitionDuration=o.msTransitionDuration=o.OTransitionDuration=o.transitionDuration=n+"ms",o.webkitTransform="translate("+t+"px,0)translateZ(0)",o.msTransform=o.MozTransform=o.OTransform="translateX("+t+"px)")}function l(t,n,i){if(!i)return void(E.style.left=n+"px");var o=+new Date,r=setInterval(function(){var s=+new Date-o;return s>i?(E.style.left=n+"px",D&&c(),e.transitionEnd&&e.transitionEnd.call(event,S,m[S]),void clearInterval(r)):void(E.style.left=(n-t)*(Math.floor(s/i*100)/100)+t+"px")},4)}function c(){w=setTimeout(i,D)}function u(){D=e.auto||0,clearTimeout(w)}var d=this,_=function(){},h=function(e){setTimeout(e||_,0)},f={addEventListener:!!window.addEventListener,touch:"ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch,transitions:function(e){var t=["transitionProperty","WebkitTransition","MozTransition","OTransition","msTransition"];for(var n in t)if(void 0!==e.style[t[n]])return!0;return!1}(document.createElement("swipe"))},p=e.el;if(p){var m,g,v,T,E=p.children[0];e=e||{};var S=parseInt(e.startSlide,10)||0,b=e.speed||300;e.continuous=void 0!==e.continuous?e.continuous:!0;var w,y,D=e.auto||0,L={},x={},M={handleEvent:function(n){switch(("mousedown"==n.type||"mouseup"==n.type||"mousemove"==n.type)&&(n.touches=[{pageX:n.pageX,pageY:n.pageY}]),n.type){case"mousedown":this.start(n);break;case"touchstart":this.start(n);break;case"touchmove":this.touchmove(n);break;case"mousemove":this.touchmove(n);break;case"touchend":h(this.end(n));break;case"mouseup":h(this.end(n));break;case"webkitTransitionEnd":case"msTransitionEnd":case"oTransitionEnd":case"otransitionend":case"transitionend":h(this.transitionEnd(n));break;case"resize":h(t)}e.stopPropagation&&n.stopPropagation()},start:function(e){var t=e.touches[0];L={x:t.pageX,y:t.pageY,time:+new Date},y=void 0,x={},f.touch?(E.addEventListener("touchmove",this,!1),E.addEventListener("touchend",this,!1)):(E.addEventListener("mousemove",this,!1),E.addEventListener("mouseup",this,!1),document.addEventListener("mouseup",this,!1))},touchmove:function(t){if(!(t.touches.length>1||t.scale&&1!==t.scale||d.slideIsDisabled)){e.disableScroll&&t.preventDefault();var n=t.touches[0];x={x:n.pageX-L.x,y:n.pageY-L.y},"undefined"==typeof y&&(y=!!(y||Math.abs(x.x)<Math.abs(x.y))),y||(t.preventDefault(),u(),e.continuous?(a(o(S-1),x.x+g[o(S-1)],0),a(S,x.x+g[S],0),a(o(S+1),x.x+g[o(S+1)],0)):(x.x=x.x/(!S&&x.x>0||S==m.length-1&&x.x<0?Math.abs(x.x)/v+1:1),a(S-1,x.x+g[S-1],0),a(S,x.x+g[S],0),a(S+1,x.x+g[S+1],0)),e.onDrag&&e.onDrag())}},end:function(){var t=+new Date-L.time,n=Number(t)<250&&Math.abs(x.x)>20||Math.abs(x.x)>v/2,i=!S&&x.x>0||S==m.length-1&&x.x<0;e.continuous&&(i=!1);var r=x.x<0;y||(n&&!i?(r?(e.continuous?(s(o(S-1),-v,0),s(o(S+2),v,0)):s(S-1,-v,0),s(S,g[S]-v,b),s(o(S+1),g[o(S+1)]-v,b),S=o(S+1)):(e.continuous?(s(o(S+1),v,0),s(o(S-2),-v,0)):s(S+1,v,0),s(S,g[S]+v,b),s(o(S-1),g[o(S-1)]+v,b),S=o(S-1)),e.callback&&e.callback(S,m[S])):e.continuous?(s(o(S-1),-v,b),s(S,0,b),s(o(S+1),v,b)):(s(S-1,-v,b),s(S,0,b),s(S+1,v,b))),f.touch?(E.removeEventListener("touchmove",M,!1),E.removeEventListener("touchend",M,!1)):(E.removeEventListener("mousemove",M,!1),E.removeEventListener("mouseup",M,!1),document.removeEventListener("mouseup",M,!1)),e.onDragEnd&&e.onDragEnd()},transitionEnd:function(t){parseInt(t.target.getAttribute("data-index"),10)==S&&(D&&c(),e.transitionEnd&&e.transitionEnd.call(t,S,m[S]))}};this.update=function(){setTimeout(t)},this.setup=function(){t()},this.loop=function(t){return arguments.length&&(e.continuous=!!t),e.continuous},this.enableSlide=function(e){return arguments.length&&(this.slideIsDisabled=!e),!this.slideIsDisabled},this.slide=this.select=function(e,t){u(),r(e,t)},this.prev=this.previous=function(){u(),n()},this.next=function(){u(),i()},this.stop=function(){u()},this.start=function(){c()},this.autoPlay=function(e){!D||0>D?u():(D=e,c())},this.currentIndex=this.selected=function(){return S},this.slidesCount=this.count=function(){return T},this.kill=function(){u(),E.style.width="",E.style.left="",m&&(m=[]),f.addEventListener?(E.removeEventListener("touchstart",M,!1),E.removeEventListener("webkitTransitionEnd",M,!1),E.removeEventListener("msTransitionEnd",M,!1),E.removeEventListener("oTransitionEnd",M,!1),E.removeEventListener("otransitionend",M,!1),E.removeEventListener("transitionend",M,!1),window.removeEventListener("resize",M,!1)):window.onresize=null},this.load=function(){t(),D&&c(),f.addEventListener?(f.touch?E.addEventListener("touchstart",M,!1):E.addEventListener("mousedown",M,!1),f.transitions&&(E.addEventListener("webkitTransitionEnd",M,!1),E.addEventListener("msTransitionEnd",M,!1),E.addEventListener("oTransitionEnd",M,!1),E.addEventListener("otransitionend",M,!1),E.addEventListener("transitionend",M,!1)),window.addEventListener("resize",M,!1)):window.onresize=function(){t()}}}}})}(ionic),function(e){"use strict";e.views.Toggle=e.views.View.inherit({initialize:function(t){var n=this;this.el=t.el,this.checkbox=t.checkbox,this.track=t.track,this.handle=t.handle,this.openPercent=-1,this.onChange=t.onChange||function(){},this.triggerThreshold=t.triggerThreshold||20,this.dragStartHandler=function(e){n.dragStart(e)},this.dragHandler=function(e){n.drag(e)},this.holdHandler=function(e){n.hold(e)},this.releaseHandler=function(e){n.release(e)},this.dragStartGesture=e.onGesture("dragstart",this.dragStartHandler,this.el),this.dragGesture=e.onGesture("drag",this.dragHandler,this.el),this.dragHoldGesture=e.onGesture("hold",this.holdHandler,this.el),this.dragReleaseGesture=e.onGesture("release",this.releaseHandler,this.el)},destroy:function(){e.offGesture(this.dragStartGesture,"dragstart",this.dragStartGesture),e.offGesture(this.dragGesture,"drag",this.dragGesture),e.offGesture(this.dragHoldGesture,"hold",this.holdHandler),e.offGesture(this.dragReleaseGesture,"release",this.releaseHandler)},tap:function(){"disabled"!==this.el.getAttribute("disabled")&&this.val(!this.checkbox.checked)},dragStart:function(e){this.checkbox.disabled||(this._dragInfo={width:this.el.offsetWidth,left:this.el.offsetLeft,right:this.el.offsetLeft+this.el.offsetWidth,triggerX:this.el.offsetWidth/2,initialState:this.checkbox.checked},e.gesture.srcEvent.preventDefault(),this.hold(e))},drag:function(t){var n=this;this._dragInfo&&(t.gesture.srcEvent.preventDefault(),e.requestAnimationFrame(function(){if(n._dragInfo){var e=t.gesture.touches[0].pageX-n._dragInfo.left,i=n._dragInfo.width-n.triggerThreshold;n._dragInfo.initialState?e<n.triggerThreshold?n.setOpenPercent(0):e>n._dragInfo.triggerX&&n.setOpenPercent(100):e<n._dragInfo.triggerX?n.setOpenPercent(0):e>i&&n.setOpenPercent(100)}}))},endDrag:function(){this._dragInfo=null},hold:function(){this.el.classList.add("dragging")},release:function(e){this.el.classList.remove("dragging"),this.endDrag(e)},setOpenPercent:function(t){if(this.openPercent<0||t<this.openPercent-3||t>this.openPercent+3)if(this.openPercent=t,0===t)this.val(!1);else if(100===t)this.val(!0);else{var n=Math.round(t/100*this.track.offsetWidth-this.handle.offsetWidth);n=1>n?0:n,this.handle.style[e.CSS.TRANSFORM]="translate3d("+n+"px,0,0)"}},val:function(t){return(t===!0||t===!1)&&(""!==this.handle.style[e.CSS.TRANSFORM]&&(this.handle.style[e.CSS.TRANSFORM]=""),this.checkbox.checked=t,this.openPercent=t?100:0,this.onChange&&this.onChange()),this.checkbox.checked}})}(ionic)}(); +!function(){function e(e,t,n){t!==!1?X.addEventListener(e,J[e],n):X.removeEventListener(e,J[e])}function t(e){var t=w(e.target),i=T(t);if(ionic.tap.requiresNativeClick(i)||$)return!1;var r=ionic.tap.pointerCoord(e);n("click",i,r.x,r.y),h(i)}function n(e,t,n,i){var r=document.createEvent("MouseEvents");r.initMouseEvent(e,!0,!0,window,1,0,0,n,i,!1,!1,!1,!1,0,null),r.isIonicTap=!0,t.dispatchEvent(r)}function i(e){return"submit"==e.target.type&&0===e.detail?null:ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)||!e.isIonicTap&&!ionic.tap.requiresNativeClick(e.target)?(e.stopPropagation(),ionic.tap.isLabelWithTextInput(e.target)||e.preventDefault(),!1):void 0}function r(t){return t.isIonicTap||p(t)?null:B?(t.stopPropagation(),ionic.Platform.isEdge()||ionic.tap.isTextInput(t.target)&&K===t.target||b(t.target.tagName)||ionic.tap.isVideo(t.target)||t.preventDefault(),!1):($=!1,q=ionic.tap.pointerCoord(t),e("mousemove"),void ionic.activator.start(t))}function a(n){return B?(n.stopPropagation(),n.preventDefault(),!1):p(n)||b(n.target.tagName)?!1:(_(n)||t(n),e("mousemove",!1),ionic.activator.end(),void($=!1))}function o(t){return _(t)?(e("mousemove",!1),ionic.activator.end(),$=!0,!1):void 0}function s(t){if(!p(t)&&($=!1,u(),q=ionic.tap.pointerCoord(t),e(j),ionic.activator.start(t),ionic.Platform.isIOS()&&ionic.tap.isLabelWithTextInput(t.target))){var n=T(w(t.target));n!==F&&t.preventDefault()}}function l(e){p(e)||(u(),_(e)||(t(e),b(e.target.tagName)&&e.preventDefault()),K=e.target,d())}function c(t){return _(t)?($=!0,e(j,!1),ionic.activator.end(),!1):void 0}function d(){e(j,!1),ionic.activator.end(),$=!1}function u(){B=!0,clearTimeout(W),W=setTimeout(function(){B=!1},600)}function p(e){return e.isTapHandled?!0:(e.isTapHandled=!0,ionic.tap.isElementTapDisabled(e.target)?!0:ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)?(e.preventDefault(),!0):void 0)}function h(e){U=null;var t=!1;"SELECT"==e.tagName?(n("mousedown",e,0,0),e.focus&&e.focus(),t=!0):v()===e?t=!0:/^(input|textarea|ion-label)$/i.test(e.tagName)||e.isContentEditable?(t=!0,e.focus&&e.focus(),e.value=e.value,B&&(U=e)):f(),t&&(v(e),ionic.trigger("ionic.focusin",{target:e},!0))}function f(){var e=v();e&&(/^(input|textarea|select)$/i.test(e.tagName)||e.isContentEditable)&&e.blur(),v(null)}function m(e){B&&ionic.tap.isTextInput(v())&&ionic.tap.isTextInput(U)&&U!==e.target&&(U.focus(),U=null),ionic.scroll.isScrolling=!1}function g(){v(null)}function v(e){return arguments.length&&(F=e),F||document.activeElement}function _(e){if(!e||1!==e.target.nodeType||!q||0===q.x&&0===q.y)return!1;var t=ionic.tap.pointerCoord(e),n=!(!e.target.classList||!e.target.classList.contains||"function"!=typeof e.target.classList.contains),i=n&&e.target.classList.contains("button")?Q:Z;return Math.abs(q.x-t.x)>i||Math.abs(q.y-t.y)>i}function w(e,t){for(var n=e,i=0;6>i&&n;i++){if("LABEL"===n.tagName)return n;n=n.parentElement}return t!==!1?e:void 0}function T(e){if(e&&"LABEL"===e.tagName){if(e.control)return e.control;if(e.querySelector){var t=e.querySelector("input,textarea,select");if(t)return t}}return e}function b(e){return/^(select|option)$/i.test(e)}function S(){ionic.keyboard.isInitialized||(V()?(window.addEventListener("native.keyboardshow",pe),window.addEventListener("native.keyboardhide",x)):document.body.addEventListener("focusout",x),document.body.addEventListener("ionic.focusin",ue),document.body.addEventListener("focusin",ue),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!0)}function y(e){clearTimeout(re),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),ionic.keyboard.height=e.keyboardHeight,le?C(O,!0):C(I,!0)}function E(e){return clearTimeout(re),e.target&&!e.target.readOnly&&ionic.tap.isKeyboardElement(e.target)&&(ne=ionic.DomUtil.getParentWithClass(e.target,de))?(ee=e.target,ne.classList.contains("overflow-scroll")||(document.body.scrollTop=0,ne.scrollTop=0,ionic.requestAnimationFrame(function(){document.body.scrollTop=0,ne.scrollTop=0}),window.navigator.msPointerEnabled?document.addEventListener("MSPointerMove",L,!1):document.addEventListener("touchmove",L,!1)),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),document.addEventListener("keydown",M,!1),void(ionic.keyboard.isOpen||V()?ionic.keyboard.isOpen&&I():C(I,!0))):(ee&&(te=ee),void(ee=null))}function x(){clearTimeout(re),(ionic.keyboard.isOpen||ionic.keyboard.isOpening)&&(ionic.keyboard.isClosing=!0,ionic.keyboard.isOpening=!1),re=setTimeout(function(){ionic.requestAnimationFrame(function(){le?C(function(){O(),P()},!1):C(P,!1)})},50)}function D(){ionic.keyboard.isLandscape=!ionic.keyboard.isLandscape,ionic.Platform.isIOS()&&O(),ionic.Platform.isAndroid()&&(ionic.keyboard.isOpen&&V()?le=!0:C(O,!1))}function M(e){ionic.scroll.isScrolling&&L(e)}function L(e){"TEXTAREA"!==e.target.tagName&&e.preventDefault()}function C(e,t){clearInterval(ie);var n,i=0,r=G(),a=r;return n=ionic.Platform.isAndroid()&&ionic.Platform.version()<4.4?30:ionic.Platform.isAndroid()?10:1,ie=setInterval(function(){a=G(),(!(++i<n)||(N(a)||z(a))&&ionic.keyboard.height)&&(V()||(ionic.keyboard.height=Math.abs(r-window.innerHeight)),ionic.keyboard.isOpen=t,clearInterval(ie),e())},50),n}function P(){clearTimeout(re),ionic.keyboard.isOpen=!1,ionic.keyboard.isClosing=!1,(ee||te)&&ionic.trigger("resetScrollView",{target:ee||te},!0),ionic.requestAnimationFrame(function(){document.body.classList.remove(ce)}),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerMove",L):document.removeEventListener("touchmove",L),document.removeEventListener("keydown",M),ionic.Platform.isAndroid()&&(V()&&cordova.plugins.Keyboard.close(),ee&&ee.blur()),ee=null,te=null}function I(){ionic.keyboard.isOpen=!0,ionic.keyboard.isOpening=!1;var e={keyboardHeight:k(),viewportHeight:ae};if(ee){e.target=ee;var t=ee.getBoundingClientRect();e.elementTop=Math.round(t.top),e.elementBottom=Math.round(t.bottom),e.windowHeight=e.viewportHeight-e.keyboardHeight,e.isElementUnderKeyboard=e.elementBottom>e.windowHeight,ionic.trigger("scrollChildIntoView",e,!0)}return setTimeout(function(){document.body.classList.add(ce)},400),e}function k(){if(ionic.keyboard.height)return ionic.keyboard.height;if(ionic.Platform.isAndroid()){if(ionic.Platform.isFullScreen)return 275;var e=window.innerHeight;return ae>e?ae-e:0}return ionic.Platform.isIOS()?ionic.keyboard.isLandscape?206:ionic.Platform.isWebView()?260:216:275}function N(e){return!!(!ionic.keyboard.isLandscape&&oe&&Math.abs(oe-e)<2)}function z(e){return!!(ionic.keyboard.isLandscape&&se&&Math.abs(se-e)<2)}function O(){le=!1,ae=G(),ionic.keyboard.isLandscape&&!se?se=ae:ionic.keyboard.isLandscape||oe||(oe=ae),ee&&ionic.trigger("resetScrollView",{target:ee},!0),ionic.keyboard.isOpen&&ionic.tap.isTextInput(ee)&&I()}function A(){var e=G();e/window.innerWidth<1&&(ionic.keyboard.isLandscape=!0),ae=e,ionic.keyboard.isLandscape&&!se?se=ae:ionic.keyboard.isLandscape||oe||(oe=ae)}function G(){var e=window.innerHeight;return ionic.Platform.isAndroid()&&ionic.Platform.isFullScreen||!ionic.keyboard.isOpen&&!ionic.keyboard.isOpening||ionic.keyboard.isClosing?e:e+k()}function V(){return!!(window.cordova&&cordova.plugins&&cordova.plugins.Keyboard)}function R(){var e;for(e=0;e<document.head.children.length;e++)if("viewport"==document.head.children[e].name){he=document.head.children[e];break}if(he){var t,n=he.content.toLowerCase().replace(/\s+/g,"").split(",");for(e=0;e<n.length;e++)n[e]&&(t=n[e].split("="),fe[t[0]]=t.length>1?t[1]:"_");H()}}function H(){var e=fe.width,t=fe.height,n=ionic.Platform,i=n.version(),r="device-width",a="device-height",o=ionic.viewport.orientation();delete fe.height,fe.width=r,n.isIPad()?i>7?delete fe.width:n.isWebView()?90==o?fe.height="0":7==i&&(fe.height=a):7>i&&(fe.height="0"):n.isIOS()&&(n.isWebView()?i>7?delete fe.width:7>i?t&&(fe.height="0"):7==i&&(fe.height=a):7>i&&t&&(fe.height="0")),(e!==fe.width||t!==fe.height)&&Y()}function Y(){var e,t=[];for(e in fe)fe[e]&&t.push(e+("_"==fe[e]?"":"="+fe[e]));he.content=t.join(", ")}window.ionic=window.ionic||{},window.ionic.views={},window.ionic.version="1.2.4",function(e){e.DelegateService=function(e){function t(){return!0}if(e.indexOf("$getByHandle")>-1)throw new Error("Method '$getByHandle' is implicitly added to each delegate service. Do not list it as a method.");return["$log",function(n){function i(e,t){this._instances=e,this.handle=t}function r(){this._instances=[]}function a(e){return function(){var t,i=this.handle,r=arguments,a=0;return this._instances.forEach(function(n){if((!i||i==n.$$delegateHandle)&&n.$$filterFn(n)){a++;var o=n[e].apply(n,r);1===a&&(t=o)}}),!a&&i?n.warn('Delegate for handle "'+i+'" could not find a corresponding element with delegate-handle="'+i+'"! '+e+"() was not called!\nPossible cause: If you are calling "+e+'() immediately, and your element with delegate-handle="'+i+'" is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to '+e+"() and try again."):t}}return e.forEach(function(e){i.prototype[e]=a(e)}),r.prototype=i.prototype,r.prototype._registerInstance=function(e,n,i){var r=this._instances;return e.$$delegateHandle=n,e.$$filterFn=i||t,r.push(e),function(){var t=r.indexOf(e);-1!==t&&r.splice(t,1)}},r.prototype.$getByHandle=function(e){return new i(this._instances,e)},new r}]}}(window.ionic),function(e,t,n){function i(){a=!0;for(var e=0;e<r.length;e++)n.requestAnimationFrame(r[e]);r=[],t.removeEventListener("DOMContentLoaded",i)}var r=[],a="complete"===t.readyState||"interactive"===t.readyState;a||t.addEventListener("DOMContentLoaded",i),e._rAF=function(){return e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||function(t){e.setTimeout(t,16)}}();var o=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame;n.DomUtil={requestAnimationFrame:function(t){return e._rAF(t)},cancelAnimationFrame:function(e){o(e)},animationFrameThrottle:function(e){var t,i,r;return function(){t=arguments,r=this,i||(i=!0,n.requestAnimationFrame(function(){e.apply(r,t),i=!1}))}},contains:function(e,t){for(var n=t;n;){if(n===e)return!0;n=n.parentNode}},getPositionInParent:function(e){return{left:e.offsetLeft,top:e.offsetTop}},getOffsetTop:function(e){var t=0;if(e.offsetParent){do t+=e.offsetTop,e=e.offsetParent;while(e);return t}},ready:function(e){a?n.requestAnimationFrame(e):r.push(e)},getTextBounds:function(n){if(t.createRange){var i=t.createRange();if(i.selectNodeContents(n),i.getBoundingClientRect){var r=i.getBoundingClientRect();if(r){var a=e.scrollX,o=e.scrollY;return{top:r.top+o,left:r.left+a,right:r.left+a+r.width,bottom:r.top+o+r.height,width:r.width,height:r.height}}}}return null},getChildIndex:function(e,t){if(t)for(var n,i=e.parentNode.children,r=0,a=0,o=i.length;o>r;r++)if(n=i[r],n.nodeName&&n.nodeName.toLowerCase()==t){if(n==e)return a;a++}return Array.prototype.slice.call(e.parentNode.children).indexOf(e)},swapNodes:function(e,t){t.parentNode.insertBefore(e,t)},elementIsDescendant:function(e,t,n){var i=e;do{if(i===t)return!0;i=i.parentNode}while(i&&i!==n);return!1},getParentWithClass:function(e,t,n){for(n=n||10;e.parentNode&&n--;){if(e.parentNode.classList&&e.parentNode.classList.contains(t))return e.parentNode;e=e.parentNode}return null},getParentOrSelfWithClass:function(e,t,n){for(n=n||10;e&&n--;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},rectContains:function(e,t,n,i,r,a){return n>e||e>r?!1:i>t||t>a?!1:!0},blurAll:function(){return t.activeElement&&t.activeElement!=t.body?(t.activeElement.blur(),t.activeElement):null},cachedAttr:function(e,t,n){if(e=e&&e.length&&e[0]||e,e&&e.setAttribute){var i="$attr-"+t;return arguments.length>2?e[i]!==n&&(e.setAttribute(t,n),e[i]=n):"undefined"==typeof e[i]&&(e[i]=e.getAttribute(t)),e[i]}},cachedStyles:function(e,t){if(e=e&&e.length&&e[0]||e,e&&e.style)for(var n in t)e["$style-"+n]!==t[n]&&(e.style[n]=e["$style-"+n]=t[n])}},n.requestAnimationFrame=n.DomUtil.requestAnimationFrame,n.cancelAnimationFrame=n.DomUtil.cancelAnimationFrame,n.animationFrameThrottle=n.DomUtil.animationFrameThrottle}(window,document,ionic),function(e){e.CustomEvent=function(){if("function"==typeof window.CustomEvent)return CustomEvent;var e=function(e,t){var n;t=t||{bubbles:!1,cancelable:!1,detail:void 0};try{n=document.createEvent("CustomEvent"),n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail)}catch(i){n=document.createEvent("Event");for(var r in t)n[r]=t[r];n.initEvent(e,t.bubbles,t.cancelable)}return n};return e.prototype=window.Event.prototype,e}(),e.EventController={VIRTUALIZED_EVENTS:["tap","swipe","swiperight","swipeleft","drag","hold","release"],trigger:function(t,n,i,r){var a=new e.CustomEvent(t,{detail:n,bubbles:!!i,cancelable:!!r});n&&n.target&&n.target.dispatchEvent&&n.target.dispatchEvent(a)||window.dispatchEvent(a)},on:function(t,n,i){for(var r=i||window,a=0,o=this.VIRTUALIZED_EVENTS.length;o>a;a++)if(t==this.VIRTUALIZED_EVENTS[a]){var s=new e.Gesture(i);return s.on(t,n),s}r.addEventListener(t,n)},off:function(e,t,n){n.removeEventListener(e,t)},onGesture:function(t,n,i,r){var a=new e.Gesture(i,r);return a.on(t,n),a},offGesture:function(e,t,n){e&&e.off(t,n)},handlePopState:function(){}},e.on=function(){e.EventController.on.apply(e.EventController,arguments)},e.off=function(){e.EventController.off.apply(e.EventController,arguments)},e.trigger=e.EventController.trigger,e.onGesture=function(){return e.EventController.onGesture.apply(e.EventController.onGesture,arguments)},e.offGesture=function(){return e.EventController.offGesture.apply(e.EventController.offGesture,arguments)}}(window.ionic),function(e){function t(){if(!e.Gestures.READY){e.Gestures.event.determineEventTypes();for(var t in e.Gestures.gestures)e.Gestures.gestures.hasOwnProperty(t)&&e.Gestures.detection.register(e.Gestures.gestures[t]);e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_MOVE,e.Gestures.detection.detect),e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_END,e.Gestures.detection.detect),e.Gestures.READY=!0}}e.Gesture=function(t,n){return new e.Gestures.Instance(t,n||{})},e.Gestures={},e.Gestures.defaults={stop_browser_behavior:"disable-user-behavior"},e.Gestures.HAS_POINTEREVENTS=window.navigator.pointerEnabled||window.navigator.msPointerEnabled,e.Gestures.HAS_TOUCHEVENTS="ontouchstart"in window,e.Gestures.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android|silk/i,e.Gestures.NO_MOUSEEVENTS=e.Gestures.HAS_TOUCHEVENTS&&window.navigator.userAgent.match(e.Gestures.MOBILE_REGEX),e.Gestures.EVENT_TYPES={},e.Gestures.DIRECTION_DOWN="down",e.Gestures.DIRECTION_LEFT="left",e.Gestures.DIRECTION_UP="up",e.Gestures.DIRECTION_RIGHT="right",e.Gestures.POINTER_MOUSE="mouse",e.Gestures.POINTER_TOUCH="touch",e.Gestures.POINTER_PEN="pen",e.Gestures.EVENT_START="start",e.Gestures.EVENT_MOVE="move",e.Gestures.EVENT_END="end",e.Gestures.DOCUMENT=window.document,e.Gestures.plugins={},e.Gestures.READY=!1,e.Gestures.Instance=function(n,i){var r=this;return null===n?this:(t(),this.element=n,this.enabled=!0,this.options=e.Gestures.utils.extend(e.Gestures.utils.extend({},e.Gestures.defaults),i||{}),this.options.stop_browser_behavior&&e.Gestures.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),e.Gestures.event.onTouch(n,e.Gestures.EVENT_START,function(t){r.enabled&&e.Gestures.detection.startDetect(r,t)}),this)},e.Gestures.Instance.prototype={on:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.addEventListener(n[i],t,!1);return this},off:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.removeEventListener(n[i],t,!1);return this},trigger:function(t,n){var i=e.Gestures.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=n;var r=this.element;return e.Gestures.utils.hasParent(n.target,r)&&(r=n.target),r.dispatchEvent(i),this},enable:function(e){return this.enabled=e,this}};var n=null,i=!1,r=!1;e.Gestures.event={bindDom:function(e,t,n){for(var i=t.split(" "),r=0;r<i.length;r++)e.addEventListener(i[r],n,!1)},onTouch:function(t,a,o){var s=this;this.bindDom(t,e.Gestures.EVENT_TYPES[a],function(l){var c=l.type.toLowerCase();if(!c.match(/mouse/)||!r){c.match(/touch/)||c.match(/pointerdown/)||c.match(/mouse/)&&1===l.which?i=!0:c.match(/mouse/)&&1!==l.which&&(i=!1),c.match(/touch|pointer/)&&(r=!0);var d=0;i&&(e.Gestures.HAS_POINTEREVENTS&&a!=e.Gestures.EVENT_END?d=e.Gestures.PointerEvent.updatePointer(a,l):c.match(/touch/)?d=l.touches.length:r||(d=c.match(/up/)?0:1),d>0&&a==e.Gestures.EVENT_END?a=e.Gestures.EVENT_MOVE:d||(a=e.Gestures.EVENT_END),(d||null===n)&&(n=l),o.call(e.Gestures.detection,s.collectEventData(t,a,s.getTouchList(n,a),l)),e.Gestures.HAS_POINTEREVENTS&&a==e.Gestures.EVENT_END&&(d=e.Gestures.PointerEvent.updatePointer(a,l))),d||(n=null,i=!1,r=!1,e.Gestures.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getEvents():e.Gestures.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_START]=t[0],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_MOVE]=t[1],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_END]=t[2]},getTouchList:function(t){return e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getTouchList():t.touches?t.touches:(t.identifier=1,[t])},collectEventData:function(t,n,i,r){var a=e.Gestures.POINTER_TOUCH;return(r.type.match(/mouse/)||e.Gestures.PointerEvent.matchType(e.Gestures.POINTER_MOUSE,r))&&(a=e.Gestures.POINTER_MOUSE),{center:e.Gestures.utils.getCenter(i),timeStamp:(new Date).getTime(),target:r.target,touches:i,eventType:n,pointerType:a,srcEvent:r,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return e.Gestures.detection.stopDetect()}}}},e.Gestures.PointerEvent={pointers:{},getTouchList:function(){var e=this,t=[];return Object.keys(e.pointers).sort().forEach(function(n){t.push(e.pointers[n])}),t},updatePointer:function(t,n){return t==e.Gestures.EVENT_END?this.pointers={}:(n.identifier=n.pointerId,this.pointers[n.pointerId]=n),Object.keys(this.pointers).length},matchType:function(t,n){if(!n.pointerType)return!1;var i={};return i[e.Gestures.POINTER_MOUSE]=n.pointerType==n.MSPOINTER_TYPE_MOUSE||n.pointerType==e.Gestures.POINTER_MOUSE,i[e.Gestures.POINTER_TOUCH]=n.pointerType==n.MSPOINTER_TYPE_TOUCH||n.pointerType==e.Gestures.POINTER_TOUCH,i[e.Gestures.POINTER_PEN]=n.pointerType==n.MSPOINTER_TYPE_PEN||n.pointerType==e.Gestures.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},e.Gestures.utils={extend:function(e,t,n){for(var i in t)void 0!==e[i]&&n||(e[i]=t[i]);return e},hasParent:function(e,t){for(;e;){if(e==t)return!0;e=e.parentNode}return!1},getCenter:function(e){for(var t=[],n=[],i=0,r=e.length;r>i;i++)t.push(e[i].pageX),n.push(e[i].pageY);return{pageX:(Math.min.apply(Math,t)+Math.max.apply(Math,t))/2,pageY:(Math.min.apply(Math,n)+Math.max.apply(Math,n))/2}},getVelocity:function(e,t,n){return{x:Math.abs(t/e)||0,y:Math.abs(n/e)||0}},getAngle:function(e,t){var n=t.pageY-e.pageY,i=t.pageX-e.pageX;return 180*Math.atan2(n,i)/Math.PI},getDirection:function(t,n){var i=Math.abs(t.pageX-n.pageX),r=Math.abs(t.pageY-n.pageY);return i>=r?t.pageX-n.pageX>0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT:t.pageY-n.pageY>0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN},getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},getScale:function(e,t){return e.length>=2&&t.length>=2?this.getDistance(t[0],t[1])/this.getDistance(e[0],e[1]):1},getRotation:function(e,t){return e.length>=2&&t.length>=2?this.getAngle(t[1],t[0])-this.getAngle(e[1],e[0]):0},isVertical:function(t){return t==e.Gestures.DIRECTION_UP||t==e.Gestures.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(e,t){e&&e.classList&&(e.classList.add(t),e.onselectstart=function(){return!1})}},e.Gestures.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,n){this.current||(this.stopped=!1,this.current={inst:t,startEvent:e.Gestures.utils.extend({},n),lastEvent:!1,name:""},this.detect(n))},detect:function(t){if(!this.current||this.stopped)return null;t=this.extendEventData(t);for(var n=this.current.inst.options,i=0,r=this.gestures.length;r>i;i++){var a=this.gestures[i];if(!this.stopped&&n[a.name]!==!1&&a.handler.call(a,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==e.Gestures.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t},stopDetect:function(){this.previous=e.Gestures.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var n=this.current.startEvent;if(n&&(t.touches.length!=n.touches.length||t.touches===n.touches)){n.touches=[];for(var i=0,r=t.touches.length;r>i;i++)n.touches.push(e.Gestures.utils.extend({},t.touches[i]))}var a=t.timeStamp-n.timeStamp,o=t.center.pageX-n.center.pageX,s=t.center.pageY-n.center.pageY,l=e.Gestures.utils.getVelocity(a,o,s);return e.Gestures.utils.extend(t,{deltaTime:a,deltaX:o,deltaY:s,velocityX:l.x,velocityY:l.y,distance:e.Gestures.utils.getDistance(n.center,t.center),angle:e.Gestures.utils.getAngle(n.center,t.center),direction:e.Gestures.utils.getDirection(n.center,t.center),scale:e.Gestures.utils.getScale(n.touches,t.touches),rotation:e.Gestures.utils.getRotation(n.touches,t.touches),startEvent:n}),t},register:function(t){var n=t.defaults||{};return void 0===n[t.name]&&(n[t.name]=!0),e.Gestures.utils.extend(e.Gestures.defaults,n,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(e,t){return e.index<t.index?-1:e.index>t.index?1:0}),this.gestures}},e.Gestures.gestures=e.Gestures.gestures||{},e.Gestures.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:9},timer:null,handler:function(t,n){switch(t.eventType){case e.Gestures.EVENT_START:clearTimeout(this.timer),e.Gestures.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==e.Gestures.detection.current.name&&(e.tap.cancelClick(),n.trigger("hold",t))},n.options.hold_timeout);break;case e.Gestures.EVENT_MOVE:t.distance>n.options.hold_threshold&&clearTimeout(this.timer);break;case e.Gestures.EVENT_END:clearTimeout(this.timer)}}},e.Gestures.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END&&"touchcancel"!=t.srcEvent.type){var i=e.Gestures.detection.previous,r=!1;if(t.deltaTime>n.options.tap_max_touchtime||t.distance>n.options.tap_max_distance)return;i&&"tap"==i.name&&t.timeStamp-i.lastEvent.timeStamp<n.options.doubletap_interval&&t.distance<n.options.doubletap_distance&&(n.trigger("doubletap",t),r=!0),(!r||n.options.tap_always)&&(e.Gestures.detection.current.name="tap",n.trigger("tap",t))}}},e.Gestures.gestures.Swipe={name:"swipe",index:40,defaults:{swipe_max_touches:1,swipe_velocity:.4},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END){if(n.options.swipe_max_touches>0&&t.touches.length>n.options.swipe_max_touches)return;(t.velocityX>n.options.swipe_velocity||t.velocityY>n.options.swipe_velocity)&&(n.trigger(this.name,t),n.trigger(this.name+t.direction,t))}}},e.Gestures.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,correct_for_drag_min_distance:!0,drag_max_touches:1,drag_block_horizontal:!0,drag_block_vertical:!0,drag_lock_to_axis:!1,drag_lock_min_distance:25,prevent_default_directions:[]},triggered:!1,handler:function(t,n){if("touchstart"==t.srcEvent.type||"touchend"==t.srcEvent.type?this.preventedFirstMove=!1:this.preventedFirstMove||"touchmove"!=t.srcEvent.type||(n.options.prevent_default_directions.length>0&&-1!=n.options.prevent_default_directions.indexOf(t.direction)&&t.srcEvent.preventDefault(),this.preventedFirstMove=!0),e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(n.options.drag_max_touches>0&&t.touches.length>n.options.drag_max_touches))switch(t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:if(t.distance<n.options.drag_min_distance&&e.Gestures.detection.current.name!=this.name)return;if(e.Gestures.detection.current.name!=this.name&&(e.Gestures.detection.current.name=this.name,n.options.correct_for_drag_min_distance)){var i=Math.abs(n.options.drag_min_distance/t.distance);e.Gestures.detection.current.startEvent.center.pageX+=t.deltaX*i,e.Gestures.detection.current.startEvent.center.pageY+=t.deltaY*i,t=e.Gestures.detection.extendEventData(t)}(e.Gestures.detection.current.lastEvent.drag_locked_to_axis||n.options.drag_lock_to_axis&&n.options.drag_lock_min_distance<=t.distance)&&(t.drag_locked_to_axis=!0);var r=e.Gestures.detection.current.lastEvent.direction;t.drag_locked_to_axis&&r!==t.direction&&(e.Gestures.utils.isVertical(r)?t.direction=t.deltaY<0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN:t.direction=t.deltaX<0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT),this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),n.trigger(this.name+t.direction,t),(n.options.drag_block_vertical&&e.Gestures.utils.isVertical(t.direction)||n.options.drag_block_horizontal&&!e.Gestures.utils.isVertical(t.direction))&&t.preventDefault();break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,n){if(e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(t.touches.length<2))switch(n.options.transform_always_block&&t.preventDefault(),t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:var i=Math.abs(1-t.scale),r=Math.abs(t.rotation);if(i<n.options.transform_min_scale&&r<n.options.transform_min_rotation)return;e.Gestures.detection.current.name=this.name,this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),r>n.options.transform_min_rotation&&n.trigger("rotate",t),i>n.options.transform_min_scale&&(n.trigger("pinch",t),n.trigger("pinch"+(t.scale<1?"in":"out"),t));break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Touch={name:"touch",index:-(1/0),defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,n){return n.options.prevent_mouseevents&&t.pointerType==e.Gestures.POINTER_MOUSE?void t.stopDetect():(n.options.prevent_default&&t.preventDefault(),void(t.eventType==e.Gestures.EVENT_START&&n.trigger(this.name,t)))}},e.Gestures.gestures.Release={name:"release",index:1/0,handler:function(t,n){t.eventType==e.Gestures.EVENT_END&&n.trigger(this.name,t)}}}(window.ionic),function(e,t,n){function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=new RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null===n?"":decodeURIComponent(n[1].replace(/\+/g," "))}function r(){setTimeout(function(){!f.isReady&&f.isWebView()},_)}function a(){f.isWebView()?t.addEventListener("deviceready",o,!1):o(),s&&e.removeEventListener("load",a,!1)}function o(){f.isReady=!0,f.detect();for(var e=0;e<v.length;e++)v[e]();v=[],n.trigger("platformready",{target:t}),h(function(){t.body.classList.add("platform-ready")})}var s,l="ios",c="android",d="windowsphone",u="edge",p="crosswalk",h=n.requestAnimationFrame,f=n.Platform={navigator:e.navigator,isReady:!1,isFullScreen:!1,platforms:null,grade:null,ua:navigator.userAgent,ready:function(e){f.isReady?e():v.push(e)},detect:function(){f._checkPlatforms(),h(function(){for(var e=0;e<f.platforms.length;e++)t.body.classList.add("platform-"+f.platforms[e])})},setGrade:function(e){var n=f.grade;f.grade=e,h(function(){n&&t.body.classList.remove("grade-"+n),t.body.classList.add("grade-"+e)})},device:function(){return e.device||{}},_checkPlatforms:function(){f.platforms=[];var t="a";f.isWebView()?(f.platforms.push("webview"),e.cordova||e.PhoneGap||e.phonegap?f.platforms.push("cordova"):e.forge&&f.platforms.push("trigger")):f.platforms.push("browser"),f.isIPad()&&f.platforms.push("ipad");var n=f.platform();if(n){f.platforms.push(n);var i=f.version();if(i){var r=i.toString();r.indexOf(".")>0?r=r.replace(".","_"):r+="_0",f.platforms.push(n+r.split("_")[0]),f.platforms.push(n+r),f.isAndroid()&&4.4>i?t=4>i?"c":"b":f.isWindowsPhone()&&(t="b")}}f.setGrade(t)},isWebView:function(){return!!(e.cordova||e.PhoneGap||e.phonegap||e.forge)},isIPad:function(){return/iPad/i.test(f.navigator.platform)?!0:/iPad/i.test(f.ua)},isIOS:function(){return f.is(l)},isAndroid:function(){return f.is(c)},isWindowsPhone:function(){return f.is(d)},isEdge:function(){return f.is(u)},isCrosswalk:function(){return f.is(p)},platform:function(){return null===m&&f.setPlatform(f.device().platform),m},setPlatform:function(e){m="undefined"!=typeof e&&null!==e&&e.length?e.toLowerCase():i("ionicplatform")?i("ionicplatform"):f.ua.indexOf("Edge")>-1?u:f.ua.indexOf("Windows Phone")>-1?d:f.ua.indexOf("Android")>0?c:/iPhone|iPad|iPod/.test(f.ua)?l:f.navigator.platform&&navigator.platform.toLowerCase().split(" ")[0]||""},version:function(){return null===g&&f.setVersion(f.device().version),g},setVersion:function(e){if("undefined"!=typeof e&&null!==e&&(e=e.split("."),e=parseFloat(e[0]+"."+(e.length>1?e[1]:0)),!isNaN(e)))return void(g=e);g=0;var t=f.platform(),n={android:/Android (\d+).(\d+)?/,ios:/OS (\d+)_(\d+)?/,windowsphone:/Windows Phone (\d+).(\d+)?/};n[t]&&(e=f.ua.match(n[t]),e&&e.length>2&&(g=parseFloat(e[1]+"."+e[2])))},is:function(e){if(e=e.toLowerCase(),f.platforms)for(var t=0;t<f.platforms.length;t++)if(f.platforms[t]===e)return!0;var n=f.platform();return n?n===e.toLowerCase():f.ua.toLowerCase().indexOf(e)>=0},exitApp:function(){f.ready(function(){navigator.app&&navigator.app.exitApp&&navigator.app.exitApp()})},showStatusBar:function(n){f._showStatusBar=n,f.ready(function(){h(function(){f._showStatusBar?(e.StatusBar&&e.StatusBar.show(),t.body.classList.remove("status-bar-hide")):(e.StatusBar&&e.StatusBar.hide(),t.body.classList.add("status-bar-hide"))})})},fullScreen:function(e,i){f.isFullScreen=e!==!1,n.DomUtil.ready(function(){h(function(){f.isFullScreen?t.body.classList.add("fullscreen"):t.body.classList.remove("fullscreen")}),f.showStatusBar(i===!0)})}},m=null,g=null,v=[],_=2e3;r(),"complete"===t.readyState?a():(s=!0,e.addEventListener("load",a,!1))}(window,document,ionic),function(e,t){"use strict";t.CSS={},t.CSS.TRANSITION=[],t.CSS.TRANSFORM=[],t.EVENTS={},function(){var n,i=["webkitTransform","transform","-webkit-transform","webkit-transform","-moz-transform","moz-transform","MozTransform","mozTransform","msTransform"];for(n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSFORM=i[n];break}for(i=["webkitTransition","mozTransition","msTransition","transition"],n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSITION=i[n];break}t.CSS.TRANSITION=t.CSS.TRANSITION||"transition";var r=t.CSS.TRANSITION.indexOf("webkit")>-1;t.CSS.TRANSITION_DURATION=(r?"-webkit-":"")+"transition-duration",t.CSS.TRANSITIONEND=(r?"webkitTransitionEnd ":"")+"transitionend"}(),function(){var e="touchstart",n="touchmove",i="touchend",r="touchcancel";window.navigator.pointerEnabled?(e="pointerdown", +n="pointermove",i="pointerup",r="pointercancel"):window.navigator.msPointerEnabled&&(e="MSPointerDown",n="MSPointerMove",i="MSPointerUp",r="MSPointerCancel"),t.EVENTS.touchstart=e,t.EVENTS.touchmove=n,t.EVENTS.touchend=i,t.EVENTS.touchcancel=r}(),"classList"in e.documentElement||!Object.defineProperty||"undefined"==typeof HTMLElement||Object.defineProperty(HTMLElement.prototype,"classList",{get:function(){function e(e){return function(){var n,i=t.className.split(/\s+/);for(n=0;n<arguments.length;n++)e(i,i.indexOf(arguments[n]),arguments[n]);t.className=i.join(" ")}}var t=this;return{add:e(function(e,t,n){~t||e.push(n)}),remove:e(function(e,t){~t&&e.splice(t,1)}),toggle:e(function(e,t,n){~t?e.splice(t,1):e.push(n)}),contains:function(e){return!!~t.className.split(/\s+/).indexOf(e)},item:function(e){return t.className.split(/\s+/)[e]||null}}}})}(document,ionic);var X,F,B,W,$,q,U,K,j="touchmove",Z=12,Q=50,J={click:i,mousedown:r,mouseup:a,mousemove:o,touchstart:s,touchend:l,touchcancel:d,touchmove:c,pointerdown:s,pointerup:l,pointercancel:d,pointermove:c,MSPointerDown:s,MSPointerUp:l,MSPointerCancel:d,MSPointerMove:c,focusin:m,focusout:g};ionic.tap={register:function(t){return X=t,e("click",!0,!0),e("mouseup"),e("mousedown"),window.navigator.pointerEnabled?(e("pointerdown"),e("pointerup"),e("pointercancel"),j="pointermove"):window.navigator.msPointerEnabled?(e("MSPointerDown"),e("MSPointerUp"),e("MSPointerCancel"),j="MSPointerMove"):(e("touchstart"),e("touchend"),e("touchcancel")),e("focusin"),e("focusout"),function(){for(var t in J)e(t,!1);X=null,F=null,B=!1,$=!1,q=null}},ignoreScrollStart:function(e){return e.defaultPrevented||/^(file|range)$/i.test(e.target.type)||"true"==(e.target.dataset?e.target.dataset.preventScroll:e.target.getAttribute("data-prevent-scroll"))||!!/^(object|embed)$/i.test(e.target.tagName)||ionic.tap.isElementTapDisabled(e.target)},isTextInput:function(e){return!!e&&("TEXTAREA"==e.tagName||"true"===e.contentEditable||"INPUT"==e.tagName&&!/^(radio|checkbox|range|file|submit|reset|color|image|button)$/i.test(e.type))},isDateInput:function(e){return!!e&&"INPUT"==e.tagName&&/^(date|time|datetime-local|month|week)$/i.test(e.type)},isVideo:function(e){return!!e&&"VIDEO"==e.tagName},isKeyboardElement:function(e){return!ionic.Platform.isIOS()||ionic.Platform.isIPad()?ionic.tap.isTextInput(e)&&!ionic.tap.isDateInput(e):ionic.tap.isTextInput(e)||!!e&&"SELECT"==e.tagName},isLabelWithTextInput:function(e){var t=w(e,!1);return!!t&&ionic.tap.isTextInput(T(t))},containsOrIsTextInput:function(e){return ionic.tap.isTextInput(e)||ionic.tap.isLabelWithTextInput(e)},cloneFocusedInput:function(e){ionic.tap.hasCheckedClone||(ionic.tap.hasCheckedClone=!0,ionic.requestAnimationFrame(function(){var t=e.querySelector(":focus");if(ionic.tap.isTextInput(t)&&!ionic.tap.isDateInput(t)){var n=t.cloneNode(!0);n.value=t.value,n.classList.add("cloned-text-input"),n.readOnly=!0,t.isContentEditable&&(n.contentEditable=t.contentEditable,n.innerHTML=t.innerHTML),t.parentElement.insertBefore(n,t),t.classList.add("previous-input-focus"),n.scrollTop=t.scrollTop}}))},hasCheckedClone:!1,removeClonedInputs:function(e){ionic.tap.hasCheckedClone=!1,ionic.requestAnimationFrame(function(){var t,n=e.querySelectorAll(".cloned-text-input"),i=e.querySelectorAll(".previous-input-focus");for(t=0;t<n.length;t++)n[t].parentElement.removeChild(n[t]);for(t=0;t<i.length;t++)i[t].classList.remove("previous-input-focus"),i[t].style.top="",ionic.keyboard.isOpen&&!ionic.keyboard.isClosing&&i[t].focus()})},requiresNativeClick:function(e){return ionic.Platform.isWindowsPhone()&&("A"==e.tagName||"BUTTON"==e.tagName||e.hasAttribute("ng-click")||"INPUT"==e.tagName&&("button"==e.type||"submit"==e.type))?!0:!e||e.disabled||/^(file|range)$/i.test(e.type)||/^(object|video)$/i.test(e.tagName)||ionic.tap.isLabelContainingFileInput(e)?!0:ionic.tap.isElementTapDisabled(e)},isLabelContainingFileInput:function(e){var t=w(e);if("LABEL"!==t.tagName)return!1;var n=t.querySelector("input[type=file]");return n&&n.disabled===!1?!0:!1},isElementTapDisabled:function(e){if(e&&1===e.nodeType)for(var t=e;t;){if("true"==(t.dataset?t.dataset.tapDisabled:t.getAttribute&&t.getAttribute("data-tap-disabled")))return!0;t=t.parentElement}return!1},setTolerance:function(e,t){Z=e,Q=t},cancelClick:function(){$=!0},pointerCoord:function(e){var t={x:0,y:0};if(e){var n=e.touches&&e.touches.length?e.touches:[e],i=e.changedTouches&&e.changedTouches[0]||n[0];i&&(t.x=i.clientX||i.pageX||0,t.y=i.clientY||i.pageY||0)}return t}},ionic.DomUtil.ready(function(){var e="undefined"!=typeof angular?angular:null;(!e||e&&!e.scenario)&&ionic.tap.register(document)}),function(e,t){"use strict";function n(){a={},t.requestAnimationFrame(r)}function i(){for(var e in a)a[e]&&(a[e].classList.add(l),o[e]=a[e]);a={}}function r(){if(t.transition&&t.transition.isActive)return void setTimeout(r,400);for(var e in o)o[e]&&(o[e].classList.remove(l),delete o[e])}var a={},o={},s=0,l="activated";t.activator={start:function(e){var n=t.tap.pointerCoord(e).x;n>0&&30>n||t.requestAnimationFrame(function(){if(!(t.scroll&&t.scroll.isScrolling||t.tap.requiresNativeClick(e.target))){for(var n,r=e.target,o=0;6>o&&(r&&1===r.nodeType);o++){if(n&&r.classList&&r.classList.contains("item")){n=r;break}if("A"==r.tagName||"BUTTON"==r.tagName||r.hasAttribute("ng-click")){n=r;break}if(r.classList.contains("button")){n=r;break}if("ION-CONTENT"==r.tagName||r.classList&&r.classList.contains("pane")||"BODY"==r.tagName)break;r=r.parentElement}n&&(a[s]=n,t.requestAnimationFrame(i),s=s>29?0:s+1)}})},end:function(){setTimeout(n,200)}}}(document,ionic),function(e){var t=0;e.Utils={arrayMove:function(e,t,n){if(n>=e.length)for(var i=n-e.length;i--+1;)e.push(void 0);return e.splice(n,0,e.splice(t,1)[0]),e},proxy:function(e,t){var n=Array.prototype.slice.call(arguments,2);return function(){return e.apply(t,n.concat(Array.prototype.slice.call(arguments)))}},debounce:function(e,t,n){var i,r,a,o,s;return function(){a=this,r=arguments,o=new Date;var l=function(){var c=new Date-o;t>c?i=setTimeout(l,t-c):(i=null,n||(s=e.apply(a,r)))},c=n&&!i;return i||(i=setTimeout(l,t)),c&&(s=e.apply(a,r)),s}},throttle:function(e,t,n){var i,r,a,o=null,s=0;n||(n={});var l=function(){s=n.leading===!1?0:Date.now(),o=null,a=e.apply(i,r)};return function(){var c=Date.now();s||n.leading!==!1||(s=c);var d=t-(c-s);return i=this,r=arguments,0>=d?(clearTimeout(o),o=null,s=c,a=e.apply(i,r)):o||n.trailing===!1||(o=setTimeout(l,d)),a}},inherit:function(t,n){var i,r=this;i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return r.apply(this,arguments)},e.extend(i,r,n);var a=function(){this.constructor=i};return a.prototype=r.prototype,i.prototype=new a,t&&e.extend(i.prototype,t),i.__super__=r.prototype,i},extend:function(e){for(var t=Array.prototype.slice.call(arguments,1),n=0;n<t.length;n++){var i=t[n];if(i)for(var r in i)e[r]=i[r]}return e},nextUid:function(){return"ion"+t++},disconnectScope:function(e){if(e&&e.$root!==e){var t=e.$parent;e.$$disconnected=!0,e.$broadcast("$ionic.disconnectScope",e),t.$$childHead===e&&(t.$$childHead=e.$$nextSibling),t.$$childTail===e&&(t.$$childTail=e.$$prevSibling),e.$$prevSibling&&(e.$$prevSibling.$$nextSibling=e.$$nextSibling),e.$$nextSibling&&(e.$$nextSibling.$$prevSibling=e.$$prevSibling),e.$$nextSibling=e.$$prevSibling=null}},reconnectScope:function(e){if(e&&e.$root!==e&&e.$$disconnected){var t=e.$parent;e.$$disconnected=!1,e.$broadcast("$ionic.reconnectScope",e),e.$$prevSibling=t.$$childTail,t.$$childHead?(t.$$childTail.$$nextSibling=e,t.$$childTail=e):t.$$childHead=t.$$childTail=e}},isScopeDisconnected:function(e){for(var t=e;t;){if(t.$$disconnected)return!0;t=t.$parent}return!1}},e.inherit=e.Utils.inherit,e.extend=e.Utils.extend,e.throttle=e.Utils.throttle,e.proxy=e.Utils.proxy,e.debounce=e.Utils.debounce}(window.ionic);var ee,te,ne,ie,re,ae=0,oe=0,se=0,le=!1,ce="keyboard-open",de="scroll-content",ue=ionic.debounce(E,200,!0),pe=ionic.debounce(y,100,!0);ionic.keyboard={isOpen:!1,isClosing:!1,isOpening:!1,height:0,isLandscape:!1,isInitialized:!1,hide:function(){V()&&cordova.plugins.Keyboard.close(),ee&&ee.blur()},show:function(){V()&&cordova.plugins.Keyboard.show()},disable:function(){V()?(window.removeEventListener("native.keyboardshow",pe),window.removeEventListener("native.keyboardhide",x)):document.body.removeEventListener("focusout",x),document.body.removeEventListener("ionic.focusin",ue),document.body.removeEventListener("focusin",ue),window.removeEventListener("orientationchange",D),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!1},enable:function(){S()}},ae=G(),ionic.Platform.ready(function(){A(),window.addEventListener("orientationchange",D),setTimeout(A,999),window.navigator.msPointerEnabled?document.addEventListener("MSPointerDown",S,!1):document.addEventListener("touchstart",S,!1)});var he,fe={};ionic.viewport={orientation:function(){return window.innerWidth>window.innerHeight?90:0}},ionic.Platform.ready(function(){R(),window.addEventListener("orientationchange",function(){setTimeout(H,1e3)},!1)}),function(e){"use strict";e.views.View=function(){this.initialize.apply(this,arguments)},e.views.View.inherit=e.inherit,e.extend(e.views.View.prototype,{initialize:function(){}})}(window.ionic);var me={effect:{}};!function(e){var t=Date.now||function(){return+new Date},n=60,i=1e3,r={},a=1;me.effect.Animate={requestAnimationFrame:function(){var t=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame,n=!!t;if(t&&!/requestAnimationFrame\(\)\s*\{\s*\[native code\]\s*\}/i.test(t.toString())&&(n=!1),n)return function(e,n){t(e,n)};var i=60,r={},a=0,o=1,s=null,l=+new Date;return function(e){var t=o++;return r[t]=e,a++,null===s&&(s=setInterval(function(){var e=+new Date,t=r;r={},a=0;for(var n in t)t.hasOwnProperty(n)&&(t[n](e),l=e);e-l>2500&&(clearInterval(s),s=null)},1e3/i)),t}}(),stop:function(e){var t=null!=r[e];return t&&(r[e]=null),t},isRunning:function(e){return null!=r[e]},start:function(e,o,s,l,c,d){var u=t(),p=u,h=0,f=0,m=a++;if(d||(d=document.body),m%20===0){var g={};for(var v in r)g[v]=!0;r=g}var _=function(a){var g=a!==!0,v=t();if(!r[m]||o&&!o(m))return r[m]=null,void(s&&s(n-f/((v-u)/i),m,!1));if(g)for(var w=Math.round((v-p)/(i/n))-1,T=0;T<Math.min(w,4);T++)_(!0),f++;l&&(h=(v-u)/l,h>1&&(h=1));var b=c?c(h):h;e(b,v,g)!==!1&&1!==h||!g?g&&(p=v,me.effect.Animate.requestAnimationFrame(_,d)):(r[m]=null,s&&s(n-f/((v-u)/i),m,1===h||null==l))};return r[m]=!0,me.effect.Animate.requestAnimationFrame(_,d),m}}}(window),function(e){var t=function(){},n=function(e){return Math.pow(e-1,3)+1},i=function(e){return(e/=.5)<1?.5*Math.pow(e,3):.5*(Math.pow(e-2,3)+2)};e.views.Scroll=e.views.View.inherit({initialize:function(n){var i=this;i.__container=n.el,i.__content=n.el.firstElementChild,setTimeout(function(){i.__container&&i.__content&&(i.__container.scrollTop=0,i.__content.scrollTop=0)}),i.options={scrollingX:!1,scrollbarX:!0,scrollingY:!0,scrollbarY:!0,startX:0,startY:0,wheelDampen:6,minScrollbarSizeX:5,minScrollbarSizeY:5,scrollbarsFade:!0,scrollbarFadeDelay:300,scrollbarResizeFadeDelay:1e3,animating:!0,animationDuration:250,decelVelocityThreshold:4,decelVelocityThresholdPaging:4,bouncing:!0,locking:!0,paging:!1,snapping:!1,zooming:!1,minZoom:.5,maxZoom:3,speedMultiplier:1,deceleration:.97,preventDefault:!1,scrollingComplete:t,penetrationDeceleration:.03,penetrationAcceleration:.08,scrollEventInterval:10,freeze:!1,getContentWidth:function(){return Math.max(i.__content.scrollWidth,i.__content.offsetWidth)},getContentHeight:function(){return Math.max(i.__content.scrollHeight,i.__content.offsetHeight+2*i.__content.offsetTop)}};for(var r in n)i.options[r]=n[r];i.hintResize=e.debounce(function(){i.resize()},1e3,!0),i.onScroll=function(){e.scroll.isScrolling?(clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)):setTimeout(i.setScrollStart,50)},i.freeze=function(e){return arguments.length&&(i.options.freeze=e),i.options.freeze},i.freezeShut=i.freeze,i.setScrollStart=function(){e.scroll.isScrolling=Math.abs(e.scroll.lastTop-i.__scrollTop)>1,clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)},i.setScrollStop=function(){e.scroll.isScrolling=!1,e.scroll.lastTop=i.__scrollTop},i.triggerScrollEvent=e.throttle(function(){i.onScroll(),e.trigger("scroll",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.options.scrollEventInterval),i.triggerScrollEndEvent=function(){e.trigger("scrollend",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.__scrollLeft=i.options.startX,i.__scrollTop=i.options.startY,i.__callback=i.getRenderFn(),i.__initEventHandlers(),i.__createScrollbars()},run:function(){this.resize(),this.__fadeScrollbars("out",this.options.scrollbarResizeFadeDelay)},__isSingleTouch:!1,__isTracking:!1,__didDecelerationComplete:!1,__isGesturing:!1,__isDragging:!1,__isDecelerating:!1,__isAnimating:!1,__clientLeft:0,__clientTop:0,__clientWidth:0,__clientHeight:0,__contentWidth:0,__contentHeight:0,__snapWidth:100,__snapHeight:100,__refreshHeight:null,__refreshActive:!1,__refreshActivate:null,__refreshDeactivate:null,__refreshStart:null,__zoomLevel:1,__scrollLeft:0,__scrollTop:0,__maxScrollLeft:0,__maxScrollTop:0,__scheduledLeft:0,__scheduledTop:0,__scheduledZoom:0,__lastTouchLeft:null,__lastTouchTop:null,__lastTouchMove:null,__positions:null,__minDecelerationScrollLeft:null,__minDecelerationScrollTop:null,__maxDecelerationScrollLeft:null,__maxDecelerationScrollTop:null,__decelerationVelocityX:null,__decelerationVelocityY:null,__transformProperty:null,__perspectiveProperty:null,__indicatorX:null,__indicatorY:null,__scrollbarFadeTimeout:null,__didWaitForSize:null,__sizerTimeout:null,__initEventHandlers:function(){function t(e){return e.touches&&e.touches.length?e.touches:[{pageX:e.pageX,pageY:e.pageY}]}var n,i=this,r=i.__container;if(i.scrollChildIntoView=function(t){var a=r.getBoundingClientRect().bottom;n=r.offsetHeight;var o=i.isShrunkForKeyboard,s=r.parentNode.classList.contains("modal"),l=s&&window.innerWidth>=680;if(!o){if(e.Platform.isIOS()||e.Platform.isFullScreen||l){var c=t.detail.viewportHeight-a,d=Math.max(0,t.detail.keyboardHeight-c);e.requestAnimationFrame(function(){n-=d,r.style.height=n+"px",r.style.overflow="visible",i.resize()})}i.isShrunkForKeyboard=!0}t.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){r.scrollTop=0,i.isShrunkForKeyboard&&!o&&(a=r.getBoundingClientRect().bottom);var s=.5*n,l=(t.detail.elementBottom+t.detail.elementTop)/2,c=l-a,d=c+s;d>0&&(e.Platform.isIOS()&&e.tap.cloneFocusedInput(r,i),i.scrollBy(0,d,!0),i.onScroll())}),t.stopPropagation()},i.resetScrollView=function(){i.isShrunkForKeyboard&&(i.isShrunkForKeyboard=!1,r.style.height="",r.style.overflow=""),i.resize()},r.addEventListener("scrollChildIntoView",i.scrollChildIntoView),document.addEventListener("resetScrollView",i.resetScrollView),i.touchStart=function(n){if(i.startCoordinates=e.tap.pointerCoord(n),!e.tap.ignoreScrollStart(n)){if(i.__isDown=!0,e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName)return void(i.__hasStarted=!1);i.__isSelectable=!0,i.__enableScrollY=!0,i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),n.preventDefault()}},i.touchMove=function(n){if(!(i.options.freeze||!i.__isDown||!i.__isDown&&n.defaultPrevented||"TEXTAREA"===n.target.tagName&&n.target.parentElement.querySelector(":focus"))){if(!i.__hasStarted&&(e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName))return i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),void n.preventDefault();if(i.startCoordinates){var a=e.tap.pointerCoord(n);i.__isSelectable&&e.tap.isTextInput(n.target)&&Math.abs(i.startCoordinates.x-a.x)>20&&(i.__enableScrollY=!1,i.__isSelectable=!0),i.__enableScrollY&&Math.abs(i.startCoordinates.y-a.y)>10&&(i.__isSelectable=!1,e.tap.cloneFocusedInput(r,i))}i.doTouchMove(t(n),n.timeStamp,n.scale),i.__isDown=!0}},i.touchMoveBubble=function(e){i.__isDown&&i.options.preventDefault&&e.preventDefault()},i.touchEnd=function(t){i.__isDown&&(i.doTouchEnd(t,t.timeStamp),i.__isDown=!1,i.__hasStarted=!1,i.__isSelectable=!0,i.__enableScrollY=!0,i.__isDragging||i.__isDecelerating||i.__isAnimating||e.tap.removeClonedInputs(r,i))},i.mouseWheel=e.animationFrameThrottle(function(t){var n=e.DomUtil.getParentOrSelfWithClass(t.target,"ionic-scroll");i.options.freeze||n!==i.__container||(i.hintResize(),i.scrollBy((t.wheelDeltaX||t.deltaX||0)/i.options.wheelDampen,(-t.wheelDeltaY||t.deltaY||0)/i.options.wheelDampen),i.__fadeScrollbars("in"),clearTimeout(i.__wheelHideBarTimeout),i.__wheelHideBarTimeout=setTimeout(function(){i.__fadeScrollbars("out")},100))}),"ontouchstart"in window)r.addEventListener("touchstart",i.touchStart,!1),i.options.preventDefault&&r.addEventListener("touchmove",i.touchMoveBubble,!1),document.addEventListener("touchmove",i.touchMove,!1),document.addEventListener("touchend",i.touchEnd,!1),document.addEventListener("touchcancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else if(window.navigator.pointerEnabled)r.addEventListener("pointerdown",i.touchStart,!1),i.options.preventDefault&&r.addEventListener("pointermove",i.touchMoveBubble,!1),document.addEventListener("pointermove",i.touchMove,!1),document.addEventListener("pointerup",i.touchEnd,!1),document.addEventListener("pointercancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else if(window.navigator.msPointerEnabled)r.addEventListener("MSPointerDown",i.touchStart,!1),i.options.preventDefault&&r.addEventListener("MSPointerMove",i.touchMoveBubble,!1),document.addEventListener("MSPointerMove",i.touchMove,!1),document.addEventListener("MSPointerUp",i.touchEnd,!1),document.addEventListener("MSPointerCancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else{var a=!1;i.mouseDown=function(n){e.tap.ignoreScrollStart(n)||"SELECT"===n.target.tagName||(i.doTouchStart(t(n),n.timeStamp),e.tap.isTextInput(n.target)||n.preventDefault(),a=!0)},i.mouseMove=function(e){i.options.freeze||!a||!a&&e.defaultPrevented||(i.doTouchMove(t(e),e.timeStamp),a=!0)},i.mouseMoveBubble=function(e){a&&i.options.preventDefault&&e.preventDefault()},i.mouseUp=function(e){a&&(i.doTouchEnd(e,e.timeStamp),a=!1)},r.addEventListener("mousedown",i.mouseDown,!1),i.options.preventDefault&&r.addEventListener("mousemove",i.mouseMoveBubble,!1),document.addEventListener("mousemove",i.mouseMove,!1),document.addEventListener("mouseup",i.mouseUp,!1),document.addEventListener("mousewheel",i.mouseWheel,!1),document.addEventListener("wheel",i.mouseWheel,!1)}},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("touchstart",n.touchStart),i.removeEventListener("touchmove",n.touchMoveBubble),document.removeEventListener("touchmove",n.touchMove),document.removeEventListener("touchend",n.touchEnd),document.removeEventListener("touchcancel",n.touchEnd),i.removeEventListener("pointerdown",n.touchStart),i.removeEventListener("pointermove",n.touchMoveBubble),document.removeEventListener("pointermove",n.touchMove),document.removeEventListener("pointerup",n.touchEnd),document.removeEventListener("pointercancel",n.touchEnd),i.removeEventListener("MSPointerDown",n.touchStart),i.removeEventListener("MSPointerMove",n.touchMoveBubble),document.removeEventListener("MSPointerMove",n.touchMove),document.removeEventListener("MSPointerUp",n.touchEnd),document.removeEventListener("MSPointerCancel",n.touchEnd),i.removeEventListener("mousedown",n.mouseDown),i.removeEventListener("mousemove",n.mouseMoveBubble),document.removeEventListener("mousemove",n.mouseMove),document.removeEventListener("mouseup",n.mouseUp),document.removeEventListener("mousewheel",n.mouseWheel),document.removeEventListener("wheel",n.mouseWheel),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),document.removeEventListener("resetScrollView",n.resetScrollView),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.__callback=n.scrollChildIntoView=n.resetScrollView=t,n.mouseMove=n.mouseDown=n.mouseUp=n.mouseWheel=n.touchStart=n.touchMove=n.touchEnd=n.touchCancel=t,n.resize=n.scrollTo=n.zoomTo=n.__scrollingComplete=t,i=null},__createScrollbar:function(e){var t=document.createElement("div"),n=document.createElement("div");return n.className="scroll-bar-indicator scroll-bar-fade-out","h"==e?t.className="scroll-bar scroll-bar-h":t.className="scroll-bar scroll-bar-v",t.appendChild(n),t},__createScrollbars:function(){var e,t,n=this;n.options.scrollingX&&(e={el:n.__createScrollbar("h"),sizeRatio:1},e.indicator=e.el.children[0],n.options.scrollbarX&&n.__container.appendChild(e.el),n.__indicatorX=e),n.options.scrollingY&&(t={el:n.__createScrollbar("v"),sizeRatio:1},t.indicator=t.el.children[0],n.options.scrollbarY&&n.__container.appendChild(t.el),n.__indicatorY=t)},__resizeScrollbars:function(){var t=this;if(t.__indicatorX){var n=Math.max(Math.round(t.__clientWidth*t.__clientWidth/t.__contentWidth),20);n>t.__contentWidth&&(n=0),n!==t.__indicatorX.size&&e.requestAnimationFrame(function(){t.__indicatorX.indicator.style.width=n+"px"}),t.__indicatorX.size=n,t.__indicatorX.minScale=t.options.minScrollbarSizeX/n,t.__indicatorX.maxPos=t.__clientWidth-n,t.__indicatorX.sizeRatio=t.__maxScrollLeft?t.__indicatorX.maxPos/t.__maxScrollLeft:1}if(t.__indicatorY){var i=Math.max(Math.round(t.__clientHeight*t.__clientHeight/t.__contentHeight),20);i>t.__contentHeight&&(i=0),i!==t.__indicatorY.size&&e.requestAnimationFrame(function(){t.__indicatorY&&(t.__indicatorY.indicator.style.height=i+"px")}),t.__indicatorY.size=i,t.__indicatorY.minScale=t.options.minScrollbarSizeY/i,t.__indicatorY.maxPos=t.__clientHeight-i,t.__indicatorY.sizeRatio=t.__maxScrollTop?t.__indicatorY.maxPos/t.__maxScrollTop:1}},__repositionScrollbars:function(){var e,t,n,i,r,a,o=this,s=0,l=0;if(o.__indicatorX){o.__indicatorY&&(s=10),r=Math.round(o.__indicatorX.sizeRatio*o.__scrollLeft)||0,n=o.__scrollLeft-(o.__maxScrollLeft-s),o.__scrollLeft<0?(t=Math.max(o.__indicatorX.minScale,(o.__indicatorX.size-Math.abs(o.__scrollLeft))/o.__indicatorX.size),r=0,o.__indicatorX.indicator.style[o.__transformOriginProperty]="left center"):n>0?(t=Math.max(o.__indicatorX.minScale,(o.__indicatorX.size-n)/o.__indicatorX.size),r=o.__indicatorX.maxPos-s,o.__indicatorX.indicator.style[o.__transformOriginProperty]="right center"):(r=Math.min(o.__maxScrollLeft,Math.max(0,r)),t=1);var c="translate3d("+r+"px, 0, 0) scaleX("+t+")";o.__indicatorX.transformProp!==c&&(o.__indicatorX.indicator.style[o.__transformProperty]=c,o.__indicatorX.transformProp=c)}if(o.__indicatorY){a=Math.round(o.__indicatorY.sizeRatio*o.__scrollTop)||0,o.__indicatorX&&(l=10),i=o.__scrollTop-(o.__maxScrollTop-l),o.__scrollTop<0?(e=Math.max(o.__indicatorY.minScale,(o.__indicatorY.size-Math.abs(o.__scrollTop))/o.__indicatorY.size),a=0,"center top"!==o.__indicatorY.originProp&&(o.__indicatorY.indicator.style[o.__transformOriginProperty]="center top",o.__indicatorY.originProp="center top")):i>0?(e=Math.max(o.__indicatorY.minScale,(o.__indicatorY.size-i)/o.__indicatorY.size),a=o.__indicatorY.maxPos-l,"center bottom"!==o.__indicatorY.originProp&&(o.__indicatorY.indicator.style[o.__transformOriginProperty]="center bottom",o.__indicatorY.originProp="center bottom")):(a=Math.min(o.__maxScrollTop,Math.max(0,a)),e=1);var d="translate3d(0,"+a+"px, 0) scaleY("+e+")";o.__indicatorY.transformProp!==d&&(o.__indicatorY.indicator.style[o.__transformProperty]=d,o.__indicatorY.transformProp=d)}},__fadeScrollbars:function(e,t){var n=this;if(n.options.scrollbarsFade){var i="scroll-bar-fade-out";n.options.scrollbarsFade===!0&&(clearTimeout(n.__scrollbarFadeTimeout),"in"==e?(n.__indicatorX&&n.__indicatorX.indicator.classList.remove(i),n.__indicatorY&&n.__indicatorY.indicator.classList.remove(i)):n.__scrollbarFadeTimeout=setTimeout(function(){n.__indicatorX&&n.__indicatorX.indicator.classList.add(i),n.__indicatorY&&n.__indicatorY.indicator.classList.add(i)},t||n.options.scrollbarFadeDelay))}},__scrollingComplete:function(){this.options.scrollingComplete(),e.tap.removeClonedInputs(this.__container,this),this.__fadeScrollbars("out")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},getRenderFn:function(){var e,t=this,n=t.__content,i=document.documentElement.style;"MozAppearance"in i?e="gecko":"WebkitAppearance"in i?e="webkit":"string"==typeof navigator.cpuClass&&(e="trident");var r,a={trident:"ms",gecko:"Moz",webkit:"Webkit",presto:"O"}[e],o=document.createElement("div"),s=a+"Perspective",l=a+"Transform",c=a+"TransformOrigin";return t.__perspectiveProperty=l,t.__transformProperty=l,t.__transformOriginProperty=c,o.style[s]!==r?function(e,i,r,a){var o="translate3d("+-e+"px,"+-i+"px,0) scale("+r+")";o!==t.contentTransform&&(n.style[l]=o,t.contentTransform=o),t.__repositionScrollbars(),a||t.triggerScrollEvent()}:o.style[l]!==r?function(e,i,r,a){n.style[l]="translate("+-e+"px,"+-i+"px) scale("+r+")",t.__repositionScrollbars(),a||t.triggerScrollEvent()}:function(e,i,r,a){n.style.marginLeft=e?-e/r+"px":"",n.style.marginTop=i?-i/r+"px":"",n.style.zoom=r||"",t.__repositionScrollbars(),a||t.triggerScrollEvent()}},setDimensions:function(e,t,n,i,r){var a=this;(e||t||n||i)&&(e===+e&&(a.__clientWidth=e),t===+t&&(a.__clientHeight=t),n===+n&&(a.__contentWidth=n),i===+i&&(a.__contentHeight=i),a.__computeScrollMax(),a.__resizeScrollbars(),r||a.scrollTo(a.__scrollLeft,a.__scrollTop,!0,null,!0))},setPosition:function(e,t){this.__clientLeft=e||0,this.__clientTop=t||0},setSnapSize:function(e,t){this.__snapWidth=e,this.__snapHeight=t},activatePullToRefresh:function(t,n){var i=this;i.__refreshHeight=t,i.__refreshActivate=function(){e.requestAnimationFrame(n.activate)},i.__refreshDeactivate=function(){e.requestAnimationFrame(n.deactivate)},i.__refreshStart=function(){e.requestAnimationFrame(n.start)},i.__refreshShow=function(){e.requestAnimationFrame(n.show)},i.__refreshHide=function(){e.requestAnimationFrame(n.hide)},i.__refreshTail=function(){e.requestAnimationFrame(n.tail)},i.__refreshTailTime=100,i.__minSpinTime=600},triggerPullToRefresh:function(){this.__publish(this.__scrollLeft,-this.__refreshHeight,this.__zoomLevel,!0);var e=new Date;this.refreshStartTime=e.getTime(),this.__refreshStart&&this.__refreshStart()},finishPullToRefresh:function(){var e=this,t=new Date,n=0;e.refreshStartTime+e.__minSpinTime>t.getTime()&&(n=e.refreshStartTime+e.__minSpinTime-t.getTime()),setTimeout(function(){e.__refreshTail&&e.__refreshTail(),setTimeout(function(){e.__refreshActive=!1,e.__refreshDeactivate&&e.__refreshDeactivate(),e.__refreshHide&&e.__refreshHide(),e.scrollTo(e.__scrollLeft,e.__scrollTop,!0)},e.__refreshTailTime)},n)},getValues:function(){return{left:this.__scrollLeft,top:this.__scrollTop,zoom:this.__zoomLevel}},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},zoomTo:function(e,t,n,i){var r=this;if(!r.options.zooming)throw new Error("Zooming is not enabled!");r.__isDecelerating&&(me.effect.Animate.stop(r.__isDecelerating),r.__isDecelerating=!1);var a=r.__zoomLevel;null==n&&(n=r.__clientWidth/2),null==i&&(i=r.__clientHeight/2),e=Math.max(Math.min(e,r.options.maxZoom),r.options.minZoom),r.__computeScrollMax(e);var o=(n+r.__scrollLeft)*e/a-n,s=(i+r.__scrollTop)*e/a-i;o>r.__maxScrollLeft?o=r.__maxScrollLeft:0>o&&(o=0),s>r.__maxScrollTop?s=r.__maxScrollTop:0>s&&(s=0),r.__publish(o,s,e,t)},zoomBy:function(e,t,n,i){this.zoomTo(this.__zoomLevel*e,t,n,i)},scrollTo:function(e,t,n,i,r){var a=this;if(a.__isDecelerating&&(me.effect.Animate.stop(a.__isDecelerating),a.__isDecelerating=!1),null!=i&&i!==a.__zoomLevel){if(!a.options.zooming)throw new Error("Zooming is not enabled!");e*=i,t*=i,a.__computeScrollMax(i)}else i=a.__zoomLevel;a.options.scrollingX?a.options.paging?e=Math.round(e/a.__clientWidth)*a.__clientWidth:a.options.snapping&&(e=Math.round(e/a.__snapWidth)*a.__snapWidth):e=a.__scrollLeft,a.options.scrollingY?a.options.paging?t=Math.round(t/a.__clientHeight)*a.__clientHeight:a.options.snapping&&(t=Math.round(t/a.__snapHeight)*a.__snapHeight):t=a.__scrollTop,e=Math.max(Math.min(a.__maxScrollLeft,e),0),t=Math.max(Math.min(a.__maxScrollTop,t),0),e===a.__scrollLeft&&t===a.__scrollTop&&(n=!1),a.__publish(e,t,i,n,r)},scrollBy:function(e,t,n){var i=this,r=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,a=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(r+(e||0),a+(t||0),n)},doMouseZoom:function(e,t,n,i){var r=e>0?.97:1.03;return this.zoomTo(this.__zoomLevel*r,!1,n-this.__clientLeft,i-this.__clientTop)},doTouchStart:function(e,t){var n=this;n.__decStopped=!(!n.__isDecelerating&&!n.__isAnimating),n.hintResize(),t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now()),n.__interruptedAnimation=!0,n.__isDecelerating&&(me.effect.Animate.stop(n.__isDecelerating),n.__isDecelerating=!1,n.__interruptedAnimation=!0),n.__isAnimating&&(me.effect.Animate.stop(n.__isAnimating),n.__isAnimating=!1,n.__interruptedAnimation=!0);var i,r,a=1===e.length;a?(i=e[0].pageX,r=e[0].pageY):(i=Math.abs(e[0].pageX+e[1].pageX)/2,r=Math.abs(e[0].pageY+e[1].pageY)/2),n.__initialTouchLeft=i,n.__initialTouchTop=r,n.__initialTouches=e,n.__zoomLevelStart=n.__zoomLevel,n.__lastTouchLeft=i,n.__lastTouchTop=r,n.__lastTouchMove=t,n.__lastScale=1,n.__enableScrollX=!a&&n.options.scrollingX,n.__enableScrollY=!a&&n.options.scrollingY,n.__isTracking=!0,n.__didDecelerationComplete=!1,n.__isDragging=!a,n.__isSingleTouch=a,n.__positions=[]},doTouchMove:function(e,t,n){t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now());var i=this;if(i.__isTracking){var r,a;2===e.length?(r=Math.abs(e[0].pageX+e[1].pageX)/2,a=Math.abs(e[0].pageY+e[1].pageY)/2,!n&&i.options.zooming&&(n=i.__getScale(i.__initialTouches,e))):(r=e[0].pageX,a=e[0].pageY);var o=i.__positions;if(i.__isDragging){i.__decStopped=!1;var s=r-i.__lastTouchLeft,l=a-i.__lastTouchTop,c=i.__scrollLeft,d=i.__scrollTop,u=i.__zoomLevel;if(null!=n&&i.options.zooming){var p=u;if(u=u/i.__lastScale*n,u=Math.max(Math.min(u,i.options.maxZoom),i.options.minZoom),p!==u){var h=r-i.__clientLeft,f=a-i.__clientTop;c=(h+c)*u/p-h,d=(f+d)*u/p-f,i.__computeScrollMax(u)}}if(i.__enableScrollX){c-=s*i.options.speedMultiplier;var m=i.__maxScrollLeft;(c>m||0>c)&&(i.options.bouncing?c+=s/2*i.options.speedMultiplier:c=c>m?m:0)}if(i.__enableScrollY){d-=l*i.options.speedMultiplier;var g=i.__maxScrollTop;d>g||0>d?i.options.bouncing||i.__refreshHeight&&0>d?(d+=l/2*i.options.speedMultiplier,i.__enableScrollX||null==i.__refreshHeight||(0>d?(i.__refreshHidden=!1,i.__refreshShow()):(i.__refreshHide(),i.__refreshHidden=!0),!i.__refreshActive&&d<=-i.__refreshHeight?(i.__refreshActive=!0,i.__refreshActivate&&i.__refreshActivate()):i.__refreshActive&&d>-i.__refreshHeight&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate()))):d=d>g?g:0:i.__refreshHeight&&!i.__refreshHidden&&(i.__refreshHide(),i.__refreshHidden=!0)}o.length>60&&o.splice(0,30),o.push(c,d,t),i.__publish(c,d,u)}else{var v=i.options.locking?3:0,_=5,w=Math.abs(r-i.__initialTouchLeft),T=Math.abs(a-i.__initialTouchTop);i.__enableScrollX=i.options.scrollingX&&w>=v,i.__enableScrollY=i.options.scrollingY&&T>=v,o.push(i.__scrollLeft,i.__scrollTop,t),i.__isDragging=(i.__enableScrollX||i.__enableScrollY)&&(w>=_||T>=_),i.__isDragging&&(i.__interruptedAnimation=!1,i.__fadeScrollbars("in"))}i.__lastTouchLeft=r,i.__lastTouchTop=a,i.__lastTouchMove=t,i.__lastScale=n}},doTouchEnd:function(t,n){n instanceof Date&&(n=n.valueOf()),"number"!=typeof n&&(n=Date.now());var i=this;if(i.__isTracking){if(i.__isTracking=!1,i.__isDragging)if(i.__isDragging=!1,i.__isSingleTouch&&i.options.animating&&n-i.__lastTouchMove<=100){for(var r=i.__positions,a=r.length-1,o=a,s=a;s>0&&r[s]>i.__lastTouchMove-100;s-=3)o=s; +if(o!==a){var l=r[a]-r[o],c=i.__scrollLeft-r[o-2],d=i.__scrollTop-r[o-1];i.__decelerationVelocityX=c/l*(1e3/60),i.__decelerationVelocityY=d/l*(1e3/60);var u=i.options.paging||i.options.snapping?i.options.decelVelocityThresholdPaging:i.options.decelVelocityThreshold;(Math.abs(i.__decelerationVelocityX)>u||Math.abs(i.__decelerationVelocityY)>u)&&(i.__refreshActive||i.__startDeceleration(n))}else i.__scrollingComplete()}else n-i.__lastTouchMove>100&&i.__scrollingComplete();else i.__decStopped&&(t.isTapHandled=!0,i.__decStopped=!1);if(!i.__isDecelerating)if(i.__refreshActive&&i.__refreshStart){i.__publish(i.__scrollLeft,-i.__refreshHeight,i.__zoomLevel,!0);var p=new Date;i.refreshStartTime=p.getTime(),i.__refreshStart&&i.__refreshStart(),e.Platform.isAndroid()||i.__startDeceleration()}else(i.__interruptedAnimation||i.__isDragging)&&i.__scrollingComplete(),i.scrollTo(i.__scrollLeft,i.__scrollTop,!0,i.__zoomLevel),i.__refreshActive&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate());i.__positions.length=0}},__publish:function(e,t,r,a,o){var s=this,l=s.__isAnimating;if(l&&(me.effect.Animate.stop(l),s.__isAnimating=!1),a&&s.options.animating){s.__scheduledLeft=e,s.__scheduledTop=t,s.__scheduledZoom=r;var c=s.__scrollLeft,d=s.__scrollTop,u=s.__zoomLevel,p=e-c,h=t-d,f=r-u,m=function(e,t,n){n&&(s.__scrollLeft=c+p*e,s.__scrollTop=d+h*e,s.__zoomLevel=u+f*e,s.__callback&&s.__callback(s.__scrollLeft,s.__scrollTop,s.__zoomLevel,o))},g=function(e){return s.__isAnimating===e},v=function(e,t,n){t===s.__isAnimating&&(s.__isAnimating=!1),(s.__didDecelerationComplete||n)&&s.__scrollingComplete(),s.options.zooming&&s.__computeScrollMax()};s.__isAnimating=me.effect.Animate.start(m,g,v,s.options.animationDuration,l?n:i)}else s.__scheduledLeft=s.__scrollLeft=e,s.__scheduledTop=s.__scrollTop=t,s.__scheduledZoom=s.__zoomLevel=r,s.__callback&&s.__callback(e,t,r,o),s.options.zooming&&s.__computeScrollMax()},__computeScrollMax:function(e){var t=this;null==e&&(e=t.__zoomLevel),t.__maxScrollLeft=Math.max(t.__contentWidth*e-t.__clientWidth,0),t.__maxScrollTop=Math.max(t.__contentHeight*e-t.__clientHeight,0),t.__didWaitForSize||t.__maxScrollLeft||t.__maxScrollTop||(t.__didWaitForSize=!0,t.__waitForSize())},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__startDeceleration:function(){var e=this;if(e.options.paging){var t=Math.max(Math.min(e.__scrollLeft,e.__maxScrollLeft),0),n=Math.max(Math.min(e.__scrollTop,e.__maxScrollTop),0),i=e.__clientWidth,r=e.__clientHeight;e.__minDecelerationScrollLeft=Math.floor(t/i)*i,e.__minDecelerationScrollTop=Math.floor(n/r)*r,e.__maxDecelerationScrollLeft=Math.ceil(t/i)*i,e.__maxDecelerationScrollTop=Math.ceil(n/r)*r}else e.__minDecelerationScrollLeft=0,e.__minDecelerationScrollTop=0,e.__maxDecelerationScrollLeft=e.__maxScrollLeft,e.__maxDecelerationScrollTop=e.__maxScrollTop,e.__refreshActive&&(e.__minDecelerationScrollTop=-1*e.__refreshHeight);var a=function(t,n,i){e.__stepThroughDeceleration(i)};e.__minVelocityToKeepDecelerating=e.options.snapping?4:.1;var o=function(){var t=Math.abs(e.__decelerationVelocityX)>=e.__minVelocityToKeepDecelerating||Math.abs(e.__decelerationVelocityY)>=e.__minVelocityToKeepDecelerating;return t||(e.__didDecelerationComplete=!0,e.options.bouncing&&!e.__refreshActive&&e.scrollTo(Math.min(Math.max(e.__scrollLeft,0),e.__maxScrollLeft),Math.min(Math.max(e.__scrollTop,0),e.__maxScrollTop),e.__refreshActive)),t},s=function(){e.__isDecelerating=!1,e.__didDecelerationComplete&&e.__scrollingComplete(),e.options.paging&&e.scrollTo(e.__scrollLeft,e.__scrollTop,e.options.snapping)};e.__isDecelerating=me.effect.Animate.start(a,o,s)},__stepThroughDeceleration:function(e){var t=this,n=t.__scrollLeft+t.__decelerationVelocityX,i=t.__scrollTop+t.__decelerationVelocityY;if(!t.options.bouncing){var r=Math.max(Math.min(t.__maxDecelerationScrollLeft,n),t.__minDecelerationScrollLeft);r!==n&&(n=r,t.__decelerationVelocityX=0);var a=Math.max(Math.min(t.__maxDecelerationScrollTop,i),t.__minDecelerationScrollTop);a!==i&&(i=a,t.__decelerationVelocityY=0)}if(e?t.__publish(n,i,t.__zoomLevel):(t.__scrollLeft=n,t.__scrollTop=i),!t.options.paging){var o=t.options.deceleration;t.__decelerationVelocityX*=o,t.__decelerationVelocityY*=o}if(t.options.bouncing){var s=0,l=0,c=t.options.penetrationDeceleration,d=t.options.penetrationAcceleration;if(n<t.__minDecelerationScrollLeft?s=t.__minDecelerationScrollLeft-n:n>t.__maxDecelerationScrollLeft&&(s=t.__maxDecelerationScrollLeft-n),i<t.__minDecelerationScrollTop?l=t.__minDecelerationScrollTop-i:i>t.__maxDecelerationScrollTop&&(l=t.__maxDecelerationScrollTop-i),0!==s){var u=s*t.__decelerationVelocityX<=t.__minDecelerationScrollLeft;u&&(t.__decelerationVelocityX+=s*c);var p=Math.abs(t.__decelerationVelocityX)<=t.__minVelocityToKeepDecelerating;(!u||p)&&(t.__decelerationVelocityX=s*d)}if(0!==l){var h=l*t.__decelerationVelocityY<=t.__minDecelerationScrollTop;h&&(t.__decelerationVelocityY+=l*c);var f=Math.abs(t.__decelerationVelocityY)<=t.__minVelocityToKeepDecelerating;(!h||f)&&(t.__decelerationVelocityY=l*d)}}},__getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},__getScale:function(e,t){return e.length>=2&&t.length>=2?this.__getDistance(t[0],t[1])/this.__getDistance(e[0],e[1]):1}}),e.scroll={isScrolling:!1,lastTop:0}}(ionic),function(e){var t=function(){},n=function(e){};e.views.ScrollNative=e.views.View.inherit({initialize:function(t){var n=this;n.__container=n.el=t.el,n.__content=t.el.firstElementChild,n.__frozen=!1,n.isNative=!0,n.__scrollTop=n.el.scrollTop,n.__scrollLeft=n.el.scrollLeft,n.__clientHeight=n.__content.clientHeight,n.__clientWidth=n.__content.clientWidth,n.__maxScrollTop=Math.max(n.__contentHeight-n.__clientHeight,0),n.__maxScrollLeft=Math.max(n.__contentWidth-n.__clientWidth,0),(t.startY>=0||t.startX>=0)&&e.requestAnimationFrame(function(){n.el.scrollTop=t.startY||0,n.el.scrollLeft=t.startX||0,n.__scrollTop=n.el.scrollTop,n.__scrollLeft=n.el.scrollLeft}),n.options={freeze:!1,getContentWidth:function(){return Math.max(n.__content.scrollWidth,n.__content.offsetWidth)},getContentHeight:function(){return Math.max(n.__content.scrollHeight,n.__content.offsetHeight+2*n.__content.offsetTop)}};for(var i in t)n.options[i]=t[i];n.onScroll=function(){e.scroll.isScrolling||(e.scroll.isScrolling=!0),clearTimeout(n.scrollTimer),n.scrollTimer=setTimeout(function(){e.scroll.isScrolling=!1},80)},n.freeze=function(e){n.__frozen=e},n.freezeShut=function(e){n.__frozenShut=e},n.__initEventHandlers()},__callback:function(){n("__callback")},zoomTo:function(){n("zoomTo")},zoomBy:function(){n("zoomBy")},activatePullToRefresh:function(){n("activatePullToRefresh")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},run:function(){this.resize()},getValues:function(){var e=this;return e.update(),{left:e.__scrollLeft,top:e.__scrollTop,zoom:1}},update:function(){var e=this;e.__scrollLeft=e.el.scrollLeft,e.__scrollTop=e.el.scrollTop},setDimensions:function(e,t,n,i){var r=this;(e||t||n||i)&&(e===+e&&(r.__clientWidth=e),t===+t&&(r.__clientHeight=t),n===+n&&(r.__contentWidth=n),i===+i&&(r.__contentHeight=i),r.__computeScrollMax())},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},scrollBy:function(e,t,n){var i=this;i.update();var r=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,a=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(r+(e||0),a+(t||0),n)},scrollTo:function(t,n,i){function r(t,n){function i(e){return--e*e*e+1}function r(){var p=Date.now(),h=Math.min(1,(p-l)/c),f=i(h);d!=t&&(a.el.scrollTop=parseInt(f*(t-d)+d,10)),u!=n&&(a.el.scrollLeft=parseInt(f*(n-u)+u,10)),1>h?e.requestAnimationFrame(r):(e.tap.removeClonedInputs(a.__container,a),a.el.style.overflowX=o,a.el.style.overflowY=s,a.resize())}var l=Date.now(),c=250,d=a.el.scrollTop,u=a.el.scrollLeft;return d===t&&u===n?(a.el.style.overflowX=o,a.el.style.overflowY=s,void a.resize()):void e.requestAnimationFrame(r)}var a=this;if(!i)return a.el.scrollTop=n,a.el.scrollLeft=t,void a.resize();var o=a.el.style.overflowX,s=a.el.style.overflowY;clearTimeout(a.__scrollToCleanupTimeout),a.__scrollToCleanupTimeout=setTimeout(function(){a.el.style.overflowX=o,a.el.style.overflowY=s},500),a.el.style.overflowY="hidden",a.el.style.overflowX="hidden",r(n,t)},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__computeScrollMax:function(){var e=this;e.__maxScrollLeft=Math.max(e.__contentWidth-e.__clientWidth,0),e.__maxScrollTop=Math.max(e.__contentHeight-e.__clientHeight,0),e.__didWaitForSize||e.__maxScrollLeft||e.__maxScrollTop||(e.__didWaitForSize=!0,e.__waitForSize())},__initEventHandlers:function(){var t,n,i=this,r=i.__container;i.scrollChildIntoView=function(a){var o=r.getBoundingClientRect();i.__originalContainerHeight||(i.__originalContainerHeight=o.height),t=i.__originalContainerHeight;var s=i.isShrunkForKeyboard,l=r.parentNode.classList.contains("modal"),c=r.parentNode.classList.contains("popover"),d=l&&window.innerWidth>=680,u=n&&n!==a.detail.keyboardHeight;(!s||u)&&(!c&&(e.Platform.isIOS()||e.Platform.isFullScreen||d)&&e.requestAnimationFrame(function(){t=Math.max(0,Math.min(i.__originalContainerHeight,i.__originalContainerHeight-(a.detail.keyboardHeight-43))),r.style.height=t+"px",r.classList.add("keyboard-up"),i.resize()}),i.isShrunkForKeyboard=!0),n=a.detail.keyboardHeight,a.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){var t=e.DomUtil.getOffsetTop(a.detail.target);setTimeout(function(){e.Platform.isIOS()&&e.tap.cloneFocusedInput(r,i),i.scrollTo(0,t-(o.top+100),!0),i.onScroll()},32)}),a.stopPropagation()},i.resetScrollView=function(){i.isShrunkForKeyboard&&(i.isShrunkForKeyboard=!1,r.style.height="",i.__originalContainerHeight=r.getBoundingClientRect().height,e.Platform.isIOS()&&e.requestAnimationFrame(function(){r.classList.remove("keyboard-up")})),i.resize()},i.handleTouchMove=function(e){return i.__frozenShut?(e.preventDefault(),e.stopPropagation(),!1):void 0},r.addEventListener("scroll",i.onScroll),r.addEventListener("scrollChildIntoView",i.scrollChildIntoView),r.addEventListener(e.EVENTS.touchstart,i.handleTouchMove),r.addEventListener(e.EVENTS.touchmove,i.handleTouchMove),document.addEventListener("resetScrollView",i.resetScrollView)},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("resetScrollView",n.resetScrollView),i.removeEventListener("scroll",n.onScroll),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),i.removeEventListener("resetScrollView",n.resetScrollView),i.removeEventListener(e.EVENTS.touchstart,n.handleTouchMove),i.removeEventListener(e.EVENTS.touchmove,n.handleTouchMove),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.resize=n.scrollTo=n.onScroll=n.resetScrollView=t,n.scrollChildIntoView=t,i=null}})}(ionic),function(e){"use strict";var t="item",n="item-content",i="item-sliding",r="item-options",a="item-placeholder",o="item-reordering",s="item-reorder",l=function(){};l.prototype={start:function(){},drag:function(){},end:function(){},isSameItem:function(){return!1}};var c=function(e){this.dragThresholdX=e.dragThresholdX||10,this.el=e.el,this.item=e.item,this.canSwipe=e.canSwipe};c.prototype=new l,c.prototype.start=function(a){var o,s,l,c;this.canSwipe()&&(o=a.target.classList.contains(n)?a.target:a.target.classList.contains(t)?a.target.querySelector("."+n):e.DomUtil.getParentWithClass(a.target,n),o&&(o.classList.remove(i),l=parseFloat(o.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])||0,s=o.parentNode.querySelector("."+r),s&&(s.classList.remove("invisible"),c=s.offsetWidth,this._currentDrag={buttons:s,buttonsWidth:c,content:o,startOffsetX:l})))},c.prototype.isSameItem=function(e){return e._lastDrag&&this._currentDrag?this._currentDrag.content==e._lastDrag.content:!1},c.prototype.clean=function(t){function n(){i.buttons&&i.buttons.classList.add("invisible")}var i=this._lastDrag;i&&i.content&&(i.content.style[e.CSS.TRANSITION]="",i.content.style[e.CSS.TRANSFORM]="",t?(i.content.style[e.CSS.TRANSITION]="none",n(),e.requestAnimationFrame(function(){i.content.style[e.CSS.TRANSITION]=""})):e.requestAnimationFrame(function(){setTimeout(n,250)}))},c.prototype.drag=e.animationFrameThrottle(function(t){var n;if(this._currentDrag&&(!this._isDragging&&(Math.abs(t.gesture.deltaX)>this.dragThresholdX||Math.abs(this._currentDrag.startOffsetX)>0)&&(this._isDragging=!0),this._isDragging)){n=this._currentDrag.buttonsWidth;var i=Math.min(0,this._currentDrag.startOffsetX+t.gesture.deltaX);-n>i&&(i=Math.min(-n,-n+.4*(t.gesture.deltaX+n))),this._currentDrag.content.$$ionicOptionsOpen=0!==i,this._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+i+"px, 0, 0)",this._currentDrag.content.style[e.CSS.TRANSITION]="none"}}),c.prototype.end=function(t,n){var i=this;if(!i._currentDrag)return void(n&&n());var r=-i._currentDrag.buttonsWidth;t.gesture.deltaX>-(i._currentDrag.buttonsWidth/2)&&("left"==t.gesture.direction&&Math.abs(t.gesture.velocityX)<.3?r=0:"right"==t.gesture.direction&&(r=0)),e.requestAnimationFrame(function(){if(0===r){i._currentDrag.content.style[e.CSS.TRANSFORM]="";var t=i._currentDrag.buttons;setTimeout(function(){t&&t.classList.add("invisible")},250)}else i._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+r+"px,0,0)";i._currentDrag.content.style[e.CSS.TRANSITION]="",i._lastDrag||(i._lastDrag={}),e.extend(i._lastDrag,i._currentDrag),i._currentDrag&&(i._currentDrag.buttons=null,i._currentDrag.content=null),i._currentDrag=null,n&&n()})};var d=function(e){var t=this;if(t.dragThresholdY=e.dragThresholdY||0,t.onReorder=e.onReorder,t.listEl=e.listEl,t.el=t.item=e.el,t.scrollEl=e.scrollEl,t.scrollView=e.scrollView,t.listElTrueTop=0,t.listEl.offsetParent){var n=t.listEl;do t.listElTrueTop+=n.offsetTop,n=n.offsetParent;while(n)}};d.prototype=new l,d.prototype._moveElement=function(t){var n=t.gesture.center.pageY+this.scrollView.getValues().top-this._currentDrag.elementHeight/2-this.listElTrueTop;this.el.style[e.CSS.TRANSFORM]="translate3d(0, "+n+"px, 0)"},d.prototype.deregister=function(){this.listEl=this.el=this.scrollEl=this.scrollView=null},d.prototype.start=function(t){var n=e.DomUtil.getChildIndex(this.el,this.el.nodeName.toLowerCase()),i=this.el.scrollHeight,r=this.el.cloneNode(!0);r.classList.add(a),this.el.parentNode.insertBefore(r,this.el),this.el.classList.add(o),this._currentDrag={elementHeight:i,startIndex:n,placeholder:r,scrollHeight:scroll,list:r.parentNode},this._moveElement(t)},d.prototype.drag=e.animationFrameThrottle(function(t){var n=this;if(this._currentDrag){var i=0,r=t.gesture.center.pageY,a=this.listElTrueTop;if(this.scrollView){var o=this.scrollView.__container;i=this.scrollView.getValues().top;var s=o.offsetTop,l=s-r+this._currentDrag.elementHeight/2,c=r+this._currentDrag.elementHeight/2-s-o.offsetHeight;t.gesture.deltaY<0&&l>0&&i>0&&(this.scrollView.scrollBy(null,-l),e.requestAnimationFrame(function(){n.drag(t)})),t.gesture.deltaY>0&&c>0&&i<this.scrollView.getScrollMax().top&&(this.scrollView.scrollBy(null,c),e.requestAnimationFrame(function(){n.drag(t)}))}!this._isDragging&&Math.abs(t.gesture.deltaY)>this.dragThresholdY&&(this._isDragging=!0),this._isDragging&&(this._moveElement(t),this._currentDrag.currentY=i+r-a)}}),d.prototype._getReorderIndex=function(){for(var e,t=this,n=Array.prototype.slice.call(t._currentDrag.placeholder.parentNode.children).filter(function(e){return e.nodeName===t.el.nodeName&&e!==t.el}),i=t._currentDrag.currentY,r=0,a=n.length;a>r;r++)if(e=n[r],r===a-1){if(i>e.offsetTop)return r}else if(0===r){if(i<e.offsetTop+e.offsetHeight)return r}else if(i>e.offsetTop-e.offsetHeight/2&&i<e.offsetTop+e.offsetHeight)return r;return t._currentDrag.startIndex},d.prototype.end=function(t,n){if(!this._currentDrag)return void(n&&n());var i=this._currentDrag.placeholder,r=this._getReorderIndex();this.el.classList.remove(o),this.el.style[e.CSS.TRANSFORM]="",i.parentNode.insertBefore(this.el,i),i.parentNode.removeChild(i),this.onReorder&&this.onReorder(this.el,this._currentDrag.startIndex,r),this._currentDrag={placeholder:null,content:null},this._currentDrag=null,n&&n()},e.views.ListView=e.views.View.inherit({initialize:function(t){var n=this;t=e.extend({onReorder:function(){},virtualRemoveThreshold:-200,virtualAddThreshold:200,canSwipe:function(){return!0}},t),e.extend(n,t),!n.itemHeight&&n.listEl&&(n.itemHeight=n.listEl.children[0]&&parseInt(n.listEl.children[0].style.height,10)),n.onRefresh=t.onRefresh||function(){},n.onRefreshOpening=t.onRefreshOpening||function(){},n.onRefreshHolding=t.onRefreshHolding||function(){};var i={};e.DomUtil.getParentOrSelfWithClass(n.el,"overflow-scroll")&&(i.prevent_default_directions=["left","right"]),window.ionic.onGesture("release",function(e){n._handleEndDrag(e)},n.el,i),window.ionic.onGesture("drag",function(e){n._handleDrag(e)},n.el,i),n._initDrag()},deregister:function(){this.el=this.listEl=this.scrollEl=this.scrollView=null,this.isScrollFreeze&&self.scrollView.freeze(!1)},stopRefreshing:function(){var e=this.el.querySelector(".list-refresher");e.style.height="0"},didScroll:function(e){var t=this;if(t.isVirtual){var n=t.itemHeight,i=e.target.scrollHeight,r=t.el.parentNode.offsetHeight,a=Math.max(0,e.scrollTop+t.virtualRemoveThreshold),o=Math.min(i,Math.abs(e.scrollTop)+r+t.virtualAddThreshold),s=parseInt(Math.abs(a/n),10),l=parseInt(Math.abs(o/n),10);t._virtualItemsToRemove=Array.prototype.slice.call(t.listEl.children,0,s),t.renderViewport&&t.renderViewport(a,o,s,l)}},didStopScrolling:function(){if(this.isVirtual)for(var e=0;e<this._virtualItemsToRemove.length;e++)this.didHideItem&&this.didHideItem(e)},clearDragEffects:function(e){this._lastDragOp&&(this._lastDragOp.clean&&this._lastDragOp.clean(e),this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=null)},_initDrag:function(){this._lastDragOp&&this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=this._dragOp,this._dragOp=null},_getItem:function(e){for(;e;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},_startDrag:function(t){var n=this;n._isDragging=!1;var i,r=n._lastDragOp;n._didDragUpOrDown&&r instanceof c&&r.clean&&r.clean(),!e.DomUtil.getParentOrSelfWithClass(t.target,s)||"up"!=t.gesture.direction&&"down"!=t.gesture.direction?!n._didDragUpOrDown&&("left"==t.gesture.direction||"right"==t.gesture.direction)&&Math.abs(t.gesture.deltaX)>5&&(i=n._getItem(t.target),i&&i.querySelector(".item-options")&&(n._dragOp=new c({el:n.el,item:i,canSwipe:n.canSwipe}),n._dragOp.start(t),t.preventDefault(),n.isScrollFreeze=n.scrollView.freeze(!0))):(i=n._getItem(t.target),i&&(n._dragOp=new d({listEl:n.el,el:i,scrollEl:n.scrollEl,scrollView:n.scrollView,onReorder:function(e,t,i){n.onReorder&&n.onReorder(e,t,i)}}),n._dragOp.start(t),t.preventDefault())),r&&n._dragOp&&!n._dragOp.isSameItem(r)&&t.defaultPrevented&&r.clean&&r.clean()},_handleEndDrag:function(e){var t=this;t.scrollView&&(t.isScrollFreeze=t.scrollView.freeze(!1)),t._didDragUpOrDown=!1,t._dragOp&&t._dragOp.end(e,function(){t._initDrag()})},_handleDrag:function(e){var t=this;Math.abs(e.gesture.deltaY)>5&&(t._didDragUpOrDown=!0),t.isDragging||t._dragOp||t._startDrag(e),t._dragOp&&(e.gesture.srcEvent.preventDefault(),t._dragOp.drag(e))}})}(ionic),function(e){"use strict";e.views.Modal=e.views.View.inherit({initialize:function(t){t=e.extend({focusFirstInput:!1,unfocusOnHide:!0,focusFirstDelay:600,backdropClickToClose:!0,hardwareBackButtonClose:!0},t),e.extend(this,t),this.el=t.el},show:function(){var e=this;e.focusFirstInput&&window.setTimeout(function(){var t=e.el.querySelector("input, textarea");t&&t.focus&&t.focus()},e.focusFirstDelay)},hide:function(){if(this.unfocusOnHide){var e=this.el.querySelectorAll("input, textarea");window.setTimeout(function(){for(var t=0;t<e.length;t++)e[t].blur&&e[t].blur()})}}})}(ionic),function(e){"use strict";e.views.SideMenu=e.views.View.inherit({initialize:function(e){this.el=e.el,this.isEnabled="undefined"==typeof e.isEnabled?!0:e.isEnabled,this.setWidth(e.width)},getFullWidth:function(){return this.width},setWidth:function(e){this.width=e,this.el.style.width=e+"px"},setIsEnabled:function(e){this.isEnabled=e},bringUp:function(){"0"!==this.el.style.zIndex&&(this.el.style.zIndex="0")},pushDown:function(){"-1"!==this.el.style.zIndex&&(this.el.style.zIndex="-1")}}),e.views.SideMenuContent=e.views.View.inherit({initialize:function(t){e.extend(this,{animationClass:"menu-animated",onDrag:function(){},onEndDrag:function(){}},t),e.onGesture("drag",e.proxy(this._onDrag,this),this.el),e.onGesture("release",e.proxy(this._onEndDrag,this),this.el)},_onDrag:function(e){this.onDrag&&this.onDrag(e)},_onEndDrag:function(e){this.onEndDrag&&this.onEndDrag(e)},disableAnimation:function(){this.el.classList.remove(this.animationClass)},enableAnimation:function(){this.el.classList.add(this.animationClass)},getTranslateX:function(){return parseFloat(this.el.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])},setTranslateX:e.animationFrameThrottle(function(t){this.el.style[e.CSS.TRANSFORM]="translate3d("+t+"px, 0, 0)"})})}(ionic),function(e){"use strict";e.views.Slider=e.views.View.inherit({initialize:function(e){function t(){if(b.offsetWidth){S=D.children,x=S.length,S.length<2&&(e.continuous=!1),T.transitions&&e.continuous&&S.length<3&&(D.appendChild(S[0].cloneNode(!0)),D.appendChild(D.children[1].cloneNode(!0)),S=D.children),y=new Array(S.length),E=b.offsetWidth||b.getBoundingClientRect().width,D.style.width=S.length*E+"px";for(var t=S.length;t--;){var n=S[t];n.style.width=E+"px",n.setAttribute("data-index",t),T.transitions&&(n.style.left=t*-E+"px",o(t,M>t?-E:t>M?E:0,0))}e.continuous&&T.transitions&&(o(r(M-1),-E,0),o(r(M+1),E,0)),T.transitions||(D.style.left=M*-E+"px"),b.style.visibility="visible",e.slidesChanged&&e.slidesChanged()}}function n(t){e.continuous?a(M-1,t):M&&a(M-1,t)}function i(t){e.continuous?a(M+1,t):M<S.length-1&&a(M+1,t)}function r(e){return(S.length+e%S.length)%S.length}function a(t,n){if(M!=t){if(!S)return void(M=t);if(T.transitions){var i=Math.abs(M-t)/(M-t);if(e.continuous){var a=i;i=-y[r(t)]/E,i!==a&&(t=-i*S.length+t)}for(var s=Math.abs(M-t)-1;s--;)o(r((t>M?t:M)-s-1),E*i,0);t=r(t),o(M,E*i,n||L),o(t,0,n||L),e.continuous&&o(r(t-i),-(E*i),0)}else t=r(t),l(M*-E,t*-E,n||L);M=t,w(e.callback&&e.callback(M,S[M]))}}function o(e,t,n){s(e,t,n),y[e]=t}function s(e,t,n){var i=S[e],r=i&&i.style;r&&(r.webkitTransitionDuration=r.MozTransitionDuration=r.msTransitionDuration=r.OTransitionDuration=r.transitionDuration=n+"ms",r.webkitTransform="translate("+t+"px,0)translateZ(0)",r.msTransform=r.MozTransform=r.OTransform="translateX("+t+"px)")}function l(t,n,i){if(!i)return void(D.style.left=n+"px");var r=+new Date,a=setInterval(function(){var o=+new Date-r;return o>i?(D.style.left=n+"px",I&&c(),e.transitionEnd&&e.transitionEnd.call(event,M,S[M]),void clearInterval(a)):void(D.style.left=(n-t)*(Math.floor(o/i*100)/100)+t+"px")},4)}function c(){C=setTimeout(i,I)}function d(){I=e.auto||0,clearTimeout(C)}var u,p,h,f=this;window.navigator.pointerEnabled?(u="pointerdown",p="pointermove",h="pointerup"):window.navigator.msPointerEnabled?(u="MSPointerDown",p="MSPointerMove",h="MSPointerUp"):(u="touchstart",p="touchmove",h="touchend");var m="mousedown",g="mousemove",v="mouseup",_=function(){},w=function(e){setTimeout(e||_,0)},T={addEventListener:!!window.addEventListener,transitions:function(e){var t=["transitionProperty","WebkitTransition","MozTransition","OTransition","msTransition"];for(var n in t)if(void 0!==e.style[t[n]])return!0;return!1}(document.createElement("swipe"))},b=e.el;if(b){var S,y,E,x,D=b.children[0];e=e||{};var M=parseInt(e.startSlide,10)||0,L=e.speed||300;e.continuous=void 0!==e.continuous?e.continuous:!0;var C,P,I=e.auto||0,k={},N={},z={handleEvent:function(n){switch(!n.touches&&n.pageX&&n.pageY&&(n.touches=[{pageX:n.pageX,pageY:n.pageY}]),n.type){case u:this.start(n);break;case m:this.start(n);break;case p:this.touchmove(n);break;case g:this.touchmove(n);break;case h:w(this.end(n));break;case v:w(this.end(n));break;case"webkitTransitionEnd":case"msTransitionEnd":case"oTransitionEnd":case"otransitionend":case"transitionend":w(this.transitionEnd(n));break;case"resize":w(t)}e.stopPropagation&&n.stopPropagation()},start:function(e){if(e.touches){var t=e.touches[0];k={x:t.pageX,y:t.pageY,time:+new Date},P=void 0,N={},D.addEventListener(p,this,!1),D.addEventListener(g,this,!1),D.addEventListener(h,this,!1),D.addEventListener(v,this,!1),document.addEventListener(h,this,!1),document.addEventListener(v,this,!1)}},touchmove:function(t){if(!(!t.touches||t.touches.length>1||t.scale&&1!==t.scale||f.slideIsDisabled)){e.disableScroll&&t.preventDefault();var n=t.touches[0];N={x:n.pageX-k.x,y:n.pageY-k.y},"undefined"==typeof P&&(P=!!(P||Math.abs(N.x)<Math.abs(N.y))),P||(t.preventDefault(),d(),e.continuous?(s(r(M-1),N.x+y[r(M-1)],0),s(M,N.x+y[M],0),s(r(M+1),N.x+y[r(M+1)],0)):(e.bouncing?N.x=N.x/(!M&&N.x>0||M==S.length-1&&N.x<0?Math.abs(N.x)/E+1:1):(E*M-N.x<0&&(N.x=Math.min(N.x,E*M)),Math.abs(N.x)>E*(S.length-M-1)&&(N.x=Math.max(-E*(S.length-M-1),N.x))),s(M-1,N.x+y[M-1],0),s(M,N.x+y[M],0),s(M+1,N.x+y[M+1],0)),e.onDrag&&e.onDrag())}},end:function(){var t=+new Date-k.time,n=Number(t)<250&&Math.abs(N.x)>20||Math.abs(N.x)>E/2,i=!M&&N.x>0||M==S.length-1&&N.x<0;e.continuous&&(i=!1);var a=N.x<0;P||(n&&!i?(a?(e.continuous?(o(r(M-1),-E,0),o(r(M+2),E,0)):o(M-1,-E,0),o(M,y[M]-E,L),o(r(M+1),y[r(M+1)]-E,L),M=r(M+1)):(e.continuous?(o(r(M+1),E,0),o(r(M-2),-E,0)):o(M+1,E,0),o(M,y[M]+E,L),o(r(M-1),y[r(M-1)]+E,L),M=r(M-1)),e.callback&&e.callback(M,S[M])):e.continuous?(o(r(M-1),-E,L),o(M,0,L),o(r(M+1),E,L)):(o(M-1,-E,L),o(M,0,L),o(M+1,E,L))),D.removeEventListener(p,z,!1),D.removeEventListener(g,z,!1),D.removeEventListener(h,z,!1),D.removeEventListener(v,z,!1),document.removeEventListener(h,z,!1),document.removeEventListener(v,z,!1),e.onDragEnd&&e.onDragEnd()},transitionEnd:function(t){parseInt(t.target.getAttribute("data-index"),10)==M&&(I&&c(),e.transitionEnd&&e.transitionEnd.call(t,M,S[M]))}};this.update=function(){setTimeout(t)},this.setup=function(){t()},this.loop=function(t){return arguments.length&&(e.continuous=!!t),e.continuous},this.enableSlide=function(e){return arguments.length&&(this.slideIsDisabled=!e),!this.slideIsDisabled},this.slide=this.select=function(e,t){d(),a(e,t)},this.prev=this.previous=function(){d(),n()},this.next=function(){d(),i()},this.stop=function(){d()},this.start=function(){c()},this.autoPlay=function(e){!I||0>I?d():(I=e,c())},this.currentIndex=this.selected=function(){return M},this.slidesCount=this.count=function(){return x},this.kill=function(){d(),D.style.width="",D.style.left="",S&&(S=[]),T.addEventListener?(D.removeEventListener(u,z,!1),D.removeEventListener(m,z,!1),D.removeEventListener("webkitTransitionEnd",z,!1),D.removeEventListener("msTransitionEnd",z,!1),D.removeEventListener("oTransitionEnd",z,!1),D.removeEventListener("otransitionend",z,!1),D.removeEventListener("transitionend",z,!1),window.removeEventListener("resize",z,!1)):window.onresize=null},this.load=function(){t(),I&&c(),T.addEventListener?(D.addEventListener(u,z,!1),D.addEventListener(m,z,!1),T.transitions&&(D.addEventListener("webkitTransitionEnd",z,!1),D.addEventListener("msTransitionEnd",z,!1),D.addEventListener("oTransitionEnd",z,!1),D.addEventListener("otransitionend",z,!1),D.addEventListener("transitionend",z,!1)),window.addEventListener("resize",z,!1)):window.onresize=function(){t()}}}}})}(ionic),function(){"use strict";function e(e){e.fn.swiper=function(t){var i;return e(this).each(function(){var e=new n(this,t);i||(i=e)}),i}}var t,n=function(e,r,a,o){function s(){return"horizontal"===y.params.direction}function l(e){return Math.floor(e)}function c(){y.autoplayTimeoutId=setTimeout(function(){y.params.loop?(y.fixLoop(),y._slideNext()):y.isEnd?r.autoplayStopOnLast?y.stopAutoplay():y._slideTo(0):y._slideNext()},y.params.autoplay)}function d(e,n){var i=t(e.target);if(!i.is(n))if("string"==typeof n)i=i.parents(n);else if(n.nodeType){var r;return i.parents().each(function(e,t){t===n&&(r=n)}),r?n:void 0}return 0===i.length?void 0:i[0]}function u(e,t){t=t||{};var n=window.MutationObserver||window.WebkitMutationObserver,i=new n(function(e){e.forEach(function(e){y.onResize(!0),y.emit("onObserverUpdate",y,e)})});i.observe(e,{attributes:"undefined"==typeof t.attributes?!0:t.attributes,childList:"undefined"==typeof t.childList?!0:t.childList,characterData:"undefined"==typeof t.characterData?!0:t.characterData}),y.observers.push(i)}function p(e){e.originalEvent&&(e=e.originalEvent);var t=e.keyCode||e.charCode;if(!y.params.allowSwipeToNext&&(s()&&39===t||!s()&&40===t))return!1;if(!y.params.allowSwipeToPrev&&(s()&&37===t||!s()&&38===t))return!1;if(!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey||document.activeElement&&document.activeElement.nodeName&&("input"===document.activeElement.nodeName.toLowerCase()||"textarea"===document.activeElement.nodeName.toLowerCase()))){if(37===t||39===t||38===t||40===t){var n=!1;if(y.container.parents(".swiper-slide").length>0&&0===y.container.parents(".swiper-slide-active").length)return;var i={left:window.pageXOffset,top:window.pageYOffset},r=window.innerWidth,a=window.innerHeight,o=y.container.offset();y.rtl&&(o.left=o.left-y.container[0].scrollLeft);for(var l=[[o.left,o.top],[o.left+y.width,o.top],[o.left,o.top+y.height],[o.left+y.width,o.top+y.height]],c=0;c<l.length;c++){var d=l[c];d[0]>=i.left&&d[0]<=i.left+r&&d[1]>=i.top&&d[1]<=i.top+a&&(n=!0)}if(!n)return}s()?((37===t||39===t)&&(e.preventDefault?e.preventDefault():e.returnValue=!1),(39===t&&!y.rtl||37===t&&y.rtl)&&y.slideNext(),(37===t&&!y.rtl||39===t&&y.rtl)&&y.slidePrev()):((38===t||40===t)&&(e.preventDefault?e.preventDefault():e.returnValue=!1),40===t&&y.slideNext(),38===t&&y.slidePrev())}}function h(e){e.originalEvent&&(e=e.originalEvent);var t=y.mousewheel.event,n=0,i=y.rtl?-1:1;if(e.detail)n=-e.detail;else if("mousewheel"===t)if(y.params.mousewheelForceToAxis)if(s()){if(!(Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)))return;n=e.wheelDeltaX*i}else{if(!(Math.abs(e.wheelDeltaY)>Math.abs(e.wheelDeltaX)))return;n=e.wheelDeltaY}else n=Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)?-e.wheelDeltaX*i:-e.wheelDeltaY;else if("DOMMouseScroll"===t)n=-e.detail;else if("wheel"===t)if(y.params.mousewheelForceToAxis)if(s()){if(!(Math.abs(e.deltaX)>Math.abs(e.deltaY)))return;n=-e.deltaX*i}else{if(!(Math.abs(e.deltaY)>Math.abs(e.deltaX)))return;n=-e.deltaY}else n=Math.abs(e.deltaX)>Math.abs(e.deltaY)?-e.deltaX*i:-e.deltaY;if(0!==n){if(y.params.mousewheelInvert&&(n=-n),y.params.freeMode){var r=y.getWrapperTranslate()+n*y.params.mousewheelSensitivity,a=y.isBeginning,o=y.isEnd;if(r>=y.minTranslate()&&(r=y.minTranslate()),r<=y.maxTranslate()&&(r=y.maxTranslate()),y.setWrapperTransition(0),y.setWrapperTranslate(r),y.updateProgress(),y.updateActiveIndex(),(!a&&y.isBeginning||!o&&y.isEnd)&&y.updateClasses(),y.params.freeModeSticky&&(clearTimeout(y.mousewheel.timeout),y.mousewheel.timeout=setTimeout(function(){y.slideReset()},300)),0===r||r===y.maxTranslate())return}else{if((new window.Date).getTime()-y.mousewheel.lastScrollTime>60)if(0>n)if(y.isEnd&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slideNext();else if(y.isBeginning&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slidePrev();y.mousewheel.lastScrollTime=(new window.Date).getTime()}return y.params.autoplay&&y.stopAutoplay(),e.preventDefault?e.preventDefault():e.returnValue=!1,!1}}function f(e,n){e=t(e);var i,r,a,o=y.rtl?-1:1;i=e.attr("data-swiper-parallax")||"0",r=e.attr("data-swiper-parallax-x"), +a=e.attr("data-swiper-parallax-y"),r||a?(r=r||"0",a=a||"0"):s()?(r=i,a="0"):(a=i,r="0"),r=r.indexOf("%")>=0?parseInt(r,10)*n*o+"%":r*n*o+"px",a=a.indexOf("%")>=0?parseInt(a,10)*n+"%":a*n+"px",e.transform("translate3d("+r+", "+a+",0px)")}function m(e){return 0!==e.indexOf("on")&&(e=e[0]!==e[0].toUpperCase()?"on"+e[0].toUpperCase()+e.substring(1):"on"+e),e}if(!(this instanceof n))return new n(e,r);var g={direction:"horizontal",touchEventsTarget:"container",initialSlide:0,speed:300,autoplay:!1,autoplayDisableOnInteraction:!0,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},cube:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fade:{crossFade:!1},parallax:!1,scrollbar:null,scrollbarHide:!0,scrollbarDraggable:!1,scrollbarSnapOnRelease:!1,keyboardControl:!1,mousewheelControl:!1,mousewheelReleaseOnEdges:!1,mousewheelInvert:!1,mousewheelForceToAxis:!1,mousewheelSensitivity:1,hashnav:!1,breakpoints:void 0,spaceBetween:0,slidesPerView:1,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,onlyExternal:!1,threshold:0,touchMoveStopPropagation:!0,pagination:null,paginationElement:"span",paginationClickable:!1,paginationHide:!1,paginationBulletRender:null,resistance:!0,resistanceRatio:.85,nextButton:null,prevButton:null,watchSlidesProgress:!1,watchSlidesVisibility:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,lazyLoading:!1,lazyLoadingInPrevNext:!1,lazyLoadingOnTransitionStart:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,control:void 0,controlInverse:!1,controlBy:"slide",allowSwipeToPrev:!0,allowSwipeToNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",slideClass:"swiper-slide",slideActiveClass:"swiper-slide-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slidePrevClass:"swiper-slide-prev",wrapperClass:"swiper-wrapper",bulletClass:"swiper-pagination-bullet",bulletActiveClass:"swiper-pagination-bullet-active",buttonDisabledClass:"swiper-button-disabled",paginationHiddenClass:"swiper-pagination-hidden",observer:!1,observeParents:!1,a11y:!1,prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",runCallbacksOnInit:!0},v=r&&r.virtualTranslate;r=r||{};var _={};for(var w in r)if("object"!=typeof r[w]||(r[w].nodeType||r[w]===window||r[w]===document||"undefined"!=typeof i&&r[w]instanceof i||"undefined"!=typeof jQuery&&r[w]instanceof jQuery))_[w]=r[w];else{_[w]={};for(var T in r[w])_[w][T]=r[w][T]}for(var b in g)if("undefined"==typeof r[b])r[b]=g[b];else if("object"==typeof r[b])for(var S in g[b])"undefined"==typeof r[b][S]&&(r[b][S]=g[b][S]);var y=this;if(y.params=r,y.originalParams=_,y.classNames=[],"undefined"!=typeof t&&"undefined"!=typeof i&&(t=i),("undefined"!=typeof t||(t="undefined"==typeof i?window.Dom7||window.Zepto||window.jQuery:i))&&(y.$=t,y.currentBreakpoint=void 0,y.getActiveBreakpoint=function(){if(!y.params.breakpoints)return!1;var e,t=!1,n=[];for(e in y.params.breakpoints)y.params.breakpoints.hasOwnProperty(e)&&n.push(e);n.sort(function(e,t){return parseInt(e,10)>parseInt(t,10)});for(var i=0;i<n.length;i++)e=n[i],e>=window.innerWidth&&!t&&(t=e);return t||"max"},y.setBreakpoint=function(){var e=y.getActiveBreakpoint();if(e&&y.currentBreakpoint!==e){var t=e in y.params.breakpoints?y.params.breakpoints[e]:y.originalParams;for(var n in t)y.params[n]=t[n];y.currentBreakpoint=e}},y.params.breakpoints&&y.setBreakpoint(),y.container=t(e),0!==y.container.length)){if(y.container.length>1)return void y.container.each(function(){new n(this,r)});y.container[0].swiper=y,y.container.data("swiper",y),y.classNames.push("swiper-container-"+y.params.direction),y.params.freeMode&&y.classNames.push("swiper-container-free-mode"),y.support.flexbox||(y.classNames.push("swiper-container-no-flexbox"),y.params.slidesPerColumn=1),y.params.autoHeight&&y.classNames.push("swiper-container-autoheight"),(y.params.parallax||y.params.watchSlidesVisibility)&&(y.params.watchSlidesProgress=!0),["cube","coverflow"].indexOf(y.params.effect)>=0&&(y.support.transforms3d?(y.params.watchSlidesProgress=!0,y.classNames.push("swiper-container-3d")):y.params.effect="slide"),"slide"!==y.params.effect&&y.classNames.push("swiper-container-"+y.params.effect),"cube"===y.params.effect&&(y.params.resistanceRatio=0,y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.centeredSlides=!1,y.params.spaceBetween=0,y.params.virtualTranslate=!0,y.params.setWrapperSize=!1),"fade"===y.params.effect&&(y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.watchSlidesProgress=!0,y.params.spaceBetween=0,"undefined"==typeof v&&(y.params.virtualTranslate=!0)),y.params.grabCursor&&y.support.touch&&(y.params.grabCursor=!1),y.wrapper=y.container.children("."+y.params.wrapperClass),y.params.pagination&&(y.paginationContainer=t(y.params.pagination),y.params.paginationClickable&&y.paginationContainer.addClass("swiper-pagination-clickable")),y.rtl=s()&&("rtl"===y.container[0].dir.toLowerCase()||"rtl"===y.container.css("direction")),y.rtl&&y.classNames.push("swiper-container-rtl"),y.rtl&&(y.wrongRTL="-webkit-box"===y.wrapper.css("display")),y.params.slidesPerColumn>1&&y.classNames.push("swiper-container-multirow"),y.device.android&&y.classNames.push("swiper-container-android"),y.container.addClass(y.classNames.join(" ")),y.translate=0,y.progress=0,y.velocity=0,y.lockSwipeToNext=function(){y.params.allowSwipeToNext=!1},y.lockSwipeToPrev=function(){y.params.allowSwipeToPrev=!1},y.lockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!1},y.unlockSwipeToNext=function(){y.params.allowSwipeToNext=!0},y.unlockSwipeToPrev=function(){y.params.allowSwipeToPrev=!0},y.unlockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!0},y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab"),y.imagesToLoad=[],y.imagesLoaded=0,y.loadImage=function(e,t,n,i,r){function a(){r&&r()}var o;e.complete&&i?a():t?(o=new window.Image,o.onload=a,o.onerror=a,n&&(o.srcset=n),t&&(o.src=t)):a()},y.preloadImages=function(){function e(){"undefined"!=typeof y&&null!==y&&(void 0!==y.imagesLoaded&&y.imagesLoaded++,y.imagesLoaded===y.imagesToLoad.length&&(y.params.updateOnImagesReady&&y.update(),y.emit("onImagesReady",y)))}y.imagesToLoad=y.container.find("img");for(var t=0;t<y.imagesToLoad.length;t++)y.loadImage(y.imagesToLoad[t],y.imagesToLoad[t].currentSrc||y.imagesToLoad[t].getAttribute("src"),y.imagesToLoad[t].srcset||y.imagesToLoad[t].getAttribute("srcset"),!0,e)},y.autoplayTimeoutId=void 0,y.autoplaying=!1,y.autoplayPaused=!1,y.startAutoplay=function(){return"undefined"!=typeof y.autoplayTimeoutId?!1:y.params.autoplay?y.autoplaying?!1:(y.autoplaying=!0,y.emit("onAutoplayStart",y),void c()):!1},y.stopAutoplay=function(e){y.autoplayTimeoutId&&(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplaying=!1,y.autoplayTimeoutId=void 0,y.emit("onAutoplayStop",y))},y.pauseAutoplay=function(e){y.autoplayPaused||(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplayPaused=!0,0===e?(y.autoplayPaused=!1,c()):y.wrapper.transitionEnd(function(){y&&(y.autoplayPaused=!1,y.autoplaying?c():y.stopAutoplay())}))},y.minTranslate=function(){return-y.snapGrid[0]},y.maxTranslate=function(){return-y.snapGrid[y.snapGrid.length-1]},y.updateAutoHeight=function(){var e=y.slides.eq(y.activeIndex)[0].offsetHeight;e&&y.wrapper.css("height",y.slides.eq(y.activeIndex)[0].offsetHeight+"px")},y.updateContainerSize=function(){var e,t;e="undefined"!=typeof y.params.width?y.params.width:y.container[0].clientWidth,t="undefined"!=typeof y.params.height?y.params.height:y.container[0].clientHeight,0===e&&s()||0===t&&!s()||(e=e-parseInt(y.container.css("padding-left"),10)-parseInt(y.container.css("padding-right"),10),t=t-parseInt(y.container.css("padding-top"),10)-parseInt(y.container.css("padding-bottom"),10),y.width=e,y.height=t,y.size=s()?y.width:y.height)},y.updateSlidesSize=function(){y.slides=y.wrapper.children("."+y.params.slideClass),y.snapGrid=[],y.slidesGrid=[],y.slidesSizesGrid=[];var e,t=y.params.spaceBetween,n=-y.params.slidesOffsetBefore,i=0,r=0;"string"==typeof t&&t.indexOf("%")>=0&&(t=parseFloat(t.replace("%",""))/100*y.size),y.virtualSize=-t,y.rtl?y.slides.css({marginLeft:"",marginTop:""}):y.slides.css({marginRight:"",marginBottom:""});var a;y.params.slidesPerColumn>1&&(a=Math.floor(y.slides.length/y.params.slidesPerColumn)===y.slides.length/y.params.slidesPerColumn?y.slides.length:Math.ceil(y.slides.length/y.params.slidesPerColumn)*y.params.slidesPerColumn,"auto"!==y.params.slidesPerView&&"row"===y.params.slidesPerColumnFill&&(a=Math.max(a,y.params.slidesPerView*y.params.slidesPerColumn)));var o,c=y.params.slidesPerColumn,d=a/c,u=d-(y.params.slidesPerColumn*d-y.slides.length);for(e=0;e<y.slides.length;e++){o=0;var p=y.slides.eq(e);if(y.params.slidesPerColumn>1){var h,f,m;"column"===y.params.slidesPerColumnFill?(f=Math.floor(e/c),m=e-f*c,(f>u||f===u&&m===c-1)&&++m>=c&&(m=0,f++),h=f+m*a/c,p.css({"-webkit-box-ordinal-group":h,"-moz-box-ordinal-group":h,"-ms-flex-order":h,"-webkit-order":h,order:h})):(m=Math.floor(e/d),f=e-m*d),p.css({"margin-top":0!==m&&y.params.spaceBetween&&y.params.spaceBetween+"px"}).attr("data-swiper-column",f).attr("data-swiper-row",m)}"none"!==p.css("display")&&("auto"===y.params.slidesPerView?(o=s()?p.outerWidth(!0):p.outerHeight(!0),y.params.roundLengths&&(o=l(o))):(o=(y.size-(y.params.slidesPerView-1)*t)/y.params.slidesPerView,y.params.roundLengths&&(o=l(o)),s()?y.slides[e].style.width=o+"px":y.slides[e].style.height=o+"px"),y.slides[e].swiperSlideSize=o,y.slidesSizesGrid.push(o),y.params.centeredSlides?(n=n+o/2+i/2+t,0===e&&(n=n-y.size/2-t),Math.abs(n)<.001&&(n=0),r%y.params.slidesPerGroup===0&&y.snapGrid.push(n),y.slidesGrid.push(n)):(r%y.params.slidesPerGroup===0&&y.snapGrid.push(n),y.slidesGrid.push(n),n=n+o+t),y.virtualSize+=o+t,i=o,r++)}y.virtualSize=Math.max(y.virtualSize,y.size)+y.params.slidesOffsetAfter;var g;if(y.rtl&&y.wrongRTL&&("slide"===y.params.effect||"coverflow"===y.params.effect)&&y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),(!y.support.flexbox||y.params.setWrapperSize)&&(s()?y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}):y.wrapper.css({height:y.virtualSize+y.params.spaceBetween+"px"})),y.params.slidesPerColumn>1&&(y.virtualSize=(o+y.params.spaceBetween)*a,y.virtualSize=Math.ceil(y.virtualSize/y.params.slidesPerColumn)-y.params.spaceBetween,y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),y.params.centeredSlides)){for(g=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<y.virtualSize+y.snapGrid[0]&&g.push(y.snapGrid[e]);y.snapGrid=g}if(!y.params.centeredSlides){for(g=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<=y.virtualSize-y.size&&g.push(y.snapGrid[e]);y.snapGrid=g,Math.floor(y.virtualSize-y.size)>Math.floor(y.snapGrid[y.snapGrid.length-1])&&y.snapGrid.push(y.virtualSize-y.size)}0===y.snapGrid.length&&(y.snapGrid=[0]),0!==y.params.spaceBetween&&(s()?y.rtl?y.slides.css({marginLeft:t+"px"}):y.slides.css({marginRight:t+"px"}):y.slides.css({marginBottom:t+"px"})),y.params.watchSlidesProgress&&y.updateSlidesOffset()},y.updateSlidesOffset=function(){for(var e=0;e<y.slides.length;e++)y.slides[e].swiperSlideOffset=s()?y.slides[e].offsetLeft:y.slides[e].offsetTop},y.updateSlidesProgress=function(e){if("undefined"==typeof e&&(e=y.translate||0),0!==y.slides.length){"undefined"==typeof y.slides[0].swiperSlideOffset&&y.updateSlidesOffset();var t=-e;y.rtl&&(t=e),y.slides.removeClass(y.params.slideVisibleClass);for(var n=0;n<y.slides.length;n++){var i=y.slides[n],r=(t-i.swiperSlideOffset)/(i.swiperSlideSize+y.params.spaceBetween);if(y.params.watchSlidesVisibility){var a=-(t-i.swiperSlideOffset),o=a+y.slidesSizesGrid[n],s=a>=0&&a<y.size||o>0&&o<=y.size||0>=a&&o>=y.size;s&&y.slides.eq(n).addClass(y.params.slideVisibleClass)}i.progress=y.rtl?-r:r}}},y.updateProgress=function(e){"undefined"==typeof e&&(e=y.translate||0);var t=y.maxTranslate()-y.minTranslate(),n=y.isBeginning,i=y.isEnd;0===t?(y.progress=0,y.isBeginning=y.isEnd=!0):(y.progress=(e-y.minTranslate())/t,y.isBeginning=y.progress<=0,y.isEnd=y.progress>=1),y.isBeginning&&!n&&y.emit("onReachBeginning",y),y.isEnd&&!i&&y.emit("onReachEnd",y),y.params.watchSlidesProgress&&y.updateSlidesProgress(e),y.emit("onProgress",y,y.progress)},y.updateActiveIndex=function(){var e,t,n,i=y.rtl?y.translate:-y.translate;for(t=0;t<y.slidesGrid.length;t++)"undefined"!=typeof y.slidesGrid[t+1]?i>=y.slidesGrid[t]&&i<y.slidesGrid[t+1]-(y.slidesGrid[t+1]-y.slidesGrid[t])/2?e=t:i>=y.slidesGrid[t]&&i<y.slidesGrid[t+1]&&(e=t+1):i>=y.slidesGrid[t]&&(e=t);(0>e||"undefined"==typeof e)&&(e=0),n=Math.floor(e/y.params.slidesPerGroup),n>=y.snapGrid.length&&(n=y.snapGrid.length-1),e!==y.activeIndex&&(y.snapIndex=n,y.previousIndex=y.activeIndex,y.activeIndex=e,y.updateClasses())},y.updateClasses=function(){y.slides.removeClass(y.params.slideActiveClass+" "+y.params.slideNextClass+" "+y.params.slidePrevClass);var e=y.slides.eq(y.activeIndex);if(e.addClass(y.params.slideActiveClass),e.next("."+y.params.slideClass).addClass(y.params.slideNextClass),e.prev("."+y.params.slideClass).addClass(y.params.slidePrevClass),y.bullets&&y.bullets.length>0){y.bullets.removeClass(y.params.bulletActiveClass);var n;y.params.loop?(n=Math.ceil(y.activeIndex-y.loopedSlides)/y.params.slidesPerGroup,n>y.slides.length-1-2*y.loopedSlides&&(n-=y.slides.length-2*y.loopedSlides),n>y.bullets.length-1&&(n-=y.bullets.length)):n="undefined"!=typeof y.snapIndex?y.snapIndex:y.activeIndex||0,y.paginationContainer.length>1?y.bullets.each(function(){t(this).index()===n&&t(this).addClass(y.params.bulletActiveClass)}):y.bullets.eq(n).addClass(y.params.bulletActiveClass)}y.params.loop||(y.params.prevButton&&(y.isBeginning?(t(y.params.prevButton).addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(t(y.params.prevButton))):(t(y.params.prevButton).removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(t(y.params.prevButton)))),y.params.nextButton&&(y.isEnd?(t(y.params.nextButton).addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(t(y.params.nextButton))):(t(y.params.nextButton).removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(t(y.params.nextButton)))))},y.updatePagination=function(){if(y.params.pagination&&y.paginationContainer&&y.paginationContainer.length>0){for(var e="",t=y.params.loop?Math.ceil((y.slides.length-2*y.loopedSlides)/y.params.slidesPerGroup):y.snapGrid.length,n=0;t>n;n++)e+=y.params.paginationBulletRender?y.params.paginationBulletRender(n,y.params.bulletClass):"<"+y.params.paginationElement+' class="'+y.params.bulletClass+'"></'+y.params.paginationElement+">";y.paginationContainer.html(e),y.bullets=y.paginationContainer.find("."+y.params.bulletClass),y.params.paginationClickable&&y.params.a11y&&y.a11y&&y.a11y.initPagination()}},y.update=function(e){function t(){i=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate()),y.setWrapperTranslate(i),y.updateActiveIndex(),y.updateClasses()}if(y.updateContainerSize(),y.updateSlidesSize(),y.updateProgress(),y.updatePagination(),y.updateClasses(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),e){var n,i;y.controller&&y.controller.spline&&(y.controller.spline=void 0),y.params.freeMode?(t(),y.params.autoHeight&&y.updateAutoHeight()):(n=("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0),n||t())}else y.params.autoHeight&&y.updateAutoHeight()},y.onResize=function(e){y.params.breakpoints&&y.setBreakpoint();var t=y.params.allowSwipeToPrev,n=y.params.allowSwipeToNext;if(y.params.allowSwipeToPrev=y.params.allowSwipeToNext=!0,y.updateContainerSize(),y.updateSlidesSize(),("auto"===y.params.slidesPerView||y.params.freeMode||e)&&y.updatePagination(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),y.controller&&y.controller.spline&&(y.controller.spline=void 0),y.params.freeMode){var i=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate());y.setWrapperTranslate(i),y.updateActiveIndex(),y.updateClasses(),y.params.autoHeight&&y.updateAutoHeight()}else y.updateClasses(),("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0);y.params.allowSwipeToPrev=t,y.params.allowSwipeToNext=n};var E=["mousedown","mousemove","mouseup"];window.navigator.pointerEnabled?E=["pointerdown","pointermove","pointerup"]:window.navigator.msPointerEnabled&&(E=["MSPointerDown","MSPointerMove","MSPointerUp"]),y.touchEvents={start:y.support.touch||!y.params.simulateTouch?"touchstart":E[0],move:y.support.touch||!y.params.simulateTouch?"touchmove":E[1],end:y.support.touch||!y.params.simulateTouch?"touchend":E[2]},(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&("container"===y.params.touchEventsTarget?y.container:y.wrapper).addClass("swiper-wp8-"+y.params.direction),y.initEvents=function(e){var n=e?"off":"on",i=e?"removeEventListener":"addEventListener",a="container"===y.params.touchEventsTarget?y.container[0]:y.wrapper[0],o=y.support.touch?a:document,s=y.params.nested?!0:!1;y.browser.ie?(a[i](y.touchEvents.start,y.onTouchStart,!1),o[i](y.touchEvents.move,y.onTouchMove,s),o[i](y.touchEvents.end,y.onTouchEnd,!1)):(y.support.touch&&(a[i](y.touchEvents.start,y.onTouchStart,!1),a[i](y.touchEvents.move,y.onTouchMove,s),a[i](y.touchEvents.end,y.onTouchEnd,!1)),!r.simulateTouch||y.device.ios||y.device.android||(a[i]("mousedown",y.onTouchStart,!1),document[i]("mousemove",y.onTouchMove,s),document[i]("mouseup",y.onTouchEnd,!1))),window[i]("resize",y.onResize),y.params.nextButton&&(t(y.params.nextButton)[n]("click",y.onClickNext),y.params.a11y&&y.a11y&&t(y.params.nextButton)[n]("keydown",y.a11y.onEnterKey)),y.params.prevButton&&(t(y.params.prevButton)[n]("click",y.onClickPrev),y.params.a11y&&y.a11y&&t(y.params.prevButton)[n]("keydown",y.a11y.onEnterKey)),y.params.pagination&&y.params.paginationClickable&&(t(y.paginationContainer)[n]("click","."+y.params.bulletClass,y.onClickIndex),y.params.a11y&&y.a11y&&t(y.paginationContainer)[n]("keydown","."+y.params.bulletClass,y.a11y.onEnterKey)),(y.params.preventClicks||y.params.preventClicksPropagation)&&a[i]("click",y.preventClicks,!0)},y.attachEvents=function(e){y.initEvents()},y.detachEvents=function(){y.initEvents(!0)},y.allowClick=!0,y.preventClicks=function(e){y.allowClick||(y.params.preventClicks&&e.preventDefault(),y.params.preventClicksPropagation&&y.animating&&(e.stopPropagation(),e.stopImmediatePropagation()))},y.onClickNext=function(e){e.preventDefault(),(!y.isEnd||y.params.loop)&&y.slideNext()},y.onClickPrev=function(e){e.preventDefault(),(!y.isBeginning||y.params.loop)&&y.slidePrev()},y.onClickIndex=function(e){e.preventDefault();var n=t(this).index()*y.params.slidesPerGroup;y.params.loop&&(n+=y.loopedSlides),y.slideTo(n)},y.updateClickedSlide=function(e){var n=d(e,"."+y.params.slideClass),i=!1;if(n)for(var r=0;r<y.slides.length;r++)y.slides[r]===n&&(i=!0);if(!n||!i)return y.clickedSlide=void 0,void(y.clickedIndex=void 0);if(y.clickedSlide=n,y.clickedIndex=t(n).index(),y.params.slideToClickedSlide&&void 0!==y.clickedIndex&&y.clickedIndex!==y.activeIndex){var a,o=y.clickedIndex;if(y.params.loop){if(y.animating)return;a=t(y.clickedSlide).attr("data-swiper-slide-index"),y.params.centeredSlides?o<y.loopedSlides-y.params.slidesPerView/2||o>y.slides.length-y.loopedSlides+y.params.slidesPerView/2?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+a+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o):o>y.slides.length-y.params.slidesPerView?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+a+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o)}else y.slideTo(o)}};var x,D,M,L,C,P,I,k,N,z,O="input, select, textarea, button",A=Date.now(),G=[];y.animating=!1,y.touches={startX:0,startY:0,currentX:0,currentY:0,diff:0};var V,R;if(y.onTouchStart=function(e){if(e.originalEvent&&(e=e.originalEvent),V="touchstart"===e.type,V||!("which"in e)||3!==e.which){if(y.params.noSwiping&&d(e,"."+y.params.noSwipingClass))return void(y.allowClick=!0);if(!y.params.swipeHandler||d(e,y.params.swipeHandler)){var n=y.touches.currentX="touchstart"===e.type?e.targetTouches[0].pageX:e.pageX,i=y.touches.currentY="touchstart"===e.type?e.targetTouches[0].pageY:e.pageY;if(!(y.device.ios&&y.params.iOSEdgeSwipeDetection&&n<=y.params.iOSEdgeSwipeThreshold)){if(x=!0,D=!1,M=!0,C=void 0,R=void 0,y.touches.startX=n,y.touches.startY=i,L=Date.now(),y.allowClick=!0,y.updateContainerSize(),y.swipeDirection=void 0,y.params.threshold>0&&(k=!1),"touchstart"!==e.type){var r=!0;t(e.target).is(O)&&(r=!1),document.activeElement&&t(document.activeElement).is(O)&&document.activeElement.blur(),r&&e.preventDefault()}y.emit("onTouchStart",y,e)}}}},y.onTouchMove=function(e){if(e.originalEvent&&(e=e.originalEvent),!(V&&"mousemove"===e.type||e.preventedByNestedSwiper)){if(y.params.onlyExternal)return y.allowClick=!1,void(x&&(y.touches.startX=y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.startY=y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,L=Date.now()));if(V&&document.activeElement&&e.target===document.activeElement&&t(e.target).is(O))return D=!0,void(y.allowClick=!1);if(M&&y.emit("onTouchMove",y,e),!(e.targetTouches&&e.targetTouches.length>1)){if(y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,"undefined"==typeof C){var n=180*Math.atan2(Math.abs(y.touches.currentY-y.touches.startY),Math.abs(y.touches.currentX-y.touches.startX))/Math.PI;C=s()?n>y.params.touchAngle:90-n>y.params.touchAngle}if(C&&y.emit("onTouchMoveOpposite",y,e),"undefined"==typeof R&&y.browser.ieTouch&&(y.touches.currentX!==y.touches.startX||y.touches.currentY!==y.touches.startY)&&(R=!0),x){if(C)return void(x=!1);if(R||!y.browser.ieTouch){y.allowClick=!1,y.emit("onSliderMove",y,e),e.preventDefault(),y.params.touchMoveStopPropagation&&!y.params.nested&&e.stopPropagation(),D||(r.loop&&y.fixLoop(),I=y.getWrapperTranslate(),y.setWrapperTransition(0),y.animating&&y.wrapper.trigger("webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd"),y.params.autoplay&&y.autoplaying&&(y.params.autoplayDisableOnInteraction?y.stopAutoplay():y.pauseAutoplay()),z=!1,y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grabbing",y.container[0].style.cursor="-moz-grabbin",y.container[0].style.cursor="grabbing")),D=!0;var i=y.touches.diff=s()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY;i*=y.params.touchRatio,y.rtl&&(i=-i),y.swipeDirection=i>0?"prev":"next",P=i+I;var a=!0;if(i>0&&P>y.minTranslate()?(a=!1,y.params.resistance&&(P=y.minTranslate()-1+Math.pow(-y.minTranslate()+I+i,y.params.resistanceRatio))):0>i&&P<y.maxTranslate()&&(a=!1,y.params.resistance&&(P=y.maxTranslate()+1-Math.pow(y.maxTranslate()-I-i,y.params.resistanceRatio))),a&&(e.preventedByNestedSwiper=!0),!y.params.allowSwipeToNext&&"next"===y.swipeDirection&&I>P&&(P=I),!y.params.allowSwipeToPrev&&"prev"===y.swipeDirection&&P>I&&(P=I),y.params.followFinger){if(y.params.threshold>0){if(!(Math.abs(i)>y.params.threshold||k))return void(P=I);if(!k)return k=!0,y.touches.startX=y.touches.currentX,y.touches.startY=y.touches.currentY,P=I,void(y.touches.diff=s()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY)}(y.params.freeMode||y.params.watchSlidesProgress)&&y.updateActiveIndex(),y.params.freeMode&&(0===G.length&&G.push({position:y.touches[s()?"startX":"startY"],time:L}),G.push({position:y.touches[s()?"currentX":"currentY"],time:(new window.Date).getTime()})),y.updateProgress(P),y.setWrapperTranslate(P)}}}}}},y.onTouchEnd=function(e){if(e.originalEvent&&(e=e.originalEvent),M&&y.emit("onTouchEnd",y,e),M=!1,x){y.params.grabCursor&&D&&x&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab");var n=Date.now(),i=n-L;if(y.allowClick&&(y.updateClickedSlide(e),y.emit("onTap",y,e),300>i&&n-A>300&&(N&&clearTimeout(N),N=setTimeout(function(){y&&(y.params.paginationHide&&y.paginationContainer.length>0&&!t(e.target).hasClass(y.params.bulletClass)&&y.paginationContainer.toggleClass(y.params.paginationHiddenClass),y.emit("onClick",y,e))},300)),300>i&&300>n-A&&(N&&clearTimeout(N),y.emit("onDoubleTap",y,e))),A=Date.now(),setTimeout(function(){y&&(y.allowClick=!0)},0),!x||!D||!y.swipeDirection||0===y.touches.diff||P===I)return void(x=D=!1);x=D=!1;var r;if(r=y.params.followFinger?y.rtl?y.translate:-y.translate:-P,y.params.freeMode){if(r<-y.minTranslate())return void y.slideTo(y.activeIndex);if(r>-y.maxTranslate())return void(y.slides.length<y.snapGrid.length?y.slideTo(y.snapGrid.length-1):y.slideTo(y.slides.length-1));if(y.params.freeModeMomentum){if(G.length>1){var a=G.pop(),o=G.pop(),s=a.position-o.position,l=a.time-o.time;y.velocity=s/l,y.velocity=y.velocity/2,Math.abs(y.velocity)<y.params.freeModeMinimumVelocity&&(y.velocity=0),(l>150||(new window.Date).getTime()-a.time>300)&&(y.velocity=0)}else y.velocity=0;G.length=0;var c=1e3*y.params.freeModeMomentumRatio,d=y.velocity*c,u=y.translate+d;y.rtl&&(u=-u);var p,h=!1,f=20*Math.abs(y.velocity)*y.params.freeModeMomentumBounceRatio;if(u<y.maxTranslate())y.params.freeModeMomentumBounce?(u+y.maxTranslate()<-f&&(u=y.maxTranslate()-f),p=y.maxTranslate(),h=!0,z=!0):u=y.maxTranslate();else if(u>y.minTranslate())y.params.freeModeMomentumBounce?(u-y.minTranslate()>f&&(u=y.minTranslate()+f),p=y.minTranslate(),h=!0,z=!0):u=y.minTranslate();else if(y.params.freeModeSticky){var m,g=0;for(g=0;g<y.snapGrid.length;g+=1)if(y.snapGrid[g]>-u){m=g;break}u=Math.abs(y.snapGrid[m]-u)<Math.abs(y.snapGrid[m-1]-u)||"next"===y.swipeDirection?y.snapGrid[m]:y.snapGrid[m-1],y.rtl||(u=-u)}if(0!==y.velocity)c=y.rtl?Math.abs((-u-y.translate)/y.velocity):Math.abs((u-y.translate)/y.velocity);else if(y.params.freeModeSticky)return void y.slideReset();y.params.freeModeMomentumBounce&&h?(y.updateProgress(p),y.setWrapperTransition(c),y.setWrapperTranslate(u),y.onTransitionStart(),y.animating=!0,y.wrapper.transitionEnd(function(){y&&z&&(y.emit("onMomentumBounce",y),y.setWrapperTransition(y.params.speed),y.setWrapperTranslate(p),y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))})):y.velocity?(y.updateProgress(u),y.setWrapperTransition(c),y.setWrapperTranslate(u),y.onTransitionStart(),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))):y.updateProgress(u),y.updateActiveIndex()}return void((!y.params.freeModeMomentum||i>=y.params.longSwipesMs)&&(y.updateProgress(),y.updateActiveIndex()))}var v,_=0,w=y.slidesSizesGrid[0];for(v=0;v<y.slidesGrid.length;v+=y.params.slidesPerGroup)"undefined"!=typeof y.slidesGrid[v+y.params.slidesPerGroup]?r>=y.slidesGrid[v]&&r<y.slidesGrid[v+y.params.slidesPerGroup]&&(_=v,w=y.slidesGrid[v+y.params.slidesPerGroup]-y.slidesGrid[v]):r>=y.slidesGrid[v]&&(_=v,w=y.slidesGrid[y.slidesGrid.length-1]-y.slidesGrid[y.slidesGrid.length-2]);var T=(r-y.slidesGrid[_])/w;if(i>y.params.longSwipesMs){if(!y.params.longSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&(T>=y.params.longSwipesRatio?y.slideTo(_+y.params.slidesPerGroup):y.slideTo(_)),"prev"===y.swipeDirection&&(T>1-y.params.longSwipesRatio?y.slideTo(_+y.params.slidesPerGroup):y.slideTo(_))}else{if(!y.params.shortSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&y.slideTo(_+y.params.slidesPerGroup),"prev"===y.swipeDirection&&y.slideTo(_)}}},y._slideTo=function(e,t){return y.slideTo(e,t,!0,!0)},y.slideTo=function(e,t,n,i){"undefined"==typeof n&&(n=!0),"undefined"==typeof e&&(e=0),0>e&&(e=0),y.snapIndex=Math.floor(e/y.params.slidesPerGroup),y.snapIndex>=y.snapGrid.length&&(y.snapIndex=y.snapGrid.length-1);var r=-y.snapGrid[y.snapIndex];y.params.autoplay&&y.autoplaying&&(i||!y.params.autoplayDisableOnInteraction?y.pauseAutoplay(t):y.stopAutoplay()),y.updateProgress(r);for(var a=0;a<y.slidesGrid.length;a++)-Math.floor(100*r)>=Math.floor(100*y.slidesGrid[a])&&(e=a);return!y.params.allowSwipeToNext&&r<y.translate&&r<y.minTranslate()?!1:!y.params.allowSwipeToPrev&&r>y.translate&&r>y.maxTranslate()&&(y.activeIndex||0)!==e?!1:("undefined"==typeof t&&(t=y.params.speed),y.previousIndex=y.activeIndex||0,y.activeIndex=e,y.rtl&&-r===y.translate||!y.rtl&&r===y.translate?(y.params.autoHeight&&y.updateAutoHeight(),y.updateClasses(),"slide"!==y.params.effect&&y.setWrapperTranslate(r),!1):(y.updateClasses(),y.onTransitionStart(n),0===t?(y.setWrapperTranslate(r),y.setWrapperTransition(0),y.onTransitionEnd(n)):(y.setWrapperTranslate(r),y.setWrapperTransition(t),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd(n)}))),!0))},y.onTransitionStart=function(e){"undefined"==typeof e&&(e=!0),y.params.autoHeight&&y.updateAutoHeight(),y.lazy&&y.lazy.onTransitionStart(),e&&(y.emit("onTransitionStart",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeStart",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextStart",y):y.emit("onSlidePrevStart",y)))},y.onTransitionEnd=function(e){y.animating=!1,y.setWrapperTransition(0),"undefined"==typeof e&&(e=!0),y.lazy&&y.lazy.onTransitionEnd(),e&&(y.emit("onTransitionEnd",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeEnd",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextEnd",y):y.emit("onSlidePrevEnd",y))),y.params.hashnav&&y.hashnav&&y.hashnav.setHash()},y.slideNext=function(e,t,n){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex+y.params.slidesPerGroup,t,e,n)}return y.slideTo(y.activeIndex+y.params.slidesPerGroup,t,e,n)},y._slideNext=function(e){return y.slideNext(!0,e,!0)},y.slidePrev=function(e,t,n){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex-1,t,e,n)}return y.slideTo(y.activeIndex-1,t,e,n)},y._slidePrev=function(e){return y.slidePrev(!0,e,!0)},y.slideReset=function(e,t,n){return y.slideTo(y.activeIndex,t,e)},y.setWrapperTransition=function(e,t){y.wrapper.transition(e),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTransition(e),y.params.parallax&&y.parallax&&y.parallax.setTransition(e),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTransition(e),y.params.control&&y.controller&&y.controller.setTransition(e,t),y.emit("onSetTransition",y,e)},y.setWrapperTranslate=function(e,t,n){var i=0,r=0,a=0;s()?i=y.rtl?-e:e:r=e,y.params.roundLengths&&(i=l(i),r=l(r)),y.params.virtualTranslate||(y.support.transforms3d?y.wrapper.transform("translate3d("+i+"px, "+r+"px, "+a+"px)"):y.wrapper.transform("translate("+i+"px, "+r+"px)")),y.translate=s()?i:r;var o,c=y.maxTranslate()-y.minTranslate();o=0===c?0:(e-y.minTranslate())/c,o!==y.progress&&y.updateProgress(e), +t&&y.updateActiveIndex(),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTranslate(y.translate),y.params.parallax&&y.parallax&&y.parallax.setTranslate(y.translate),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTranslate(y.translate),y.params.control&&y.controller&&y.controller.setTranslate(y.translate,n),y.emit("onSetTranslate",y,y.translate)},y.getTranslate=function(e,t){var n,i,r,a;return"undefined"==typeof t&&(t="x"),y.params.virtualTranslate?y.rtl?-y.translate:y.translate:(r=window.getComputedStyle(e,null),window.WebKitCSSMatrix?(i=r.transform||r.webkitTransform,i.split(",").length>6&&(i=i.split(", ").map(function(e){return e.replace(",",".")}).join(", ")),a=new window.WebKitCSSMatrix("none"===i?"":i)):(a=r.MozTransform||r.OTransform||r.MsTransform||r.msTransform||r.transform||r.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),n=a.toString().split(",")),"x"===t&&(i=window.WebKitCSSMatrix?a.m41:16===n.length?parseFloat(n[12]):parseFloat(n[4])),"y"===t&&(i=window.WebKitCSSMatrix?a.m42:16===n.length?parseFloat(n[13]):parseFloat(n[5])),y.rtl&&i&&(i=-i),i||0)},y.getWrapperTranslate=function(e){return"undefined"==typeof e&&(e=s()?"x":"y"),y.getTranslate(y.wrapper[0],e)},y.observers=[],y.initObservers=function(){if(y.params.observeParents)for(var e=y.container.parents(),t=0;t<e.length;t++)u(e[t]);u(y.container[0],{childList:!1}),u(y.wrapper[0],{attributes:!1})},y.disconnectObservers=function(){for(var e=0;e<y.observers.length;e++)y.observers[e].disconnect();y.observers=[]},y.createLoop=function(){var e=y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass);angular.element(e).remove();var n=y.wrapper.children("."+y.params.slideClass);"auto"!==y.params.slidesPerView||y.params.loopedSlides||(y.params.loopedSlides=n.length),y.loopedSlides=parseInt(y.params.loopedSlides||y.params.slidesPerView,10),y.loopedSlides=y.loopedSlides+y.params.loopAdditionalSlides,y.loopedSlides>n.length&&(y.loopedSlides=n.length);var i,r,a,s=[],l=[];for(n.each(function(e,i){var r=t(this);e<y.loopedSlides&&l.push(i),e<n.length&&e>=n.length-y.loopedSlides&&s.push(i),r.attr("data-swiper-slide-index",e)}),i=0;i<l.length;i++)a=angular.element(l[i]).clone().addClass(y.params.slideDuplicateClass),a.removeAttr("ng-transclude"),a.removeAttr("ng-repeat"),r=angular.element(l[i]).scope(),a=o(a)(r),angular.element(y.wrapper).append(a);for(i=s.length-1;i>=0;i--)a=angular.element(s[i]).clone().addClass(y.params.slideDuplicateClass),a.removeAttr("ng-transclude"),a.removeAttr("ng-repeat"),r=angular.element(s[i]).scope(),a=o(a)(r),angular.element(y.wrapper).prepend(a)},y.destroyLoop=function(){y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass).remove(),y.slides.removeAttr("data-swiper-slide-index")},y.fixLoop=function(){var e;y.activeIndex<y.loopedSlides?(e=y.slides.length-3*y.loopedSlides+y.activeIndex,e+=y.loopedSlides,y.slideTo(e,0,!1,!0)):("auto"===y.params.slidesPerView&&y.activeIndex>=2*y.loopedSlides||y.activeIndex>y.slides.length-2*y.params.slidesPerView)&&(e=-y.slides.length+y.activeIndex+y.loopedSlides,e+=y.loopedSlides,y.slideTo(e,0,!1,!0))},y.appendSlide=function(e){if(y.params.loop&&y.destroyLoop(),"object"==typeof e&&e.length)for(var t=0;t<e.length;t++)e[t]&&y.wrapper.append(e[t]);else y.wrapper.append(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0)},y.prependSlide=function(e){y.params.loop&&y.destroyLoop();var t=y.activeIndex+1;if("object"==typeof e&&e.length){for(var n=0;n<e.length;n++)e[n]&&y.wrapper.prepend(e[n]);t=y.activeIndex+e.length}else y.wrapper.prepend(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.slideTo(t,0,!1)},y.removeSlide=function(e){y.params.loop&&(y.destroyLoop(),y.slides=y.wrapper.children("."+y.params.slideClass));var t,n=y.activeIndex;if("object"==typeof e&&e.length){for(var i=0;i<e.length;i++)t=e[i],y.slides[t]&&y.slides.eq(t).remove(),n>t&&n--;n=Math.max(n,0)}else t=e,y.slides[t]&&y.slides.eq(t).remove(),n>t&&n--,n=Math.max(n,0);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.params.loop?y.slideTo(n+y.loopedSlides,0,!1):y.slideTo(n,0,!1)},y.removeAllSlides=function(){for(var e=[],t=0;t<y.slides.length;t++)e.push(t);y.removeSlide(e)},y.effects={fade:{setTranslate:function(){for(var e=0;e<y.slides.length;e++){var t=y.slides.eq(e),n=t[0].swiperSlideOffset,i=-n;y.params.virtualTranslate||(i-=y.translate);var r=0;s()||(r=i,i=0);var a=y.params.fade.crossFade?Math.max(1-Math.abs(t[0].progress),0):1+Math.min(Math.max(t[0].progress,-1),0);t.css({opacity:a}).transform("translate3d("+i+"px, "+r+"px, 0px)")}},setTransition:function(e){if(y.slides.transition(e),y.params.virtualTranslate&&0!==e){var t=!1;y.slides.transitionEnd(function(){if(!t&&y){t=!0,y.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],n=0;n<e.length;n++)y.wrapper.trigger(e[n])}})}}},cube:{setTranslate:function(){var e,n=0;y.params.cube.shadow&&(s()?(e=y.wrapper.find(".swiper-cube-shadow"),0===e.length&&(e=t('<div class="swiper-cube-shadow"></div>'),y.wrapper.append(e)),e.css({height:y.width+"px"})):(e=y.container.find(".swiper-cube-shadow"),0===e.length&&(e=t('<div class="swiper-cube-shadow"></div>'),y.container.append(e))));for(var i=0;i<y.slides.length;i++){var r=y.slides.eq(i),a=90*i,o=Math.floor(a/360);y.rtl&&(a=-a,o=Math.floor(-a/360));var l=Math.max(Math.min(r[0].progress,1),-1),c=0,d=0,u=0;i%4===0?(c=4*-o*y.size,u=0):(i-1)%4===0?(c=0,u=4*-o*y.size):(i-2)%4===0?(c=y.size+4*o*y.size,u=y.size):(i-3)%4===0&&(c=-y.size,u=3*y.size+4*y.size*o),y.rtl&&(c=-c),s()||(d=c,c=0);var p="rotateX("+(s()?0:-a)+"deg) rotateY("+(s()?a:0)+"deg) translate3d("+c+"px, "+d+"px, "+u+"px)";if(1>=l&&l>-1&&(n=90*i+90*l,y.rtl&&(n=90*-i-90*l)),r.transform(p),y.params.cube.slideShadows){var h=s()?r.find(".swiper-slide-shadow-left"):r.find(".swiper-slide-shadow-top"),f=s()?r.find(".swiper-slide-shadow-right"):r.find(".swiper-slide-shadow-bottom");0===h.length&&(h=t('<div class="swiper-slide-shadow-'+(s()?"left":"top")+'"></div>'),r.append(h)),0===f.length&&(f=t('<div class="swiper-slide-shadow-'+(s()?"right":"bottom")+'"></div>'),r.append(f));r[0].progress;h.length&&(h[0].style.opacity=-r[0].progress),f.length&&(f[0].style.opacity=r[0].progress)}}if(y.wrapper.css({"-webkit-transform-origin":"50% 50% -"+y.size/2+"px","-moz-transform-origin":"50% 50% -"+y.size/2+"px","-ms-transform-origin":"50% 50% -"+y.size/2+"px","transform-origin":"50% 50% -"+y.size/2+"px"}),y.params.cube.shadow)if(s())e.transform("translate3d(0px, "+(y.width/2+y.params.cube.shadowOffset)+"px, "+-y.width/2+"px) rotateX(90deg) rotateZ(0deg) scale("+y.params.cube.shadowScale+")");else{var m=Math.abs(n)-90*Math.floor(Math.abs(n)/90),g=1.5-(Math.sin(2*m*Math.PI/360)/2+Math.cos(2*m*Math.PI/360)/2),v=y.params.cube.shadowScale,_=y.params.cube.shadowScale/g,w=y.params.cube.shadowOffset;e.transform("scale3d("+v+", 1, "+_+") translate3d(0px, "+(y.height/2+w)+"px, "+-y.height/2/_+"px) rotateX(-90deg)")}var T=y.isSafari||y.isUiWebView?-y.size/2:0;y.wrapper.transform("translate3d(0px,0,"+T+"px) rotateX("+(s()?0:n)+"deg) rotateY("+(s()?-n:0)+"deg)")},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),y.params.cube.shadow&&!s()&&y.container.find(".swiper-cube-shadow").transition(e)}},coverflow:{setTranslate:function(){for(var e=y.translate,n=s()?-e+y.width/2:-e+y.height/2,i=s()?y.params.coverflow.rotate:-y.params.coverflow.rotate,r=y.params.coverflow.depth,a=0,o=y.slides.length;o>a;a++){var l=y.slides.eq(a),c=y.slidesSizesGrid[a],d=l[0].swiperSlideOffset,u=(n-d-c/2)/c*y.params.coverflow.modifier,p=s()?i*u:0,h=s()?0:i*u,f=-r*Math.abs(u),m=s()?0:y.params.coverflow.stretch*u,g=s()?y.params.coverflow.stretch*u:0;Math.abs(g)<.001&&(g=0),Math.abs(m)<.001&&(m=0),Math.abs(f)<.001&&(f=0),Math.abs(p)<.001&&(p=0),Math.abs(h)<.001&&(h=0);var v="translate3d("+g+"px,"+m+"px,"+f+"px) rotateX("+h+"deg) rotateY("+p+"deg)";if(l.transform(v),l[0].style.zIndex=-Math.abs(Math.round(u))+1,y.params.coverflow.slideShadows){var _=s()?l.find(".swiper-slide-shadow-left"):l.find(".swiper-slide-shadow-top"),w=s()?l.find(".swiper-slide-shadow-right"):l.find(".swiper-slide-shadow-bottom");0===_.length&&(_=t('<div class="swiper-slide-shadow-'+(s()?"left":"top")+'"></div>'),l.append(_)),0===w.length&&(w=t('<div class="swiper-slide-shadow-'+(s()?"right":"bottom")+'"></div>'),l.append(w)),_.length&&(_[0].style.opacity=u>0?u:0),w.length&&(w[0].style.opacity=-u>0?-u:0)}}if(y.browser.ie){var T=y.wrapper[0].style;T.perspectiveOrigin=n+"px 50%"}},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)}}},y.lazy={initialImageLoaded:!1,loadImageInSlide:function(e,n){if("undefined"!=typeof e&&("undefined"==typeof n&&(n=!0),0!==y.slides.length)){var i=y.slides.eq(e),r=i.find(".swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)");!i.hasClass("swiper-lazy")||i.hasClass("swiper-lazy-loaded")||i.hasClass("swiper-lazy-loading")||(r=r.add(i[0])),0!==r.length&&r.each(function(){var e=t(this);e.addClass("swiper-lazy-loading");var r=e.attr("data-background"),a=e.attr("data-src"),o=e.attr("data-srcset");y.loadImage(e[0],a||r,o,!1,function(){if(r?(e.css("background-image","url("+r+")"),e.removeAttr("data-background")):(o&&(e.attr("srcset",o),e.removeAttr("data-srcset")),a&&(e.attr("src",a),e.removeAttr("data-src"))),e.addClass("swiper-lazy-loaded").removeClass("swiper-lazy-loading"),i.find(".swiper-lazy-preloader, .preloader").remove(),y.params.loop&&n){var t=i.attr("data-swiper-slide-index");if(i.hasClass(y.params.slideDuplicateClass)){var s=y.wrapper.children('[data-swiper-slide-index="'+t+'"]:not(.'+y.params.slideDuplicateClass+")");y.lazy.loadImageInSlide(s.index(),!1)}else{var l=y.wrapper.children("."+y.params.slideDuplicateClass+'[data-swiper-slide-index="'+t+'"]');y.lazy.loadImageInSlide(l.index(),!1)}}y.emit("onLazyImageReady",y,i[0],e[0])}),y.emit("onLazyImageLoad",y,i[0],e[0])})}},load:function(){var e;if(y.params.watchSlidesVisibility)y.wrapper.children("."+y.params.slideVisibleClass).each(function(){y.lazy.loadImageInSlide(t(this).index())});else if(y.params.slidesPerView>1)for(e=y.activeIndex;e<y.activeIndex+y.params.slidesPerView;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);else y.lazy.loadImageInSlide(y.activeIndex);if(y.params.lazyLoadingInPrevNext)if(y.params.slidesPerView>1){for(e=y.activeIndex+y.params.slidesPerView;e<y.activeIndex+y.params.slidesPerView+y.params.slidesPerView;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);for(e=y.activeIndex-y.params.slidesPerView;e<y.activeIndex;e++)y.slides[e]&&y.lazy.loadImageInSlide(e)}else{var n=y.wrapper.children("."+y.params.slideNextClass);n.length>0&&y.lazy.loadImageInSlide(n.index());var i=y.wrapper.children("."+y.params.slidePrevClass);i.length>0&&y.lazy.loadImageInSlide(i.index())}},onTransitionStart:function(){y.params.lazyLoading&&(y.params.lazyLoadingOnTransitionStart||!y.params.lazyLoadingOnTransitionStart&&!y.lazy.initialImageLoaded)&&y.lazy.load()},onTransitionEnd:function(){y.params.lazyLoading&&!y.params.lazyLoadingOnTransitionStart&&y.lazy.load()}},y.scrollbar={isTouched:!1,setDragPosition:function(e){var t=y.scrollbar,n=s()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageX:e.pageX||e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageY:e.pageY||e.clientY,i=n-t.track.offset()[s()?"left":"top"]-t.dragSize/2,r=-y.minTranslate()*t.moveDivider,a=-y.maxTranslate()*t.moveDivider;r>i?i=r:i>a&&(i=a),i=-i/t.moveDivider,y.updateProgress(i),y.setWrapperTranslate(i,!0)},dragStart:function(e){var t=y.scrollbar;t.isTouched=!0,e.preventDefault(),e.stopPropagation(),t.setDragPosition(e),clearTimeout(t.dragTimeout),t.track.transition(0),y.params.scrollbarHide&&t.track.css("opacity",1),y.wrapper.transition(100),t.drag.transition(100),y.emit("onScrollbarDragStart",y)},dragMove:function(e){var t=y.scrollbar;t.isTouched&&(e.preventDefault?e.preventDefault():e.returnValue=!1,t.setDragPosition(e),y.wrapper.transition(0),t.track.transition(0),t.drag.transition(0),y.emit("onScrollbarDragMove",y))},dragEnd:function(e){var t=y.scrollbar;t.isTouched&&(t.isTouched=!1,y.params.scrollbarHide&&(clearTimeout(t.dragTimeout),t.dragTimeout=setTimeout(function(){t.track.css("opacity",0),t.track.transition(400)},1e3)),y.emit("onScrollbarDragEnd",y),y.params.scrollbarSnapOnRelease&&y.slideReset())},enableDraggable:function(){var e=y.scrollbar,n=y.support.touch?e.track:document;t(e.track).on(y.touchEvents.start,e.dragStart),t(n).on(y.touchEvents.move,e.dragMove),t(n).on(y.touchEvents.end,e.dragEnd)},disableDraggable:function(){var e=y.scrollbar,n=y.support.touch?e.track:document;t(e.track).off(y.touchEvents.start,e.dragStart),t(n).off(y.touchEvents.move,e.dragMove),t(n).off(y.touchEvents.end,e.dragEnd)},set:function(){if(y.params.scrollbar){var e=y.scrollbar;e.track=t(y.params.scrollbar),e.drag=e.track.find(".swiper-scrollbar-drag"),0===e.drag.length&&(e.drag=t('<div class="swiper-scrollbar-drag"></div>'),e.track.append(e.drag)),e.drag[0].style.width="",e.drag[0].style.height="",e.trackSize=s()?e.track[0].offsetWidth:e.track[0].offsetHeight,e.divider=y.size/y.virtualSize,e.moveDivider=e.divider*(e.trackSize/y.size),e.dragSize=e.trackSize*e.divider,s()?e.drag[0].style.width=e.dragSize+"px":e.drag[0].style.height=e.dragSize+"px",e.divider>=1?e.track[0].style.display="none":e.track[0].style.display="",y.params.scrollbarHide&&(e.track[0].style.opacity=0)}},setTranslate:function(){if(y.params.scrollbar){var e,t=y.scrollbar,n=(y.translate||0,t.dragSize);e=(t.trackSize-t.dragSize)*y.progress,y.rtl&&s()?(e=-e,e>0?(n=t.dragSize-e,e=0):-e+t.dragSize>t.trackSize&&(n=t.trackSize+e)):0>e?(n=t.dragSize+e,e=0):e+t.dragSize>t.trackSize&&(n=t.trackSize-e),s()?(y.support.transforms3d?t.drag.transform("translate3d("+e+"px, 0, 0)"):t.drag.transform("translateX("+e+"px)"),t.drag[0].style.width=n+"px"):(y.support.transforms3d?t.drag.transform("translate3d(0px, "+e+"px, 0)"):t.drag.transform("translateY("+e+"px)"),t.drag[0].style.height=n+"px"),y.params.scrollbarHide&&(clearTimeout(t.timeout),t.track[0].style.opacity=1,t.timeout=setTimeout(function(){t.track[0].style.opacity=0,t.track.transition(400)},1e3))}},setTransition:function(e){y.params.scrollbar&&y.scrollbar.drag.transition(e)}},y.controller={LinearSpline:function(e,t){this.x=e,this.y=t,this.lastIndex=e.length-1;var n,i;this.x.length;this.interpolate=function(e){return e?(i=r(this.x,e),n=i-1,(e-this.x[n])*(this.y[i]-this.y[n])/(this.x[i]-this.x[n])+this.y[n]):0};var r=function(){var e,t,n;return function(i,r){for(t=-1,e=i.length;e-t>1;)i[n=e+t>>1]<=r?t=n:e=n;return e}}()},getInterpolateFunction:function(e){y.controller.spline||(y.controller.spline=y.params.loop?new y.controller.LinearSpline(y.slidesGrid,e.slidesGrid):new y.controller.LinearSpline(y.snapGrid,e.snapGrid))},setTranslate:function(e,t){function i(t){e=t.rtl&&"horizontal"===t.params.direction?-y.translate:y.translate,"slide"===y.params.controlBy&&(y.controller.getInterpolateFunction(t),a=-y.controller.spline.interpolate(-e)),a&&"container"!==y.params.controlBy||(r=(t.maxTranslate()-t.minTranslate())/(y.maxTranslate()-y.minTranslate()),a=(e-y.minTranslate())*r+t.minTranslate()),y.params.controlInverse&&(a=t.maxTranslate()-a),t.updateProgress(a),t.setWrapperTranslate(a,!1,y),t.updateActiveIndex()}var r,a,o=y.params.control;if(y.isArray(o))for(var s=0;s<o.length;s++)o[s]!==t&&o[s]instanceof n&&i(o[s]);else o instanceof n&&t!==o&&i(o)},setTransition:function(e,t){function i(t){t.setWrapperTransition(e,y),0!==e&&(t.onTransitionStart(),t.wrapper.transitionEnd(function(){a&&(t.params.loop&&"slide"===y.params.controlBy&&t.fixLoop(),t.onTransitionEnd())}))}var r,a=y.params.control;if(y.isArray(a))for(r=0;r<a.length;r++)a[r]!==t&&a[r]instanceof n&&i(a[r]);else a instanceof n&&t!==a&&i(a)}},y.hashnav={init:function(){if(y.params.hashnav){y.hashnav.initialized=!0;var e=document.location.hash.replace("#","");if(e)for(var t=0,n=0,i=y.slides.length;i>n;n++){var r=y.slides.eq(n),a=r.attr("data-hash");if(a===e&&!r.hasClass(y.params.slideDuplicateClass)){var o=r.index();y.slideTo(o,t,y.params.runCallbacksOnInit,!0)}}}},setHash:function(){y.hashnav.initialized&&y.params.hashnav&&(document.location.hash=y.slides.eq(y.activeIndex).attr("data-hash")||"")}},y.disableKeyboardControl=function(){y.params.keyboardControl=!1,t(document).off("keydown",p)},y.enableKeyboardControl=function(){y.params.keyboardControl=!0,t(document).on("keydown",p)},y.mousewheel={event:!1,lastScrollTime:(new window.Date).getTime()},y.params.mousewheelControl){try{new window.WheelEvent("wheel"),y.mousewheel.event="wheel"}catch(H){}y.mousewheel.event||void 0===document.onmousewheel||(y.mousewheel.event="mousewheel"),y.mousewheel.event||(y.mousewheel.event="DOMMouseScroll")}y.disableMousewheelControl=function(){return y.mousewheel.event?(y.container.off(y.mousewheel.event,h),!0):!1},y.enableMousewheelControl=function(){return y.mousewheel.event?(y.container.on(y.mousewheel.event,h),!0):!1},y.parallax={setTranslate:function(){y.container.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){f(this,y.progress)}),y.slides.each(function(){var e=t(this);e.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var t=Math.min(Math.max(e[0].progress,-1),1);f(this,t)})})},setTransition:function(e){"undefined"==typeof e&&(e=y.params.speed),y.container.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var n=t(this),i=parseInt(n.attr("data-swiper-parallax-duration"),10)||e;0===e&&(i=0),n.transition(i)})}},y._plugins=[];for(var Y in y.plugins){var X=y.plugins[Y](y,y.params[Y]);X&&y._plugins.push(X)}return y.callPlugins=function(e){for(var t=0;t<y._plugins.length;t++)e in y._plugins[t]&&y._plugins[t][e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.emitterEventListeners={},y.emit=function(e){y.params[e]&&y.params[e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);var t;if(y.emitterEventListeners[e])for(t=0;t<y.emitterEventListeners[e].length;t++)y.emitterEventListeners[e][t](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);y.callPlugins&&y.callPlugins(e,arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.on=function(e,t){return e=m(e),y.emitterEventListeners[e]||(y.emitterEventListeners[e]=[]),y.emitterEventListeners[e].push(t),y},y.off=function(e,t){var n;if(e=m(e),"undefined"==typeof t)return y.emitterEventListeners[e]=[],y;if(y.emitterEventListeners[e]&&0!==y.emitterEventListeners[e].length){for(n=0;n<y.emitterEventListeners[e].length;n++)y.emitterEventListeners[e][n]===t&&y.emitterEventListeners[e].splice(n,1);return y}},y.once=function(e,t){e=m(e);var n=function(){t(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]),y.off(e,n)};return y.on(e,n),y},y.a11y={makeFocusable:function(e){return e.attr("tabIndex","0"),e},addRole:function(e,t){return e.attr("role",t),e},addLabel:function(e,t){return e.attr("aria-label",t),e},disable:function(e){return e.attr("aria-disabled",!0),e},enable:function(e){return e.attr("aria-disabled",!1),e},onEnterKey:function(e){13===e.keyCode&&(t(e.target).is(y.params.nextButton)?(y.onClickNext(e),y.isEnd?y.a11y.notify(y.params.lastSlideMessage):y.a11y.notify(y.params.nextSlideMessage)):t(e.target).is(y.params.prevButton)&&(y.onClickPrev(e),y.isBeginning?y.a11y.notify(y.params.firstSlideMessage):y.a11y.notify(y.params.prevSlideMessage)),t(e.target).is("."+y.params.bulletClass)&&t(e.target)[0].click())},liveRegion:t('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'),notify:function(e){var t=y.a11y.liveRegion;0!==t.length&&(t.html(""),t.html(e))},init:function(){if(y.params.nextButton){var e=t(y.params.nextButton);y.a11y.makeFocusable(e),y.a11y.addRole(e,"button"),y.a11y.addLabel(e,y.params.nextSlideMessage)}if(y.params.prevButton){var n=t(y.params.prevButton);y.a11y.makeFocusable(n),y.a11y.addRole(n,"button"),y.a11y.addLabel(n,y.params.prevSlideMessage)}t(y.container).append(y.a11y.liveRegion)},initPagination:function(){y.params.pagination&&y.params.paginationClickable&&y.bullets&&y.bullets.length&&y.bullets.each(function(){var e=t(this);y.a11y.makeFocusable(e),y.a11y.addRole(e,"button"),y.a11y.addLabel(e,y.params.paginationBulletMessage.replace(/{{index}}/,e.index()+1))})},destroy:function(){y.a11y.liveRegion&&y.a11y.liveRegion.length>0&&y.a11y.liveRegion.remove()}},y.init=function(){y.params.loop&&y.createLoop(),y.updateContainerSize(),y.updateSlidesSize(),y.updatePagination(),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.set(),y.params.scrollbarDraggable&&y.scrollbar.enableDraggable()),"slide"!==y.params.effect&&y.effects[y.params.effect]&&(y.params.loop||y.updateProgress(),y.effects[y.params.effect].setTranslate()),y.params.loop?y.slideTo(y.params.initialSlide+y.loopedSlides,0,y.params.runCallbacksOnInit):(y.slideTo(y.params.initialSlide,0,y.params.runCallbacksOnInit),0===y.params.initialSlide&&(y.parallax&&y.params.parallax&&y.parallax.setTranslate(),y.lazy&&y.params.lazyLoading&&(y.lazy.load(),y.lazy.initialImageLoaded=!0))),y.attachEvents(),y.params.observer&&y.support.observer&&y.initObservers(),y.params.preloadImages&&!y.params.lazyLoading&&y.preloadImages(),y.params.autoplay&&y.startAutoplay(),y.params.keyboardControl&&y.enableKeyboardControl&&y.enableKeyboardControl(),y.params.mousewheelControl&&y.enableMousewheelControl&&y.enableMousewheelControl(),y.params.hashnav&&y.hashnav&&y.hashnav.init(),y.params.a11y&&y.a11y&&y.a11y.init(),y.emit("onInit",y)},y.cleanupStyles=function(){y.container.removeClass(y.classNames.join(" ")).removeAttr("style"),y.wrapper.removeAttr("style"),y.slides&&y.slides.length&&y.slides.removeClass([y.params.slideVisibleClass,y.params.slideActiveClass,y.params.slideNextClass,y.params.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-column").removeAttr("data-swiper-row"),y.paginationContainer&&y.paginationContainer.length&&y.paginationContainer.removeClass(y.params.paginationHiddenClass),y.bullets&&y.bullets.length&&y.bullets.removeClass(y.params.bulletActiveClass),y.params.prevButton&&t(y.params.prevButton).removeClass(y.params.buttonDisabledClass),y.params.nextButton&&t(y.params.nextButton).removeClass(y.params.buttonDisabledClass),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.track&&y.scrollbar.track.length&&y.scrollbar.track.removeAttr("style"),y.scrollbar.drag&&y.scrollbar.drag.length&&y.scrollbar.drag.removeAttr("style"))},y.destroy=function(e,t){y.detachEvents(),y.stopAutoplay(),y.params.scrollbar&&y.scrollbar&&y.params.scrollbarDraggable&&y.scrollbar.disableDraggable(),y.params.loop&&y.destroyLoop(),t&&y.cleanupStyles(),y.disconnectObservers(),y.params.keyboardControl&&y.disableKeyboardControl&&y.disableKeyboardControl(),y.params.mousewheelControl&&y.disableMousewheelControl&&y.disableMousewheelControl(),y.params.a11y&&y.a11y&&y.a11y.destroy(),y.emit("onDestroy"),e!==!1&&(y=null)},y.init(),y}};n.prototype={isSafari:function(){var e=navigator.userAgent.toLowerCase();return e.indexOf("safari")>=0&&e.indexOf("chrome")<0&&e.indexOf("android")<0}(),isUiWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent),isArray:function(e){return"[object Array]"===Object.prototype.toString.apply(e)},browser:{ie:window.navigator.pointerEnabled||window.navigator.msPointerEnabled,ieTouch:window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>1||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>1},device:function(){var e=navigator.userAgent,t=e.match(/(Android);?[\s\/]+([\d.]+)?/),n=e.match(/(iPad).*OS\s([\d_]+)/),i=e.match(/(iPod)(.*OS\s([\d_]+))?/),r=!n&&e.match(/(iPhone\sOS)\s([\d_]+)/);return{ios:n||r||i,android:t}}(),support:{touch:window.Modernizr&&Modernizr.touch===!0||function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)}(),transforms3d:window.Modernizr&&Modernizr.csstransforms3d===!0||function(){var e=document.createElement("div").style;return"webkitPerspective"in e||"MozPerspective"in e||"OPerspective"in e||"MsPerspective"in e||"perspective"in e}(),flexbox:function(){for(var e=document.createElement("div").style,t="alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient".split(" "),n=0;n<t.length;n++)if(t[n]in e)return!0}(),observer:function(){return"MutationObserver"in window||"WebkitMutationObserver"in window}()},plugins:{}};for(var i=(function(){var e=function(e){var t=this,n=0;for(n=0;n<e.length;n++)t[n]=e[n];return t.length=e.length,this},t=function(t,n){var i=[],r=0;if(t&&!n&&t instanceof e)return t;if(t)if("string"==typeof t){var a,o,s=t.trim();if(s.indexOf("<")>=0&&s.indexOf(">")>=0){var l="div";for(0===s.indexOf("<li")&&(l="ul"),0===s.indexOf("<tr")&&(l="tbody"),(0===s.indexOf("<td")||0===s.indexOf("<th"))&&(l="tr"),0===s.indexOf("<tbody")&&(l="table"),0===s.indexOf("<option")&&(l="select"),o=document.createElement(l),o.innerHTML=t,r=0;r<o.childNodes.length;r++)i.push(o.childNodes[r])}else for(a=n||"#"!==t[0]||t.match(/[ .<>:~]/)?(n||document).querySelectorAll(t):[document.getElementById(t.split("#")[1])],r=0;r<a.length;r++)a[r]&&i.push(a[r])}else if(t.nodeType||t===window||t===document)i.push(t);else if(t.length>0&&t[0].nodeType)for(r=0;r<t.length;r++)i.push(t[r]);return new e(i)};return e.prototype={addClass:function(e){if("undefined"==typeof e)return this;for(var t=e.split(" "),n=0;n<t.length;n++)for(var i=0;i<this.length;i++)this[i].classList.add(t[n]);return this},removeClass:function(e){for(var t=e.split(" "),n=0;n<t.length;n++)for(var i=0;i<this.length;i++)this[i].classList.remove(t[n]);return this},hasClass:function(e){return this[0]?this[0].classList.contains(e):!1},toggleClass:function(e){for(var t=e.split(" "),n=0;n<t.length;n++)for(var i=0;i<this.length;i++)this[i].classList.toggle(t[n]);return this},attr:function(e,t){if(1===arguments.length&&"string"==typeof e)return this[0]?this[0].getAttribute(e):void 0;for(var n=0;n<this.length;n++)if(2===arguments.length)this[n].setAttribute(e,t);else for(var i in e)this[n][i]=e[i],this[n].setAttribute(i,e[i]);return this},removeAttr:function(e){for(var t=0;t<this.length;t++)this[t].removeAttribute(e);return this},data:function(e,t){if("undefined"==typeof t){if(this[0]){var n=this[0].getAttribute("data-"+e);return n?n:this[0].dom7ElementDataStorage&&e in this[0].dom7ElementDataStorage?this[0].dom7ElementDataStorage[e]:void 0}return void 0}for(var i=0;i<this.length;i++){var r=this[i];r.dom7ElementDataStorage||(r.dom7ElementDataStorage={}),r.dom7ElementDataStorage[e]=t}return this},transform:function(e){for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransform=n.MsTransform=n.msTransform=n.MozTransform=n.OTransform=n.transform=e}return this},transition:function(e){"string"!=typeof e&&(e+="ms");for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransitionDuration=n.MsTransitionDuration=n.msTransitionDuration=n.MozTransitionDuration=n.OTransitionDuration=n.transitionDuration=e}return this},on:function(e,n,i,r){function a(e){var r=e.target;if(t(r).is(n))i.call(r,e);else for(var a=t(r).parents(),o=0;o<a.length;o++)t(a[o]).is(n)&&i.call(a[o],e)}var o,s,l=e.split(" ");for(o=0;o<this.length;o++)if("function"==typeof n||n===!1)for("function"==typeof n&&(i=arguments[1],r=arguments[2]||!1),s=0;s<l.length;s++)this[o].addEventListener(l[s],i,r);else for(s=0;s<l.length;s++)this[o].dom7LiveListeners||(this[o].dom7LiveListeners=[]),this[o].dom7LiveListeners.push({listener:i,liveListener:a}),this[o].addEventListener(l[s],a,r);return this},off:function(e,t,n,i){for(var r=e.split(" "),a=0;a<r.length;a++)for(var o=0;o<this.length;o++)if("function"==typeof t||t===!1)"function"==typeof t&&(n=arguments[1],i=arguments[2]||!1),this[o].removeEventListener(r[a],n,i);else if(this[o].dom7LiveListeners)for(var s=0;s<this[o].dom7LiveListeners.length;s++)this[o].dom7LiveListeners[s].listener===n&&this[o].removeEventListener(r[a],this[o].dom7LiveListeners[s].liveListener,i);return this},once:function(e,t,n,i){function r(o){n(o),a.off(e,t,r,i)}var a=this;"function"==typeof t&&(t=!1,n=arguments[1],i=arguments[2]),a.on(e,t,r,i)},trigger:function(e,t){for(var n=0;n<this.length;n++){var i;try{i=new window.CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0})}catch(r){i=document.createEvent("Event"),i.initEvent(e,!0,!0),i.detail=t}this[n].dispatchEvent(i)}return this},transitionEnd:function(e){function t(a){if(a.target===this)for(e.call(this,a),n=0;n<i.length;n++)r.off(i[n],t)}var n,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],r=this;if(e)for(n=0;n<i.length;n++)r.on(i[n],t);return this},width:function(){return this[0]===window?window.innerWidth:this.length>0?parseFloat(this.css("width")):null},outerWidth:function(e){return this.length>0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null},height:function(){return this[0]===window?window.innerHeight:this.length>0?parseFloat(this.css("height")):null},outerHeight:function(e){return this.length>0?e?this[0].offsetHeight+parseFloat(this.css("margin-top"))+parseFloat(this.css("margin-bottom")):this[0].offsetHeight:null},offset:function(){if(this.length>0){var e=this[0],t=e.getBoundingClientRect(),n=document.body,i=e.clientTop||n.clientTop||0,r=e.clientLeft||n.clientLeft||0,a=window.pageYOffset||e.scrollTop,o=window.pageXOffset||e.scrollLeft;return{top:t.top+a-i,left:t.left+o-r}}return null},css:function(e,t){var n;if(1===arguments.length){if("string"!=typeof e){for(n=0;n<this.length;n++)for(var i in e)this[n].style[i]=e[i];return this}if(this[0])return window.getComputedStyle(this[0],null).getPropertyValue(e)}if(2===arguments.length&&"string"==typeof e){for(n=0;n<this.length;n++)this[n].style[e]=t;return this}return this},each:function(e){for(var t=0;t<this.length;t++)e.call(this[t],t,this[t]);return this},html:function(e){if("undefined"==typeof e)return this[0]?this[0].innerHTML:void 0;for(var t=0;t<this.length;t++)this[t].innerHTML=e;return this},is:function(n){if(!this[0])return!1;var i,r;if("string"==typeof n){var a=this[0];if(a===document)return n===document;if(a===window)return n===window;if(a.matches)return a.matches(n);if(a.webkitMatchesSelector)return a.webkitMatchesSelector(n);if(a.mozMatchesSelector)return a.mozMatchesSelector(n);if(a.msMatchesSelector)return a.msMatchesSelector(n);for(i=t(n),r=0;r<i.length;r++)if(i[r]===this[0])return!0;return!1}if(n===document)return this[0]===document;if(n===window)return this[0]===window;if(n.nodeType||n instanceof e){for(i=n.nodeType?[n]:n,r=0;r<i.length;r++)if(i[r]===this[0])return!0;return!1}return!1},index:function(){if(this[0]){for(var e=this[0],t=0;null!==(e=e.previousSibling);)1===e.nodeType&&t++;return t}return void 0},eq:function(t){if("undefined"==typeof t)return this;var n,i=this.length;return t>i-1?new e([]):0>t?(n=i+t,new e(0>n?[]:[this[n]])):new e([this[t]])},append:function(t){var n,i;for(n=0;n<this.length;n++)if("string"==typeof t){var r=document.createElement("div");for(r.innerHTML=t;r.firstChild;)this[n].appendChild(r.firstChild)}else if(t instanceof e)for(i=0;i<t.length;i++)this[n].appendChild(t[i]);else this[n].appendChild(t);return this},prepend:function(t){var n,i;for(n=0;n<this.length;n++)if("string"==typeof t){var r=document.createElement("div");for(r.innerHTML=t,i=r.childNodes.length-1;i>=0;i--)this[n].insertBefore(r.childNodes[i],this[n].childNodes[0])}else if(t instanceof e)for(i=0;i<t.length;i++)this[n].insertBefore(t[i],this[n].childNodes[0]);else this[n].insertBefore(t,this[n].childNodes[0]); +return this},insertBefore:function(e){for(var n=t(e),i=0;i<this.length;i++)if(1===n.length)n[0].parentNode.insertBefore(this[i],n[0]);else if(n.length>1)for(var r=0;r<n.length;r++)n[r].parentNode.insertBefore(this[i].cloneNode(!0),n[r])},insertAfter:function(e){for(var n=t(e),i=0;i<this.length;i++)if(1===n.length)n[0].parentNode.insertBefore(this[i],n[0].nextSibling);else if(n.length>1)for(var r=0;r<n.length;r++)n[r].parentNode.insertBefore(this[i].cloneNode(!0),n[r].nextSibling)},next:function(n){return new e(this.length>0?n?this[0].nextElementSibling&&t(this[0].nextElementSibling).is(n)?[this[0].nextElementSibling]:[]:this[0].nextElementSibling?[this[0].nextElementSibling]:[]:[])},nextAll:function(n){var i=[],r=this[0];if(!r)return new e([]);for(;r.nextElementSibling;){var a=r.nextElementSibling;n?t(a).is(n)&&i.push(a):i.push(a),r=a}return new e(i)},prev:function(n){return new e(this.length>0?n?this[0].previousElementSibling&&t(this[0].previousElementSibling).is(n)?[this[0].previousElementSibling]:[]:this[0].previousElementSibling?[this[0].previousElementSibling]:[]:[])},prevAll:function(n){var i=[],r=this[0];if(!r)return new e([]);for(;r.previousElementSibling;){var a=r.previousElementSibling;n?t(a).is(n)&&i.push(a):i.push(a),r=a}return new e(i)},parent:function(e){for(var n=[],i=0;i<this.length;i++)e?t(this[i].parentNode).is(e)&&n.push(this[i].parentNode):n.push(this[i].parentNode);return t(t.unique(n))},parents:function(e){for(var n=[],i=0;i<this.length;i++)for(var r=this[i].parentNode;r;)e?t(r).is(e)&&n.push(r):n.push(r),r=r.parentNode;return t(t.unique(n))},find:function(t){for(var n=[],i=0;i<this.length;i++)for(var r=this[i].querySelectorAll(t),a=0;a<r.length;a++)n.push(r[a]);return new e(n)},children:function(n){for(var i=[],r=0;r<this.length;r++)for(var a=this[r].childNodes,o=0;o<a.length;o++)n?1===a[o].nodeType&&t(a[o]).is(n)&&i.push(a[o]):1===a[o].nodeType&&i.push(a[o]);return new e(t.unique(i))},remove:function(){for(var e=0;e<this.length;e++)this[e].parentNode&&this[e].parentNode.removeChild(this[e]);return this},add:function(){var e,n,i=this;for(e=0;e<arguments.length;e++){var r=t(arguments[e]);for(n=0;n<r.length;n++)i[i.length]=r[n],i.length++}return i}},t.fn=e.prototype,t.unique=function(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t},t}()),r=["jQuery","Zepto","Dom7"],a=0;a<r.length;a++)window[r[a]]&&e(window[r[a]]);var o;o="undefined"==typeof i?window.Dom7||window.Zepto||window.jQuery:i,o&&("transitionEnd"in o.fn||(o.fn.transitionEnd=function(e){function t(a){if(a.target===this)for(e.call(this,a),n=0;n<i.length;n++)r.off(i[n],t)}var n,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],r=this;if(e)for(n=0;n<i.length;n++)r.on(i[n],t);return this}),"transform"in o.fn||(o.fn.transform=function(e){for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransform=n.MsTransform=n.msTransform=n.MozTransform=n.OTransform=n.transform=e}return this}),"transition"in o.fn||(o.fn.transition=function(e){"string"!=typeof e&&(e+="ms");for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransitionDuration=n.MsTransitionDuration=n.msTransitionDuration=n.MozTransitionDuration=n.OTransitionDuration=n.transitionDuration=e}return this})),ionic.views.Swiper=n}(),function(e){"use strict";e.views.Toggle=e.views.View.inherit({initialize:function(t){var n=this;this.el=t.el,this.checkbox=t.checkbox,this.track=t.track,this.handle=t.handle,this.openPercent=-1,this.onChange=t.onChange||function(){},this.triggerThreshold=t.triggerThreshold||20,this.dragStartHandler=function(e){n.dragStart(e)},this.dragHandler=function(e){n.drag(e)},this.holdHandler=function(e){n.hold(e)},this.releaseHandler=function(e){n.release(e)},this.dragStartGesture=e.onGesture("dragstart",this.dragStartHandler,this.el),this.dragGesture=e.onGesture("drag",this.dragHandler,this.el),this.dragHoldGesture=e.onGesture("hold",this.holdHandler,this.el),this.dragReleaseGesture=e.onGesture("release",this.releaseHandler,this.el)},destroy:function(){e.offGesture(this.dragStartGesture,"dragstart",this.dragStartGesture),e.offGesture(this.dragGesture,"drag",this.dragGesture),e.offGesture(this.dragHoldGesture,"hold",this.holdHandler),e.offGesture(this.dragReleaseGesture,"release",this.releaseHandler)},tap:function(){"disabled"!==this.el.getAttribute("disabled")&&this.val(!this.checkbox.checked)},dragStart:function(e){this.checkbox.disabled||(this._dragInfo={width:this.el.offsetWidth,left:this.el.offsetLeft,right:this.el.offsetLeft+this.el.offsetWidth,triggerX:this.el.offsetWidth/2,initialState:this.checkbox.checked},e.gesture.srcEvent.preventDefault(),this.hold(e))},drag:function(t){var n=this;this._dragInfo&&(t.gesture.srcEvent.preventDefault(),e.requestAnimationFrame(function(){if(n._dragInfo){var e=t.gesture.touches[0].pageX-n._dragInfo.left,i=n._dragInfo.width-n.triggerThreshold;n._dragInfo.initialState?e<n.triggerThreshold?n.setOpenPercent(0):e>n._dragInfo.triggerX&&n.setOpenPercent(100):e<n._dragInfo.triggerX?n.setOpenPercent(0):e>i&&n.setOpenPercent(100)}}))},endDrag:function(){this._dragInfo=null},hold:function(){this.el.classList.add("dragging")},release:function(e){this.el.classList.remove("dragging"),this.endDrag(e)},setOpenPercent:function(t){if(this.openPercent<0||t<this.openPercent-3||t>this.openPercent+3)if(this.openPercent=t,0===t)this.val(!1);else if(100===t)this.val(!0);else{var n=Math.round(t/100*this.track.offsetWidth-this.handle.offsetWidth);n=1>n?0:n,this.handle.style[e.CSS.TRANSFORM]="translate3d("+n+"px,0,0)"}},val:function(t){return(t===!0||t===!1)&&(""!==this.handle.style[e.CSS.TRANSFORM]&&(this.handle.style[e.CSS.TRANSFORM]=""),this.checkbox.checked=t,this.openPercent=t?100:0,this.onChange&&this.onChange()),this.checkbox.checked}})}(ionic)}(); /*! * ionic.bundle.js is a concatenation of: * ionic.js, angular.js, angular-animate.js, @@ -30,254 +33,294 @@ a.__scheduledZoom=o;var c=a.__scrollLeft,u=a.__scrollTop,d=a.__zoomLevel,_=e-c,h */ /* - AngularJS v1.3.13 - (c) 2010-2014 Google, Inc. http://angularjs.org + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org License: MIT */ -(function(M,Y,t){'use strict';function S(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.3.13/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ta(b){if(null==b||Ua(b))return!1;var a=b.length;return b.nodeType=== -oa&&a?!0:F(b)||H(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function s(b,a,c){var d,e;if(b)if(G(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(H(b)||Ta(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==s)b.forEach(a,c,b);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d,b);return b}function Ed(b,a,c){for(var d=Object.keys(b).sort(),e=0;e<d.length;e++)a.call(c, -b[d[e]],d[e]);return d}function lc(b){return function(a,c){b(c,a)}}function Fd(){return++ob}function mc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function x(b){for(var a=b.$$hashKey,c=1,d=arguments.length;c<d;c++){var e=arguments[c];if(e)for(var f=Object.keys(e),g=0,h=f.length;g<h;g++){var l=f[g];b[l]=e[l]}}mc(b,a);return b}function ba(b){return parseInt(b,10)}function Pb(b,a){return x(Object.create(b),a)}function z(){}function pa(b){return b}function ea(b){return function(){return b}}function B(b){return"undefined"=== -typeof b}function y(b){return"undefined"!==typeof b}function I(b){return null!==b&&"object"===typeof b}function F(b){return"string"===typeof b}function V(b){return"number"===typeof b}function qa(b){return"[object Date]"===Da.call(b)}function G(b){return"function"===typeof b}function pb(b){return"[object RegExp]"===Da.call(b)}function Ua(b){return b&&b.window===b}function Va(b){return b&&b.$evalAsync&&b.$watch}function Wa(b){return"boolean"===typeof b}function nc(b){return!(!b||!(b.nodeName||b.prop&& -b.attr&&b.find))}function Gd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function ua(b){return Q(b.nodeName||b[0]&&b[0].nodeName)}function Xa(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return a}function Ea(b,a,c,d){if(Ua(b)||Va(b))throw Ka("cpws");if(a){if(b===a)throw Ka("cpi");c=c||[];d=d||[];if(I(b)){var e=c.indexOf(b);if(-1!==e)return d[e];c.push(b);d.push(a)}if(H(b))for(var f=a.length=0;f<b.length;f++)e=Ea(b[f],null,c,d),I(b[f])&&(c.push(b[f]),d.push(e)),a.push(e); -else{var g=a.$$hashKey;H(a)?a.length=0:s(a,function(b,c){delete a[c]});for(f in b)b.hasOwnProperty(f)&&(e=Ea(b[f],null,c,d),I(b[f])&&(c.push(b[f]),d.push(e)),a[f]=e);mc(a,g)}}else if(a=b)H(b)?a=Ea(b,[],c,d):qa(b)?a=new Date(b.getTime()):pb(b)?(a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex):I(b)&&(e=Object.create(Object.getPrototypeOf(b)),a=Ea(b,e,c,d));return a}function ra(b,a){if(H(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(I(b))for(c in a=a||{}, -b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ga(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(H(b)){if(!H(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ga(b[d],a[d]))return!1;return!0}}else{if(qa(b))return qa(a)?ga(b.getTime(),a.getTime()):!1;if(pb(b)&&pb(a))return b.toString()==a.toString();if(Va(b)||Va(a)||Ua(b)||Ua(a)||H(a))return!1;c={};for(d in b)if("$"!==d.charAt(0)&&!G(b[d])){if(!ga(b[d], -a[d]))return!1;c[d]=!0}for(d in a)if(!c.hasOwnProperty(d)&&"$"!==d.charAt(0)&&a[d]!==t&&!G(a[d]))return!1;return!0}return!1}function Ya(b,a,c){return b.concat(Za.call(a,c))}function oc(b,a){var c=2<arguments.length?Za.call(arguments,2):[];return!G(a)||a instanceof RegExp?a:c.length?function(){return arguments.length?a.apply(b,Ya(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Hd(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)&&"$"===b.charAt(1)? -c=t:Ua(a)?c="$WINDOW":a&&Y===a?c="$DOCUMENT":Va(a)&&(c="$SCOPE");return c}function $a(b,a){if("undefined"===typeof b)return t;V(a)||(a=a?2:null);return JSON.stringify(b,Hd,a)}function pc(b){return F(b)?JSON.parse(b):b}function va(b){b=D(b).clone();try{b.empty()}catch(a){}var c=D("<div>").append(b).html();try{return b[0].nodeType===qb?Q(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+Q(b)})}catch(d){return Q(c)}}function qc(b){try{return decodeURIComponent(b)}catch(a){}}function rc(b){var a= -{},c,d;s((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,"%20").split("="),d=qc(c[0]),y(d)&&(b=y(c[1])?qc(c[1]):!0,sc.call(a,d)?H(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];s(b,function(b,d){H(b)?s(b,function(b){a.push(Fa(d,!0)+(!0===b?"":"="+Fa(b,!0)))}):a.push(Fa(d,!0)+(!0===b?"":"="+Fa(b,!0)))});return a.length?a.join("&"):""}function rb(b){return Fa(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Fa(b,a){return encodeURIComponent(b).replace(/%40/gi, -"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Id(b,a){var c,d,e=sb.length;b=D(b);for(d=0;d<e;++d)if(c=sb[d]+a,F(c=b.attr(c)))return c;return null}function Jd(b,a){var c,d,e={};s(sb,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});s(sb,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Id(c,"strict-di"), -a(c,d?[d]:[],e))}function tc(b,a,c){I(c)||(c={});c=x({strictDi:!1},c);var d=function(){b=D(b);if(b.injector()){var d=b[0]===Y?"document":va(b);throw Ka("btstrpd",d.replace(/</,"<").replace(/>/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=ab(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector", -d);c(b)(a)})}]);return d},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;M&&e.test(M.name)&&(c.debugInfoEnabled=!0,M.name=M.name.replace(e,""));if(M&&!f.test(M.name))return d();M.name=M.name.replace(f,"");ca.resumeBootstrap=function(b){s(b,function(b){a.push(b)});return d()};G(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function Kd(){M.name="NG_ENABLE_DEBUG_INFO!"+M.name;M.location.reload()}function Ld(b){b=ca.element(b).injector();if(!b)throw Ka("test");return b.get("$$testability")} -function uc(b,a){a=a||"_";return b.replace(Md,function(b,d){return(d?a:"")+b.toLowerCase()})}function Nd(){var b;vc||((sa=M.jQuery)&&sa.fn.on?(D=sa,x(sa.fn,{scope:La.scope,isolateScope:La.isolateScope,controller:La.controller,injector:La.injector,inheritedData:La.inheritedData}),b=sa.cleanData,sa.cleanData=function(a){var c;if(Rb)Rb=!1;else for(var d=0,e;null!=(e=a[d]);d++)(c=sa._data(e,"events"))&&c.$destroy&&sa(e).triggerHandler("$destroy");b(a)}):D=R,ca.element=D,vc=!0)}function Sb(b,a,c){if(!b)throw Ka("areq", -a||"?",c||"required");return b}function tb(b,a,c){c&&H(b)&&(b=b[b.length-1]);Sb(G(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ma(b,a){if("hasOwnProperty"===b)throw Ka("badname",a);}function wc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&G(b)?oc(e,b):b}function ub(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!==b);return D(c)}function ha(){return Object.create(null)} -function Od(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=S("$injector"),d=S("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||S;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(c,d,e,f){f||(f=b);return function(){f[e||"push"]([c,d,arguments]);return u}}if(!g)throw c("nomod",f);var b=[],d=[],e=[],q=a("$injector","invoke","push",d),u={_invokeQueue:b,_configBlocks:d, -_runBlocks:e,requires:g,name:f,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:q,run:function(a){e.push(a);return this}};h&&q(h);return u})}})}function Pd(b){x(b,{bootstrap:tc,copy:Ea,extend:x,equals:ga, -element:D,forEach:s,injector:ab,noop:z,bind:oc,toJson:$a,fromJson:pc,identity:pa,isUndefined:B,isDefined:y,isString:F,isFunction:G,isObject:I,isNumber:V,isElement:nc,isArray:H,version:Qd,isDate:qa,lowercase:Q,uppercase:vb,callbacks:{counter:0},getTestability:Ld,$$minErr:S,$$csp:bb,reloadWithDebugInfo:Kd});cb=Od(M);try{cb("ngLocale")}catch(a){cb("ngLocale",[]).provider("$locale",Rd)}cb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:Sd});a.provider("$compile",xc).directive({a:Td, -input:yc,textarea:yc,form:Ud,script:Vd,select:Wd,style:Xd,option:Yd,ngBind:Zd,ngBindHtml:$d,ngBindTemplate:ae,ngClass:be,ngClassEven:ce,ngClassOdd:de,ngCloak:ee,ngController:fe,ngForm:ge,ngHide:he,ngIf:ie,ngInclude:je,ngInit:ke,ngNonBindable:le,ngPluralize:me,ngRepeat:ne,ngShow:oe,ngStyle:pe,ngSwitch:qe,ngSwitchWhen:re,ngSwitchDefault:se,ngOptions:te,ngTransclude:ue,ngModel:ve,ngList:we,ngChange:xe,pattern:zc,ngPattern:zc,required:Ac,ngRequired:Ac,minlength:Bc,ngMinlength:Bc,maxlength:Cc,ngMaxlength:Cc, -ngValue:ye,ngModelOptions:ze}).directive({ngInclude:Ae}).directive(wb).directive(Dc);a.provider({$anchorScroll:Be,$animate:Ce,$browser:De,$cacheFactory:Ee,$controller:Fe,$document:Ge,$exceptionHandler:He,$filter:Ec,$interpolate:Ie,$interval:Je,$http:Ke,$httpBackend:Le,$location:Me,$log:Ne,$parse:Oe,$rootScope:Pe,$q:Qe,$$q:Re,$sce:Se,$sceDelegate:Te,$sniffer:Ue,$templateCache:Ve,$templateRequest:We,$$testability:Xe,$timeout:Ye,$window:Ze,$$rAF:$e,$$asyncCallback:af,$$jqLite:bf})}])}function db(b){return b.replace(cf, -function(a,b,d,e){return e?d.toUpperCase():d}).replace(df,"Moz$1")}function Fc(b){b=b.nodeType;return b===oa||!b||9===b}function Gc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Tb.test(b)){c=c||e.appendChild(a.createElement("div"));d=(ef.exec(b)||["",""])[1].toLowerCase();d=ia[d]||ia._default;c.innerHTML=d[1]+b.replace(ff,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=Ya(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";s(f,function(a){e.appendChild(a)}); -return e}function R(b){if(b instanceof R)return b;var a;F(b)&&(b=U(b),a=!0);if(!(this instanceof R)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new R(b)}if(a){a=Y;var c;b=(c=gf.exec(b))?[a.createElement(c[1])]:(c=Gc(b,a))?c.childNodes:[]}Hc(this,b)}function Vb(b){return b.cloneNode(!0)}function xb(b,a){a||yb(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)yb(c[d])}function Ic(b,a,c,d){if(y(d))throw Ub("offargs");var e=(d=zb(b))&&d.events,f=d&&d.handle;if(f)if(a)s(a.split(" "), -function(a){if(y(c)){var d=e[a];Xa(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a,f,!1),delete e[a]}function yb(b,a){var c=b.ng339,d=c&&Ab[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Ic(b)),delete Ab[c],b.ng339=t))}function zb(b,a){var c=b.ng339,c=c&&Ab[c];a&&!c&&(b.ng339=c=++hf,c=Ab[c]={events:{},data:{},handle:t});return c}function Wb(b,a,c){if(Fc(b)){var d=y(c),e=!d&&a&&!I(a), -f=!a;b=(b=zb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];x(b,a)}}}function Bb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function Cb(b,a){a&&b.setAttribute&&s(a.split(" "),function(a){b.setAttribute("class",U((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+U(a)+" "," ")))})}function Db(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," "); -s(a.split(" "),function(a){a=U(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",U(c))}}function Hc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c=a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Jc(b,a){return Eb(b,"$"+(a||"ngController")+"Controller")}function Eb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=H(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=D.data(b,a[d]))!==t)return c;b=b.parentNode|| -11===b.nodeType&&b.host}}function Kc(b){for(xb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Lc(b,a){a||xb(b);var c=b.parentNode;c&&c.removeChild(b)}function jf(b,a){a=a||M;if("complete"===a.document.readyState)a.setTimeout(b);else D(a).on("load",b)}function Mc(b,a){var c=Fb[a.toLowerCase()];return c&&Nc[ua(b)]&&c}function kf(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Oc[a]}function lf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f= -a[e||c.type],g=f?f.length:0;if(g){if(B(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=ra(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function bf(){this.$get=function(){return x(R,{hasClass:function(b,a){b.attr&&(b=b[0]); -return Bb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return Db(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return Cb(b,a)}})}}function Na(b,a){var c=b&&b.$$hashKey;if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Fd)():c+":"+b}function eb(b,a){if(a){var c=0;this.nextUid=function(){return++c}}s(b,this.put,this)}function mf(b){return(b=b.toString().replace(Pc,"").match(Qc))?"function("+(b[1]||"").replace(/[\s\r\n]+/, -" ")+")":"fn"}function ab(b,a){function c(a){return function(b,c){if(I(b))s(b,lc(a));else return a(b,c)}}function d(a,b){Ma(a,"service");if(G(b)||H(b))b=q.instantiate(b);if(!b.$get)throw Ga("pget",a);return n[a+"Provider"]=b}function e(a,b){return function(){var c=r.invoke(b,this);if(B(c))throw Ga("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;s(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=q.get(e[0]);f[e[1]].apply(f, -e[2])}}if(!m.get(a)){m.put(a,!0);try{F(a)?(c=cb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):G(a)?b.push(q.invoke(a)):H(a)?b.push(q.invoke(a)):tb(a,"module")}catch(e){throw H(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ga("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Ga("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a), -b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var h=[],k=ab.$$annotate(b,a,g),l,q,n;q=0;for(l=k.length;q<l;q++){n=k[q];if("string"!==typeof n)throw Ga("itkn",n);h.push(f&&f.hasOwnProperty(n)?f[n]:d(n,g))}H(b)&&(b=b[l]);return b.apply(c,h)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((H(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return I(a)||G(a)?a:d},get:d,annotate:ab.$$annotate,has:function(a){return n.hasOwnProperty(a+ -"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],m=new eb([],!0),n={$provide:{provider:c(d),factory:c(f),service:c(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ea(b),!1)}),constant:c(function(a,b){Ma(a,"constant");n[a]=b;u[a]=b}),decorator:function(a,b){var c=q.get(a+"Provider"),d=c.$get;c.$get=function(){var a=r.invoke(d,c);return r.invoke(b,null,{$delegate:a})}}}},q=n.$injector=h(n,function(a,b){ca.isString(b)&&k.push(b); -throw Ga("unpr",k.join(" <- "));}),u={},r=u.$injector=h(u,function(a,b){var c=q.get(a+"Provider",b);return r.invoke(c.$get,c,t,a)});s(g(b),function(a){r.invoke(a||z)});return r}function Be(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ua(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;G(c)?c=c():nc(c)?(c=c[0],c="fixed"!== -a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):V(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0,0)}function g(){var a=c.hash(),b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||jf(function(){d.$evalAsync(g)})});return g}]}function af(){this.$get=["$$rAF","$timeout",function(b,a){return b.supported?function(a){return b(a)}: -function(b){return a(b,0,!1)}}]}function nf(b,a,c,d){function e(a){try{a.apply(null,Za.call(arguments,1))}finally{if(v--,0===v)for(;w.length;)try{w.pop()()}catch(b){c.error(b)}}}function f(a,b){(function N(){s(L,function(a){a()});C=b(N,a)})()}function g(){h();l()}function h(){A=b.history.state;A=B(A)?null:A;ga(A,J)&&(A=J);J=A}function l(){if(E!==m.url()||O!==A)E=m.url(),O=A,s(W,function(a){a(m.url(),A)})}function k(a){try{return decodeURIComponent(a)}catch(b){return a}}var m=this,n=a[0],q=b.location, -u=b.history,r=b.setTimeout,P=b.clearTimeout,p={};m.isMock=!1;var v=0,w=[];m.$$completeOutstandingRequest=e;m.$$incOutstandingRequestCount=function(){v++};m.notifyWhenNoOutstandingRequests=function(a){s(L,function(a){a()});0===v?a():w.push(a)};var L=[],C;m.addPollFn=function(a){B(C)&&f(100,r);L.push(a);return a};var A,O,E=q.href,T=a.find("base"),X=null;h();O=A;m.url=function(a,c,e){B(e)&&(e=null);q!==b.location&&(q=b.location);u!==b.history&&(u=b.history);if(a){var f=O===e;if(E===a&&(!d.history||f))return m; -var g=E&&Ha(E)===Ha(a);E=a;O=e;!d.history||g&&f?(g||(X=a),c?q.replace(a):g?(c=q,e=a.indexOf("#"),a=-1===e?"":a.substr(e+1),c.hash=a):q.href=a):(u[c?"replaceState":"pushState"](e,"",a),h(),O=A);return m}return X||q.href.replace(/%27/g,"'")};m.state=function(){return A};var W=[],wa=!1,J=null;m.onUrlChange=function(a){if(!wa){if(d.history)D(b).on("popstate",g);D(b).on("hashchange",g);wa=!0}W.push(a);return a};m.$$checkUrlChange=l;m.baseHref=function(){var a=T.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/, -""):""};var fa={},y="",da=m.baseHref();m.cookies=function(a,b){var d,e,f,g;if(a)b===t?n.cookie=encodeURIComponent(a)+"=;path="+da+";expires=Thu, 01 Jan 1970 00:00:00 GMT":F(b)&&(d=(n.cookie=encodeURIComponent(a)+"="+encodeURIComponent(b)+";path="+da).length+1,4096<d&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"));else{if(n.cookie!==y)for(y=n.cookie,d=y.split("; "),fa={},f=0;f<d.length;f++)e=d[f],g=e.indexOf("="),0<g&&(a=k(e.substring(0,g)), -fa[a]===t&&(fa[a]=k(e.substring(g+1))));return fa}};m.defer=function(a,b){var c;v++;c=r(function(){delete p[c];e(a)},b||0);p[c]=!0;return c};m.defer.cancel=function(a){return p[a]?(delete p[a],P(a),e(z),!0):!1}}function De(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new nf(b,d,a,c)}]}function Ee(){this.$get=function(){function b(b,d){function e(a){a!=n&&(q?q==a&&(q=a.n):q=a,f(a.n,a.p),f(a,n),n=a,n.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw S("$cacheFactory")("iid", -b);var g=0,h=x({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,m={},n=null,q=null;return a[b]={put:function(a,b){if(k<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}if(!B(b))return a in l||g++,l[a]=b,g>k&&this.remove(q.key),b},get:function(a){if(k<Number.MAX_VALUE){var b=m[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=m[a];if(!b)return;b==n&&(n=b.p);b==q&&(q=b.n);f(b.n,b.p);delete m[a]}delete l[a];g--},removeAll:function(){l={};g=0;m={};n=q=null},destroy:function(){m= -h=l=null;delete a[b]},info:function(){return x({},h,{size:g})}}}var a={};b.info=function(){var b={};s(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function Ve(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function xc(b,a){function c(a,b){var c=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,d={};s(a,function(a,e){var f=a.match(c);if(!f)throw ja("iscp",b,e,a);d[e]={mode:f[1][0],collection:"*"===f[2],optional:"?"===f[3],attrName:f[4]||e}});return d}var d= -{},e=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,f=/(([\w\-]+)(?:\:([^;]+))?;?)/,g=Gd("ngSrc,ngSrcset,src,srcset"),h=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,l=/^(on[a-z]+|formaction)$/;this.directive=function n(a,e){Ma(a,"directive");F(a)?(Sb(e,"directiveFactory"),d.hasOwnProperty(a)||(d[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,e){var f=[];s(d[a],function(d,g){try{var h=b.invoke(d);G(h)?h={compile:ea(h)}:!h.compile&&h.link&&(h.compile=ea(h.link));h.priority=h.priority||0;h.index= -g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";I(h.scope)&&(h.$$isolateBindings=c(h.scope,h.name));f.push(h)}catch(l){e(l)}});return f}])),d[a].push(e)):s(a,lc(n));return this};this.aHrefSanitizationWhitelist=function(b){return y(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};var k=!0;this.debugInfoEnabled= -function(a){return y(a)?(k=a,this):k};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,r,P,p,v,w,L,C,A){function O(a,b){try{a.addClass(b)}catch(c){}}function E(a,b,c,d,e){a instanceof D||(a=D(a));s(a,function(b,c){b.nodeType==qb&&b.nodeValue.match(/\S+/)&&(a[c]=D(b).wrap("<span></span>").parent()[0])});var f=T(a,b,a,c,d,e);E.$$addScopeClass(a);var g=null;return function(b,c, -d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ua(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?D(Xb(g,D("<div>").append(a).html())):c?La.clone.call(a):a;if(h)for(var l in h)d.data("$"+l+"Controller",h[l].instance);E.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function T(a,b,c,d,e,f){function g(a,c,d,e){var f,l,k,q,n,p,w;if(r)for(w= -Array(c.length),q=0;q<h.length;q+=3)f=h[q],w[f]=c[f];else w=c;q=0;for(n=h.length;q<n;)l=w[h[q++]],c=h[q++],f=h[q++],c?(c.scope?(k=a.$new(),E.$$addScopeInfo(D(l),k)):k=a,p=c.transcludeOnThisElement?X(a,c.transclude,e,c.elementTranscludeOnThisElement):!c.templateOnThisElement&&e?e:!e&&b?X(a,b):null,c(f,k,l,d,p)):f&&f(a,l.childNodes,t,e)}for(var h=[],l,k,q,n,r,p=0;p<a.length;p++){l=new Yb;k=W(a[p],[],l,0===p?d:t,e);(f=k.length?fa(k,a[p],l,b,c,null,[],[],f):null)&&f.scope&&E.$$addScopeClass(l.$$element); -l=f&&f.terminal||!(q=a[p].childNodes)||!q.length?null:T(q,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||l)h.push(p,f,l),n=!0,r=r||f;f=null}return n?g:null}function X(a,b,c,d){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function W(a,b,c,d,g){var h=c.$attr,l;switch(a.nodeType){case oa:da(b,ya(ua(a)),"E",d,g);for(var k,q,n,r=a.attributes,p=0,w=r&&r.length;p< -w;p++){var P=!1,L=!1;k=r[p];l=k.name;q=U(k.value);k=ya(l);if(n=gb.test(k))l=l.replace(Sc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var u=k.replace(/(Start|End)$/,"");B(u)&&k===u+"Start"&&(P=l,L=l.substr(0,l.length-5)+"end",l=l.substr(0,l.length-6));k=ya(l.toLowerCase());h[k]=l;if(n||!c.hasOwnProperty(k))c[k]=q,Mc(a,k)&&(c[k]=!0);Pa(a,b,q,k,n);da(b,k,"A",d,g,P,L)}a=a.className;I(a)&&(a=a.animVal);if(F(a)&&""!==a)for(;l=f.exec(a);)k=ya(l[2]),da(b,k,"C",d,g)&&(c[k]=U(l[3])), -a=a.substr(l.index+l[0].length);break;case qb:M(b,a.nodeValue);break;case 8:try{if(l=e.exec(a.nodeValue))k=ya(l[1]),da(b,k,"M",d,g)&&(c[k]=U(l[2]))}catch(v){}}b.sort(N);return b}function wa(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ja("uterdir",b,c);a.nodeType==oa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return D(d)}function J(a,b,c){return function(d,e,f,g,h){e=wa(e[0],b,c);return a(d,e,f,g,h)}}function fa(a, -d,e,f,g,l,k,n,r){function w(a,b,c,d){if(a){c&&(a=J(a,c,d));a.require=K.require;a.directiveName=x;if(T===K||K.$$isolateScope)a=Z(a,{isolateScope:!0});k.push(a)}if(b){c&&(b=J(b,c,d));b.require=K.require;b.directiveName=x;if(T===K||K.$$isolateScope)b=Z(b,{isolateScope:!0});n.push(b)}}function L(a,b,c,d){var e,f="data",g=!1,l=c,k;if(F(b)){k=b.match(h);b=b.substring(k[0].length);k[3]&&(k[1]?k[3]=null:k[1]=k[3]);"^"===k[1]?f="inheritedData":"^^"===k[1]&&(f="inheritedData",l=c.parent());"?"===k[2]&&(g=!0); -e=null;d&&"data"===f&&(e=d[b])&&(e=e.instance);e=e||l[f]("$"+b+"Controller");if(!e&&!g)throw ja("ctreq",b,a);return e||null}H(b)&&(e=[],s(b,function(b){e.push(L(a,b,c,d))}));return e}function v(a,c,f,g,h){function l(a,b,c){var d;Va(a)||(c=b,b=a,a=t);z&&(d=O);c||(c=z?W.parent():W);return h(a,b,d,c,wa)}var r,w,u,A,O,fb,W,J;d===f?(J=e,W=e.$$element):(W=D(f),J=new Yb(W,e));T&&(A=c.$new(!0));h&&(fb=l,fb.$$boundTransclude=h);C&&(X={},O={},s(C,function(a){var b={$scope:a===T||a.$$isolateScope?A:c,$element:W, -$attrs:J,$transclude:fb};u=a.controller;"@"==u&&(u=J[a.name]);b=p(u,b,!0,a.controllerAs);O[a.name]=b;z||W.data("$"+a.name+"Controller",b.instance);X[a.name]=b}));if(T){E.$$addScopeInfo(W,A,!0,!(ka&&(ka===T||ka===T.$$originalDirective)));E.$$addScopeClass(W,!0);g=X&&X[T.name];var xa=A;g&&g.identifier&&!0===T.bindToController&&(xa=g.instance);s(A.$$isolateBindings=T.$$isolateBindings,function(a,d){var e=a.attrName,f=a.optional,g,h,l,k;switch(a.mode){case "@":J.$observe(e,function(a){xa[d]=a});J.$$observers[e].$$scope= -c;J[e]&&(xa[d]=b(J[e])(c));break;case "=":if(f&&!J[e])break;h=P(J[e]);k=h.literal?ga:function(a,b){return a===b||a!==a&&b!==b};l=h.assign||function(){g=xa[d]=h(c);throw ja("nonassign",J[e],T.name);};g=xa[d]=h(c);f=function(a){k(a,xa[d])||(k(a,g)?l(c,a=xa[d]):xa[d]=a);return g=a};f.$stateful=!0;f=a.collection?c.$watchCollection(J[e],f):c.$watch(P(J[e],f),null,h.literal);A.$on("$destroy",f);break;case "&":h=P(J[e]),xa[d]=function(a){return h(c,a)}}})}X&&(s(X,function(a){a()}),X=null);g=0;for(r=k.length;g< -r;g++)w=k[g],$(w,w.isolateScope?A:c,W,J,w.require&&L(w.directiveName,w.require,W,O),fb);var wa=c;T&&(T.template||null===T.templateUrl)&&(wa=A);a&&a(wa,f.childNodes,t,h);for(g=n.length-1;0<=g;g--)w=n[g],$(w,w.isolateScope?A:c,W,J,w.require&&L(w.directiveName,w.require,W,O),fb)}r=r||{};for(var A=-Number.MAX_VALUE,O,C=r.controllerDirectives,X,T=r.newIsolateScopeDirective,ka=r.templateDirective,fa=r.nonTlbTranscludeDirective,da=!1,B=!1,z=r.hasElementTranscludeDirective,aa=e.$$element=D(d),K,x,N,Aa=f, -Q,M=0,R=a.length;M<R;M++){K=a[M];var Pa=K.$$start,gb=K.$$end;Pa&&(aa=wa(d,Pa,gb));N=t;if(A>K.priority)break;if(N=K.scope)K.templateUrl||(I(N)?(Oa("new/isolated scope",T||O,K,aa),T=K):Oa("new/isolated scope",T,K,aa)),O=O||K;x=K.name;!K.templateUrl&&K.controller&&(N=K.controller,C=C||{},Oa("'"+x+"' controller",C[x],K,aa),C[x]=K);if(N=K.transclude)da=!0,K.$$tlb||(Oa("transclusion",fa,K,aa),fa=K),"element"==N?(z=!0,A=K.priority,N=aa,aa=e.$$element=D(Y.createComment(" "+x+": "+e[x]+" ")),d=aa[0],V(g,Za.call(N, -0),d),Aa=E(N,f,A,l&&l.name,{nonTlbTranscludeDirective:fa})):(N=D(Vb(d)).contents(),aa.empty(),Aa=E(N,f));if(K.template)if(B=!0,Oa("template",ka,K,aa),ka=K,N=G(K.template)?K.template(aa,e):K.template,N=Tc(N),K.replace){l=K;N=Tb.test(N)?Uc(Xb(K.templateNamespace,U(N))):[];d=N[0];if(1!=N.length||d.nodeType!==oa)throw ja("tplrt",x,"");V(g,aa,d);R={$attr:{}};N=W(d,[],R);var ba=a.splice(M+1,a.length-(M+1));T&&y(N);a=a.concat(N).concat(ba);Rc(e,R);R=a.length}else aa.html(N);if(K.templateUrl)B=!0,Oa("template", -ka,K,aa),ka=K,K.replace&&(l=K),v=S(a.splice(M,a.length-M),aa,e,g,da&&Aa,k,n,{controllerDirectives:C,newIsolateScopeDirective:T,templateDirective:ka,nonTlbTranscludeDirective:fa}),R=a.length;else if(K.compile)try{Q=K.compile(aa,e,Aa),G(Q)?w(null,Q,Pa,gb):Q&&w(Q.pre,Q.post,Pa,gb)}catch(of){c(of,va(aa))}K.terminal&&(v.terminal=!0,A=Math.max(A,K.priority))}v.scope=O&&!0===O.scope;v.transcludeOnThisElement=da;v.elementTranscludeOnThisElement=z;v.templateOnThisElement=B;v.transclude=Aa;r.hasElementTranscludeDirective= -z;return v}function y(a){for(var b=0,c=a.length;b<c;b++)a[b]=Pb(a[b],{$$isolateScope:!0})}function da(b,e,f,g,h,l,k){if(e===h)return null;h=null;if(d.hasOwnProperty(e)){var q;e=a.get(e+"Directive");for(var r=0,p=e.length;r<p;r++)try{q=e[r],(g===t||g>q.priority)&&-1!=q.restrict.indexOf(f)&&(l&&(q=Pb(q,{$$start:l,$$end:k})),b.push(q),h=q)}catch(w){c(w)}}return h}function B(b){if(d.hasOwnProperty(b))for(var c=a.get(b+"Directive"),e=0,f=c.length;e<f;e++)if(b=c[e],b.multiElement)return!0;return!1}function Rc(a, -b){var c=b.$attr,d=a.$attr,e=a.$$element;s(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});s(b,function(b,f){"class"==f?(O(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function S(a,b,c,d,e,f,g,h){var l=[],k,q,n=b[0],p=a.shift(),w=Pb(p,{templateUrl:null,transclude:null,replace:null,$$originalDirective:p}), -P=G(p.templateUrl)?p.templateUrl(b,c):p.templateUrl,u=p.templateNamespace;b.empty();r(L.getTrustedResourceUrl(P)).then(function(r){var L,v;r=Tc(r);if(p.replace){r=Tb.test(r)?Uc(Xb(u,U(r))):[];L=r[0];if(1!=r.length||L.nodeType!==oa)throw ja("tplrt",p.name,P);r={$attr:{}};V(d,b,L);var A=W(L,[],r);I(p.scope)&&y(A);a=A.concat(a);Rc(c,r)}else L=n,b.html(r);a.unshift(w);k=fa(a,L,c,e,b,p,f,g,h);s(d,function(a,c){a==L&&(d[c]=b[0])});for(q=T(b[0].childNodes,e);l.length;){r=l.shift();v=l.shift();var C=l.shift(), -E=l.shift(),A=b[0];if(!r.$$destroyed){if(v!==n){var J=v.className;h.hasElementTranscludeDirective&&p.replace||(A=Vb(L));V(C,D(v),A);O(D(A),J)}v=k.transcludeOnThisElement?X(r,k.transclude,E):E;k(q,r,A,d,v)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(k.transcludeOnThisElement&&(a=X(b,k.transclude,e)),k(q,b,c,d,a)))}}function N(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function Oa(a,b,c,d){if(b)throw ja("multidir", -b.name,c.name,a,va(d));}function M(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&E.$$addBindingClass(a);return function(a,c){var e=c.parent();b||E.$$addBindingClass(e);E.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Xb(a,b){a=Q(a||"html");switch(a){case "svg":case "math":var c=Y.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function R(a,b){if("srcdoc"== -b)return L.HTML;var c=ua(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return L.RESOURCE_URL}function Pa(a,c,d,e,f){var h=R(a,e);f=g[e]||f;var k=b(d,!0,h,f);if(k){if("multiple"===e&&"select"===ua(a))throw ja("selmulti",va(a));c.push({priority:100,compile:function(){return{pre:function(a,c,g){c=g.$$observers||(g.$$observers={});if(l.test(e))throw ja("nodomevents");var n=g[e];n!==d&&(k=n&&b(n,!0,h,f),d=n);k&&(g[e]=k(a),(c[e]||(c[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope|| -a).$watch(k,function(a,b){"class"===e&&a!=b?g.$updateClass(a,b):g.$set(e,a)}))}}}})}}function V(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var l=a.length;g<l;g++,h++)h<l?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=Y.createDocumentFragment();a.appendChild(d);D(c).data(D(d).data());sa?(Rb=!0,sa.cleanData([d])):delete D.cache[d[D.expando]];d=1;for(e=b.length;d<e;d++)f=b[d],D(f).remove(), -a.appendChild(f),delete b[d];b[0]=c;b.length=1}function Z(a,b){return x(function(){return a.apply(null,arguments)},a,b)}function $(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,va(d))}}var Yb=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=a};Yb.prototype={$normalize:ya,$addClass:function(a){a&&0<a.length&&C.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&C.removeClass(this.$$element,a)},$updateClass:function(a, -b){var c=Vc(a,b);c&&c.length&&C.addClass(this.$$element,c);(c=Vc(b,a))&&c.length&&C.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Mc(f,a),h=kf(f,a),f=a;g?(this.$$element.prop(a,b),e=g):h&&(this[h]=b,f=h);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=uc(a,"-"));g=ua(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=A(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",h=U(b),l=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,l=/\s/.test(h)? -l:/(,)/,h=h.split(l),l=Math.floor(h.length/2),k=0;k<l;k++)var q=2*k,g=g+A(U(h[q]),!0),g=g+(" "+U(h[q+1]));h=U(h[2*k]).split(/\s/);g+=A(U(h[0]),!0);2===h.length&&(g+=" "+U(h[1]));this[a]=b=g}!1!==d&&(null===b||b===t?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&s(a[f],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ha()),e=d[a]||(d[a]=[]);e.push(b);v.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])}); -return function(){Xa(e,b)}}};var Aa=b.startSymbol(),ka=b.endSymbol(),Tc="{{"==Aa||"}}"==ka?pa:function(a){return a.replace(/\{\{/g,Aa).replace(/}}/g,ka)},gb=/^ngAttr[A-Z]/;E.$$addBindingInfo=k?function(a,b){var c=a.data("$binding")||[];H(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:z;E.$$addBindingClass=k?function(a){O(a,"ng-binding")}:z;E.$$addScopeInfo=k?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:z;E.$$addScopeClass=k?function(a,b){O(a,b?"ng-isolate-scope": -"ng-scope")}:z;return E}]}function ya(b){return db(b.replace(Sc,""))}function Vc(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function Uc(b){b=D(b);var a=b.length;if(1>=a)return b;for(;a--;)8===b[a].nodeType&&pf.call(b,a,1);return b}function Fe(){var b={},a=!1,c=/^(\S+)(\s+as\s+(\w+))?$/;this.register=function(a,c){Ma(a,"controller");I(a)?x(b,a):b[a]=c};this.allowGlobals=function(){a= -!0};this.$get=["$injector","$window",function(d,e){function f(a,b,c,d){if(!a||!I(a.$scope))throw S("$controller")("noscp",d,b);a.$scope[b]=c}return function(g,h,l,k){var m,n,q;l=!0===l;k&&F(k)&&(q=k);if(F(g)){k=g.match(c);if(!k)throw qf("ctrlfmt",g);n=k[1];q=q||k[3];g=b.hasOwnProperty(n)?b[n]:wc(h.$scope,n,!0)||(a?wc(e,n,!0):t);tb(g,n,!0)}if(l)return l=(H(g)?g[g.length-1]:g).prototype,m=Object.create(l||null),q&&f(h,q,m,n||g.name),x(function(){d.invoke(g,m,h,n);return m},{instance:m,identifier:q}); -m=d.instantiate(g,h,n);q&&f(h,q,m,n||g.name);return m}}]}function Ge(){this.$get=["$window",function(b){return D(b.document)}]}function He(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b,a){if(F(b)){var c=b.replace(rf,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(Wc))||(d=(d=c.match(sf))&&tf[d[0]].test(c));d&&(b=pc(c))}}return b}function Xc(b){var a=ha(),c,d,e;if(!b)return a;s(b.split("\n"),function(b){e=b.indexOf(":");c=Q(U(b.substr(0, -e)));d=U(b.substr(e+1));c&&(a[c]=a[c]?a[c]+", "+d:d)});return a}function Yc(b){var a=I(b)?b:t;return function(c){a||(a=Xc(b));return c?(c=a[Q(c)],void 0===c&&(c=null),c):a}}function Zc(b,a,c,d){if(G(d))return d(b,a,c);s(d,function(d){b=d(b,a,c)});return b}function Ke(){var b=this.defaults={transformResponse:[Zb],transformRequest:[function(a){return I(a)&&"[object File]"!==Da.call(a)&&"[object Blob]"!==Da.call(a)&&"[object FormData]"!==Da.call(a)?$a(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"}, -post:ra($b),put:ra($b),patch:ra($b)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},a=!1;this.useApplyAsync=function(b){return y(b)?(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=x({},a);b.data=a.data?Zc(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a){var b,c={};s(a,function(a,d){G(a)?(b= -a(),null!=b&&(c[d]=b)):c[d]=a});return c}if(!ca.isObject(a))throw S("$http")("badreq",a);var e=x({method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse},a);e.headers=function(a){var c=b.headers,e=x({},a.headers),f,g,c=x({},c.common,c[Q(a.method)]);a:for(f in c){a=Q(f);for(g in e)if(Q(g)===a)continue a;e[f]=c[f]}return d(e)}(a);e.method=vb(e.method);var f=[function(a){var d=a.headers,e=Zc(a.data,Yc(d),t,a.transformRequest);B(e)&&s(d,function(a,b){"content-type"===Q(b)&& -delete d[b]});B(a.withCredentials)&&!B(b.withCredentials)&&(a.withCredentials=b.withCredentials);return m(a,e).then(c,c)},t],g=h.when(e);for(s(u,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var l=f.shift(),g=g.then(a,l)}g.success=function(a){g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){g.then(null,function(b){a(b.data,b.status,b.headers,e)}); -return g};return g}function m(c,f){function l(b,c,d,e){function f(){m(c,b,d,e)}O&&(200<=b&&300>b?O.put(X,[b,c,Xc(d),e]):O.remove(X));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function m(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?C.resolve:C.reject)({data:a,status:b,headers:Yc(d),config:c,statusText:e})}function w(a){m(a.data,a.status,ra(a.headers()),a.statusText)}function u(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var C=h.defer(),A=C.promise,O,E,s=c.headers,X=n(c.url, -c.params);k.pendingRequests.push(c);A.then(u,u);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(O=I(c.cache)?c.cache:I(b.cache)?b.cache:q);O&&(E=O.get(X),y(E)?E&&G(E.then)?E.then(w,w):H(E)?m(E[1],E[0],ra(E[2]),E[3]):m(E,200,{},"OK"):O.put(X,A));B(E)&&((E=$c(c.url)?e.cookies()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(s[c.xsrfHeaderName||b.xsrfHeaderName]=E),d(c.method,X,f,l,s,c.timeout,c.withCredentials,c.responseType));return A}function n(a,b){if(!b)return a;var c=[];Ed(b, -function(a,b){null===a||B(a)||(H(a)||(a=[a]),s(a,function(a){I(a)&&(a=qa(a)?a.toISOString():$a(a));c.push(Fa(b)+"="+Fa(a))}))});0<c.length&&(a+=(-1==a.indexOf("?")?"?":"&")+c.join("&"));return a}var q=f("$http"),u=[];s(c,function(a){u.unshift(F(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){s(arguments,function(a){k[a]=function(b,c){return k(x(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){s(arguments,function(a){k[a]=function(b,c,d){return k(x(d||{},{method:a, -url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function uf(){return new M.XMLHttpRequest}function Le(){this.$get=["$browser","$window","$document",function(b,a,c){return vf(b,uf,b.defer,a.angular.callbacks,c[0])}]}function vf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m,!1);f.removeEventListener("error",m,!1);e.body.removeChild(f);f=null;var g=-1,u="unknown";a&&("load"!== -a.type||d[b].called||(a={type:"error"}),u=a.type,g="error"===a.type?404:200);c&&c(g,u)};f.addEventListener("load",m,!1);f.addEventListener("error",m,!1);e.body.appendChild(f);return m}return function(e,h,l,k,m,n,q,u){function r(){v&&v();w&&w.abort()}function P(a,d,e,f,g){C!==t&&c.cancel(C);v=w=null;a(d,e,f,g);b.$$completeOutstandingRequest(z)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==Q(e)){var p="_"+(d.counter++).toString(36);d[p]=function(a){d[p].data=a;d[p].called=!0};var v=f(h.replace("JSON_CALLBACK", -"angular.callbacks."+p),p,function(a,b){P(k,a,d[p].data,"",b);d[p]=z})}else{var w=a();w.open(e,h,!0);s(m,function(a,b){y(a)&&w.setRequestHeader(b,a)});w.onload=function(){var a=w.statusText||"",b="response"in w?w.response:w.responseText,c=1223===w.status?204:w.status;0===c&&(c=b?200:"file"==Ba(h).protocol?404:0);P(k,c,b,w.getAllResponseHeaders(),a)};e=function(){P(k,-1,null,null,"")};w.onerror=e;w.onabort=e;q&&(w.withCredentials=!0);if(u)try{w.responseType=u}catch(L){if("json"!==u)throw L;}w.send(l|| -null)}if(0<n)var C=c(r,n);else n&&G(n.then)&&n.then(r)}}function Ie(){var b="{{",a="}}";this.startSymbol=function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(f,g,u,r){function P(c){return c.replace(k,b).replace(m,a)}function p(a){try{var b=a;a=u?e.getTrusted(u,b):e.valueOf(b);var c;if(r&&!y(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;case "number":a= -""+a;break;default:a=$a(a)}c=a}return c}catch(g){c=ac("interr",f,g.toString()),d(c)}}r=!!r;for(var v,w,L=0,C=[],A=[],O=f.length,E=[],s=[];L<O;)if(-1!=(v=f.indexOf(b,L))&&-1!=(w=f.indexOf(a,v+h)))L!==v&&E.push(P(f.substring(L,v))),L=f.substring(v+h,w),C.push(L),A.push(c(L,p)),L=w+l,s.push(E.length),E.push("");else{L!==O&&E.push(P(f.substring(L)));break}if(u&&1<E.length)throw ac("noconcat",f);if(!g||C.length){var X=function(a){for(var b=0,c=C.length;b<c;b++){if(r&&B(a[b]))return;E[s[b]]=a[b]}return E.join("")}; -return x(function(a){var b=0,c=C.length,e=Array(c);try{for(;b<c;b++)e[b]=A[b](a);return X(e)}catch(g){a=ac("interr",f,g.toString()),d(a)}},{exp:f,expressions:C,$$watchDelegate:function(a,b,c){var d;return a.$watchGroup(A,function(c,e){var f=X(c);G(b)&&b.call(this,f,c!==e?d:f,a);d=f},c)}})}}var h=b.length,l=a.length,k=new RegExp(b.replace(/./g,f),"g"),m=new RegExp(a.replace(/./g,f),"g");g.startSymbol=function(){return b};g.endSymbol=function(){return a};return g}]}function Je(){this.$get=["$rootScope", -"$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var m=a.setInterval,n=a.clearInterval,q=0,u=y(k)&&!k,r=(u?d:c).defer(),P=r.promise;l=y(l)?l:0;P.then(null,null,e);P.$$intervalId=m(function(){r.notify(q++);0<l&&q>=l&&(r.resolve(q),n(P.$$intervalId),delete f[P.$$intervalId]);u||b.$apply()},h);f[P.$$intervalId]=r;return P}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]} -function Rd(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "), -DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a"},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=rb(b[a]);return b.join("/")}function ad(b,a){var c=Ba(b);a.$$protocol= -c.protocol;a.$$host=c.hostname;a.$$port=ba(c.port)||wf[c.protocol]||null}function bd(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=rc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function za(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ha(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Gb(b){return b.replace(/(#.+)|#$/, -"$1")}function cc(b){return b.substr(0,Ha(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);ad(b,this);this.$$parse=function(a){var b=za(c,a);if(!F(b))throw Hb("ipthprfx",a,c);bd(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+rb(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)), -!0;var f,g;(f=za(b,d))!==t?(g=f,g=(f=za(a,f))!==t?c+(za("/",f)||f):b+g):(f=za(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);ad(b,this);this.$$parse=function(d){d=za(b,d)||za(c,d);var e;"#"===d.charAt(0)?(e=za(a,d),B(e)&&(e=d)):e=this.$$html5?d:"";bd(e,this);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash? -"#"+rb(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ha(b)==Ha(a)?(this.$$parse(a),!0):!1}}function cd(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ha(d)?f=d:(g=za(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=Qb(this.$$search),e=this.$$hash?"#"+rb(this.$$hash): -"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Ib(b){return function(){return this[b]}}function dd(b,a){return function(c){if(B(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Me(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return y(a)?(b=a,this):b};this.html5Mode=function(b){return Wa(b)?(a.enabled=b,this):I(b)?(Wa(b.enabled)&&(a.enabled=b.enabled),Wa(b.requireBase)&&(a.requireBase=b.requireBase),Wa(b.rewriteLinks)&& -(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,m;m=d.baseHref();var n=d.url(),q;if(a.enabled){if(!m&&a.requireBase)throw Hb("nobase");q=n.substring(0,n.indexOf("/",n.indexOf("//")+2))+(m||"/");m=e.history?dc:cd}else q= -Ha(n),m=ec;k=new m(q,"#"+b);k.$$parseLinkUrl(n,n);k.$$state=d.state();var u=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=D(b.target);"a"!==ua(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");I(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);u.test(h)||!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h, -l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Gb(k.absUrl())!=Gb(n)&&d.url(k.absUrl(),!0);var r=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(r=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=Gb(d.url()),b=Gb(k.absUrl()),f=d.state(),g=k.$$replace, -q=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(r||q)r=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(q&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function Ne(){var b=!0,a=this;this.debugEnabled=function(a){return y(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)? -"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||z;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];s(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}function ta(b,a){if("__defineGetter__"=== -b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw la("isecfld",a);return b}function ma(b,a){if(b){if(b.constructor===b)throw la("isecfn",a);if(b.window===b)throw la("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw la("isecdom",a);if(b===Object)throw la("isecobj",a);}return b}function fc(b){return b.constant}function hb(b,a,c,d,e){ma(b,e);ma(a,e);c=c.split(".");for(var f,g=0;1<c.length;g++){f=ta(c.shift(),e);var h=0===g&&a&&a[f]|| -b[f];h||(h={},b[f]=h);b=ma(h,e)}f=ta(c.shift(),e);ma(b[f],e);return b[f]=d}function Qa(b){return"constructor"==b}function ed(b,a,c,d,e,f,g){ta(b,f);ta(a,f);ta(c,f);ta(d,f);ta(e,f);var h=function(a){return ma(a,f)},l=g||Qa(b)?h:pa,k=g||Qa(a)?h:pa,m=g||Qa(c)?h:pa,n=g||Qa(d)?h:pa,q=g||Qa(e)?h:pa;return function(f,g){var h=g&&g.hasOwnProperty(b)?g:f;if(null==h)return h;h=l(h[b]);if(!a)return h;if(null==h)return t;h=k(h[a]);if(!c)return h;if(null==h)return t;h=m(h[c]);if(!d)return h;if(null==h)return t; -h=n(h[d]);return e?null==h?t:h=q(h[e]):h}}function xf(b,a){return function(c,d){return b(c,d,ma,a)}}function yf(b,a,c){var d=a.expensiveChecks,e=d?zf:Af,f=e[b];if(f)return f;var g=b.split("."),h=g.length;if(a.csp)f=6>h?ed(g[0],g[1],g[2],g[3],g[4],c,d):function(a,b){var e=0,f;do f=ed(g[e++],g[e++],g[e++],g[e++],g[e++],c,d)(a,b),b=t,a=f;while(e<h);return f};else{var l="";d&&(l+="s = eso(s, fe);\nl = eso(l, fe);\n");var k=d;s(g,function(a,b){ta(a,c);var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+ -"."+a;if(d||Qa(a))e="eso("+e+", fe)",k=!0;l+="if(s == null) return undefined;\ns="+e+";\n"});l+="return s;";a=new Function("s","l","eso","fe",l);a.toString=ea(l);k&&(a=xf(a,c));f=a}f.sharedGetter=!0;f.assign=function(a,c,d){return hb(a,d,b,c,b)};return e[b]=f}function gc(b){return G(b.valueOf)?b.valueOf():Bf.call(b)}function Oe(){var b=ha(),a=ha();this.$get=["$filter","$sniffer",function(c,d){function e(a){var b=a;a.sharedGetter&&(b=function(b,c){return a(b,c)},b.literal=a.literal,b.constant=a.constant, -b.assign=a.assign);return b}function f(a,b){for(var c=0,d=a.length;c<d;c++){var e=a[c];e.constant||(e.inputs?f(e.inputs,b):-1===b.indexOf(e)&&b.push(e))}return b}function g(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=gc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function h(a,b,c,d){var e=d.$$inputs||(d.$$inputs=f(d.inputs,[])),h;if(1===e.length){var l=g,e=e[0];return a.$watch(function(a){var b=e(a);g(b,l)||(h=d(a),l=b&&gc(b));return h},b,c)}for(var k=[],q=0,n=e.length;q<n;q++)k[q]= -g;return a.$watch(function(a){for(var b=!1,c=0,f=e.length;c<f;c++){var l=e[c](a);if(b||(b=!g(l,k[c])))k[c]=l&&gc(l)}b&&(h=d(a));return h},b,c)}function l(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;G(b)&&b.apply(this,arguments);y(a)&&d.$$postDigest(function(){y(f)&&e()})},c)}function k(a,b,c,d){function e(a){var b=!0;s(a,function(a){y(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;G(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&& -f()})},c)}function m(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){G(b)&&b.apply(this,arguments);e()},c)}function n(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==k&&c!==l?function(c,d){var e=a(c,d);return b(e,c,d)}:function(c,d){var e=a(c,d),f=b(e,c,d);return y(e)?f:e};a.$$watchDelegate&&a.$$watchDelegate!==h?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=h,c.inputs=[a]);return c}var q={csp:d.csp,expensiveChecks:!1},u={csp:d.csp,expensiveChecks:!0}; -return function(d,f,g){var v,w,L;switch(typeof d){case "string":L=d=d.trim();var C=g?a:b;v=C[L];v||(":"===d.charAt(0)&&":"===d.charAt(1)&&(w=!0,d=d.substring(2)),g=g?u:q,v=new hc(g),v=(new ib(v,c,g)).parse(d),v.constant?v.$$watchDelegate=m:w?(v=e(v),v.$$watchDelegate=v.literal?k:l):v.inputs&&(v.$$watchDelegate=h),C[L]=v);return n(v,f);case "function":return n(d,f);default:return n(z,f)}}}]}function Qe(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return fd(function(a){b.$evalAsync(a)}, -a)}]}function Re(){this.$get=["$browser","$exceptionHandler",function(b,a){return fd(function(a){b.defer(a)},a)}]}function fd(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&&c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=t;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status]; -try{G(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),a(h)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=S("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending||[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a, -b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(I(b)||G(b))d=b&&b.then;G(d)?(this.promise.$$state.status=-1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status|| -this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(G(b)?b(c):c)}catch(h){a(h)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{G(c)&&(d=c())}catch(e){return l(e,!1)}return d&&G(d.then)? -d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},m=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},n=function u(a){if(!G(a))throw h("norslvr",a);if(!(this instanceof u))return new u(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};n.defer=function(){return new g};n.reject=function(a){var b=new g;b.reject(a);return b.promise};n.when=m;n.all=function(a){var b=new g,c=0,d=H(a)?[]:{};s(a,function(a,e){c++;m(a).then(function(a){d.hasOwnProperty(e)|| -(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return n}function $e(){this.$get=["$window","$timeout",function(b,a){var c=b.requestAnimationFrame||b.webkitRequestAnimationFrame,d=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,e=!!c,f=e?function(a){var b=c(a);return function(){d(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};f.supported=e;return f}]}function Pe(){var b= -10,a=S("$rootScope"),c=null,d=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(e,f,g,h){function l(){this.$id=++ob;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$isolateBindings=null}function k(b){if(r.$$phase)throw a("inprog",r.$$phase);r.$$phase=b}function m(a, -b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function n(){}function q(){for(;v.length;)try{v.shift()()}catch(a){f(a)}d=null}function u(){null===d&&(d=h.defer(function(){r.$apply(q)}))}l.prototype={constructor:l,$new:function(a,b){function c(){d.$$destroyed=!0}var d;b=b||this;a?(d=new l,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=function(){this.$$watchers=this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners= -{};this.$$listenerCount={};this.$id=++ob;this.$$ChildScope=null},this.$$ChildScope.prototype=this),d=new this.$$ChildScope);d.$parent=b;d.$$prevSibling=b.$$childTail;b.$$childHead?(b.$$childTail.$$nextSibling=d,b.$$childTail=d):b.$$childHead=b.$$childTail=d;(a||b!=this)&&d.$on("$destroy",c);return d},$watch:function(a,b,d){var e=g(a);if(e.$$watchDelegate)return e.$$watchDelegate(this,b,d,e);var f=this.$$watchers,h={fn:b,last:n,get:e,exp:a,eq:!!d};c=null;G(b)||(h.fn=z);f||(f=this.$$watchers=[]);f.unshift(h); -return function(){Xa(f,h);c=null}},$watchGroup:function(a,b){function c(){h=!1;l?(l=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,l=!0;if(!a.length){var k=!0;g.$evalAsync(function(){k&&b(e,e,g)});return function(){k=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});s(a,function(a,b){var l=g.$watch(a,function(a,f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(l)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a, -b){function c(a){e=a;var b,d,g,h;if(!B(e)){if(I(e))if(Ta(e))for(f!==q&&(f=q,u=f.length=0,k++),a=e.length,u!==a&&(k++,f.length=u=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(k++,f[b]=g);else{f!==m&&(f=m={},u=0,k++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(k++,f[b]=g)):(u++,f[b]=g,k++));if(u>a)for(b in k++,f)e.hasOwnProperty(b)||(u--,delete f[b])}else f!==e&&(f=e,k++);return k}}c.$stateful=!0;var d=this,e,f,h,l=1<b.length,k=0,n=g(a,c),q=[],m= -{},p=!0,u=0;return this.$watch(n,function(){p?(p=!1,b(e,e,d)):b(e,h,d);if(l)if(I(e))if(Ta(e)){h=Array(e.length);for(var a=0;a<e.length;a++)h[a]=e[a]}else for(a in h={},e)sc.call(e,a)&&(h[a]=e[a]);else h=e})},$digest:function(){var e,g,l,m,u,v,s=b,t,W=[],y,J;k("$digest");h.$$checkUrlChange();this===r&&null!==d&&(h.defer.cancel(d),q());c=null;do{v=!1;for(t=this;P.length;){try{J=P.shift(),J.scope.$eval(J.expression,J.locals)}catch(D){f(D)}c=null}a:do{if(m=t.$$watchers)for(u=m.length;u--;)try{if(e=m[u])if((g= -e.get(t))!==(l=e.last)&&!(e.eq?ga(g,l):"number"===typeof g&&"number"===typeof l&&isNaN(g)&&isNaN(l)))v=!0,c=e,e.last=e.eq?Ea(g,null):g,e.fn(g,l===n?g:l,t),5>s&&(y=4-s,W[y]||(W[y]=[]),W[y].push({msg:G(e.exp)?"fn: "+(e.exp.name||e.exp.toString()):e.exp,newVal:g,oldVal:l}));else if(e===c){v=!1;break a}}catch(B){f(B)}if(!(m=t.$$childHead||t!==this&&t.$$nextSibling))for(;t!==this&&!(m=t.$$nextSibling);)t=t.$parent}while(t=m);if((v||P.length)&&!s--)throw r.$$phase=null,a("infdig",b,W);}while(v||P.length); -for(r.$$phase=null;p.length;)try{p.shift()()}catch(da){f(da)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(this!==r){for(var b in this.$$listenerCount)m(this,this.$$listenerCount[b],b);a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a.$$childTail==this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling); -this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=z;this.$on=this.$watch=this.$watchGroup=function(){return z};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){r.$$phase||P.length||h.defer(function(){P.length&&r.$digest()});P.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){p.push(a)},$apply:function(a){try{return k("$apply"), -this.$eval(a)}catch(b){f(b)}finally{r.$$phase=null;try{r.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&v.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,m(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e, -stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},l=Ya([h],arguments,1),k,m;do{d=e.$$listeners[a]||c;h.currentScope=e;k=0;for(m=d.length;k<m;k++)if(d[k])try{d[k].apply(null,l)}catch(n){f(n)}else d.splice(k,1),k--,m--;if(g)return h.currentScope=null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e; -for(var g=Ya([e],arguments,1),h,l;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(l=d.length;h<l;h++)if(d[h])try{d[h].apply(null,g)}catch(k){f(k)}else d.splice(h,1),h--,l--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var r=new l,P=r.$$asyncQueue=[],p=r.$$postDigestQueue=[],v=r.$$applyAsyncQueue=[];return r}]}function Sd(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/; -this.aHrefSanitizationWhitelist=function(a){return y(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Ba(c).href;return""===f||f.match(e)?c:"unsafe:"+f}}}function Cf(b){if("self"===b)return b;if(F(b)){if(-1<b.indexOf("***"))throw Ca("iwcard",b);b=gd(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(pb(b))return new RegExp("^"+b.source+"$");throw Ca("imatcher");}function hd(b){var a= -[];y(b)&&s(b,function(b){a.push(Cf(b))});return a}function Te(){this.SCE_CONTEXTS=na;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=hd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&&(a=hd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?$c(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()}; -b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw Ca("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[na.HTML]=e(g);h[na.CSS]=e(g);h[na.URL]=e(g);h[na.JS]=e(g);h[na.RESOURCE_URL]=e(h[na.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Ca("icontext",a,b);if(null===b||b===t||""===b)return b;if("string"!==typeof b)throw Ca("itype",a);return new c(b)},getTrusted:function(c,e){if(null=== -e||e===t||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(c===na.RESOURCE_URL){var g=Ba(e.toString()),n,q,u=!1;n=0;for(q=b.length;n<q;n++)if(d(b[n],g)){u=!0;break}if(u)for(n=0,q=a.length;n<q;n++)if(d(a[n],g)){u=!1;break}if(u)return e;throw Ca("insecurl",e.toString());}if(c===na.HTML)return f(e);throw Ca("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function Se(){var b=!0;this.enabled=function(a){arguments.length&& -(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&8>Ra)throw Ca("iequirks");var d=ra(na);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=d.getTrusted=function(a,b){return b},d.valueOf=pa);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;s(na,function(a,b){var c=Q(b);d[db("parse_as_"+c)]=function(b){return e(a, -b)};d[db("get_trusted_"+c)]=function(b){return f(a,b)};d[db("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function Ue(){this.$get=["$window","$document",function(b,a){var c={},d=ba((/android (\d+)/.exec(Q((b.navigator||{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,m=!1;if(l){for(var n in l)if(k=h.exec(n)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit"); -k=!!("transition"in l||g+"Transition"in l);m=!!("animation"in l||g+"Animation"in l);!d||k&&m||(k=F(f.body.style.webkitTransition),m=F(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===a&&11>=Ra)return!1;if(B(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:bb(),vendorPrefix:g,transitions:k,animations:m,android:d}}]}function We(){this.$get=["$templateCache","$http","$q",function(b,a,c){function d(e,f){d.totalPendingRequests++; -var g=a.defaults&&a.defaults.transformResponse;H(g)?g=g.filter(function(a){return a!==Zb}):g===Zb&&(g=null);return a.get(e,{cache:b,transformResponse:g}).finally(function(){d.totalPendingRequests--}).then(function(a){return a.data},function(a){if(!f)throw ja("tpload",e);return c.reject(a)})}d.totalPendingRequests=0;return d}]}function Xe(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];s(a,function(a){var d= -ca.element(a).data("$binding");d&&s(d,function(d){c?(new RegExp("(^|\\s)"+gd(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function Ye(){this.$get= -["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){var m=y(k)&&!k,n=(m?d:c).defer(),q=n.promise;l=a.defer(function(){try{n.resolve(f())}catch(a){n.reject(a),e(a)}finally{delete g[q.$$timeoutId]}m||b.$apply()},l);q.$$timeoutId=l;g[l]=n;return q}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Ba(b){Ra&&(Z.setAttribute("href",b),b=Z.href); -Z.setAttribute("href",b);return{href:Z.href,protocol:Z.protocol?Z.protocol.replace(/:$/,""):"",host:Z.host,search:Z.search?Z.search.replace(/^\?/,""):"",hash:Z.hash?Z.hash.replace(/^#/,""):"",hostname:Z.hostname,port:Z.port,pathname:"/"===Z.pathname.charAt(0)?Z.pathname:"/"+Z.pathname}}function $c(b){b=F(b)?Ba(b):b;return b.protocol===id.protocol&&b.host===id.host}function Ze(){this.$get=ea(M)}function Ec(b){function a(c,d){if(I(c)){var e={};s(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+ -"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",jd);a("date",kd);a("filter",Df);a("json",Ef);a("limitTo",Ff);a("lowercase",Gf);a("number",ld);a("orderBy",md);a("uppercase",Hf)}function Df(){return function(b,a,c){if(!H(b))return b;var d;switch(typeof a){case "function":break;case "boolean":case "number":case "string":d=!0;case "object":a=If(a,c,d);break;default:return b}return b.filter(a)}}function If(b,a,c){var d=I(b)&&"$"in -b;!0===a?a=ga:G(a)||(a=function(a,b){if(I(a)||I(b))return!1;a=Q(""+a);b=Q(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!I(e)?Ia(e,b.$,a,!1):Ia(e,b,a,c)}}function Ia(b,a,c,d,e){var f=typeof b,g=typeof a;if("string"===g&&"!"===a.charAt(0))return!Ia(b,a.substring(1),c,d);if(H(b))return b.some(function(b){return Ia(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==h.charAt(0)&&Ia(b[h],a,c,!0))return!0;return e?!1:Ia(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!G(e)&& -(f="$"===h,!Ia(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function jd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){B(d)&&(d=a.CURRENCY_SYM);B(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:nd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function ld(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==b?b:nd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function nd(b,a,c,d,e){if(!isFinite(b)||I(b))return"";var f= -0>b;b=Math.abs(b);var g=b+"",h="",l=[],k=!1;if(-1!==g.indexOf("e")){var m=g.match(/([\d\.]+)e(-?)(\d+)/);m&&"-"==m[2]&&m[3]>e+1?b=0:(h=g,k=!0)}if(k)0<e&&1>b&&(h=b.toFixed(e),b=parseFloat(h));else{g=(g.split(od)[1]||"").length;B(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(od),k=g[0],g=g[1]||"",n=0,q=a.lgSize,u=a.gSize;if(k.length>=q+u)for(n=k.length-q,m=0;m<n;m++)0===(n-m)%u&&0!==m&&(h+=c),h+=k.charAt(m);for(m=n;m<k.length;m++)0=== -(k.length-m)%q&&0!==m&&(h+=c),h+=k.charAt(m);for(;g.length<e;)g+="0";e&&"0"!==e&&(h+=d+g.substr(0,e))}0===b&&(f=!1);l.push(f?a.negPre:a.posPre,h,f?a.negSuf:a.posSuf);return l.join("")}function Jb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function $(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=c;0===e&&-12==c&&(e=12);return Jb(e,a,d)}}function Kb(b,a){return function(c,d){var e=c["get"+b](),f=vb(a?"SHORT"+b:b);return d[f][e]}} -function pd(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function qd(b){return function(a){var c=pd(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Jb(a,b)}}function kd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=ba(b[9]+b[10]),g=ba(b[9]+b[11]));h.call(a,ba(b[1]),ba(b[2])-1,ba(b[3]));f=ba(b[4]||0)-f; -g=ba(b[5]||0)-g;h=ba(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;F(c)&&(c=Jf.test(c)?ba(c):a(c));V(c)&&(c=new Date(c));if(!qa(c))return c;for(;e;)(k=Kf.exec(e))?(h=Ya(h,k,1),e=h.pop()):(h.push(e),e=null);f&&"UTC"===f&&(c=new Date(c.getTime()),c.setMinutes(c.getMinutes()+ -c.getTimezoneOffset()));s(h,function(a){l=Lf[a];g+=l?l(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Ef(){return function(b,a){B(a)&&(a=2);return $a(b,a)}}function Ff(){return function(b,a){V(b)&&(b=b.toString());return H(b)||F(b)?(a=Infinity===Math.abs(Number(a))?Number(a):ba(a))?0<a?b.slice(0,a):b.slice(a):F(b)?"":[]:b}}function md(b){return function(a,c,d){function e(a,b){return b?function(b,c){return a(c,b)}:a}function f(a){switch(typeof a){case "number":case "boolean":case "string":return!0; -default:return!1}}function g(a){return null===a?"null":"function"===typeof a.valueOf&&(a=a.valueOf(),f(a))||"function"===typeof a.toString&&(a=a.toString(),f(a))?a:""}function h(a,b){var c=typeof a,d=typeof b;c===d&&"object"===c&&(a=g(a),b=g(b));return c===d?("string"===c&&(a=a.toLowerCase(),b=b.toLowerCase()),a===b?0:a<b?-1:1):c<d?-1:1}if(!Ta(a))return a;c=H(c)?c:[c];0===c.length&&(c=["+"]);c=c.map(function(a){var c=!1,d=a||pa;if(F(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))c="-"==a.charAt(0),a=a.substring(1); -if(""===a)return e(h,c);d=b(a);if(d.constant){var f=d();return e(function(a,b){return h(a[f],b[f])},c)}}return e(function(a,b){return h(d(a),d(b))},c)});return Za.call(a).sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(0!==e)return e}return 0},d))}}function Ja(b){G(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ea(b)}function rd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Lb;f.$error={};f.$$success={};f.$pending=t;f.$name=e(a.name||a.ngForm|| -"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){s(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){s(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ma(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];s(f.$pending,function(b,c){f.$setValidity(c, -null,a)});s(f.$error,function(b,c){f.$setValidity(c,null,a)});s(f.$$success,function(b,c){f.$setValidity(c,null,a)});Xa(g,a)};sd({ctrl:this,$element:b,set:function(a,b,c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(Xa(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Sa);d.addClass(b,Mb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Sa,Mb+" ng-submitted");f.$dirty=!1;f.$pristine= -!0;f.$submitted=!1;s(g,function(a){a.$setPristine()})};f.$setUntouched=function(){s(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b,"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function ic(b){b.$formatters.push(function(a){return b.$isEmpty(a)?a:a.toString()})}function jb(b,a,c,d,e,f){var g=Q(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e= -a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=U(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}};if(e.hasEvent("input"))a.on("input",l);else{var k,m=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",m)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}} -function Nb(b,a){return function(c,d){var e,f;if(qa(c))return c;if(F(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(Mf.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},s(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0, -1E3*f.sss||0)}return NaN}}function kb(b,a,c,d){return function(e,f,g,h,l,k,m){function n(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function q(a){return y(a)?qa(a)?a:c(a):t}td(e,f,g,h);jb(e,f,g,h,l,k);var u=h&&h.$options&&h.$options.timezone,r;h.$$parserName=b;h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,r),"UTC"===u&&b.setMinutes(b.getMinutes()-b.getTimezoneOffset()),b):t});h.$formatters.push(function(a){if(a&&!qa(a))throw Ob("datefmt",a);if(n(a)){if((r=a)&&"UTC"=== -u){var b=6E4*r.getTimezoneOffset();r=new Date(r.getTime()+b)}return m("date")(a,d,u)}r=null;return""});if(y(g.min)||g.ngMin){var s;h.$validators.min=function(a){return!n(a)||B(s)||c(a)>=s};g.$observe("min",function(a){s=q(a);h.$validate()})}if(y(g.max)||g.ngMax){var p;h.$validators.max=function(a){return!n(a)||B(p)||c(a)<=p};g.$observe("max",function(a){p=q(a);h.$validate()})}}}function td(b,a,c,d){(d.$$hasNativeValidators=I(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{}; -return c.badInput&&!c.typeMismatch?t:b})}function ud(b,a,c,d,e){if(y(d)){b=b(d);if(!b.constant)throw S("ngModel")("constexpr",c,d);return b(a)}return e}function jc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],m=0;m<b.length;m++)if(e==b[m])continue a;c.push(e)}return c}function e(a){if(!H(a)){if(F(a))return a.split(" ");if(I(a)){var b=[];s(a,function(a,c){a&&(b=b.concat(c.split(" ")))});return b}}return a}return{restrict:"AC",link:function(f, -g,h){function l(a,b){var c=g.data("$classCounts")||{},d=[];s(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!m){var u=l(k,1);h.$addClass(u)}else if(!ga(b,m)){var r=e(m),u=d(k,r),k=d(r,k),u=l(u,1),k=l(k,-1);u&&u.length&&c.addClass(g,u);k&&k.length&&c.removeClass(g,k)}}m=ra(b)}var m;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index", -function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function sd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}function c(b,c){b=b?"-"+uc(b,"-"):"";a(lb+b,!0===c);a(vd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[vd]=!(f[lb]=e.hasClass(lb));d.$setValidity=function(b,e,f){e===t?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&& -h(d.$pending,b,f),wd(d.$pending)&&(d.$pending=t));Wa(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(xd,!0),d.$valid=d.$invalid=t,c("",null)):(a(xd,!1),d.$valid=wd(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?t:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function wd(b){if(b)for(var a in b)return!1;return!0}var Nf=/^\/(.+)\/([a-z]*)$/,Q=function(b){return F(b)?b.toLowerCase(): -b},sc=Object.prototype.hasOwnProperty,vb=function(b){return F(b)?b.toUpperCase():b},Ra,D,sa,Za=[].slice,pf=[].splice,Of=[].push,Da=Object.prototype.toString,Ka=S("ng"),ca=M.angular||(M.angular={}),cb,ob=0;Ra=Y.documentMode;z.$inject=[];pa.$inject=[];var H=Array.isArray,U=function(b){return F(b)?b.trim():b},gd=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},bb=function(){if(y(bb.isActive_))return bb.isActive_;var b=!(!Y.querySelector("[ng-csp]")&&!Y.querySelector("[data-ng-csp]")); -if(!b)try{new Function("")}catch(a){b=!0}return bb.isActive_=b},sb=["ng-","data-ng-","ng:","x-ng-"],Md=/[A-Z]/g,vc=!1,Rb,oa=1,qb=3,Qd={full:"1.3.13",major:1,minor:3,dot:13,codeName:"meticulous-riffleshuffle"};R.expando="ng339";var Ab=R.cache={},hf=1;R._data=function(b){return this.cache[b[this.expando]]||{}};var cf=/([\:\-\_]+(.))/g,df=/^moz([A-Z])/,Pf={mouseleave:"mouseout",mouseenter:"mouseover"},Ub=S("jqLite"),gf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,ef=/<([\w:]+)/,ff=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, -ia={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ia.optgroup=ia.option;ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead;ia.th=ia.td;var La=R.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===Y.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),R(M).on("load",a))}, -toString:function(){var b=[];s(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?D(this[b]):D(this[this.length+b])},length:0,push:Of,sort:[].sort,splice:[].splice},Fb={};s("multiple selected checked disabled readOnly required open".split(" "),function(b){Fb[Q(b)]=b});var Nc={};s("input select option textarea button form details".split(" "),function(b){Nc[b]=!0});var Oc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"}; -s({data:Wb,removeData:yb},function(b,a){R[a]=b});s({data:Wb,inheritedData:Eb,scope:function(b){return D.data(b,"$scope")||Eb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return D.data(b,"$isolateScope")||D.data(b,"$isolateScopeNoTemplate")},controller:Jc,injector:function(b){return Eb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Bb,css:function(b,a,c){a=db(a);if(y(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=Q(a);if(Fb[d])if(y(c))c? -(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||z).specified?d:t;else if(y(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(y(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(B(b)){var d=a.nodeType;return d===oa||d===qb?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(B(a)){if(b.multiple&&"select"===ua(b)){var c=[];s(b.options,function(a){a.selected&& -c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(B(a))return b.innerHTML;xb(b,!0);b.innerHTML=a},empty:Kc},function(b,a){R.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Kc&&(2==b.length&&b!==Bb&&b!==Jc?a:d)===t){if(I(a)){for(e=0;e<g;e++)if(b===Wb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===t?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}}); -s({removeData:yb,on:function a(c,d,e,f){if(y(f))throw Ub("onargs");if(Fc(c)){var g=zb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=lf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"===d?a(c,Pf[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Ic,one:function(a,c,d){a=D(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c, -d)},replaceWith:function(a,c){var d,e=a.parentNode;xb(a);s(new R(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];s(a.childNodes,function(a){a.nodeType===oa&&c.push(a)});return c},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===oa||11===d){c=new R(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===oa){var d=a.firstChild;s(new R(c),function(c){a.insertBefore(c, -d)})}},wrap:function(a,c){c=D(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Lc,detach:function(a){Lc(a,!0)},after:function(a,c){var d=a,e=a.parentNode;c=new R(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h,d.nextSibling);d=h}},addClass:Db,removeClass:Cb,toggleClass:function(a,c,d){c&&s(c.split(" "),function(c){var f=d;B(f)&&(f=!Bb(a,c));(f?Db:Cb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling}, -find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Vb,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=zb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:z,type:g,target:a},c.type&&(e=x(e, -c)),c=ra(h),f=d?[e].concat(d):[e],s(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){R.prototype[c]=function(c,e,f){for(var g,h=0,l=this.length;h<l;h++)B(g)?(g=a(this[h],c,e,f),y(g)&&(g=D(g))):Hc(g,a(this[h],c,e,f));return y(g)?g:this};R.prototype.bind=R.prototype.on;R.prototype.unbind=R.prototype.off});eb.prototype={put:function(a,c){this[Na(a,this.nextUid)]=c},get:function(a){return this[Na(a,this.nextUid)]},remove:function(a){var c=this[a=Na(a,this.nextUid)];delete this[a]; -return c}};var Qc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,Qf=/,/,Rf=/^\s*(_?)(\S+?)\1\s*$/,Pc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ga=S("$injector");ab.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e=[];if(a.length){if(c)throw F(d)&&d||(d=a.name||mf(a)),Ga("strictdi",d);c=a.toString().replace(Pc,"");c=c.match(Qc);s(c[1].split(Qf),function(a){a.replace(Rf,function(a,c,d){e.push(d)})})}a.$inject=e}}else H(a)?(c=a.length-1,tb(a[c],"fn"),e=a.slice(0,c)):tb(a,"fn",!0);return e}; -var Sf=S("$animate"),Ce=["$provide",function(a){this.$$selectors={};this.register=function(c,d){var e=c+"-animation";if(c&&"."!=c.charAt(0))throw Sf("notcsel",c);this.$$selectors[c.substr(1)]=e;a.factory(e,d)};this.classNameFilter=function(a){1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null);return this.$$classNameFilter};this.$get=["$$q","$$asyncCallback","$rootScope",function(a,d,e){function f(d){var f,g=a.defer();g.promise.$$cancelFn=function(){f&&f()};e.$$postDigest(function(){f= -d(function(){g.resolve()})});return g.promise}function g(a,c){var d=[],e=[],f=ha();s((a.attr("class")||"").split(/\s+/),function(a){f[a]=!0});s(c,function(a,c){var g=f[c];!1===a&&g?e.push(c):!0!==a||g||d.push(c)});return 0<d.length+e.length&&[d.length?d:null,e.length?e:null]}function h(a,c,d){for(var e=0,f=c.length;e<f;++e)a[c[e]]=d}function l(){m||(m=a.defer(),d(function(){m.resolve();m=null}));return m.promise}function k(a,c){if(ca.isObject(c)){var d=x(c.from||{},c.to||{});a.css(d)}}var m;return{animate:function(a, -c,d){k(a,{from:c,to:d});return l()},enter:function(a,c,d,e){k(a,e);d?d.after(a):c.prepend(a);return l()},leave:function(a,c){a.remove();return l()},move:function(a,c,d,e){return this.enter(a,c,d,e)},addClass:function(a,c,d){return this.setClass(a,c,[],d)},$$addClassImmediately:function(a,c,d){a=D(a);c=F(c)?c:H(c)?c.join(" "):"";s(a,function(a){Db(a,c)});k(a,d);return l()},removeClass:function(a,c,d){return this.setClass(a,[],c,d)},$$removeClassImmediately:function(a,c,d){a=D(a);c=F(c)?c:H(c)?c.join(" "): -"";s(a,function(a){Cb(a,c)});k(a,d);return l()},setClass:function(a,c,d,e){var k=this,l=!1;a=D(a);var m=a.data("$$animateClasses");m?e&&m.options&&(m.options=ca.extend(m.options||{},e)):(m={classes:{},options:e},l=!0);e=m.classes;c=H(c)?c:c.split(" ");d=H(d)?d:d.split(" ");h(e,c,!0);h(e,d,!1);l&&(m.promise=f(function(c){var d=a.data("$$animateClasses");a.removeData("$$animateClasses");if(d){var e=g(a,d.classes);e&&k.$$setClassImmediately(a,e[0],e[1],d.options)}c()}),a.data("$$animateClasses",m)); -return m.promise},$$setClassImmediately:function(a,c,d,e){c&&this.$$addClassImmediately(a,c);d&&this.$$removeClassImmediately(a,d);k(a,e);return l()},enabled:z,cancel:z}}]}],ja=S("$compile");xc.$inject=["$provide","$$sanitizeUriProvider"];var Sc=/^((?:x|data)[\:\-_])/i,qf=S("$controller"),Wc="application/json",$b={"Content-Type":Wc+";charset=utf-8"},sf=/^\[|^\{(?!\{)/,tf={"[":/]$/,"{":/}$/},rf=/^\)\]\}',?\n/,ac=S("$interpolate"),Tf=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,wf={http:80,https:443,ftp:21},Hb= -S("$location"),Uf={$$html5:!1,$$replace:!1,absUrl:Ib("$$absUrl"),url:function(a){if(B(a))return this.$$url;var c=Tf.exec(a);(c[1]||""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Ib("$$protocol"),host:Ib("$$host"),port:Ib("$$port"),path:dd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(F(a)||V(a))a= -a.toString(),this.$$search=rc(a);else if(I(a))a=Ea(a,{}),s(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Hb("isrcharg");break;default:B(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:dd("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};s([cd,ec,dc],function(a){a.prototype=Object.create(Uf);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==dc||!this.$$html5)throw Hb("nostate"); -this.$$state=B(c)?null:c;return this}});var la=S("$parse"),Vf=Function.prototype.call,Wf=Function.prototype.apply,Xf=Function.prototype.bind,mb=ha();s({"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:function(){}},function(a,c){a.constant=a.literal=a.sharedGetter=!0;mb[c]=a});mb["this"]=function(a){return a};mb["this"].sharedGetter=!0;var nb=x(ha(),{"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return y(d)?y(e)?d+e:d:y(e)?e:t},"-":function(a,c,d,e){d=d(a, -c);e=e(a,c);return(y(d)?d:0)-(y(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"===":function(a,c,d,e){return d(a,c)===e(a,c)},"!==":function(a,c,d,e){return d(a,c)!==e(a,c)},"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a, -c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"!":function(a,c,d){return!d(a,c)},"=":!0,"|":!0}),Yf={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},hc=function(a){this.options=a};hc.prototype={constructor:hc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber(); -else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var c=a+this.peek(),d=c+this.peek(2),e=nb[c],f=nb[d];nb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+ -a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=y(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw la("lexerr",a,c,this.text); -},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=Q(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var e=this.peek();if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a= -this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&!this.isNumber(c))break;this.index++}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+= -4,d+=String.fromCharCode(parseInt(f,16))):d+=Yf[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===a){this.index++;this.tokens.push({index:c,text:e,constant:!0,value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var ib=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d};ib.ZERO=x(function(){return 0},{sharedGetter:!0,constant:!0});ib.prototype={constructor:ib,parse:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.statements();0!==this.tokens.length&&this.throwError("is an unexpected token", -this.tokens[0]);a.literal=!!a.literal;a.constant=!!a.constant;return a},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.peek().identifier&&this.peek().text in mb?a=mb[this.consume().text]:this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var c,d;c=this.expect("(","[",".");)"("===c.text?(a=this.functionCall(a, -d),d=null):"["===c.text?(d=a,a=this.objectIndex(a)):"."===c.text?(d=a,a=this.fieldAccess(a)):this.throwError("IMPOSSIBLE");return a},throwError:function(a,c){throw la("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},peekToken:function(){if(0===this.tokens.length)throw la("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];var g=a.text;if(g===c||g===d||g===e||g=== -f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},consume:function(a){if(0===this.tokens.length)throw la("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},unaryFn:function(a,c){var d=nb[a];return x(function(a,f){return d(a,f,c)},{constant:c.constant,inputs:[c]})},binaryFn:function(a,c,d,e){var f=nb[c];return x(function(c,e){return f(c,e,a,d)},{constant:a.constant&& -d.constant,inputs:!e&&[a,d]})},identifier:function(){for(var a=this.consume().text;this.peek(".")&&this.peekAhead(1).identifier&&!this.peekAhead(2,"(");)a+=this.consume().text+this.consume().text;return yf(a,this.options,this.text)},constant:function(){var a=this.consume().value;return x(function(){return a},{constant:!0,literal:!0})},statements:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.filterChain()),!this.expect(";"))return 1===a.length?a[0]:function(c, -d){for(var e,f=0,g=a.length;f<g;f++)e=a[f](c,d);return e}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},filter:function(a){var c=this.$filter(this.consume().text),d,e;if(this.peek(":"))for(d=[],e=[];this.expect(":");)d.push(this.expression());var f=[a].concat(d||[]);return x(function(f,h){var l=a(f,h);if(e){e[0]=l;for(l=d.length;l--;)e[l+1]=d[l](f,h);return c.apply(t,e)}return c(l)},{constant:!c.$stateful&&f.every(fc),inputs:!c.$stateful&&f})},expression:function(){return this.assignment()}, -assignment:function(){var a=this.ternary(),c,d;return(d=this.expect("="))?(a.assign||this.throwError("implies assignment but ["+this.text.substring(0,d.index)+"] can not be assigned to",d),c=this.ternary(),x(function(d,f){return a.assign(d,c(d,f),f)},{inputs:[a,c]})):a},ternary:function(){var a=this.logicalOR(),c;if(this.expect("?")&&(c=this.assignment(),this.consume(":"))){var d=this.assignment();return x(function(e,f){return a(e,f)?c(e,f):d(e,f)},{constant:a.constant&&c.constant&&d.constant})}return a}, -logicalOR:function(){for(var a=this.logicalAND(),c;c=this.expect("||");)a=this.binaryFn(a,c.text,this.logicalAND(),!0);return a},logicalAND:function(){for(var a=this.equality(),c;c=this.expect("&&");)a=this.binaryFn(a,c.text,this.equality(),!0);return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a=this.binaryFn(a,c.text,this.relational());return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a=this.binaryFn(a,c.text, -this.additive());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.text,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.text,this.unary());return a},unary:function(){var a;return this.expect("+")?this.primary():(a=this.expect("-"))?this.binaryFn(ib.ZERO,a.text,this.unary()):(a=this.expect("!"))?this.unaryFn(a.text,this.unary()):this.primary()},fieldAccess:function(a){var c= -this.identifier();return x(function(d,e,f){d=f||a(d,e);return null==d?t:c(d)},{assign:function(d,e,f){var g=a(d,f);g||a.assign(d,g={},f);return c.assign(g,e)}})},objectIndex:function(a){var c=this.text,d=this.expression();this.consume("]");return x(function(e,f){var g=a(e,f),h=d(e,f);ta(h,c);return g?ma(g[h],c):t},{assign:function(e,f,g){var h=ta(d(e,g),c),l=ma(a(e,g),c);l||a.assign(e,l={},g);return l[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression()); -while(this.expect(","))}this.consume(")");var e=this.text,f=d.length?[]:null;return function(g,h){var l=c?c(g,h):y(c)?t:g,k=a(g,h,l)||z;if(f)for(var m=d.length;m--;)f[m]=ma(d[m](g,h),e);ma(l,e);if(k){if(k.constructor===k)throw la("isecfn",e);if(k===Vf||k===Wf||k===Xf)throw la("isecff",e);}l=k.apply?k.apply(l,f):k(f[0],f[1],f[2],f[3],f[4]);f&&(f.length=0);return ma(l,e)}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(",")) -}this.consume("]");return x(function(c,d){for(var e=[],f=0,g=a.length;f<g;f++)e.push(a[f](c,d));return e},{literal:!0,constant:a.every(fc),inputs:a})},object:function(){var a=[],c=[];if("}"!==this.peekToken().text){do{if(this.peek("}"))break;var d=this.consume();d.constant?a.push(d.value):d.identifier?a.push(d.text):this.throwError("invalid key",d);this.consume(":");c.push(this.expression())}while(this.expect(","))}this.consume("}");return x(function(d,f){for(var g={},h=0,l=c.length;h<l;h++)g[a[h]]= -c[h](d,f);return g},{literal:!0,constant:c.every(fc),inputs:c})}};var Af=ha(),zf=ha(),Bf=Object.prototype.valueOf,Ca=S("$sce"),na={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ja=S("$compile"),Z=Y.createElement("a"),id=Ba(M.location.href);Ec.$inject=["$provide"];jd.$inject=["$locale"];ld.$inject=["$locale"];var od=".",Lf={yyyy:$("FullYear",4),yy:$("FullYear",2,0,!0),y:$("FullYear",1),MMMM:Kb("Month"),MMM:Kb("Month",!0),MM:$("Month",2,1),M:$("Month",1,1),dd:$("Date",2),d:$("Date", -1),HH:$("Hours",2),H:$("Hours",1),hh:$("Hours",2,-12),h:$("Hours",1,-12),mm:$("Minutes",2),m:$("Minutes",1),ss:$("Seconds",2),s:$("Seconds",1),sss:$("Milliseconds",3),EEEE:Kb("Day"),EEE:Kb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=a?"+":"")+(Jb(Math[0<a?"floor":"ceil"](a/60),2)+Jb(Math.abs(a%60),2))},ww:qd(2),w:qd(1)},Kf=/((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,Jf=/^\-?\d+$/; -kd.$inject=["$locale"];var Gf=ea(Q),Hf=ea(vb);md.$inject=["$parse"];var Td=ea({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===Da.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),wb={};s(Fb,function(a,c){if("multiple"!=a){var d=ya("ng-"+c);wb[d]=function(){return{restrict:"A",priority:100,link:function(a,f,g){a.$watch(g[d],function(a){g.$set(c, -!!a)})}}}}});s(Oc,function(a,c){wb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(Nf))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});s(["src","srcset","href"],function(a){var c=ya("ng-"+a);wb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===Da.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",g=null);f.$observe(c, -function(c){c?(f.$set(h,c),Ra&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Lb={$addControl:z,$$renameControl:function(a,c){a.$name=c},$removeControl:z,$setValidity:z,$setDirty:z,$setPristine:z,$setSubmitted:z};rd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var yd=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:rd,compile:function(a){a.addClass(Sa).addClass(lb);return{pre:function(a,d,g,h){if(!("action"in g)){var l=function(c){a.$apply(function(){h.$commitViewValue(); -h.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",l,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",l,!1)},0,!1)})}var k=h.$$parentForm,m=h.$name;m&&(hb(a,null,m,h,m),g.$observe(g.name?"name":"ngForm",function(c){m!==c&&(hb(a,null,m,t,m),m=c,hb(a,null,m,h,m),k.$$renameControl(h,m))}));d.on("$destroy",function(){k.$removeControl(h);m&&hb(a,null,m,t,m);x(h,Lb)})}}}}}]},Ud=yd(),ge=yd(!0),Mf=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/, -Zf=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,$f=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,ag=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,zd=/^(\d{4})-(\d{2})-(\d{2})$/,Ad=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,kc=/^(\d{4})-W(\d\d)$/,Bd=/^(\d{4})-(\d\d)$/,Cd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Dd={text:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);ic(e)},date:kb("date",zd,Nb(zd,["yyyy", -"MM","dd"]),"yyyy-MM-dd"),"datetime-local":kb("datetimelocal",Ad,Nb(Ad,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:kb("time",Cd,Nb(Cd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:kb("week",kc,function(a,c){if(qa(a))return a;if(F(a)){kc.lastIndex=0;var d=kc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=pd(e),f=7*(f-1);c&&(d=c.getHours(),g=c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:kb("month", -Bd,Nb(Bd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){td(a,c,d,e);jb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:ag.test(a)?parseFloat(a):t});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Ob("numfmt",a);a=a.toString()}return a});if(d.min||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||B(h)||a>=h};d.$observe("min",function(a){y(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(d.max|| -d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||B(l)||a<=l};d.$observe("max",function(a){y(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);ic(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||Zf.test(d)}},email:function(a,c,d,e,f,g){jb(a,c,d,e,f,g);ic(e);e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||$f.test(d)}},radio:function(a,c, -d,e){B(d.name)&&c.attr("name",++ob);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=ud(l,a,"ngTrueValue",d.ngTrueValue,!0),m=ud(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ga(a, -k)});e.$parsers.push(function(a){return a?k:m})},hidden:z,button:z,submit:z,reset:z,file:z},yc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Dd[Q(h.type)]||Dd.text)(f,g,h,l[0],c,a,d,e)}}}}],bg=/^(true|false|\d+)$/,ye=function(){return{restrict:"A",priority:100,compile:function(a,c){return bg.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value", -a)})}}}},Zd=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],ae=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===t?"":a})}}}}],$d=["$sce", -"$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],xe=ea({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),be=jc("",!0),de=jc("Odd",0),ce=jc("Even",1),ee=Ja({compile:function(a,c){c.$set("ngCloak", -t);a.removeClass("ng-cloak")}}),fe=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Dc={},cg={blur:!0,focus:!0};s("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=ya("ng-"+a);Dc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})}; -cg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ie=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=Y.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=ub(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],je=["$templateRequest","$anchorScroll", -"$animate","$sce",function(a,c,d,e){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(f,g){var h=g.ngInclude||g.src,l=g.onload||"",k=g.autoscroll;return function(f,g,q,s,r){var t=0,p,v,w,L=function(){v&&(v.remove(),v=null);p&&(p.$destroy(),p=null);w&&(d.leave(w).then(function(){v=null}),v=w,w=null)};f.$watch(e.parseAsResourceUrl(h),function(e){var h=function(){!y(k)||k&&!f.$eval(k)||c()},q=++t;e?(a(e,!0).then(function(a){if(q===t){var c=f.$new(); -s.template=a;a=r(c,function(a){L();d.enter(a,null,g).then(h)});p=c;w=a;p.$emit("$includeContentLoaded",e);f.$eval(l)}},function(){q===t&&(L(),f.$emit("$includeContentError",e))}),f.$emit("$includeContentRequested",e)):(L(),s.template=null)})}}}}],Ae=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Gc(f.template,Y).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}], -ke=Ja({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),we=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?U(f):f;e.$parsers.push(function(a){if(!B(a)){var c=[];a&&s(a.split(h),function(a){a&&c.push(g?U(a):a)});return c}});e.$formatters.push(function(a){return H(a)?a.join(f):t});e.$isEmpty=function(a){return!a||!a.length}}}},lb="ng-valid",vd="ng-invalid",Sa="ng-pristine", -Mb="ng-dirty",xd="ng-pending",Ob=new S("ngModel"),dg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,m){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success= -{};this.$pending=t;this.$name=m(d.name||"",!1)(a);var n=f(d.ngModel),q=n.assign,u=n,r=q,P=null,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");u=function(a){var d=n(a);G(d)&&(d=c(a));return d};r=function(a,c){G(n(a))?g(a,{$$$p:p.$modelValue}):q(a,p.$modelValue)}}else if(!n.assign)throw Ob("nonassign",d.ngModel,va(e));};this.$render=z;this.$isEmpty=function(a){return B(a)||""===a||null===a||a!==a};var v=e.inheritedData("$formController")|| -Lb,w=0;sd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:v,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Mb);g.addClass(e,Sa)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Sa);g.addClass(e,Mb);v.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched", -"ng-untouched")};this.$rollbackViewValue=function(){h.cancel(P);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(p.$error[p.$$parserName||"parse"]?!1:t,a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:t,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators=function(a,c,d,e){function f(){var a= -!0;s(p.$validators,function(e,f){var g=e(c,d);a=a&&g;h(f,g)});return a?!0:(s(p.$asyncValidators,function(a,c){h(c,null)}),!1)}function g(){var a=[],e=!0;s(p.$asyncValidators,function(f,g){var l=f(c,d);if(!l||!G(l.then))throw Ob("$asyncValidators",l);h(g,t);a.push(l.then(function(){h(g,!0)},function(a){e=!1;h(g,!1)}))});a.length?k.all(a).then(function(){l(e)},z):l(!0)}function h(a,c){m===w&&p.$setValidity(a,c)}function l(a){m===w&&e(a)}w++;var m=w;(function(a){var c=p.$$parserName||"parse";if(a=== -t)h(c,null);else if(h(c,a),!a)return s(p.$validators,function(a,c){h(c,null)}),s(p.$asyncValidators,function(a,c){h(c,null)}),!1;return!0})(a)?f()?g():l(!1):l(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(P);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue,d=B(c)?t:!0;if(d)for(var e=0;e<p.$parsers.length;e++)if(c= -p.$parsers[e](c),B(c)){d=!1;break}V(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=u(a));var f=p.$modelValue,g=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=c;g&&(p.$modelValue=c,p.$modelValue!==f&&p.$$writeModelToScope());p.$$runValidators(d,c,p.$$lastCommittedViewValue,function(a){g||(p.$modelValue=a?c:t,p.$modelValue!==f&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){r(a,p.$modelValue);s(p.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};this.$setViewValue= -function(a,c){p.$viewValue=a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=p.$options;e&&y(e.debounce)&&(e=e.debounce,V(e)?d=e:V(e[c])?d=e[c]:V(e["default"])&&(d=e["default"]));h.cancel(P);d?P=h(function(){p.$commitViewValue()},d):l.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var c=u(a);if(c!==p.$modelValue){p.$modelValue=p.$$rawModelValue=c;for(var d=p.$formatters,e=d.length, -f=c;e--;)f=d[e](f);p.$viewValue!==f&&(p.$viewValue=p.$$lastCommittedViewValue=f,p.$render(),p.$$runValidators(t,c,f,z))}return c})}],ve=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:dg,priority:1,compile:function(c){c.addClass(Sa).addClass("ng-untouched").addClass(lb);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Lb;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name",function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy", -function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],eg=/(\s+|^)default(\s+|$)/,ze=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=a.$eval(c.ngModelOptions);this.$options.updateOn!==t?(this.$options.updateOnDefault= -!1,this.$options.updateOn=U(this.$options.updateOn.replace(eg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},le=Ja({terminal:!0,priority:1E3}),me=["$locale","$interpolate",function(a,c){var d=/{}/g,e=/^when(Minus)?(.+)$/;return{restrict:"EA",link:function(f,g,h){function l(a){g.text(a||"")}var k=h.count,m=h.$attr.when&&g.attr(h.$attr.when),n=h.offset||0,q=f.$eval(m)||{},u={},m=c.startSymbol(),r=c.endSymbol(),t=m+k+"-"+n+r,p=ca.noop,v;s(h,function(a,c){var d= -e.exec(c);d&&(d=(d[1]?"-":"")+Q(d[2]),q[d]=g.attr(h.$attr[c]))});s(q,function(a,e){u[e]=c(a.replace(d,t))});f.$watch(k,function(c){c=parseFloat(c);var d=isNaN(c);d||c in q||(c=a.pluralCat(c-n));c===v||d&&isNaN(v)||(p(),p=f.$watch(u[c],l),v=c)})}}}],ne=["$parse","$animate",function(a,c){var d=S("ngRepeat"),e=function(a,c,d,e,k,m,n){a[d]=e;k&&(a[k]=m);a.$index=c;a.$first=0===c;a.$last=c===n-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element", -priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=Y.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var m=k[1],n=k[2],q=k[3],u=k[4],k=m.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);if(!k)throw d("iidexp",m);var r=k[3]||k[1],y=k[2];if(q&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(q)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(q)))throw d("badident", -q);var p,v,w,B,z={$id:Na};u?p=a(u):(w=function(a,c){return Na(c)},B=function(a){return a});return function(a,f,g,k,m){p&&(v=function(c,d,e){y&&(z[y]=c);z[r]=d;z.$index=e;return p(a,z)});var u=ha();a.$watchCollection(n,function(g){var k,p,n=f[0],E,z=ha(),x,T,N,G,H,C,I;q&&(a[q]=g);if(Ta(g))H=g,p=v||w;else{p=v||B;H=[];for(I in g)g.hasOwnProperty(I)&&"$"!=I.charAt(0)&&H.push(I);H.sort()}x=H.length;I=Array(x);for(k=0;k<x;k++)if(T=g===H?k:H[k],N=g[T],G=p(T,N,k),u[G])C=u[G],delete u[G],z[G]=C,I[k]=C;else{if(z[G])throw s(I, -function(a){a&&a.scope&&(u[a.id]=a)}),d("dupes",h,G,N);I[k]={id:G,scope:t,clone:t};z[G]=!0}for(E in u){C=u[E];G=ub(C.clone);c.leave(G);if(G[0].parentNode)for(k=0,p=G.length;k<p;k++)G[k].$$NG_REMOVED=!0;C.scope.$destroy()}for(k=0;k<x;k++)if(T=g===H?k:H[k],N=g[T],C=I[k],C.scope){E=n;do E=E.nextSibling;while(E&&E.$$NG_REMOVED);C.clone[0]!=E&&c.move(ub(C.clone),null,D(n));n=C.clone[C.clone.length-1];e(C.scope,k,r,N,y,T,x)}else m(function(a,d){C.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a, -null,D(n));n=f;C.clone=a;z[C.id]=C;e(C.scope,k,r,N,y,T,x)});u=z})}}}}],oe=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],he=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],pe=Ja(function(a,c,d){a.$watchCollection(d.ngStyle, -function(a,d){d&&a!==d&&s(d,function(a,d){c.css(d,"")});a&&c.css(a)})}),qe=["$animate",function(a){return{restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],m=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch||e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=0;for(e=k.length;d<e;++d){var r=ub(h[d].clone);k[d].$destroy();(l[d]=a.leave(r)).then(m(l,d))}h.length=0;k.length=0;(g= -f.cases["!"+c]||f.cases["?"])&&s(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=Y.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],re=Ja({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,element:c})}}),se=Ja({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0, -link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),ue=Ja({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw S("ngTransclude")("orphan",va(c));f(function(a){c.empty();c.append(a)})}}),Vd=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],fg=S("ngOptions"),te=ea({restrict:"A",terminal:!0}),Wd=["$compile","$parse",function(a,c){var d=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/, -e={$setViewValue:z};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope","$attrs",function(a,c,d){var l=this,k={},m=e,n;l.databound=d.ngModel;l.init=function(a,c,d){m=a;n=d};l.addOption=function(c,d){Ma(c,'"option value"');k[c]=!0;m.$viewValue==c&&(a.val(c),n.parent()&&n.remove());d&&d[0].hasAttribute("selected")&&(d[0].selected=!0)};l.removeOption=function(a){this.hasOption(a)&&(delete k[a],m.$viewValue===a&&this.renderUnknownOption(a))};l.renderUnknownOption=function(c){c= -"? "+Na(c)+" ?";n.val(c);a.prepend(n);a.val(c);n.prop("selected",!0)};l.hasOption=function(a){return k.hasOwnProperty(a)};c.$on("$destroy",function(){l.renderUnknownOption=z})}],link:function(e,g,h,l){function k(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(C.parent()&&C.remove(),c.val(a),""===a&&p.prop("selected",!0)):B(a)&&p?c.val(""):e.renderUnknownOption(a)};c.on("change",function(){a.$apply(function(){C.parent()&&C.remove();d.$setViewValue(c.val())})})}function m(a,c,d){var e; -d.$render=function(){var a=new eb(d.$viewValue);s(c.find("option"),function(c){c.selected=y(a.get(c.value))})};a.$watch(function(){ga(e,d.$viewValue)||(e=ra(d.$viewValue),d.$render())});c.on("change",function(){a.$apply(function(){var a=[];s(c.find("option"),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function n(e,f,g){function h(a,c,d){S[x]=d;D&&(S[D]=c);return a(e,S)}function k(a){var c;if(u)if(M&&H(a)){c=new eb([]);for(var d=0;d<a.length;d++)c.put(h(M,null,a[d]),!0)}else c= -new eb(a);else M&&(a=h(M,null,a));return function(d,e){var f;f=M?M:B?B:F;return u?y(c.remove(h(f,d,e))):a===h(f,d,e)}}function l(){v||(e.$$postDigest(p),v=!0)}function m(a,c,d){a[c]=a[c]||0;a[c]+=d?1:-1}function p(){v=!1;var a={"":[]},c=[""],d,l,n,r,t;n=g.$viewValue;r=O(e)||[];var B=D?Object.keys(r).sort():r,x,A,H,F,N={};t=k(n);var J=!1,U,V;Q={};for(F=0;H=B.length,F<H;F++){x=F;if(D&&(x=B[F],"$"===x.charAt(0)))continue;A=r[x];d=h(I,x,A)||"";(l=a[d])||(l=a[d]=[],c.push(d));d=t(x,A);J=J||d;A=h(C,x,A); -A=y(A)?A:"";V=M?M(e,S):D?B[F]:F;M&&(Q[V]=x);l.push({id:V,label:A,selected:d})}u||(z||null===n?a[""].unshift({id:"",label:"",selected:!J}):J||a[""].unshift({id:"?",label:"",selected:!0}));x=0;for(B=c.length;x<B;x++){d=c[x];l=a[d];R.length<=x?(n={element:G.clone().attr("label",d),label:l.label},r=[n],R.push(r),f.append(n.element)):(r=R[x],n=r[0],n.label!=d&&n.element.attr("label",n.label=d));J=null;F=0;for(H=l.length;F<H;F++)d=l[F],(t=r[F+1])?(J=t.element,t.label!==d.label&&(m(N,t.label,!1),m(N,d.label, -!0),J.text(t.label=d.label),J.prop("label",t.label)),t.id!==d.id&&J.val(t.id=d.id),J[0].selected!==d.selected&&(J.prop("selected",t.selected=d.selected),Ra&&J.prop("selected",t.selected))):(""===d.id&&z?U=z:(U=w.clone()).val(d.id).prop("selected",d.selected).attr("selected",d.selected).prop("label",d.label).text(d.label),r.push(t={element:U,label:d.label,id:d.id,selected:d.selected}),m(N,d.label,!0),J?J.after(U):n.element.append(U),J=U);for(F++;r.length>F;)d=r.pop(),m(N,d.label,!1),d.element.remove()}for(;R.length> -x;){l=R.pop();for(F=1;F<l.length;++F)m(N,l[F].label,!1);l[0].element.remove()}s(N,function(a,c){0<a?q.addOption(c):0>a&&q.removeOption(c)})}var n;if(!(n=r.match(d)))throw fg("iexp",r,va(f));var C=c(n[2]||n[1]),x=n[4]||n[6],A=/ as /.test(n[0])&&n[1],B=A?c(A):null,D=n[5],I=c(n[3]||""),F=c(n[2]?n[1]:x),O=c(n[7]),M=n[8]?c(n[8]):null,Q={},R=[[{element:f,label:""}]],S={};z&&(a(z)(e),z.removeClass("ng-scope"),z.remove());f.empty();f.on("change",function(){e.$apply(function(){var a=O(e)||[],c;if(u)c=[],s(f.val(), -function(d){d=M?Q[d]:d;c.push("?"===d?t:""===d?null:h(B?B:F,d,a[d]))});else{var d=M?Q[f.val()]:f.val();c="?"===d?t:""===d?null:h(B?B:F,d,a[d])}g.$setViewValue(c);p()})});g.$render=p;e.$watchCollection(O,l);e.$watchCollection(function(){var a=O(e),c;if(a&&H(a)){c=Array(a.length);for(var d=0,f=a.length;d<f;d++)c[d]=h(C,d,a[d])}else if(a)for(d in c={},a)a.hasOwnProperty(d)&&(c[d]=h(C,d,a[d]));return c},l);u&&e.$watchCollection(function(){return g.$modelValue},l)}if(l[1]){var q=l[0];l=l[1];var u=h.multiple, -r=h.ngOptions,z=!1,p,v=!1,w=D(Y.createElement("option")),G=D(Y.createElement("optgroup")),C=w.clone();h=0;for(var A=g.children(),x=A.length;h<x;h++)if(""===A[h].value){p=z=A.eq(h);break}q.init(l,z,C);u&&(l.$isEmpty=function(a){return!a||0===a.length});r?n(e,g,l):u?m(e,g,l):k(e,g,l,q)}}}}],Yd=["$interpolate",function(a){var c={addOption:z,removeOption:z};return{restrict:"E",priority:100,compile:function(d,e){if(B(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k= -d.parent(),m=k.data("$selectController")||k.parent().data("$selectController");m&&m.databound||(m=c);f?a.$watch(f,function(a,c){e.$set("value",a);c!==a&&m.removeOption(c);m.addOption(a,d)}):m.addOption(e.value,d);d.on("$destroy",function(){m.removeOption(e.value)})}}}}],Xd=ea({restrict:"E",terminal:!1}),Ac=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}}, -zc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){F(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw S("ngPattern")("noregexp",g,a,va(c));f=a||t;e.$validate()});e.$validators.pattern=function(a){return e.$isEmpty(a)||B(f)||f.test(a)}}}}},Cc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=ba(a);f=isNaN(a)?-1:a;e.$validate()}); -e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Bc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=ba(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};M.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(Nd(),Pd(ca),D(Y).ready(function(){Jd(Y,tc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document).find("head").prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}</style>'); +(function(O,U,t){'use strict';function J(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.3/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ea(b){if(null==b||Wa(b))return!1;var a="length"in Object(b)&&b.length; +return b.nodeType===qa&&a?!0:L(b)||G(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function m(b,a,c){var d,e;if(b)if(z(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(G(b)||Ea(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==m)b.forEach(a,c,b);else if(nc(b))for(d in b)a.call(c,b[d],d,b);else if("function"===typeof b.hasOwnProperty)for(d in b)b.hasOwnProperty(d)&& +a.call(c,b[d],d,b);else for(d in b)Xa.call(b,d)&&a.call(c,b[d],d,b);return b}function oc(b,a,c){for(var d=Object.keys(b).sort(),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function pc(b){return function(a,c){b(c,a)}}function Ud(){return++nb}function qc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function Nb(b,a,c){for(var d=b.$$hashKey,e=0,f=a.length;e<f;++e){var g=a[e];if(H(g)||z(g))for(var h=Object.keys(g),l=0,k=h.length;l<k;l++){var n=h[l],r=g[n];c&&H(r)?aa(r)?b[n]=new Date(r.valueOf()):(H(b[n])|| +(b[n]=G(r)?[]:{}),Nb(b[n],[r],!0)):b[n]=r}}qc(b,d);return b}function P(b){return Nb(b,za.call(arguments,1),!1)}function Vd(b){return Nb(b,za.call(arguments,1),!0)}function W(b){return parseInt(b,10)}function Ob(b,a){return P(Object.create(b),a)}function v(){}function Ya(b){return b}function ra(b){return function(){return b}}function rc(b){return z(b.toString)&&b.toString!==Object.prototype.toString}function A(b){return"undefined"===typeof b}function w(b){return"undefined"!==typeof b}function H(b){return null!== +b&&"object"===typeof b}function nc(b){return null!==b&&"object"===typeof b&&!sc(b)}function L(b){return"string"===typeof b}function V(b){return"number"===typeof b}function aa(b){return"[object Date]"===sa.call(b)}function z(b){return"function"===typeof b}function Za(b){return"[object RegExp]"===sa.call(b)}function Wa(b){return b&&b.window===b}function $a(b){return b&&b.$evalAsync&&b.$watch}function ab(b){return"boolean"===typeof b}function tc(b){return!(!b||!(b.nodeName||b.prop&&b.attr&&b.find))} +function Wd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function ta(b){return M(b.nodeName||b[0]&&b[0].nodeName)}function bb(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return c}function fa(b,a,c,d){if(Wa(b)||$a(b))throw Fa("cpws");if(uc.test(sa.call(a)))throw Fa("cpta");if(a){if(b===a)throw Fa("cpi");c=c||[];d=d||[];H(b)&&(c.push(b),d.push(a));var e;if(G(b))for(e=a.length=0;e<b.length;e++)a.push(fa(b[e],null,c,d));else{var f=a.$$hashKey;G(a)?a.length=0:m(a,function(b, +c){delete a[c]});if(nc(b))for(e in b)a[e]=fa(b[e],null,c,d);else if(b&&"function"===typeof b.hasOwnProperty)for(e in b)b.hasOwnProperty(e)&&(a[e]=fa(b[e],null,c,d));else for(e in b)Xa.call(b,e)&&(a[e]=fa(b[e],null,c,d));qc(a,f)}}else if(a=b,H(b)){if(c&&-1!==(f=c.indexOf(b)))return d[f];if(G(b))return fa(b,[],c,d);if(uc.test(sa.call(b)))a=new b.constructor(b);else if(aa(b))a=new Date(b.getTime());else if(Za(b))a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex;else return e= +Object.create(sc(b)),fa(b,e,c,d);d&&(c.push(b),d.push(a))}return a}function ia(b,a){if(G(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(H(b))for(c in a=a||{},b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ka(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(G(b)){if(!G(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ka(b[d],a[d]))return!1;return!0}}else{if(aa(b))return aa(a)? +ka(b.getTime(),a.getTime()):!1;if(Za(b))return Za(a)?b.toString()==a.toString():!1;if($a(b)||$a(a)||Wa(b)||Wa(a)||G(a)||aa(a)||Za(a))return!1;c=ga();for(d in b)if("$"!==d.charAt(0)&&!z(b[d])){if(!ka(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!(d in c||"$"===d.charAt(0)||a[d]===t||z(a[d])))return!1;return!0}return!1}function cb(b,a,c){return b.concat(za.call(a,c))}function vc(b,a){var c=2<arguments.length?za.call(arguments,2):[];return!z(a)||a instanceof RegExp?a:c.length?function(){return arguments.length? +a.apply(b,cb(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Xd(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)&&"$"===b.charAt(1)?c=t:Wa(a)?c="$WINDOW":a&&U===a?c="$DOCUMENT":$a(a)&&(c="$SCOPE");return c}function db(b,a){if("undefined"===typeof b)return t;V(a)||(a=a?2:null);return JSON.stringify(b,Xd,a)}function wc(b){return L(b)?JSON.parse(b):b}function xc(b,a){var c=Date.parse("Jan 01, 1970 00:00:00 "+b)/6E4;return isNaN(c)?a:c}function Pb(b, +a,c){c=c?-1:1;var d=xc(a,b.getTimezoneOffset());a=b;b=c*(d-b.getTimezoneOffset());a=new Date(a.getTime());a.setMinutes(a.getMinutes()+b);return a}function ua(b){b=y(b).clone();try{b.empty()}catch(a){}var c=y("<div>").append(b).html();try{return b[0].nodeType===Na?M(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+M(b)})}catch(d){return M(c)}}function yc(b){try{return decodeURIComponent(b)}catch(a){}}function zc(b){var a={},c,d;m((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g, +"%20").split("="),d=yc(c[0]),w(d)&&(b=w(c[1])?yc(c[1]):!0,Xa.call(a,d)?G(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];m(b,function(b,d){G(b)?m(b,function(b){a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))}):a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))});return a.length?a.join("&"):""}function ob(b){return ma(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ma(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g, +"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Yd(b,a){var c,d,e=Oa.length;for(d=0;d<e;++d)if(c=Oa[d]+a,L(c=b.getAttribute(c)))return c;return null}function Zd(b,a){var c,d,e={};m(Oa,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});m(Oa,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Yd(c,"strict-di"),a(c,d?[d]:[],e))}function Ac(b,a,c){H(c)|| +(c={});c=P({strictDi:!1},c);var d=function(){b=y(b);if(b.injector()){var d=b[0]===U?"document":ua(b);throw Fa("btstrpd",d.replace(/</,"<").replace(/>/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=eb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e= +/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;O&&e.test(O.name)&&(c.debugInfoEnabled=!0,O.name=O.name.replace(e,""));if(O&&!f.test(O.name))return d();O.name=O.name.replace(f,"");ca.resumeBootstrap=function(b){m(b,function(b){a.push(b)});return d()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function $d(){O.name="NG_ENABLE_DEBUG_INFO!"+O.name;O.location.reload()}function ae(b){b=ca.element(b).injector();if(!b)throw Fa("test");return b.get("$$testability")}function Bc(b,a){a=a|| +"_";return b.replace(be,function(b,d){return(d?a:"")+b.toLowerCase()})}function ce(){var b;if(!Cc){var a=pb();la=O.jQuery;w(a)&&(la=null===a?t:O[a]);la&&la.fn.on?(y=la,P(la.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),b=la.cleanData,la.cleanData=function(a){var d;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d=la._data(f,"events"))&&d.$destroy&&la(f).triggerHandler("$destroy");b(a)}):y=Q;ca.element=y;Cc=!0}}function Sb(b, +a,c){if(!b)throw Fa("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&G(b)&&(b=b[b.length-1]);Sb(z(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ra(b,a){if("hasOwnProperty"===b)throw Fa("badname",a);}function Dc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&z(b)?vc(e,b):b}function qb(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!== +b);return y(c)}function ga(){return Object.create(null)}function de(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=J("$injector"),d=J("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||J;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(b,c,e,f){f||(f=d);return function(){f[e||"push"]([b,c,arguments]);return C}}function b(a,c){return function(b,e){e&&z(e)&& +(e.$$moduleName=f);d.push([a,c,arguments]);return C}}if(!g)throw c("nomod",f);var d=[],e=[],s=[],x=a("$injector","invoke","push",e),C={_invokeQueue:d,_configBlocks:e,_runBlocks:s,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator"),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider", +"register"),directive:b("$compileProvider","directive"),config:x,run:function(a){s.push(a);return this}};h&&x(h);return C})}})}function ee(b){P(b,{bootstrap:Ac,copy:fa,extend:P,merge:Vd,equals:ka,element:y,forEach:m,injector:eb,noop:v,bind:vc,toJson:db,fromJson:wc,identity:Ya,isUndefined:A,isDefined:w,isString:L,isFunction:z,isObject:H,isNumber:V,isElement:tc,isArray:G,version:fe,isDate:aa,lowercase:M,uppercase:rb,callbacks:{counter:0},getTestability:ae,$$minErr:J,$$csp:fb,reloadWithDebugInfo:$d}); +gb=de(O);try{gb("ngLocale")}catch(a){gb("ngLocale",[]).provider("$locale",ge)}gb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:he});a.provider("$compile",Ec).directive({a:ie,input:Fc,textarea:Fc,form:je,script:ke,select:le,style:me,option:ne,ngBind:oe,ngBindHtml:pe,ngBindTemplate:qe,ngClass:re,ngClassEven:se,ngClassOdd:te,ngCloak:ue,ngController:ve,ngForm:we,ngHide:xe,ngIf:ye,ngInclude:ze,ngInit:Ae,ngNonBindable:Be,ngPluralize:Ce,ngRepeat:De,ngShow:Ee,ngStyle:Fe,ngSwitch:Ge, +ngSwitchWhen:He,ngSwitchDefault:Ie,ngOptions:Je,ngTransclude:Ke,ngModel:Le,ngList:Me,ngChange:Ne,pattern:Gc,ngPattern:Gc,required:Hc,ngRequired:Hc,minlength:Ic,ngMinlength:Ic,maxlength:Jc,ngMaxlength:Jc,ngValue:Oe,ngModelOptions:Pe}).directive({ngInclude:Qe}).directive(sb).directive(Kc);a.provider({$anchorScroll:Re,$animate:Se,$$animateQueue:Te,$$AnimateRunner:Ue,$browser:Ve,$cacheFactory:We,$controller:Xe,$document:Ye,$exceptionHandler:Ze,$filter:Lc,$interpolate:$e,$interval:af,$http:bf,$httpParamSerializer:cf, +$httpParamSerializerJQLike:df,$httpBackend:ef,$location:ff,$log:gf,$parse:hf,$rootScope:jf,$q:kf,$$q:lf,$sce:mf,$sceDelegate:nf,$sniffer:of,$templateCache:pf,$templateRequest:qf,$$testability:rf,$timeout:sf,$window:tf,$$rAF:uf,$$jqLite:vf,$$HashMap:wf,$$cookieReader:xf})}])}function hb(b){return b.replace(yf,function(a,b,d,e){return e?d.toUpperCase():d}).replace(zf,"Moz$1")}function Mc(b){b=b.nodeType;return b===qa||!b||9===b}function Nc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Tb.test(b)){c= +c||e.appendChild(a.createElement("div"));d=(Af.exec(b)||["",""])[1].toLowerCase();d=na[d]||na._default;c.innerHTML=d[1]+b.replace(Bf,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=cb(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";m(f,function(a){e.appendChild(a)});return e}function Q(b){if(b instanceof Q)return b;var a;L(b)&&(b=R(b),a=!0);if(!(this instanceof Q)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new Q(b)}if(a){a=U; +var c;b=(c=Cf.exec(b))?[a.createElement(c[1])]:(c=Nc(b,a))?c.childNodes:[]}Oc(this,b)}function Vb(b){return b.cloneNode(!0)}function tb(b,a){a||ub(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)ub(c[d])}function Pc(b,a,c,d){if(w(d))throw Ub("offargs");var e=(d=vb(b))&&d.events,f=d&&d.handle;if(f)if(a)m(a.split(" "),function(a){if(w(c)){var d=e[a];bb(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a, +f,!1),delete e[a]}function ub(b,a){var c=b.ng339,d=c&&ib[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Pc(b)),delete ib[c],b.ng339=t))}function vb(b,a){var c=b.ng339,c=c&&ib[c];a&&!c&&(b.ng339=c=++Df,c=ib[c]={events:{},data:{},handle:t});return c}function Wb(b,a,c){if(Mc(b)){var d=w(c),e=!d&&a&&!H(a),f=!a;b=(b=vb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];P(b,a)}}}function wb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+ +" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function xb(b,a){a&&b.setAttribute&&m(a.split(" "),function(a){b.setAttribute("class",R((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+R(a)+" "," ")))})}function yb(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");m(a.split(" "),function(a){a=R(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",R(c))}}function Oc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c= +a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Qc(b,a){return zb(b,"$"+(a||"ngController")+"Controller")}function zb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=G(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=y.data(b,a[d]))!==t)return c;b=b.parentNode||11===b.nodeType&&b.host}}function Rc(b){for(tb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Xb(b,a){a||tb(b);var c=b.parentNode;c&&c.removeChild(b)}function Ef(b, +a){a=a||O;if("complete"===a.document.readyState)a.setTimeout(b);else y(a).on("load",b)}function Sc(b,a){var c=Ab[a.toLowerCase()];return c&&Tc[ta(b)]&&c}function Ff(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Uc[a]}function Gf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=a[e||c.type],g=f?f.length:0;if(g){if(A(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped= +!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=ia(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function vf(){this.$get=function(){return P(Q,{hasClass:function(b,a){b.attr&&(b=b[0]);return wb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return yb(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return xb(b,a)}})}}function Ga(b,a){var c=b&&b.$$hashKey; +if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Ud)():c+":"+b}function Sa(b,a){if(a){var c=0;this.nextUid=function(){return++c}}m(b,this.put,this)}function Hf(b){return(b=b.toString().replace(Vc,"").match(Wc))?"function("+(b[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function eb(b,a){function c(a){return function(b,c){if(H(b))m(b,pc(a));else return a(b,c)}}function d(a,b){Ra(a,"service");if(z(b)||G(b))b=s.instantiate(b); +if(!b.$get)throw Ha("pget",a);return r[a+"Provider"]=b}function e(a,b){return function(){var c=C.invoke(b,this);if(A(c))throw Ha("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;m(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=s.get(e[0]);f[e[1]].apply(f,e[2])}}if(!n.get(a)){n.put(a,!0);try{L(a)?(c=gb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(s.invoke(a)):G(a)? +b.push(s.invoke(a)):Qa(a,"module")}catch(e){throw G(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ha("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Ha("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a),b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var h=[],k=eb.$$annotate(b, +a,g),l,s,n;s=0;for(l=k.length;s<l;s++){n=k[s];if("string"!==typeof n)throw Ha("itkn",n);h.push(f&&f.hasOwnProperty(n)?f[n]:d(n,g))}G(b)&&(b=b[l]);return b.apply(c,h)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((G(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return H(a)||z(a)?a:d},get:d,annotate:eb.$$annotate,has:function(a){return r.hasOwnProperty(a+"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],n=new Sa([],!0),r={$provide:{provider:c(d),factory:c(f),service:c(function(a, +b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ra(b),!1)}),constant:c(function(a,b){Ra(a,"constant");r[a]=b;x[a]=b}),decorator:function(a,b){var c=s.get(a+"Provider"),d=c.$get;c.$get=function(){var a=C.invoke(d,c);return C.invoke(b,null,{$delegate:a})}}}},s=r.$injector=h(r,function(a,b){ca.isString(b)&&k.push(b);throw Ha("unpr",k.join(" <- "));}),x={},C=x.$injector=h(x,function(a,b){var c=s.get(a+"Provider",b);return C.invoke(c.$get,c,t,a)});m(g(b), +function(a){a&&C.invoke(a)});return C}function Re(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ta(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():tc(c)?(c=c[0],c="fixed"!==a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):V(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0, +0)}function g(a){a=L(a)?a:c.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||Ef(function(){d.$evalAsync(g)})});return g}]}function jb(b,a){if(!b&&!a)return"";if(!b)return a;if(!a)return b;G(b)&&(b=b.join(" "));G(a)&&(a=a.join(" "));return b+" "+a}function If(b){L(b)&&(b=b.split(" "));var a=ga();m(b,function(b){b.length&&(a[b]=!0)});return a}function Ia(b){return H(b)? +b:{}}function Jf(b,a,c,d){function e(a){try{a.apply(null,za.call(arguments,1))}finally{if(C--,0===C)for(;F.length;)try{F.pop()()}catch(b){c.error(b)}}}function f(){g();h()}function g(){a:{try{u=n.state;break a}catch(a){}u=void 0}u=A(u)?null:u;ka(u,D)&&(u=D);D=u}function h(){if(K!==l.url()||p!==u)K=l.url(),p=u,m(B,function(a){a(l.url(),u)})}var l=this,k=b.location,n=b.history,r=b.setTimeout,s=b.clearTimeout,x={};l.isMock=!1;var C=0,F=[];l.$$completeOutstandingRequest=e;l.$$incOutstandingRequestCount= +function(){C++};l.notifyWhenNoOutstandingRequests=function(a){0===C?a():F.push(a)};var u,p,K=k.href,q=a.find("base"),I=null;g();p=u;l.url=function(a,c,e){A(e)&&(e=null);k!==b.location&&(k=b.location);n!==b.history&&(n=b.history);if(a){var f=p===e;if(K===a&&(!d.history||f))return l;var h=K&&Ja(K)===Ja(a);K=a;p=e;if(!d.history||h&&f){if(!h||I)I=a;c?k.replace(a):h?(c=k,e=a.indexOf("#"),a=-1===e?"":a.substr(e),c.hash=a):k.href=a}else n[c?"replaceState":"pushState"](e,"",a),g(),p=u;return l}return I|| +k.href.replace(/%27/g,"'")};l.state=function(){return u};var B=[],N=!1,D=null;l.onUrlChange=function(a){if(!N){if(d.history)y(b).on("popstate",f);y(b).on("hashchange",f);N=!0}B.push(a);return a};l.$$applicationDestroyed=function(){y(b).off("hashchange popstate",f)};l.$$checkUrlChange=h;l.baseHref=function(){var a=q.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};l.defer=function(a,b){var c;C++;c=r(function(){delete x[c];e(a)},b||0);x[c]=!0;return c};l.defer.cancel=function(a){return x[a]? +(delete x[a],s(a),e(v),!0):!1}}function Ve(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new Jf(b,d,a,c)}]}function We(){this.$get=function(){function b(b,d){function e(a){a!=r&&(s?s==a&&(s=a.n):s=a,f(a.n,a.p),f(a,r),r=a,r.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw J("$cacheFactory")("iid",b);var g=0,h=P({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,n={},r=null,s=null;return a[b]={put:function(a,b){if(!A(b)){if(k<Number.MAX_VALUE){var c= +n[a]||(n[a]={key:a});e(c)}a in l||g++;l[a]=b;g>k&&this.remove(s.key);return b}},get:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;b==r&&(r=b.p);b==s&&(s=b.n);f(b.n,b.p);delete n[a]}delete l[a];g--},removeAll:function(){l={};g=0;n={};r=s=null},destroy:function(){n=h=l=null;delete a[b]},info:function(){return P({},h,{size:g})}}}var a={};b.info=function(){var b={};m(a,function(a,e){b[e]=a.info()});return b}; +b.get=function(b){return a[b]};return b}}function pf(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Ec(b,a){function c(a,b,c){var d=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,e={};m(a,function(a,f){var g=a.match(d);if(!g)throw ea("iscp",b,f,a,c?"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f}});return e}function d(a){var b=a.charAt(0);if(!b||b!==M(b))throw ea("baddir",a);if(a!==a.trim())throw ea("baddir", +a);}var e={},f=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,g=/(([\w\-]+)(?:\:([^;]+))?;?)/,h=Wd("ngSrc,ngSrcset,src,srcset"),l=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,k=/^(on[a-z]+|formaction)$/;this.directive=function s(a,f){Ra(a,"directive");L(a)?(d(a),Sb(f,"directiveFactory"),e.hasOwnProperty(a)||(e[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,d){var f=[];m(e[a],function(e,g){try{var h=b.invoke(e);z(h)?h={compile:ra(h)}:!h.compile&&h.link&&(h.compile=ra(h.link));h.priority=h.priority|| +0;h.index=g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";var k=h,l=h,s=h.name,n={isolateScope:null,bindToController:null};H(l.scope)&&(!0===l.bindToController?(n.bindToController=c(l.scope,s,!0),n.isolateScope={}):n.isolateScope=c(l.scope,s,!1));H(l.bindToController)&&(n.bindToController=c(l.bindToController,s,!0));if(H(n.bindToController)){var C=l.controller,$=l.controllerAs;if(!C)throw ea("noctrl",s);var ha;a:if($&&L($))ha=$;else{if(L(C)){var m=Xc.exec(C); +if(m){ha=m[3];break a}}ha=void 0}if(!ha)throw ea("noident",s);}var q=k.$$bindings=n;H(q.isolateScope)&&(h.$$isolateBindings=q.isolateScope);h.$$moduleName=e.$$moduleName;f.push(h)}catch(t){d(t)}});return f}])),e[a].push(f)):m(a,pc(s));return this};this.aHrefSanitizationWhitelist=function(b){return w(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()}; +var n=!0;this.debugInfoEnabled=function(a){return w(a)?(n=a,this):n};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,d,u,p,K,q,I,B,N){function D(a,b){try{a.addClass(b)}catch(c){}}function Z(a,b,c,d,e){a instanceof y||(a=y(a));m(a,function(b,c){b.nodeType==Na&&b.nodeValue.match(/\S+/)&&(a[c]=y(b).wrap("<span></span>").parent()[0])});var f=S(a,b,a,c,d,e);Z.$$addScopeClass(a); +var g=null;return function(b,c,d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?y(Yb(g,y("<div>").append(a).html())):c?Pa.clone.call(a):a;if(h)for(var k in h)d.data("$"+k+"Controller",h[k].instance);Z.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function S(a,b,c,d,e,f){function g(a, +c,d,e){var f,k,l,s,n,B,C;if(p)for(C=Array(c.length),s=0;s<h.length;s+=3)f=h[s],C[f]=c[f];else C=c;s=0;for(n=h.length;s<n;)if(k=C[h[s++]],c=h[s++],f=h[s++],c){if(c.scope){if(l=a.$new(),Z.$$addScopeInfo(y(k),l),B=c.$$destroyBindings)c.$$destroyBindings=null,l.$on("$destroyed",B)}else l=a;B=c.transcludeOnThisElement?$(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?$(a,b):null;c(f,l,k,d,B,c)}else f&&f(a,k.childNodes,t,e)}for(var h=[],k,l,s,n,p,B=0;B<a.length;B++){k=new aa;l=ha(a[B],[],k,0===B? +d:t,e);(f=l.length?E(l,a[B],k,b,c,null,[],[],f):null)&&f.scope&&Z.$$addScopeClass(k.$$element);k=f&&f.terminal||!(s=a[B].childNodes)||!s.length?null:S(s,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(B,f,k),n=!0,p=p||f;f=null}return n?g:null}function $(a,b,c){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function ha(a,b,c,d,e){var h=c.$attr,k;switch(a.nodeType){case qa:w(b, +wa(ta(a)),"E",d,e);for(var l,s,n,p=a.attributes,B=0,C=p&&p.length;B<C;B++){var x=!1,S=!1;l=p[B];k=l.name;s=R(l.value);l=wa(k);if(n=ia.test(l))k=k.replace(Zc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var F=l.replace(/(Start|End)$/,"");A(F)&&l===F+"Start"&&(x=k,S=k.substr(0,k.length-5)+"end",k=k.substr(0,k.length-6));l=wa(k.toLowerCase());h[l]=k;if(n||!c.hasOwnProperty(l))c[l]=s,Sc(a,l)&&(c[l]=!0);V(a,b,s,l,n);w(b,l,"A",d,e,x,S)}a=a.className;H(a)&&(a=a.animVal);if(L(a)&& +""!==a)for(;k=g.exec(a);)l=wa(k[2]),w(b,l,"C",d,e)&&(c[l]=R(k[3])),a=a.substr(k.index+k[0].length);break;case Na:if(11===Ua)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===Na;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);xa(b,a.nodeValue);break;case 8:try{if(k=f.exec(a.nodeValue))l=wa(k[1]),w(b,l,"M",d,e)&&(c[l]=R(k[2]))}catch($){}}b.sort(Aa);return b}function va(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ea("uterdir",b,c); +a.nodeType==qa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return y(d)}function Yc(a,b,c){return function(d,e,f,g,h){e=va(e[0],b,c);return a(d,e,f,g,h)}}function E(a,b,d,e,f,g,h,k,s){function n(a,b,c,d){if(a){c&&(a=Yc(a,c,d));a.require=E.require;a.directiveName=w;if(u===E||E.$$isolateScope)a=X(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=Yc(b,c,d));b.require=E.require;b.directiveName=w;if(u===E||E.$$isolateScope)b=X(b,{isolateScope:!0});k.push(b)}} +function B(a,b,c,d){var e;if(L(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;e||(d="$"+b+"Controller",e=g?c.inheritedData(d):c.data(d));if(!e&&!f)throw ea("ctreq",b,a);}else if(G(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=B(a,b[g],c,d);return e||null}function x(a,b,c,d,e,f){var g=ga(),h;for(h in d){var k=d[h],l={$scope:k===u||k.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},s=k.controller;"@"==s&&(s=b[k.name]);l=p(s, +l,!0,k.controllerAs);g[k.name]=l;q||a.data("$"+k.name+"Controller",l.instance)}return g}function S(a,c,e,f,g,l){function s(a,b,c){var d;$a(a)||(c=b,b=a,a=t);q&&(d=m);c||(c=q?ja.parent():ja);return g(a,b,d,c,va)}var n,p,C,F,m,ha,ja;b===e?(f=d,ja=d.$$element):(ja=y(e),f=new aa(ja,d));u&&(F=c.$new(!0));g&&(ha=s,ha.$$boundTransclude=g);N&&(m=x(ja,f,ha,N,F,c));u&&(Z.$$addScopeInfo(ja,F,!0,!(D&&(D===u||D===u.$$originalDirective))),Z.$$addScopeClass(ja,!0),F.$$isolateBindings=u.$$isolateBindings,W(c,f,F, +F.$$isolateBindings,u,F));if(m){var K=u||$,I;K&&m[K.name]&&(p=K.$$bindings.bindToController,(C=m[K.name])&&C.identifier&&p&&(I=C,l.$$destroyBindings=W(c,f,C.instance,p,K)));for(n in m){C=m[n];var E=C();E!==C.instance&&(C.instance=E,ja.data("$"+n+"Controller",E),C===I&&(l.$$destroyBindings(),l.$$destroyBindings=W(c,f,E,p,K)))}}n=0;for(l=h.length;n<l;n++)p=h[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha);var va=c;u&&(u.template||null===u.templateUrl)&&(va=F);a&&a(va, +e.childNodes,t,g);for(n=k.length-1;0<=n;n--)p=k[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha)}s=s||{};for(var F=-Number.MAX_VALUE,$=s.newScopeDirective,N=s.controllerDirectives,u=s.newIsolateScopeDirective,D=s.templateDirective,m=s.nonTlbTranscludeDirective,K=!1,I=!1,q=s.hasElementTranscludeDirective,ba=d.$$element=y(b),E,w,v,A=e,Aa,xa=0,Ta=a.length;xa<Ta;xa++){E=a[xa];var M=E.$$start,P=E.$$end;M&&(ba=va(b,M,P));v=t;if(F>E.priority)break;if(v=E.scope)E.templateUrl|| +(H(v)?(O("new/isolated scope",u||$,E,ba),u=E):O("new/isolated scope",u,E,ba)),$=$||E;w=E.name;!E.templateUrl&&E.controller&&(v=E.controller,N=N||ga(),O("'"+w+"' controller",N[w],E,ba),N[w]=E);if(v=E.transclude)K=!0,E.$$tlb||(O("transclusion",m,E,ba),m=E),"element"==v?(q=!0,F=E.priority,v=ba,ba=d.$$element=y(U.createComment(" "+w+": "+d[w]+" ")),b=ba[0],T(f,za.call(v,0),b),A=Z(v,e,F,g&&g.name,{nonTlbTranscludeDirective:m})):(v=y(Vb(b)).contents(),ba.empty(),A=Z(v,e));if(E.template)if(I=!0,O("template", +D,E,ba),D=E,v=z(E.template)?E.template(ba,d):E.template,v=fa(v),E.replace){g=E;v=Tb.test(v)?$c(Yb(E.templateNamespace,R(v))):[];b=v[0];if(1!=v.length||b.nodeType!==qa)throw ea("tplrt",w,"");T(f,ba,b);Ta={$attr:{}};v=ha(b,[],Ta);var Q=a.splice(xa+1,a.length-(xa+1));u&&ad(v);a=a.concat(v).concat(Q);J(d,Ta);Ta=a.length}else ba.html(v);if(E.templateUrl)I=!0,O("template",D,E,ba),D=E,E.replace&&(g=E),S=Lf(a.splice(xa,a.length-xa),ba,d,f,K&&A,h,k,{controllerDirectives:N,newScopeDirective:$!==E&&$,newIsolateScopeDirective:u, +templateDirective:D,nonTlbTranscludeDirective:m}),Ta=a.length;else if(E.compile)try{Aa=E.compile(ba,d,A),z(Aa)?n(null,Aa,M,P):Aa&&n(Aa.pre,Aa.post,M,P)}catch(Kf){c(Kf,ua(ba))}E.terminal&&(S.terminal=!0,F=Math.max(F,E.priority))}S.scope=$&&!0===$.scope;S.transcludeOnThisElement=K;S.templateOnThisElement=I;S.transclude=A;s.hasElementTranscludeDirective=q;return S}function ad(a){for(var b=0,c=a.length;b<c;b++)a[b]=Ob(a[b],{$$isolateScope:!0})}function w(b,d,f,g,h,k,l){if(d===h)return null;h=null;if(e.hasOwnProperty(d)){var n; +d=a.get(d+"Directive");for(var p=0,B=d.length;p<B;p++)try{n=d[p],(g===t||g>n.priority)&&-1!=n.restrict.indexOf(f)&&(k&&(n=Ob(n,{$$start:k,$$end:l})),b.push(n),h=n)}catch(x){c(x)}}return h}function A(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d<f;d++)if(b=c[d],b.multiElement)return!0;return!1}function J(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;m(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});m(b,function(b,f){"class"== +f?(D(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function Lf(a,b,c,e,f,g,h,k){var l=[],s,n,p=b[0],B=a.shift(),C=Ob(B,{templateUrl:null,transclude:null,replace:null,$$originalDirective:B}),x=z(B.templateUrl)?B.templateUrl(b,c):B.templateUrl,N=B.templateNamespace;b.empty();d(x).then(function(d){var F,u;d=fa(d);if(B.replace){d=Tb.test(d)?$c(Yb(N,R(d))): +[];F=d[0];if(1!=d.length||F.nodeType!==qa)throw ea("tplrt",B.name,x);d={$attr:{}};T(e,b,F);var K=ha(F,[],d);H(B.scope)&&ad(K);a=K.concat(a);J(c,d)}else F=p,b.html(d);a.unshift(C);s=E(a,F,c,f,b,B,g,h,k);m(e,function(a,c){a==F&&(e[c]=b[0])});for(n=S(b[0].childNodes,f);l.length;){d=l.shift();u=l.shift();var I=l.shift(),va=l.shift(),K=b[0];if(!d.$$destroyed){if(u!==p){var Z=u.className;k.hasElementTranscludeDirective&&B.replace||(K=Vb(F));T(I,y(u),K);D(y(K),Z)}u=s.transcludeOnThisElement?$(d,s.transclude, +va):va;s(n,d,K,e,u,s)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(s.transcludeOnThisElement&&(a=$(b,s.transclude,e)),s(n,b,c,d,a,s)))}}function Aa(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function O(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ea("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,ua(d));}function xa(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a= +a.parent();var b=!!a.length;b&&Z.$$addBindingClass(a);return function(a,c){var e=c.parent();b||Z.$$addBindingClass(e);Z.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Yb(a,b){a=M(a||"html");switch(a){case "svg":case "math":var c=U.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function Q(a,b){if("srcdoc"==b)return I.HTML;var c=ta(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b|| +"ngSrc"==b))return I.RESOURCE_URL}function V(a,c,d,e,f){var g=Q(a,e);f=h[e]||f;var l=b(d,!0,g,f);if(l){if("multiple"===e&&"select"===ta(a))throw ea("selmulti",ua(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers={});if(k.test(e))throw ea("nodomevents");var s=h[e];s!==d&&(l=s&&b(s,!0,g,f),d=s);l&&(h[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e, +a)}))}}}})}}function T(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=U.createDocumentFragment();a.appendChild(d);y.hasData(d)&&(y(c).data(y(d).data()),la?(Rb=!0,la.cleanData([d])):delete y.cache[d[y.expando]]);d=1;for(e=b.length;d<e;d++)f=b[d],y(f).remove(),a.appendChild(f),delete b[d];b[0]=c;b.length=1}function X(a, +b){return P(function(){return a.apply(null,arguments)},a,b)}function Y(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,ua(d))}}function W(a,c,d,e,f,g){var h;m(e,function(e,g){var k=e.attrName,l=e.optional,s=e.mode,n,p,B,C;Xa.call(c,k)||(c[k]=t);switch(s){case "@":c[k]||l||(d[g]=t);c.$observe(k,function(a){d[g]=a});c.$$observers[k].$$scope=a;c[k]&&(d[g]=b(c[k])(a));break;case "=":if(l&&!c[k])break;p=u(c[k]);C=p.literal?ka:function(a,b){return a===b||a!==a&&b!==b};B=p.assign||function(){n=d[g]=p(a);throw ea("nonassign", +c[k],f.name);};n=d[g]=p(a);l=function(b){C(b,d[g])||(C(b,n)?B(a,b=d[g]):d[g]=b);return n=b};l.$stateful=!0;l=e.collection?a.$watchCollection(c[k],l):a.$watch(u(c[k],l),null,p.literal);h=h||[];h.push(l);break;case "&":p=u(c[k]);if(p===v&&l)break;d[g]=function(b){return p(a,b)}}});e=h?function(){for(var a=0,b=h.length;a<b;++a)h[a]()}:v;return g&&e!==v?(g.$on("$destroy",e),v):e}var aa=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element= +a};aa.prototype={$normalize:wa,$addClass:function(a){a&&0<a.length&&B.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&B.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=bd(a,b);c&&c.length&&B.addClass(this.$$element,c);(c=bd(b,a))&&c.length&&B.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Sc(f,a),h=Ff(f,a),f=a;g?(this.$$element.prop(a,b),e=g):h&&(this[h]=b,f=h);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Bc(a, +"-"));g=ta(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=N(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",h=R(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(h)?k:/(,)/,h=h.split(k),k=Math.floor(h.length/2),l=0;l<k;l++)var s=2*l,g=g+N(R(h[s]),!0),g=g+(" "+R(h[s+1]));h=R(h[2*l]).split(/\s/);g+=N(R(h[0]),!0);2===h.length&&(g+=" "+R(h[1]));this[a]=b=g}!1!==d&&(null===b||b===t?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&m(a[f], +function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ga()),e=d[a]||(d[a]=[]);e.push(b);K.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])});return function(){bb(e,b)}}};var ca=b.startSymbol(),da=b.endSymbol(),fa="{{"==ca||"}}"==da?Ya:function(a){return a.replace(/\{\{/g,ca).replace(/}}/g,da)},ia=/^ngAttr[A-Z]/;Z.$$addBindingInfo=n?function(a,b){var c=a.data("$binding")||[];G(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:v;Z.$$addBindingClass= +n?function(a){D(a,"ng-binding")}:v;Z.$$addScopeInfo=n?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:v;Z.$$addScopeClass=n?function(a,b){D(a,b?"ng-isolate-scope":"ng-scope")}:v;return Z}]}function wa(b){return hb(b.replace(Zc,""))}function bd(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function $c(b){b=y(b);var a=b.length;if(1>=a)return b;for(;a--;)8=== +b[a].nodeType&&Mf.call(b,a,1);return b}function Xe(){var b={},a=!1;this.register=function(a,d){Ra(a,"controller");H(a)?P(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!H(a.$scope))throw J("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,l){var k,n,r;h=!0===h;l&&L(l)&&(r=l);if(L(f)){l=f.match(Xc);if(!l)throw Nf("ctrlfmt",f);n=l[1];r=r||l[3];f=b.hasOwnProperty(n)?b[n]:Dc(g.$scope,n,!0)||(a?Dc(d,n,!0):t);Qa(f, +n,!0)}if(h)return h=(G(f)?f[f.length-1]:f).prototype,k=Object.create(h||null),r&&e(g,r,k,n||f.name),P(function(){var a=c.invoke(f,k,g,n);a!==k&&(H(a)||z(a))&&(k=a,r&&e(g,r,k,n||f.name));return k},{instance:k,identifier:r});k=c.instantiate(f,g,n);r&&e(g,r,k,n||f.name);return k}}]}function Ye(){this.$get=["$window",function(b){return y(b.document)}]}function Ze(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b){return H(b)?aa(b)?b.toISOString():db(b):b} +function cf(){this.$get=function(){return function(b){if(!b)return"";var a=[];oc(b,function(b,d){null===b||A(b)||(G(b)?m(b,function(b,c){a.push(ma(d)+"="+ma(Zb(b)))}):a.push(ma(d)+"="+ma(Zb(b))))});return a.join("&")}}}function df(){this.$get=function(){return function(b){function a(b,e,f){null===b||A(b)||(G(b)?m(b,function(b){a(b,e+"[]")}):H(b)&&!aa(b)?oc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(ma(e)+"="+ma(Zb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function $b(b, +a){if(L(b)){var c=b.replace(Of,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(cd))||(d=(d=c.match(Pf))&&Qf[d[0]].test(c));d&&(b=wc(c))}}return b}function dd(b){var a=ga(),c;L(b)?m(b.split("\n"),function(b){c=b.indexOf(":");var e=M(R(b.substr(0,c)));b=R(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):H(b)&&m(b,function(b,c){var f=M(c),g=R(b);f&&(a[f]=a[f]?a[f]+", "+g:g)});return a}function ed(b){var a;return function(c){a||(a=dd(b));return c?(c=a[M(c)],void 0===c&&(c=null),c):a}}function fd(b, +a,c,d){if(z(d))return d(b,a,c);m(d,function(d){b=d(b,a,c)});return b}function bf(){var b=this.defaults={transformResponse:[$b],transformRequest:[function(a){return H(a)&&"[object File]"!==sa.call(a)&&"[object Blob]"!==sa.call(a)&&"[object FormData]"!==sa.call(a)?db(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ac),put:ia(ac),patch:ia(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return w(b)? +(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=P({},a);b.data=a.data?fd(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a,b){var c,e={};m(a,function(a,d){z(a)?(c=a(b),null!=c&&(e[d]=c)):e[d]=a});return e}if(!ca.isObject(a))throw J("$http")("badreq",a);var e=P({method:"get",transformRequest:b.transformRequest, +transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);e.headers=function(a){var c=b.headers,e=P({},a.headers),f,g,h,c=P({},c.common,c[M(a.method)]);a:for(f in c){g=M(f);for(h in e)if(M(h)===g)continue a;e[f]=c[f]}return d(e,ia(a))}(a);e.method=rb(e.method);e.paramSerializer=L(e.paramSerializer)?l.get(e.paramSerializer):e.paramSerializer;var f=[function(a){var d=a.headers,e=fd(a.data,ed(d),t,a.transformRequest);A(e)&&m(d,function(a,b){"content-type"===M(b)&&delete d[b]});A(a.withCredentials)&& +!A(b.withCredentials)&&(a.withCredentials=b.withCredentials);return n(a,e).then(c,c)},t],g=h.when(e);for(m(x,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),g=g.then(a,k)}g.success=function(a){Qa(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){Qa(a,"fn");g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g} +function n(c,f){function l(b,c,d,e){function f(){n(c,b,d,e)}N&&(200<=b&&300>b?N.put(S,[b,c,dd(d),e]):N.remove(S));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function n(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:ed(d),config:c,statusText:e})}function x(a){n(a.data,a.status,ia(a.headers()),a.statusText)}function m(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),B=I.promise,N,D,q=c.headers,S=r(c.url,c.paramSerializer(c.params)); +k.pendingRequests.push(c);B.then(m,m);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(N=H(c.cache)?c.cache:H(b.cache)?b.cache:s);N&&(D=N.get(S),w(D)?D&&z(D.then)?D.then(x,x):G(D)?n(D[1],D[0],ia(D[2]),D[3]):n(D,200,{},"OK"):N.put(S,B));A(D)&&((D=gd(c.url)?e()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(q[c.xsrfHeaderName||b.xsrfHeaderName]=D),d(c.method,S,f,l,q,c.timeout,c.withCredentials,c.responseType));return B}function r(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b); +return a}var s=f("$http");b.paramSerializer=L(b.paramSerializer)?l.get(b.paramSerializer):b.paramSerializer;var x=[];m(c,function(a){x.unshift(L(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){m(arguments,function(a){k[a]=function(b,c){return k(P({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){m(arguments,function(a){k[a]=function(b,c,d){return k(P({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function Rf(){return new O.XMLHttpRequest} +function ef(){this.$get=["$browser","$window","$document",function(b,a,c){return Sf(b,Rf,b.defer,a.angular.callbacks,c[0])}]}function Sf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),n=null;f.type="text/javascript";f.src=a;f.async=!0;n=function(a){f.removeEventListener("load",n,!1);f.removeEventListener("error",n,!1);e.body.removeChild(f);f=null;var g=-1,x="unknown";a&&("load"!==a.type||d[b].called||(a={type:"error"}),x=a.type,g="error"===a.type?404:200);c&&c(g,x)};f.addEventListener("load", +n,!1);f.addEventListener("error",n,!1);e.body.appendChild(f);return n}return function(e,h,l,k,n,r,s,x){function C(){p&&p();K&&K.abort()}function F(a,d,e,f,g){I!==t&&c.cancel(I);p=K=null;a(d,e,f,g);b.$$completeOutstandingRequest(v)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==M(e)){var u="_"+(d.counter++).toString(36);d[u]=function(a){d[u].data=a;d[u].called=!0};var p=f(h.replace("JSON_CALLBACK","angular.callbacks."+u),u,function(a,b){F(k,a,d[u].data,"",b);d[u]=v})}else{var K=a();K.open(e, +h,!0);m(n,function(a,b){w(a)&&K.setRequestHeader(b,a)});K.onload=function(){var a=K.statusText||"",b="response"in K?K.response:K.responseText,c=1223===K.status?204:K.status;0===c&&(c=b?200:"file"==Ba(h).protocol?404:0);F(k,c,b,K.getAllResponseHeaders(),a)};e=function(){F(k,-1,null,null,"")};K.onerror=e;K.onabort=e;s&&(K.withCredentials=!0);if(x)try{K.responseType=x}catch(q){if("json"!==x)throw q;}K.send(l)}if(0<r)var I=c(C,r);else r&&z(r.then)&&r.then(C)}}function $e(){var b="{{",a="}}";this.startSymbol= +function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(n,b).replace(r,a)}function h(f,h,n,r){function u(a){try{var b=a;a=n?e.getTrusted(n,b):e.valueOf(b);var c;if(r&&!w(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=db(a)}c=a}return c}catch(g){d(Ka.interr(f,g))}}r=!!r;for(var p,m,q=0,I= +[],B=[],N=f.length,D=[],t=[];q<N;)if(-1!=(p=f.indexOf(b,q))&&-1!=(m=f.indexOf(a,p+l)))q!==p&&D.push(g(f.substring(q,p))),q=f.substring(p+l,m),I.push(q),B.push(c(q,u)),q=m+k,t.push(D.length),D.push("");else{q!==N&&D.push(g(f.substring(q)));break}n&&1<D.length&&Ka.throwNoconcat(f);if(!h||I.length){var S=function(a){for(var b=0,c=I.length;b<c;b++){if(r&&A(a[b]))return;D[t[b]]=a[b]}return D.join("")};return P(function(a){var b=0,c=I.length,e=Array(c);try{for(;b<c;b++)e[b]=B[b](a);return S(e)}catch(g){d(Ka.interr(f, +g))}},{exp:f,expressions:I,$$watchDelegate:function(a,b){var c;return a.$watchGroup(B,function(d,e){var f=S(d);z(b)&&b.call(this,f,d!==e?c:f,a);c=f})}})}}var l=b.length,k=a.length,n=new RegExp(b.replace(/./g,f),"g"),r=new RegExp(a.replace(/./g,f),"g");h.startSymbol=function(){return b};h.endSymbol=function(){return a};return h}]}function af(){this.$get=["$rootScope","$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var n=4<arguments.length,r=n?za.call(arguments,4):[],s=a.setInterval,x=a.clearInterval, +C=0,F=w(k)&&!k,u=(F?d:c).defer(),p=u.promise;l=w(l)?l:0;p.then(null,null,n?function(){e.apply(null,r)}:e);p.$$intervalId=s(function(){u.notify(C++);0<l&&C>=l&&(u.resolve(C),x(p.$$intervalId),delete f[p.$$intervalId]);F||b.$apply()},h);f[p.$$intervalId]=u;return p}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function ge(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".", +GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), +SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=ob(b[a]);return b.join("/")}function hd(b,a){var c=Ba(b);a.$$protocol=c.protocol; +a.$$host=c.hostname;a.$$port=W(c.port)||Tf[c.protocol]||null}function id(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=zc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ya(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ja(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Bb(b){return b.replace(/(#.+)|#$/, +"$1")}function cc(b){return b.substr(0,Ja(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);hd(b,this);this.$$parse=function(a){var b=ya(c,a);if(!L(b))throw Cb("ipthprfx",a,c);id(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)), +!0;var f,g;(f=ya(b,d))!==t?(g=f,g=(f=ya(a,f))!==t?c+(ya("/",f)||f):b+g):(f=ya(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);hd(b,this);this.$$parse=function(d){var e=ya(b,d)||ya(c,d),f;A(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",A(e)&&(b=d,this.replace())):(f=ya(a,e),A(f)&&(f=e));id(f,this);d=this.$$path;var e=b,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(d=(f=g.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose= +function(){var c=Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ja(b)==Ja(a)?(this.$$parse(a),!0):!1}}function jd(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ja(d)?f=d:(g=ya(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c= +Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Db(b){return function(){return this[b]}}function kd(b,a){return function(c){if(A(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ff(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return w(a)?(b=a,this):b};this.html5Mode=function(b){return ab(b)?(a.enabled=b,this):H(b)?(ab(b.enabled)&&(a.enabled=b.enabled), +ab(b.requireBase)&&(a.requireBase=b.requireBase),ab(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var r=d.url(),s;if(a.enabled){if(!n&&a.requireBase)throw Cb("nobase");s=r.substring(0, +r.indexOf("/",r.indexOf("//")+2))+(n||"/");n=e.history?dc:jd}else s=Ja(r),n=ec;k=new n(s,"#"+b);k.$$parseLinkUrl(r,r);k.$$state=d.state();var x=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=y(b.target);"a"!==ta(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);x.test(h)|| +!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Bb(k.absUrl())!=Bb(r)&&d.url(k.absUrl(),!0);var C=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(C=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a= +Bb(d.url()),b=Bb(k.absUrl()),f=d.state(),g=k.$$replace,n=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(C||n)C=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(n&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function gf(){var b=!0,a=this;this.debugEnabled=function(a){return w(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&& +(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||v;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];m(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]} +function Ca(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw da("isecfld",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b.window===b)throw da("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw da("isecdom",a);if(b===Object)throw da("isecobj",a);}return b}function ld(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b===Uf||b===Vf||b===Wf)throw da("isecff",a); +}}function Xf(b,a){return"undefined"!==typeof b?b:a}function md(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function T(b,a){var c,d;switch(b.type){case q.Program:c=!0;m(b.body,function(b){T(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case q.Literal:b.constant=!0;b.toWatch=[];break;case q.UnaryExpression:T(b.argument,a);b.constant=b.argument.constant;b.toWatch=b.argument.toWatch;break;case q.BinaryExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&& +b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch);break;case q.LogicalExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case q.ConditionalExpression:T(b.test,a);T(b.alternate,a);T(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case q.Identifier:b.constant=!1;b.toWatch=[b];break;case q.MemberExpression:T(b.object,a);b.computed&&T(b.property,a); +b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch=[b];break;case q.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];m(b.arguments,function(b){T(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case q.AssignmentExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=[b];break;case q.ArrayExpression:c=!0;d=[];m(b.elements,function(b){T(b,a);c= +c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=d;break;case q.ObjectExpression:c=!0;d=[];m(b.properties,function(b){T(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case q.ThisExpression:b.constant=!1,b.toWatch=[]}}function nd(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:t}}function od(b){return b.type===q.Identifier||b.type===q.MemberExpression}function pd(b){if(1=== +b.body.length&&od(b.body[0].expression))return{type:q.AssignmentExpression,left:b.body[0].expression,right:{type:q.NGValueParameter},operator:"="}}function qd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===q.Literal||b.body[0].expression.type===q.ArrayExpression||b.body[0].expression.type===q.ObjectExpression)}function rd(b,a){this.astBuilder=b;this.$filter=a}function sd(b,a){this.astBuilder=b;this.$filter=a}function Eb(b,a,c,d){oa(b,d);a=a.split(".");for(var e,f=0;1< +a.length;f++){e=Ca(a.shift(),d);var g=oa(b[e],d);g||(g={},b[e]=g);b=g}e=Ca(a.shift(),d);oa(b[e],d);return b[e]=c}function Fb(b){return"constructor"==b}function fc(b){return z(b.valueOf)?b.valueOf():Yf.call(b)}function hf(){var b=ga(),a=ga();this.$get=["$filter","$sniffer",function(c,d){function e(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=fc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function f(a,b,c,d,f){var g=d.inputs,h;if(1===g.length){var k=e,g=g[0];return a.$watch(function(a){var b= +g(a);e(b,k)||(h=d(a,t,t,[b]),k=b&&fc(b));return h},b,c,f)}for(var l=[],n=[],r=0,m=g.length;r<m;r++)l[r]=e,n[r]=null;return a.$watch(function(a){for(var b=!1,c=0,f=g.length;c<f;c++){var k=g[c](a);if(b||(b=!e(k,l[c])))n[c]=k,l[c]=k&&fc(k)}b&&(h=d(a,t,t,n));return h},b,c,f)}function g(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);w(a)&&d.$$postDigest(function(){w(f)&&e()})},c)}function h(a,b,c,d){function e(a){var b=!0;m(a,function(a){w(a)|| +(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function l(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){z(b)&&b.apply(this,arguments);e()},c)}function k(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==h&&c!==g?function(c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}:function(c,d,e,f){e=a(c,d,e,f);c=b(e,c,d);return w(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!== +f?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=f,c.inputs=a.inputs?a.inputs:[a]);return c}var n={csp:d.csp,expensiveChecks:!1},r={csp:d.csp,expensiveChecks:!0};return function(d,e,C){var m,u,p;switch(typeof d){case "string":p=d=d.trim();var q=C?a:b;m=q[p];m||(":"===d.charAt(0)&&":"===d.charAt(1)&&(u=!0,d=d.substring(2)),C=C?r:n,m=new gc(C),m=(new hc(m,c,C)).parse(d),m.constant?m.$$watchDelegate=l:u?m.$$watchDelegate=m.literal?h:g:m.inputs&&(m.$$watchDelegate=f),q[p]=m);return k(m, +e);case "function":return k(d,e);default:return v}}}]}function kf(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return td(function(a){b.$evalAsync(a)},a)}]}function lf(){this.$get=["$browser","$exceptionHandler",function(b,a){return td(function(a){b.defer(a)},a)}]}function td(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&& +c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=t;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status];try{z(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),a(h)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=J("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending|| +[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(H(b)||z(b))d=b&&b.then;z(d)?(this.promise.$$state.status= +-1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(z(b)? +b(c):c)}catch(h){a(h)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return l(e,!1)}return d&&z(d.then)?d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},n=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},r=function x(a){if(!z(a))throw h("norslvr",a);if(!(this instanceof x))return new x(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise}; +r.defer=function(){return new g};r.reject=function(a){var b=new g;b.reject(a);return b.promise};r.when=n;r.resolve=n;r.all=function(a){var b=new g,c=0,d=G(a)?[]:{};m(a,function(a,e){c++;n(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return r}function uf(){this.$get=["$window","$timeout",function(b,a){function c(){for(var a=0;a<n.length;a++){var b=n[a];b&&(n[a]=null,b())}k=n.length=0}function d(a){var b= +n.length;k++;n.push(a);0===b&&(l=h(c));return function(){0<=b&&(b=n[b]=null,0===--k&&l&&(l(),l=null,n.length=0))}}var e=b.requestAnimationFrame||b.webkitRequestAnimationFrame,f=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,g=!!e,h=g?function(a){var b=e(a);return function(){f(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};d.supported=g;var l,k=0,n=[];return d}]}function jf(){function b(a){function b(){this.$$watchers=this.$$nextSibling= +this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++nb;this.$$ChildScope=null}b.prototype=a;return b}var a=10,c=J("$rootScope"),d=null,e=null;this.digestTtl=function(b){arguments.length&&(a=b);return a};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(f,g,h,l){function k(a){a.currentScope.$$destroyed=!0}function n(){this.$id=++nb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead= +this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function r(a){if(p.$$phase)throw c("inprog",p.$$phase);p.$$phase=a}function s(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function x(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function q(){}function F(){for(;I.length;)try{I.shift()()}catch(a){g(a)}e=null}function u(){null===e&&(e= +l.defer(function(){p.$apply(F)}))}n.prototype={constructor:n,$new:function(a,c){var d;c=c||this;a?(d=new n,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=b(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(a||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,c,e){var f=h(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,c,f,a);var g=this,k=g.$$watchers,l= +{fn:b,last:q,get:f,exp:e||a,eq:!!c};d=null;z(b)||(l.fn=v);k||(k=g.$$watchers=[]);k.unshift(l);s(this,1);return function(){0<=bb(k,l)&&s(g,-1);d=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&b(e,e,g)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});m(a,function(a,b){var k=g.$watch(a,function(a, +f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!A(e)){if(H(e))if(Ea(e))for(f!==r&&(f=r,m=f.length=0,l++),a=e.length,m!==a&&(l++,f.length=m=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==s&&(f=s={},m=0,l++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(m++,f[b]=g,l++));if(m>a)for(b in l++,f)e.hasOwnProperty(b)|| +(m--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,g,k=1<b.length,l=0,n=h(a,c),r=[],s={},p=!0,m=0;return this.$watch(n,function(){p?(p=!1,b(e,e,d)):b(e,g,d);if(k)if(H(e))if(Ea(e)){g=Array(e.length);for(var a=0;a<e.length;a++)g[a]=e[a]}else for(a in g={},e)Xa.call(e,a)&&(g[a]=e[a]);else g=e})},$digest:function(){var b,f,h,k,n,s,m=a,x,u=[],E,I;r("$digest");l.$$checkUrlChange();this===p&&null!==e&&(l.defer.cancel(e),F());d=null;do{s=!1;for(x=this;t.length;){try{I=t.shift(), +I.scope.$eval(I.expression,I.locals)}catch(v){g(v)}d=null}a:do{if(k=x.$$watchers)for(n=k.length;n--;)try{if(b=k[n])if((f=b.get(x))!==(h=b.last)&&!(b.eq?ka(f,h):"number"===typeof f&&"number"===typeof h&&isNaN(f)&&isNaN(h)))s=!0,d=b,b.last=b.eq?fa(f,null):f,b.fn(f,h===q?f:h,x),5>m&&(E=4-m,u[E]||(u[E]=[]),u[E].push({msg:z(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){s=!1;break a}}catch(A){g(A)}if(!(k=x.$$watchersCount&&x.$$childHead||x!==this&&x.$$nextSibling))for(;x!== +this&&!(k=x.$$nextSibling);)x=x.$parent}while(x=k);if((s||t.length)&&!m--)throw p.$$phase=null,c("infdig",a,u);}while(s||t.length);for(p.$$phase=null;w.length;)try{w.shift()()}catch(y){g(y)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===p&&l.$$applicationDestroyed();s(this,-this.$$watchersCount);for(var b in this.$$listenerCount)x(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail== +this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=v;this.$on=this.$watch=this.$watchGroup=function(){return v};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return h(a)(this,b)}, +$evalAsync:function(a,b){p.$$phase||t.length||l.defer(function(){t.length&&p.$digest()});t.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){w.push(a)},$apply:function(a){try{return r("$apply"),this.$eval(a)}catch(b){g(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&I.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]|| +(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,x(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=cb([h],arguments,1),l,n;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(n=d.length;l<n;l++)if(d[l])try{d[l].apply(null,k)}catch(r){g(r)}else d.splice(l,1),l--,n--;if(f)return h.currentScope= +null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var f=cb([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,f)}catch(l){g(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d= +c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var p=new n,t=p.$$asyncQueue=[],w=p.$$postDigestQueue=[],I=p.$$applyAsyncQueue=[];return p}]}function he(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(a){return w(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Ba(c).href;return""===f||f.match(e)?c:"unsafe:"+ +f}}}function Zf(b){if("self"===b)return b;if(L(b)){if(-1<b.indexOf("***"))throw Da("iwcard",b);b=ud(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(Za(b))return new RegExp("^"+b.source+"$");throw Da("imatcher");}function vd(b){var a=[];w(b)&&m(b,function(b){a.push(Zf(b))});return a}function nf(){this.SCE_CONTEXTS=pa;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=vd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&& +(a=vd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?gd(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw Da("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[pa.HTML]=e(g);h[pa.CSS]=e(g);h[pa.URL]= +e(g);h[pa.JS]=e(g);h[pa.RESOURCE_URL]=e(h[pa.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Da("icontext",a,b);if(null===b||b===t||""===b)return b;if("string"!==typeof b)throw Da("itype",a);return new c(b)},getTrusted:function(c,e){if(null===e||e===t||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(c===pa.RESOURCE_URL){var g=Ba(e.toString()),r,s,m=!1;r=0;for(s=b.length;r<s;r++)if(d(b[r],g)){m=!0;break}if(m)for(r= +0,s=a.length;r<s;r++)if(d(a[r],g)){m=!1;break}if(m)return e;throw Da("insecurl",e.toString());}if(c===pa.HTML)return f(e);throw Da("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function mf(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&8>Ua)throw Da("iequirks");var d=ia(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs= +d.getTrusted=function(a,b){return b},d.valueOf=Ya);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;m(pa,function(a,b){var c=M(b);d[hb("parse_as_"+c)]=function(b){return e(a,b)};d[hb("get_trusted_"+c)]=function(b){return f(a,b)};d[hb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function of(){this.$get=["$window","$document",function(b,a){var c={},d=W((/android (\d+)/.exec(M((b.navigator|| +{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var r in l)if(k=h.exec(r)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);n=!!("animation"in l||g+"Animation"in l);!d||k&&n||(k=L(l.webkitTransition),n=L(l.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"=== +a&&11>=Ua)return!1;if(A(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:fb(),vendorPrefix:g,transitions:k,animations:n,android:d}}]}function qf(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,g){e.totalPendingRequests++;L(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var h=a.defaults&&a.defaults.transformResponse;G(h)?h=h.filter(function(a){return a!==$b}):h===$b&&(h=null);return a.get(f,{cache:b,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(a){b.put(f, +a.data);return a.data},function(a){if(!g)throw ea("tpload",f,a.status,a.statusText);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function rf(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];m(a,function(a){var d=ca.element(a).data("$binding");d&&m(d,function(d){c?(new RegExp("(^|\\s)"+ud(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a, +b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function sf(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){z(f)||(k=l,l=f,f=v);var n=za.call(arguments,3),r=w(k)&&!k,s=(r?d:c).defer(), +m=s.promise,q;q=a.defer(function(){try{s.resolve(f.apply(null,n))}catch(a){s.reject(a),e(a)}finally{delete g[m.$$timeoutId]}r||b.$apply()},l);m.$$timeoutId=q;g[q]=s;return m}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Ba(b){Ua&&(X.setAttribute("href",b),b=X.href);X.setAttribute("href",b);return{href:X.href,protocol:X.protocol?X.protocol.replace(/:$/,""):"",host:X.host, +search:X.search?X.search.replace(/^\?/,""):"",hash:X.hash?X.hash.replace(/^#/,""):"",hostname:X.hostname,port:X.port,pathname:"/"===X.pathname.charAt(0)?X.pathname:"/"+X.pathname}}function gd(b){b=L(b)?Ba(b):b;return b.protocol===wd.protocol&&b.host===wd.host}function tf(){this.$get=ra(O)}function xd(b){function a(a){try{return decodeURIComponent(a)}catch(b){return a}}var c=b[0]||{},d={},e="";return function(){var b,g,h,l,k;b=c.cookie||"";if(b!==e)for(e=b,b=e.split("; "),d={},h=0;h<b.length;h++)g= +b[h],l=g.indexOf("="),0<l&&(k=a(g.substring(0,l)),d[k]===t&&(d[k]=a(g.substring(l+1))));return d}}function xf(){this.$get=xd}function Lc(b){function a(c,d){if(H(c)){var e={};m(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",yd);a("date",zd);a("filter",$f);a("json",ag);a("limitTo",bg);a("lowercase",cg);a("number",Ad);a("orderBy",Bd);a("uppercase",dg)}function $f(){return function(b, +a,c){if(!Ea(b)){if(null==b)return b;throw J("filter")("notarray",b);}var d;switch(ic(a)){case "function":break;case "boolean":case "null":case "number":case "string":d=!0;case "object":a=eg(a,c,d);break;default:return b}return Array.prototype.filter.call(b,a)}}function eg(b,a,c){var d=H(b)&&"$"in b;!0===a?a=ka:z(a)||(a=function(a,b){if(A(a))return!1;if(null===a||null===b)return a===b;if(H(b)||H(a)&&!rc(a))return!1;a=M(""+a);b=M(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!H(e)?La(e, +b.$,a,!1):La(e,b,a,c)}}function La(b,a,c,d,e){var f=ic(b),g=ic(a);if("string"===g&&"!"===a.charAt(0))return!La(b,a.substring(1),c,d);if(G(b))return b.some(function(b){return La(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==h.charAt(0)&&La(b[h],a,c,!0))return!0;return e?!1:La(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!z(e)&&!A(e)&&(f="$"===h,!La(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function ic(b){return null=== +b?"null":typeof b}function yd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){A(d)&&(d=a.CURRENCY_SYM);A(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:Cd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function Ad(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==b?b:Cd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Cd(b,a,c,d,e){if(H(b))return"";var f=0>b;b=Math.abs(b);var g=Infinity===b;if(!g&&!isFinite(b))return"";var h=b+"",l="",k=!1,n=[];g&&(l="\u221e"); +if(!g&&-1!==h.indexOf("e")){var r=h.match(/([\d\.]+)e(-?)(\d+)/);r&&"-"==r[2]&&r[3]>e+1?b=0:(l=h,k=!0)}if(g||k)0<e&&1>b&&(l=b.toFixed(e),b=parseFloat(l));else{g=(h.split(Dd)[1]||"").length;A(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(Dd),h=g[0],g=g[1]||"",r=0,s=a.lgSize,m=a.gSize;if(h.length>=s+m)for(r=h.length-s,k=0;k<r;k++)0===(r-k)%m&&0!==k&&(l+=c),l+=h.charAt(k);for(k=r;k<h.length;k++)0===(h.length-k)%s&&0!==k&& +(l+=c),l+=h.charAt(k);for(;g.length<e;)g+="0";e&&"0"!==e&&(l+=d+g.substr(0,e))}0===b&&(f=!1);n.push(f?a.negPre:a.posPre,l,f?a.negSuf:a.posSuf);return n.join("")}function Gb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function Y(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c,d){var e=c["get"+b](),f=rb(a?"SHORT"+b:b);return d[f][e]}}function Ed(b){var a= +(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Fd(b){return function(a){var c=Ed(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function jc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function zd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=W(b[9]+b[10]),g=W(b[9]+b[11]));h.call(a,W(b[1]), +W(b[2])-1,W(b[3]));f=W(b[4]||0)-f;g=W(b[5]||0)-g;h=W(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;L(c)&&(c=fg.test(c)?W(c):a(c));V(c)&&(c=new Date(c));if(!aa(c)||!isFinite(c.getTime()))return c;for(;e;)(k=gg.exec(e))?(h=cb(h,k,1),e=h.pop()):(h.push(e),e=null);var n=c.getTimezoneOffset(); +f&&(n=xc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));m(h,function(a){l=hg[a];g+=l?l(c,b.DATETIME_FORMATS,n):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function ag(){return function(b,a){A(a)&&(a=2);return db(b,a)}}function bg(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):W(a);if(isNaN(a))return b;V(b)&&(b=b.toString());if(!G(b)&&!L(b))return b;c=!c||isNaN(c)?0:W(c);c=0>c&&c>=-b.length?b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0, +c+a),c)}}function Bd(b){function a(a,c){c=c?-1:1;return a.map(function(a){var d=1,h=Ya;if(z(a))h=a;else if(L(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))d="-"==a.charAt(0)?-1:1,a=a.substring(1);if(""!==a&&(h=b(a),h.constant))var l=h(),h=function(a){return a[l]}}return{get:h,descending:d*c}})}function c(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}return function(b,e,f){if(!Ea(b))return b;G(e)||(e=[e]);0===e.length&&(e=["+"]);var g=a(e,f);b=Array.prototype.map.call(b, +function(a,b){return{value:a,predicateValues:g.map(function(d){var e=d.get(a);d=typeof e;if(null===e)d="string",e="null";else if("string"===d)e=e.toLowerCase();else if("object"===d)a:{if("function"===typeof e.valueOf&&(e=e.valueOf(),c(e)))break a;if(rc(e)&&(e=e.toString(),c(e)))break a;e=b}return{value:e,type:d}})}});b.sort(function(a,b){for(var c=0,d=0,e=g.length;d<e;++d){var c=a.predicateValues[d],f=b.predicateValues[d],m=0;c.type===f.type?c.value!==f.value&&(m=c.value<f.value?-1:1):m=c.type<f.type? +-1:1;if(c=m*g[d].descending)break}return c});return b=b.map(function(a){return a.value})}}function Ma(b){z(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ra(b)}function Gd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Ib;f.$error={};f.$$success={};f.$pending=t;f.$name=e(a.name||a.ngForm||"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){m(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue= +function(){m(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ra(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];m(f.$pending,function(b,c){f.$setValidity(c,null,a)});m(f.$error,function(b,c){f.$setValidity(c,null,a)});m(f.$$success,function(b,c){f.$setValidity(c,null,a)});bb(g,a)};Hd({ctrl:this,$element:b,set:function(a,b, +c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(bb(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Va);d.addClass(b,Jb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Va,Jb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;m(g,function(a){a.$setPristine()})};f.$setUntouched=function(){m(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b, +"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function kc(b){b.$formatters.push(function(a){return b.$isEmpty(a)?a:a.toString()})}function kb(b,a,c,d,e,f){var g=M(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e=a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=R(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}}; +if(e.hasEvent("input"))a.on("input",l);else{var k,n=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Kb(b,a){return function(c,d){var e,f;if(aa(c))return c;if(L(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1)); +if(ig.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},m(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function lb(b,a,c,d){return function(e,f,g,h,l,k,n){function r(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function s(a){return w(a)? +aa(a)?a:c(a):t}Id(e,f,g,h);kb(e,f,g,h,l,k);var m=h&&h.$options&&h.$options.timezone,q;h.$$parserName=b;h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,q),m&&(b=Pb(b,m)),b):t});h.$formatters.push(function(a){if(a&&!aa(a))throw Lb("datefmt",a);if(r(a))return(q=a)&&m&&(q=Pb(q,m,!0)),n("date")(a,d,m);q=null;return""});if(w(g.min)||g.ngMin){var F;h.$validators.min=function(a){return!r(a)||A(F)||c(a)>=F};g.$observe("min",function(a){F=s(a);h.$validate()})}if(w(g.max)||g.ngMax){var u; +h.$validators.max=function(a){return!r(a)||A(u)||c(a)<=u};g.$observe("max",function(a){u=s(a);h.$validate()})}}}function Id(b,a,c,d){(d.$$hasNativeValidators=H(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?t:b})}function Jd(b,a,c,d,e){if(w(d)){b=b(d);if(!b.constant)throw J("ngModel")("constexpr",c,d);return b(a)}return e}function lc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e= +a[d],n=0;n<b.length;n++)if(e==b[n])continue a;c.push(e)}return c}function e(a){var b=[];return G(a)?(m(a,function(a){b=b.concat(e(a))}),b):L(a)?a.split(" "):H(a)?(m(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",link:function(f,g,h){function l(a,b){var c=g.data("$classCounts")||ga(),d=[];m(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!n){var m= +l(k,1);h.$addClass(m)}else if(!ka(b,n)){var q=e(n),m=d(k,q),k=d(q,k),m=l(m,1),k=l(k,-1);m&&m.length&&c.addClass(g,m);k&&k.length&&c.removeClass(g,k)}}n=ia(b)}var n;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function Hd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)} +function c(b,c){b=b?"-"+Bc(b,"-"):"";a(mb+b,!0===c);a(Kd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[Kd]=!(f[mb]=e.hasClass(mb));d.$setValidity=function(b,e,f){e===t?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&&h(d.$pending,b,f),Ld(d.$pending)&&(d.$pending=t));ab(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(Md,!0),d.$valid=d.$invalid=t,c("",null)):(a(Md, +!1),d.$valid=Ld(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?t:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function Ld(b){if(b)for(var a in b)if(b.hasOwnProperty(a))return!1;return!0}var jg=/^\/(.+)\/([a-z]*)$/,M=function(b){return L(b)?b.toLowerCase():b},Xa=Object.prototype.hasOwnProperty,rb=function(b){return L(b)?b.toUpperCase():b},Ua,y,la,za=[].slice,Mf=[].splice,kg=[].push,sa=Object.prototype.toString,sc=Object.getPrototypeOf,Fa=J("ng"),ca= +O.angular||(O.angular={}),gb,nb=0;Ua=U.documentMode;v.$inject=[];Ya.$inject=[];var G=Array.isArray,uc=/^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/,R=function(b){return L(b)?b.trim():b},ud=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},fb=function(){if(w(fb.isActive_))return fb.isActive_;var b=!(!U.querySelector("[ng-csp]")&&!U.querySelector("[data-ng-csp]"));if(!b)try{new Function("")}catch(a){b=!0}return fb.isActive_= +b},pb=function(){if(w(pb.name_))return pb.name_;var b,a,c=Oa.length,d,e;for(a=0;a<c;++a)if(d=Oa[a],b=U.querySelector("["+d.replace(":","\\:")+"jq]")){e=b.getAttribute(d+"jq");break}return pb.name_=e},Oa=["ng-","data-ng-","ng:","x-ng-"],be=/[A-Z]/g,Cc=!1,Rb,qa=1,Na=3,fe={full:"1.4.3",major:1,minor:4,dot:3,codeName:"foam-acceleration"};Q.expando="ng339";var ib=Q.cache={},Df=1;Q._data=function(b){return this.cache[b[this.expando]]||{}};var yf=/([\:\-\_]+(.))/g,zf=/^moz([A-Z])/,lg={mouseleave:"mouseout", +mouseenter:"mouseover"},Ub=J("jqLite"),Cf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,Af=/<([\w:]+)/,Bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,na={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};na.optgroup=na.option;na.tbody=na.tfoot=na.colgroup=na.caption=na.thead; +na.th=na.td;var Pa=Q.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===U.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),Q(O).on("load",a))},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?y(this[b]):y(this[this.length+b])},length:0,push:kg,sort:[].sort,splice:[].splice},Ab={};m("multiple selected checked disabled readOnly required open".split(" "),function(b){Ab[M(b)]=b});var Tc={};m("input select option textarea button form details".split(" "), +function(b){Tc[b]=!0});var Uc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};m({data:Wb,removeData:ub,hasData:function(b){for(var a in ib[b.ng339])return!0;return!1}},function(b,a){Q[a]=b});m({data:Wb,inheritedData:zb,scope:function(b){return y.data(b,"$scope")||zb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return y.data(b,"$isolateScope")||y.data(b,"$isolateScopeNoTemplate")},controller:Qc,injector:function(b){return zb(b, +"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:wb,css:function(b,a,c){a=hb(a);if(w(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==Na&&2!==d&&8!==d)if(d=M(a),Ab[d])if(w(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||v).specified?d:t;else if(w(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(w(c))b[a]=c;else return b[a]}, +text:function(){function b(a,b){if(A(b)){var d=a.nodeType;return d===qa||d===Na?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(A(a)){if(b.multiple&&"select"===ta(b)){var c=[];m(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(A(a))return b.innerHTML;tb(b,!0);b.innerHTML=a},empty:Rc},function(b,a){Q.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Rc&&(2==b.length&&b!==wb&&b!==Qc? +a:d)===t){if(H(a)){for(e=0;e<g;e++)if(b===Wb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===t?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}});m({removeData:ub,on:function a(c,d,e,f){if(w(f))throw Ub("onargs");if(Mc(c)){var g=vb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=Gf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"=== +d?a(c,lg[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Pc,one:function(a,c,d){a=y(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c,d)},replaceWith:function(a,c){var d,e=a.parentNode;tb(a);m(new Q(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];m(a.childNodes,function(a){a.nodeType===qa&&c.push(a)});return c},contents:function(a){return a.contentDocument|| +a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===qa||11===d){c=new Q(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===qa){var d=a.firstChild;m(new Q(c),function(c){a.insertBefore(c,d)})}},wrap:function(a,c){c=y(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Xb,detach:function(a){Xb(a,!0)},after:function(a,c){var d=a,e=a.parentNode;c=new Q(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h, +d.nextSibling);d=h}},addClass:yb,removeClass:xb,toggleClass:function(a,c,d){c&&m(c.split(" "),function(c){var f=d;A(f)&&(f=!wb(a,c));(f?yb:xb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Vb,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=vb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0=== +this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:v,type:g,target:a},c.type&&(e=P(e,c)),c=ia(h),f=d?[e].concat(d):[e],m(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){Q.prototype[c]=function(c,e,f){for(var g,h=0,l=this.length;h<l;h++)A(g)?(g=a(this[h],c,e,f),w(g)&&(g=y(g))):Oc(g,a(this[h],c,e,f));return w(g)?g:this};Q.prototype.bind= +Q.prototype.on;Q.prototype.unbind=Q.prototype.off});Sa.prototype={put:function(a,c){this[Ga(a,this.nextUid)]=c},get:function(a){return this[Ga(a,this.nextUid)]},remove:function(a){var c=this[a=Ga(a,this.nextUid)];delete this[a];return c}};var wf=[function(){this.$get=[function(){return Sa}]}],Wc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,mg=/,/,ng=/^\s*(_?)(\S+?)\1\s*$/,Vc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ha=J("$injector");eb.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e= +[];if(a.length){if(c)throw L(d)&&d||(d=a.name||Hf(a)),Ha("strictdi",d);c=a.toString().replace(Vc,"");c=c.match(Wc);m(c[1].split(mg),function(a){a.replace(ng,function(a,c,d){e.push(d)})})}a.$inject=e}}else G(a)?(c=a.length-1,Qa(a[c],"fn"),e=a.slice(0,c)):Qa(a,"fn",!0);return e};var Nd=J("$animate"),Ue=function(){this.$get=["$q","$$rAF",function(a,c){function d(){}d.all=v;d.chain=v;d.prototype={end:v,cancel:v,resume:v,pause:v,complete:v,then:function(d,f){return a(function(a){c(function(){a()})}).then(d, +f)}};return d}]},Te=function(){var a=new Sa,c=[];this.$get=["$$AnimateRunner","$rootScope",function(d,e){function f(d,f,l){var k=a.get(d);k||(a.put(d,k={}),c.push(d));f&&m(f.split(" "),function(a){a&&(k[a]=!0)});l&&m(l.split(" "),function(a){a&&(k[a]=!1)});1<c.length||e.$$postDigest(function(){m(c,function(c){var d=a.get(c);if(d){var e=If(c.attr("class")),f="",g="";m(d,function(a,c){a!==!!e[c]&&(a?f+=(f.length?" ":"")+c:g+=(g.length?" ":"")+c)});m(c,function(a){f&&yb(a,f);g&&xb(a,g)});a.remove(c)}}); +c.length=0})}return{enabled:v,on:v,off:v,pin:v,push:function(a,c,e,k){k&&k();e=e||{};e.from&&a.css(e.from);e.to&&a.css(e.to);(e.addClass||e.removeClass)&&f(a,e.addClass,e.removeClass);return new d}}}]},Se=["$provide",function(a){var c=this;this.$$registeredAnimations=Object.create(null);this.register=function(d,e){if(d&&"."!==d.charAt(0))throw Nd("notcsel",d);var f=d+"-animation";c.$$registeredAnimations[d.substr(1)]=f;a.factory(f,e)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter= +a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Nd("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function c(a,d,e){if(e){var l;a:{for(l=0;l<e.length;l++){var k=e[l];if(1===k.nodeType){l=k;break a}}l=void 0}!l||l.parentNode||l.previousElementSibling||(e=null)}e?e.after(a):d.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(f,g,h,l){g= +g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"enter",Ia(l))},move:function(f,g,h,l){g=g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"move",Ia(l))},leave:function(c,e){return a.push(c,"leave",Ia(e),function(){c.remove()})},addClass:function(c,e,h){h=Ia(h);h.addClass=jb(h.addclass,e);return a.push(c,"addClass",h)},removeClass:function(c,e,h){h=Ia(h);h.removeClass=jb(h.removeClass,e);return a.push(c,"removeClass",h)},setClass:function(c,e,h,l){l=Ia(l);l.addClass=jb(l.addClass, +e);l.removeClass=jb(l.removeClass,h);return a.push(c,"setClass",l)},animate:function(c,e,h,l,k){k=Ia(k);k.from=k.from?P(k.from,e):e;k.to=k.to?P(k.to,h):h;k.tempClasses=jb(k.tempClasses,l||"ng-inline-animate");return a.push(c,"animate",k)}}}]}],ea=J("$compile");Ec.$inject=["$provide","$$sanitizeUriProvider"];var Zc=/^((?:x|data)[\:\-_])/i,Nf=J("$controller"),Xc=/^(\S+)(\s+as\s+(\w+))?$/,cd="application/json",ac={"Content-Type":cd+";charset=utf-8"},Pf=/^\[|^\{(?!\{)/,Qf={"[":/]$/,"{":/}$/},Of=/^\)\]\}',?\n/, +Ka=ca.$interpolateMinErr=J("$interpolate");Ka.throwNoconcat=function(a){throw Ka("noconcat",a);};Ka.interr=function(a,c){return Ka("interr",a,c.toString())};var og=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,Tf={http:80,https:443,ftp:21},Cb=J("$location"),pg={$$html5:!1,$$replace:!1,absUrl:Db("$$absUrl"),url:function(a){if(A(a))return this.$$url;var c=og.exec(a);(c[1]||""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Db("$$protocol"), +host:Db("$$host"),port:Db("$$port"),path:kd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(L(a)||V(a))a=a.toString(),this.$$search=zc(a);else if(H(a))a=fa(a,{}),m(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Cb("isrcharg");break;default:A(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:kd("$$hash",function(a){return null!== +a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};m([jd,ec,dc],function(a){a.prototype=Object.create(pg);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==dc||!this.$$html5)throw Cb("nostate");this.$$state=A(c)?null:c;return this}});var da=J("$parse"),Uf=Function.prototype.call,Vf=Function.prototype.apply,Wf=Function.prototype.bind,Mb=ga();m("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Mb[a]=!0});var qg={n:"\n",f:"\f",r:"\r", +t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++; +else{var c=a+this.peek(),d=c+this.peek(2),e=Mb[c],f=Mb[d];Mb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a|| +"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=w(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw da("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=M(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var e=this.peek(); +if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&!this.isNumber(c))break;this.index++}this.tokens.push({index:a, +text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+=4,d+=String.fromCharCode(parseInt(f,16))):d+=qg[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===a){this.index++;this.tokens.push({index:c,text:e,constant:!0, +value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var q=function(a,c){this.lexer=a;this.options=c};q.Program="Program";q.ExpressionStatement="ExpressionStatement";q.AssignmentExpression="AssignmentExpression";q.ConditionalExpression="ConditionalExpression";q.LogicalExpression="LogicalExpression";q.BinaryExpression="BinaryExpression";q.UnaryExpression="UnaryExpression";q.CallExpression="CallExpression";q.MemberExpression="MemberExpression";q.Identifier="Identifier";q.Literal= +"Literal";q.ArrayExpression="ArrayExpression";q.Property="Property";q.ObjectExpression="ObjectExpression";q.ThisExpression="ThisExpression";q.NGValueParameter="NGValueParameter";q.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:q.Program, +body:a}},expressionStatement:function(){return{type:q.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:q.AssignmentExpression,left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),c,d;return this.expect("?")&&(c=this.expression(),this.consume(":"))? +(d=this.expression(),{type:q.ConditionalExpression,test:a,alternate:c,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:q.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:q.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a={type:q.BinaryExpression, +operator:c.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:q.BinaryExpression,operator:c.text, +left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:q.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=fa(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant(): +this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:q.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===c.text?(a={type:q.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===c.text?a={type:q.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:q.CallExpression,callee:this.identifier(), +arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:q.Identifier,name:a.text}},constant:function(){return{type:q.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break; +a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:q.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;c={type:q.Property,kind:"init"};this.peek().constant?c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:q.ObjectExpression,properties:a}}, +throwError:function(a,c){throw da("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw da("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw da("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a]; +var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:q.Literal,value:!0},"false":{type:q.Literal,value:!1},"null":{type:q.Literal,value:null},undefined:{type:q.Literal,value:t},"this":{type:q.ThisExpression}}};rd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[], +body:[],own:{}},inputs:[]};T(e,d.$filter);var f="",g;this.stage="assign";if(g=pd(e))this.state.computing="assign",f=this.nextId(),this.recurse(g,f),f="fn.assign="+this.generateFunction("assign","s,v,l");g=nd(e.body);d.stage="inputs";m(g,function(a,c){var e="fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+ +"var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","ifDefined","plus","text",f))(this.$filter,Ca,oa,ld,Xf,md,a);this.state=this.stage=t;f.literal=qd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;m(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")}, +generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],c=this;m(this.state.filters,function(d,e){a.push(d+"=$filter("+c.escape(e)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,g){var h,l,k=this,n,r;e=e||v;if(!g&&w(a.watchId))c=c||this.nextId(),this.if_("i", +this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case q.Program:m(a.body,function(c,d){k.recurse(c.expression,t,t,function(a){l=a});d!==a.body.length-1?k.current().body.push(l,";"):k.return_(l)});break;case q.Literal:r=this.escape(a.value);this.assign(c,r);e(r);break;case q.UnaryExpression:this.recurse(a.argument,t,t,function(a){l=a});r=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,r);e(r);break;case q.BinaryExpression:this.recurse(a.left, +t,t,function(a){h=a});this.recurse(a.right,t,t,function(a){l=a});r="+"===a.operator?this.plus(h,l):"-"===a.operator?this.ifDefined(h,0)+a.operator+this.ifDefined(l,0):"("+h+")"+a.operator+"("+l+")";this.assign(c,r);e(r);break;case q.LogicalExpression:c=c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case q.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c); +break;case q.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Ca(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l", +a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case q.MemberExpression:h=d&&(d.context=this.nextId())||this.nextId();c=c||this.nextId();k.recurse(a.object,h,t,function(){k.if_(k.notNull(h),function(){if(a.computed)l=k.nextId(),k.recurse(a.property,l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(h,l)),k.lazyAssign(k.computedMember(h,l),"{}")),r=k.ensureSafeObject(k.computedMember(h,l)),k.assign(c,r),d&&(d.computed=!0,d.name=l);else{Ca(a.property.name); +f&&1!==f&&k.if_(k.not(k.nonComputedMember(h,a.property.name)),k.lazyAssign(k.nonComputedMember(h,a.property.name),"{}"));r=k.nonComputedMember(h,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))r=k.ensureSafeObject(r);k.assign(c,r);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(c,"undefined")});e(c)},!!f);break;case q.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),n=[],m(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);n.push(c)}),r=l+ +"("+n.join(",")+")",k.assign(c,r),e(c)):(l=k.nextId(),h={},n=[],k.recurse(a.callee,l,h,function(){k.if_(k.notNull(l),function(){k.addEnsureSafeFunction(l);m(a.arguments,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(k.ensureSafeObject(a))})});h.name?(k.state.expensiveChecks||k.addEnsureSafeObject(h.context),r=k.member(h.context,h.name,h.computed)+"("+n.join(",")+")"):r=l+"("+n.join(",")+")";r=k.ensureSafeObject(r);k.assign(c,r)},function(){k.assign(c,"undefined")});e(c)}));break;case q.AssignmentExpression:l= +this.nextId();h={};if(!od(a.left))throw da("lval");this.recurse(a.left,t,h,function(){k.if_(k.notNull(h.context),function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(h.context,h.name,h.computed));r=k.member(h.context,h.name,h.computed)+a.operator+l;k.assign(c,r);e(c||r)})},1);break;case q.ArrayExpression:n=[];m(a.elements,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(a)})});r="["+n.join(",")+"]";this.assign(c,r);e(r);break;case q.ObjectExpression:n=[];m(a.properties,function(a){k.recurse(a.value, +k.nextId(),t,function(c){n.push(k.escape(a.key.type===q.Identifier?a.key.name:""+a.key.value)+":"+c)})});r="{"+n.join(",")+"}";this.assign(c,r);e(r);break;case q.ThisExpression:this.assign(c,"s");e("s");break;case q.NGValueParameter:this.assign(c,"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)|| +(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+a+","+c+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+ +"."+c},computedMember:function(a,c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+ +a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},lazyRecurse:function(a,c,d,e,f,g){var h=this;return function(){h.recurse(a,c,d,e,f,g)}},lazyAssign:function(a,c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(L(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true"; +if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw da("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}};sd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;T(e,d.$filter);var f,g;if(f=pd(e))g=this.recurse(f);f=nd(e.body);var h;f&&(h=[],m(f,function(a,c){var e=d.recurse(a); +a.input=e;h.push(e);a.watchId=c}));var l=[];m(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;m(l,function(e){d=e(a,c)});return d};g&&(f.assign=function(a,c,d){return g(a,d,c)});h&&(f.inputs=h);f.literal=qd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,g=this,h;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case q.Literal:return this.value(a.value,c);case q.UnaryExpression:return f= +this.recurse(a.argument),this["unary"+a.operator](f,c);case q.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.LogicalExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case q.Identifier:return Ca(a.name,g.expression),g.identifier(a.name,g.expensiveChecks||Fb(a.name), +c,d,g.expression);case q.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Ca(a.property.name,g.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed?this.computedMember(e,f,c,d,g.expression):this.nonComputedMember(e,f,g.expensiveChecks,c,d,g.expression);case q.CallExpression:return h=[],m(a.arguments,function(a){h.push(g.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,g){for(var m= +[],q=0;q<h.length;++q)m.push(h[q](a,d,e,g));a=f.apply(t,m,g);return c?{context:t,name:t,value:a}:a}:function(a,d,e,r){var m=f(a,d,e,r),q;if(null!=m.value){oa(m.context,g.expression);ld(m.value,g.expression);q=[];for(var t=0;t<h.length;++t)q.push(oa(h[t](a,d,e,r),g.expression));q=oa(m.value.apply(m.context,q),g.expression)}return c?{value:q}:q};case q.AssignmentExpression:return e=this.recurse(a.left,!0,1),f=this.recurse(a.right),function(a,d,h,r){var m=e(a,d,h,r);a=f(a,d,h,r);oa(m.value,g.expression); +m.context[m.name]=a;return c?{value:a}:a};case q.ArrayExpression:return h=[],m(a.elements,function(a){h.push(g.recurse(a))}),function(a,d,e,f){for(var g=[],m=0;m<h.length;++m)g.push(h[m](a,d,e,f));return c?{value:g}:g};case q.ObjectExpression:return h=[],m(a.properties,function(a){h.push({key:a.key.type===q.Identifier?a.key.name:""+a.key.value,value:g.recurse(a.value)})}),function(a,d,e,f){for(var g={},m=0;m<h.length;++m)g[h[m].key]=h[m].value(a,d,e,f);return c?{value:g}:g};case q.ThisExpression:return function(a){return c? +{value:a}:a};case q.NGValueParameter:return function(a,d,e,f){return c?{value:e}:e}}},"unary+":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?+d:0;return c?{value:d}:d}},"unary-":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?-d:0;return c?{value:d}:d}},"unary!":function(a,c){return function(d,e,f,g){d=!a(d,e,f,g);return c?{value:d}:d}},"binary+":function(a,c,d){return function(e,f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=md(l,e);return d?{value:l}:l}},"binary-":function(a,c,d){return function(e, +f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=(w(l)?l:0)-(w(e)?e:0);return d?{value:l}:l}},"binary*":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)*c(e,f,g,h);return d?{value:e}:e}},"binary/":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)/c(e,f,g,h);return d?{value:e}:e}},"binary%":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)%c(e,f,g,h);return d?{value:e}:e}},"binary===":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)===c(e,f,g,h);return d?{value:e}:e}},"binary!==":function(a, +c,d){return function(e,f,g,h){e=a(e,f,g,h)!==c(e,f,g,h);return d?{value:e}:e}},"binary==":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)==c(e,f,g,h);return d?{value:e}:e}},"binary!=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)!=c(e,f,g,h);return d?{value:e}:e}},"binary<":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)<c(e,f,g,h);return d?{value:e}:e}},"binary>":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>c(e,f,g,h);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e, +f,g,h){e=a(e,f,g,h)<=c(e,f,g,h);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>=c(e,f,g,h);return d?{value:e}:e}},"binary&&":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)&&c(e,f,g,h);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)||c(e,f,g,h);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,g,h,l){f=a(f,g,h,l)?c(f,g,h,l):d(f,g,h,l);return e?{value:f}:f}},value:function(a,c){return function(){return c? +{context:t,name:t,value:a}:a}},identifier:function(a,c,d,e,f){return function(g,h,l,k){g=h&&a in h?h:g;e&&1!==e&&g&&!g[a]&&(g[a]={});h=g?g[a]:t;c&&oa(h,f);return d?{context:g,name:a,value:h}:h}},computedMember:function(a,c,d,e,f){return function(g,h,l,k){var n=a(g,h,l,k),m,s;null!=n&&(m=c(g,h,l,k),Ca(m,f),e&&1!==e&&n&&!n[m]&&(n[m]={}),s=n[m],oa(s,f));return d?{context:n,name:m,value:s}:s}},nonComputedMember:function(a,c,d,e,f,g){return function(h,l,k,n){h=a(h,l,k,n);f&&1!==f&&h&&!h[c]&&(h[c]={}); +l=null!=h?h[c]:t;(d||Fb(c))&&oa(l,g);return e?{context:h,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,g){return g?g[c]:a(d,e,f)}}};var hc=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d;this.ast=new q(this.lexer);this.astCompiler=d.csp?new sd(this.ast,c):new rd(this.ast,c)};hc.prototype={constructor:hc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};ga();ga();var Yf=Object.prototype.valueOf,Da=J("$sce"),pa={HTML:"html",CSS:"css",URL:"url", +RESOURCE_URL:"resourceUrl",JS:"js"},ea=J("$compile"),X=U.createElement("a"),wd=Ba(O.location.href);xd.$inject=["$document"];Lc.$inject=["$provide"];yd.$inject=["$locale"];Ad.$inject=["$locale"];var Dd=".",hg={yyyy:Y("FullYear",4),yy:Y("FullYear",2,0,!0),y:Y("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:Y("Month",2,1),M:Y("Month",1,1),dd:Y("Date",2),d:Y("Date",1),HH:Y("Hours",2),H:Y("Hours",1),hh:Y("Hours",2,-12),h:Y("Hours",1,-12),mm:Y("Minutes",2),m:Y("Minutes",1),ss:Y("Seconds",2),s:Y("Seconds", +1),sss:Y("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a,c,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0<a?"floor":"ceil"](a/60),2)+Gb(Math.abs(a%60),2))},ww:Fd(2),w:Fd(1),G:jc,GG:jc,GGG:jc,GGGG:function(a,c){return 0>=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},gg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,fg=/^\-?\d+$/;zd.$inject=["$locale"];var cg=ra(M),dg=ra(rb);Bd.$inject= +["$parse"];var ie=ra({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===sa.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),sb={};m(Ab,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=wa("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});sb[e]=function(){return{restrict:"A", +priority:100,link:f}}}});m(Uc,function(a,c){sb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(jg))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});m(["src","srcset","href"],function(a){var c=wa("ng-"+a);sb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===sa.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href", +g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ua&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Ib={$addControl:v,$$renameControl:function(a,c){a.$name=c},$removeControl:v,$setValidity:v,$setDirty:v,$setPristine:v,$setSubmitted:v};Gd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Od=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Gd,compile:function(d,e){d.addClass(Va).addClass(mb);var f=e.name?"name":a&&e.ngForm?"ngForm": +!1;return{pre:function(a,d,e,k){if(!("action"in e)){var n=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",n,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",n,!1)},0,!1)})}var m=k.$$parentForm;f&&(Eb(a,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(Eb(a,k.$name,t,k.$name),m.$$renameControl(k,c),Eb(a,k.$name,k,k.$name))}));d.on("$destroy",function(){m.$removeControl(k);f&&Eb(a,e[f],t, +k.$name);P(k,Ib)})}}}}}]},je=Od(),we=Od(!0),ig=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,rg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,sg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,tg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Pd=/^(\d{4})-(\d{2})-(\d{2})$/,Qd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Rd=/^(\d{4})-(\d\d)$/, +Sd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Td={text:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e)},date:lb("date",Pd,Kb(Pd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":lb("datetimelocal",Qd,Kb(Qd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:lb("time",Sd,Kb(Sd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:lb("week",mc,function(a,c){if(aa(a))return a;if(L(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=Ed(e),f=7*(f-1);c&&(d=c.getHours(),g= +c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:lb("month",Rd,Kb(Rd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){Id(a,c,d,e);kb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:tg.test(a)?parseFloat(a):t});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Lb("numfmt",a);a=a.toString()}return a});if(w(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)|| +A(h)||a>=h};d.$observe("min",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(w(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||A(l)||a<=l};d.$observe("max",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||rg.test(d)}},email:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e); +e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||sg.test(d)}},radio:function(a,c,d,e){A(d.name)&&c.attr("name",++nb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=Jd(l,a,"ngTrueValue",d.ngTrueValue,!0),n=Jd(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&& +a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a,k)});e.$parsers.push(function(a){return a?k:n})},hidden:v,button:v,submit:v,reset:v,file:v},Fc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Td[M(h.type)]||Td.text)(f,g,h,l[0],c,a,d,e)}}}}],ug=/^(true|false|\d+)$/,Oe=function(){return{restrict:"A",priority:100,compile:function(a, +c){return ug.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},oe=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],qe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate)); +c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===t?"":a})}}}}],pe=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],Ne=ra({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}), +re=lc("",!0),te=lc("Odd",0),se=lc("Even",1),ue=Ma({compile:function(a,c){c.$set("ngCloak",t);a.removeClass("ng-cloak")}}),ve=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Kc={},vg={blur:!0,focus:!0};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=wa("ng-"+a);Kc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h= +d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};vg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ye=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=U.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k= +qb(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],ze=["$templateRequest","$anchorScroll","$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(e,f){var g=f.ngInclude||f.src,h=f.onload||"",l=f.autoscroll;return function(e,f,m,s,q){var t=0,F,u,p,v=function(){u&&(u.remove(),u=null);F&&(F.$destroy(),F=null);p&&(d.leave(p).then(function(){u=null}),u=p,p=null)};e.$watch(g,function(g){var m=function(){!w(l)||l&&!e.$eval(l)|| +c()},r=++t;g?(a(g,!0).then(function(a){if(r===t){var c=e.$new();s.template=a;a=q(c,function(a){v();d.enter(a,null,f).then(m)});F=c;p=a;F.$emit("$includeContentLoaded",g);e.$eval(h)}},function(){r===t&&(v(),e.$emit("$includeContentError",g))}),e.$emit("$includeContentRequested",g)):(v(),s.template=null)})}}}}],Qe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Nc(f.template,U).childNodes)(c,function(a){d.append(a)}, +{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],Ae=Ma({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Me=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?R(f):f;e.$parsers.push(function(a){if(!A(a)){var c=[];a&&m(a.split(h),function(a){a&&c.push(g?R(a):a)});return c}});e.$formatters.push(function(a){return G(a)?a.join(f):t});e.$isEmpty=function(a){return!a|| +!a.length}}}},mb="ng-valid",Kd="ng-invalid",Va="ng-pristine",Jb="ng-dirty",Md="ng-pending",Lb=new J("ngModel"),wg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty= +!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=t;this.$name=n(d.name||"",!1)(a);var r=f(d.ngModel),s=r.assign,q=r,C=s,F=null,u,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");q=function(a){var d=r(a);z(d)&&(d=c(a));return d};C=function(a,c){z(r(a))?g(a,{$$$p:p.$modelValue}):s(a,p.$modelValue)}}else if(!r.assign)throw Lb("nonassign",d.ngModel,ua(e));};this.$render=v;this.$isEmpty=function(a){return A(a)|| +""===a||null===a||a!==a};var K=e.inheritedData("$formController")||Ib,y=0;Hd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:K,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Jb);g.addClass(e,Va)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Va);g.addClass(e,Jb);K.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched= +function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(F);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:t,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators= +function(a,c,d){function e(){var d=!0;m(p.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(m(p.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;m(p.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!z(k.then))throw Lb("$asyncValidators",k);g(h,t);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},v):h(!0)}function g(a,c){l===y&&p.$setValidity(a,c)}function h(a){l===y&&d(a)}y++;var l=y;(function(){var a= +p.$$parserName||"parse";if(u===t)g(a,null);else return u||(m(p.$validators,function(a,c){g(c,null)}),m(p.$asyncValidators,function(a,c){g(c,null)})),g(a,u),u;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(F);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue;if(u=A(c)?t:!0)for(var d= +0;d<p.$parsers.length;d++)if(c=p.$parsers[d](c),A(c)){u=!1;break}V(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=q(a));var e=p.$modelValue,f=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=c;f&&(p.$modelValue=c,p.$modelValue!==e&&p.$$writeModelToScope());p.$$runValidators(c,p.$$lastCommittedViewValue,function(a){f||(p.$modelValue=a?c:t,p.$modelValue!==e&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){C(a,p.$modelValue);m(p.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})}; +this.$setViewValue=function(a,c){p.$viewValue=a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=p.$options;e&&w(e.debounce)&&(e=e.debounce,V(e)?d=e:V(e[c])?d=e[c]:V(e["default"])&&(d=e["default"]));h.cancel(F);d?F=h(function(){p.$commitViewValue()},d):l.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var c=q(a);if(c!==p.$modelValue&&(p.$modelValue===p.$modelValue||c===c)){p.$modelValue= +p.$$rawModelValue=c;u=t;for(var d=p.$formatters,e=d.length,f=c;e--;)f=d[e](f);p.$viewValue!==f&&(p.$viewValue=p.$$lastCommittedViewValue=f,p.$render(),p.$$runValidators(c,f,v))}return c})}],Le=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:wg,priority:1,compile:function(c){c.addClass(Va).addClass("ng-untouched").addClass(mb);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Ib;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name", +function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy",function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],xg=/(\s+|^)default(\s+|$)/,Pe=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=fa(a.$eval(c.ngModelOptions)); +this.$options.updateOn!==t?(this.$options.updateOnDefault=!1,this.$options.updateOn=R(this.$options.updateOn.replace(xg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},Be=Ma({terminal:!0,priority:1E3}),yg=J("ngOptions"),zg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/, +Je=["$compile","$parse",function(a,c){function d(a,d,e){function f(a,c,d,e,g){this.selectValue=a;this.viewValue=c;this.label=d;this.group=e;this.disabled=g}function n(a){var c;if(!q&&Ea(a))c=a;else{c=[];for(var d in a)a.hasOwnProperty(d)&&"$"!==d.charAt(0)&&c.push(d)}return c}var m=a.match(zg);if(!m)throw yg("iexp",a,ua(d));var s=m[5]||m[7],q=m[6];a=/ as /.test(m[0])&&m[1];var t=m[9];d=c(m[2]?m[1]:s);var v=a&&c(a)||d,u=t&&c(t),p=t?function(a,c){return u(e,c)}:function(a){return Ga(a)},w=function(a, +c){return p(a,z(a,c))},y=c(m[2]||m[1]),A=c(m[3]||""),B=c(m[4]||""),N=c(m[8]),D={},z=q?function(a,c){D[q]=c;D[s]=a;return D}:function(a){D[s]=a;return D};return{trackBy:t,getTrackByValue:w,getWatchables:c(N,function(a){var c=[];a=a||[];for(var d=n(a),f=d.length,g=0;g<f;g++){var h=a===d?g:d[g],k=z(a[h],h),h=p(a[h],k);c.push(h);if(m[2]||m[1])h=y(e,k),c.push(h);m[4]&&(k=B(e,k),c.push(k))}return c}),getOptions:function(){for(var a=[],c={},d=N(e)||[],g=n(d),h=g.length,m=0;m<h;m++){var r=d===g?m:g[m],s= +z(d[r],r),q=v(e,s),r=p(q,s),u=y(e,s),x=A(e,s),s=B(e,s),q=new f(r,q,u,x,s);a.push(q);c[r]=q}return{items:a,selectValueMap:c,getOptionFromViewValue:function(a){return c[w(a)]},getViewValueFromOption:function(a){return t?ca.copy(a.viewValue):a.viewValue}}}}}var e=U.createElement("option"),f=U.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","?ngModel"],link:function(c,h,l,k){function n(a,c){a.element=c;c.disabled=a.disabled;a.value!==c.value&&(c.value=a.selectValue);a.label!== +c.label&&(c.label=a.label,c.textContent=a.label)}function r(a,c,d,e){c&&M(c.nodeName)===d?d=c:(d=e.cloneNode(!1),c?a.insertBefore(d,c):a.appendChild(d));return d}function s(a){for(var c;a;)c=a.nextSibling,Xb(a),a=c}function q(a){var c=p&&p[0],d=N&&N[0];if(c||d)for(;a&&(a===c||a===d);)a=a.nextSibling;return a}function t(){var a=D&&u.readValue();D=z.getOptions();var c={},d=h[0].firstChild;B&&h.prepend(p);d=q(d);D.items.forEach(function(a){var g,k;a.group?(g=c[a.group],g||(g=r(h[0],d,"optgroup",f),d= +g.nextSibling,g.label=a.group,g=c[a.group]={groupElement:g,currentOptionElement:g.firstChild}),k=r(g.groupElement,g.currentOptionElement,"option",e),n(a,k),g.currentOptionElement=k.nextSibling):(k=r(h[0],d,"option",e),n(a,k),d=k.nextSibling)});Object.keys(c).forEach(function(a){s(c[a].currentOptionElement)});s(d);v.$render();if(!v.$isEmpty(a)){var g=u.readValue();(z.trackBy?ka(a,g):a===g)||(v.$setViewValue(g),v.$render())}}var v=k[1];if(v){var u=k[0];k=l.multiple;for(var p,w=0,A=h.children(),I=A.length;w< +I;w++)if(""===A[w].value){p=A.eq(w);break}var B=!!p,N=y(e.cloneNode(!1));N.val("?");var D,z=d(l.ngOptions,h,c);k?(v.$isEmpty=function(a){return!a||0===a.length},u.writeValue=function(a){D.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){(a=D.getOptionFromViewValue(a))&&!a.disabled&&(a.element.selected=!0)})},u.readValue=function(){var a=h.val()||[],c=[];m(a,function(a){a=D.selectValueMap[a];a.disabled||c.push(D.getViewValueFromOption(a))});return c},z.trackBy&&c.$watchCollection(function(){if(G(v.$viewValue))return v.$viewValue.map(function(a){return z.getTrackByValue(a)})}, +function(){v.$render()})):(u.writeValue=function(a){var c=D.getOptionFromViewValue(a);c&&!c.disabled?h[0].value!==c.selectValue&&(N.remove(),B||p.remove(),h[0].value=c.selectValue,c.element.selected=!0,c.element.setAttribute("selected","selected")):null===a||B?(N.remove(),B||h.prepend(p),h.val(""),p.prop("selected",!0),p.attr("selected",!0)):(B||p.remove(),h.prepend(N),h.val("?"),N.prop("selected",!0),N.attr("selected",!0))},u.readValue=function(){var a=D.selectValueMap[h.val()];return a&&!a.disabled? +(B||p.remove(),N.remove(),D.getViewValueFromOption(a)):null},z.trackBy&&c.$watch(function(){return z.getTrackByValue(v.$viewValue)},function(){v.$render()}));B?(p.remove(),a(p)(c),p.removeClass("ng-scope")):p=y(e.cloneNode(!1));t();c.$watchCollection(z.getWatchables,t)}}}}],Ce=["$locale","$interpolate","$log",function(a,c,d){var e=/{}/g,f=/^when(Minus)?(.+)$/;return{link:function(g,h,l){function k(a){h.text(a||"")}var n=l.count,r=l.$attr.when&&h.attr(l.$attr.when),s=l.offset||0,q=g.$eval(r)||{},t= +{},w=c.startSymbol(),u=c.endSymbol(),p=w+n+"-"+s+u,y=ca.noop,z;m(l,function(a,c){var d=f.exec(c);d&&(d=(d[1]?"-":"")+M(d[2]),q[d]=h.attr(l.$attr[c]))});m(q,function(a,d){t[d]=c(a.replace(e,p))});g.$watch(n,function(c){var e=parseFloat(c),f=isNaN(e);f||e in q||(e=a.pluralCat(e-s));e===z||f&&V(z)&&isNaN(z)||(y(),f=t[e],A(f)?(null!=c&&d.debug("ngPluralize: no rule defined for '"+e+"' in "+r),y=v,k()):y=g.$watch(f,k),z=e)})}}}],De=["$parse","$animate",function(a,c){var d=J("ngRepeat"),e=function(a,c, +d,e,k,m,r){a[d]=e;k&&(a[k]=m);a.$index=c;a.$first=0===c;a.$last=c===r-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=U.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var n=k[1],r=k[2],s=k[3],q=k[4],k=n.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/); +if(!k)throw d("iidexp",n);var v=k[3]||k[1],w=k[2];if(s&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(s)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(s)))throw d("badident",s);var u,p,z,A,I={$id:Ga};q?u=a(q):(z=function(a,c){return Ga(c)},A=function(a){return a});return function(a,f,g,k,n){u&&(p=function(c,d,e){w&&(I[w]=c);I[v]=d;I.$index=e;return u(a,I)});var q=ga();a.$watchCollection(r,function(g){var k,r,u=f[0],x,D=ga(),I,H,L,G,M,J,O;s&&(a[s]=g);if(Ea(g))M= +g,r=p||z;else for(O in r=p||A,M=[],g)g.hasOwnProperty(O)&&"$"!==O.charAt(0)&&M.push(O);I=M.length;O=Array(I);for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],G=r(H,L,k),q[G])J=q[G],delete q[G],D[G]=J,O[k]=J;else{if(D[G])throw m(O,function(a){a&&a.scope&&(q[a.id]=a)}),d("dupes",h,G,L);O[k]={id:G,scope:t,clone:t};D[G]=!0}for(x in q){J=q[x];G=qb(J.clone);c.leave(G);if(G[0].parentNode)for(k=0,r=G.length;k<r;k++)G[k].$$NG_REMOVED=!0;J.scope.$destroy()}for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],J=O[k],J.scope){x= +u;do x=x.nextSibling;while(x&&x.$$NG_REMOVED);J.clone[0]!=x&&c.move(qb(J.clone),null,y(u));u=J.clone[J.clone.length-1];e(J.scope,k,v,L,w,H,I)}else n(function(a,d){J.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a,null,y(u));u=f;J.clone=a;D[J.id]=J;e(J.scope,k,v,L,w,H,I)});q=D})}}}}],Ee=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],xe=["$animate", +function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Fe=Ma(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&m(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Ge=["$animate",function(a){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],n=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch|| +e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=0;for(e=k.length;d<e;++d){var q=qb(h[d].clone);k[d].$destroy();(l[d]=a.leave(q)).then(n(l,d))}h.length=0;k.length=0;(g=f.cases["!"+c]||f.cases["?"])&&m(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=U.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],He=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e, +f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,element:c})}}),Ie=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),Ke=Ma({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw J("ngTransclude")("orphan",ua(c));f(function(a){c.empty();c.append(a)})}}),ke=["$templateCache",function(a){return{restrict:"E",terminal:!0, +compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],Ag={$setViewValue:v,$render:v},Bg=["$element","$scope","$attrs",function(a,c,d){var e=this,f=new Sa;e.ngModelCtrl=Ag;e.unknownOption=y(U.createElement("option"));e.renderUnknownOption=function(c){c="? "+Ga(c)+" ?";e.unknownOption.val(c);a.prepend(e.unknownOption);a.val(c)};c.$on("$destroy",function(){e.renderUnknownOption=v});e.removeUnknownOption=function(){e.unknownOption.parent()&&e.unknownOption.remove()};e.readValue= +function(){e.removeUnknownOption();return a.val()};e.writeValue=function(c){e.hasOption(c)?(e.removeUnknownOption(),a.val(c),""===c&&e.emptyOption.prop("selected",!0)):null==c&&e.emptyOption?(e.removeUnknownOption(),a.val("")):e.renderUnknownOption(c)};e.addOption=function(a,c){Ra(a,'"option value"');""===a&&(e.emptyOption=c);var d=f.get(a)||0;f.put(a,d+1)};e.removeOption=function(a){var c=f.get(a);c&&(1===c?(f.remove(a),""===a&&(e.emptyOption=t)):f.put(a,c-1))};e.hasOption=function(a){return!!f.get(a)}}], +le=function(){return{restrict:"E",require:["select","?ngModel"],controller:Bg,link:function(a,c,d,e){var f=e[1];if(f){var g=e[0];g.ngModelCtrl=f;f.$render=function(){g.writeValue(f.$viewValue)};c.on("change",function(){a.$apply(function(){f.$setViewValue(g.readValue())})});if(d.multiple){g.readValue=function(){var a=[];m(c.find("option"),function(c){c.selected&&a.push(c.value)});return a};g.writeValue=function(a){var d=new Sa(a);m(c.find("option"),function(a){a.selected=w(d.get(a.value))})};var h, +l=NaN;a.$watch(function(){l!==f.$viewValue||ka(h,f.$viewValue)||(h=ia(f.$viewValue),f.$render());l=f.$viewValue});f.$isEmpty=function(a){return!a||0===a.length}}}}}},ne=["$interpolate",function(a){function c(a){a[0].hasAttribute("selected")&&(a[0].selected=!0)}return{restrict:"E",priority:100,compile:function(d,e){if(A(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),m=k.data("$selectController")||k.parent().data("$selectController");m&&m.ngModelCtrl&& +(f?a.$watch(f,function(a,f){e.$set("value",a);f!==a&&m.removeOption(f);m.addOption(a,d);m.ngModelCtrl.$render();c(d)}):(m.addOption(e.value,d),m.ngModelCtrl.$render(),c(d)),d.on("$destroy",function(){m.removeOption(e.value);m.ngModelCtrl.$render()}))}}}}],me=ra({restrict:"E",terminal:!1}),Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}}, +Gc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){L(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw J("ngPattern")("noregexp",g,a,ua(c));f=a||t;e.$validate()});e.$validators.pattern=function(a){return e.$isEmpty(a)||A(f)||f.test(a)}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=W(a);f=isNaN(a)?-1:a;e.$validate()}); +e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Ic=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=W(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};O.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(ce(),ee(ca),y(U).ready(function(){Zd(U,Ac)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>'); //# sourceMappingURL=angular.min.js.map /*! @@ -288,37 +331,56 @@ e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}} */ /* - AngularJS v1.3.13 - (c) 2010-2014 Google, Inc. http://angularjs.org + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org License: MIT */ -(function(N,f,W){'use strict';f.module("ngAnimate",["ng"]).directive("ngAnimateChildren",function(){return function(X,C,g){g=g.ngAnimateChildren;f.isString(g)&&0===g.length?C.data("$$ngAnimateChildren",!0):X.$watch(g,function(f){C.data("$$ngAnimateChildren",!!f)})}}).factory("$$animateReflow",["$$rAF","$document",function(f,C){return function(g){return f(function(){g()})}}]).config(["$provide","$animateProvider",function(X,C){function g(f){for(var n=0;n<f.length;n++){var g=f[n];if(1==g.nodeType)return g}} -function ba(f,n){return g(f)==g(n)}var t=f.noop,n=f.forEach,da=C.$$selectors,aa=f.isArray,ea=f.isString,ga=f.isObject,r={running:!0},u;X.decorator("$animate",["$delegate","$$q","$injector","$sniffer","$rootElement","$$asyncCallback","$rootScope","$document","$templateRequest","$$jqLite",function(O,N,M,Y,y,H,P,W,Z,Q){function R(a,c){var b=a.data("$$ngAnimateState")||{};c&&(b.running=!0,b.structural=!0,a.data("$$ngAnimateState",b));return b.disabled||b.running&&b.structural}function D(a){var c,b=N.defer(); -b.promise.$$cancelFn=function(){c&&c()};P.$$postDigest(function(){c=a(function(){b.resolve()})});return b.promise}function I(a){if(ga(a))return a.tempClasses&&ea(a.tempClasses)&&(a.tempClasses=a.tempClasses.split(/\s+/)),a}function S(a,c,b){b=b||{};var d={};n(b,function(e,a){n(a.split(" "),function(a){d[a]=e})});var h=Object.create(null);n((a.attr("class")||"").split(/\s+/),function(e){h[e]=!0});var f=[],l=[];n(c&&c.classes||[],function(e,a){var b=h[a],c=d[a]||{};!1===e?(b||"addClass"==c.event)&& -l.push(a):!0===e&&(b&&"removeClass"!=c.event||f.push(a))});return 0<f.length+l.length&&[f.join(" "),l.join(" ")]}function T(a){if(a){var c=[],b={};a=a.substr(1).split(".");(Y.transitions||Y.animations)&&c.push(M.get(da[""]));for(var d=0;d<a.length;d++){var f=a[d],k=da[f];k&&!b[f]&&(c.push(M.get(k)),b[f]=!0)}return c}}function U(a,c,b,d){function h(e,a){var b=e[a],c=e["before"+a.charAt(0).toUpperCase()+a.substr(1)];if(b||c)return"leave"==a&&(c=b,b=null),u.push({event:a,fn:b}),J.push({event:a,fn:c}), -!0}function k(c,l,w){var E=[];n(c,function(a){a.fn&&E.push(a)});var m=0;n(E,function(c,f){var p=function(){a:{if(l){(l[f]||t)();if(++m<E.length)break a;l=null}w()}};switch(c.event){case "setClass":l.push(c.fn(a,e,A,p,d));break;case "animate":l.push(c.fn(a,b,d.from,d.to,p));break;case "addClass":l.push(c.fn(a,e||b,p,d));break;case "removeClass":l.push(c.fn(a,A||b,p,d));break;default:l.push(c.fn(a,p,d))}});l&&0===l.length&&w()}var l=a[0];if(l){d&&(d.to=d.to||{},d.from=d.from||{});var e,A;aa(b)&&(e= -b[0],A=b[1],e?A?b=e+" "+A:(b=e,c="addClass"):(b=A,c="removeClass"));var w="setClass"==c,E=w||"addClass"==c||"removeClass"==c||"animate"==c,p=a.attr("class")+" "+b;if(x(p)){var ca=t,m=[],J=[],g=t,s=[],u=[],p=(" "+p).replace(/\s+/g,".");n(T(p),function(a){!h(a,c)&&w&&(h(a,"addClass"),h(a,"removeClass"))});return{node:l,event:c,className:b,isClassBased:E,isSetClassOperation:w,applyStyles:function(){d&&a.css(f.extend(d.from||{},d.to||{}))},before:function(a){ca=a;k(J,m,function(){ca=t;a()})},after:function(a){g= -a;k(u,s,function(){g=t;a()})},cancel:function(){m&&(n(m,function(a){(a||t)(!0)}),ca(!0));s&&(n(s,function(a){(a||t)(!0)}),g(!0))}}}}}function G(a,c,b,d,h,k,l,e){function A(e){var l="$animate:"+e;J&&J[l]&&0<J[l].length&&H(function(){b.triggerHandler(l,{event:a,className:c})})}function w(){A("before")}function E(){A("after")}function p(){p.hasBeenRun||(p.hasBeenRun=!0,k())}function g(){if(!g.hasBeenRun){m&&m.applyStyles();g.hasBeenRun=!0;l&&l.tempClasses&&n(l.tempClasses,function(a){u.removeClass(b, -a)});var w=b.data("$$ngAnimateState");w&&(m&&m.isClassBased?B(b,c):(H(function(){var e=b.data("$$ngAnimateState")||{};fa==e.index&&B(b,c,a)}),b.data("$$ngAnimateState",w)));A("close");e()}}var m=U(b,a,c,l);if(!m)return p(),w(),E(),g(),t;a=m.event;c=m.className;var J=f.element._data(m.node),J=J&&J.events;d||(d=h?h.parent():b.parent());if(z(b,d))return p(),w(),E(),g(),t;d=b.data("$$ngAnimateState")||{};var L=d.active||{},s=d.totalActive||0,q=d.last;h=!1;if(0<s){s=[];if(m.isClassBased)"setClass"==q.event? -(s.push(q),B(b,c)):L[c]&&(v=L[c],v.event==a?h=!0:(s.push(v),B(b,c)));else if("leave"==a&&L["ng-leave"])h=!0;else{for(var v in L)s.push(L[v]);d={};B(b,!0)}0<s.length&&n(s,function(a){a.cancel()})}!m.isClassBased||m.isSetClassOperation||"animate"==a||h||(h="addClass"==a==b.hasClass(c));if(h)return p(),w(),E(),A("close"),e(),t;L=d.active||{};s=d.totalActive||0;if("leave"==a)b.one("$destroy",function(a){a=f.element(this);var e=a.data("$$ngAnimateState");e&&(e=e.active["ng-leave"])&&(e.cancel(),B(a,"ng-leave"))}); -u.addClass(b,"ng-animate");l&&l.tempClasses&&n(l.tempClasses,function(a){u.addClass(b,a)});var fa=K++;s++;L[c]=m;b.data("$$ngAnimateState",{last:m,active:L,index:fa,totalActive:s});w();m.before(function(e){var l=b.data("$$ngAnimateState");e=e||!l||!l.active[c]||m.isClassBased&&l.active[c].event!=a;p();!0===e?g():(E(),m.after(g))});return m.cancel}function q(a){if(a=g(a))a=f.isFunction(a.getElementsByClassName)?a.getElementsByClassName("ng-animate"):a.querySelectorAll(".ng-animate"),n(a,function(a){a= -f.element(a);(a=a.data("$$ngAnimateState"))&&a.active&&n(a.active,function(a){a.cancel()})})}function B(a,c){if(ba(a,y))r.disabled||(r.running=!1,r.structural=!1);else if(c){var b=a.data("$$ngAnimateState")||{},d=!0===c;!d&&b.active&&b.active[c]&&(b.totalActive--,delete b.active[c]);if(d||!b.totalActive)u.removeClass(a,"ng-animate"),a.removeData("$$ngAnimateState")}}function z(a,c){if(r.disabled)return!0;if(ba(a,y))return r.running;var b,d,g;do{if(0===c.length)break;var k=ba(c,y),l=k?r:c.data("$$ngAnimateState")|| -{};if(l.disabled)return!0;k&&(g=!0);!1!==b&&(k=c.data("$$ngAnimateChildren"),f.isDefined(k)&&(b=k));d=d||l.running||l.last&&!l.last.isClassBased}while(c=c.parent());return!g||!b&&d}u=Q;y.data("$$ngAnimateState",r);var $=P.$watch(function(){return Z.totalPendingRequests},function(a,c){0===a&&($(),P.$$postDigest(function(){P.$$postDigest(function(){r.running=!1})}))}),K=0,V=C.classNameFilter(),x=V?function(a){return V.test(a)}:function(){return!0};return{animate:function(a,c,b,d,h){d=d||"ng-inline-animate"; -h=I(h)||{};h.from=b?c:null;h.to=b?b:c;return D(function(b){return G("animate",d,f.element(g(a)),null,null,t,h,b)})},enter:function(a,c,b,d){d=I(d);a=f.element(a);c=c&&f.element(c);b=b&&f.element(b);R(a,!0);O.enter(a,c,b);return D(function(h){return G("enter","ng-enter",f.element(g(a)),c,b,t,d,h)})},leave:function(a,c){c=I(c);a=f.element(a);q(a);R(a,!0);return D(function(b){return G("leave","ng-leave",f.element(g(a)),null,null,function(){O.leave(a)},c,b)})},move:function(a,c,b,d){d=I(d);a=f.element(a); -c=c&&f.element(c);b=b&&f.element(b);q(a);R(a,!0);O.move(a,c,b);return D(function(h){return G("move","ng-move",f.element(g(a)),c,b,t,d,h)})},addClass:function(a,c,b){return this.setClass(a,c,[],b)},removeClass:function(a,c,b){return this.setClass(a,[],c,b)},setClass:function(a,c,b,d){d=I(d);a=f.element(a);a=f.element(g(a));if(R(a))return O.$$setClassImmediately(a,c,b,d);var h,k=a.data("$$animateClasses"),l=!!k;k||(k={classes:{}});h=k.classes;c=aa(c)?c:c.split(" ");n(c,function(a){a&&a.length&&(h[a]= -!0)});b=aa(b)?b:b.split(" ");n(b,function(a){a&&a.length&&(h[a]=!1)});if(l)return d&&k.options&&(k.options=f.extend(k.options||{},d)),k.promise;a.data("$$animateClasses",k={classes:h,options:d});return k.promise=D(function(e){var l=a.parent(),b=g(a),c=b.parentNode;if(!c||c.$$NG_REMOVED||b.$$NG_REMOVED)e();else{b=a.data("$$animateClasses");a.removeData("$$animateClasses");var c=a.data("$$ngAnimateState")||{},d=S(a,b,c.active);return d?G("setClass",d,a,l,null,function(){d[0]&&O.$$addClassImmediately(a, -d[0]);d[1]&&O.$$removeClassImmediately(a,d[1])},b.options,e):e()}})},cancel:function(a){a.$$cancelFn()},enabled:function(a,c){switch(arguments.length){case 2:if(a)B(c);else{var b=c.data("$$ngAnimateState")||{};b.disabled=!0;c.data("$$ngAnimateState",b)}break;case 1:r.disabled=!a;break;default:a=!r.disabled}return!!a}}}]);C.register("",["$window","$sniffer","$timeout","$$animateReflow",function(r,C,M,Y){function y(){b||(b=Y(function(){c=[];b=null;x={}}))}function H(a,e){b&&b();c.push(e);b=Y(function(){n(c, -function(a){a()});c=[];b=null;x={}})}function P(a,e){var b=g(a);a=f.element(b);k.push(a);b=Date.now()+e;b<=h||(M.cancel(d),h=b,d=M(function(){X(k);k=[]},e,!1))}function X(a){n(a,function(a){(a=a.data("$$ngAnimateCSS3Data"))&&n(a.closeAnimationFns,function(a){a()})})}function Z(a,e){var b=e?x[e]:null;if(!b){var c=0,d=0,f=0,g=0;n(a,function(a){if(1==a.nodeType){a=r.getComputedStyle(a)||{};c=Math.max(Q(a[z+"Duration"]),c);d=Math.max(Q(a[z+"Delay"]),d);g=Math.max(Q(a[K+"Delay"]),g);var e=Q(a[K+"Duration"]); -0<e&&(e*=parseInt(a[K+"IterationCount"],10)||1);f=Math.max(e,f)}});b={total:0,transitionDelay:d,transitionDuration:c,animationDelay:g,animationDuration:f};e&&(x[e]=b)}return b}function Q(a){var e=0;a=ea(a)?a.split(/\s*,\s*/):[];n(a,function(a){e=Math.max(parseFloat(a)||0,e)});return e}function R(b,e,c,d){b=0<=["ng-enter","ng-leave","ng-move"].indexOf(c);var f,p=e.parent(),h=p.data("$$ngAnimateKey");h||(p.data("$$ngAnimateKey",++a),h=a);f=h+"-"+g(e).getAttribute("class");var p=f+" "+c,h=x[p]?++x[p].total: -0,m={};if(0<h){var n=c+"-stagger",m=f+" "+n;(f=!x[m])&&u.addClass(e,n);m=Z(e,m);f&&u.removeClass(e,n)}u.addClass(e,c);var n=e.data("$$ngAnimateCSS3Data")||{},k=Z(e,p);f=k.transitionDuration;k=k.animationDuration;if(b&&0===f&&0===k)return u.removeClass(e,c),!1;c=d||b&&0<f;b=0<k&&0<m.animationDelay&&0===m.animationDuration;e.data("$$ngAnimateCSS3Data",{stagger:m,cacheKey:p,running:n.running||0,itemIndex:h,blockTransition:c,closeAnimationFns:n.closeAnimationFns||[]});p=g(e);c&&(I(p,!0),d&&e.css(d)); -b&&(p.style[K+"PlayState"]="paused");return!0}function D(a,e,b,c,d){function f(){e.off(D,h);u.removeClass(e,k);u.removeClass(e,t);z&&M.cancel(z);G(e,b);var a=g(e),c;for(c in s)a.style.removeProperty(s[c])}function h(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-H,0)>=C&&b>=x&&c()}var m=g(e);a=e.data("$$ngAnimateCSS3Data");if(-1!=m.getAttribute("class").indexOf(b)&&a){var k="",t="";n(b.split(" "),function(a, -b){var e=(0<b?" ":"")+a;k+=e+"-active";t+=e+"-pending"});var s=[],q=a.itemIndex,v=a.stagger,r=0;if(0<q){r=0;0<v.transitionDelay&&0===v.transitionDuration&&(r=v.transitionDelay*q);var y=0;0<v.animationDelay&&0===v.animationDuration&&(y=v.animationDelay*q,s.push(B+"animation-play-state"));r=Math.round(100*Math.max(r,y))/100}r||(u.addClass(e,k),a.blockTransition&&I(m,!1));var F=Z(e,a.cacheKey+" "+k),x=Math.max(F.transitionDuration,F.animationDuration);if(0===x)u.removeClass(e,k),G(e,b),c();else{!r&& -d&&0<Object.keys(d).length&&(F.transitionDuration||(e.css("transition",F.animationDuration+"s linear all"),s.push("transition")),e.css(d));var q=Math.max(F.transitionDelay,F.animationDelay),C=1E3*q;0<s.length&&(v=m.getAttribute("style")||"",";"!==v.charAt(v.length-1)&&(v+=";"),m.setAttribute("style",v+" "));var H=Date.now(),D=V+" "+$,q=1E3*(r+1.5*(q+x)),z;0<r&&(u.addClass(e,t),z=M(function(){z=null;0<F.transitionDuration&&I(m,!1);0<F.animationDuration&&(m.style[K+"PlayState"]="");u.addClass(e,k); -u.removeClass(e,t);d&&(0===F.transitionDuration&&e.css("transition",F.animationDuration+"s linear all"),e.css(d),s.push("transition"))},1E3*r,!1));e.on(D,h);a.closeAnimationFns.push(function(){f();c()});a.running++;P(e,q);return f}}else c()}function I(a,b){a.style[z+"Property"]=b?"none":""}function S(a,b,c,d){if(R(a,b,c,d))return function(a){a&&G(b,c)}}function T(a,b,c,d,f){if(b.data("$$ngAnimateCSS3Data"))return D(a,b,c,d,f);G(b,c);d()}function U(a,b,c,d,f){var g=S(a,b,c,f.from);if(g){var h=g;H(b, -function(){h=T(a,b,c,d,f.to)});return function(a){(h||t)(a)}}y();d()}function G(a,b){u.removeClass(a,b);var c=a.data("$$ngAnimateCSS3Data");c&&(c.running&&c.running--,c.running&&0!==c.running||a.removeData("$$ngAnimateCSS3Data"))}function q(a,b){var c="";a=aa(a)?a:a.split(/\s+/);n(a,function(a,d){a&&0<a.length&&(c+=(0<d?" ":"")+a+b)});return c}var B="",z,$,K,V;N.ontransitionend===W&&N.onwebkittransitionend!==W?(B="-webkit-",z="WebkitTransition",$="webkitTransitionEnd transitionend"):(z="transition", -$="transitionend");N.onanimationend===W&&N.onwebkitanimationend!==W?(B="-webkit-",K="WebkitAnimation",V="webkitAnimationEnd animationend"):(K="animation",V="animationend");var x={},a=0,c=[],b,d=null,h=0,k=[];return{animate:function(a,b,c,d,f,g){g=g||{};g.from=c;g.to=d;return U("animate",a,b,f,g)},enter:function(a,b,c){c=c||{};return U("enter",a,"ng-enter",b,c)},leave:function(a,b,c){c=c||{};return U("leave",a,"ng-leave",b,c)},move:function(a,b,c){c=c||{};return U("move",a,"ng-move",b,c)},beforeSetClass:function(a, -b,c,d,f){f=f||{};b=q(c,"-remove")+" "+q(b,"-add");if(f=S("setClass",a,b,f.from))return H(a,d),f;y();d()},beforeAddClass:function(a,b,c,d){d=d||{};if(b=S("addClass",a,q(b,"-add"),d.from))return H(a,c),b;y();c()},beforeRemoveClass:function(a,b,c,d){d=d||{};if(b=S("removeClass",a,q(b,"-remove"),d.from))return H(a,c),b;y();c()},setClass:function(a,b,c,d,f){f=f||{};c=q(c,"-remove");b=q(b,"-add");return T("setClass",a,c+" "+b,d,f.to)},addClass:function(a,b,c,d){d=d||{};return T("addClass",a,q(b,"-add"), -c,d.to)},removeClass:function(a,b,c,d){d=d||{};return T("removeClass",a,q(b,"-remove"),c,d.to)}}}])}])})(window,window.angular); +(function(F,t,W){'use strict';function ua(a,b,c){if(!a)throw ngMinErr("areq",b||"?",c||"required");return a}function va(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;X(a)&&(a=a.join(" "));X(b)&&(b=b.join(" "));return a+" "+b}function Ea(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function ba(a,b,c){var d="";a=X(a)?a:a&&U(a)&&a.length?a.split(/\s+/):[];u(a,function(a,s){a&&0<a.length&&(d+=0<s?" ":"",d+=c?b+a:a+b)});return d}function Fa(a){if(a instanceof G)switch(a.length){case 0:return[]; +case 1:if(1===a[0].nodeType)return a;break;default:return G(ka(a))}if(1===a.nodeType)return G(a)}function ka(a){if(!a[0])return a;for(var b=0;b<a.length;b++){var c=a[b];if(1==c.nodeType)return c}}function Ga(a,b,c){u(b,function(b){a.addClass(b,c)})}function Ha(a,b,c){u(b,function(b){a.removeClass(b,c)})}function ha(a){return function(b,c){c.addClass&&(Ga(a,b,c.addClass),c.addClass=null);c.removeClass&&(Ha(a,b,c.removeClass),c.removeClass=null)}}function ia(a){a=a||{};if(!a.$$prepared){var b=a.domOperation|| +H;a.domOperation=function(){a.$$domOperationFired=!0;b();b=H};a.$$prepared=!0}return a}function ca(a,b){wa(a,b);xa(a,b)}function wa(a,b){b.from&&(a.css(b.from),b.from=null)}function xa(a,b){b.to&&(a.css(b.to),b.to=null)}function R(a,b,c){var d=(b.addClass||"")+" "+(c.addClass||""),e=(b.removeClass||"")+" "+(c.removeClass||"");a=Ia(a.attr("class"),d,e);ya(b,c);b.addClass=a.addClass?a.addClass:null;b.removeClass=a.removeClass?a.removeClass:null;return b}function Ia(a,b,c){function d(a){U(a)&&(a=a.split(" ")); +var b={};u(a,function(a){a.length&&(b[a]=!0)});return b}var e={};a=d(a);b=d(b);u(b,function(a,b){e[b]=1});c=d(c);u(c,function(a,b){e[b]=1===e[b]?null:-1});var s={addClass:"",removeClass:""};u(e,function(b,c){var d,e;1===b?(d="addClass",e=!a[c]):-1===b&&(d="removeClass",e=a[c]);e&&(s[d].length&&(s[d]+=" "),s[d]+=c)});return s}function z(a){return a instanceof t.element?a[0]:a}function za(a,b,c){var d=Object.create(null),e=a.getComputedStyle(b)||{};u(c,function(a,b){var c=e[a];if(c){var k=c.charAt(0); +if("-"===k||"+"===k||0<=k)c=Ja(c);0===c&&(c=null);d[b]=c}});return d}function Ja(a){var b=0;a=a.split(/\s*,\s*/);u(a,function(a){"s"==a.charAt(a.length-1)&&(a=a.substring(0,a.length-1));a=parseFloat(a)||0;b=b?Math.max(a,b):a});return b}function la(a){return 0===a||null!=a}function Aa(a,b){var c=O,d=a+"s";b?c+="Duration":d+=" linear all";return[c,d]}function ja(a,b){var c=b?"-"+b+"s":"";da(a,[ea,c]);return[ea,c]}function ma(a,b){var c=b?"paused":"",d=V+"PlayState";da(a,[d,c]);return[d,c]}function da(a, +b){a.style[b[0]]=b[1]}function Ba(){var a=Object.create(null);return{flush:function(){a=Object.create(null)},count:function(b){return(b=a[b])?b.total:0},get:function(b){return(b=a[b])&&b.value},put:function(b,c){a[b]?a[b].total++:a[b]={total:1,value:c}}}}var H=t.noop,ya=t.extend,G=t.element,u=t.forEach,X=t.isArray,U=t.isString,na=t.isObject,Ka=t.isUndefined,La=t.isDefined,Ca=t.isFunction,oa=t.isElement,O,pa,V,qa;F.ontransitionend===W&&F.onwebkittransitionend!==W?(O="WebkitTransition",pa="webkitTransitionEnd transitionend"): +(O="transition",pa="transitionend");F.onanimationend===W&&F.onwebkitanimationend!==W?(V="WebkitAnimation",qa="webkitAnimationEnd animationend"):(V="animation",qa="animationend");var ra=V+"Delay",sa=V+"Duration",ea=O+"Delay";F=O+"Duration";var Ma={transitionDuration:F,transitionDelay:ea,transitionProperty:O+"Property",animationDuration:sa,animationDelay:ra,animationIterationCount:V+"IterationCount"},Na={transitionDuration:F,transitionDelay:ea,animationDuration:sa,animationDelay:ra};t.module("ngAnimate", +[]).directive("ngAnimateChildren",[function(){return function(a,b,c){a=c.ngAnimateChildren;t.isString(a)&&0===a.length?b.data("$$ngAnimateChildren",!0):c.$observe("ngAnimateChildren",function(a){b.data("$$ngAnimateChildren","on"===a||"true"===a)})}}]).factory("$$rAFMutex",["$$rAF",function(a){return function(){var b=!1;a(function(){b=!0});return function(c){b?c():a(c)}}}]).factory("$$rAFScheduler",["$$rAF",function(a){function b(a){d.push([].concat(a));c()}function c(){if(d.length){for(var b=[],n= +0;n<d.length;n++){var h=d[n];h.shift()();h.length&&b.push(h)}d=b;e||a(function(){e||c()})}}var d=[],e;b.waitUntilQuiet=function(b){e&&e();e=a(function(){e=null;b();c()})};return b}]).factory("$$AnimateRunner",["$q","$$rAFMutex",function(a,b){function c(a){this.setHost(a);this._doneCallbacks=[];this._runInAnimationFrame=b();this._state=0}c.chain=function(a,b){function c(){if(n===a.length)b(!0);else a[n](function(a){!1===a?b(!1):(n++,c())})}var n=0;c()};c.all=function(a,b){function c(s){h=h&&s;++n=== +a.length&&b(h)}var n=0,h=!0;u(a,function(a){a.done(c)})};c.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===this._state?a():this._doneCallbacks.push(a)},progress:H,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&& +this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end();this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=this;0===b._state&&(b._state=1,b._runInAnimationFrame(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(u(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=0,this._state=2)}};return c}]).provider("$$animateQueue",["$animateProvider", +function(a){function b(a,b,c,h){return d[a].some(function(a){return a(b,c,h)})}function c(a,b){a=a||{};var c=0<(a.addClass||"").length,d=0<(a.removeClass||"").length;return b?c&&d:c||d}var d=this.rules={skip:[],cancel:[],join:[]};d.join.push(function(a,b,d){return!b.structural&&c(b.options)});d.skip.push(function(a,b,d){return!b.structural&&!c(b.options)});d.skip.push(function(a,b,c){return"leave"==c.event&&b.structural});d.skip.push(function(a,b,c){return c.structural&&!b.structural});d.cancel.push(function(a, +b,c){return c.structural&&b.structural});d.cancel.push(function(a,b,c){return 2===c.state&&b.structural});d.cancel.push(function(a,b,c){a=b.options;c=c.options;return a.addClass&&a.addClass===c.removeClass||a.removeClass&&a.removeClass===c.addClass});this.$get=["$$rAF","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite",function(d,s,n,h,k,D,A,Z,I){function w(a,b){var c=z(a),f=[],m=l[b];m&&u(m,function(a){a.node.contains(c)&&f.push(a.callback)}); +return f}function B(a,b,c,f){d(function(){u(w(b,a),function(a){a(b,c,f)})})}function r(a,S,p){function d(b,c,f,p){B(c,a,f,p);b.progress(c,f,p)}function g(b){Da(a,p);ca(a,p);p.domOperation();l.complete(!b)}var P,E;if(a=Fa(a))P=z(a),E=a.parent();p=ia(p);var l=new A;if(!P)return g(),l;X(p.addClass)&&(p.addClass=p.addClass.join(" "));X(p.removeClass)&&(p.removeClass=p.removeClass.join(" "));p.from&&!na(p.from)&&(p.from=null);p.to&&!na(p.to)&&(p.to=null);var e=[P.className,p.addClass,p.removeClass].join(" "); +if(!v(e))return g(),l;var M=0<=["enter","move","leave"].indexOf(S),h=!x||L.get(P),e=!h&&m.get(P)||{},k=!!e.state;h||k&&1==e.state||(h=!ta(a,E,S));if(h)return g(),l;M&&K(a);h={structural:M,element:a,event:S,close:g,options:p,runner:l};if(k){if(b("skip",a,h,e)){if(2===e.state)return g(),l;R(a,e.options,p);return e.runner}if(b("cancel",a,h,e))2===e.state?e.runner.end():e.structural?e.close():R(a,h.options,e.options);else if(b("join",a,h,e))if(2===e.state)R(a,p,{});else return S=h.event=e.event,p=R(a, +e.options,h.options),l}else R(a,p,{});(k=h.structural)||(k="animate"===h.event&&0<Object.keys(h.options.to||{}).length||c(h.options));if(!k)return g(),C(a),l;M&&f(E);var r=(e.counter||0)+1;h.counter=r;ga(a,1,h);s.$$postDigest(function(){var b=m.get(P),v=!b,b=b||{},e=a.parent()||[],E=0<e.length&&("animate"===b.event||b.structural||c(b.options));if(v||b.counter!==r||!E){v&&(Da(a,p),ca(a,p));if(v||M&&b.event!==S)p.domOperation(),l.end();E||C(a)}else S=!b.structural&&c(b.options,!0)?"setClass":b.event, +b.structural&&f(e),ga(a,2),b=D(a,S,b.options),b.done(function(b){g(!b);(b=m.get(P))&&b.counter===r&&C(z(a));d(l,S,"close",{})}),l.setHost(b),d(l,S,"start",{})});return l}function K(a){a=z(a).querySelectorAll("[data-ng-animate]");u(a,function(a){var b=parseInt(a.getAttribute("data-ng-animate")),c=m.get(a);switch(b){case 2:c.runner.end();case 1:c&&m.remove(a)}})}function C(a){a=z(a);a.removeAttribute("data-ng-animate");m.remove(a)}function E(a,b){return z(a)===z(b)}function f(a){a=z(a);do{if(!a||1!== +a.nodeType)break;var b=m.get(a);if(b){var f=a;!b.structural&&c(b.options)&&(2===b.state&&b.runner.end(),C(f))}a=a.parentNode}while(1)}function ta(a,b,c){var f=c=!1,d=!1,v;for((a=a.data("$ngAnimatePin"))&&(b=a);b&&b.length;){f||(f=E(b,n));a=b[0];if(1!==a.nodeType)break;var e=m.get(a)||{};d||(d=e.structural||L.get(a));if(Ka(v)||!0===v)a=b.data("$$ngAnimateChildren"),La(a)&&(v=a);if(d&&!1===v)break;f||(f=E(b,n),f||(a=b.data("$ngAnimatePin"))&&(b=a));c||(c=E(b,g));b=b.parent()}return(!d||v)&&f&&c}function ga(a, +b,c){c=c||{};c.state=b;a=z(a);a.setAttribute("data-ng-animate",b);c=(b=m.get(a))?ya(b,c):c;m.put(a,c)}var m=new k,L=new k,x=null,M=s.$watch(function(){return 0===Z.totalPendingRequests},function(a){a&&(M(),s.$$postDigest(function(){s.$$postDigest(function(){null===x&&(x=!0)})}))}),g=G(h[0].body),l={},P=a.classNameFilter(),v=P?function(a){return P.test(a)}:function(){return!0},Da=ha(I);return{on:function(a,b,c){b=ka(b);l[a]=l[a]||[];l[a].push({node:b,callback:c})},off:function(a,b,c){function f(a, +b,c){var d=ka(b);return a.filter(function(a){return!(a.node===d&&(!c||a.callback===c))})}var d=l[a];d&&(l[a]=1===arguments.length?null:f(d,b,c))},pin:function(a,b){ua(oa(a),"element","not an element");ua(oa(b),"parentElement","not an element");a.data("$ngAnimatePin",b)},push:function(a,b,c,f){c=c||{};c.domOperation=f;return r(a,b,c)},enabled:function(a,b){var c=arguments.length;if(0===c)b=!!x;else if(oa(a)){var f=z(a),d=L.get(f);1===c?b=!d:(b=!!b)?d&&L.remove(f):L.put(f,!0)}else b=x=!!a;return b}}}]}]).provider("$$animation", +["$animateProvider",function(a){function b(a){return a.data("$$animationRunner")}var c=this.drivers=[];this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$rAFScheduler",function(a,e,s,n,h){var k=[],D=ha(a),A=0,Z=0,I=[];return function(w,B,r){function K(a){a=a.hasAttribute("ng-animate-ref")?[a]:a.querySelectorAll("[ng-animate-ref]");var b=[];u(a,function(a){var c=a.getAttribute("ng-animate-ref");c&&c.length&&b.push(a)});return b}function C(a){var b=[],c={};u(a,function(a,f){var d=z(a.element), +m=0<=["enter","move"].indexOf(a.event),d=a.structural?K(d):[];if(d.length){var g=m?"to":"from";u(d,function(a){var b=a.getAttribute("ng-animate-ref");c[b]=c[b]||{};c[b][g]={animationID:f,element:G(a)}})}else b.push(a)});var f={},d={};u(c,function(c,m){var g=c.from,e=c.to;if(g&&e){var l=a[g.animationID],h=a[e.animationID],x=g.animationID.toString();if(!d[x]){var B=d[x]={structural:!0,beforeStart:function(){l.beforeStart();h.beforeStart()},close:function(){l.close();h.close()},classes:E(l.classes,h.classes), +from:l,to:h,anchors:[]};B.classes.length?b.push(B):(b.push(l),b.push(h))}d[x].anchors.push({out:g.element,"in":e.element})}else g=g?g.animationID:e.animationID,e=g.toString(),f[e]||(f[e]=!0,b.push(a[g]))});return b}function E(a,b){a=a.split(" ");b=b.split(" ");for(var c=[],f=0;f<a.length;f++){var d=a[f];if("ng-"!==d.substring(0,3))for(var g=0;g<b.length;g++)if(d===b[g]){c.push(d);break}}return c.join(" ")}function f(a){for(var b=c.length-1;0<=b;b--){var f=c[b];if(s.has(f)&&(f=s.get(f)(a)))return f}} +function ta(a,c){a.from&&a.to?(b(a.from.element).setHost(c),b(a.to.element).setHost(c)):b(a.element).setHost(c)}function ga(){var a=b(w);!a||"leave"===B&&r.$$domOperationFired||a.end()}function m(b){w.off("$destroy",ga);w.removeData("$$animationRunner");D(w,r);ca(w,r);r.domOperation();g&&a.removeClass(w,g);w.removeClass("ng-animate");x.complete(!b)}r=ia(r);var L=0<=["enter","move","leave"].indexOf(B),x=new n({end:function(){m()},cancel:function(){m(!0)}});if(!c.length)return m(),x;w.data("$$animationRunner", +x);var M=va(w.attr("class"),va(r.addClass,r.removeClass)),g=r.tempClasses;g&&(M+=" "+g,r.tempClasses=null);var l;L||(l=A,A+=1);k.push({element:w,classes:M,event:B,classBasedIndex:l,structural:L,options:r,beforeStart:function(){w.addClass("ng-animate");g&&a.addClass(w,g)},close:m});w.on("$destroy",ga);if(1<k.length)return x;e.$$postDigest(function(){Z=A;A=0;I.length=0;var a=[];u(k,function(c){b(c.element)&&a.push(c)});k.length=0;u(C(a),function(a){function c(){a.beforeStart();var d,g=a.close,e=a.anchors? +a.from.element||a.to.element:a.element;b(e)&&z(e).parentNode&&(e=f(a))&&(d=e.start);d?(d=d(),d.done(function(a){g(!a)}),ta(a,d)):g()}a.structural?c():(I.push({node:z(a.element),fn:c}),a.classBasedIndex===Z-1&&(I=I.sort(function(a,b){return b.node.contains(a.node)}).map(function(a){return a.fn}),h(I)))})});return x}}]}]).provider("$animateCss",["$animateProvider",function(a){var b=Ba(),c=Ba();this.$get=["$window","$$jqLite","$$AnimateRunner","$timeout","$document","$sniffer","$$rAFScheduler",function(a, +e,s,n,h,k,D){function A(a,b){var c=a.parentNode;return(c.$$ngAnimateParentKey||(c.$$ngAnimateParentKey=++r))+"-"+a.getAttribute("class")+"-"+b}function Z(h,f,B,k){var m;0<b.count(B)&&(m=c.get(B),m||(f=ba(f,"-stagger"),e.addClass(h,f),m=za(a,h,k),m.animationDuration=Math.max(m.animationDuration,0),m.transitionDuration=Math.max(m.transitionDuration,0),e.removeClass(h,f),c.put(B,m)));return m||{}}function I(a){C.push(a);D.waitUntilQuiet(function(){b.flush();c.flush();for(var a=K.offsetWidth+1,d=0;d< +C.length;d++)C[d](a);C.length=0})}function w(c,f,e){f=b.get(e);f||(f=za(a,c,Ma),"infinite"===f.animationIterationCount&&(f.animationIterationCount=1));b.put(e,f);c=f;e=c.animationDelay;f=c.transitionDelay;c.maxDelay=e&&f?Math.max(e,f):e||f;c.maxDuration=Math.max(c.animationDuration*c.animationIterationCount,c.transitionDuration);return c}var B=ha(e),r=0,K=z(h).body,C=[];return function(a,c){function d(){m()}function h(){m(!0)}function m(b){if(!(K||C&&D)){K=!0;D=!1;e.removeClass(a,Y);e.removeClass(a, +W);ma(g,!1);ja(g,!1);u(l,function(a){g.style[a[0]]=""});B(a,c);ca(a,c);if(c.onDone)c.onDone();p&&p.complete(!b)}}function L(a){q.blockTransition&&ja(g,a);q.blockKeyframeAnimation&&ma(g,!!a)}function x(){p=new s({end:d,cancel:h});m();return{$$willAnimate:!1,start:function(){return p},end:d}}function M(){function b(){if(!K){L(!1);u(l,function(a){g.style[a[0]]=a[1]});B(a,c);e.addClass(a,W);if(q.recalculateTimingStyles){fa=g.className+" "+Y;$=A(g,fa);y=w(g,fa,$);Q=y.maxDelay;H=Math.max(Q,0);J=y.maxDuration; +if(0===J){m();return}q.hasTransitions=0<y.transitionDuration;q.hasAnimations=0<y.animationDuration}if(q.applyTransitionDelay||q.applyAnimationDelay){Q="boolean"!==typeof c.delay&&la(c.delay)?parseFloat(c.delay):Q;H=Math.max(Q,0);var k;q.applyTransitionDelay&&(y.transitionDelay=Q,k=[ea,Q+"s"],l.push(k),g.style[k[0]]=k[1]);q.applyAnimationDelay&&(y.animationDelay=Q,k=[ra,Q+"s"],l.push(k),g.style[k[0]]=k[1])}F=1E3*H;G=1E3*J;if(c.easing){var r=c.easing;q.hasTransitions&&(k=O+"TimingFunction",l.push([k, +r]),g.style[k]=r);q.hasAnimations&&(k=V+"TimingFunction",l.push([k,r]),g.style[k]=r)}y.transitionDuration&&p.push(pa);y.animationDuration&&p.push(qa);x=Date.now();a.on(p.join(" "),h);n(d,F+1.5*G);xa(a,c)}}function d(){m()}function h(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-x,0)>=F&&b>=J&&(C=!0,m())}if(!K)if(g.parentNode){var x,p=[],k=function(a){if(C)D&&a&&(D=!1,m());else if(D=!a,y.animationDuration)if(a= +ma(g,D),D)l.push(a);else{var b=l,c=b.indexOf(a);0<=a&&b.splice(c,1)}},r=0<U&&(y.transitionDuration&&0===T.transitionDuration||y.animationDuration&&0===T.animationDuration)&&Math.max(T.animationDelay,T.transitionDelay);r?n(b,Math.floor(r*U*1E3),!1):b();t.resume=function(){k(!0)};t.pause=function(){k(!1)}}else m()}var g=z(a);if(!g||!g.parentNode)return x();c=ia(c);var l=[],r=a.attr("class"),v=Ea(c),K,D,C,p,t,H,F,J,G;if(0===c.duration||!k.animations&&!k.transitions)return x();var aa=c.event&&X(c.event)? +c.event.join(" "):c.event,R="",N="";aa&&c.structural?R=ba(aa,"ng-",!0):aa&&(R=aa);c.addClass&&(N+=ba(c.addClass,"-add"));c.removeClass&&(N.length&&(N+=" "),N+=ba(c.removeClass,"-remove"));c.applyClassesEarly&&N.length&&(B(a,c),N="");var Y=[R,N].join(" ").trim(),fa=r+" "+Y,W=ba(Y,"-active"),r=v.to&&0<Object.keys(v.to).length;if(!(0<(c.keyframeStyle||"").length||r||Y))return x();var $,T;0<c.stagger?(v=parseFloat(c.stagger),T={transitionDelay:v,animationDelay:v,transitionDuration:0,animationDuration:0}): +($=A(g,fa),T=Z(g,Y,$,Na));e.addClass(a,Y);c.transitionStyle&&(v=[O,c.transitionStyle],da(g,v),l.push(v));0<=c.duration&&(v=0<g.style[O].length,v=Aa(c.duration,v),da(g,v),l.push(v));c.keyframeStyle&&(v=[V,c.keyframeStyle],da(g,v),l.push(v));var U=T?0<=c.staggerIndex?c.staggerIndex:b.count($):0;(aa=0===U)&&ja(g,9999);var y=w(g,fa,$),Q=y.maxDelay;H=Math.max(Q,0);J=y.maxDuration;var q={};q.hasTransitions=0<y.transitionDuration;q.hasAnimations=0<y.animationDuration;q.hasTransitionAll=q.hasTransitions&& +"all"==y.transitionProperty;q.applyTransitionDuration=r&&(q.hasTransitions&&!q.hasTransitionAll||q.hasAnimations&&!q.hasTransitions);q.applyAnimationDuration=c.duration&&q.hasAnimations;q.applyTransitionDelay=la(c.delay)&&(q.applyTransitionDuration||q.hasTransitions);q.applyAnimationDelay=la(c.delay)&&q.hasAnimations;q.recalculateTimingStyles=0<N.length;if(q.applyTransitionDuration||q.applyAnimationDuration)J=c.duration?parseFloat(c.duration):J,q.applyTransitionDuration&&(q.hasTransitions=!0,y.transitionDuration= +J,v=0<g.style[O+"Property"].length,l.push(Aa(J,v))),q.applyAnimationDuration&&(q.hasAnimations=!0,y.animationDuration=J,l.push([sa,J+"s"]));if(0===J&&!q.recalculateTimingStyles)return x();null==c.duration&&0<y.transitionDuration&&(q.recalculateTimingStyles=q.recalculateTimingStyles||aa);F=1E3*H;G=1E3*J;c.skipBlocking||(q.blockTransition=0<y.transitionDuration,q.blockKeyframeAnimation=0<y.animationDuration&&0<T.animationDelay&&0===T.animationDuration);wa(a,c);q.blockTransition||ja(g,!1);L(J);return{$$willAnimate:!0, +end:d,start:function(){if(!K)return t={end:d,cancel:h,resume:null,pause:null},p=new s(t),I(M),p}}}}]}]).provider("$$animateCssDriver",["$$animationProvider",function(a){a.drivers.push("$$animateCssDriver");this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$document","$sniffer",function(a,c,d,e,s,n){function h(a){return a.replace(/\bng-\S+\b/g,"")}function k(a,b){U(a)&&(a=a.split(" "));U(b)&&(b=b.split(" "));return a.filter(function(a){return-1===b.indexOf(a)}).join(" ")}function D(c, +e,A){function D(a){var b={},c=z(a).getBoundingClientRect();u(["width","height","top","left"],function(a){var d=c[a];switch(a){case "top":d+=I.scrollTop;break;case "left":d+=I.scrollLeft}b[a]=Math.floor(d)+"px"});return b}function s(){var c=h(A.attr("class")||""),d=k(c,t),c=k(t,c),d=a(n,{to:D(A),addClass:"ng-anchor-in "+d,removeClass:"ng-anchor-out "+c,delay:!0});return d.$$willAnimate?d:null}function f(){n.remove();e.removeClass("ng-animate-shim");A.removeClass("ng-animate-shim")}var n=G(z(e).cloneNode(!0)), +t=h(n.attr("class")||"");e.addClass("ng-animate-shim");A.addClass("ng-animate-shim");n.addClass("ng-anchor");w.append(n);var m;c=function(){var c=a(n,{addClass:"ng-anchor-out",delay:!0,from:D(e)});return c.$$willAnimate?c:null}();if(!c&&(m=s(),!m))return f();var L=c||m;return{start:function(){function a(){c&&c.end()}var b,c=L.start();c.done(function(){c=null;if(!m&&(m=s()))return c=m.start(),c.done(function(){c=null;f();b.complete()}),c;f();b.complete()});return b=new d({end:a,cancel:a})}}}function A(a, +b,c,e){var h=t(a),f=t(b),k=[];u(e,function(a){(a=D(c,a.out,a["in"]))&&k.push(a)});if(h||f||0!==k.length)return{start:function(){function a(){u(b,function(a){a.end()})}var b=[];h&&b.push(h.start());f&&b.push(f.start());u(k,function(a){b.push(a.start())});var c=new d({end:a,cancel:a});d.all(b,function(a){c.complete(a)});return c}}}function t(c){var d=c.element,e=c.options||{};c.structural?(e.structural=e.applyClassesEarly=!0,e.event=c.event,"leave"===e.event&&(e.onDone=e.domOperation)):e.event=null; +c=a(d,e);return c.$$willAnimate?c:null}if(!n.animations&&!n.transitions)return H;var I=z(s).body;c=z(e);var w=G(I.parentNode===c?I:c);return function(a){return a.from&&a.to?A(a.from,a.to,a.classes,a.anchors):t(a)}}]}]).provider("$$animateJs",["$animateProvider",function(a){this.$get=["$injector","$$AnimateRunner","$$rAFMutex","$$jqLite",function(b,c,d,e){function s(c){c=X(c)?c:c.split(" ");for(var d=[],e={},A=0;A<c.length;A++){var n=c[A],s=a.$$registeredAnimations[n];s&&!e[n]&&(d.push(b.get(s)),e[n]= +!0)}return d}var n=ha(e);return function(a,b,d,e){function t(){e.domOperation();n(a,e)}function z(a,b,d,e,g){switch(d){case "animate":b=[b,e.from,e.to,g];break;case "setClass":b=[b,r,K,g];break;case "addClass":b=[b,r,g];break;case "removeClass":b=[b,K,g];break;default:b=[b,g]}b.push(e);if(a=a.apply(a,b))if(Ca(a.start)&&(a=a.start()),a instanceof c)a.done(g);else if(Ca(a))return a;return H}function w(a,b,d,e,g){var f=[];u(e,function(e){var h=e[g];h&&f.push(function(){var e,g,f=!1,l=function(a){f|| +(f=!0,(g||H)(a),e.complete(!a))};e=new c({end:function(){l()},cancel:function(){l(!0)}});g=z(h,a,b,d,function(a){l(!1===a)});return e})});return f}function B(a,b,d,e,g){var f=w(a,b,d,e,g);if(0===f.length){var h,k;"beforeSetClass"===g?(h=w(a,"removeClass",d,e,"beforeRemoveClass"),k=w(a,"addClass",d,e,"beforeAddClass")):"setClass"===g&&(h=w(a,"removeClass",d,e,"removeClass"),k=w(a,"addClass",d,e,"addClass"));h&&(f=f.concat(h));k&&(f=f.concat(k))}if(0!==f.length)return function(a){var b=[];f.length&& +u(f,function(a){b.push(a())});b.length?c.all(b,a):a();return function(a){u(b,function(b){a?b.cancel():b.end()})}}}3===arguments.length&&na(d)&&(e=d,d=null);e=ia(e);d||(d=a.attr("class")||"",e.addClass&&(d+=" "+e.addClass),e.removeClass&&(d+=" "+e.removeClass));var r=e.addClass,K=e.removeClass,C=s(d),E,f;if(C.length){var F,G;"leave"==b?(G="leave",F="afterLeave"):(G="before"+b.charAt(0).toUpperCase()+b.substr(1),F=b);"enter"!==b&&"move"!==b&&(E=B(a,b,e,C,G));f=B(a,b,e,C,F)}if(E||f)return{start:function(){function b(c){n= +!0;t();ca(a,e);g.complete(c)}var d,k=[];E&&k.push(function(a){d=E(a)});k.length?k.push(function(a){t();a(!0)}):t();f&&k.push(function(a){d=f(a)});var n=!1,g=new c({end:function(){n||((d||H)(void 0),b(void 0))},cancel:function(){n||((d||H)(!0),b(!0))}});c.chain(k,b);return g}}}}]}]).provider("$$animateJsDriver",["$$animationProvider",function(a){a.drivers.push("$$animateJsDriver");this.$get=["$$animateJs","$$AnimateRunner",function(a,c){function d(c){return a(c.element,c.event,c.classes,c.options)} +return function(a){if(a.from&&a.to){var b=d(a.from),n=d(a.to);if(b||n)return{start:function(){function a(){return function(){u(d,function(a){a.end()})}}var d=[];b&&d.push(b.start());n&&d.push(n.start());c.all(d,function(a){e.complete(a)});var e=new c({end:a(),cancel:a()});return e}}}else return d(a)}}]}])})(window,window.angular); //# sourceMappingURL=angular-animate.min.js.map /*! @@ -329,20 +391,20 @@ c,d.to)},removeClass:function(a,b,c,d){d=d||{};return T("removeClass",a,q(b,"-re */ /* - AngularJS v1.3.13 - (c) 2010-2014 Google, Inc. http://angularjs.org + AngularJS v1.4.3 + (c) 2010-2015 Google, Inc. http://angularjs.org License: MIT */ -(function(n,h,p){'use strict';function E(a){var d=[];s(d,h.noop).chars(a);return d.join("")}function g(a){var d={};a=a.split(",");var c;for(c=0;c<a.length;c++)d[a[c]]=!0;return d}function F(a,d){function c(a,b,c,l){b=h.lowercase(b);if(t[b])for(;f.last()&&u[f.last()];)e("",f.last());v[b]&&f.last()==b&&e("",b);(l=w[b]||!!l)||f.push(b);var m={};c.replace(G,function(a,b,d,c,e){m[b]=r(d||c||e||"")});d.start&&d.start(b,m,l)}function e(a,b){var c=0,e;if(b=h.lowercase(b))for(c=f.length-1;0<=c&&f[c]!=b;c--); -if(0<=c){for(e=f.length-1;e>=c;e--)d.end&&d.end(f[e]);f.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,k,f=[],m=a,l;for(f.last=function(){return f[f.length-1]};a;){l="";k=!0;if(f.last()&&x[f.last()])a=a.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*"+f.last()+"[^>]*>","i"),function(a,b){b=b.replace(H,"$1").replace(I,"$1");d.chars&&d.chars(r(b));return""}),e("",f.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e",b)===b&&(d.comment&& -d.comment(a.substring(4,b)),a=a.substring(b+3),k=!1);else if(y.test(a)){if(b=a.match(y))a=a.replace(b[0],""),k=!1}else if(J.test(a)){if(b=a.match(z))a=a.substring(b[0].length),b[0].replace(z,e),k=!1}else K.test(a)&&((b=a.match(A))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(A,c)),k=!1):(l+="<",a=a.substring(1)));k&&(b=a.indexOf("<"),l+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),d.chars&&d.chars(r(l)))}if(a==m)throw L("badparse",a);m=a}e()}function r(a){if(!a)return"";var d=M.exec(a);a=d[1]; -var c=d[3];if(d=d[2])q.innerHTML=d.replace(/</g,"<"),d="textContent"in q?q.textContent:q.innerText;return a+d+c}function B(a){return a.replace(/&/g,"&").replace(N,function(a){var c=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(c-55296)+(a-56320)+65536)+";"}).replace(O,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"<").replace(/>/g,">")}function s(a,d){var c=!1,e=h.bind(a,a.push);return{start:function(a,k,f){a=h.lowercase(a);!c&&x[a]&&(c=a);c||!0!==C[a]||(e("<"),e(a), -h.forEach(k,function(c,f){var k=h.lowercase(f),g="img"===a&&"src"===k||"background"===k;!0!==P[k]||!0===D[k]&&!d(c,g)||(e(" "),e(f),e('="'),e(B(c)),e('"'))}),e(f?"/>":">"))},end:function(a){a=h.lowercase(a);c||!0!==C[a]||(e("</"),e(a),e(">"));a==c&&(c=!1)},chars:function(a){c||e(B(a))}}}var L=h.$$minErr("$sanitize"),A=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,z=/^<\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, -K=/^</,J=/^<\//,H=/\x3c!--(.*?)--\x3e/g,y=/<!DOCTYPE([^>]*?)>/i,I=/<!\[CDATA\[(.*?)]]\x3e/g,N=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,O=/([^\#-~| |!])/g,w=g("area,br,col,hr,img,wbr");n=g("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr");p=g("rp,rt");var v=h.extend({},p,n),t=h.extend({},n,g("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),u=h.extend({},p,g("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")); -n=g("animate,animateColor,animateMotion,animateTransform,circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,stop,svg,switch,text,title,tspan,use");var x=g("script,style"),C=h.extend({},w,t,u,v,n),D=g("background,cite,href,longdesc,src,usemap,xlink:href");n=g("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,target,title,type,valign,value,vspace,width"); -p=g("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan"); -var P=h.extend({},D,p,n),q=document.createElement("pre"),M=/^(\s*)([\s\S]*?)(\s*)$/;h.module("ngSanitize",[]).provider("$sanitize",function(){this.$get=["$$sanitizeUri",function(a){return function(d){var c=[];F(d,s(c,function(c,b){return!/^unsafe/.test(a(c,b))}));return c.join("")}}]});h.module("ngSanitize").filter("linky",["$sanitize",function(a){var d=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/,c=/^mailto:/;return function(e,b){function k(a){a&&g.push(E(a))} -function f(a,c){g.push("<a ");h.isDefined(b)&&g.push('target="',b,'" ');g.push('href="',a.replace(/"/g,"""),'">');k(c);g.push("</a>")}if(!e)return e;for(var m,l=e,g=[],n,p;m=l.match(d);)n=m[0],m[2]||m[4]||(n=(m[3]?"http://":"mailto:")+n),p=m.index,k(l.substr(0,p)),f(n,m[0].replace(c,"")),l=l.substring(p+m[0].length);k(l);return a(g.join(""))}}])})(window,window.angular); +(function(n,h,p){'use strict';function E(a){var f=[];r(f,h.noop).chars(a);return f.join("")}function g(a,f){var d={},c=a.split(","),b;for(b=0;b<c.length;b++)d[f?h.lowercase(c[b]):c[b]]=!0;return d}function F(a,f){function d(a,b,d,l){b=h.lowercase(b);if(s[b])for(;e.last()&&t[e.last()];)c("",e.last());u[b]&&e.last()==b&&c("",b);(l=v[b]||!!l)||e.push(b);var m={};d.replace(G,function(b,a,f,c,d){m[a]=q(f||c||d||"")});f.start&&f.start(b,m,l)}function c(b,a){var c=0,d;if(a=h.lowercase(a))for(c=e.length- +1;0<=c&&e[c]!=a;c--);if(0<=c){for(d=e.length-1;d>=c;d--)f.end&&f.end(e[d]);e.length=c}}"string"!==typeof a&&(a=null===a||"undefined"===typeof a?"":""+a);var b,k,e=[],m=a,l;for(e.last=function(){return e[e.length-1]};a;){l="";k=!0;if(e.last()&&w[e.last()])a=a.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*"+e.last()+"[^>]*>","i"),function(a,b){b=b.replace(H,"$1").replace(I,"$1");f.chars&&f.chars(q(b));return""}),c("",e.last());else{if(0===a.indexOf("\x3c!--"))b=a.indexOf("--",4),0<=b&&a.lastIndexOf("--\x3e", +b)===b&&(f.comment&&f.comment(a.substring(4,b)),a=a.substring(b+3),k=!1);else if(x.test(a)){if(b=a.match(x))a=a.replace(b[0],""),k=!1}else if(J.test(a)){if(b=a.match(y))a=a.substring(b[0].length),b[0].replace(y,c),k=!1}else K.test(a)&&((b=a.match(z))?(b[4]&&(a=a.substring(b[0].length),b[0].replace(z,d)),k=!1):(l+="<",a=a.substring(1)));k&&(b=a.indexOf("<"),l+=0>b?a:a.substring(0,b),a=0>b?"":a.substring(b),f.chars&&f.chars(q(l)))}if(a==m)throw L("badparse",a);m=a}c()}function q(a){if(!a)return"";A.innerHTML= +a.replace(/</g,"<");return A.textContent}function B(a){return a.replace(/&/g,"&").replace(M,function(a){var d=a.charCodeAt(0);a=a.charCodeAt(1);return"&#"+(1024*(d-55296)+(a-56320)+65536)+";"}).replace(N,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"<").replace(/>/g,">")}function r(a,f){var d=!1,c=h.bind(a,a.push);return{start:function(a,k,e){a=h.lowercase(a);!d&&w[a]&&(d=a);d||!0!==C[a]||(c("<"),c(a),h.forEach(k,function(d,e){var k=h.lowercase(e),g="img"===a&&"src"===k|| +"background"===k;!0!==O[k]||!0===D[k]&&!f(d,g)||(c(" "),c(e),c('="'),c(B(d)),c('"'))}),c(e?"/>":">"))},end:function(a){a=h.lowercase(a);d||!0!==C[a]||(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(B(a))}}}var L=h.$$minErr("$sanitize"),z=/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,y=/^<\/\s*([\w:-]+)[^>]*>/,G=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,K=/^</,J=/^<\//,H=/\x3c!--(.*?)--\x3e/g,x=/<!DOCTYPE([^>]*?)>/i, +I=/<!\[CDATA\[(.*?)]]\x3e/g,M=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,N=/([^\#-~| |!])/g,v=g("area,br,col,hr,img,wbr");n=g("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr");p=g("rp,rt");var u=h.extend({},p,n),s=h.extend({},n,g("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),t=h.extend({},p,g("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")); +n=g("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,stop,svg,switch,text,title,tspan,use");var w=g("script,style"),C=h.extend({},v,s,t,u,n),D=g("background,cite,href,longdesc,src,usemap,xlink:href");n=g("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,valign,value,vspace,width"); +p=g("accent-height,accumulate,additive,alphabetic,arabic-form,ascent,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan", +!0);var O=h.extend({},D,p,n),A=document.createElement("pre");h.module("ngSanitize",[]).provider("$sanitize",function(){this.$get=["$$sanitizeUri",function(a){return function(f){var d=[];F(f,r(d,function(c,b){return!/^unsafe/.test(a(c,b))}));return d.join("")}}]});h.module("ngSanitize").filter("linky",["$sanitize",function(a){var f=/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,d=/^mailto:/i;return function(c,b){function k(a){a&&g.push(E(a))}function e(a, +c){g.push("<a ");h.isDefined(b)&&g.push('target="',b,'" ');g.push('href="',a.replace(/"/g,"""),'">');k(c);g.push("</a>")}if(!c)return c;for(var m,l=c,g=[],n,p;m=l.match(f);)n=m[0],m[2]||m[4]||(n=(m[3]?"http://":"mailto:")+n),p=m.index,k(l.substr(0,p)),e(n,m[0].replace(d,"")),l=l.substring(p+m[0].length);k(l);return a(g.join(""))}}])})(window,window.angular); //# sourceMappingURL=angular-sanitize.min.js.map /*! @@ -367,10 +429,10 @@ function f(a,c){g.push("<a ");h.isDefined(b)&&g.push('target="',b,'" ');g.push(' */ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -380,7 +442,7 @@ function f(a,c){g.push("<a ");h.isDefined(b)&&g.push('target="',b,'" ');g.push(' * */ -!function(){function e(e,t,n,i,o,r){function a(i,a,c,s,l){function d(){N.resizeRequiresRefresh(w.__clientWidth,w.__clientHeight)&&g()}function f(){var e;return e={dataLength:0,width:0,height:0,resizeRequiresRefresh:function(t,n){var i=e.dataLength&&t&&n&&(t!==e.width||n!==e.height);return e.width=t,e.height=n,!!i},dataChangeRequiresRefresh:function(t){var n=t.length>0||t.length<e.dataLength;return e.dataLength=t.length,!!n}}}function h(){return T||(T=new e({afterItemsNode:M[0],containerNode:y,heightData:A,widthData:E,forceRefreshImages:!(!u(c.forceRefreshImages)||"false"===c.forceRefreshImages),keyExpression:B,renderBuffer:_,scope:i,scrollView:s.scrollView,transclude:l}))}function p(){var e=angular.element(w.__content.querySelector(".collection-repeat-after-container"));if(!e.length){var t=!1,n=[].filter.call(w.__content.childNodes,function(e){return ionic.DomUtil.contains(e,y)?(t=!0,!1):t});e=angular.element('<span class="collection-repeat-after-container">'),w.options.scrollingX&&e.addClass("horizontal"),e.append(n),w.__content.appendChild(e[0])}return e}function v(){R?m(R,A):A.computed=!0,L?m(L,E):E.computed=!0}function g(){var e=P.length>0;if(e&&(A.computed||E.computed)&&$(),e&&A.computed){if(A.value=V.height,!A.value)throw new Error('collection-repeat tried to compute the height of repeated elements "'+k+'", but was unable to. Please provide the "item-height" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!A.dynamic&&A.getValue&&(A.value=A.getValue());if(e&&E.computed){if(E.value=V.width,!E.value)throw new Error('collection-repeat tried to compute the width of repeated elements "'+k+'", but was unable to. Please provide the "item-width" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!E.dynamic&&E.getValue&&(E.value=E.getValue());h().refreshLayout()}function m(e,n){if(e){var i;try{i=t(e)}catch(o){e.trim().match(/\d+(px|%)$/)&&(e='"'+e+'"'),i=t(e)}var r=e.replace(/(\'|\"|px|%)/g,"").trim(),a=r.length&&!/([a-zA-Z]|\$|:|\?)/.test(r);if(n.attrValue=e,a){var c=parseInt(i());if(e.indexOf("%")>-1){var s=c/100;n.getValue=n===A?function(){return Math.floor(s*w.__clientHeight)}:function(){return Math.floor(s*w.__clientWidth)}}else n.value=c}else n.dynamic=!0,n.getValue=n===A?function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseInt(n)/100*w.__clientHeight):parseInt(n)}:function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseInt(n)/100*w.__clientWidth):parseInt(n)}}}function $(){H||l(O=i.$new(),function(e){e[0].removeAttribute("collection-repeat"),H=e[0]}),O[B]=(x(i)||[])[0],o.$$phase||O.$digest(),y.appendChild(H);var e=n.getComputedStyle(H);V.width=parseInt(e.width),V.height=parseInt(e.height),y.removeChild(H)}var w=s.scrollView,b=a[0],y=angular.element('<div class="collection-repeat-container">')[0];if(b.parentNode.replaceChild(y,b),w.options.scrollingX&&w.options.scrollingY)throw new Error("collection-repeat expected a parent x or y scrollView, not an xy scrollView.");var k=c.collectionRepeat,C=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!C)throw new Error("collection-repeat expected expression in form of '_item_ in _collection_[ track by _id_]' but got '"+c.collectionRepeat+"'.");var T,B=C[1],I=C[2],x=t(I),A={},E={},V={},P=[],D=c.itemRenderBuffer||c.collectionBufferSize,_=angular.isDefined(D)?parseInt(D):S,R=c.itemHeight||c.collectionItemHeight,L=c.itemWidth||c.collectionItemWidth,M=p(),N=f();v(),s.$element.on("scroll-resize",g),angular.element(n).on("resize",d);var z=o.$on("$ionicExposeAside",ionic.animationFrameThrottle(function(){s.scrollView.resize(),d()}));r(g,0,!1),i.$watchCollection(x,function(e){if(P=e||(e=[]),!angular.isArray(e))throw new Error("collection-repeat expected an array for '"+I+"', but got a "+typeof value);i.$$postDigest(function(){h().setData(P),N.dataChangeRequiresRefresh(P)&&g()})}),i.$on("$destroy",function(){angular.element(n).off("resize",d),z(),s.$element&&s.$element.off("scroll-resize",g),H&&H.parentNode&&H.parentNode.removeChild(H),O&&O.$destroy(),O=H=null,T&&T.destroy(),T=null});var H,O}return{restrict:"A",priority:1e3,transclude:"element",$$tlb:!0,require:"^^$ionicScroll",link:a}}function t(e,t,n){var i={primaryPos:0,secondaryPos:0,primarySize:0,secondarySize:0,rowPrimarySize:0};return function(o){function r(){return a(!0)}function a(t){if(!a.destroyed){var n,o,r,l,u,d=ee.getScrollValue(),f=d+ee.scrollPrimarySize;ee.updateRenderRange(d,f),W=Math.max(0,W-T),F=Math.min(A.length-1,F+T);for(n in Z)(W>n||n>F)&&(r=Z[n],delete Z[n],j.push(r),r.isShown=!1);for(n=W;F>=n;n++)n>=A.length||Z[n]&&!t||(r=Z[n]||(Z[n]=j.length?j.pop():G.length?G.shift():new s),K.push(r),r.isShown=!0,u=r.scope,u.$index=n,u[C]=A[n],u.$first=0===n,u.$last=n===A.length-1,u.$middle=!(u.$first||u.$last),u.$odd=!(u.$even=0===(1&n)),u.$$disconnected&&ionic.Utils.reconnectScope(r.scope),l=ee.getDimensions(n),(r.secondaryPos!==l.secondaryPos||r.primaryPos!==l.primaryPos)&&(r.node.style[ionic.CSS.TRANSFORM]=H.replace(N,r.primaryPos=l.primaryPos).replace(z,r.secondaryPos=l.secondaryPos)),(r.secondarySize!==l.secondarySize||r.primarySize!==l.primarySize)&&(r.node.style.cssText=r.node.style.cssText.replace(y,O.replace(N,(r.primarySize=l.primarySize)+1).replace(z,r.secondarySize=l.secondarySize))));for(F===A.length-1&&(l=ee.getDimensions(A.length-1)||i,m.style[ionic.CSS.TRANSFORM]=H.replace(N,l.primaryPos+l.primarySize).replace(z,0));j.length;)r=j.pop(),r.scope.$broadcast("$collectionRepeatLeave"),ionic.Utils.disconnectScope(r.scope),G.push(r),r.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",r.primaryPos=r.secondaryPos=null;if(w)for(n=0,o=K.length;o>n&&(r=K[n]);n++)if(r.images)for(var h,p=0,v=r.images.length;v>p&&(h=r.images[p]);p++){var g=h.src;h.src=b,h.src=g}if(t)for(var $=e.$$phase;K.length;)r=K.pop(),$||r.scope.$digest();else c()}}function c(){var t;c.running||(c.running=!0,n(function(){for(var n=e.$$phase;K.length;)t=K.pop(),t.isShown&&(n||t.scope.$digest());c.running=!1}))}function s(){var e=this;this.scope=B.$new(),this.id="item"+J++,x(this.scope,function(t){e.element=t,e.element.data("$$collectionRepeatItem",e),e.node=t[0],e.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",e.node.style.cssText+=" height: 0px; width: 0px;",ionic.Utils.disconnectScope(e.scope),$.appendChild(e.node),e.images=t[0].getElementsByTagName("img")})}function l(){this.getItemPrimarySize=P,this.getItemSecondarySize=_,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollTop-q,I.__maxScrollTop-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientHeight,this.scrollSecondarySize=I.__clientWidth,this.estimatedPrimarySize=v,this.estimatedSecondarySize=g,this.estimatedItemsAcross=L&&Math.floor(I.__clientWidth/g)||1}}function u(){this.getItemPrimarySize=_,this.getItemSecondarySize=P,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollLeft-q,I.__maxScrollLeft-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientWidth,this.scrollSecondarySize=I.__clientHeight,this.estimatedPrimarySize=g,this.estimatedSecondarySize=v,this.estimatedItemsAcross=L&&Math.floor(I.__clientHeight/v)||1}}function d(){this.getEstimatedSecondaryPos=function(e){return e%this.estimatedItemsAcross*this.estimatedSecondarySize},this.getEstimatedPrimaryPos=function(e){return Math.floor(e/this.estimatedItemsAcross)*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)*this.estimatedItemsAcross}}function f(){this.getEstimatedSecondaryPos=function(){return 0},this.getEstimatedPrimaryPos=function(e){return e*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)}}function h(){this.getContentSize=function(){return this.getEstimatedPrimaryPos(A.length-1)+this.estimatedPrimarySize+q+U};var e={};this.getDimensions=function(t){return e.primaryPos=this.getEstimatedPrimaryPos(t),e.secondaryPos=this.getEstimatedSecondaryPos(t),e.primarySize=this.estimatedPrimarySize,e.secondarySize=this.estimatedSecondarySize,e},this.updateRenderRange=function(e,t){W=Math.max(0,this.getEstimatedIndex(e)),F=Math.min(A.length-1,this.getEstimatedIndex(t)+this.estimatedItemsAcross-1),Y=Math.max(0,this.getEstimatedPrimaryPos(W)),X=this.getEstimatedPrimaryPos(F)+this.estimatedPrimarySize}}function p(){function e(e){var t,r,a;for(t=Math.max(0,n);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.primarySize=o.getItemPrimarySize(t,A[t]),a.secondarySize=o.scrollSecondarySize,a.primaryPos=r.primaryPos+r.primarySize,a.secondaryPos=0}function t(e){var t,r,a;for(t=Math.max(n,0);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.secondarySize=Math.min(o.getItemSecondarySize(t,A[t]),o.scrollSecondarySize),a.secondaryPos=r.secondaryPos+r.secondarySize,0===t||a.secondaryPos+a.secondarySize>o.scrollSecondarySize?(a.secondaryPos=0,a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos+r.rowPrimarySize,a.rowStartIndex=t,a.rowPrimarySize=a.primarySize):(a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos,a.rowStartIndex=r.rowStartIndex,c[a.rowStartIndex].rowPrimarySize=a.rowPrimarySize=Math.max(c[a.rowStartIndex].rowPrimarySize,a.primarySize),a.rowPrimarySize=Math.max(a.primarySize,a.rowPrimarySize))}var n,o=this,r=ionic.debounce(Q,25,!0),a=L?t:e,c=[];this.getContentSize=function(){var e=c[n]||i;return(e.primaryPos+e.primarySize||0)+this.getEstimatedPrimaryPos(A.length-n-1)+q+U},this.onDestroy=function(){c.length=0},this.onRefreshData=function(){var e,t;for(e=c.length,t=A.length;t>e;e++)c.push({});n=-1},this.onRefreshLayout=function(){n=-1},this.getDimensions=function(e){return e=Math.min(e,A.length-1),e>n&&(e>.9*A.length?(a(A.length-1),n=A.length-1,Q()):(a(e),n=e,r())),c[e]};var s=-1,l=-1;this.updateRenderRange=function(e,t){var n,i,o;if(this.getDimensions(2*this.getEstimatedIndex(t)),-1===s||0===e)n=0;else if(e>=l)for(n=s,i=A.length;i>n&&!((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>=e);n++);else for(n=s;n>=0;n--)if((o=this.getDimensions(n))&&o.primaryPos<=e){n=L?o.rowStartIndex:n;break}W=Math.min(Math.max(0,n),A.length-1),Y=-1!==W?this.getDimensions(W).primaryPos:-1;var r;for(n=W+1,i=A.length;i>n;n++)if((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>t){if(L)for(r=o;i-1>n&&(o=this.getDimensions(n+1)).primaryPos===r.primaryPos;)n++;break}F=Math.min(n,A.length-1),X=-1!==F?(o=this.getDimensions(F)).primaryPos+(o.rowPrimarySize||o.primarySize):-1,l=e,s=W}}var v,g,m=o.afterItemsNode,$=o.containerNode,w=o.forceRefreshImages,S=o.heightData,k=o.widthData,C=o.keyExpression,T=o.renderBuffer,B=o.scope,I=o.scrollView,x=o.transclude,A=[],E={},V=S.getValue||function(){return S.value},P=function(e,t){return E[C]=t,E.$index=e,V(B,E)},D=k.getValue||function(){return k.value},_=function(e,t){return E[C]=t,E.$index=e,D(B,E)},R=!!I.options.scrollingY,L=R?k.dynamic||k.value!==I.__clientWidth:S.dynamic||S.value!==I.__clientHeight,M=!S.dynamic&&!k.dynamic,N="PRIMARY",z="SECONDARY",H=R?"translate3d(SECONDARYpx,PRIMARYpx,0)":"translate3d(PRIMARYpx,SECONDARYpx,0)",O=R?"height: PRIMARYpx; width: SECONDARYpx;":"height: SECONDARYpx; width: PRIMARYpx;",q=0,U=0,W=-1,F=-1,X=-1,Y=-1,G=[],j=[],K=[],Z={},J=0,Q=R?function(){I.setDimensions(null,null,null,ee.getContentSize(),!0)}:function(){I.setDimensions(null,null,ee.getContentSize(),null,!0)},ee=R?new l:new u;(L?d:f).call(ee),(M?h:p).call(ee);var te=R?"getContentHeight":"getContentWidth",ne=I.options[te];I.options[te]=angular.bind(ee,ee.getContentSize),I.__$callback=I.__callback,I.__callback=function(e,t,n,i){var o=ee.getScrollValue();(-1===W||o+ee.scrollPrimarySize>X||Y>o)&&a(),I.__$callback(e,t,n,i)};var ie=!1,oe=!1;this.refreshLayout=function(){A.length?(v=P(0,A[0]),g=_(0,A[0])):(v=100,g=100);var e=getComputedStyle(m)||{},n=m.firstElementChild&&getComputedStyle(m.firstElementChild)||{},i=m.lastElementChild&&getComputedStyle(m.lastElementChild)||{};U=(parseInt(e[R?"height":"width"])||0)+(n&&parseInt(n[R?"marginTop":"marginLeft"])||0)+(i&&parseInt(i[R?"marginBottom":"marginRight"])||0),q=0;var o=$;do q+=o[R?"offsetTop":"offsetLeft"];while(ionic.DomUtil.contains(I.__content,o=o.offsetParent));var a=$.previousElementSibling,c=a?t.getComputedStyle(a):{},l=parseInt(c[R?"marginBottom":"marginRight"]||0);if($.style[ionic.CSS.TRANSFORM]=H.replace(N,-l).replace(z,0),q-=l,I.__clientHeight&&I.__clientWidth||(I.__clientWidth=I.__container.clientWidth,I.__clientHeight=I.__container.clientHeight),(ee.onRefreshLayout||angular.noop)(),ee.refreshDirection(),Q(),!ie)for(var u=Math.max(20,3*T),d=0;u>d;d++)G.push(new s);ie=!0,ie&&oe&&((I.__scrollLeft>I.__maxScrollLeft||I.__scrollTop>I.__maxScrollTop)&&I.resize(),r(!0))},this.setData=function(e){A=e,(ee.onRefreshData||angular.noop)(),oe=!0},this.destroy=function(){a.destroyed=!0,G.forEach(function(e){e.scope.$destroy(),e.scope=e.element=e.node=e.images=null}),G.length=K.length=j.length=0,Z={},I.options[te]=ne,I.__callback=I.__$callback,I.resize(),(ee.onDestroy||angular.noop)()}}}function n(e){return["$ionicGesture","$parse",function(t,n){var i=e.substr(2).toLowerCase();return function(o,r,a){var c=n(a[e]),s=function(e){o.$apply(function(){c(o,{$event:e})})},l=t.on(i,s,r);o.$on("$destroy",function(){t.off(l,i,s)})}}]}function i(){return["$ionicScrollDelegate",function(e){return{restrict:"E",link:function(t,n,i){function o(t){for(var i=3,o=t.target;i--&&o;){if(o.classList.contains("button")||o.tagName.match(/input|textarea|select/i)||o.isContentEditable)return;o=o.parentNode}var r=t.gesture&&t.gesture.touches[0]||t.detail.touches[0],a=n[0].getBoundingClientRect();ionic.DomUtil.rectContains(r.pageX,r.pageY,a.left,a.top-20,a.left+a.width,a.top+a.height)&&e.scrollTop(!0)}"true"!=i.noTapScroll&&(ionic.on("tap",o,n[0]),t.$on("$destroy",function(){ionic.off("tap",o,n[0])}))}}}]}function o(e){return["$document","$timeout",function(t,n){return{restrict:"E",controller:"$ionicHeaderBar",compile:function(i){function o(t,n,i,o){e?(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subheader");t.$hasHeader=n&&!i,t.$hasSubheader=n&&i,t.$emit("$ionicSubheader",t.$hasSubheader)}),t.$on("$destroy",function(){delete t.$hasHeader,delete t.$hasSubheader}),o.align(),t.$on("$ionicHeader.align",function(){ionic.requestAnimationFrame(function(){o.align()})})):(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subfooter");t.$hasFooter=n&&!i,t.$hasSubfooter=n&&i}),t.$on("$destroy",function(){delete t.$hasFooter,delete t.$hasSubfooter}),t.$watch("$hasTabs",function(e){n.toggleClass("has-tabs",!!e)}))}return i.addClass(e?"bar bar-header":"bar bar-footer"),n(function(){e&&t[0].getElementsByClassName("tabs-top").length&&i.addClass("has-tabs-top")}),{pre:o}}}}]}function r(e){return e.clientHeight}function a(e){e.stopPropagation()}var c=angular.module("ionic",["ngAnimate","ngSanitize","ui.router"]),s=angular.extend,l=angular.forEach,u=angular.isDefined,d=angular.isNumber,f=angular.isString,h=angular.element,p=angular.noop;c.factory("$ionicActionSheet",["$rootScope","$compile","$animate","$timeout","$ionicTemplateLoader","$ionicPlatform","$ionicBody","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c){function l(o){function l(e){e&&/icon/.test(e)&&(u.$actionSheetHasIcon=!0)}var u=e.$new(!0);s(u,{cancel:p,destructiveButtonClicked:p,buttonClicked:p,$deregisterBackButton:p,buttons:[],cancelOnStateChange:!0},o||{});for(var d=0;d<u.buttons.length;d++)l(u.buttons[d].text);l(u.cancelText),l(u.destructiveText);var f=u.element=t('<ion-action-sheet ng-class="cssClass" buttons="buttons"></ion-action-sheet>')(u),v=h(f[0].querySelector(".action-sheet-wrapper")),g=u.cancelOnStateChange?e.$on("$stateChangeSuccess",function(){u.cancel()}):p;return u.removeSheet=function(e){u.removed||(u.removed=!0,v.removeClass("action-sheet-up"),i(function(){a.removeClass("action-sheet-open")},400),u.$deregisterBackButton(),g(),n.removeClass(f,"active").then(function(){u.$destroy(),f.remove(),u.cancel.$scope=v=null,(e||p)()}))},u.showSheet=function(e){u.removed||(a.append(f).addClass("action-sheet-open"),n.addClass(f,"active").then(function(){u.removed||(e||p)()}),i(function(){u.removed||v.addClass("action-sheet-up")},20,!1))},u.$deregisterBackButton=r.registerBackButtonAction(function(){i(u.cancel)},c.actionSheet),u.cancel=function(){u.removeSheet(o.cancel)},u.buttonClicked=function(e){o.buttonClicked(e,o.buttons[e])===!0&&u.removeSheet()},u.destructiveButtonClicked=function(){o.destructiveButtonClicked()===!0&&u.removeSheet()},u.showSheet(),u.cancel.$scope=u,u.cancel}return{show:l}}]),h.prototype.addClass=function(e){var t,n,i,o,r,a;if(e&&"ng-scope"!=e&&"ng-isolate-scope"!=e)for(t=0;t<this.length;t++)if(o=this[t],o.setAttribute)if(e.indexOf(" ")<0&&o.classList.add)o.classList.add(e);else{for(a=(" "+(o.getAttribute("class")||"")+" ").replace(/[\n\t]/g," "),r=e.split(" "),n=0;n<r.length;n++)i=r[n].trim(),-1===a.indexOf(" "+i+" ")&&(a+=i+" ");o.setAttribute("class",a.trim())}return this},h.prototype.removeClass=function(e){var t,n,i,o,r;if(e)for(t=0;t<this.length;t++)if(r=this[t],r.getAttribute)if(e.indexOf(" ")<0&&r.classList.remove)r.classList.remove(e);else for(i=e.split(" "),n=0;n<i.length;n++)o=i[n],r.setAttribute("class",(" "+(r.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+o.trim()+" "," ").trim());return this},c.factory("$ionicBackdrop",["$document","$timeout","$$rAF",function(e,t,n){function i(){c++,1===c&&(a.addClass("visible"),n(function(){c>=1&&a.addClass("active")}))}function o(){1===c&&(a.removeClass("active"),t(function(){0===c&&a.removeClass("visible")},400,!1)),c=Math.max(0,c-1)}function r(){return a}var a=h('<div class="backdrop">'),c=0;return e[0].body.appendChild(a[0]),{retain:i,release:o,getElement:r,_element:a}}]),c.factory("$ionicBind",["$parse","$interpolate",function(e,t){var n=/^\s*([@=&])(\??)\s*(\w*)\s*$/;return function(i,o,r){l(r||{},function(r,a){var c,s,l=r.match(n)||[],u=l[3]||a,d=l[1];switch(d){case"@":if(!o[u])return;o.$observe(u,function(e){i[a]=e}),o[u]&&(i[a]=t(o[u])(i));break;case"=":if(!o[u])return;s=i.$watch(o[u],function(e){i[a]=e}),i.$on("$destroy",s);break;case"&":if(o[u]&&o[u].match(RegExp(a+"(.*?)")))throw new Error('& expression binding "'+a+'" looks like it will recursively call "'+o[u]+'" and cause a stack overflow! Please choose a different scopeName.');c=e(o[u]),i[a]=function(e){return c(i,e)}}})}}]),c.factory("$ionicBody",["$document",function(e){return{addClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.add(arguments[t]);return this},removeClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.remove(arguments[t]);return this},enableClass:function(e){var t=Array.prototype.slice.call(arguments).slice(1);return e?this.addClass.apply(this,t):this.removeClass.apply(this,t),this},append:function(t){return e[0].body.appendChild(t.length?t[0]:t),this},get:function(){return e[0].body}}}]),c.factory("$ionicClickBlock",["$document","$ionicBody","$timeout",function(e,t,n){function i(e){e.preventDefault(),e.stopPropagation()}function o(){s&&(a?a.classList.remove(l):(a=e[0].createElement("div"),a.className="click-block",t.append(a),a.addEventListener("touchstart",i),a.addEventListener("mousedown",i)),s=!1)}function r(){a&&a.classList.add(l)}var a,c,s,l="click-block-hide";return{show:function(e){s=!0,n.cancel(c),c=n(this.hide,e||310,!1),o()},hide:function(){s=!1,n.cancel(c),r()}}}]),c.factory("$ionicGesture",[function(){return{on:function(e,t,n,i){return window.ionic.onGesture(e,t,n[0],i)},off:function(e,t,n){return window.ionic.offGesture(e,t,n)}}}]),c.factory("$ionicHistory",["$rootScope","$state","$location","$window","$timeout","$ionicViewSwitcher","$ionicNavViewDelegate",function(e,t,n,i,o,r,a){function c(e){return e?L.views[e]:null}function l(e){return e?c(e.backViewId):null}function d(e){return e?c(e.forwardViewId):null}function f(e){return e?L.histories[e]:null}function h(e){var t=p(e);return L.histories[t.historyId]||(L.histories[t.historyId]={historyId:t.historyId,parentHistoryId:p(t.scope.$parent).historyId,stack:[],cursor:-1}),f(t.historyId)}function p(t){for(var n=t;n;){if(n.hasOwnProperty("$historyId"))return{historyId:n.$historyId,scope:n};n=n.$parent}return{historyId:"root",scope:e}}function v(e){L.currentView=c(e),L.backView=l(L.currentView),L.forwardView=d(L.currentView)}function g(){var e;if(t&&t.current&&t.current.name){if(e=t.current.name,t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&t.params[n]&&(e+="_"+n+"="+t.params[n]);return e}return ionic.Utils.nextUid()}function m(){var e;if(t&&t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&(e=e||{},e[n]=t.params[n]);return e}function $(e){return e&&e.length&&/ion-side-menus|ion-tabs/i.test(e[0].tagName)}function w(e,t){return t&&t.$$state&&t.$$state.self.canSwipeBack===!1?!1:e&&"false"===e.attr("can-swipe-back")?!1:!0}var b,y,S,k,C,T="initialView",B="newView",I="moveBack",x="moveForward",A="back",E="forward",V="enter",P="exit",D="swap",_="none",R=0,L={histories:{root:{historyId:"root",parentHistoryId:null,stack:[],cursor:-1}},views:{},backView:null,forwardView:null,currentView:null},M=function(){};return M.prototype.initialize=function(e){if(e){for(var t in e)this[t]=e[t];return this}return null},M.prototype.go=function(){if(this.stateName)return t.go(this.stateName,this.stateParams);if(this.url&&this.url!==n.url()){if(L.backView===this)return i.history.go(-1);if(L.forwardView===this)return i.history.go(1);n.url(this.url)}return null},M.prototype.destroy=function(){this.scope&&(this.scope.$destroy&&this.scope.$destroy(),this.scope=null)},{register:function(e,t){var i,a,s,u=g(),d=h(e),$=L.currentView,M=L.backView,N=L.forwardView,z=null,H=null,O=_,q=d.historyId,U=n.url();if(b!==u&&(b=u,R++),C)z=C.viewId,H=C.action,O=C.direction,C=null;else if(M&&M.stateId===u)z=M.viewId,q=M.historyId,H=I,M.historyId===$.historyId?O=A:$&&(O=P,i=f(M.historyId),i&&i.parentHistoryId===$.historyId?O=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(O=D)));else if(N&&N.stateId===u)z=N.viewId,q=N.historyId,H=x,N.historyId===$.historyId?O=E:$&&(O=P,$.historyId===d.parentHistoryId?O=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(O=D))),i=p(e),N.historyId&&i.scope&&(i.scope.$historyId=N.historyId,q=N.historyId);else if($&&$.historyId!==q&&d.cursor>-1&&d.stack.length>0&&d.cursor<d.stack.length&&d.stack[d.cursor].stateId===u){var W=d.stack[d.cursor];z=W.viewId,q=W.historyId,H=I,O=D,i=f($.historyId),i&&i.parentHistoryId===q?O=P:(i=f(q),i&&i.parentHistoryId===$.historyId&&(O=V)),i=c(W.backViewId),i&&W.historyId!==i.historyId&&(d.stack[d.cursor].backViewId=$.viewId)}else{if(s=r.createViewEle(t),this.isAbstractEle(s,t))return{action:"abstractView",direction:_,ele:s};if(z=ionic.Utils.nextUid(),$){if($.forwardViewId=z,H=B,N&&$.stateId!==N.stateId&&$.historyId===N.historyId&&(i=f(N.historyId))){for(a=i.stack.length-1;a>=N.index;a--){var F=i.stack[a];F&&F.destroy&&F.destroy(),i.stack.splice(a)}q=N.historyId}d.historyId===$.historyId?O=E:$.historyId!==d.historyId&&(O=V,i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId?O=D:(i=f(i.parentHistoryId),i&&i.historyId===d.historyId&&(O=P)))}else H=T;2>R&&(O=_),L.views[z]=this.createView({viewId:z,index:d.stack.length,historyId:d.historyId,backViewId:$&&$.viewId?$.viewId:null,forwardViewId:null,stateId:u,stateName:this.currentStateName(),stateParams:m(),url:U,canSwipeBack:w(s,t)}),d.stack.push(L.views[z])}if(S&&S(),o.cancel(k),y){if(y.disableAnimate&&(O=_),y.disableBack&&(L.views[z].backViewId=null),y.historyRoot){for(a=0;a<d.stack.length;a++)d.stack[a].viewId===z?(d.stack[a].index=0,d.stack[a].backViewId=d.stack[a].forwardViewId=null):delete L.views[d.stack[a].viewId];d.stack=[L.views[z]]}y=null}if(v(z),L.backView&&q==L.backView.historyId&&u==L.backView.stateId&&U==L.backView.url)for(a=0;a<d.stack.length;a++)if(d.stack[a].viewId==z){H="dupNav",O=_,a>0&&(d.stack[a-1].forwardViewId=null),L.forwardView=null,L.currentView.index=L.backView.index,L.currentView.backViewId=L.backView.backViewId,L.backView=l(L.backView),d.stack.splice(a,1);break}return d.cursor=L.currentView.index,{viewId:z,action:H,direction:O,historyId:q,enableBack:this.enabledBack(L.currentView),isHistoryRoot:0===L.currentView.index,ele:s}},registerHistory:function(e){e.$historyId=ionic.Utils.nextUid()},createView:function(e){var t=new M;return t.initialize(e)},getViewById:c,viewHistory:function(){return L},currentView:function(e){return arguments.length&&(L.currentView=e),L.currentView},currentHistoryId:function(){return L.currentView?L.currentView.historyId:null},currentTitle:function(e){return L.currentView?(arguments.length&&(L.currentView.title=e),L.currentView.title):void 0},backView:function(e){return arguments.length&&(L.backView=e),L.backView},backTitle:function(e){var t=e&&c(e.backViewId)||L.backView;return t&&t.title},forwardView:function(e){return arguments.length&&(L.forwardView=e),L.forwardView},currentStateName:function(){return t&&t.current?t.current.name:null},isCurrentStateNavView:function(e){return!!(t&&t.current&&t.current.views&&t.current.views[e])},goToHistoryRoot:function(e){if(e){var t=f(e);if(t&&t.stack.length){if(L.currentView&&L.currentView.viewId===t.stack[0].viewId)return;C={viewId:t.stack[0].viewId,action:I,direction:A},t.stack[0].go()}}},goBack:function(e){if(u(e)&&-1!==e){if(e>-1)return;var t=L.histories[this.currentHistoryId()],n=t.cursor+e+1;1>n&&(n=1),t.cursor=n,v(t.stack[n].viewId);for(var i=n-1,r=[],a=c(t.stack[i].forwardViewId);a&&(r.push(a.stateId||a.viewId),i++,!(i>=t.stack.length));)a=c(t.stack[i].forwardViewId);var s=this;r.length&&o(function(){s.clearCache(r)},600)}L.backView&&L.backView.go()},enabledBack:function(e){var t=l(e);return!(!t||t.historyId!==e.historyId)},clearHistory:function(){var e=L.histories,t=L.currentView;if(e)for(var n in e)e[n].stack&&(e[n].stack=[],e[n].cursor=-1),t&&t.historyId===n?(t.backViewId=t.forwardViewId=null,e[n].stack.push(t)):e[n].destroy&&e[n].destroy();for(var i in L.views)i!==t.viewId&&delete L.views[i];t&&v(t.viewId)},clearCache:function(e){o(function(){a._instances.forEach(function(t){t.clearCache(e)})})},nextViewOptions:function(t){return S&&S(),arguments.length&&(o.cancel(k),null===t?y=t:(y=y||{},s(y,t),y.expire&&(S=e.$on("$stateChangeSuccess",function(){k=o(function(){y=null},y.expire)})))),y},isAbstractEle:function(e,t){return t&&t.$$state&&t.$$state.self["abstract"]?!0:!(!e||!$(e)&&!$(e.children()))},isActiveScope:function(e){if(!e)return!1;for(var t,n=e,i=this.currentHistoryId();n;){if(n.$$disconnected)return!1;if(!t&&n.hasOwnProperty("$historyId")&&(t=!0),i){if(n.hasOwnProperty("$historyId")&&i==n.$historyId)return!0;if(n.hasOwnProperty("$activeHistoryId")&&i==n.$activeHistoryId){if(n.hasOwnProperty("$historyId"))return!0;if(!t)return!0}}t&&n.hasOwnProperty("$activeHistoryId")&&(t=!1),n=n.$parent}return i?"root"==i:!0}}}]).run(["$rootScope","$state","$location","$document","$ionicPlatform","$ionicHistory","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a){function c(e){var t=r.backView();return t?t.go():ionic.Platform.exitApp(),e.preventDefault(),!1}e.$on("$ionicView.beforeEnter",function(){ionic.keyboard&&ionic.keyboard.hide&&ionic.keyboard.hide()}),e.$on("$ionicHistory.change",function(e,i){if(!i)return null;var o=r.viewHistory(),a=i.historyId?o.histories[i.historyId]:null;if(a&&a.cursor>-1&&a.cursor<a.stack.length){var c=a.stack[a.cursor];return c.go(i)}!i.url&&i.uiSref&&(i.url=t.href(i.uiSref)),i.url&&(0===i.url.indexOf("#")&&(i.url=i.url.replace("#","")),i.url!==n.url()&&n.url(i.url))}),e.$ionicGoBack=function(e){r.goBack(e)},e.$on("$ionicView.afterEnter",function(e,t){t&&t.title&&(i[0].title=t.title)}),o.registerBackButtonAction(c,a.view)}]),c.provider("$ionicConfig",function(){function e(e,i){a.platform[e]=i,o.platform[e]={},t(a,a.platform[e]),n(a.platform[e],o.platform[e],"")}function t(e,n){for(var i in e)i!=r&&e.hasOwnProperty(i)&&(angular.isObject(e[i])?(u(n[i])||(n[i]={}),t(e[i],n[i])):u(n[i])||(n[i]=null))}function n(e,t,o){l(e,function(c,s){angular.isObject(e[s])?(t[s]={},n(e[s],t[s],o+"."+s)):t[s]=function(n){if(arguments.length)return e[s]=n,t;if(e[s]==r){var c=i(a.platform,ionic.Platform.platform()+o+"."+s);return c||c===!1?c:i(a.platform,"default"+o+"."+s)}return e[s]}})}function i(e,t){t=t.split(".");for(var n=0;n<t.length;n++){if(!e||!u(e[t[n]]))return null;e=e[t[n]]}return e}var o=this;o.platform={};var r="platform",a={views:{maxCache:r,forwardCache:r,transition:r,swipeBackEnabled:r,swipeBackHitWidth:r},navBar:{alignTitle:r,positionPrimaryButtons:r,positionSecondaryButtons:r,transition:r},backButton:{icon:r,text:r,previousTitleText:r},form:{checkbox:r,toggle:r},scrolling:{jsScrolling:r},spinner:{icon:r},tabs:{style:r,position:r},templates:{maxPrefetch:r},platform:{}};n(a,o,""),e("default",{views:{maxCache:10,forwardCache:!1,transition:"ios",swipeBackEnabled:!0,swipeBackHitWidth:45},navBar:{alignTitle:"center",positionPrimaryButtons:"left",positionSecondaryButtons:"right",transition:"view"},backButton:{icon:"ion-ios-arrow-back",text:"Back",previousTitleText:!0},form:{checkbox:"circle",toggle:"large"},scrolling:{jsScrolling:!0},spinner:{icon:"ios"},tabs:{style:"standard",position:"bottom"},templates:{maxPrefetch:30}}),e("ios",{}),e("android",{views:{transition:"android",swipeBackEnabled:!1},navBar:{alignTitle:"left",positionPrimaryButtons:"right",positionSecondaryButtons:"right"},backButton:{icon:"ion-android-arrow-back",text:!1,previousTitleText:!1},form:{checkbox:"square",toggle:"small"},spinner:{icon:"android"},tabs:{style:"striped",position:"top"}}),e("windowsphone",{spinner:{icon:"android"}}),o.transitions={views:{},navBar:{}},o.transitions.views.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,o.opacity=t,i>-1&&(o.boxShadow="0 0 10px rgba(0,0,0,"+(r.shouldAnimate?.45*i:.3)+")"),o[ionic.CSS.TRANSFORM]="translate3d("+n+"%,0,0)",ionic.DomUtil.cachedStyles(e,o)}var r={run:function(i){"forward"==n?(o(e,1,99*(1-i),1-i),o(t,1-.1*i,-33*i,-1)):"back"==n?(o(e,1-.1*(1-i),-33*(1-i),-1),o(t,1,100*i,1-i)):(o(e,1,0,-1),o(t,0,0,-1))},shouldAnimate:i&&("forward"==n||"back"==n)};return r},o.transitions.navBar.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=c.shouldAnimate?"":"0ms",o.opacity=1===t?"":t,e.setCss("buttons-left",o),e.setCss("buttons-right",o),e.setCss("back-button",o),o[ionic.CSS.TRANSFORM]="translate3d("+i+"px,0,0)",e.setCss("back-text",o),o[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e.setCss("title",o)}function r(e,t,n){if(e&&t){var i=(e.titleTextX()+e.titleWidth())*(1-n),r=t&&(t.titleTextX()-e.backButtonTextLeft())*(1-n)||0;o(e,n,i,r)}}function a(e,t,n){if(e&&t){var i=(-(e.titleTextX()-t.backButtonTextLeft())-e.titleLeftRight())*n;o(e,1-n,i,0)}}var c={run:function(n){var i=e.controller(),o=t&&t.controller();"back"==c.direction?(a(i,o,1-n),r(o,i,1-n)):(r(i,o,n),a(o,i,n))},direction:n,shouldAnimate:i&&("forward"==n||"back"==n)};return c},o.transitions.views.android=function(e,t,n,i){function o(e,t){var n={};n[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,n[ionic.CSS.TRANSFORM]="translate3d("+t+"%,0,0)",ionic.DomUtil.cachedStyles(e,n)}i=i&&("forward"==n||"back"==n);var r={run:function(i){"forward"==n?(o(e,99*(1-i)),o(t,-100*i)):"back"==n?(o(e,-100*(1-i)),o(t,100*i)):(o(e,0),o(t,0))},shouldAnimate:i};return r},o.transitions.navBar.android=function(e,t,n,i){function o(e,t){if(e){var n={};n.opacity=1===t?"":t,e.setCss("buttons-left",n),e.setCss("buttons-right",n),e.setCss("back-button",n),e.setCss("back-text",n),e.setCss("title",n)}}return{run:function(n){o(e.controller(),n),o(t&&t.controller(),1-n)},shouldAnimate:i&&("forward"==n||"back"==n)}},o.transitions.views.none=function(e,t){return{run:function(n){o.transitions.views.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.transitions.navBar.none=function(e,t){return{run:function(n){o.transitions.navBar.ios(e,t,!1,!1).run(n), -o.transitions.navBar.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.setPlatformConfig=e,o.$get=function(){return o}}).config(["$compileProvider",function(e){e.aHrefSanitizationWhitelist(/^\s*(https?|tel|ftp|mailto|file|ghttps?|ms-appx|x-wmapp0):/),e.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|x-wmapp0):|data:image\//)}]);var v='<div class="loading-container"><div class="loading"></div></div>',g="$ionicLoading instance.hide() has been deprecated. Use $ionicLoading.hide().",m="$ionicLoading instance.show() has been deprecated. Use $ionicLoading.show().",$="$ionicLoading instance.setContent() has been deprecated. Use $ionicLoading.show({ template: 'my content' }).";c.constant("$ionicLoadingConfig",{template:"<ion-spinner></ion-spinner>"}).factory("$ionicLoading",["$ionicLoadingConfig","$ionicBody","$ionicTemplateLoader","$ionicBackdrop","$timeout","$q","$log","$compile","$ionicPlatform","$rootScope","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c,l,u,d){function f(){return b||(b=n.compile({template:v,appendTo:t.get()}).then(function(e){return e.show=function(a){var s=a.templateUrl?n.load(a.templateUrl):r.when(a.template||a.content||"");e.scope=a.scope||e.scope,e.isShown||(e.hasBackdrop=!a.noBackdrop&&a.showBackdrop!==!1,e.hasBackdrop&&(i.retain(),i.getElement().addClass("backdrop-loading"))),a.duration&&(o.cancel(e.durationTimeout),e.durationTimeout=o(angular.bind(e,e.hide),+a.duration)),y(),y=l.registerBackButtonAction(p,d.loading),s.then(function(n){if(n){var i=e.element.children();i.html(n),c(i.contents())(e.scope)}e.isShown&&(e.element.addClass("visible"),ionic.requestAnimationFrame(function(){e.isShown&&(e.element.addClass("active"),t.addClass("loading-active"))}))}),e.isShown=!0},e.hide=function(){y(),e.isShown&&(e.hasBackdrop&&(i.release(),i.getElement().removeClass("backdrop-loading")),e.element.removeClass("active"),t.removeClass("loading-active"),setTimeout(function(){!e.isShown&&e.element.removeClass("visible")},200)),o.cancel(e.durationTimeout),e.isShown=!1},e})),b}function h(t){t=s({},e||{},t||{});var n=t.delay||t.showDelay||0;return S(),k(),t.hideOnStateChange&&(S=u.$on("$stateChangeSuccess",w),k=u.$on("$stateChangeError",w)),o.cancel(C),C=o(p,n),C.then(f).then(function(e){return e.show(t)}),{hide:function(){return a.error(g),w.apply(this,arguments)},show:function(){return a.error(m),h.apply(this,arguments)},setContent:function(e){return a.error($),f().then(function(t){t.show({template:e})})}}}function w(){S(),k(),o.cancel(C),f().then(function(e){e.hide()})}var b,y=p,S=p,k=p,C=r.when();return{show:h,hide:w,_getLoader:f}}]),c.factory("$ionicModal",["$rootScope","$ionicBody","$compile","$timeout","$ionicPlatform","$ionicTemplateLoader","$$q","$log","$ionicClickBlock","$window","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c,l,u,d){var f=ionic.views.Modal.inherit({initialize:function(e){ionic.views.Modal.prototype.initialize.call(this,e),this.animation=e.animation||"slide-in-up"},show:function(e){var n=this;if(n.scope.$$destroyed)return c.error("Cannot call "+n.viewType+".show() after remove(). Please create a new "+n.viewType+" instance."),a.when();l.show(600),m.add(n);var r=h(n.modalEl);n.el.classList.remove("hide"),i(function(){n._isShown&&t.addClass(n.viewType+"-open")},400,!1),n.el.parentElement||(r.addClass(n.animation),t.append(n.el));var s=r.data("$$ionicScrollController");return s&&s.resize(),e&&n.positionView&&(n.positionView(e,r),n._onWindowResize=function(){n._isShown&&n.positionView(e,r)},ionic.on("resize",n._onWindowResize,window)),r.addClass("ng-enter active").removeClass("ng-leave ng-leave-active"),n._isShown=!0,n._deregisterBackButton=o.registerBackButtonAction(n.hardwareBackButtonClose?angular.bind(n,n.hide):p,d.modal),ionic.views.Modal.prototype.show.call(n),i(function(){n._isShown&&(r.addClass("ng-enter-active"),ionic.trigger("resize"),n.scope.$parent&&n.scope.$parent.$broadcast(n.viewType+".shown",n),n.el.classList.add("active"),n.scope.$broadcast("$ionicHeader.align"))},20),i(function(){n._isShown&&n.$el.on("click",function(e){n.backdropClickToClose&&e.target===n.el&&m.isHighest(n)&&n.hide()})},400)},hide:function(){var e=this,n=h(e.modalEl);return l.show(600),m.remove(e),e.el.classList.remove("active"),n.addClass("ng-leave"),i(function(){e._isShown||n.addClass("ng-leave-active").removeClass("ng-enter ng-enter-active active")},20,!1),e.$el.off("click"),e._isShown=!1,e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".hidden",e),e._deregisterBackButton&&e._deregisterBackButton(),ionic.views.Modal.prototype.hide.call(e),e.positionView&&ionic.off("resize",e._onWindowResize,window),i(function(){t.removeClass(e.viewType+"-open"),e.el.classList.add("hide")},e.hideDelay||320)},remove:function(){var e=this;return e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".removed",e),e.hide().then(function(){e.scope.$destroy(),e.$el.remove()})},isShown:function(){return!!this._isShown}}),v=function(t,i){var o=i.scope&&i.scope.$new()||e.$new(!0);i.viewType=i.viewType||"modal",s(o,{$hasHeader:!1,$hasSubheader:!1,$hasFooter:!1,$hasSubfooter:!1,$hasTabs:!1,$hasTabsTop:!1});var r=n("<ion-"+i.viewType+">"+t+"</ion-"+i.viewType+">")(o);i.$el=r,i.el=r[0],i.modalEl=i.el.querySelector("."+i.viewType);var a=new f(i);return a.scope=o,i.scope||(o[i.viewType]=a),a},g=[],m={add:function(e){g.push(e)},remove:function(e){var t=g.indexOf(e);t>-1&&t<g.length&&g.splice(t,1)},isHighest:function(e){var t=g.indexOf(e);return t>-1&&t===g.length-1}};return{fromTemplate:function(e,t){var n=v(e,t||{});return n},fromTemplateUrl:function(e,t,n){var i;return angular.isFunction(t)&&(i=t,t=n),r.load(e).then(function(e){var n=v(e,t||{});return i&&i(n),n})},stack:m}}]),c.service("$ionicNavBarDelegate",ionic.DelegateService(["align","showBackButton","showBar","title","changeTitle","setTitle","getTitle","back","getPreviousTitle"])),c.service("$ionicNavViewDelegate",ionic.DelegateService(["clearCache"])),c.constant("IONIC_BACK_PRIORITY",{view:100,sideMenu:150,modal:200,actionSheet:300,popup:400,loading:500}).provider("$ionicPlatform",function(){return{$get:["$q",function(e){var t={onHardwareBackButton:function(e){ionic.Platform.ready(function(){document.addEventListener("backbutton",e,!1)})},offHardwareBackButton:function(e){ionic.Platform.ready(function(){document.removeEventListener("backbutton",e)})},$backButtonActions:{},registerBackButtonAction:function(e,n,i){t._hasBackButtonHandler||(t.$backButtonActions={},t.onHardwareBackButton(t.hardwareBackButtonClick),t._hasBackButtonHandler=!0);var o={id:i?i:ionic.Utils.nextUid(),priority:n?n:0,fn:e};return t.$backButtonActions[o.id]=o,function(){delete t.$backButtonActions[o.id]}},hardwareBackButtonClick:function(e){var n,i;for(i in t.$backButtonActions)(!n||t.$backButtonActions[i].priority>=n.priority)&&(n=t.$backButtonActions[i]);return n?(n.fn(e),n):void 0},is:function(e){return ionic.Platform.is(e)},on:function(e,t){return ionic.Platform.ready(function(){document.addEventListener(e,t,!1)}),function(){ionic.Platform.ready(function(){document.removeEventListener(e,t)})}},ready:function(t){var n=e.defer();return ionic.Platform.ready(function(){n.resolve(),t&&t()}),n.promise}};return t}]}}),c.factory("$ionicPopover",["$ionicModal","$ionicPosition","$document","$window",function(e,t,n,i){function o(e,n){var o=h(e.target||e),a=t.offset(o),c=n.prop("offsetWidth"),s=n.prop("offsetHeight"),l=i.innerWidth,u=i.innerHeight,d={left:a.left+a.width/2-c/2},f=h(n[0].querySelector(".popover-arrow"));d.left<r?d.left=r:d.left+c+r>l&&(d.left=l-c-r),a.top+a.height+s>u&&a.top-s>0?(d.top=a.top-s,n.addClass("popover-bottom")):(d.top=a.top+a.height,n.removeClass("popover-bottom")),f.css({left:a.left+a.width/2-f.prop("offsetWidth")/2-d.left+"px"}),n.css({top:d.top+"px",left:d.left+"px",marginLeft:"0",opacity:"1"})}var r=6,a={viewType:"popover",hideDelay:1,animation:"none",positionView:o};return{fromTemplate:function(t,n){return e.fromTemplate(t,ionic.Utils.extend(a,n||{}))},fromTemplateUrl:function(t,n){return e.fromTemplateUrl(t,ionic.Utils.extend(a,n||{}))}}}]);var w='<div class="popup-container" ng-class="cssClass"><div class="popup"><div class="popup-head"><h3 class="popup-title" ng-bind-html="title"></h3><h5 class="popup-sub-title" ng-bind-html="subTitle" ng-if="subTitle"></h5></div><div class="popup-body"></div><div class="popup-buttons" ng-show="buttons.length"><button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button></div></div></div>';c.factory("$ionicPopup",["$ionicTemplateLoader","$ionicBackdrop","$q","$timeout","$rootScope","$ionicBody","$compile","$ionicPlatform","$ionicModal","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,c,l,u){function d(t){t=s({scope:null,title:"",buttons:[]},t||{});var c={};return c.scope=(t.scope||o).$new(),c.element=h(w),c.responseDeferred=n.defer(),r.get().appendChild(c.element[0]),a(c.element)(c.scope),s(c.scope,{title:t.title,buttons:t.buttons,subTitle:t.subTitle,cssClass:t.cssClass,$buttonTapped:function(e,t){var n=(e.onTap||p)(t);t=t.originalEvent||t,t.defaultPrevented||c.responseDeferred.resolve(n)}}),n.when(t.templateUrl?e.load(t.templateUrl):t.template||t.content||"").then(function(e){var t=h(c.element[0].querySelector(".popup-body"));e?(t.html(e),a(t.contents())(c.scope)):t.remove()}),c.show=function(){c.isShown||c.removed||(l.stack.add(c),c.isShown=!0,ionic.requestAnimationFrame(function(){c.isShown&&(c.element.removeClass("popup-hidden"),c.element.addClass("popup-showing active"),g(c.element))}))},c.hide=function(e){return e=e||p,c.isShown?(l.stack.remove(c),c.isShown=!1,c.element.removeClass("active"),c.element.addClass("popup-hidden"),void i(e,250,!1)):e()},c.remove=function(){!c.removed&&l.stack.isHighest(c)&&(c.hide(function(){c.element.remove(),c.scope.$destroy()}),c.removed=!0)},c}function f(){var e=S[S.length-1];e&&e.responseDeferred.resolve()}function v(e){function n(){S.push(o),i(o.show,a,!1),o.responseDeferred.promise.then(function(e){var n=S.indexOf(o);return-1!==n&&S.splice(n,1),S.length>0?S[S.length-1].show():(t.release(),i(function(){S.length||r.removeClass("popup-open")},400,!1),(k._backButtonActionDone||p)()),o.remove(),e})}var o=k._createPopup(e),a=0;return S.length>0?(S[S.length-1].hide(),a=y.stackPushDelay):(r.addClass("popup-open"),t.retain(),k._backButtonActionDone=c.registerBackButtonAction(f,u.popup)),o.responseDeferred.promise.close=function(e){o.removed||o.responseDeferred.resolve(e)},o.responseDeferred.notify({close:o.responseDeferred.close}),n(),o.responseDeferred.promise}function g(e){var t=e[0].querySelector("[autofocus]");t&&t.focus()}function m(e){return v(s({buttons:[{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function $(e){return v(s({buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){return!1}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function b(e){var t=o.$new(!0);t.data={};var n="";return e.template&&/<[a-z][\s\S]*>/i.test(e.template)===!1&&(n="<span>"+e.template+"</span>",delete e.template),v(s({template:n+'<input ng-model="data.response" type="'+(e.inputType||"text")+'" placeholder="'+(e.inputPlaceholder||"")+'">',scope:t,buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return t.data.response||""}}]},e||{}))}var y={stackPushDelay:75},S=[],k={show:v,alert:m,confirm:$,prompt:b,_createPopup:d,_popupStack:S};return k}]),c.factory("$ionicPosition",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function i(e){return"static"===(n(e,"position")||"static")}var o=function(t){for(var n=e[0],o=t.offsetParent||n;o&&o!==n&&i(o);)o=o.offsetParent;return o||n};return{position:function(t){var n=this.offset(t),i={top:0,left:0},r=o(t[0]);r!=e[0]&&(i=this.offset(h(r)),i.top+=r.clientTop-r.scrollTop,i.left+=r.clientLeft-r.scrollLeft);var a=t[0].getBoundingClientRect();return{width:a.width||t.prop("offsetWidth"),height:a.height||t.prop("offsetHeight"),top:n.top-i.top,left:n.left-i.left}},offset:function(n){var i=n[0].getBoundingClientRect();return{width:i.width||n.prop("offsetWidth"),height:i.height||n.prop("offsetHeight"),top:i.top+(t.pageYOffset||e[0].documentElement.scrollTop),left:i.left+(t.pageXOffset||e[0].documentElement.scrollLeft)}}}}]),c.service("$ionicScrollDelegate",ionic.DelegateService(["resize","scrollTop","scrollBottom","scrollTo","scrollBy","zoomTo","zoomBy","getScrollPosition","anchorScroll","freezeScroll","freezeAllScrolls","getScrollView"])),c.service("$ionicSideMenuDelegate",ionic.DelegateService(["toggleLeft","toggleRight","getOpenRatio","isOpen","isOpenLeft","isOpenRight","canDragContent","edgeDragThreshold"])),c.service("$ionicSlideBoxDelegate",ionic.DelegateService(["update","slide","select","enableSlide","previous","next","stop","autoPlay","start","currentIndex","selected","slidesCount","count","loop"])),c.service("$ionicTabsDelegate",ionic.DelegateService(["select","selectedIndex"])),function(){var e=[];c.factory("$ionicTemplateCache",["$http","$templateCache","$timeout",function(t,n,i){function o(e){return"undefined"==typeof e?r():(f(e)&&(e=[e]),l(e,function(e){c.push(e)}),void(a&&r()))}function r(){var e;if(o._runCount++,a=!0,0!==c.length){for(var s=0;4>s&&(e=c.pop());)f(e)&&t.get(e,{cache:n}),s++;c.length&&i(r,1e3)}}var a,c=e;return o._runCount=0,o}]).config(["$stateProvider","$ionicConfigProvider",function(t,n){var i=t.state;t.state=function(o,r){if("object"==typeof r){var a=r.prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch();if(a&&f(r.templateUrl)&&e.push(r.templateUrl),angular.isObject(r.views))for(var c in r.views)a=r.views[c].prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch(),a&&f(r.views[c].templateUrl)&&e.push(r.views[c].templateUrl)}return i.call(t,o,r)}}]).run(["$ionicTemplateCache",function(e){e()}])}(),c.factory("$ionicTemplateLoader",["$compile","$controller","$http","$q","$rootScope","$templateCache",function(e,t,n,i,o,r){function a(e){return n.get(e,{cache:r}).then(function(e){return e.data&&e.data.trim()})}function c(n){n=s({template:"",templateUrl:"",scope:null,controller:null,locals:{},appendTo:null},n||{});var r=n.templateUrl?this.load(n.templateUrl):i.when(n.template);return r.then(function(i){var r,a=n.scope||o.$new(),c=h("<div>").html(i).contents();return n.controller&&(r=t(n.controller,s(n.locals,{$scope:a})),c.children().data("$ngControllerController",r)),n.appendTo&&h(n.appendTo).append(c),e(c)(a),{element:c,scope:a}})}return{load:a,compile:c}}]),c.factory("$ionicViewService",["$ionicHistory","$log",function(e,t){function n(e,n){t.warn("$ionicViewService"+e+" is deprecated, please use $ionicHistory"+n+" instead: http://ionicframework.com/docs/nightly/api/service/$ionicHistory/")}n("","");var i={getCurrentView:"currentView",getBackView:"backView",getForwardView:"forwardView",getCurrentStateName:"currentStateName",nextViewOptions:"nextViewOptions",clearHistory:"clearHistory"};return l(i,function(t,o){i[o]=function(){return n("."+o,"."+t),e[t].apply(this,arguments)}}),i}]),c.factory("$ionicViewSwitcher",["$timeout","$document","$q","$ionicClickBlock","$ionicConfig","$ionicNavBarDelegate",function(e,t,n,i,o,r){function a(e,t){return c(e)["abstract"]?c(e).name:t?t.stateId||t.viewId:ionic.Utils.nextUid()}function c(e){return e&&e.$$state&&e.$$state.self||{}}function d(e,t,n,i){var r=c(e),a=g||V(t,"view-transition")||r.viewTransition||o.views.transition()||"ios",l=o.navBar.transition();return n=m||V(t,"view-direction")||r.viewDirection||n||"none",s(f(i),{transition:a,navBarTransition:"view"===l?a:l,direction:n,shouldAnimate:"none"!==a&&"none"!==n})}function f(e){return e=e||{},{viewId:e.viewId,historyId:e.historyId,stateId:e.stateId,stateName:e.stateName,stateParams:e.stateParams}}function p(e,t){return arguments.length>1?void V(e,T,t):V(e,T)}function v(e){if(e&&e.length){var t=e.scope();t&&(t.$emit("$ionicView.unloaded",e.data(C)),t.$destroy()),e.remove()}}var g,m,$="webkitTransitionEnd transitionend",w="$noCache",b="$destroyEle",y="$eleId",S="$accessed",k="$fallbackTimer",C="$viewData",T="nav-view",B="active",I="cached",x="stage",A=0;ionic.transition=ionic.transition||{},ionic.transition.isActive=!1;var E,V=ionic.DomUtil.cachedAttr,P=[],D=1100,_={create:function(t,l,h,T,E,R){var L,M,N,z=++A,H={init:function(e,t){_.isTransitioning(!0),H.loadViewElements(e),H.render(e,function(){t&&t()})},loadViewElements:function(e){var n,i,o,r=t.getViewElements(),c=a(l,h),s=t.activeEleId();for(n=0,i=r.length;i>n&&(o=r.eq(n),o.data(y)===c?o.data(w)?(o.data(y,c+ionic.Utils.nextUid()),o.data(b,!0)):L=o:u(s)&&o.data(y)===s&&(M=o),!L||!M);n++);N=!!L,N||(L=e.ele||_.createViewEle(l),L.data(y,c)),R&&t.activeEleId(c),e.ele=null},render:function(e,n){if(N)ionic.Utils.reconnectScope(L.scope());else{p(L,x);var i=d(l,L,e.direction,h),r=o.transitions.views[i.transition]||o.transitions.views.none;r(L,null,i.direction,!0).run(0),L.data(C,{viewId:i.viewId,historyId:i.historyId,stateName:i.stateName,stateParams:i.stateParams}),(c(l).cache===!1||"false"===c(l).cache||"false"==L.attr("cache-view")||0===o.views.maxCache())&&L.data(w,!0);var a=t.appendViewElement(L,l);delete i.direction,delete i.transition,a.$emit("$ionicView.loaded",i)}L.data(S,Date.now()),n&&n()},transition:function(a,c,u){function v(){p(L,W.shouldAnimate?"entering":B),p(M,W.shouldAnimate?"leaving":I),W.run(1),r._instances.forEach(function(e){e.triggerTransitionStart(z)}),W.shouldAnimate||b()}function w(e){e.target===this&&b()}function b(){b.x||(b.x=!0,L.off($,w),e.cancel(L.data(k)),M&&e.cancel(M.data(k)),H.emit("after",O,q),C&&C.resolve(t),z===A&&(n.all(P).then(_.transitionEnd),H.cleanup(O)),r._instances.forEach(function(e){e.triggerTransitionEnd()}),g=m=h=T=L=M=null)}function y(e){e.target===this&&S()}function S(){p(L,I),p(M,B),L.off($,y),e.cancel(L.data(k)),_.transitionEnd([t])}var C,O=d(l,L,a,h),q=s(s({},O),f(T));O.transitionId=q.transitionId=z,O.fromCache=!!N,O.enableBack=!!c,O.renderStart=E,O.renderEnd=R,V(L.parent(),"nav-view-transition",O.transition),V(L.parent(),"nav-view-direction",O.direction),e.cancel(L.data(k));var U=o.transitions.views[O.transition]||o.transitions.views.none,W=U(L,M,O.direction,O.shouldAnimate&&u&&R);if(W.shouldAnimate&&(L.on($,w),L.data(k,e(b,D)),i.show(D)),E&&(H.emit("before",O,q),p(L,x),W.run(0)),R&&(C=n.defer(),P.push(C.promise)),E&&R)e(v,16);else{if(!R)return p(L,"entering"),p(M,"leaving"),{run:W.run,cancel:function(t){t?(L.on($,y),L.data(k,e(S,D)),i.show(D)):S(),W.shouldAnimate=t,W.run(0),W=null}};R&&v()}},emit:function(e,t,n){var i=L.scope(),o=M&&M.scope();"after"==e&&(i&&i.$emit("$ionicView.enter",t),o?o.$emit("$ionicView.leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView.leave",n)),i&&i.$emit("$ionicView."+e+"Enter",t),o?o.$emit("$ionicView."+e+"Leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView."+e+"Leave",n)},cleanup:function(e){M&&"back"==e.direction&&!o.views.forwardCache()&&v(M);var n,i,r,a=t.getViewElements(),c=a.length,s=c-1>o.views.maxCache(),l=Date.now();for(n=0;c>n;n++)i=a.eq(n),s&&i.data(S)<l?(l=i.data(S),r=a.eq(n)):i.data(b)&&p(i)!=B&&v(i);v(r),L.data(w)&&L.data(b,!0)},enteringEle:function(){return L},leavingEle:function(){return M}};return H},transitionEnd:function(e){l(e,function(e){e.transitionEnd()}),_.isTransitioning(!1),i.hide(),P=[]},nextTransition:function(e){g=e},nextDirection:function(e){m=e},isTransitioning:function(t){return arguments.length&&(ionic.transition.isActive=!!t,e.cancel(E),t&&(E=e(function(){_.isTransitioning(!1)},999))),ionic.transition.isActive},createViewEle:function(e){var n=t[0].createElement("div");return e&&e.$template&&(n.innerHTML=e.$template,1===n.children.length)?(n.children[0].classList.add("pane"),h(n.children[0])):(n.className="pane",h(n))},viewEleIsActive:function(e,t){p(e,t?B:I)},getTransitionData:d,navViewAttr:p,destroyViewEle:v};return _}]),c.config(["$provide",function(e){e.decorator("$compile",["$delegate",function(e){return e.$$addScopeInfo=function(e,t,n,i){var o=n?i?"$isolateScopeNoTemplate":"$isolateScope":"$scope";e.data(o,t)},e}])}]),c.config(["$provide",function(e){function t(e,t){return e.__hash=e.hash,e.hash=function(n){return u(n)&&t(function(){var e=document.querySelector(".scroll-content");e&&(e.scrollTop=0)},0,!1),e.__hash(n)},e}e.decorator("$location",["$delegate","$timeout",t])}]),c.controller("$ionicHeaderBar",["$scope","$element","$attrs","$q","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r){function a(e){return C[e]||(C[e]=t[0].querySelector("."+e)),C[e]}var c="title",s="back-text",l="back-button",u="default-title",d="previous-title",f="hide",h=this,p="",v="",g=0,m=0,$="",w=!1,b=!0,y=!0,S=!1,k=0;h.beforeEnter=function(t){e.$broadcast("$ionicView.beforeEnter",t)},h.title=function(e){return arguments.length&&e!==p&&(a(c).innerHTML=e,p=e,k=0),p},h.enableBack=function(e,t){return arguments.length&&(w=e,t||h.updateBackButton()),w},h.showBack=function(e,t){return arguments.length&&(b=e,t||h.updateBackButton()),b},h.showNavBack=function(e){y=e,h.updateBackButton()},h.updateBackButton=function(){var e;(b&&y&&w)!==S&&(S=b&&y&&w,e=a(l),e&&e.classList[S?"remove":"add"](f)),w&&(e=e||a(l),e&&(h.backButtonIcon!==o.backButton.icon()&&(e=a(l+" .icon"),e&&(h.backButtonIcon=o.backButton.icon(),e.className="icon "+h.backButtonIcon)),h.backButtonText!==o.backButton.text()&&(e=a(l+" .back-text"),e&&(e.textContent=h.backButtonText=o.backButton.text()))))},h.titleTextWidth=function(){if(!k){var e=ionic.DomUtil.getTextBounds(a(c));k=Math.min(e&&e.width||30)}return k},h.titleWidth=function(){var e=h.titleTextWidth(),t=a(c).offsetWidth;return e>t&&(e=t+(g-m-5)),e},h.titleTextX=function(){return t[0].offsetWidth/2-h.titleWidth()/2},h.titleLeftRight=function(){return g-m},h.backButtonTextLeft=function(){for(var e=0,t=a(s);t;)e+=t.offsetLeft,t=t.parentElement;return e},h.resetBackButton=function(e){if(o.backButton.previousTitleText()){var t=a(d);if(t){t.classList.remove(f);var n=e&&r.getViewById(e.viewId),i=r.backTitle(n);i!==v&&(v=t.innerHTML=i)}var c=a(u);c&&c.classList.remove(f)}},h.align=function(e){var i=a(c);e=e||n.alignTitle||o.navBar.alignTitle();var r=h.calcWidths(e,!1);if(b&&v&&o.backButton.previousTitleText()){var s=h.calcWidths(e,!0),l=t[0].offsetWidth-s.titleLeft-s.titleRight;h.titleTextWidth()<=l&&(r=s)}return h.updatePositions(i,r.titleLeft,r.titleRight,r.buttonsLeft,r.buttonsRight,r.css,r.showPrevTitle)},h.calcWidths=function(e,n){var i,o,r,h,p,v,g,m,$,w=a(c),y=a(l),S=t[0].childNodes,k=0,C=0,T=0,B=0,I="",x=0;for(i=0;i<S.length;i++){if(p=S[i],g=0,1==p.nodeType){if(p===w){$=!0;continue}if(p.classList.contains(f))continue;if(b&&p===y){for(o=0;o<p.childNodes.length;o++)if(h=p.childNodes[o],1==h.nodeType)if(h.classList.contains(s))for(r=0;r<h.children.length;r++)if(v=h.children[r],n){if(v.classList.contains(u))continue;x+=v.offsetWidth}else{if(v.classList.contains(d))continue;x+=v.offsetWidth}else x+=h.offsetWidth;else 3==h.nodeType&&h.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(h),x+=m&&m.width||0);g=x||p.offsetWidth}else g=p.offsetWidth}else 3==p.nodeType&&p.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(p),g=m&&m.width||0);$?C+=g:k+=g}if("left"==e)I="title-left",k&&(T=k+15),C&&(B=C+15);else if("right"==e)I="title-right",k&&(T=k+15),C&&(B=C+15);else{var A=Math.max(k,C)+10;A>10&&(T=B=A)}return{backButtonWidth:x,buttonsLeft:k,buttonsRight:C,titleLeft:T,titleRight:B,showPrevTitle:n,css:I}},h.updatePositions=function(e,n,r,c,s,l,p){var v=i.defer();if(e&&(n!==g&&(e.style.left=n?n+"px":"",g=n),r!==m&&(e.style.right=r?r+"px":"",m=r),l!==$&&(l&&e.classList.add(l),$&&e.classList.remove($),$=l)),o.backButton.previousTitleText()){var w=a(d),b=a(u);w&&w.classList[p?"remove":"add"](f),b&&b.classList[p?"add":"remove"](f)}return ionic.requestAnimationFrame(function(){if(e&&e.offsetWidth+10<e.scrollWidth){var n=s+5,i=t[0].offsetWidth-g-h.titleTextWidth()-20;r=n>i?n:i,r!==m&&(e.style.right=r+"px",m=r)}v.resolve()}),v.promise},h.setCss=function(e,t){ionic.DomUtil.cachedStyles(a(e),t)};var C={};e.$on("$destroy",function(){for(var e in C)C[e]=null})}]),c.controller("$ionInfiniteScroll",["$scope","$attrs","$element","$timeout",function(e,t,n,i){function o(){ionic.requestAnimationFrame(function(){n[0].classList.add("active")}),s.isLoading=!0,e.$parent&&e.$parent.$apply(t.onInfinite||"")}function r(){ionic.requestAnimationFrame(function(){n[0].classList.remove("active")}),i(function(){s.jsScrolling&&s.scrollView.resize(),(s.jsScrolling&&s.scrollView.__container&&s.scrollView.__container.offsetHeight>0||!s.jsScrolling)&&s.checkBounds()},30,!1),s.isLoading=!1}function a(){if(!s.isLoading){var e={};if(s.jsScrolling){e=s.getJSMaxScroll();var t=s.scrollView.getValues();(-1!==e.left&&t.left>=e.left||-1!==e.top&&t.top>=e.top)&&o()}else e=s.getNativeMaxScroll(),(-1!==e.left&&s.scrollEl.scrollLeft>=e.left-s.scrollEl.clientWidth||-1!==e.top&&s.scrollEl.scrollTop>=e.top-s.scrollEl.clientHeight)&&o()}}function c(e){var n=(t.distance||"2.5%").trim(),i=-1!==n.indexOf("%");return i?e*(1-parseFloat(n)/100):e-parseFloat(n)}var s=this;s.isLoading=!1,e.icon=function(){return u(t.icon)?t.icon:"ion-load-d"},e.spinner=function(){return u(t.spinner)?t.spinner:""},e.$on("scroll.infiniteScrollComplete",function(){r()}),e.$on("$destroy",function(){s.scrollCtrl&&s.scrollCtrl.$element&&s.scrollCtrl.$element.off("scroll",s.checkBounds),s.scrollEl&&s.scrollEl.removeEventListener&&s.scrollEl.removeEventListener("scroll",s.checkBounds)}),s.checkBounds=ionic.Utils.throttle(a,300),s.getJSMaxScroll=function(){var e=s.scrollView.getScrollMax();return{left:s.scrollView.options.scrollingX?c(e.left):-1,top:s.scrollView.options.scrollingY?c(e.top):-1}},s.getNativeMaxScroll=function(){var e={left:s.scrollEl.scrollWidth,top:s.scrollEl.scrollHeight},t=window.getComputedStyle(s.scrollEl)||{};return{left:"scroll"===t.overflowX||"auto"===t.overflowX||"scroll"===s.scrollEl.style["overflow-x"]?c(e.left):-1,top:"scroll"===t.overflowY||"auto"===t.overflowY||"scroll"===s.scrollEl.style["overflow-y"]?c(e.top):-1}},s.__finishInfiniteScroll=r}]),c.service("$ionicListDelegate",ionic.DelegateService(["showReorder","showDelete","canSwipeItems","closeOptionButtons"])).controller("$ionicList",["$scope","$attrs","$ionicListDelegate","$ionicHistory",function(e,t,n,i){var o=this,r=!0,a=!1,c=!1,s=n._registerInstance(o,t.delegateHandle,function(){return i.isActiveScope(e)});e.$on("$destroy",s),o.showReorder=function(e){return arguments.length&&(a=!!e),a},o.showDelete=function(e){return arguments.length&&(c=!!e),c},o.canSwipeItems=function(e){return arguments.length&&(r=!!e),r},o.closeOptionButtons=function(){o.listView&&o.listView.clearDragEffects()}}]),c.controller("$ionicNavBar",["$scope","$element","$attrs","$compile","$timeout","$ionicNavBarDelegate","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r,a,c){function s(e,t){var n=console.warn||console.log;n&&n.call(console,"navBarController."+e+" is deprecated, please use "+t+" instead")}function d(e){return x[e]?h(x[e]):void 0}function f(){for(var e=0;e<I.length;e++)if(I[e].isActive)return I[e]}function p(){for(var e=0;e<I.length;e++)if(!I[e].isActive)return I[e]}function v(e,t){e&&ionic.DomUtil.cachedAttr(e.containerEle(),"nav-bar",t)}function g(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}var m,$,w,b="hide",y="$ionNavBarController",S="primaryButtons",k="secondaryButtons",C="backButton",T="primaryButtons secondaryButtons leftButtons rightButtons title".split(" "),B=this,I=[],x={},A=!0;t.parent().data(y,B);var E=n.delegateHandle||"navBar"+ionic.Utils.nextUid(),V=r._registerInstance(B,E);B.init=function(){t.addClass("nav-bar-container"),ionic.DomUtil.cachedAttr(t,"nav-bar-transition",a.views.transition()),B.createHeaderBar(!1),B.createHeaderBar(!0),e.$emit("ionNavBar.init",E)},B.createHeaderBar=function(o){function r(e,t){e&&("title"===t?g.append(e):"rightButtons"==t||t==k&&"left"!=a.navBar.positionSecondaryButtons()||t==S&&"right"==a.navBar.positionPrimaryButtons()?(v||(v=h('<div class="buttons buttons-right">'),f.append(v)),t==k?v.append(e):v.prepend(e)):(p||(p=h('<div class="buttons buttons-left">'),m[C]?m[C].after(p):f.prepend(p)),t==k?p.append(e):p.prepend(e)))}var c=h('<div class="nav-bar-block">');ionic.DomUtil.cachedAttr(c,"nav-bar",o?"active":"cached");var s=n.alignTitle||a.navBar.alignTitle(),f=h("<ion-header-bar>").addClass(n["class"]).attr("align-title",s);u(n.noTapScroll)&&f.attr("no-tap-scroll",n.noTapScroll);var p,v,g=h('<div class="title title-'+s+'">'),m={},$={};m[C]=d(C),m[C]&&f.append(m[C]),f.append(g),l(T,function(e){m[e]=d(e),r(m[e],e)});for(var w=0;w<f[0].children.length;w++)f[0].children[w].classList.add("header-item");c.append(f),t.append(i(c)(e.$new()));var y=f.data("$ionHeaderBarController");y.backButtonIcon=a.backButton.icon(),y.backButtonText=a.backButton.text();var B={isActive:o,title:function(e){y.title(e)},setItem:function(e,t){B.removeItem(t),e?("title"===t&&B.title(""),r(e,t),m[t]&&m[t].addClass(b),$[t]=e):m[t]&&m[t].removeClass(b)},removeItem:function(e){$[e]&&($[e].scope().$destroy(),$[e].remove(),$[e]=null)},containerEle:function(){return c},headerBarEle:function(){return f},afterLeave:function(){l(T,function(e){B.removeItem(e)}),y.resetBackButton()},controller:function(){return y},destroy:function(){l(T,function(e){B.removeItem(e)}),c.scope().$destroy();for(var e in m)m[e]&&(m[e].removeData(),m[e]=null);p&&p.removeData(),v&&v.removeData(),g.removeData(),f.removeData(),c.remove(),c=f=g=p=v=null}};return I.push(B),B},B.navElement=function(e,t){return u(t)&&(x[e]=t),x[e]},B.update=function(e){var t=!e.hasHeaderBar&&e.showNavBar;e.transition=a.views.transition(),t||(e.direction="none"),B.enable(t);var n=B.isInitialized?p():f(),i=B.isInitialized?f():null,o=n.controller();o.enableBack(e.enableBack,!0),o.showBack(e.showBack,!0),o.updateBackButton(),B.title(e.title,n),B.showBar(t),e.navBarItems&&l(T,function(t){n.setItem(e.navBarItems[t],t)}),B.transition(n,i,e),B.isInitialized=!0,g("")},B.transition=function(n,i,r){function c(){for(var e=0;e<I.length;e++)I[e].isActive=!1;n.isActive=!0,v(n,"active"),v(i,"cached"),B.activeTransition=d=$=null}var s=n.controller(),l=a.transitions.navBar[r.navBarTransition]||a.transitions.navBar.none,u=r.transitionId;s.beforeEnter(r);var d=l(n,i,r.direction,r.shouldAnimate&&B.isInitialized);ionic.DomUtil.cachedAttr(t,"nav-bar-transition",r.navBarTransition),ionic.DomUtil.cachedAttr(t,"nav-bar-direction",r.direction),d.shouldAnimate&&r.renderEnd?v(n,"stage"):(v(n,"entering"),v(i,"leaving")),s.resetBackButton(r),d.run(0),B.activeTransition={run:function(e){d.shouldAnimate=!1,d.direction="back",d.run(e)},cancel:function(t,o,r){g(o),v(i,"active"),v(n,"cached"),d.shouldAnimate=t,d.run(0),B.activeTransition=d=null;var a;r.showBar!==B.showBar()&&B.showBar(r.showBar),r.showBackButton!==B.showBackButton()&&B.showBackButton(r.showBackButton),a&&e.$apply()},complete:function(e,t){g(t),d.shouldAnimate=e,d.run(1),$=c}},o(s.align,16),(m=function(){w===u&&(v(n,"entering"),v(i,"leaving"),d.run(1),$=function(){w!=u&&d.shouldAnimate||c()},m=null)})()},B.triggerTransitionStart=function(e){w=e,m&&m()},B.triggerTransitionEnd=function(){$&&$()},B.showBar=function(t){return arguments.length&&(B.visibleBar(t),e.$parent.$hasHeader=!!t),!!e.$parent.$hasHeader},B.visibleBar=function(e){e&&!A?(t.removeClass(b),B.align()):!e&&A&&t.addClass(b),A=e},B.enable=function(e){B.visibleBar(e);for(var t=0;t<r._instances.length;t++)r._instances[t]!==B&&r._instances[t].visibleBar(!1)},B.showBackButton=function(t){if(arguments.length){for(var n=0;n<I.length;n++)I[n].controller().showNavBack(!!t);e.$isBackButtonShown=!!t}return e.$isBackButtonShown},B.showActiveBackButton=function(e){var t=f();return t?arguments.length?t.controller().showBack(e):t.controller().showBack():void 0},B.title=function(t,n){return u(t)&&(t=t||"",n=n||f(),n&&n.title(t), -e.$title=t,c.currentTitle(t)),e.$title},B.align=function(e,t){t=t||f(),t&&t.controller().align(e)},B.hasTabsTop=function(e){t[e?"addClass":"removeClass"]("nav-bar-tabs-top")},B.hasBarSubheader=function(e){t[e?"addClass":"removeClass"]("nav-bar-has-subheader")},B.changeTitle=function(e){s("changeTitle(val)","title(val)"),B.title(e)},B.setTitle=function(e){s("setTitle(val)","title(val)"),B.title(e)},B.getTitle=function(){return s("getTitle()","title()"),B.title()},B.back=function(){s("back()","$ionicHistory.goBack()"),c.goBack()},B.getPreviousTitle=function(){s("getPreviousTitle()","$ionicHistory.backTitle()"),c.goBack()},e.$on("$destroy",function(){e.$parent.$hasHeader=!1,t.parent().removeData(y);for(var n=0;n<I.length;n++)I[n].destroy();t.remove(),t=I=null,V()})}]),c.controller("$ionicNavView",["$scope","$element","$attrs","$compile","$controller","$ionicNavBarDelegate","$ionicNavViewDelegate","$ionicHistory","$ionicViewSwitcher","$ionicConfig","$ionicScrollDelegate",function(e,t,n,i,o,r,a,c,l,u,d){function f(e,n){for(var i,o,r=t.children(),a=0,c=r.length;c>a;a++)if(i=r.eq(a),A(i)==T){o=i.scope(),o&&o.$emit(e.name.replace("Tabs","View"),n);break}}function h(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}function p(e,t){var n=g();n&&n.hasTabsTop(t)}function v(e,t){var n=g();n&&n.hasBarSubheader(t)}function g(){if($)for(var e=0;e<r._instances.length;e++)if(r._instances[e].$$delegateHandle==$)return r._instances[e];return t.inheritedData("$ionNavBarController")}var m,$,w,b,y,S="$eleId",k="$destroyEle",C="$noCache",T="active",B="cached",I=this,x=!1,A=l.navViewAttr;I.scope=e,I.element=t,I.init=function(){var i=n.name||"",o=t.parent().inheritedData("$uiView"),r=o&&o.state?o.state.name:"";i.indexOf("@")<0&&(i=i+"@"+r);var c={name:i,state:null};t.data("$uiView",c);var s=a._registerInstance(I,n.delegateHandle);return e.$on("$destroy",function(){s(),I.isSwipeFreeze&&d.freezeAllScrolls(!1)}),e.$on("$ionicHistory.deselect",I.cacheCleanup),e.$on("$ionicTabs.top",p),e.$on("$ionicSubheader",v),e.$on("$ionicTabs.beforeLeave",f),e.$on("$ionicTabs.afterLeave",f),e.$on("$ionicTabs.leave",f),ionic.Platform.ready(function(){ionic.Platform.isWebView()&&u.views.swipeBackEnabled()&&I.initSwipeBack()}),c},I.register=function(t){var n=s({},c.currentView()),i=c.register(e,t);I.update(i);var o=c.getViewById(i.viewId)||{},r=b!==i.viewId;I.render(i,t,o,n,r,!0)},I.update=function(e){x=!0,m=e.direction;var n=t.parent().inheritedData("$ionNavViewController");n&&(n.isPrimary(!1),("enter"===m||"exit"===m)&&(n.direction(m),"enter"===m&&(m="none")))},I.render=function(e,t,n,i,o,r){var a=l.create(I,t,n,i,o,r);a.init(e,function(){a.transition(I.direction(),e.enableBack,!y),b=y=null})},I.beforeEnter=function(e){if(x){$=e.navBarDelegate;var t=g();t&&t.update(e),h("")}},I.activeEleId=function(e){return arguments.length&&(w=e),w},I.transitionEnd=function(){var e,n,i,o=t.children();for(e=0,n=o.length;n>e;e++)i=o.eq(e),i.data(S)===w?A(i,T):("leaving"===A(i)||A(i)===T||A(i)===B)&&(i.data(k)||i.data(C)?l.destroyViewEle(i):(A(i,B),ionic.Utils.disconnectScope(i.scope())));h(""),I.isSwipeFreeze&&d.freezeAllScrolls(!1)},I.cacheCleanup=function(){for(var e=t.children(),n=0,i=e.length;i>n;n++)e.eq(n).data(k)&&l.destroyViewEle(e.eq(n))},I.clearCache=function(e){var n,i,o,r,a,c,s=t.children();for(o=0,r=s.length;r>o;o++)if(n=s.eq(o),e)for(c=n.data(S),a=0;a<e.length;a++)c===e[a]&&l.destroyViewEle(n);else A(n)==B?l.destroyViewEle(n):A(n)==T&&(i=n.scope(),i&&i.$broadcast("$ionicView.clearCache"))},I.getViewElements=function(){return t.children()},I.appendViewElement=function(n,r){var a=i(n);t.append(n);var c=e.$new();if(r&&r.$$controller){r.$scope=c;var s=o(r.$$controller,r);t.children().data("$ngControllerController",s)}return a(c),c},I.title=function(e){var t=g();t&&t.title(e)},I.enableBackButton=function(e){var t=g();t&&t.enableBackButton(e)},I.showBackButton=function(e){var t=g();return t?arguments.length?t.showActiveBackButton(e):t.showActiveBackButton():!0},I.showBar=function(e){var t=g();return t?arguments.length?t.showBar(e):t.showBar():!0},I.isPrimary=function(e){return arguments.length&&(x=e),x},I.direction=function(e){return arguments.length&&(m=e),m},I.initSwipeBack=function(){function n(e){if(x&&(S=r(e),!(S>C))){p=c.backView();var n=c.currentView();if(p&&p.historyId===n.historyId&&n.canSwipeBack!==!1){w||(w=window.innerWidth),I.isSwipeFreeze=d.freezeAllScrolls(!0);var a={direction:"back"};k=[],T={showBar:I.showBar(),showBackButton:I.showBackButton()};var u=l.create(I,a,p,n,!0,!1);u.loadViewElements(a),u.render(a),s=u.transition("back",c.enabledBack(p),!0),f=g(),m=ionic.onGesture("drag",i,t[0]),$=ionic.onGesture("release",o,t[0])}}}function i(e){if(x&&s){var t=r(e);if(k.push({t:Date.now(),x:t}),t>=w-15)o(e);else{var n=Math.min(Math.max(a(t),0),1);s.run(n),f&&f.activeTransition&&f.activeTransition.run(n)}}}function o(e){if(x&&s&&k&&k.length>1){for(var t=Date.now(),n=r(e),c=k[k.length-1],l=k.length-2;l>=0&&!(t-c.t>200);l--)c=k[l];var u=n>=k[k.length-2].x,v=a(n),g=Math.abs(c.x-n)/(t-c.t);if(b=p.viewId,y=.03>v||v>.97,u&&(v>.5||g>.1)){var S=g>.5||.05>g||n>w-45?"fast":"slow";h(y?"":S),p.go(),f&&f.activeTransition&&f.activeTransition.complete(!y,S)}else h(y?"":"fast"),b=null,s.cancel(!y),f&&f.activeTransition&&f.activeTransition.cancel(!y,"fast",T),y=null}ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),w=s=k=null,I.isSwipeFreeze=d.freezeAllScrolls(!1)}function r(e){return ionic.tap.pointerCoord(e.gesture.srcEvent).x}function a(e){return(e-S)/w}var s,f,p,v,m,$,w,S,k,C=u.views.swipeBackHitWidth(),T={};v=ionic.onGesture("dragstart",n,t[0]),e.$on("$destroy",function(){ionic.offGesture(v,"dragstart",n),ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),I.element=s=f=null})}}]),c.controller("$ionicRefresher",["$scope","$attrs","$element","$ionicBind","$timeout",function(e,t,n,i,o){function r(){(P||k)&&(E=null,k?(k=!1,T=0,B>I?(g(),f(I,A)):(f(0,A,v),C=!1)):(T=0,C=!1,d(!1)))}function a(e){if(P&&!(e.touches.length>1)){if(null===E&&(E=parseInt(e.touches[0].screenY,10)),ionic.Platform.isAndroid()&&4.4===ionic.Platform.version()&&0===b.scrollTop&&(k=!0,e.preventDefault()),V=parseInt(e.touches[0].screenY,10)-E,0>=V-T||0!==b.scrollTop)return C&&(C=!1,d(!1)),k&&l(b,-1*parseInt(V-T,10)),void(0!==B&&s(0));V>0&&0===b.scrollTop&&!C&&(T=V),e.preventDefault(),C||(C=!0,d(!0)),k=!0,s(parseInt((V-T)/3,10)),!x&&B>I?(x=!0,ionic.requestAnimationFrame(p)):x&&I>B&&(x=!1,ionic.requestAnimationFrame(v))}}function c(e){P=0===e.target.scrollTop||k}function s(e){y.style[ionic.CSS.TRANSFORM]="translateY("+e+"px)",B=e}function l(e,t){e.scrollTop=t;var n=document.createEvent("UIEvents");n.initUIEvent("scroll",!0,!0,window,1),e.dispatchEvent(n)}function d(e){ionic.requestAnimationFrame(e?function(){y.classList.add("overscroll"),m()}:function(){y.classList.remove("overscroll"),$(),v()})}function f(e,t,n){function i(e){return--e*e*e+1}function o(){var c=Date.now(),l=Math.min(1,(c-r)/t),u=i(l);s(parseInt(u*(e-a)+a,10)),1>l?ionic.requestAnimationFrame(o):(5>e&&e>-5&&(C=!1,d(!1)),n&&n())}var r=Date.now(),a=B;return a===e?void n():void ionic.requestAnimationFrame(o)}function h(){ionic.off("touchmove",a,y),ionic.off("touchend",r,y),ionic.off("scroll",c,b),b=null,y=null}function p(){n[0].classList.add("active"),e.$onPulling()}function v(){o(function(){n.removeClass("active refreshing refreshing-tail"),x&&(x=!1)},150)}function g(){n[0].classList.add("refreshing"),e.$onRefresh()}function m(){n[0].classList.remove("invisible")}function $(){n[0].classList.add("invisible")}function w(){n[0].classList.add("refreshing-tail")}var b,y,S=this,k=!1,C=!1,T=0,B=0,I=60,x=!1,A=500,E=null,V=null,P=!0;u(t.pullingIcon)||t.$set("pullingIcon","ion-android-arrow-down"),e.showSpinner=!u(t.refreshingIcon)&&"none"!=t.spinner,e.showIcon=u(t.refreshingIcon),i(e,t,{pullingIcon:"@",pullingText:"@",refreshingIcon:"@",refreshingText:"@",spinner:"@",disablePullingRotation:"@",$onRefresh:"&onRefresh",$onPulling:"&onPulling"}),e.$on("scroll.refreshComplete",function(){o(function(){ionic.requestAnimationFrame(w),f(0,A,v),o(function(){C&&(C=!1,d(!1))},A)},A)}),S.init=function(){if(b=n.parent().parent()[0],y=n.parent()[0],!(b&&b.classList.contains("ionic-scroll")&&y&&y.classList.contains("scroll")))throw new Error("Refresher must be immediate child of ion-content or ion-scroll");ionic.on("touchmove",a,y),ionic.on("touchend",r,y),ionic.on("scroll",c,b),e.$on("$destroy",h)},S.getRefresherDomMethods=function(){return{activate:p,deactivate:v,start:g,show:m,hide:$,tail:w}},S.__handleTouchmove=a,S.__getScrollChild=function(){return y},S.__getScrollParent=function(){return b}}]),c.controller("$ionicScroll",["$scope","scrollViewOptions","$timeout","$window","$location","$document","$ionicScrollDelegate","$ionicHistory",function(e,t,n,i,o,r,a,c){var s=this;s.__timeout=n,s._scrollViewOptions=t,s.isNative=function(){return!!t.nativeScrolling};var l,d=s.element=t.el,f=s.$element=h(d);l=s.isNative()?s.scrollView=new ionic.views.ScrollNative(t):s.scrollView=new ionic.views.Scroll(t),(f.parent().length?f.parent():f).data("$$ionicScrollController",s);var p=a._registerInstance(s,t.delegateHandle,function(){return c.isActiveScope(e)});u(t.bouncing)||ionic.Platform.ready(function(){l.options&&(l.options.bouncing=!0,ionic.Platform.isAndroid()&&(l.options.bouncing=!1,l.options.deceleration=.95))});var v=angular.bind(l,l.resize);angular.element(i).on("resize",v);var g=function(t){var n=(t.originalEvent||t).detail||{};e.$onScroll&&e.$onScroll({event:t,scrollTop:n.scrollTop||0,scrollLeft:n.scrollLeft||0})};f.on("scroll",g),e.$on("$destroy",function(){p(),l&&l.__cleanup&&l.__cleanup(),angular.element(i).off("resize",v),f.off("scroll",g),l=s.scrollView=t=s._scrollViewOptions=t.el=s._scrollViewOptions.el=f=s.$element=d=null}),n(function(){l&&l.run&&l.run()}),s.getScrollView=function(){return l},s.getScrollPosition=function(){return l.getValues()},s.resize=function(){return n(v,0,!1).then(function(){f&&f.triggerHandler("scroll-resize")})},s.scrollTop=function(e){s.resize().then(function(){l.scrollTo(0,0,!!e)})},s.scrollBottom=function(e){s.resize().then(function(){var t=l.getScrollMax();l.scrollTo(t.left,t.top,!!e)})},s.scrollTo=function(e,t,n){s.resize().then(function(){l.scrollTo(e,t,!!n)})},s.zoomTo=function(e,t,n,i){s.resize().then(function(){l.zoomTo(e,!!t,n,i)})},s.zoomBy=function(e,t,n,i){s.resize().then(function(){l.zoomBy(e,!!t,n,i)})},s.scrollBy=function(e,t,n){s.resize().then(function(){l.scrollBy(e,t,!!n)})},s.anchorScroll=function(e){s.resize().then(function(){var t=o.hash(),n=t&&r[0].getElementById(t);if(!t||!n)return void l.scrollTo(0,0,!!e);var i=n,a=0,c=0;do null!==i&&(a+=i.offsetLeft),null!==i&&(c+=i.offsetTop),i=i.offsetParent;while(i.attributes!=s.element.attributes&&i.offsetParent);l.scrollTo(a,c,!!e)})},s.freezeScroll=l.freeze,s.freezeAllScrolls=function(e){for(var t=0;t<a._instances.length;t++)a._instances[t].freezeScroll(e)},s._setRefresher=function(e,t,n){s.refresher=t;var i=s.refresher.clientHeight||60;l.activatePullToRefresh(i,n)}}]),c.controller("$ionicSideMenus",["$scope","$attrs","$ionicSideMenuDelegate","$ionicPlatform","$ionicBody","$ionicHistory","$ionicScrollDelegate","IONIC_BACK_PRIORITY","$rootScope",function(e,t,n,i,o,r,a,c,s){function l(e){e&&!w.isScrollFreeze?a.freezeAllScrolls(e):!e&&w.isScrollFreeze&&a.freezeAllScrolls(!1),w.isScrollFreeze=e}var u,f,h,v,g,m,$,w=this,b=!0;w.$scope=e,w.initialize=function(e){w.left=e.left,w.right=e.right,w.setContent(e.content),w.dragThresholdX=e.dragThresholdX||10,r.registerHistory(w.$scope)},w.setContent=function(e){e&&(w.content=e,w.content.onDrag=function(e){w._handleDrag(e)},w.content.endDrag=function(e){w._endDrag(e)})},w.isOpenLeft=function(){return w.getOpenAmount()>0},w.isOpenRight=function(){return w.getOpenAmount()<0},w.toggleLeft=function(e){if(!$&&w.left.isEnabled){var t=w.getOpenAmount();0===arguments.length&&(e=0>=t),w.content.enableAnimation(),e?(w.openPercentage(100),s.$emit("$ionicSideMenuOpen","left")):(w.openPercentage(0),s.$emit("$ionicSideMenuClose","left"))}},w.toggleRight=function(e){if(!$&&w.right.isEnabled){var t=w.getOpenAmount();0===arguments.length&&(e=t>=0),w.content.enableAnimation(),e?(w.openPercentage(-100),s.$emit("$ionicSideMenuOpen","right")):(w.openPercentage(0),s.$emit("$ionicSideMenuClose","right"))}},w.toggle=function(e){"right"==e?w.toggleRight():w.toggleLeft()},w.close=function(){w.openPercentage(0),s.$emit("$ionicSideMenuClose","left"),s.$emit("$ionicSideMenuClose","right")},w.getOpenAmount=function(){return w.content&&w.content.getTranslateX()||0},w.getOpenRatio=function(){var e=w.getOpenAmount();return e>=0?e/w.left.width:e/w.right.width},w.isOpen=function(){return 0!==w.getOpenAmount()},w.getOpenPercentage=function(){return 100*w.getOpenRatio()},w.openPercentage=function(e){var t=e/100;w.left&&e>=0?w.openAmount(w.left.width*t):w.right&&0>e&&w.openAmount(w.right.width*t),o.enableClass(0!==e,"menu-open"),l(!1)},w.openAmount=function(e){var t=w.left&&w.left.width||0,n=w.right&&w.right.width||0;return(w.left&&w.left.isEnabled||!(e>0))&&(w.right&&w.right.isEnabled||!(0>e))?f&&e>t?void w.content.setTranslateX(t):u&&-n>e?void w.content.setTranslateX(-n):(w.content.setTranslateX(e),void(e>=0?(f=!0,u=!1,e>0&&(w.right&&w.right.pushDown&&w.right.pushDown(),w.left&&w.left.bringUp&&w.left.bringUp())):(u=!0,f=!1,w.right&&w.right.bringUp&&w.right.bringUp(),w.left&&w.left.pushDown&&w.left.pushDown()))):void w.content.setTranslateX(0)},w.snapToRest=function(e){w.content.enableAnimation(),h=!1;var t=w.getOpenRatio();if(0===t)return void w.openPercentage(0);var n=.3,i=e.gesture.velocityX,o=e.gesture.direction;w.openPercentage(t>0&&.5>t&&"right"==o&&n>i?0:t>.5&&"left"==o&&n>i?100:0>t&&t>-.5&&"left"==o&&n>i?0:.5>t&&"right"==o&&n>i?-100:"right"==o&&t>=0&&(t>=.5||i>n)?100:"left"==o&&0>=t&&(-.5>=t||i>n)?-100:0)},w.enableMenuWithBackViews=function(e){return arguments.length&&(b=!!e),b},w.isAsideExposed=function(){return!!$},w.exposeAside=function(e){(w.left&&w.left.isEnabled||w.right&&w.right.isEnabled)&&(w.close(),$=e,w.left&&w.left.isEnabled?w.content.setMarginLeft($?w.left.width:0):w.right&&w.right.isEnabled&&w.content.setMarginRight($?w.right.width:0),w.$scope.$emit("$ionicExposeAside",$))},w.activeAsideResizing=function(e){o.enableClass(e,"aside-resizing")},w._endDrag=function(e){l(!1),$||(h&&w.snapToRest(e),v=null,g=null,m=null)},w._handleDrag=function(t){!$&&e.dragContent&&(v?g=t.gesture.touches[0].pageX:(v=t.gesture.touches[0].pageX,g=v),!h&&Math.abs(g-v)>w.dragThresholdX&&(v=g,h=!0,w.content.disableAnimation(),m=w.getOpenAmount()),h&&(w.openAmount(m+(g-v)),l(!0)))},w.canDragContent=function(t){return arguments.length&&(e.dragContent=!!t),e.dragContent},w.edgeThreshold=25,w.edgeThresholdEnabled=!1,w.edgeDragThreshold=function(e){return arguments.length&&(d(e)&&e>0?(w.edgeThreshold=e,w.edgeThresholdEnabled=!0):w.edgeThresholdEnabled=!!e),w.edgeThresholdEnabled},w.isDraggableTarget=function(t){var n=w.edgeThresholdEnabled&&!w.isOpen(),i=t.gesture.startEvent&&t.gesture.startEvent.center&&t.gesture.startEvent.center.pageX,o=!n||i<=w.edgeThreshold||i>=w.content.element.offsetWidth-w.edgeThreshold,a=r.backView(),c=b?!0:!a;if(!c){var s=r.currentView()||{};return a.historyId!==s.historyId}return(e.dragContent||w.isOpen())&&o&&!t.gesture.srcEvent.defaultPrevented&&c&&!t.target.tagName.match(/input|textarea|select|object|embed/i)&&!t.target.isContentEditable&&!(t.target.dataset?t.target.dataset.preventScroll:"true"==t.target.getAttribute("data-prevent-scroll"))},e.sideMenuContentTranslateX=0;var y=p,S=angular.bind(w,w.close);e.$watch(function(){return 0!==w.getOpenAmount()},function(e){y(),e&&(y=i.registerBackButtonAction(S,c.sideMenu))});var k=n._registerInstance(w,t.delegateHandle,function(){return r.isActiveScope(e)});e.$on("$destroy",function(){k(),y(),w.$scope=null,w.content&&(w.content.element=null,w.content=null),l(!1)}),w.initialize({left:{width:275},right:{width:275}})}]),function(e){function t(e,i,o,r){var a,c,s,l=document.createElement(f[e]||e);for(a in i)if(angular.isArray(i[a]))for(c=0;c<i[a].length;c++)if(i[a][c].fn)for(s=0;s<i[a][c].t;s++)t(a,i[a][c].fn(s,r),l,r);else t(a,i[a][c],l,r);else n(l,a,i[a]);o.appendChild(l)}function n(e,t,n){e.setAttribute(f[t]||t,n)}function i(e,t){var n=e.split(";"),i=n.slice(t),o=n.slice(0,n.length-i.length);return n=i.concat(o).reverse(),n.join(";")+";"+n[0]}function o(e,t){return e/=t/2,1>e?.5*e*e*e:(e-=2,.5*(e*e*e+2))}var r="translate(32,32)",a="stroke-opacity",s="round",l="indefinite",u="750ms",d="none",f={a:"animate",an:"attributeName",at:"animateTransform",c:"circle",da:"stroke-dasharray",os:"stroke-dashoffset",f:"fill",lc:"stroke-linecap",rc:"repeatCount",sw:"stroke-width",t:"transform",v:"values"},h={v:"0,32,32;360,32,32",an:"transform",type:"rotate",rc:l,dur:u},p={sw:4,lc:s,line:[{fn:function(e,t){return{y1:"ios"==t?17:12,y2:"ios"==t?29:20,t:r+" rotate("+(30*e+(6>e?180:-180))+")",a:[{fn:function(){return{an:a,dur:u,v:i("0;.1;.15;.25;.35;.45;.55;.65;.7;.85;1",e),rc:l}},t:1}]}},t:12}]},v={android:{c:[{sw:6,da:128,os:82,r:26,cx:32,cy:32,f:d}]},ios:p,"ios-small":p,bubbles:{sw:0,c:[{fn:function(e){return{cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,a:[{fn:function(){return{an:"r",dur:u,v:i("1;2;3;4;5;6;7;8",e),rc:l}},t:1}]}},t:8}]},circles:{c:[{fn:function(e){return{r:5,cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".3;.3;.3;.4;.7;.85;.9;1",e),rc:l}},t:1}]}},t:8}]},crescent:{c:[{sw:4,da:128,os:82,r:26,cx:32,cy:32,f:d,at:[h]}]},dots:{c:[{fn:function(e){return{cx:16+16*e,cy:32,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".5;.6;.8;1;.8;.6;.5",e),rc:l}},t:1},{fn:function(){return{an:"r",dur:u,v:i("4;5;6;5;4;3;3",e),rc:l}},t:1}]}},t:3}]},lines:{sw:7,lc:s,line:[{fn:function(e){return{x1:10+14*e,x2:10+14*e,a:[{fn:function(){return{an:"y1",dur:u,v:i("16;18;28;18;16",e),rc:l}},t:1},{fn:function(){return{an:"y2",dur:u,v:i("48;44;36;46;48",e),rc:l}},t:1},{fn:function(){return{an:a,dur:u,v:i("1;.8;.5;.4;1",e),rc:l}},t:1}]}},t:4}]},ripple:{f:d,"fill-rule":"evenodd",sw:3,circle:[{fn:function(e){return{cx:32,cy:32,a:[{fn:function(){return{an:"r",begin:-1*e+"s",dur:"2s",v:"0;24",keyTimes:"0;1",keySplines:"0.1,0.2,0.3,1",calcMode:"spline",rc:l}},t:1},{fn:function(){return{an:a,begin:-1*e+"s",dur:"2s",v:".2;1;.2;0",rc:l}},t:1}]}},t:2}]},spiral:{defs:[{linearGradient:[{id:"sGD",gradientUnits:"userSpaceOnUse",x1:55,y1:46,x2:2,y2:46,stop:[{offset:.1,"class":"stop1"},{offset:1,"class":"stop2"}]}]}],g:[{sw:4,lc:s,f:d,path:[{stroke:"url(#sGD)",d:"M4,32 c0,15,12,28,28,28c8,0,16-4,21-9"},{d:"M60,32 C60,16,47.464,4,32,4S4,16,4,32"}],at:[h]}]}},g={android:function(t){function i(){var t=o(Date.now()-r,650),u=1,d=0,f=188-58*t,h=182-182*t;a%2&&(u=-1,d=-64,f=128- -58*t,h=182*t);var p=[0,-101,-90,-11,-180,79,-270,-191][a];n(l,"da",Math.max(Math.min(f,188),128)),n(l,"os",Math.max(Math.min(h,182),0)),n(l,"t","scale("+u+",1) translate("+d+",0) rotate("+p+",32,32)"),c+=4.1,c>359&&(c=0),n(s,"t","rotate("+c+",32,32)"),t>=1&&(a++,a>7&&(a=0),r=Date.now()),e.requestAnimationFrame(i)}var r,a=0,c=0,s=t.querySelector("g"),l=t.querySelector("circle");return function(){r=Date.now(),i()}}};c.controller("$ionicSpinner",["$element","$attrs","$ionicConfig",function(e,n,i){var o;this.init=function(){o=n.icon||i.spinner.icon();var r=document.createElement("div");return t("svg",{viewBox:"0 0 64 64",g:[v[o]]},r,o),e.html(r.innerHTML),this.start(),o},this.start=function(){g[o]&&g[o](e[0])()}}])}(ionic),c.controller("$ionicTab",["$scope","$ionicHistory","$attrs","$location","$state",function(e,t,n,i,o){this.$scope=e,this.hrefMatchesState=function(){return n.href&&0===i.path().indexOf(n.href.replace(/^#/,"").replace(/\/$/,""))},this.srefMatchesState=function(){return n.uiSref&&o.includes(n.uiSref.split("(")[0])},this.navNameMatchesState=function(){return this.navViewName&&t.isCurrentStateNavView(this.navViewName)},this.tabMatchesState=function(){return this.hrefMatchesState()||this.srefMatchesState()||this.navNameMatchesState()}}]),c.controller("$ionicTabs",["$scope","$element","$ionicHistory",function(e,t,n){var i,o=this,r=null,a=null;o.tabs=[],o.selectedIndex=function(){return o.tabs.indexOf(r)},o.selectedTab=function(){return r},o.previousSelectedTab=function(){return a},o.add=function(e){n.registerHistory(e),o.tabs.push(e)},o.remove=function(e){var t=o.tabs.indexOf(e);if(-1!==t){if(e.$tabSelected)if(o.deselect(e),1===o.tabs.length);else{var n=t===o.tabs.length-1?t-1:t+1;o.select(o.tabs[n])}o.tabs.splice(t,1)}},o.deselect=function(e){e.$tabSelected&&(a=r,r=i=null,e.$tabSelected=!1,(e.onDeselect||p)(),e.$broadcast&&e.$broadcast("$ionicHistory.deselect"))},o.select=function(t,a){var c;if(d(t)){if(c=t,c>=o.tabs.length)return;t=o.tabs[c]}else c=o.tabs.indexOf(t);1===arguments.length&&(a=!(!t.navViewName&&!t.uiSref)),r&&r.$historyId==t.$historyId?a&&n.goToHistoryRoot(t.$historyId):i!==c&&(l(o.tabs,function(e){o.deselect(e)}),r=t,i=c,o.$scope&&o.$scope.$parent&&(o.$scope.$parent.$activeHistoryId=t.$historyId),t.$tabSelected=!0,(t.onSelect||p)(),a&&e.$emit("$ionicHistory.change",{type:"tab",tabIndex:c,historyId:t.$historyId,navViewName:t.navViewName,hasNavView:!!t.navViewName,title:t.title,url:t.href,uiSref:t.uiSref}))},o.hasActiveScope=function(){for(var e=0;e<o.tabs.length;e++)if(n.isActiveScope(o.tabs[e]))return!0;return!1}}]),c.controller("$ionicView",["$scope","$element","$attrs","$compile","$rootScope",function(e,t,n,i,o){function r(){var t=u(n.viewTitle)&&"viewTitle"||u(n.title)&&"title";t&&(a(n[t]),$.push(n.$observe(t,a))),u(n.hideBackButton)&&$.push(e.$watch(n.hideBackButton,function(e){f.showBackButton(!e)})),u(n.hideNavBar)&&$.push(e.$watch(n.hideNavBar,function(e){f.showBar(!e)}))}function a(e){u(e)&&e!==v&&(v=e,f.title(v))}function c(){for(var e=0;e<$.length;e++)$[e]();$=[]}function l(t){return t?i(t)(e.$new()):void 0}function d(t){return!!e.$eval(n[t])}var f,h,p,v,g=this,m={},$=[],w=e.$on("ionNavBar.init",function(e,t){e.stopPropagation(),h=t});g.init=function(){w();var n=t.inheritedData("$ionModalController");f=t.inheritedData("$ionNavViewController"),f&&!n&&(e.$on("$ionicView.beforeEnter",g.beforeEnter),e.$on("$ionicView.afterEnter",r),e.$on("$ionicView.beforeLeave",c))},g.beforeEnter=function(t,i){if(i&&!i.viewNotified){i.viewNotified=!0,o.$$phase||e.$digest(),v=u(n.viewTitle)?n.viewTitle:n.title;var r={};for(var a in m)r[a]=l(m[a]);f.beforeEnter(s(i,{title:v,showBack:!d("hideBackButton"),navBarItems:r,navBarDelegate:h||null,showNavBar:!d("hideNavBar"),hasHeaderBar:!!p})),c()}},g.navElement=function(e,t){m[e]=t}}]),c.directive("ionActionSheet",["$document",function(e){return{restrict:"E",scope:!0,replace:!0,link:function(t,n){var i=function(e){27==e.which&&(t.cancel(),t.$apply())},o=function(e){e.target==n[0]&&(t.cancel(),t.$apply())};t.$on("$destroy",function(){n.remove(),e.unbind("keyup",i)}),e.bind("keyup",i),n.bind("click",o)},template:'<div class="action-sheet-backdrop"><div class="action-sheet-wrapper"><div class="action-sheet" ng-class="{\'action-sheet-has-icons\': $actionSheetHasIcon}"><div class="action-sheet-group action-sheet-options"><div class="action-sheet-title" ng-if="titleText" ng-bind-html="titleText"></div><button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-repeat="b in buttons" ng-bind-html="b.text"></button><button class="button destructive action-sheet-destructive" ng-if="destructiveText" ng-click="destructiveButtonClicked()" ng-bind-html="destructiveText"></button></div><div class="action-sheet-group action-sheet-cancel" ng-if="cancelText"><button class="button" ng-click="cancel()" ng-bind-html="cancelText"></button></div></div></div></div>'}}]),c.directive("ionCheckbox",["$ionicConfig",function(e){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-checkbox"><div class="checkbox checkbox-input-hidden disable-pointer-events"><input type="checkbox"><i class="checkbox-icon"></i></div><div class="item-content disable-pointer-events" ng-transclude></div></label>',compile:function(t,n){var i=t.find("input");l({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){u(e)&&i.attr(t,e)});var o=t[0].querySelector(".checkbox");o.classList.add("checkbox-"+e.form.checkbox())}}}]),c.directive("collectionRepeat",e).factory("$ionicCollectionManager",t);var b="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",y=/height:.*?px;\s*width:.*?px/,S=3;e.$inject=["$ionicCollectionManager","$parse","$window","$$rAF","$rootScope","$timeout"],t.$inject=["$rootScope","$window","$$rAF"],c.directive("ionContent",["$timeout","$controller","$ionicBind","$ionicConfig",function(e,t,n,i){return{restrict:"E",require:"^?ionNavView",scope:!0,priority:800,compile:function(e,o){function r(e,i,r){function l(){e.$onScrollComplete({scrollTop:c.scrollView.__scrollTop,scrollLeft:c.scrollView.__scrollLeft})}var d=e.$parent;if(e.$watch(function(){return(d.$hasHeader?" has-header":"")+(d.$hasSubheader?" has-subheader":"")+(d.$hasFooter?" has-footer":"")+(d.$hasSubfooter?" has-subfooter":"")+(d.$hasTabs?" has-tabs":"")+(d.$hasTabsTop?" has-tabs-top":"")},function(e,t){i.removeClass(t),i.addClass(e)}),e.$hasHeader=e.$hasSubheader=e.$hasFooter=e.$hasSubfooter=e.$hasTabs=e.$hasTabsTop=!1,n(e,r,{$onScroll:"&onScroll",$onScrollComplete:"&onScrollComplete",hasBouncing:"@",padding:"@",direction:"@",scrollbarX:"@",scrollbarY:"@",startX:"@",startY:"@",scrollEventInterval:"@"}),e.direction=e.direction||"y",u(r.padding)&&e.$watch(r.padding,function(e){(a||i).toggleClass("padding",!!e)}),"false"===r.scroll);else{var f={};s?(i.addClass("overflow-scroll"),f={el:i[0],delegateHandle:o.delegateHandle,startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,nativeScrolling:!0}):f={el:i[0],delegateHandle:o.delegateHandle,locking:"true"===(o.locking||"true"),bouncing:e.$eval(e.hasBouncing),startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,scrollEventInterval:parseInt(e.scrollEventInterval,10)||10,scrollingComplete:l},c=t("$ionicScroll",{$scope:e,scrollViewOptions:f}),e.$on("$destroy",function(){f&&(f.scrollingComplete=p,delete f.el),a=null,i=null,o.$$element=null})}}var a,c;e.addClass("scroll-content ionic-scroll"),"false"!=o.scroll?(a=h('<div class="scroll"></div>'),a.append(e.contents()),e.append(a)):e.addClass("scroll-content-false");var s="true"===o.overflowScroll||!i.scrolling.jsScrolling();return s&&(s=!e[0].querySelector("[collection-repeat]")),{pre:r}}}}]),c.directive("exposeAsideWhen",["$window",function(e){return{restrict:"A",require:"^ionSideMenus",link:function(t,n,i,o){function r(){var t="large"==i.exposeAsideWhen?"(min-width:768px)":i.exposeAsideWhen;o.exposeAside(e.matchMedia(t).matches),o.activeAsideResizing(!1)}function a(){o.activeAsideResizing(!0),c()}var c=ionic.debounce(function(){t.$apply(r)},300,!1);t.$evalAsync(r),ionic.on("resize",a,e),t.$on("$destroy",function(){ionic.off("resize",a,e)})}}}]);var k="onHold onTap onDoubleTap onTouch onRelease onDragStart onDrag onDragEnd onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeDown onSwipeLeft".split(" ");k.forEach(function(e){c.directive(e,n(e))}),c.directive("ionHeaderBar",i()).directive("ionHeaderBar",o(!0)).directive("ionFooterBar",o(!1)),c.directive("ionInfiniteScroll",["$timeout",function(e){return{restrict:"E",require:["?^$ionicScroll","ionInfiniteScroll"],template:function(e,t){return t.icon?'<i class="icon {{icon()}} icon-refreshing {{scrollingType}}"></i>':'<ion-spinner icon="{{spinner()}}"></ion-spinner>'},scope:!0,controller:"$ionInfiniteScroll",link:function(t,n,i,o){var r=o[1],a=r.scrollCtrl=o[0],c=r.jsScrolling=!a.isNative();if(c)r.scrollView=a.scrollView,t.scrollingType="js-scrolling",a.$element.on("scroll",r.checkBounds);else{var s=ionic.DomUtil.getParentOrSelfWithClass(n[0].parentNode,"overflow-scroll");if(r.scrollEl=s,!s)throw"Infinite scroll must be used inside a scrollable div";r.scrollEl.addEventListener("scroll",r.checkBounds)}var l=u(i.immediateCheck)?t.$eval(i.immediateCheck):!0;l&&e(function(){r.checkBounds()})}}}]),c.directive("ionItem",["$$rAF",function(e){return{restrict:"E",controller:["$scope","$element",function(e,t){this.$scope=e,this.$element=t}],scope:!0,compile:function(t,n){var i=u(n.href)||u(n.ngHref)||u(n.uiSref),o=i||/ion-(delete|option|reorder)-button/i.test(t.html());if(o){var r=h(i?"<a></a>":"<div></div>");r.addClass("item-content"),(u(n.href)||u(n.ngHref))&&(r.attr("ng-href","{{$href()}}"),u(n.target)&&r.attr("target","{{$target()}}")),r.append(t.contents()),t.addClass("item item-complex").append(r)}else t.addClass("item");return function(t,n,i){t.$href=function(){return i.href||i.ngHref},t.$target=function(){return i.target};var o=n[0].querySelector(".item-content");o&&t.$on("$collectionRepeatLeave",function(){o&&o.$$ionicOptionsOpen&&(o.style[ionic.CSS.TRANSFORM]="",o.style[ionic.CSS.TRANSITION]="none",e(function(){o.style[ionic.CSS.TRANSITION]=""}),o.$$ionicOptionsOpen=!1)})}}}}]);var C='<div class="item-left-edit item-delete enable-pointer-events"></div>';c.directive("ionDeleteButton",function(){function e(e){e.stopPropagation()}return{restrict:"E",require:["^^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),function(t,n,i,o){function r(){c=c||n.controller("ionList"),c&&c.showDelete()&&s.addClass("visible active")}var a=o[0],c=o[1],s=h(C);s.append(n),a.$element.append(s).addClass("item-left-editable"),n.on("click",e),r(),t.$on("$ionic.reconnectScope",r)}}}}),c.directive("itemFloatingLabel",function(){return{restrict:"C",link:function(e,t){var n=t[0],i=n.querySelector("input, textarea"),o=n.querySelector(".input-label");if(i&&o){var r=function(){i.value?o.classList.add("has-input"):o.classList.remove("has-input")};i.addEventListener("input",r);var a=h(i).controller("ngModel");a&&(a.$render=function(){i.value=a.$viewValue||"",r()}),e.$on("$destroy",function(){i.removeEventListener("input",r)})}}}});var T='<div class="item-options invisible"></div>';c.directive("ionOptionButton",[function(){function e(e){e.stopPropagation()}return{restrict:"E",require:"^ionItem",priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button",!0),function(t,n,i,o){o.optionsContainer||(o.optionsContainer=h(T),o.$element.append(o.optionsContainer)),o.optionsContainer.append(n),o.$element.addClass("item-right-editable"),n.on("click",e)}}}}]);var B='<div data-prevent-scroll="true" class="item-right-edit item-reorder enable-pointer-events"></div>';c.directive("ionReorderButton",["$parse",function(e){return{restrict:"E",require:["^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),t[0].setAttribute("data-prevent-scroll",!0),function(t,n,i,o){var r=o[0],a=o[1],c=e(i.onReorder);t.$onReorder=function(e,n){c(t,{$fromIndex:e,$toIndex:n})},i.ngClick||i.onClick||i.onclick||(n[0].onclick=function(e){return e.stopPropagation(),!1});var s=h(B);s.append(n),r.$element.append(s).addClass("item-right-editable"),a&&a.showReorder()&&s.addClass("visible active")}}}}]),c.directive("keyboardAttach",function(){return function(e,t){function n(e){if(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen){var n=e.keyboardHeight||e.detail.keyboardHeight;t.css("bottom",n+"px"),o=t.controller("$ionicScroll"),o&&(o.scrollView.__container.style.bottom=n+r(t[0])+"px")}}function i(){(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen)&&(t.css("bottom",""),o&&(o.scrollView.__container.style.bottom=""))}ionic.on("native.keyboardshow",n,window), -ionic.on("native.keyboardhide",i,window),ionic.on("native.showkeyboard",n,window),ionic.on("native.hidekeyboard",i,window);var o;e.$on("$destroy",function(){ionic.off("native.keyboardshow",n,window),ionic.off("native.keyboardhide",i,window),ionic.off("native.showkeyboard",n,window),ionic.off("native.hidekeyboard",i,window)})}}),c.directive("ionList",["$timeout",function(e){return{restrict:"E",require:["ionList","^?$ionicScroll"],controller:"$ionicList",compile:function(t,n){var i=h('<div class="list">').append(t.contents()).addClass(n.type);return t.append(i),function(t,i,o,r){function a(){function o(e,t){t()&&e.addClass("visible")||e.removeClass("active"),ionic.requestAnimationFrame(function(){t()&&e.addClass("active")||e.removeClass("visible")})}var r=c.listView=new ionic.views.ListView({el:i[0],listEl:i.children()[0],scrollEl:s&&s.element,scrollView:s&&s.scrollView,onReorder:function(t,n,i){var o=h(t).scope();o&&o.$onReorder&&e(function(){o.$onReorder(n,i)})},canSwipe:function(){return c.canSwipeItems()}});t.$on("$destroy",function(){r&&(r.deregister&&r.deregister(),r=null)}),u(n.canSwipe)&&t.$watch("!!("+n.canSwipe+")",function(e){c.canSwipeItems(e)}),u(n.showDelete)&&t.$watch("!!("+n.showDelete+")",function(e){c.showDelete(e)}),u(n.showReorder)&&t.$watch("!!("+n.showReorder+")",function(e){c.showReorder(e)}),t.$watch(function(){return c.showDelete()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-left-editing",e),i.toggleClass("disable-pointer-events",e);var n=h(i[0].getElementsByClassName("item-delete"));o(n,c.showDelete)}}),t.$watch(function(){return c.showReorder()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-right-editing",e),i.toggleClass("disable-pointer-events",e);var n=h(i[0].getElementsByClassName("item-reorder"));o(n,c.showReorder)}})}var c=r[0],s=r[1];e(a)}}}}]),c.directive("menuClose",["$ionicHistory",function(e){return{restrict:"AC",link:function(t,n){n.bind("click",function(){var t=n.inheritedData("$ionSideMenusController");t&&(e.nextViewOptions({historyRoot:!0,disableAnimate:!0,expire:300}),t.close())})}}}]),c.directive("menuToggle",function(){return{restrict:"AC",link:function(e,t,n){e.$on("$ionicView.beforeEnter",function(e,n){if(n.enableBack){var i=t.inheritedData("$ionSideMenusController");i.enableMenuWithBackViews()||t.addClass("hide")}else t.removeClass("hide")}),t.bind("click",function(){var e=t.inheritedData("$ionSideMenusController");e&&e.toggle(n.menuToggle)})}}}),c.directive("ionModal",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="modal-backdrop"><div class="modal-backdrop-bg"></div><div class="modal-wrapper" ng-transclude></div></div>'}}]),c.directive("ionModalView",function(){return{restrict:"E",compile:function(e){e.addClass("modal")}}}),c.directive("ionNavBackButton",["$ionicConfig","$document",function(e,t){return{restrict:"E",require:"^ionNavBar",compile:function(n,i){function o(e){return/ion-|icon/.test(e.className)}var r=t[0].createElement("button");for(var a in i.$attr)r.setAttribute(i.$attr[a],i[a]);i.ngClick||r.setAttribute("ng-click","$ionicGoBack()"),r.className="button back-button hide buttons "+(n.attr("class")||""),r.innerHTML=n.html()||"";for(var c,s,l,u,d=o(n[0]),f=0;f<n[0].childNodes.length;f++)c=n[0].childNodes[f],1===c.nodeType?o(c)?d=!0:c.classList.contains("default-title")?l=!0:c.classList.contains("previous-title")&&(u=!0):s||3!==c.nodeType||(s=!!c.nodeValue.trim());var h=e.backButton.icon();if(!d&&h&&"none"!==h&&(r.innerHTML='<i class="icon '+h+'"></i> '+r.innerHTML,r.className+=" button-clear"),!s){var p=t[0].createElement("span");p.className="back-text",!l&&e.backButton.text()&&(p.innerHTML+='<span class="default-title">'+e.backButton.text()+"</span>"),!u&&e.backButton.previousTitleText()&&(p.innerHTML+='<span class="previous-title"></span>'),r.appendChild(p)}return n.attr("class","hide"),n.empty(),{pre:function(e,t,n,i){i.navElement("backButton",r.outerHTML),r=null}}}}}]),c.directive("ionNavBar",function(){return{restrict:"E",controller:"$ionicNavBar",scope:!0,link:function(e,t,n,i){i.init()}}}),c.directive("ionNavButtons",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="left";/^primary|secondary|right$/i.test(n.side||"")&&(i=n.side.toLowerCase());var o=e[0].createElement("span");o.className=i+"-buttons",o.innerHTML=t.html();var r=i+"Buttons";return t.attr("class","hide"),t.empty(),{pre:function(e,t,n,i){var a=t.parent().data("$ionViewController");a?a.navElement(r,o.outerHTML):i.navElement(r,o.outerHTML),o=null}}}}}]),c.directive("navDirection",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextDirection(i.navDirection)})}}}]),c.directive("ionNavTitle",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="title",o=e[0].createElement("span");for(var r in n.$attr)o.setAttribute(n.$attr[r],n[r]);return o.classList.add("nav-bar-title"),o.innerHTML=t.html(),t.attr("class","hide"),t.empty(),{pre:function(e,t,n,r){var a=t.parent().data("$ionViewController");a?a.navElement(i,o.outerHTML):r.navElement(i,o.outerHTML),o=null}}}}}]),c.directive("navTransition",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextTransition(i.navTransition)})}}}]),c.directive("ionNavView",["$state","$ionicConfig",function(e,t){return{restrict:"E",terminal:!0,priority:2e3,transclude:!0,controller:"$ionicNavView",compile:function(n,i,o){return n.addClass("view-container"),ionic.DomUtil.cachedAttr(n,"nav-view-transition",t.views.transition()),function(t,n,i,r){function a(t){var n=e.$current&&e.$current.locals[s.name];n&&(t||n!==c)&&(c=n,s.state=n.$$state,r.register(n))}var c;o(t,function(e){n.append(e)});var s=r.init();t.$on("$stateChangeSuccess",function(){a(!1)}),t.$on("$viewContentLoading",function(){a(!1)}),a(!0)}}}}]),c.config(["$provide",function(e){e.decorator("ngClickDirective",["$delegate",function(e){return e.shift(),e}])}]).factory("$ionicNgClick",["$parse",function(e){return function(t,n,i){var o=angular.isFunction(i)?i:e(i);n.on("click",function(e){t.$apply(function(){o(t,{$event:e})})}),n.onclick=p}}]).directive("ngClick",["$ionicNgClick",function(e){return function(t,n,i){e(t,n,i.ngClick)}}]).directive("ionStopEvent",function(){return{restrict:"A",link:function(e,t,n){t.bind(n.ionStopEvent,a)}}}),c.directive("ionPane",function(){return{restrict:"E",link:function(e,t){t.addClass("pane")}}}),c.directive("ionPopover",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="popover-backdrop"><div class="popover-wrapper" ng-transclude></div></div>'}}]),c.directive("ionPopoverView",function(){return{restrict:"E",compile:function(e){e.append(h('<div class="popover-arrow">')),e.addClass("popover")}}}),c.directive("ionRadio",function(){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-radio"><input type="radio" name="radio-group"><div class="item-content disable-pointer-events" ng-transclude></div><i class="radio-icon disable-pointer-events icon ion-checkmark"></i></label>',compile:function(e,t){t.icon&&e.children().eq(2).removeClass("ion-checkmark").addClass(t.icon);var n=e.find("input");return l({name:t.name,value:t.value,disabled:t.disabled,"ng-value":t.ngValue,"ng-model":t.ngModel,"ng-disabled":t.ngDisabled,"ng-change":t.ngChange,"ng-required":t.ngRequired,required:t.required},function(e,t){u(e)&&n.attr(t,e)}),function(e,t,n){e.getValue=function(){return e.ngValue||n.value}}}}}),c.directive("ionRefresher",[function(){return{restrict:"E",replace:!0,require:["?^$ionicScroll","ionRefresher"],controller:"$ionicRefresher",template:'<div class="scroll-refresher invisible" collection-repeat-ignore><div class="ionic-refresher-content" ng-class="{\'ionic-refresher-with-text\': pullingText || refreshingText}"><div class="icon-pulling" ng-class="{\'pulling-rotation-disabled\':disablePullingRotation}"><i class="icon {{pullingIcon}}"></i></div><div class="text-pulling" ng-bind-html="pullingText"></div><div class="icon-refreshing"><ion-spinner ng-if="showSpinner" icon="{{spinner}}"></ion-spinner><i ng-if="showIcon" class="icon {{refreshingIcon}}"></i></div><div class="text-refreshing" ng-bind-html="refreshingText"></div></div></div>',link:function(e,t,n,i){var o=i[0],r=i[1];!o||o.isNative()?r.init():(t[0].classList.add("js-scrolling"),o._setRefresher(e,t[0],r.getRefresherDomMethods()),e.$on("scroll.refreshComplete",function(){e.$evalAsync(function(){o.scrollView.finishPullToRefresh()})}))}}}]),c.directive("ionScroll",["$timeout","$controller","$ionicBind",function(e,t,n){return{restrict:"E",scope:!0,controller:function(){},compile:function(e){function i(e,i,r){n(e,r,{direction:"@",paging:"@",$onScroll:"&onScroll",scroll:"@",scrollbarX:"@",scrollbarY:"@",zooming:"@",minZoom:"@",maxZoom:"@"}),e.direction=e.direction||"y",u(r.padding)&&e.$watch(r.padding,function(e){o.toggleClass("padding",!!e)}),e.$eval(e.paging)===!0&&o.addClass("scroll-paging"),e.direction||(e.direction="y");var a=e.$eval(e.paging)===!0,c={el:i[0],delegateHandle:r.delegateHandle,locking:"true"===(r.locking||"true"),bouncing:e.$eval(r.hasBouncing),paging:a,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,zooming:e.$eval(e.zooming)===!0,maxZoom:e.$eval(e.maxZoom)||3,minZoom:e.$eval(e.minZoom)||.5,preventDefault:!0};a&&(c.speedMultiplier=.8,c.bouncing=!1),t("$ionicScroll",{$scope:e,scrollViewOptions:c})}e.addClass("scroll-view ionic-scroll");var o=h('<div class="scroll"></div>');return o.append(e.contents()),e.append(o),{pre:i}}}}]),c.directive("ionSideMenu",function(){return{restrict:"E",require:"^ionSideMenus",scope:!0,compile:function(e,t){return angular.isUndefined(t.isEnabled)&&t.$set("isEnabled","true"),angular.isUndefined(t.width)&&t.$set("width","275"),e.addClass("menu menu-"+t.side),function(e,n,i,o){e.side=i.side||"left";var r=o[e.side]=new ionic.views.SideMenu({width:t.width,el:n[0],isEnabled:!0});e.$watch(i.width,function(e){var t=+e;t&&t==e&&r.setWidth(+e)}),e.$watch(i.isEnabled,function(e){r.setIsEnabled(!!e)})}}}}),c.directive("ionSideMenuContent",["$timeout","$ionicGesture","$window",function(e,t,n){return{restrict:"EA",require:"^ionSideMenus",scope:!0,compile:function(i,o){function r(r,a,c,s){function l(e){0!==s.getOpenAmount()?(s.close(),e.gesture.srcEvent.preventDefault(),v=null,g=null):v||(v=ionic.tap.pointerCoord(e.gesture.srcEvent))}function d(e){s.isDraggableTarget(e)&&"x"==p(e)&&(s._handleDrag(e),e.gesture.srcEvent.preventDefault())}function f(e){"x"==p(e)&&e.gesture.srcEvent.preventDefault()}function h(e){s._endDrag(e),v=null,g=null}function p(e){if(g)return g;if(e&&e.gesture){if(v){var t=ionic.tap.pointerCoord(e.gesture.srcEvent),n=Math.abs(t.x-v.x),i=Math.abs(t.y-v.y),o=i>n?"y":"x";return Math.max(n,i)>30&&(g=o),o}v=ionic.tap.pointerCoord(e.gesture.srcEvent)}return"y"}var v=null,g=null;u(o.dragContent)?r.$watch(o.dragContent,function(e){s.canDragContent(e)}):s.canDragContent(!0),u(o.edgeDragThreshold)&&r.$watch(o.edgeDragThreshold,function(e){s.edgeDragThreshold(e)});var m={element:i[0],onDrag:function(){},endDrag:function(){},getTranslateX:function(){return r.sideMenuContentTranslateX||0},setTranslateX:ionic.animationFrameThrottle(function(t){var n=m.offsetX+t;a[0].style[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e(function(){r.sideMenuContentTranslateX=t})}),setMarginLeft:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style[ionic.CSS.TRANSFORM]="translate3d("+e+"px,0,0)",a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)",a[0].style.width="",m.offsetX=0)}),setMarginRight:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style.width="",m.offsetX=0),a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)"}),enableAnimation:function(){r.animationEnabled=!0,a[0].classList.add("menu-animated")},disableAnimation:function(){r.animationEnabled=!1,a[0].classList.remove("menu-animated")},offsetX:0};s.setContent(m);var $={stop_browser_behavior:!1};ionic.DomUtil.getParentOrSelfWithClass(a[0],"overflow-scroll")&&($.prevent_default_directions=["left","right"]);var w=t.on("tap",l,a,$),b=t.on("dragright",d,a,$),y=t.on("dragleft",d,a,$),S=t.on("dragup",f,a,$),k=t.on("dragdown",f,a,$),C=t.on("release",h,a,$);r.$on("$destroy",function(){m&&(m.element=null,m=null),t.off(y,"dragleft",d),t.off(b,"dragright",d),t.off(S,"dragup",f),t.off(k,"dragdown",f),t.off(C,"release",h),t.off(w,"tap",l)})}return i.addClass("menu-content pane"),{pre:r}}}}]),c.directive("ionSideMenus",["$ionicBody",function(e){return{restrict:"ECA",controller:"$ionicSideMenus",compile:function(t,n){function i(t,n,i,o){o.enableMenuWithBackViews(t.$eval(i.enableMenuWithBackViews)),t.$on("$ionicExposeAside",function(n,i){t.$exposeAside||(t.$exposeAside={}),t.$exposeAside.active=i,e.enableClass(i,"aside-open")}),t.$on("$ionicView.beforeEnter",function(e,n){n.historyId&&(t.$activeHistoryId=n.historyId)}),t.$on("$destroy",function(){e.removeClass("menu-open","aside-open")})}return n.$set("class",(n["class"]||"")+" view"),{pre:i}}}}]),c.directive("ionSlideBox",["$timeout","$compile","$ionicSlideBoxDelegate","$ionicHistory","$ionicScrollDelegate",function(e,t,n,i,o){return{restrict:"E",replace:!0,transclude:!0,scope:{autoPlay:"=",doesContinue:"@",slideInterval:"@",showPager:"@",pagerClick:"&",disableScroll:"@",onSlideChanged:"&",activeSlide:"=?"},controller:["$scope","$element","$attrs",function(t,r,a){function c(e){e&&!s.isScrollFreeze?o.freezeAllScrolls(e):!e&&s.isScrollFreeze&&o.freezeAllScrolls(!1),s.isScrollFreeze=e}var s=this,l=t.$eval(t.doesContinue)===!0,d=u(a.autoPlay)?!!t.autoPlay:!1,f=d?t.$eval(t.slideInterval)||4e3:0,h=new ionic.views.Slider({el:r[0],auto:f,continuous:l,startSlide:t.activeSlide,slidesChanged:function(){t.currentSlide=h.currentIndex(),e(function(){})},callback:function(n){t.currentSlide=n,t.onSlideChanged({index:t.currentSlide,$index:t.currentSlide}),t.$parent.$broadcast("slideBox.slideChanged",n),t.activeSlide=n,e(function(){})},onDrag:function(){c(!0)},onDragEnd:function(){c(!1)}});h.enableSlide(t.$eval(a.disableScroll)!==!0),t.$watch("activeSlide",function(e){u(e)&&h.slide(e)}),t.$on("slideBox.nextSlide",function(){h.next()}),t.$on("slideBox.prevSlide",function(){h.prev()}),t.$on("slideBox.setSlide",function(e,t){h.slide(t)}),this.__slider=h;var p=n._registerInstance(h,a.delegateHandle,function(){return i.isActiveScope(t)});t.$on("$destroy",function(){p(),h.kill()}),this.slidesCount=function(){return h.slidesCount()},this.onPagerClick=function(e){t.pagerClick({index:e})},e(function(){h.load()})}],template:'<div class="slider"><div class="slider-slides" ng-transclude></div></div>',link:function(e,n,i){function o(){if(!r){var i=e.$new();r=h("<ion-pager></ion-pager>"),n.append(r),r=t(r)(i)}return r}u(i.showPager)||(e.showPager=!0,o().toggleClass("hide",!1)),i.$observe("showPager",function(t){t=e.$eval(t),o().toggleClass("hide",!t)});var r}}}]).directive("ionSlide",function(){return{restrict:"E",require:"^ionSlideBox",compile:function(e){e.addClass("slider-slide")}}}).directive("ionPager",function(){return{restrict:"E",replace:!0,require:"^ionSlideBox",template:'<div class="slider-pager"><span class="slider-pager-page" ng-repeat="slide in numSlides() track by $index" ng-class="{active: $index == currentSlide}" ng-click="pagerClick($index)"><i class="icon ion-record"></i></span></div>',link:function(e,t,n,i){var o=function(e){for(var n=t[0].children,i=n.length,o=0;i>o;o++)o==e?n[o].classList.add("active"):n[o].classList.remove("active")};e.pagerClick=function(e){i.onPagerClick(e)},e.numSlides=function(){return new Array(i.slidesCount())},e.$watch("currentSlide",function(e){o(e)})}}}),c.directive("ionSpinner",function(){return{restrict:"E",controller:"$ionicSpinner",link:function(e,t,n,i){var o=i.init();t.addClass("spinner spinner-"+o)}}}),c.directive("ionTab",["$compile","$ionicConfig","$ionicBind","$ionicViewSwitcher",function(e,t,n,i){function o(e,t){return u(t)?" "+e+'="'+t+'"':""}return{restrict:"E",require:["^ionTabs","ionTab"],controller:"$ionicTab",scope:!0,compile:function(r,a){for(var c="<ion-tab-nav"+o("ng-click",a.ngClick)+o("title",a.title)+o("icon",a.icon)+o("icon-on",a.iconOn)+o("icon-off",a.iconOff)+o("badge",a.badge)+o("badge-style",a.badgeStyle)+o("hidden",a.hidden)+o("disabled",a.disabled)+o("class",a["class"])+"></ion-tab-nav>",s=document.createElement("div"),l=0;l<r[0].children.length;l++)s.appendChild(r[0].children[l].cloneNode(!0));var u=s.childElementCount;r.empty();var d,f;return u&&("ION-NAV-VIEW"===s.children[0].tagName&&(d=s.children[0].getAttribute("name"),s.children[0].classList.add("view-container"),f=!0),1===u&&(s=s.children[0]),f||s.classList.add("pane"),s.classList.add("tab-content")),function(o,r,a,l){function f(){w.tabMatchesState()&&$.select(o,!1)}function p(n){n&&u?(b||(g=o.$new(),m=h(s),i.viewEleIsActive(m,!0),$.$element.append(m),e(m)(g),b=!0),i.viewEleIsActive(m,!0)):b&&m&&(t.views.maxCache()>0?i.viewEleIsActive(m,!1):v())}function v(){g&&g.$destroy(),b&&m&&m.remove(),s.innerHTML="",b=g=m=null}var g,m,$=l[0],w=l[1],b=!1;o.$tabSelected=!1,n(o,a,{onSelect:"&",onDeselect:"&",title:"@",uiSref:"@",href:"@"}),$.add(o),o.$on("$destroy",function(){o.$tabsDestroy||$.remove(o),y.isolateScope().$destroy(),y.remove(),y=s=m=null}),r[0].removeAttribute("title"),d&&(w.navViewName=o.navViewName=d),o.$on("$stateChangeSuccess",f),f();var y=h(c);y.data("$ionTabsController",$),y.data("$ionTabController",w),$.$tabsElement.append(e(y)(o)),o.$watch("$tabSelected",p),o.$on("$ionicView.afterEnter",function(){i.viewEleIsActive(m,o.$tabSelected)}),o.$on("$ionicView.clearCache",function(){o.$tabSelected||v()})}}}}]),c.directive("ionTabNav",[function(){return{restrict:"E",replace:!0,require:["^ionTabs","^ionTab"],template:"<a ng-class=\"{'tab-item-active': isTabActive(), 'has-badge':badge, 'tab-hidden':isHidden()}\" "+' ng-disabled="disabled()" class="tab-item"><span class="badge {{badgeStyle}}" ng-if="badge">{{badge}}</span><i class="icon {{getIconOn()}}" ng-if="getIconOn() && isTabActive()"></i><i class="icon {{getIconOff()}}" ng-if="getIconOff() && !isTabActive()"></i><span class="tab-title" ng-bind-html="title"></span></a>',scope:{title:"@",icon:"@",iconOn:"@",iconOff:"@",badge:"=",hidden:"@",disabled:"&",badgeStyle:"@","class":"@"},link:function(e,t,n,i){var o=i[0],r=i[1];t[0].removeAttribute("title"),e.selectTab=function(e){e.preventDefault(),o.select(r.$scope,!0)},n.ngClick||t.on("click",function(t){e.$apply(function(){e.selectTab(t)})}),e.isHidden=function(){return"true"===n.hidden||n.hidden===!0?!0:!1},e.getIconOn=function(){return e.iconOn||e.icon},e.getIconOff=function(){return e.iconOff||e.icon},e.isTabActive=function(){return o.selectedTab()===r.$scope}}}}]),c.directive("ionTabs",["$ionicTabsDelegate","$ionicConfig",function(e,t){return{restrict:"E",scope:!0,controller:"$ionicTabs",compile:function(n){function i(t,n,i,o){function a(e,t){e.stopPropagation();var n=o.previousSelectedTab();n&&n.$broadcast(e.name.replace("NavView","Tabs"),t)}var c=e._registerInstance(o,i.delegateHandle,o.hasActiveScope);o.$scope=t,o.$element=n,o.$tabsElement=h(n[0].querySelector(".tabs")),t.$watch(function(){return n[0].className},function(e){var n=-1!==e.indexOf("tabs-top"),i=-1!==e.indexOf("tabs-item-hide");t.$hasTabs=!n&&!i,t.$hasTabsTop=n&&!i,t.$emit("$ionicTabs.top",t.$hasTabsTop)}),t.$on("$ionicNavView.beforeLeave",a),t.$on("$ionicNavView.afterLeave",a),t.$on("$ionicNavView.leave",a),t.$on("$destroy",function(){t.$tabsDestroy=!0,c(),o.$tabsElement=o.$element=o.$scope=r=null,delete t.$hasTabs,delete t.$hasTabsTop})}function o(e,t,n,i){i.selectedTab()||i.select(0)}var r=h('<div class="tab-nav tabs">');return r.append(n.contents()),n.append(r).addClass("tabs-"+t.tabs.position()+" tabs-"+t.tabs.style()),{pre:i,post:o}}}}]),c.directive("ionToggle",["$timeout","$ionicConfig",function(e,t){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<div class="item item-toggle"><div ng-transclude></div><label class="toggle"><input type="checkbox"><div class="track"><div class="handle"></div></div></label></div>',compile:function(e,n){var i=e.find("input");return l({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){u(e)&&i.attr(t,e)}),n.toggleClass&&e[0].getElementsByTagName("label")[0].classList.add(n.toggleClass),e.addClass("toggle-"+t.form.toggle()),function(e,t){var n=t[0].getElementsByTagName("label")[0],i=n.children[0],o=n.children[1],r=o.children[0],a=h(i).controller("ngModel");e.toggle=new ionic.views.Toggle({el:n,track:o,checkbox:i,handle:r,onChange:function(){a&&(a.$setViewValue(i.checked),e.$apply())}}),e.$on("$destroy",function(){e.toggle.destroy()})}}}}]),c.directive("ionView",function(){return{restrict:"EA",priority:1e3,controller:"$ionicView",compile:function(e){return e.addClass("pane"),e[0].removeAttribute("title"),function(e,t,n,i){i.init()}}}})}(); \ No newline at end of file +!function(){function e(e,t,n,i,o,r){function a(i,a,c,s,u){function d(){N.resizeRequiresRefresh(w.__clientWidth,w.__clientHeight)&&g()}function f(){var e;return e={dataLength:0,width:0,height:0,resizeRequiresRefresh:function(t,n){var i=e.dataLength&&t&&n&&(t!==e.width||n!==e.height);return e.width=t,e.height=n,!!i},dataChangeRequiresRefresh:function(t){var n=t.length>0||t.length<e.dataLength;return e.dataLength=t.length,!!n}}}function h(){return T||(T=new e({afterItemsNode:M[0],containerNode:S,heightData:A,widthData:E,forceRefreshImages:!(!l(c.forceRefreshImages)||"false"===c.forceRefreshImages),keyExpression:B,renderBuffer:D,scope:i,scrollView:s.scrollView,transclude:u}))}function p(){var e=angular.element(w.__content.querySelector(".collection-repeat-after-container"));if(!e.length){var t=!1,n=[].filter.call(w.__content.childNodes,function(e){return ionic.DomUtil.contains(e,S)?(t=!0,!1):t});e=angular.element('<span class="collection-repeat-after-container">'),w.options.scrollingX&&e.addClass("horizontal"),e.append(n),w.__content.appendChild(e[0])}return e}function v(){L?m(L,A):A.computed=!0,R?m(R,E):E.computed=!0}function g(){var e=P.length>0;if(e&&(A.computed||E.computed)&&$(),e&&A.computed){if(A.value=V.height,!A.value)throw new Error('collection-repeat tried to compute the height of repeated elements "'+k+'", but was unable to. Please provide the "item-height" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!A.dynamic&&A.getValue&&(A.value=A.getValue());if(e&&E.computed){if(E.value=V.width,!E.value)throw new Error('collection-repeat tried to compute the width of repeated elements "'+k+'", but was unable to. Please provide the "item-width" attribute. http://ionicframework.com/docs/api/directive/collectionRepeat/')}else!E.dynamic&&E.getValue&&(E.value=E.getValue());h().refreshLayout()}function m(e,n){if(e){var i;try{i=t(e)}catch(o){e.trim().match(/\d+(px|%)$/)&&(e='"'+e+'"'),i=t(e)}var r=e.replace(/(\'|\"|px|%)/g,"").trim(),a=r.length&&!/([a-zA-Z]|\$|:|\?)/.test(r);if(n.attrValue=e,a)if(e.indexOf("%")>-1){var c=parseFloat(i())/100;n.getValue=n===A?function(){return Math.floor(c*w.__clientHeight)}:function(){return Math.floor(c*w.__clientWidth)}}else n.value=parseInt(i());else n.dynamic=!0,n.getValue=n===A?function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseFloat(n)/100*w.__clientHeight):parseInt(n)}:function(e,t){var n=i(e,t);return n.charAt&&"%"===n.charAt(n.length-1)?Math.floor(parseFloat(n)/100*w.__clientWidth):parseInt(n)}}}function $(){O||u(H=i.$new(),function(e){e[0].removeAttribute("collection-repeat"),O=e[0]}),H[B]=(x(i)||[])[0],o.$$phase||H.$digest(),S.appendChild(O);var e=n.getComputedStyle(O);V.width=parseInt(e.width),V.height=parseInt(e.height),S.removeChild(O)}var w=s.scrollView,b=a[0],S=angular.element('<div class="collection-repeat-container">')[0];if(b.parentNode.replaceChild(S,b),w.options.scrollingX&&w.options.scrollingY)throw new Error("collection-repeat expected a parent x or y scrollView, not an xy scrollView.");var k=c.collectionRepeat,C=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!C)throw new Error("collection-repeat expected expression in form of '_item_ in _collection_[ track by _id_]' but got '"+c.collectionRepeat+"'.");var T,B=C[1],I=C[2],x=t(I),A={},E={},V={},P=[],_=c.itemRenderBuffer||c.collectionBufferSize,D=angular.isDefined(_)?parseInt(_):y,L=c.itemHeight||c.collectionItemHeight,R=c.itemWidth||c.collectionItemWidth,M=p(),N=f();v(),s.$element.on("scroll-resize",g),angular.element(n).on("resize",d);var z=o.$on("$ionicExposeAside",ionic.animationFrameThrottle(function(){s.scrollView.resize(),d()}));r(g,0,!1),i.$watchCollection(x,function(e){if(P=e||(e=[]),!angular.isArray(e))throw new Error("collection-repeat expected an array for '"+I+"', but got a "+typeof value);i.$$postDigest(function(){h().setData(P),N.dataChangeRequiresRefresh(P)&&g()})}),i.$on("$destroy",function(){angular.element(n).off("resize",d),z(),s.$element&&s.$element.off("scroll-resize",g),O&&O.parentNode&&O.parentNode.removeChild(O),H&&H.$destroy(),H=O=null,T&&T.destroy(),T=null});var O,H}return{restrict:"A",priority:1e3,transclude:"element",$$tlb:!0,require:"^^$ionicScroll",link:a}}function t(e,t,n){var i={primaryPos:0,secondaryPos:0,primarySize:0,secondarySize:0,rowPrimarySize:0};return function(o){function r(){return a(!0)}function a(t){if(!a.destroyed){var n,o,r,l,u,d=ee.getScrollValue(),f=d+ee.scrollPrimarySize;ee.updateRenderRange(d,f),F=Math.max(0,F-T),W=Math.min(A.length-1,W+T);for(n in Z)(F>n||n>W)&&(r=Z[n],delete Z[n],G.push(r),r.isShown=!1);for(n=F;W>=n;n++)n>=A.length||Z[n]&&!t||(r=Z[n]||(Z[n]=G.length?G.pop():j.length?j.shift():new s),K.push(r),r.isShown=!0,u=r.scope,u.$index=n,u[C]=A[n],u.$first=0===n,u.$last=n===A.length-1,u.$middle=!(u.$first||u.$last),u.$odd=!(u.$even=0===(1&n)),u.$$disconnected&&ionic.Utils.reconnectScope(r.scope),l=ee.getDimensions(n),(r.secondaryPos!==l.secondaryPos||r.primaryPos!==l.primaryPos)&&(r.node.style[ionic.CSS.TRANSFORM]=O.replace(N,r.primaryPos=l.primaryPos).replace(z,r.secondaryPos=l.secondaryPos)),(r.secondarySize!==l.secondarySize||r.primarySize!==l.primarySize)&&(r.node.style.cssText=r.node.style.cssText.replace(b,H.replace(N,(r.primarySize=l.primarySize)+1).replace(z,r.secondarySize=l.secondarySize))));for(W===A.length-1&&(l=ee.getDimensions(A.length-1)||i,m.style[ionic.CSS.TRANSFORM]=O.replace(N,l.primaryPos+l.primarySize).replace(z,0));G.length;)r=G.pop(),r.scope.$broadcast("$collectionRepeatLeave"),ionic.Utils.disconnectScope(r.scope),j.push(r),r.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",r.primaryPos=r.secondaryPos=null;if(y)for(n=0,o=K.length;o>n&&(r=K[n]);n++)if(r.images)for(var h,p=0,v=r.images.length;v>p&&(h=r.images[p]);p++){var g=h.src;h.src=w,h.src=g}if(t)for(var $=e.$$phase;K.length;)r=K.pop(),$||r.scope.$digest();else c()}}function c(){var t;c.running||(c.running=!0,n(function(){for(var n=e.$$phase;K.length;)t=K.pop(),t.isShown&&(n||t.scope.$digest());c.running=!1}))}function s(){var e=this;this.scope=B.$new(),this.id="item"+J++,x(this.scope,function(t){e.element=t,e.element.data("$$collectionRepeatItem",e),e.node=t[0],e.node.style[ionic.CSS.TRANSFORM]="translate3d(-9999px,-9999px,0)",e.node.style.cssText+=" height: 0px; width: 0px;",ionic.Utils.disconnectScope(e.scope),$.appendChild(e.node),e.images=t[0].getElementsByTagName("img")})}function l(){this.getItemPrimarySize=P,this.getItemSecondarySize=D,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollTop-q,I.__maxScrollTop-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientHeight,this.scrollSecondarySize=I.__clientWidth,this.estimatedPrimarySize=v,this.estimatedSecondarySize=g,this.estimatedItemsAcross=R&&Math.floor(I.__clientWidth/g)||1}}function u(){this.getItemPrimarySize=D,this.getItemSecondarySize=P,this.getScrollValue=function(){return Math.max(0,Math.min(I.__scrollLeft-q,I.__maxScrollLeft-q-U))},this.refreshDirection=function(){this.scrollPrimarySize=I.__clientWidth,this.scrollSecondarySize=I.__clientHeight,this.estimatedPrimarySize=g,this.estimatedSecondarySize=v,this.estimatedItemsAcross=R&&Math.floor(I.__clientHeight/v)||1}}function d(){this.getEstimatedSecondaryPos=function(e){return e%this.estimatedItemsAcross*this.estimatedSecondarySize},this.getEstimatedPrimaryPos=function(e){return Math.floor(e/this.estimatedItemsAcross)*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)*this.estimatedItemsAcross}}function f(){this.getEstimatedSecondaryPos=function(){return 0},this.getEstimatedPrimaryPos=function(e){return e*this.estimatedPrimarySize},this.getEstimatedIndex=function(e){return Math.floor(e/this.estimatedPrimarySize)}}function h(){this.getContentSize=function(){return this.getEstimatedPrimaryPos(A.length-1)+this.estimatedPrimarySize+q+U};var e={};this.getDimensions=function(t){return e.primaryPos=this.getEstimatedPrimaryPos(t),e.secondaryPos=this.getEstimatedSecondaryPos(t),e.primarySize=this.estimatedPrimarySize,e.secondarySize=this.estimatedSecondarySize,e},this.updateRenderRange=function(e,t){F=Math.max(0,this.getEstimatedIndex(e)),W=Math.min(A.length-1,this.getEstimatedIndex(t)+this.estimatedItemsAcross-1),Y=Math.max(0,this.getEstimatedPrimaryPos(F)),X=this.getEstimatedPrimaryPos(W)+this.estimatedPrimarySize}}function p(){function e(e){var t,r,a;for(t=Math.max(0,n);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.primarySize=o.getItemPrimarySize(t,A[t]),a.secondarySize=o.scrollSecondarySize,a.primaryPos=r.primaryPos+r.primarySize,a.secondaryPos=0}function t(e){var t,r,a;for(t=Math.max(n,0);e>=t&&(a=c[t]);t++)r=c[t-1]||i,a.secondarySize=Math.min(o.getItemSecondarySize(t,A[t]),o.scrollSecondarySize),a.secondaryPos=r.secondaryPos+r.secondarySize,0===t||a.secondaryPos+a.secondarySize>o.scrollSecondarySize?(a.secondaryPos=0,a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos+r.rowPrimarySize,a.rowStartIndex=t,a.rowPrimarySize=a.primarySize):(a.primarySize=o.getItemPrimarySize(t,A[t]),a.primaryPos=r.primaryPos,a.rowStartIndex=r.rowStartIndex,c[a.rowStartIndex].rowPrimarySize=a.rowPrimarySize=Math.max(c[a.rowStartIndex].rowPrimarySize,a.primarySize),a.rowPrimarySize=Math.max(a.primarySize,a.rowPrimarySize))}var n,o=this,r=ionic.debounce(Q,25,!0),a=R?t:e,c=[];this.getContentSize=function(){var e=c[n]||i;return(e.primaryPos+e.primarySize||0)+this.getEstimatedPrimaryPos(A.length-n-1)+q+U},this.onDestroy=function(){c.length=0},this.onRefreshData=function(){var e,t;for(e=c.length,t=A.length;t>e;e++)c.push({});n=-1},this.onRefreshLayout=function(){n=-1},this.getDimensions=function(e){return e=Math.min(e,A.length-1),e>n&&(e>.9*A.length?(a(A.length-1),n=A.length-1,Q()):(a(e),n=e,r())),c[e]};var s=-1,l=-1;this.updateRenderRange=function(e,t){var n,i,o;if(this.getDimensions(2*this.getEstimatedIndex(t)),-1===s||0===e)n=0;else if(e>=l)for(n=s,i=A.length;i>n&&!((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>=e);n++);else for(n=s;n>=0;n--)if((o=this.getDimensions(n))&&o.primaryPos<=e){n=R?o.rowStartIndex:n;break}F=Math.min(Math.max(0,n),A.length-1),Y=-1!==F?this.getDimensions(F).primaryPos:-1;var r;for(n=F+1,i=A.length;i>n;n++)if((o=this.getDimensions(n))&&o.primaryPos+o.rowPrimarySize>t){if(R)for(r=o;i-1>n&&(o=this.getDimensions(n+1)).primaryPos===r.primaryPos;)n++;break}W=Math.min(n,A.length-1),X=-1!==W?(o=this.getDimensions(W)).primaryPos+(o.rowPrimarySize||o.primarySize):-1,l=e,s=F}}var v,g,m=o.afterItemsNode,$=o.containerNode,y=o.forceRefreshImages,S=o.heightData,k=o.widthData,C=o.keyExpression,T=o.renderBuffer,B=o.scope,I=o.scrollView,x=o.transclude,A=[],E={},V=S.getValue||function(){return S.value},P=function(e,t){return E[C]=t,E.$index=e,V(B,E)},_=k.getValue||function(){return k.value},D=function(e,t){return E[C]=t,E.$index=e,_(B,E)},L=!!I.options.scrollingY,R=L?k.dynamic||k.value!==I.__clientWidth:S.dynamic||S.value!==I.__clientHeight,M=!S.dynamic&&!k.dynamic,N="PRIMARY",z="SECONDARY",O=L?"translate3d(SECONDARYpx,PRIMARYpx,0)":"translate3d(PRIMARYpx,SECONDARYpx,0)",H=L?"height: PRIMARYpx; width: SECONDARYpx;":"height: SECONDARYpx; width: PRIMARYpx;",q=0,U=0,F=-1,W=-1,X=-1,Y=-1,j=[],G=[],K=[],Z={},J=0,Q=L?function(){I.setDimensions(null,null,null,ee.getContentSize(),!0)}:function(){I.setDimensions(null,null,ee.getContentSize(),null,!0)},ee=L?new l:new u;(R?d:f).call(ee),(M?h:p).call(ee);var te=L?"getContentHeight":"getContentWidth",ne=I.options[te];I.options[te]=angular.bind(ee,ee.getContentSize),I.__$callback=I.__callback,I.__callback=function(e,t,n,i){var o=ee.getScrollValue();(-1===F||o+ee.scrollPrimarySize>X||Y>o)&&a(),I.__$callback(e,t,n,i)};var ie=!1,oe=!1;this.refreshLayout=function(){A.length?(v=P(0,A[0]),g=D(0,A[0])):(v=100,g=100);var e=getComputedStyle(m)||{},n=m.firstElementChild&&getComputedStyle(m.firstElementChild)||{},i=m.lastElementChild&&getComputedStyle(m.lastElementChild)||{};U=(parseInt(e[L?"height":"width"])||0)+(n&&parseInt(n[L?"marginTop":"marginLeft"])||0)+(i&&parseInt(i[L?"marginBottom":"marginRight"])||0),q=0;var o=$;do q+=o[L?"offsetTop":"offsetLeft"];while(ionic.DomUtil.contains(I.__content,o=o.offsetParent));var a=$.previousElementSibling,c=a?t.getComputedStyle(a):{},l=parseInt(c[L?"marginBottom":"marginRight"]||0);if($.style[ionic.CSS.TRANSFORM]=O.replace(N,-l).replace(z,0),q-=l,I.__clientHeight&&I.__clientWidth||(I.__clientWidth=I.__container.clientWidth,I.__clientHeight=I.__container.clientHeight),(ee.onRefreshLayout||angular.noop)(),ee.refreshDirection(),Q(),!ie)for(var u=Math.max(20,3*T),d=0;u>d;d++)j.push(new s);ie=!0,ie&&oe&&((I.__scrollLeft>I.__maxScrollLeft||I.__scrollTop>I.__maxScrollTop)&&I.resize(),r(!0))},this.setData=function(e){A=e,(ee.onRefreshData||angular.noop)(),oe=!0},this.destroy=function(){a.destroyed=!0,j.forEach(function(e){e.scope.$destroy(),e.scope=e.element=e.node=e.images=null}),j.length=K.length=G.length=0,Z={},I.options[te]=ne,I.__callback=I.__$callback,I.resize(),(ee.onDestroy||angular.noop)()}}}function n(e){return["$ionicGesture","$parse",function(t,n){var i=e.substr(2).toLowerCase();return function(o,r,a){var c=n(a[e]),s=function(e){o.$apply(function(){c(o,{$event:e})})},l=t.on(i,s,r);o.$on("$destroy",function(){t.off(l,i,s)})}}]}function i(e){return["$document","$timeout",function(t,n){return{restrict:"E",controller:"$ionicHeaderBar",compile:function(i){function o(t,n,i,o){e?(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subheader");t.$hasHeader=n&&!i,t.$hasSubheader=n&&i,t.$emit("$ionicSubheader",t.$hasSubheader)}),t.$on("$destroy",function(){delete t.$hasHeader,delete t.$hasSubheader}),o.align(),t.$on("$ionicHeader.align",function(){ionic.requestAnimationFrame(function(){o.align()})})):(t.$watch(function(){return n[0].className},function(e){var n=-1===e.indexOf("ng-hide"),i=-1!==e.indexOf("bar-subfooter");t.$hasFooter=n&&!i,t.$hasSubfooter=n&&i}),t.$on("$destroy",function(){delete t.$hasFooter,delete t.$hasSubfooter}),t.$watch("$hasTabs",function(e){n.toggleClass("has-tabs",!!e)}),o.align(),t.$on("$ionicFooter.align",function(){ionic.requestAnimationFrame(function(){o.align()})}))}return i.addClass(e?"bar bar-header":"bar bar-footer"),n(function(){e&&t[0].getElementsByClassName("tabs-top").length&&i.addClass("has-tabs-top")}),{pre:o}}}}]}function o(e){return e.clientHeight}function r(e){e.stopPropagation()}var a=angular.module("ionic",["ngAnimate","ngSanitize","ui.router","ngIOS9UIWebViewPatch"]),c=angular.extend,s=angular.forEach,l=angular.isDefined,u=angular.isNumber,d=angular.isString,f=angular.element,h=angular.noop;a.factory("$ionicActionSheet",["$rootScope","$compile","$animate","$timeout","$ionicTemplateLoader","$ionicPlatform","$ionicBody","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s){function l(o){function l(e){e&&/icon/.test(e)&&(u.$actionSheetHasIcon=!0)}var u=e.$new(!0);c(u,{cancel:h,destructiveButtonClicked:h,buttonClicked:h,$deregisterBackButton:h,buttons:[],cancelOnStateChange:!0},o||{});for(var d=0;d<u.buttons.length;d++)l(u.buttons[d].text);l(u.cancelText),l(u.destructiveText);var p=u.element=t('<ion-action-sheet ng-class="cssClass" buttons="buttons"></ion-action-sheet>')(u),v=f(p[0].querySelector(".action-sheet-wrapper")),g=u.cancelOnStateChange?e.$on("$stateChangeSuccess",function(){u.cancel()}):h;return u.removeSheet=function(e){u.removed||(u.removed=!0,v.removeClass("action-sheet-up"),i(function(){a.removeClass("action-sheet-open")},400),u.$deregisterBackButton(),g(),n.removeClass(p,"active").then(function(){u.$destroy(),p.remove(),u.cancel.$scope=v=null,(e||h)(o.buttons)}))},u.showSheet=function(e){u.removed||(a.append(p).addClass("action-sheet-open"),n.addClass(p,"active").then(function(){u.removed||(e||h)()}),i(function(){u.removed||v.addClass("action-sheet-up")},20,!1))},u.$deregisterBackButton=r.registerBackButtonAction(function(){i(u.cancel)},s.actionSheet),u.cancel=function(){u.removeSheet(o.cancel)},u.buttonClicked=function(e){o.buttonClicked(e,o.buttons[e])===!0&&u.removeSheet()},u.destructiveButtonClicked=function(){o.destructiveButtonClicked()===!0&&u.removeSheet()},u.showSheet(),u.cancel.$scope=u,u.cancel}return{show:l}}]),f.prototype.addClass=function(e){var t,n,i,o,r,a;if(e&&"ng-scope"!=e&&"ng-isolate-scope"!=e)for(t=0;t<this.length;t++)if(o=this[t],o.setAttribute)if(e.indexOf(" ")<0&&o.classList.add)o.classList.add(e);else{for(a=(" "+(o.getAttribute("class")||"")+" ").replace(/[\n\t]/g," "),r=e.split(" "),n=0;n<r.length;n++)i=r[n].trim(),-1===a.indexOf(" "+i+" ")&&(a+=i+" ");o.setAttribute("class",a.trim())}return this},f.prototype.removeClass=function(e){var t,n,i,o,r;if(e)for(t=0;t<this.length;t++)if(r=this[t],r.getAttribute)if(e.indexOf(" ")<0&&r.classList.remove)r.classList.remove(e);else for(i=e.split(" "),n=0;n<i.length;n++)o=i[n],r.setAttribute("class",(" "+(r.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+o.trim()+" "," ").trim());return this},a.factory("$ionicBackdrop",["$document","$timeout","$$rAF","$rootScope",function(e,t,n,i){function o(){s++,1===s&&(c.addClass("visible"),i.$broadcast("backdrop.shown"),n(function(){s>=1&&c.addClass("active")}))}function r(){1===s&&(c.removeClass("active"),i.$broadcast("backdrop.hidden"),t(function(){0===s&&c.removeClass("visible")},400,!1)),s=Math.max(0,s-1)}function a(){return c}var c=f('<div class="backdrop">'),s=0;return e[0].body.appendChild(c[0]),{retain:o,release:r,getElement:a,_element:c}}]),a.factory("$ionicBind",["$parse","$interpolate",function(e,t){var n=/^\s*([@=&])(\??)\s*(\w*)\s*$/;return function(i,o,r){s(r||{},function(r,a){var c,s,l=r.match(n)||[],u=l[3]||a,d=l[1];switch(d){case"@":if(!o[u])return;o.$observe(u,function(e){i[a]=e}),o[u]&&(i[a]=t(o[u])(i));break;case"=":if(!o[u])return;s=i.$watch(o[u],function(e){i[a]=e}),i.$on("$destroy",s);break;case"&":if(o[u]&&o[u].match(RegExp(a+"(.*?)")))throw new Error('& expression binding "'+a+'" looks like it will recursively call "'+o[u]+'" and cause a stack overflow! Please choose a different scopeName.');c=e(o[u]),i[a]=function(e){return c(i,e)}}})}}]),a.factory("$ionicBody",["$document",function(e){return{addClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.add(arguments[t]);return this},removeClass:function(){for(var t=0;t<arguments.length;t++)e[0].body.classList.remove(arguments[t]);return this},enableClass:function(e){var t=Array.prototype.slice.call(arguments).slice(1);return e?this.addClass.apply(this,t):this.removeClass.apply(this,t),this},append:function(t){return e[0].body.appendChild(t.length?t[0]:t),this},get:function(){return e[0].body}}}]),a.factory("$ionicClickBlock",["$document","$ionicBody","$timeout",function(e,t,n){function i(e){e.preventDefault(),e.stopPropagation()}function o(){s&&(a?a.classList.remove(l):(a=e[0].createElement("div"),a.className="click-block",t.append(a),a.addEventListener("touchstart",i),a.addEventListener("mousedown",i)),s=!1)}function r(){a&&a.classList.add(l)}var a,c,s,l="click-block-hide";return{show:function(e){s=!0,n.cancel(c),c=n(this.hide,e||310,!1),o()},hide:function(){s=!1,n.cancel(c),r()}}}]),a.factory("$ionicGesture",[function(){return{on:function(e,t,n,i){return window.ionic.onGesture(e,t,n[0],i)},off:function(e,t,n){return window.ionic.offGesture(e,t,n)}}}]),a.factory("$ionicHistory",["$rootScope","$state","$location","$window","$timeout","$ionicViewSwitcher","$ionicNavViewDelegate",function(e,t,n,i,o,r,a){function s(e){return e?R.views[e]:null}function u(e){return e?s(e.backViewId):null}function d(e){return e?s(e.forwardViewId):null}function f(e){return e?R.histories[e]:null}function h(e){var t=p(e);return R.histories[t.historyId]||(R.histories[t.historyId]={historyId:t.historyId,parentHistoryId:p(t.scope.$parent).historyId,stack:[],cursor:-1}),f(t.historyId)}function p(t){for(var n=t;n;){if(n.hasOwnProperty("$historyId"))return{historyId:n.$historyId,scope:n};n=n.$parent}return{historyId:"root",scope:e}}function v(e){R.currentView=s(e),R.backView=u(R.currentView),R.forwardView=d(R.currentView)}function g(){var e;if(t&&t.current&&t.current.name){if(e=t.current.name,t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&t.params[n]&&(e+="_"+n+"="+t.params[n]);return e}return ionic.Utils.nextUid()}function m(){var e;if(t&&t.params)for(var n in t.params)t.params.hasOwnProperty(n)&&(e=e||{},e[n]=t.params[n]);return e}function $(e){return e&&e.length&&/ion-side-menus|ion-tabs/i.test(e[0].tagName)}function w(e,t){return t&&t.$$state&&t.$$state.self.canSwipeBack===!1?!1:e&&"false"===e.attr("can-swipe-back")?!1:!0}var b,y,S,k,C,T="initialView",B="newView",I="moveBack",x="moveForward",A="back",E="forward",V="enter",P="exit",_="swap",D="none",L=0,R={histories:{root:{historyId:"root",parentHistoryId:null,stack:[],cursor:-1}},views:{},backView:null,forwardView:null,currentView:null},M=function(){};return M.prototype.initialize=function(e){if(e){for(var t in e)this[t]=e[t];return this}return null},M.prototype.go=function(){if(this.stateName)return t.go(this.stateName,this.stateParams);if(this.url&&this.url!==n.url()){if(R.backView===this)return i.history.go(-1);if(R.forwardView===this)return i.history.go(1);n.url(this.url)}return null},M.prototype.destroy=function(){this.scope&&(this.scope.$destroy&&this.scope.$destroy(),this.scope=null)},{register:function(e,t){var i,a,c,l=g(),d=h(e),$=R.currentView,M=R.backView,N=R.forwardView,z=null,O=null,H=D,q=d.historyId,U=n.url();if(b!==l&&(b=l,L++),C)z=C.viewId,O=C.action,H=C.direction,C=null;else if(M&&M.stateId===l)z=M.viewId,q=M.historyId,O=I,M.historyId===$.historyId?H=A:$&&(H=P,i=f(M.historyId),i&&i.parentHistoryId===$.historyId?H=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(H=_)));else if(N&&N.stateId===l)z=N.viewId,q=N.historyId,O=x,N.historyId===$.historyId?H=E:$&&(H=P,$.historyId===d.parentHistoryId?H=V:(i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId&&(H=_))),i=p(e),N.historyId&&i.scope&&(i.scope.$historyId=N.historyId,q=N.historyId);else if($&&$.historyId!==q&&d.cursor>-1&&d.stack.length>0&&d.cursor<d.stack.length&&d.stack[d.cursor].stateId===l){var F=d.stack[d.cursor];z=F.viewId,q=F.historyId,O=I,H=_,i=f($.historyId),i&&i.parentHistoryId===q?H=P:(i=f(q),i&&i.parentHistoryId===$.historyId&&(H=V)),i=s(F.backViewId),i&&F.historyId!==i.historyId&&(d.stack[d.cursor].backViewId=$.viewId)}else{if(c=r.createViewEle(t),this.isAbstractEle(c,t))return{action:"abstractView",direction:D,ele:c};if(z=ionic.Utils.nextUid(),$){if($.forwardViewId=z,O=B,N&&$.stateId!==N.stateId&&$.historyId===N.historyId&&(i=f(N.historyId))){for(a=i.stack.length-1;a>=N.index;a--){var W=i.stack[a];W&&W.destroy&&W.destroy(),i.stack.splice(a)}q=N.historyId}d.historyId===$.historyId?H=E:$.historyId!==d.historyId&&(H=V,i=f($.historyId),i&&i.parentHistoryId===d.parentHistoryId?H=_:(i=f(i.parentHistoryId),i&&i.historyId===d.historyId&&(H=P)))}else O=T;2>L&&(H=D),R.views[z]=this.createView({viewId:z,index:d.stack.length,historyId:d.historyId,backViewId:$&&$.viewId?$.viewId:null,forwardViewId:null,stateId:l,stateName:this.currentStateName(),stateParams:m(),url:U,canSwipeBack:w(c,t)}),d.stack.push(R.views[z])}if(S&&S(),o.cancel(k),y){if(y.disableAnimate&&(H=D),y.disableBack&&(R.views[z].backViewId=null),y.historyRoot){for(a=0;a<d.stack.length;a++)d.stack[a].viewId===z?(d.stack[a].index=0,d.stack[a].backViewId=d.stack[a].forwardViewId=null):delete R.views[d.stack[a].viewId];d.stack=[R.views[z]]}y=null}if(v(z),R.backView&&q==R.backView.historyId&&l==R.backView.stateId&&U==R.backView.url)for(a=0;a<d.stack.length;a++)if(d.stack[a].viewId==z){O="dupNav",H=D,a>0&&(d.stack[a-1].forwardViewId=null),R.forwardView=null,R.currentView.index=R.backView.index,R.currentView.backViewId=R.backView.backViewId,R.backView=u(R.backView),d.stack.splice(a,1);break}return d.cursor=R.currentView.index,{viewId:z,action:O,direction:H,historyId:q,enableBack:this.enabledBack(R.currentView),isHistoryRoot:0===R.currentView.index,ele:c}},registerHistory:function(e){e.$historyId=ionic.Utils.nextUid()},createView:function(e){var t=new M;return t.initialize(e)},getViewById:s,viewHistory:function(){return R},currentView:function(e){return arguments.length&&(R.currentView=e),R.currentView},currentHistoryId:function(){return R.currentView?R.currentView.historyId:null},currentTitle:function(e){return R.currentView?(arguments.length&&(R.currentView.title=e),R.currentView.title):void 0},backView:function(e){return arguments.length&&(R.backView=e),R.backView},backTitle:function(e){var t=e&&s(e.backViewId)||R.backView;return t&&t.title},forwardView:function(e){return arguments.length&&(R.forwardView=e),R.forwardView},currentStateName:function(){return t&&t.current?t.current.name:null},isCurrentStateNavView:function(e){return!!(t&&t.current&&t.current.views&&t.current.views[e])},goToHistoryRoot:function(e){if(e){var t=f(e);if(t&&t.stack.length){if(R.currentView&&R.currentView.viewId===t.stack[0].viewId)return;C={viewId:t.stack[0].viewId,action:I,direction:A},t.stack[0].go()}}},goBack:function(e){if(l(e)&&-1!==e){if(e>-1)return;var t=R.histories[this.currentHistoryId()],n=t.cursor+e+1;1>n&&(n=1),t.cursor=n,v(t.stack[n].viewId);for(var i=n-1,r=[],a=s(t.stack[i].forwardViewId);a&&(r.push(a.stateId||a.viewId),i++,!(i>=t.stack.length));)a=s(t.stack[i].forwardViewId);var c=this;r.length&&o(function(){c.clearCache(r)},600)}R.backView&&R.backView.go()},enabledBack:function(e){var t=u(e);return!(!t||t.historyId!==e.historyId)},clearHistory:function(){var e=R.histories,t=R.currentView;if(e)for(var n in e)e[n].stack&&(e[n].stack=[],e[n].cursor=-1),t&&t.historyId===n?(t.backViewId=t.forwardViewId=null,e[n].stack.push(t)):e[n].destroy&&e[n].destroy();for(var i in R.views)i!==t.viewId&&delete R.views[i];t&&v(t.viewId)},clearCache:function(e){return o(function(){a._instances.forEach(function(t){t.clearCache(e)})})},nextViewOptions:function(t){return S&&S(),arguments.length&&(o.cancel(k),null===t?y=t:(y=y||{},c(y,t),y.expire&&(S=e.$on("$stateChangeSuccess",function(){k=o(function(){y=null},y.expire)})))),y},isAbstractEle:function(e,t){return t&&t.$$state&&t.$$state.self["abstract"]?!0:!(!e||!$(e)&&!$(e.children()))},isActiveScope:function(e){if(!e)return!1;for(var t,n=e,i=this.currentHistoryId();n;){if(n.$$disconnected)return!1;if(!t&&n.hasOwnProperty("$historyId")&&(t=!0),i){if(n.hasOwnProperty("$historyId")&&i==n.$historyId)return!0;if(n.hasOwnProperty("$activeHistoryId")&&i==n.$activeHistoryId){if(n.hasOwnProperty("$historyId"))return!0;if(!t)return!0}}t&&n.hasOwnProperty("$activeHistoryId")&&(t=!1),n=n.$parent}return i?"root"==i:!0}}}]).run(["$rootScope","$state","$location","$document","$ionicPlatform","$ionicHistory","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a){function c(e){var t=r.backView();return t?t.go():ionic.Platform.exitApp(),e.preventDefault(),!1}e.$on("$ionicView.beforeEnter",function(){ionic.keyboard&&ionic.keyboard.hide&&ionic.keyboard.hide()}),e.$on("$ionicHistory.change",function(e,i){if(!i)return null;var o=r.viewHistory(),a=i.historyId?o.histories[i.historyId]:null;if(a&&a.cursor>-1&&a.cursor<a.stack.length){var c=a.stack[a.cursor];return c.go(i)}!i.url&&i.uiSref&&(i.url=t.href(i.uiSref)),i.url&&(0===i.url.indexOf("#")&&(i.url=i.url.replace("#","")),i.url!==n.url()&&n.url(i.url))}),e.$ionicGoBack=function(e){r.goBack(e)},e.$on("$ionicView.afterEnter",function(e,t){t&&t.title&&(i[0].title=t.title)}),o.registerBackButtonAction(c,a.view)}]),a.provider("$ionicConfig",function(){function e(e,i){a.platform[e]=i,o.platform[e]={},t(a,a.platform[e]),n(a.platform[e],o.platform[e],"")}function t(e,n){for(var i in e)i!=r&&e.hasOwnProperty(i)&&(angular.isObject(e[i])?(l(n[i])||(n[i]={}),t(e[i],n[i])):l(n[i])||(n[i]=null))}function n(e,t,o){s(e,function(c,s){angular.isObject(e[s])?(t[s]={},n(e[s],t[s],o+"."+s)):t[s]=function(n){if(arguments.length)return e[s]=n,t;if(e[s]==r){var c=i(a.platform,ionic.Platform.platform()+o+"."+s);return c||c===!1?c:i(a.platform,"default"+o+"."+s)}return e[s]}})}function i(e,t){t=t.split(".");for(var n=0;n<t.length;n++){if(!e||!l(e[t[n]]))return null;e=e[t[n]]}return e}var o=this;o.platform={};var r="platform",a={views:{maxCache:r,forwardCache:r,transition:r,swipeBackEnabled:r,swipeBackHitWidth:r},navBar:{alignTitle:r,positionPrimaryButtons:r,positionSecondaryButtons:r,transition:r},backButton:{icon:r,text:r,previousTitleText:r},form:{checkbox:r,toggle:r},scrolling:{jsScrolling:r},spinner:{icon:r},tabs:{style:r,position:r},templates:{maxPrefetch:r},platform:{}};n(a,o,""),e("default",{views:{maxCache:10,forwardCache:!1,transition:"ios",swipeBackEnabled:!0,swipeBackHitWidth:45},navBar:{alignTitle:"center",positionPrimaryButtons:"left",positionSecondaryButtons:"right",transition:"view"},backButton:{icon:"ion-ios-arrow-back",text:"Back",previousTitleText:!0},form:{checkbox:"circle",toggle:"large"},scrolling:{jsScrolling:!0},spinner:{icon:"ios"},tabs:{style:"standard",position:"bottom"},templates:{maxPrefetch:30}}),e("ios",{}),e("android",{views:{transition:"android",swipeBackEnabled:!1},navBar:{alignTitle:"left",positionPrimaryButtons:"right",positionSecondaryButtons:"right"},backButton:{icon:"ion-android-arrow-back",text:!1,previousTitleText:!1},form:{checkbox:"square",toggle:"small"},spinner:{icon:"android"},tabs:{style:"striped",position:"top"},scrolling:{jsScrolling:!1}}),e("windowsphone",{spinner:{icon:"android"}}),o.transitions={views:{},navBar:{}},o.transitions.views.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,o.opacity=t,i>-1&&(o.boxShadow="0 0 10px rgba(0,0,0,"+(r.shouldAnimate?.45*i:.3)+")"),o[ionic.CSS.TRANSFORM]="translate3d("+n+"%,0,0)",ionic.DomUtil.cachedStyles(e,o)}var r={run:function(i){"forward"==n?(o(e,1,99*(1-i),1-i),o(t,1-.1*i,-33*i,-1)):"back"==n?(o(e,1-.1*(1-i),-33*(1-i),-1),o(t,1,100*i,1-i)):(o(e,1,0,-1),o(t,0,0,-1))},shouldAnimate:i&&("forward"==n||"back"==n)};return r},o.transitions.navBar.ios=function(e,t,n,i){function o(e,t,n,i){var o={};o[ionic.CSS.TRANSITION_DURATION]=c.shouldAnimate?"":"0ms",o.opacity=1===t?"":t,e.setCss("buttons-left",o),e.setCss("buttons-right",o),e.setCss("back-button",o),o[ionic.CSS.TRANSFORM]="translate3d("+i+"px,0,0)",e.setCss("back-text",o),o[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e.setCss("title",o)}function r(e,t,n){if(e&&t){var i=(e.titleTextX()+e.titleWidth())*(1-n),r=t&&(t.titleTextX()-e.backButtonTextLeft())*(1-n)||0;o(e,n,i,r)}}function a(e,t,n){if(e&&t){var i=(-(e.titleTextX()-t.backButtonTextLeft())-e.titleLeftRight())*n;o(e,1-n,i,0)}}var c={run:function(n){var i=e.controller(),o=t&&t.controller();"back"==c.direction?(a(i,o,1-n),r(o,i,1-n)):(r(i,o,n),a(o,i,n))},direction:n,shouldAnimate:i&&("forward"==n||"back"==n)};return c},o.transitions.views.android=function(e,t,n,i){function o(e,t){var n={};n[ionic.CSS.TRANSITION_DURATION]=r.shouldAnimate?"":0,n[ionic.CSS.TRANSFORM]="translate3d("+t+"%,0,0)",ionic.DomUtil.cachedStyles(e,n)}i=i&&("forward"==n||"back"==n);var r={run:function(i){"forward"==n?(o(e,99*(1-i)),o(t,-100*i)):"back"==n?(o(e,-100*(1-i)),o(t,100*i)):(o(e,0),o(t,0))},shouldAnimate:i};return r},o.transitions.navBar.android=function(e,t,n,i){function o(e,t){if(e){var n={};n.opacity=1===t?"":t,e.setCss("buttons-left",n),e.setCss("buttons-right",n),e.setCss("back-button",n),e.setCss("back-text",n),e.setCss("title",n)}}return{run:function(n){o(e.controller(),n),o(t&&t.controller(),1-n)},shouldAnimate:i&&("forward"==n||"back"==n)}},o.transitions.views.none=function(e,t){return{run:function(n){o.transitions.views.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.transitions.navBar.none=function(e,t){return{run:function(n){o.transitions.navBar.ios(e,t,!1,!1).run(n),o.transitions.navBar.android(e,t,!1,!1).run(n)},shouldAnimate:!1}},o.setPlatformConfig=e,o.$get=function(){return o}}).config(["$compileProvider",function(e){e.aHrefSanitizationWhitelist(/^\s*(https?|sms|tel|geo|ftp|mailto|file|ghttps?|ms-appx-web|ms-appx|x-wmapp0):/),e.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|content|blob|ms-appx|ms-appx-web|x-wmapp0):|data:image\//); +}]);var p='<div class="loading-container"><div class="loading"></div></div>',v="$ionicLoading instance.hide() has been deprecated. Use $ionicLoading.hide().",g="$ionicLoading instance.show() has been deprecated. Use $ionicLoading.show().",m="$ionicLoading instance.setContent() has been deprecated. Use $ionicLoading.show({ template: 'my content' }).";a.constant("$ionicLoadingConfig",{template:"<ion-spinner></ion-spinner>"}).factory("$ionicLoading",["$ionicLoadingConfig","$ionicBody","$ionicTemplateLoader","$ionicBackdrop","$timeout","$q","$log","$compile","$ionicPlatform","$rootScope","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s,l,u,d){function f(){return b||(b=n.compile({template:p,appendTo:t.get()}).then(function(e){return e.show=function(a){var c=a.templateUrl?n.load(a.templateUrl):r.when(a.template||a.content||"");e.scope=a.scope||e.scope,e.isShown||(e.hasBackdrop=!a.noBackdrop&&a.showBackdrop!==!1,e.hasBackdrop&&(i.retain(),i.getElement().addClass("backdrop-loading"))),a.duration&&(o.cancel(e.durationTimeout),e.durationTimeout=o(angular.bind(e,e.hide),+a.duration)),y(),y=l.registerBackButtonAction(h,d.loading),c.then(function(n){if(n){var i=e.element.children();i.html(n),s(i.contents())(e.scope)}e.isShown&&(e.element.addClass("visible"),ionic.requestAnimationFrame(function(){e.isShown&&(e.element.addClass("active"),t.addClass("loading-active"))}))}),e.isShown=!0},e.hide=function(){y(),e.isShown&&(e.hasBackdrop&&(i.release(),i.getElement().removeClass("backdrop-loading")),e.element.removeClass("active"),t.removeClass("loading-active"),e.element.removeClass("visible"),ionic.requestAnimationFrame(function(){!e.isShown&&e.element.removeClass("visible")})),o.cancel(e.durationTimeout),e.isShown=!1;var n=e.element.children();n.html("")},e})),b}function $(t){t=c({},e||{},t||{});var n=t.delay||t.showDelay||0;return S(),k(),t.hideOnStateChange&&(S=u.$on("$stateChangeSuccess",w),k=u.$on("$stateChangeError",w)),o.cancel(C),C=o(h,n),C.then(f).then(function(e){return e.show(t)}),{hide:function(){return a.error(v),w.apply(this,arguments)},show:function(){return a.error(g),$.apply(this,arguments)},setContent:function(e){return a.error(m),f().then(function(t){t.show({template:e})})}}}function w(){S(),k(),o.cancel(C),f().then(function(e){e.hide()})}var b,y=h,S=h,k=h,C=r.when();return{show:$,hide:w,_getLoader:f}}]),a.factory("$ionicModal",["$rootScope","$ionicBody","$compile","$timeout","$ionicPlatform","$ionicTemplateLoader","$$q","$log","$ionicClickBlock","$window","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s,l,u,d){var p=ionic.views.Modal.inherit({initialize:function(e){ionic.views.Modal.prototype.initialize.call(this,e),this.animation=e.animation||"slide-in-up"},show:function(e){var n=this;if(n.scope.$$destroyed)return s.error("Cannot call "+n.viewType+".show() after remove(). Please create a new "+n.viewType+" instance."),a.when();l.show(600),m.add(n);var r=f(n.modalEl);n.el.classList.remove("hide"),i(function(){n._isShown&&t.addClass(n.viewType+"-open")},400,!1),n.el.parentElement||(r.addClass(n.animation),t.append(n.el));var c=r.data("$$ionicScrollController");return c&&c.resize(),e&&n.positionView&&(n.positionView(e,r),n._onWindowResize=function(){n._isShown&&n.positionView(e,r)},ionic.on("resize",n._onWindowResize,window)),r.addClass("ng-enter active").removeClass("ng-leave ng-leave-active"),n._isShown=!0,n._deregisterBackButton=o.registerBackButtonAction(n.hardwareBackButtonClose?angular.bind(n,n.hide):h,d.modal),ionic.views.Modal.prototype.show.call(n),i(function(){n._isShown&&(r.addClass("ng-enter-active"),ionic.trigger("resize"),n.scope.$parent&&n.scope.$parent.$broadcast(n.viewType+".shown",n),n.el.classList.add("active"),n.scope.$broadcast("$ionicHeader.align"),n.scope.$broadcast("$ionicFooter.align"))},20),i(function(){n._isShown&&(n.$el.on("touchmove",function(e){var t=ionic.DomUtil.getParentOrSelfWithClass(e.target,"scroll");t||e.preventDefault()}),n.$el.on("click",function(e){n.backdropClickToClose&&e.target===n.el&&m.isHighest(n)&&n.hide()}))},400)},hide:function(){var e=this,n=f(e.modalEl);return l.show(600),m.remove(e),e.el.classList.remove("active"),n.addClass("ng-leave"),i(function(){e._isShown||n.addClass("ng-leave-active").removeClass("ng-enter ng-enter-active active")},20,!1),e.$el.off("click"),e._isShown=!1,e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".hidden",e),e._deregisterBackButton&&e._deregisterBackButton(),ionic.views.Modal.prototype.hide.call(e),e.positionView&&ionic.off("resize",e._onWindowResize,window),i(function(){t.removeClass(e.viewType+"-open"),e.el.classList.add("hide")},e.hideDelay||320)},remove:function(){var e=this;return e.scope.$parent&&e.scope.$parent.$broadcast(e.viewType+".removed",e),e.hide().then(function(){e.scope.$destroy(),e.$el.remove()})},isShown:function(){return!!this._isShown}}),v=function(t,i){var o=i.scope&&i.scope.$new()||e.$new(!0);i.viewType=i.viewType||"modal",c(o,{$hasHeader:!1,$hasSubheader:!1,$hasFooter:!1,$hasSubfooter:!1,$hasTabs:!1,$hasTabsTop:!1});var r=n("<ion-"+i.viewType+">"+t+"</ion-"+i.viewType+">")(o);i.$el=r,i.el=r[0],i.modalEl=i.el.querySelector("."+i.viewType);var a=new p(i);return a.scope=o,i.scope||(o[i.viewType]=a),a},g=[],m={add:function(e){g.push(e)},remove:function(e){var t=g.indexOf(e);t>-1&&t<g.length&&g.splice(t,1)},isHighest:function(e){var t=g.indexOf(e);return t>-1&&t===g.length-1}};return{fromTemplate:function(e,t){var n=v(e,t||{});return n},fromTemplateUrl:function(e,t,n){var i;return angular.isFunction(t)&&(i=t,t=n),r.load(e).then(function(e){var n=v(e,t||{});return i&&i(n),n})},stack:m}}]),a.service("$ionicNavBarDelegate",ionic.DelegateService(["align","showBackButton","showBar","title","changeTitle","setTitle","getTitle","back","getPreviousTitle"])),a.service("$ionicNavViewDelegate",ionic.DelegateService(["clearCache"])),a.constant("IONIC_BACK_PRIORITY",{view:100,sideMenu:150,modal:200,actionSheet:300,popup:400,loading:500}).provider("$ionicPlatform",function(){return{$get:["$q","$ionicScrollDelegate",function(e,t){var n={onHardwareBackButton:function(e){ionic.Platform.ready(function(){document.addEventListener("backbutton",e,!1)})},offHardwareBackButton:function(e){ionic.Platform.ready(function(){document.removeEventListener("backbutton",e)})},$backButtonActions:{},registerBackButtonAction:function(e,t,i){n._hasBackButtonHandler||(n.$backButtonActions={},n.onHardwareBackButton(n.hardwareBackButtonClick),n._hasBackButtonHandler=!0);var o={id:i?i:ionic.Utils.nextUid(),priority:t?t:0,fn:e};return n.$backButtonActions[o.id]=o,function(){delete n.$backButtonActions[o.id]}},hardwareBackButtonClick:function(e){var t,i;for(i in n.$backButtonActions)(!t||n.$backButtonActions[i].priority>=t.priority)&&(t=n.$backButtonActions[i]);return t?(t.fn(e),t):void 0},is:function(e){return ionic.Platform.is(e)},on:function(e,t){return ionic.Platform.ready(function(){document.addEventListener(e,t,!1)}),function(){ionic.Platform.ready(function(){document.removeEventListener(e,t)})}},ready:function(t){var n=e.defer();return ionic.Platform.ready(function(){n.resolve(),t&&t()}),n.promise}};return window.addEventListener("statusTap",function(){t.scrollTop(!0)}),n}]}}),a.factory("$ionicPopover",["$ionicModal","$ionicPosition","$document","$window",function(e,t,n,i){function o(e,n){var o=f(e.target||e),a=t.offset(o),c=n.prop("offsetWidth"),s=n.prop("offsetHeight"),l=i.innerWidth,u=i.innerHeight,d={left:a.left+a.width/2-c/2},h=f(n[0].querySelector(".popover-arrow"));d.left<r?d.left=r:d.left+c+r>l&&(d.left=l-c-r),a.top+a.height+s>u&&a.top-s>0?(d.top=a.top-s,n.addClass("popover-bottom")):(d.top=a.top+a.height,n.removeClass("popover-bottom")),h.css({left:a.left+a.width/2-h.prop("offsetWidth")/2-d.left+"px"}),n.css({top:d.top+"px",left:d.left+"px",marginLeft:"0",opacity:"1"})}var r=6,a={viewType:"popover",hideDelay:1,animation:"none",positionView:o};return{fromTemplate:function(t,n){return e.fromTemplate(t,ionic.Utils.extend({},a,n))},fromTemplateUrl:function(t,n){return e.fromTemplateUrl(t,ionic.Utils.extend({},a,n))}}}]);var $='<div class="popup-container" ng-class="cssClass"><div class="popup"><div class="popup-head"><h3 class="popup-title" ng-bind-html="title"></h3><h5 class="popup-sub-title" ng-bind-html="subTitle" ng-if="subTitle"></h5></div><div class="popup-body"></div><div class="popup-buttons" ng-show="buttons.length"><button ng-repeat="button in buttons" ng-click="$buttonTapped(button, $event)" class="button" ng-class="button.type || \'button-default\'" ng-bind-html="button.text"></button></div></div></div>';a.factory("$ionicPopup",["$ionicTemplateLoader","$ionicBackdrop","$q","$timeout","$rootScope","$ionicBody","$compile","$ionicPlatform","$ionicModal","IONIC_BACK_PRIORITY",function(e,t,n,i,o,r,a,s,l,u){function d(t){t=c({scope:null,title:"",buttons:[]},t||{});var s={};return s.scope=(t.scope||o).$new(),s.element=f($),s.responseDeferred=n.defer(),r.get().appendChild(s.element[0]),a(s.element)(s.scope),c(s.scope,{title:t.title,buttons:t.buttons,subTitle:t.subTitle,cssClass:t.cssClass,$buttonTapped:function(e,t){var n=(e.onTap||h).apply(s,[t]);t=t.originalEvent||t,t.defaultPrevented||s.responseDeferred.resolve(n)}}),n.when(t.templateUrl?e.load(t.templateUrl):t.template||t.content||"").then(function(e){var t=f(s.element[0].querySelector(".popup-body"));e?(t.html(e),a(t.contents())(s.scope)):t.remove()}),s.show=function(){s.isShown||s.removed||(l.stack.add(s),s.isShown=!0,ionic.requestAnimationFrame(function(){s.isShown&&(s.element.removeClass("popup-hidden"),s.element.addClass("popup-showing active"),g(s.element))}))},s.hide=function(e){return e=e||h,s.isShown?(l.stack.remove(s),s.isShown=!1,s.element.removeClass("active"),s.element.addClass("popup-hidden"),void i(e,250,!1)):e()},s.remove=function(){s.removed||(s.hide(function(){s.element.remove(),s.scope.$destroy()}),s.removed=!0)},s}function p(){var e=S[S.length-1];e&&e.responseDeferred.resolve()}function v(e){function n(){S.push(o),i(o.show,a,!1),o.responseDeferred.promise.then(function(e){var n=S.indexOf(o);return-1!==n&&S.splice(n,1),o.remove(),S.length>0?S[S.length-1].show():(t.release(),i(function(){S.length||r.removeClass("popup-open")},400,!1),(k._backButtonActionDone||h)()),e})}var o=k._createPopup(e),a=0;return S.length>0?(a=y.stackPushDelay,i(S[S.length-1].hide,a,!1)):(r.addClass("popup-open"),t.retain(),k._backButtonActionDone=s.registerBackButtonAction(p,u.popup)),o.responseDeferred.promise.close=function(e){o.removed||o.responseDeferred.resolve(e)},o.responseDeferred.notify({close:o.responseDeferred.close}),n(),o.responseDeferred.promise}function g(e){var t=e[0].querySelector("[autofocus]");t&&t.focus()}function m(e){return v(c({buttons:[{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function w(e){return v(c({buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){return!1}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return!0}}]},e||{}))}function b(e){var t=o.$new(!0);t.data={},t.data.fieldtype=e.inputType?e.inputType:"text",t.data.response=e.defaultText?e.defaultText:"",t.data.placeholder=e.inputPlaceholder?e.inputPlaceholder:"",t.data.maxlength=e.maxLength?parseInt(e.maxLength):"";var n="";return e.template&&/<[a-z][\s\S]*>/i.test(e.template)===!1&&(n="<span>"+e.template+"</span>",delete e.template),v(c({template:n+'<input ng-model="data.response" type="{{ data.fieldtype }}"maxlength="{{ data.maxlength }}"placeholder="{{ data.placeholder }}">',scope:t,buttons:[{text:e.cancelText||"Cancel",type:e.cancelType||"button-default",onTap:function(){}},{text:e.okText||"OK",type:e.okType||"button-positive",onTap:function(){return t.data.response||""}}]},e||{}))}var y={stackPushDelay:75},S=[],k={show:v,alert:m,confirm:w,prompt:b,_createPopup:d,_popupStack:S};return k}]),a.factory("$ionicPosition",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function i(e){return"static"===(n(e,"position")||"static")}var o=function(t){for(var n=e[0],o=t.offsetParent||n;o&&o!==n&&i(o);)o=o.offsetParent;return o||n};return{position:function(t){var n=this.offset(t),i={top:0,left:0},r=o(t[0]);r!=e[0]&&(i=this.offset(f(r)),i.top+=r.clientTop-r.scrollTop,i.left+=r.clientLeft-r.scrollLeft);var a=t[0].getBoundingClientRect();return{width:a.width||t.prop("offsetWidth"),height:a.height||t.prop("offsetHeight"),top:n.top-i.top,left:n.left-i.left}},offset:function(n){var i=n[0].getBoundingClientRect();return{width:i.width||n.prop("offsetWidth"),height:i.height||n.prop("offsetHeight"),top:i.top+(t.pageYOffset||e[0].documentElement.scrollTop),left:i.left+(t.pageXOffset||e[0].documentElement.scrollLeft)}}}}]),a.service("$ionicScrollDelegate",ionic.DelegateService(["resize","scrollTop","scrollBottom","scrollTo","scrollBy","zoomTo","zoomBy","getScrollPosition","anchorScroll","freezeScroll","freezeAllScrolls","getScrollView"])),a.service("$ionicSideMenuDelegate",ionic.DelegateService(["toggleLeft","toggleRight","getOpenRatio","isOpen","isOpenLeft","isOpenRight","canDragContent","edgeDragThreshold"])),a.service("$ionicSlideBoxDelegate",ionic.DelegateService(["update","slide","select","enableSlide","previous","next","stop","autoPlay","start","currentIndex","selected","slidesCount","count","loop"])),a.service("$ionicTabsDelegate",ionic.DelegateService(["select","selectedIndex","showBar"])),function(){var e=[];a.factory("$ionicTemplateCache",["$http","$templateCache","$timeout",function(t,n,i){function o(e){return"undefined"==typeof e?r():(d(e)&&(e=[e]),s(e,function(e){c.push(e)}),void(a&&r()))}function r(){var e;if(o._runCount++,a=!0,0!==c.length){for(var s=0;4>s&&(e=c.pop());)d(e)&&t.get(e,{cache:n}),s++;c.length&&i(r,1e3)}}var a,c=e;return o._runCount=0,o}]).config(["$stateProvider","$ionicConfigProvider",function(t,n){var i=t.state;t.state=function(o,r){if("object"==typeof r){var a=r.prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch();if(a&&d(r.templateUrl)&&e.push(r.templateUrl),angular.isObject(r.views))for(var c in r.views)a=r.views[c].prefetchTemplate!==!1&&e.length<n.templates.maxPrefetch(),a&&d(r.views[c].templateUrl)&&e.push(r.views[c].templateUrl)}return i.call(t,o,r)}}]).run(["$ionicTemplateCache",function(e){e()}])}(),a.factory("$ionicTemplateLoader",["$compile","$controller","$http","$q","$rootScope","$templateCache",function(e,t,n,i,o,r){function a(e){return n.get(e,{cache:r}).then(function(e){return e.data&&e.data.trim()})}function s(n){n=c({template:"",templateUrl:"",scope:null,controller:null,locals:{},appendTo:null},n||{});var r=n.templateUrl?this.load(n.templateUrl):i.when(n.template);return r.then(function(i){var r,a=n.scope||o.$new(),s=f("<div>").html(i).contents();return n.controller&&(r=t(n.controller,c(n.locals,{$scope:a})),s.children().data("$ngControllerController",r)),n.appendTo&&f(n.appendTo).append(s),e(s)(a),{element:s,scope:a}})}return{load:a,compile:s}}]),a.factory("$ionicViewService",["$ionicHistory","$log",function(e,t){function n(e,n){t.warn("$ionicViewService"+e+" is deprecated, please use $ionicHistory"+n+" instead: http://ionicframework.com/docs/nightly/api/service/$ionicHistory/")}n("","");var i={getCurrentView:"currentView",getBackView:"backView",getForwardView:"forwardView",getCurrentStateName:"currentStateName",nextViewOptions:"nextViewOptions",clearHistory:"clearHistory"};return s(i,function(t,o){i[o]=function(){return n("."+o,"."+t),e[t].apply(this,arguments)}}),i}]),a.factory("$ionicViewSwitcher",["$timeout","$document","$q","$ionicClickBlock","$ionicConfig","$ionicNavBarDelegate",function(e,t,n,i,o,r){function a(e,t){return u(e)["abstract"]?u(e).name:t?t.stateId||t.viewId:ionic.Utils.nextUid()}function u(e){return e&&e.$$state&&e.$$state.self||{}}function d(e,t,n,i){var r=u(e),a=g||V(t,"view-transition")||r.viewTransition||o.views.transition()||"ios",s=o.navBar.transition();return n=m||V(t,"view-direction")||r.viewDirection||n||"none",c(h(i),{transition:a,navBarTransition:"view"===s?a:s,direction:n,shouldAnimate:"none"!==a&&"none"!==n})}function h(e){return e=e||{},{viewId:e.viewId,historyId:e.historyId,stateId:e.stateId,stateName:e.stateName,stateParams:e.stateParams}}function p(e,t){return arguments.length>1?void V(e,T,t):V(e,T)}function v(e){if(e&&e.length){var t=e.scope();t&&(t.$emit("$ionicView.unloaded",e.data(C)),t.$destroy()),e.remove()}}var g,m,$="webkitTransitionEnd transitionend",w="$noCache",b="$destroyEle",y="$eleId",S="$accessed",k="$fallbackTimer",C="$viewData",T="nav-view",B="active",I="cached",x="stage",A=0;ionic.transition=ionic.transition||{},ionic.transition.isActive=!1;var E,V=ionic.DomUtil.cachedAttr,P=[],_=1100,D={create:function(t,s,f,T,E,L){var R,M,N,z=++A,O={init:function(e,t){D.isTransitioning(!0),O.loadViewElements(e),O.render(e,function(){t&&t()})},loadViewElements:function(e){var n,i,o,r=t.getViewElements(),c=a(s,f),u=t.activeEleId();for(n=0,i=r.length;i>n&&(o=r.eq(n),o.data(y)===c?o.data(w)?(o.data(y,c+ionic.Utils.nextUid()),o.data(b,!0)):R=o:l(u)&&o.data(y)===u&&(M=o),!R||!M);n++);N=!!R,N||(R=e.ele||D.createViewEle(s),R.data(y,c)),L&&t.activeEleId(c),e.ele=null},render:function(e,n){if(N)ionic.Utils.reconnectScope(R.scope());else{p(R,x);var i=d(s,R,e.direction,f),r=o.transitions.views[i.transition]||o.transitions.views.none;r(R,null,i.direction,!0).run(0),R.data(C,{viewId:i.viewId,historyId:i.historyId,stateName:i.stateName,stateParams:i.stateParams}),(u(s).cache===!1||"false"===u(s).cache||"false"==R.attr("cache-view")||0===o.views.maxCache())&&R.data(w,!0);var a=t.appendViewElement(R,s);delete i.direction,delete i.transition,a.$emit("$ionicView.loaded",i)}R.data(S,Date.now()),n&&n()},transition:function(a,l,u){function v(){p(R,F.shouldAnimate?"entering":B),p(M,F.shouldAnimate?"leaving":I),F.run(1),r._instances.forEach(function(e){e.triggerTransitionStart(z)}),F.shouldAnimate||b()}function w(e){e.target===this&&b()}function b(){b.x||(b.x=!0,R.off($,w),e.cancel(R.data(k)),M&&e.cancel(M.data(k)),C&&C.resolve(t),z===A&&(n.all(P).then(D.transitionEnd),O.emit("after",H,q),O.cleanup(H)),r._instances.forEach(function(e){e.triggerTransitionEnd()}),g=m=f=T=R=M=null)}function y(e){e.target===this&&S()}function S(){p(R,I),p(M,B),R.off($,y),e.cancel(R.data(k)),D.transitionEnd([t])}var C,H=d(s,R,a,f),q=c(c({},H),h(T));H.transitionId=q.transitionId=z,H.fromCache=!!N,H.enableBack=!!l,H.renderStart=E,H.renderEnd=L,V(R.parent(),"nav-view-transition",H.transition),V(R.parent(),"nav-view-direction",H.direction),e.cancel(R.data(k));var U=o.transitions.views[H.transition]||o.transitions.views.none,F=U(R,M,H.direction,H.shouldAnimate&&u&&L);if(F.shouldAnimate&&(R.on($,w),R.data(k,e(b,_)),i.show(_)),E&&(O.emit("before",H,q),p(R,x),F.run(0)),L&&(C=n.defer(),P.push(C.promise)),E&&L)e(function(){ionic.requestAnimationFrame(v)});else{if(!L)return p(R,"entering"),p(M,"leaving"),{run:F.run,cancel:function(t){t?(R.on($,y),R.data(k,e(S,_)),i.show(_)):S(),F.shouldAnimate=t,F.run(0),F=null}};L&&v()}},emit:function(e,t,n){var i=R.scope(),o=M&&M.scope();"after"==e&&(i&&i.$emit("$ionicView.enter",t),o?o.$emit("$ionicView.leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView.leave",n)),i&&i.$emit("$ionicView."+e+"Enter",t),o?o.$emit("$ionicView."+e+"Leave",n):i&&n&&n.viewId&&i.$emit("$ionicNavView."+e+"Leave",n)},cleanup:function(e){M&&"back"==e.direction&&!o.views.forwardCache()&&v(M);var n,i,r,a=t.getViewElements(),c=a.length,s=c-1>o.views.maxCache(),l=Date.now();for(n=0;c>n;n++)i=a.eq(n),s&&i.data(S)<l?(l=i.data(S),r=a.eq(n)):i.data(b)&&p(i)!=B&&v(i);v(r),R.data(w)&&R.data(b,!0)},enteringEle:function(){return R},leavingEle:function(){return M}};return O},transitionEnd:function(e){s(e,function(e){e.transitionEnd()}),D.isTransitioning(!1),i.hide(),P=[]},nextTransition:function(e){g=e},nextDirection:function(e){m=e},isTransitioning:function(t){return arguments.length&&(ionic.transition.isActive=!!t,e.cancel(E),t&&(E=e(function(){D.isTransitioning(!1)},999))),ionic.transition.isActive},createViewEle:function(e){var n=t[0].createElement("div");return e&&e.$template&&(n.innerHTML=e.$template,1===n.children.length)?(n.children[0].classList.add("pane"),f(n.children[0])):(n.className="pane",f(n))},viewEleIsActive:function(e,t){p(e,t?B:I)},getTransitionData:d,navViewAttr:p,destroyViewEle:v};return D}]),angular.module("ngIOS9UIWebViewPatch",["ng"]).config(["$provide",function(e){"use strict";e.decorator("$browser",["$delegate","$window",function(e,t){function n(e){return/(iPhone|iPad|iPod).* OS 9_\d/.test(e)&&!/Version\/9\./.test(e)}function i(e){function t(){n=null}var n=null,i=e.url;return e.url=function(){return arguments.length?(n=arguments[0],i.apply(e,arguments)):n||i.apply(e,arguments)},window.addEventListener("popstate",t,!1),window.addEventListener("hashchange",t,!1),e}return n(t.navigator.userAgent)?i(e):e}])}]),a.config(["$provide",function(e){e.decorator("$compile",["$delegate",function(e){return e.$$addScopeInfo=function(e,t,n,i){var o=n?i?"$isolateScopeNoTemplate":"$isolateScope":"$scope";e.data(o,t)},e}])}]),a.config(["$provide",function(e){function t(e,t){return e.__hash=e.hash,e.hash=function(n){return l(n)&&n.length>0&&t(function(){var e=document.querySelector(".scroll-content");e&&(e.scrollTop=0)},0,!1),e.__hash(n)},e}e.decorator("$location",["$delegate","$timeout",t])}]),a.controller("$ionicHeaderBar",["$scope","$element","$attrs","$q","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r){function a(e){return C[e]||(C[e]=t[0].querySelector("."+e)),C[e]}var c="title",s="back-text",l="back-button",u="default-title",d="previous-title",f="hide",h=this,p="",v="",g=0,m=0,$="",w=!1,b=!0,y=!0,S=!1,k=0;h.beforeEnter=function(t){e.$broadcast("$ionicView.beforeEnter",t)},h.title=function(e){return arguments.length&&e!==p&&(a(c).innerHTML=e,p=e,k=0),p},h.enableBack=function(e,t){return arguments.length&&(w=e,t||h.updateBackButton()),w},h.showBack=function(e,t){return arguments.length&&(b=e,t||h.updateBackButton()),b},h.showNavBack=function(e){y=e,h.updateBackButton()},h.updateBackButton=function(){var e;(b&&y&&w)!==S&&(S=b&&y&&w,e=a(l),e&&e.classList[S?"remove":"add"](f)),w&&(e=e||a(l),e&&(h.backButtonIcon!==o.backButton.icon()&&(e=a(l+" .icon"),e&&(h.backButtonIcon=o.backButton.icon(),e.className="icon "+h.backButtonIcon)),h.backButtonText!==o.backButton.text()&&(e=a(l+" .back-text"),e&&(e.textContent=h.backButtonText=o.backButton.text()))))},h.titleTextWidth=function(){if(!k){var e=ionic.DomUtil.getTextBounds(a(c));k=Math.min(e&&e.width||30)}return k},h.titleWidth=function(){var e=h.titleTextWidth(),t=a(c).offsetWidth;return e>t&&(e=t+(g-m-5)),e},h.titleTextX=function(){return t[0].offsetWidth/2-h.titleWidth()/2},h.titleLeftRight=function(){return g-m},h.backButtonTextLeft=function(){for(var e=0,t=a(s);t;)e+=t.offsetLeft,t=t.parentElement;return e},h.resetBackButton=function(e){if(o.backButton.previousTitleText()){var t=a(d);if(t){t.classList.remove(f);var n=e&&r.getViewById(e.viewId),i=r.backTitle(n);i!==v&&(v=t.innerHTML=i)}var c=a(u);c&&c.classList.remove(f)}},h.align=function(e){var i=a(c);e=e||n.alignTitle||o.navBar.alignTitle();var r=h.calcWidths(e,!1);if(b&&v&&o.backButton.previousTitleText()){var s=h.calcWidths(e,!0),l=t[0].offsetWidth-s.titleLeft-s.titleRight;h.titleTextWidth()<=l&&(r=s)}return h.updatePositions(i,r.titleLeft,r.titleRight,r.buttonsLeft,r.buttonsRight,r.css,r.showPrevTitle)},h.calcWidths=function(e,n){var i,o,r,h,p,v,g,m,$,w=a(c),y=a(l),S=t[0].childNodes,k=0,C=0,T=0,B=0,I="",x=0;for(i=0;i<S.length;i++){if(p=S[i],g=0,1==p.nodeType){if(p===w){$=!0;continue}if(p.classList.contains(f))continue;if(b&&p===y){for(o=0;o<p.childNodes.length;o++)if(h=p.childNodes[o],1==h.nodeType)if(h.classList.contains(s))for(r=0;r<h.children.length;r++)if(v=h.children[r],n){if(v.classList.contains(u))continue;x+=v.offsetWidth}else{if(v.classList.contains(d))continue;x+=v.offsetWidth}else x+=h.offsetWidth;else 3==h.nodeType&&h.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(h),x+=m&&m.width||0);g=x||p.offsetWidth}else g=p.offsetWidth}else 3==p.nodeType&&p.nodeValue.trim()&&(m=ionic.DomUtil.getTextBounds(p),g=m&&m.width||0);$?C+=g:k+=g}if("left"==e)I="title-left",k&&(T=k+15),C&&(B=C+15);else if("right"==e)I="title-right",k&&(T=k+15),C&&(B=C+15);else{var A=Math.max(k,C)+10;A>10&&(T=B=A)}return{backButtonWidth:x,buttonsLeft:k,buttonsRight:C,titleLeft:T,titleRight:B,showPrevTitle:n,css:I}},h.updatePositions=function(e,n,r,c,s,l,p){var v=i.defer();if(e&&(n!==g&&(e.style.left=n?n+"px":"",g=n),r!==m&&(e.style.right=r?r+"px":"",m=r),l!==$&&(l&&e.classList.add(l),$&&e.classList.remove($),$=l)),o.backButton.previousTitleText()){var w=a(d),b=a(u);w&&w.classList[p?"remove":"add"](f),b&&b.classList[p?"add":"remove"](f)}return ionic.requestAnimationFrame(function(){if(e&&e.offsetWidth+10<e.scrollWidth){var n=s+5,i=t[0].offsetWidth-g-h.titleTextWidth()-20;r=n>i?n:i,r!==m&&(e.style.right=r+"px",m=r)}v.resolve()}),v.promise},h.setCss=function(e,t){ionic.DomUtil.cachedStyles(a(e),t)};var C={};e.$on("$destroy",function(){for(var e in C)C[e]=null})}]),a.controller("$ionInfiniteScroll",["$scope","$attrs","$element","$timeout",function(e,t,n,i){function o(){ionic.requestAnimationFrame(function(){n[0].classList.add("active")}),s.isLoading=!0,e.$parent&&e.$parent.$apply(t.onInfinite||"")}function r(){ionic.requestAnimationFrame(function(){n[0].classList.remove("active")}),i(function(){s.jsScrolling&&s.scrollView.resize(),(s.jsScrolling&&s.scrollView.__container&&s.scrollView.__container.offsetHeight>0||!s.jsScrolling)&&s.checkBounds()},30,!1),s.isLoading=!1}function a(){if(!s.isLoading){var e={};if(s.jsScrolling){e=s.getJSMaxScroll();var t=s.scrollView.getValues();(-1!==e.left&&t.left>=e.left||-1!==e.top&&t.top>=e.top)&&o()}else e=s.getNativeMaxScroll(),(-1!==e.left&&s.scrollEl.scrollLeft>=e.left-s.scrollEl.clientWidth||-1!==e.top&&s.scrollEl.scrollTop>=e.top-s.scrollEl.clientHeight)&&o()}}function c(e){var n=(t.distance||"2.5%").trim(),i=-1!==n.indexOf("%");return i?e*(1-parseFloat(n)/100):e-parseFloat(n)}var s=this;s.isLoading=!1,e.icon=function(){return l(t.icon)?t.icon:"ion-load-d"},e.spinner=function(){return l(t.spinner)?t.spinner:""},e.$on("scroll.infiniteScrollComplete",function(){r()}),e.$on("$destroy",function(){s.scrollCtrl&&s.scrollCtrl.$element&&s.scrollCtrl.$element.off("scroll",s.checkBounds),s.scrollEl&&s.scrollEl.removeEventListener&&s.scrollEl.removeEventListener("scroll",s.checkBounds)}),s.checkBounds=ionic.Utils.throttle(a,300),s.getJSMaxScroll=function(){var e=s.scrollView.getScrollMax();return{left:s.scrollView.options.scrollingX?c(e.left):-1,top:s.scrollView.options.scrollingY?c(e.top):-1}},s.getNativeMaxScroll=function(){var e={left:s.scrollEl.scrollWidth,top:s.scrollEl.scrollHeight},t=window.getComputedStyle(s.scrollEl)||{};return{left:!e.left||"scroll"!==t.overflowX&&"auto"!==t.overflowX&&"scroll"!==s.scrollEl.style["overflow-x"]?-1:c(e.left),top:!e.top||"scroll"!==t.overflowY&&"auto"!==t.overflowY&&"scroll"!==s.scrollEl.style["overflow-y"]?-1:c(e.top)}},s.__finishInfiniteScroll=r}]),a.service("$ionicListDelegate",ionic.DelegateService(["showReorder","showDelete","canSwipeItems","closeOptionButtons"])).controller("$ionicList",["$scope","$attrs","$ionicListDelegate","$ionicHistory",function(e,t,n,i){var o=this,r=!0,a=!1,c=!1,s=n._registerInstance(o,t.delegateHandle,function(){return i.isActiveScope(e)});e.$on("$destroy",s),o.showReorder=function(e){return arguments.length&&(a=!!e),a},o.showDelete=function(e){return arguments.length&&(c=!!e),c},o.canSwipeItems=function(e){return arguments.length&&(r=!!e),r},o.closeOptionButtons=function(){o.listView&&o.listView.clearDragEffects()}}]),a.controller("$ionicNavBar",["$scope","$element","$attrs","$compile","$timeout","$ionicNavBarDelegate","$ionicConfig","$ionicHistory",function(e,t,n,i,o,r,a,c){function u(e,t){var n=console.warn||console.log;n&&n.call(console,"navBarController."+e+" is deprecated, please use "+t+" instead")}function d(e){return x[e]?f(x[e]):void 0}function h(){for(var e=0;e<I.length;e++)if(I[e].isActive)return I[e]}function p(){for(var e=0;e<I.length;e++)if(!I[e].isActive)return I[e]}function v(e,t){e&&ionic.DomUtil.cachedAttr(e.containerEle(),"nav-bar",t)}function g(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}var m,$,w,b="hide",y="$ionNavBarController",S="primaryButtons",k="secondaryButtons",C="backButton",T="primaryButtons secondaryButtons leftButtons rightButtons title".split(" "),B=this,I=[],x={},A=!0;t.parent().data(y,B);var E=n.delegateHandle||"navBar"+ionic.Utils.nextUid(),V=r._registerInstance(B,E);B.init=function(){t.addClass("nav-bar-container"),ionic.DomUtil.cachedAttr(t,"nav-bar-transition",a.views.transition()),B.createHeaderBar(!1),B.createHeaderBar(!0),e.$emit("ionNavBar.init",E)},B.createHeaderBar=function(o){function r(e,t){e&&("title"===t?g.append(e):"rightButtons"==t||t==k&&"left"!=a.navBar.positionSecondaryButtons()||t==S&&"right"==a.navBar.positionPrimaryButtons()?(v||(v=f('<div class="buttons buttons-right">'),h.append(v)),t==k?v.append(e):v.prepend(e)):(p||(p=f('<div class="buttons buttons-left">'),m[C]?m[C].after(p):h.prepend(p)),t==k?p.append(e):p.prepend(e)))}var c=f('<div class="nav-bar-block">');ionic.DomUtil.cachedAttr(c,"nav-bar",o?"active":"cached");var u=n.alignTitle||a.navBar.alignTitle(),h=f("<ion-header-bar>").addClass(n["class"]).attr("align-title",u);l(n.noTapScroll)&&h.attr("no-tap-scroll",n.noTapScroll);var p,v,g=f('<div class="title title-'+u+'">'),m={},$={};m[C]=d(C),m[C]&&h.append(m[C]),h.append(g),s(T,function(e){m[e]=d(e),r(m[e],e)});for(var w=0;w<h[0].children.length;w++)h[0].children[w].classList.add("header-item");c.append(h),t.append(i(c)(e.$new()));var y=h.data("$ionHeaderBarController");y.backButtonIcon=a.backButton.icon(),y.backButtonText=a.backButton.text();var B={isActive:o,title:function(e){y.title(e)},setItem:function(e,t){B.removeItem(t),e?("title"===t&&B.title(""),r(e,t),m[t]&&m[t].addClass(b),$[t]=e):m[t]&&m[t].removeClass(b)},removeItem:function(e){$[e]&&($[e].scope().$destroy(),$[e].remove(),$[e]=null)},containerEle:function(){return c},headerBarEle:function(){return h},afterLeave:function(){s(T,function(e){B.removeItem(e)}),y.resetBackButton()},controller:function(){return y},destroy:function(){s(T,function(e){B.removeItem(e)}),c.scope().$destroy();for(var e in m)m[e]&&(m[e].removeData(),m[e]=null);p&&p.removeData(),v&&v.removeData(),g.removeData(),h.removeData(),c.remove(),c=h=g=p=v=null}};return I.push(B),B},B.navElement=function(e,t){return l(t)&&(x[e]=t),x[e]},B.update=function(e){var t=!e.hasHeaderBar&&e.showNavBar;e.transition=a.views.transition(),t||(e.direction="none"),B.enable(t);var n=B.isInitialized?p():h(),i=B.isInitialized?h():null,o=n.controller();o.enableBack(e.enableBack,!0),o.showBack(e.showBack,!0),o.updateBackButton(),B.title(e.title,n),B.showBar(t),e.navBarItems&&s(T,function(t){n.setItem(e.navBarItems[t],t)}),B.transition(n,i,e),B.isInitialized=!0,g("")},B.transition=function(n,i,r){function c(){for(var e=0;e<I.length;e++)I[e].isActive=!1;n.isActive=!0,v(n,"active"),v(i,"cached"),B.activeTransition=d=$=null}var s=n.controller(),l=a.transitions.navBar[r.navBarTransition]||a.transitions.navBar.none,u=r.transitionId;s.beforeEnter(r);var d=l(n,i,r.direction,r.shouldAnimate&&B.isInitialized);ionic.DomUtil.cachedAttr(t,"nav-bar-transition",r.navBarTransition),ionic.DomUtil.cachedAttr(t,"nav-bar-direction",r.direction),d.shouldAnimate&&r.renderEnd?v(n,"stage"):(v(n,"entering"),v(i,"leaving")),s.resetBackButton(r),d.run(0),B.activeTransition={run:function(e){d.shouldAnimate=!1,d.direction="back",d.run(e)},cancel:function(t,o,r){g(o),v(i,"active"),v(n,"cached"),d.shouldAnimate=t,d.run(0),B.activeTransition=d=null;var a;r.showBar!==B.showBar()&&B.showBar(r.showBar),r.showBackButton!==B.showBackButton()&&B.showBackButton(r.showBackButton),a&&e.$apply()},complete:function(e,t){g(t),d.shouldAnimate=e,d.run(1),$=c}},o(s.align,16),(m=function(){w===u&&(v(n,"entering"),v(i,"leaving"),d.run(1),$=function(){w!=u&&d.shouldAnimate||c(); +},m=null)})()},B.triggerTransitionStart=function(e){w=e,m&&m()},B.triggerTransitionEnd=function(){$&&$()},B.showBar=function(t){return arguments.length&&(B.visibleBar(t),e.$parent.$hasHeader=!!t),!!e.$parent.$hasHeader},B.visibleBar=function(e){e&&!A?(t.removeClass(b),B.align()):!e&&A&&t.addClass(b),A=e},B.enable=function(e){B.visibleBar(e);for(var t=0;t<r._instances.length;t++)r._instances[t]!==B&&r._instances[t].visibleBar(!1)},B.showBackButton=function(t){if(arguments.length){for(var n=0;n<I.length;n++)I[n].controller().showNavBack(!!t);e.$isBackButtonShown=!!t}return e.$isBackButtonShown},B.showActiveBackButton=function(e){var t=h();return t?arguments.length?t.controller().showBack(e):t.controller().showBack():void 0},B.title=function(t,n){return l(t)&&(t=t||"",n=n||h(),n&&n.title(t),e.$title=t,c.currentTitle(t)),e.$title},B.align=function(e,t){t=t||h(),t&&t.controller().align(e)},B.hasTabsTop=function(e){t[e?"addClass":"removeClass"]("nav-bar-tabs-top")},B.hasBarSubheader=function(e){t[e?"addClass":"removeClass"]("nav-bar-has-subheader")},B.changeTitle=function(e){u("changeTitle(val)","title(val)"),B.title(e)},B.setTitle=function(e){u("setTitle(val)","title(val)"),B.title(e)},B.getTitle=function(){return u("getTitle()","title()"),B.title()},B.back=function(){u("back()","$ionicHistory.goBack()"),c.goBack()},B.getPreviousTitle=function(){u("getPreviousTitle()","$ionicHistory.backTitle()"),c.goBack()},e.$on("$destroy",function(){e.$parent.$hasHeader=!1,t.parent().removeData(y);for(var n=0;n<I.length;n++)I[n].destroy();t.remove(),t=I=null,V()})}]),a.controller("$ionicNavView",["$scope","$element","$attrs","$compile","$controller","$ionicNavBarDelegate","$ionicNavViewDelegate","$ionicHistory","$ionicViewSwitcher","$ionicConfig","$ionicScrollDelegate",function(e,t,n,i,o,r,a,s,l,u,d){function f(e,n){for(var i,o,r=t.children(),a=0,c=r.length;c>a;a++)if(i=r.eq(a),A(i)==T){o=i.scope(),o&&o.$emit(e.name.replace("Tabs","View"),n);break}}function h(e){ionic.DomUtil.cachedAttr(t,"nav-swipe",e)}function p(e,t){var n=g();n&&n.hasTabsTop(t)}function v(e,t){var n=g();n&&n.hasBarSubheader(t)}function g(){if($)for(var e=0;e<r._instances.length;e++)if(r._instances[e].$$delegateHandle==$)return r._instances[e];return t.inheritedData("$ionNavBarController")}var m,$,w,b,y,S="$eleId",k="$destroyEle",C="$noCache",T="active",B="cached",I=this,x=!1,A=l.navViewAttr;I.scope=e,I.element=t,I.init=function(){var i=n.name||"",o=t.parent().inheritedData("$uiView"),r=o&&o.state?o.state.name:"";i.indexOf("@")<0&&(i=i+"@"+r);var c={name:i,state:null};t.data("$uiView",c);var s=a._registerInstance(I,n.delegateHandle);return e.$on("$destroy",function(){s(),I.isSwipeFreeze&&d.freezeAllScrolls(!1)}),e.$on("$ionicHistory.deselect",I.cacheCleanup),e.$on("$ionicTabs.top",p),e.$on("$ionicSubheader",v),e.$on("$ionicTabs.beforeLeave",f),e.$on("$ionicTabs.afterLeave",f),e.$on("$ionicTabs.leave",f),ionic.Platform.ready(function(){ionic.Platform.isWebView()&&u.views.swipeBackEnabled()&&I.initSwipeBack()}),c},I.register=function(t){var n=c({},s.currentView()),i=s.register(e,t);I.update(i);var o=s.getViewById(i.viewId)||{},r=b!==i.viewId;I.render(i,t,o,n,r,!0)},I.update=function(e){x=!0,m=e.direction;var n=t.parent().inheritedData("$ionNavViewController");n&&(n.isPrimary(!1),("enter"===m||"exit"===m)&&(n.direction(m),"enter"===m&&(m="none")))},I.render=function(e,t,n,i,o,r){var a=l.create(I,t,n,i,o,r);a.init(e,function(){a.transition(I.direction(),e.enableBack,!y),b=y=null})},I.beforeEnter=function(e){if(x){$=e.navBarDelegate;var t=g();t&&t.update(e),h("")}},I.activeEleId=function(e){return arguments.length&&(w=e),w},I.transitionEnd=function(){var e,n,i,o=t.children();for(e=0,n=o.length;n>e;e++)i=o.eq(e),i.data(S)===w?A(i,T):("leaving"===A(i)||A(i)===T||A(i)===B)&&(i.data(k)||i.data(C)?l.destroyViewEle(i):(A(i,B),ionic.Utils.disconnectScope(i.scope())));h(""),I.isSwipeFreeze&&d.freezeAllScrolls(!1)},I.cacheCleanup=function(){for(var e=t.children(),n=0,i=e.length;i>n;n++)e.eq(n).data(k)&&l.destroyViewEle(e.eq(n))},I.clearCache=function(e){var n,i,o,r,a,c,s=t.children();for(o=0,r=s.length;r>o;o++)if(n=s.eq(o),e)for(c=n.data(S),a=0;a<e.length;a++)c===e[a]&&l.destroyViewEle(n);else A(n)==B?l.destroyViewEle(n):A(n)==T&&(i=n.scope(),i&&i.$broadcast("$ionicView.clearCache"))},I.getViewElements=function(){return t.children()},I.appendViewElement=function(n,r){var a=i(n);t.append(n);var c=e.$new();if(r&&r.$$controller){r.$scope=c;var s=o(r.$$controller,r);r.$$controllerAs&&(c[r.$$controllerAs]=s),t.children().data("$ngControllerController",s)}return a(c),c},I.title=function(e){var t=g();t&&t.title(e)},I.enableBackButton=function(e){var t=g();t&&t.enableBackButton(e)},I.showBackButton=function(e){var t=g();return t?arguments.length?t.showActiveBackButton(e):t.showActiveBackButton():!0},I.showBar=function(e){var t=g();return t?arguments.length?t.showBar(e):t.showBar():!0},I.isPrimary=function(e){return arguments.length&&(x=e),x},I.direction=function(e){return arguments.length&&(m=e),m},I.initSwipeBack=function(){function n(e){if(x&&(S=r(e),!(S>C))){p=s.backView();var n=s.currentView();if(p&&p.historyId===n.historyId&&n.canSwipeBack!==!1){w||(w=window.innerWidth),I.isSwipeFreeze=d.freezeAllScrolls(!0);var a={direction:"back"};k=[],T={showBar:I.showBar(),showBackButton:I.showBackButton()};var u=l.create(I,a,p,n,!0,!1);u.loadViewElements(a),u.render(a),c=u.transition("back",s.enabledBack(p),!0),f=g(),m=ionic.onGesture("drag",i,t[0]),$=ionic.onGesture("release",o,t[0])}}}function i(e){if(x&&c){var t=r(e);if(k.push({t:Date.now(),x:t}),t>=w-15)o(e);else{var n=Math.min(Math.max(a(t),0),1);c.run(n),f&&f.activeTransition&&f.activeTransition.run(n)}}}function o(e){if(x&&c&&k&&k.length>1){for(var t=Date.now(),n=r(e),s=k[k.length-1],l=k.length-2;l>=0&&!(t-s.t>200);l--)s=k[l];var u=n>=k[k.length-2].x,v=a(n),g=Math.abs(s.x-n)/(t-s.t);if(b=p.viewId,y=.03>v||v>.97,u&&(v>.5||g>.1)){var S=g>.5||.05>g||n>w-45?"fast":"slow";h(y?"":S),p.go(),f&&f.activeTransition&&f.activeTransition.complete(!y,S)}else h(y?"":"fast"),b=null,c.cancel(!y),f&&f.activeTransition&&f.activeTransition.cancel(!y,"fast",T),y=null}ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),w=c=k=null,I.isSwipeFreeze=d.freezeAllScrolls(!1)}function r(e){return ionic.tap.pointerCoord(e.gesture.srcEvent).x}function a(e){return(e-S)/w}var c,f,p,v,m,$,w,S,k,C=u.views.swipeBackHitWidth(),T={};v=ionic.onGesture("dragstart",n,t[0]),e.$on("$destroy",function(){ionic.offGesture(v,"dragstart",n),ionic.offGesture(m,"drag",i),ionic.offGesture($,"release",o),I.element=c=f=null})}}]),a.controller("$ionicRefresher",["$scope","$attrs","$element","$ionicBind","$timeout",function(e,t,n,i,o){function r(e){e.touches=e.touches||[{screenX:e.screenX,screenY:e.screenY}],P=Math.floor(e.touches[0].screenY)}function a(e){e.touches=e.touches||[{screenX:e.screenX,screenY:e.screenY}],P=e.touches[0].screenY}function c(){P=null,(D||T)&&(T?(T=!1,I=0,x>A?($(),p(A,V)):(p(0,V,m),B=!1)):(I=0,B=!1,h(!1)))}function s(e){if(e.touches=e.touches||[{screenX:e.screenX,screenY:e.screenY}],(P||"mousemove"!=e.type)&&D&&!(e.touches.length>1)){if(null===P&&(P=e.touches[0].screenY),_=e.touches[0].screenY-P,ionic.Platform.isAndroid()&&4.4===ionic.Platform.version()&&!ionic.Platform.isCrosswalk()&&0===S.scrollTop&&_>0&&(T=!0,e.preventDefault()),0>=_-I||0!==S.scrollTop)return B&&(B=!1,h(!1)),T&&f(S,_- -1*I),void(0!==x&&d(0));_>0&&0===S.scrollTop&&!B&&(I=_),e.preventDefault(),B||(B=!0,h(!0)),T=!0,d((_-I)/3),!E&&x>A?(E=!0,ionic.requestAnimationFrame(g)):E&&A>x&&(E=!1,ionic.requestAnimationFrame(m))}}function u(e){D=0===e.target.scrollTop||T}function d(e){k.style[ionic.CSS.TRANSFORM]="translateY("+e+"px)",x=e}function f(e,t){e.scrollTop=t;var n=document.createEvent("UIEvents");n.initUIEvent("scroll",!0,!0,window,1),e.dispatchEvent(n)}function h(e){e?ionic.requestAnimationFrame(function(){k.classList.add("overscroll"),w()}):ionic.requestAnimationFrame(function(){k.classList.remove("overscroll"),b(),m()})}function p(e,t,n){function i(e){return--e*e*e+1}function o(){var c=Date.now(),s=Math.min(1,(c-r)/t),l=i(s);d(Math.floor(l*(e-a)+a)),1>s?ionic.requestAnimationFrame(o):(5>e&&e>-5&&(B=!1,h(!1)),n&&n())}var r=Date.now(),a=x;return a===e?void n():void ionic.requestAnimationFrame(o)}function v(){ionic.off(L,a,k),ionic.off(R,s,k),ionic.off(M,c,k),ionic.off("mousedown",r,k),ionic.off("mousemove",s,k),ionic.off("mouseup",c,k),ionic.off("scroll",u,S),S=null,k=null}function g(){n[0].classList.add("active"),e.$onPulling()}function m(){o(function(){n.removeClass("active refreshing refreshing-tail"),E&&(E=!1)},150)}function $(){n[0].classList.add("refreshing");var t=e.$onRefresh();t&&t.then&&t["finally"](function(){e.$broadcast("scroll.refreshComplete")})}function w(){n[0].classList.remove("invisible")}function b(){n[0].classList.add("invisible")}function y(){n[0].classList.add("refreshing-tail")}var S,k,C=this,T=!1,B=!1,I=0,x=0,A=60,E=!1,V=500,P=null,_=null,D=!0;l(t.pullingIcon)||t.$set("pullingIcon","ion-android-arrow-down"),e.showSpinner=!l(t.refreshingIcon)&&"none"!=t.spinner,e.showIcon=l(t.refreshingIcon),i(e,t,{pullingIcon:"@",pullingText:"@",refreshingIcon:"@",refreshingText:"@",spinner:"@",disablePullingRotation:"@",$onRefresh:"&onRefresh",$onPulling:"&onPulling"}),e.$on("scroll.refreshComplete",function(){o(function(){ionic.requestAnimationFrame(y),p(0,V,m),o(function(){B&&(B=!1,h(!1))},V)},V)});var L,R,M;window.navigator.pointerEnabled?(L="pointerdown",R="pointermove",M="pointerup"):window.navigator.msPointerEnabled?(L="MSPointerDown",R="MSPointerMove",M="MSPointerUp"):(L="touchstart",R="touchmove",M="touchend"),C.init=function(){if(S=n.parent().parent()[0],k=n.parent()[0],!(S&&S.classList.contains("ionic-scroll")&&k&&k.classList.contains("scroll")))throw new Error("Refresher must be immediate child of ion-content or ion-scroll");ionic.on(L,a,k),ionic.on(R,s,k),ionic.on(M,c,k),ionic.on("mousedown",r,k),ionic.on("mousemove",s,k),ionic.on("mouseup",c,k),ionic.on("scroll",u,S),e.$on("$destroy",v)},C.getRefresherDomMethods=function(){return{activate:g,deactivate:m,start:$,show:w,hide:b,tail:y}},C.__handleTouchmove=s,C.__getScrollChild=function(){return k},C.__getScrollParent=function(){return S}}]),a.controller("$ionicScroll",["$scope","scrollViewOptions","$timeout","$window","$location","$document","$ionicScrollDelegate","$ionicHistory",function(e,t,n,i,o,r,a,c){var s=this;s.__timeout=n,s._scrollViewOptions=t,s.isNative=function(){return!!t.nativeScrolling};var u,d=s.element=t.el,h=s.$element=f(d);u=s.isNative()?s.scrollView=new ionic.views.ScrollNative(t):s.scrollView=new ionic.views.Scroll(t),(h.parent().length?h.parent():h).data("$$ionicScrollController",s);var p=a._registerInstance(s,t.delegateHandle,function(){return c.isActiveScope(e)});l(t.bouncing)||ionic.Platform.ready(function(){u&&u.options&&(u.options.bouncing=!0,ionic.Platform.isAndroid()&&(u.options.bouncing=!1,u.options.deceleration=.95))});var v=angular.bind(u,u.resize);angular.element(i).on("resize",v);var g=function(t){var n=(t.originalEvent||t).detail||{};e.$onScroll&&e.$onScroll({event:t,scrollTop:n.scrollTop||0,scrollLeft:n.scrollLeft||0})};h.on("scroll",g),e.$on("$destroy",function(){p(),u&&u.__cleanup&&u.__cleanup(),angular.element(i).off("resize",v),h.off("scroll",g),u=s.scrollView=t=s._scrollViewOptions=t.el=s._scrollViewOptions.el=h=s.$element=d=null}),n(function(){u&&u.run&&u.run()}),s.getScrollView=function(){return u},s.getScrollPosition=function(){return u.getValues()},s.resize=function(){return n(v,0,!1).then(function(){h&&h.triggerHandler("scroll-resize")})},s.scrollTop=function(e){s.resize().then(function(){u&&u.scrollTo(0,0,!!e)})},s.scrollBottom=function(e){s.resize().then(function(){if(u){var t=u.getScrollMax();u.scrollTo(t.left,t.top,!!e)}})},s.scrollTo=function(e,t,n){s.resize().then(function(){u&&u.scrollTo(e,t,!!n)})},s.zoomTo=function(e,t,n,i){s.resize().then(function(){u&&u.zoomTo(e,!!t,n,i)})},s.zoomBy=function(e,t,n,i){s.resize().then(function(){u&&u.zoomBy(e,!!t,n,i)})},s.scrollBy=function(e,t,n){s.resize().then(function(){u&&u.scrollBy(e,t,!!n)})},s.anchorScroll=function(e){s.resize().then(function(){if(u){var t=o.hash(),n=t&&r[0].getElementById(t);if(!t||!n)return void u.scrollTo(0,0,!!e);var i=n,a=0,c=0;do null!==i&&(a+=i.offsetLeft),null!==i&&(c+=i.offsetTop),i=i.offsetParent;while(i.attributes!=s.element.attributes&&i.offsetParent);u.scrollTo(a,c,!!e)}})},s.freezeScroll=u.freeze,s.freezeScrollShut=u.freezeShut,s.freezeAllScrolls=function(e){for(var t=0;t<a._instances.length;t++)a._instances[t].freezeScroll(e)},s._setRefresher=function(e,t,n){s.refresher=t;var i=s.refresher.clientHeight||60;u.activatePullToRefresh(i,n)}}]),a.controller("$ionicSideMenus",["$scope","$attrs","$ionicSideMenuDelegate","$ionicPlatform","$ionicBody","$ionicHistory","$ionicScrollDelegate","IONIC_BACK_PRIORITY","$rootScope",function(e,t,n,i,o,r,a,c,s){var l,d,f,p,v,g,m,$=this,w=!0;$.$scope=e,$.initialize=function(e){$.left=e.left,$.right=e.right,$.setContent(e.content),$.dragThresholdX=e.dragThresholdX||10,r.registerHistory($.$scope)},$.setContent=function(e){e&&($.content=e,$.content.onDrag=function(e){$._handleDrag(e)},$.content.endDrag=function(e){$._endDrag(e)})},$.isOpenLeft=function(){return $.getOpenAmount()>0},$.isOpenRight=function(){return $.getOpenAmount()<0},$.toggleLeft=function(e){if(!m&&$.left.isEnabled){var t=$.getOpenAmount();0===arguments.length&&(e=0>=t),$.content.enableAnimation(),e?($.openPercentage(100),s.$emit("$ionicSideMenuOpen","left")):($.openPercentage(0),s.$emit("$ionicSideMenuClose","left"))}},$.toggleRight=function(e){if(!m&&$.right.isEnabled){var t=$.getOpenAmount();0===arguments.length&&(e=t>=0),$.content.enableAnimation(),e?($.openPercentage(-100),s.$emit("$ionicSideMenuOpen","right")):($.openPercentage(0),s.$emit("$ionicSideMenuClose","right"))}},$.toggle=function(e){"right"==e?$.toggleRight():$.toggleLeft()},$.close=function(){$.openPercentage(0),s.$emit("$ionicSideMenuClose","left"),s.$emit("$ionicSideMenuClose","right")},$.getOpenAmount=function(){return $.content&&$.content.getTranslateX()||0},$.getOpenRatio=function(){var e=$.getOpenAmount();return e>=0?e/$.left.width:e/$.right.width},$.isOpen=function(){return 0!==$.getOpenAmount()},$.getOpenPercentage=function(){return 100*$.getOpenRatio()},$.openPercentage=function(e){var t=e/100;$.left&&e>=0?$.openAmount($.left.width*t):$.right&&0>e&&$.openAmount($.right.width*t),o.enableClass(0!==e,"menu-open"),$.content.setCanScroll(0==e)},$.openAmount=function(e){var t=$.left&&$.left.width||0,n=$.right&&$.right.width||0;return($.left&&$.left.isEnabled||!(e>0))&&($.right&&$.right.isEnabled||!(0>e))?d&&e>t?void $.content.setTranslateX(t):l&&-n>e?void $.content.setTranslateX(-n):($.content.setTranslateX(e),void(e>=0?(d=!0,l=!1,e>0&&($.right&&$.right.pushDown&&$.right.pushDown(),$.left&&$.left.bringUp&&$.left.bringUp())):(l=!0,d=!1,$.right&&$.right.bringUp&&$.right.bringUp(),$.left&&$.left.pushDown&&$.left.pushDown()))):void $.content.setTranslateX(0)},$.snapToRest=function(e){$.content.enableAnimation(),f=!1;var t=$.getOpenRatio();if(0===t)return void $.openPercentage(0);var n=.3,i=e.gesture.velocityX,o=e.gesture.direction;t>0&&.5>t&&"right"==o&&n>i?$.openPercentage(0):t>.5&&"left"==o&&n>i?$.openPercentage(100):0>t&&t>-.5&&"left"==o&&n>i?$.openPercentage(0):.5>t&&"right"==o&&n>i?$.openPercentage(-100):"right"==o&&t>=0&&(t>=.5||i>n)?$.openPercentage(100):"left"==o&&0>=t&&(-.5>=t||i>n)?$.openPercentage(-100):$.openPercentage(0)},$.enableMenuWithBackViews=function(e){return arguments.length&&(w=!!e),w},$.isAsideExposed=function(){return!!m},$.exposeAside=function(e){($.left&&$.left.isEnabled||$.right&&$.right.isEnabled)&&($.close(),m=e,$.left&&$.left.isEnabled&&$.right&&$.right.isEnabled?$.content.setMarginLeftAndRight(m?$.left.width:0,m?$.right.width:0):$.left&&$.left.isEnabled?$.content.setMarginLeft(m?$.left.width:0):$.right&&$.right.isEnabled&&$.content.setMarginRight(m?$.right.width:0),$.$scope.$emit("$ionicExposeAside",m))},$.activeAsideResizing=function(e){o.enableClass(e,"aside-resizing")},$._endDrag=function(e){m||(f&&$.snapToRest(e),p=null,v=null,g=null)},$._handleDrag=function(t){!m&&e.dragContent&&(p?v=t.gesture.touches[0].pageX:(p=t.gesture.touches[0].pageX,v=p),!f&&Math.abs(v-p)>$.dragThresholdX&&(p=v,f=!0,$.content.disableAnimation(),g=$.getOpenAmount()),f&&$.openAmount(g+(v-p)))},$.canDragContent=function(t){return arguments.length&&(e.dragContent=!!t),e.dragContent},$.edgeThreshold=25,$.edgeThresholdEnabled=!1,$.edgeDragThreshold=function(e){return arguments.length&&(u(e)&&e>0?($.edgeThreshold=e,$.edgeThresholdEnabled=!0):$.edgeThresholdEnabled=!!e),$.edgeThresholdEnabled},$.isDraggableTarget=function(t){var n=$.edgeThresholdEnabled&&!$.isOpen(),i=t.gesture.startEvent&&t.gesture.startEvent.center&&t.gesture.startEvent.center.pageX,o=!n||i<=$.edgeThreshold||i>=$.content.element.offsetWidth-$.edgeThreshold,a=r.backView(),c=w?!0:!a;if(!c){var s=r.currentView()||{};return o&&a.historyId!==s.historyId}return(e.dragContent||$.isOpen())&&o&&!t.gesture.srcEvent.defaultPrevented&&c&&!t.target.tagName.match(/input|textarea|select|object|embed/i)&&!t.target.isContentEditable&&!(t.target.dataset?t.target.dataset.preventScroll:"true"==t.target.getAttribute("data-prevent-scroll"))},e.sideMenuContentTranslateX=0;var b=h,y=angular.bind($,$.close);e.$watch(function(){return 0!==$.getOpenAmount()},function(e){b(),e&&(b=i.registerBackButtonAction(y,c.sideMenu))});var S=n._registerInstance($,t.delegateHandle,function(){return r.isActiveScope(e)});e.$on("$destroy",function(){S(),b(),$.$scope=null,$.content&&($.content.setCanScroll(!0),$.content.element=null,$.content=null)}),$.initialize({left:{width:275},right:{width:275}})}]),function(e){function t(e,i,o,r){var a,c,s,l=document.createElement(f[e]||e);for(a in i)if(angular.isArray(i[a]))for(c=0;c<i[a].length;c++)if(i[a][c].fn)for(s=0;s<i[a][c].t;s++)t(a,i[a][c].fn(s,r),l,r);else t(a,i[a][c],l,r);else n(l,a,i[a]);o.appendChild(l)}function n(e,t,n){e.setAttribute(f[t]||t,n)}function i(e,t){var n=e.split(";"),i=n.slice(t),o=n.slice(0,n.length-i.length);return n=i.concat(o).reverse(),n.join(";")+";"+n[0]}function o(e,t){return e/=t/2,1>e?.5*e*e*e:(e-=2,.5*(e*e*e+2))}var r="translate(32,32)",c="stroke-opacity",s="round",l="indefinite",u="750ms",d="none",f={a:"animate",an:"attributeName",at:"animateTransform",c:"circle",da:"stroke-dasharray",os:"stroke-dashoffset",f:"fill",lc:"stroke-linecap",rc:"repeatCount",sw:"stroke-width",t:"transform",v:"values"},h={v:"0,32,32;360,32,32",an:"transform",type:"rotate",rc:l,dur:u},p={sw:4,lc:s,line:[{fn:function(e,t){return{y1:"ios"==t?17:12,y2:"ios"==t?29:20,t:r+" rotate("+(30*e+(6>e?180:-180))+")",a:[{fn:function(){return{an:c,dur:u,v:i("0;.1;.15;.25;.35;.45;.55;.65;.7;.85;1",e),rc:l}},t:1}]}},t:12}]},v={android:{c:[{sw:6,da:128,os:82,r:26,cx:32,cy:32,f:d}]},ios:p,"ios-small":p,bubbles:{sw:0,c:[{fn:function(e){return{cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,a:[{fn:function(){return{an:"r",dur:u,v:i("1;2;3;4;5;6;7;8",e),rc:l}},t:1}]}},t:8}]},circles:{c:[{fn:function(e){return{r:5,cx:24*Math.cos(2*Math.PI*e/8),cy:24*Math.sin(2*Math.PI*e/8),t:r,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".3;.3;.3;.4;.7;.85;.9;1",e),rc:l}},t:1}]}},t:8}]},crescent:{c:[{sw:4,da:128,os:82,r:26,cx:32,cy:32,f:d,at:[h]}]},dots:{c:[{fn:function(e){return{cx:16+16*e,cy:32,sw:0,a:[{fn:function(){return{an:"fill-opacity",dur:u,v:i(".5;.6;.8;1;.8;.6;.5",e),rc:l}},t:1},{fn:function(){return{an:"r",dur:u,v:i("4;5;6;5;4;3;3",e),rc:l}},t:1}]}},t:3}]},lines:{sw:7,lc:s,line:[{fn:function(e){return{x1:10+14*e,x2:10+14*e,a:[{fn:function(){return{an:"y1",dur:u,v:i("16;18;28;18;16",e),rc:l}},t:1},{fn:function(){return{an:"y2",dur:u,v:i("48;44;36;46;48",e),rc:l}},t:1},{fn:function(){return{an:c,dur:u,v:i("1;.8;.5;.4;1",e),rc:l}},t:1}]}},t:4}]},ripple:{f:d,"fill-rule":"evenodd",sw:3,circle:[{fn:function(e){return{cx:32,cy:32,a:[{fn:function(){return{an:"r",begin:-1*e+"s",dur:"2s",v:"0;24",keyTimes:"0;1",keySplines:"0.1,0.2,0.3,1",calcMode:"spline",rc:l}},t:1},{fn:function(){return{an:c,begin:-1*e+"s",dur:"2s",v:".2;1;.2;0",rc:l}},t:1}]}},t:2}]},spiral:{defs:[{linearGradient:[{id:"sGD",gradientUnits:"userSpaceOnUse",x1:55,y1:46,x2:2,y2:46,stop:[{offset:.1,"class":"stop1"},{offset:1,"class":"stop2"}]}]}],g:[{sw:4,lc:s,f:d,path:[{stroke:"url(#sGD)",d:"M4,32 c0,15,12,28,28,28c8,0,16-4,21-9"},{d:"M60,32 C60,16,47.464,4,32,4S4,16,4,32"}],at:[h]}]}},g={android:function(t){function i(){if(!r.stop){var t=o(Date.now()-a,650),d=1,f=0,h=188-58*t,p=182-182*t;c%2&&(d=-1,f=-64,h=128- -58*t,p=182*t);var v=[0,-101,-90,-11,-180,79,-270,-191][c];n(u,"da",Math.max(Math.min(h,188),128)),n(u,"os",Math.max(Math.min(p,182),0)),n(u,"t","scale("+d+",1) translate("+f+",0) rotate("+v+",32,32)"),s+=4.1,s>359&&(s=0),n(l,"t","rotate("+s+",32,32)"),t>=1&&(c++,c>7&&(c=0),a=Date.now()),e.requestAnimationFrame(i)}}var r=this;this.stop=!1;var a,c=0,s=0,l=t.querySelector("g"),u=t.querySelector("circle");return function(){return a=Date.now(),i(),r}}};a.controller("$ionicSpinner",["$element","$attrs","$ionicConfig",function(e,n,i){var o,r;this.init=function(){o=n.icon||i.spinner.icon();var r=document.createElement("div");return t("svg",{viewBox:"0 0 64 64",g:[v[o]]},r,o),e.html(r.innerHTML),this.start(),o},this.start=function(){g[o]&&(r=g[o](e[0])())},this.stop=function(){g[o]&&(r.stop=!0)}}])}(ionic),a.controller("$ionicTab",["$scope","$ionicHistory","$attrs","$location","$state",function(e,t,n,i,o){this.$scope=e,this.hrefMatchesState=function(){return n.href&&0===i.path().indexOf(n.href.replace(/^#/,"").replace(/\/$/,""))},this.srefMatchesState=function(){return n.uiSref&&o.includes(n.uiSref.split("(")[0])},this.navNameMatchesState=function(){return this.navViewName&&t.isCurrentStateNavView(this.navViewName)},this.tabMatchesState=function(){return this.hrefMatchesState()||this.srefMatchesState()||this.navNameMatchesState()}}]),a.controller("$ionicTabs",["$scope","$element","$ionicHistory",function(e,t,n){var i,o=this,r=null,a=null,c=!0;o.tabs=[],o.selectedIndex=function(){return o.tabs.indexOf(r)},o.selectedTab=function(){return r},o.previousSelectedTab=function(){return a},o.add=function(e){n.registerHistory(e),o.tabs.push(e)},o.remove=function(e){var t=o.tabs.indexOf(e);if(-1!==t){if(e.$tabSelected)if(o.deselect(e),1===o.tabs.length);else{var n=t===o.tabs.length-1?t-1:t+1;o.select(o.tabs[n])}o.tabs.splice(t,1)}},o.deselect=function(e){e.$tabSelected&&(a=r,r=i=null,e.$tabSelected=!1,(e.onDeselect||h)(),e.$broadcast&&e.$broadcast("$ionicHistory.deselect"))},o.select=function(t,a){var c;if(u(t)){if(c=t,c>=o.tabs.length)return;t=o.tabs[c]}else c=o.tabs.indexOf(t);1===arguments.length&&(a=!(!t.navViewName&&!t.uiSref)),r&&r.$historyId==t.$historyId?a&&n.goToHistoryRoot(t.$historyId):i!==c&&(s(o.tabs,function(e){o.deselect(e)}),r=t,i=c,o.$scope&&o.$scope.$parent&&(o.$scope.$parent.$activeHistoryId=t.$historyId),t.$tabSelected=!0,(t.onSelect||h)(),a&&e.$emit("$ionicHistory.change",{type:"tab",tabIndex:c,historyId:t.$historyId,navViewName:t.navViewName,hasNavView:!!t.navViewName,title:t.title,url:t.href,uiSref:t.uiSref}))},o.hasActiveScope=function(){for(var e=0;e<o.tabs.length;e++)if(n.isActiveScope(o.tabs[e]))return!0;return!1},o.showBar=function(e){return arguments.length&&(e?t.removeClass("tabs-item-hide"):t.addClass("tabs-item-hide"),c=!!e),c}}]),a.controller("$ionicView",["$scope","$element","$attrs","$compile","$rootScope",function(e,t,n,i,o){function r(){var t=l(n.viewTitle)&&"viewTitle"||l(n.title)&&"title";t&&(a(n[t]),$.push(n.$observe(t,a))),l(n.hideBackButton)&&$.push(e.$watch(n.hideBackButton,function(e){f.showBackButton(!e)})),l(n.hideNavBar)&&$.push(e.$watch(n.hideNavBar,function(e){f.showBar(!e)}))}function a(e){l(e)&&e!==v&&(v=e,f.title(v))}function s(){for(var e=0;e<$.length;e++)$[e]();$=[]}function u(t){return t?i(t)(e.$new()):void 0}function d(t){return!!e.$eval(n[t])}var f,h,p,v,g=this,m={},$=[],w=e.$on("ionNavBar.init",function(e,t){e.stopPropagation(),h=t});g.init=function(){w();var n=t.inheritedData("$ionModalController");f=t.inheritedData("$ionNavViewController"),f&&!n&&(e.$on("$ionicView.beforeEnter",g.beforeEnter),e.$on("$ionicView.afterEnter",r),e.$on("$ionicView.beforeLeave",s))},g.beforeEnter=function(t,i){if(i&&!i.viewNotified){i.viewNotified=!0,o.$$phase||e.$digest(),v=l(n.viewTitle)?n.viewTitle:n.title;var r={};for(var a in m)r[a]=u(m[a]);f.beforeEnter(c(i,{title:v,showBack:!d("hideBackButton"),navBarItems:r,navBarDelegate:h||null,showNavBar:!d("hideNavBar"),hasHeaderBar:!!p})),s()}},g.navElement=function(e,t){m[e]=t}}]),a.directive("ionActionSheet",["$document",function(e){return{restrict:"E",scope:!0,replace:!0,link:function(t,n){var i=function(e){27==e.which&&(t.cancel(),t.$apply())},o=function(e){e.target==n[0]&&(t.cancel(),t.$apply())};t.$on("$destroy",function(){n.remove(),e.unbind("keyup",i)}),e.bind("keyup",i),n.bind("click",o)},template:'<div class="action-sheet-backdrop"><div class="action-sheet-wrapper"><div class="action-sheet" ng-class="{\'action-sheet-has-icons\': $actionSheetHasIcon}"><div class="action-sheet-group action-sheet-options"><div class="action-sheet-title" ng-if="titleText" ng-bind-html="titleText"></div><button class="button action-sheet-option" ng-click="buttonClicked($index)" ng-class="b.className" ng-repeat="b in buttons" ng-bind-html="b.text"></button><button class="button destructive action-sheet-destructive" ng-if="destructiveText" ng-click="destructiveButtonClicked()" ng-bind-html="destructiveText"></button></div><div class="action-sheet-group action-sheet-cancel" ng-if="cancelText"><button class="button" ng-click="cancel()" ng-bind-html="cancelText"></button></div></div></div></div>'}}]),a.directive("ionCheckbox",["$ionicConfig",function(e){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-checkbox"><div class="checkbox checkbox-input-hidden disable-pointer-events"><input type="checkbox"><i class="checkbox-icon"></i></div><div class="item-content disable-pointer-events" ng-transclude></div></label>',compile:function(t,n){var i=t.find("input");s({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){l(e)&&i.attr(t,e)});var o=t[0].querySelector(".checkbox");o.classList.add("checkbox-"+e.form.checkbox())}}}]),a.directive("collectionRepeat",e).factory("$ionicCollectionManager",t);var w="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",b=/height:.*?px;\s*width:.*?px/,y=3;e.$inject=["$ionicCollectionManager","$parse","$window","$$rAF","$rootScope","$timeout"],t.$inject=["$rootScope","$window","$$rAF"],a.directive("ionContent",["$timeout","$controller","$ionicBind","$ionicConfig",function(e,t,n,i){return{restrict:"E",require:"^?ionNavView",scope:!0,priority:800,compile:function(e,o){function r(e,i,r){function u(){e.$onScrollComplete({scrollTop:c.scrollView.__scrollTop,scrollLeft:c.scrollView.__scrollLeft})}var d=e.$parent;if(e.$watch(function(){return(d.$hasHeader?" has-header":"")+(d.$hasSubheader?" has-subheader":"")+(d.$hasFooter?" has-footer":"")+(d.$hasSubfooter?" has-subfooter":"")+(d.$hasTabs?" has-tabs":"")+(d.$hasTabsTop?" has-tabs-top":"")},function(e,t){i.removeClass(t),i.addClass(e)}),e.$hasHeader=e.$hasSubheader=e.$hasFooter=e.$hasSubfooter=e.$hasTabs=e.$hasTabsTop=!1,n(e,r,{$onScroll:"&onScroll",$onScrollComplete:"&onScrollComplete",hasBouncing:"@",padding:"@",direction:"@",scrollbarX:"@",scrollbarY:"@",startX:"@",startY:"@",scrollEventInterval:"@"}),e.direction=e.direction||"y",l(r.padding)&&e.$watch(r.padding,function(e){(a||i).toggleClass("padding",!!e)}),"false"===r.scroll);else{var f={};s?(i.addClass("overflow-scroll"),f={el:i[0],delegateHandle:o.delegateHandle,startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,nativeScrolling:!0}):f={el:i[0],delegateHandle:o.delegateHandle,locking:"true"===(o.locking||"true"),bouncing:e.$eval(e.hasBouncing),startX:e.$eval(e.startX)||0,startY:e.$eval(e.startY)||0,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,scrollEventInterval:parseInt(e.scrollEventInterval,10)||10,scrollingComplete:u},c=t("$ionicScroll",{$scope:e,scrollViewOptions:f}),e.scrollCtrl=c,e.$on("$destroy",function(){f&&(f.scrollingComplete=h,delete f.el),a=null,i=null,o.$$element=null})}}var a,c;e.addClass("scroll-content ionic-scroll"),"false"!=o.scroll?(a=f('<div class="scroll"></div>'),a.append(e.contents()),e.append(a)):e.addClass("scroll-content-false");var s="false"!==o.overflowScroll&&("true"===o.overflowScroll||!i.scrolling.jsScrolling());return s&&(s=!e[0].querySelector("[collection-repeat]")),{pre:r}}}}]),a.directive("exposeAsideWhen",["$window",function(e){return{restrict:"A",require:"^ionSideMenus",link:function(t,n,i,o){function r(){var t="large"==i.exposeAsideWhen?"(min-width:768px)":i.exposeAsideWhen;o.exposeAside(e.matchMedia(t).matches),o.activeAsideResizing(!1)}function a(){o.activeAsideResizing(!0),l()}var c="large"==i.exposeAsideWhen?"(min-width:768px)":i.exposeAsideWhen,s=e.matchMedia(c);s.addListener(function(){a()});var l=ionic.debounce(function(){t.$apply(r)},300,!1);t.$evalAsync(r)}}}]);var S="onHold onTap onDoubleTap onTouch onRelease onDragStart onDrag onDragEnd onDragUp onDragRight onDragDown onDragLeft onSwipe onSwipeUp onSwipeRight onSwipeDown onSwipeLeft".split(" ");S.forEach(function(e){a.directive(e,n(e))}),a.directive("ionHeaderBar",i(!0)).directive("ionFooterBar",i(!1)),a.directive("ionInfiniteScroll",["$timeout",function(e){return{restrict:"E",require:["?^$ionicScroll","ionInfiniteScroll"],template:function(e,t){return t.icon?'<i class="icon {{icon()}} icon-refreshing {{scrollingType}}"></i>':'<ion-spinner icon="{{spinner()}}"></ion-spinner>'},scope:!0,controller:"$ionInfiniteScroll",link:function(t,n,i,o){var r=o[1],a=r.scrollCtrl=o[0],c=r.jsScrolling=!a.isNative();if(c)r.scrollView=a.scrollView,t.scrollingType="js-scrolling",a.$element.on("scroll",r.checkBounds);else{var s=ionic.DomUtil.getParentOrSelfWithClass(n[0].parentNode,"overflow-scroll");if(r.scrollEl=s,!s)throw"Infinite scroll must be used inside a scrollable div";r.scrollEl.addEventListener("scroll",r.checkBounds)}var u=l(i.immediateCheck)?t.$eval(i.immediateCheck):!0;u&&e(function(){r.checkBounds()})}}}]);var k=-1;a.directive("ionInput",[function(){return{restrict:"E",controller:["$scope","$element",function(e,t){this.$scope=e,this.$element=t,this.setInputAriaLabeledBy=function(e){var n=t[0].querySelectorAll("input,textarea");n.length&&n[0].setAttribute("aria-labelledby",e)},this.focus=function(){var e=t[0].querySelectorAll("input,textarea");e.length&&e[0].focus()}}]}}]),a.directive("ionLabel",[function(){return{restrict:"E",require:"?^ionInput",compile:function(){return function(e,t,n,i){var o=t[0];t.addClass("input-label"),t.attr("aria-label",t.text());var r=o.id||"_label-"+ ++k;o.id||t.attr("id",r),i&&(i.setInputAriaLabeledBy(r),t.on("click",function(){i.focus()}))}}}}]),a.directive("inputLabel",[function(){return{restrict:"C",require:"?^ionInput",compile:function(){return function(e,t,n,i){var o=t[0];t.attr("aria-label",t.text());var r=o.id||"_label-"+ ++k;o.id||t.attr("id",r),i&&i.setInputAriaLabeledBy(r)}}}}]),a.directive("ionItem",["$$rAF",function(e){return{restrict:"E",controller:["$scope","$element",function(e,t){this.$scope=e,this.$element=t}],scope:!0,compile:function(t,n){var i=l(n.href)||l(n.ngHref)||l(n.uiSref),o=i||/ion-(delete|option|reorder)-button/i.test(t.html());if(o){var r=f(i?"<a></a>":"<div></div>");r.addClass("item-content"),(l(n.href)||l(n.ngHref))&&(r.attr("ng-href","{{$href()}}"),l(n.target)&&r.attr("target","{{$target()}}")),r.append(t.contents()),t.addClass("item item-complex").append(r); +}else t.addClass("item");return function(t,n,i){t.$href=function(){return i.href||i.ngHref},t.$target=function(){return i.target};var o=n[0].querySelector(".item-content");o&&t.$on("$collectionRepeatLeave",function(){o&&o.$$ionicOptionsOpen&&(o.style[ionic.CSS.TRANSFORM]="",o.style[ionic.CSS.TRANSITION]="none",e(function(){o.style[ionic.CSS.TRANSITION]=""}),o.$$ionicOptionsOpen=!1)})}}}}]);var C='<div class="item-left-edit item-delete enable-pointer-events"></div>';a.directive("ionDeleteButton",function(){function e(e){e.stopPropagation()}return{restrict:"E",require:["^^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),function(t,n,i,o){function r(){c=c||n.controller("ionList"),c&&c.showDelete()&&s.addClass("visible active")}var a=o[0],c=o[1],s=f(C);s.append(n),a.$element.append(s).addClass("item-left-editable"),n.on("click",e),r(),t.$on("$ionic.reconnectScope",r)}}}}),a.directive("itemFloatingLabel",function(){return{restrict:"C",link:function(e,t){var n=t[0],i=n.querySelector("input, textarea"),o=n.querySelector(".input-label");if(i&&o){var r=function(){i.value?o.classList.add("has-input"):o.classList.remove("has-input")};i.addEventListener("input",r);var a=f(i).controller("ngModel");a&&(a.$render=function(){i.value=a.$viewValue||"",r()}),e.$on("$destroy",function(){i.removeEventListener("input",r)})}}}});var T='<div class="item-options invisible"></div>';a.directive("ionOptionButton",[function(){function e(e){e.stopPropagation()}return{restrict:"E",require:"^ionItem",priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button",!0),function(t,n,i,o){o.optionsContainer||(o.optionsContainer=f(T),o.$element.append(o.optionsContainer)),o.optionsContainer.append(n),o.$element.addClass("item-right-editable"),n.on("click",e)}}}}]);var B='<div data-prevent-scroll="true" class="item-right-edit item-reorder enable-pointer-events"></div>';a.directive("ionReorderButton",["$parse",function(e){return{restrict:"E",require:["^ionItem","^?ionList"],priority:Number.MAX_VALUE,compile:function(t,n){return n.$set("class",(n["class"]||"")+" button icon button-icon",!0),t[0].setAttribute("data-prevent-scroll",!0),function(t,n,i,o){var r=o[0],a=o[1],c=e(i.onReorder);t.$onReorder=function(e,n){c(t,{$fromIndex:e,$toIndex:n})},i.ngClick||i.onClick||i.onclick||(n[0].onclick=function(e){return e.stopPropagation(),!1});var s=f(B);s.append(n),r.$element.append(s).addClass("item-right-editable"),a&&a.showReorder()&&s.addClass("visible active")}}}}]),a.directive("keyboardAttach",function(){return function(e,t){function n(e){if(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen){var n=e.keyboardHeight||e.detail&&e.detail.keyboardHeight;t.css("bottom",n+"px"),r=t.controller("$ionicScroll"),r&&(r.scrollView.__container.style.bottom=n+o(t[0])+"px")}}function i(){(!ionic.Platform.isAndroid()||ionic.Platform.isFullScreen)&&(t.css("bottom",""),r&&(r.scrollView.__container.style.bottom=""))}ionic.on("native.keyboardshow",n,window),ionic.on("native.keyboardhide",i,window),ionic.on("native.showkeyboard",n,window),ionic.on("native.hidekeyboard",i,window);var r;e.$on("$destroy",function(){ionic.off("native.keyboardshow",n,window),ionic.off("native.keyboardhide",i,window),ionic.off("native.showkeyboard",n,window),ionic.off("native.hidekeyboard",i,window)})}}),a.directive("ionList",["$timeout",function(e){return{restrict:"E",require:["ionList","^?$ionicScroll"],controller:"$ionicList",compile:function(t,n){var i=f('<div class="list">').append(t.contents()).addClass(n.type);return t.append(i),function(t,i,o,r){function a(){function o(e,t){t()&&e.addClass("visible")||e.removeClass("active"),ionic.requestAnimationFrame(function(){t()&&e.addClass("active")||e.removeClass("visible")})}var r=c.listView=new ionic.views.ListView({el:i[0],listEl:i.children()[0],scrollEl:s&&s.element,scrollView:s&&s.scrollView,onReorder:function(t,n,i){var o=f(t).scope();o&&o.$onReorder&&e(function(){o.$onReorder(n,i)})},canSwipe:function(){return c.canSwipeItems()}});t.$on("$destroy",function(){r&&(r.deregister&&r.deregister(),r=null)}),l(n.canSwipe)&&t.$watch("!!("+n.canSwipe+")",function(e){c.canSwipeItems(e)}),l(n.showDelete)&&t.$watch("!!("+n.showDelete+")",function(e){c.showDelete(e)}),l(n.showReorder)&&t.$watch("!!("+n.showReorder+")",function(e){c.showReorder(e)}),t.$watch(function(){return c.showDelete()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-left-editing",e),i.toggleClass("disable-pointer-events",e);var n=f(i[0].getElementsByClassName("item-delete"));o(n,c.showDelete)}}),t.$watch(function(){return c.showReorder()},function(e,t){if(e||t){e&&c.closeOptionButtons(),c.canSwipeItems(!e),i.children().toggleClass("list-right-editing",e),i.toggleClass("disable-pointer-events",e);var n=f(i[0].getElementsByClassName("item-reorder"));o(n,c.showReorder)}})}var c=r[0],s=r[1];e(a)}}}}]),a.directive("menuClose",["$ionicHistory","$timeout",function(e,t){return{restrict:"AC",link:function(n,i){i.bind("click",function(){var n=i.inheritedData("$ionSideMenusController");n&&(e.nextViewOptions({historyRoot:!0,disableAnimate:!0,expire:300}),t(function(){e.nextViewOptions({historyRoot:!1,disableAnimate:!1})},300),n.close())})}}}]),a.directive("menuToggle",function(){return{restrict:"AC",link:function(e,t,n){e.$on("$ionicView.beforeEnter",function(e,n){if(n.enableBack){var i=t.inheritedData("$ionSideMenusController");i.enableMenuWithBackViews()||t.addClass("hide")}else t.removeClass("hide")}),t.bind("click",function(){var e=t.inheritedData("$ionSideMenusController");e&&e.toggle(n.menuToggle)})}}}),a.directive("ionModal",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="modal-backdrop"><div class="modal-backdrop-bg"></div><div class="modal-wrapper" ng-transclude></div></div>'}}]),a.directive("ionModalView",function(){return{restrict:"E",compile:function(e){e.addClass("modal")}}}),a.directive("ionNavBackButton",["$ionicConfig","$document",function(e,t){return{restrict:"E",require:"^ionNavBar",compile:function(n,i){function o(e){return/ion-|icon/.test(e.className)}var r=t[0].createElement("button");for(var a in i.$attr)r.setAttribute(i.$attr[a],i[a]);i.ngClick||r.setAttribute("ng-click","$ionicGoBack()"),r.className="button back-button hide buttons "+(n.attr("class")||""),r.innerHTML=n.html()||"";for(var c,s,l,u,d=o(n[0]),f=0;f<n[0].childNodes.length;f++)c=n[0].childNodes[f],1===c.nodeType?o(c)?d=!0:c.classList.contains("default-title")?l=!0:c.classList.contains("previous-title")&&(u=!0):s||3!==c.nodeType||(s=!!c.nodeValue.trim());var h=e.backButton.icon();if(!d&&h&&"none"!==h&&(r.innerHTML='<i class="icon '+h+'"></i> '+r.innerHTML,r.className+=" button-clear"),!s){var p=t[0].createElement("span");p.className="back-text",!l&&e.backButton.text()&&(p.innerHTML+='<span class="default-title">'+e.backButton.text()+"</span>"),!u&&e.backButton.previousTitleText()&&(p.innerHTML+='<span class="previous-title"></span>'),r.appendChild(p)}return n.attr("class","hide"),n.empty(),{pre:function(e,t,n,i){i.navElement("backButton",r.outerHTML),r=null}}}}}]),a.directive("ionNavBar",function(){return{restrict:"E",controller:"$ionicNavBar",scope:!0,link:function(e,t,n,i){i.init()}}}),a.directive("ionNavButtons",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="left";/^primary|secondary|right$/i.test(n.side||"")&&(i=n.side.toLowerCase());var o=e[0].createElement("span");o.className=i+"-buttons",o.innerHTML=t.html();var r=i+"Buttons";return t.attr("class","hide"),t.empty(),{pre:function(e,t,n,i){var a=t.parent().data("$ionViewController");a?a.navElement(r,o.outerHTML):i.navElement(r,o.outerHTML),o=null}}}}}]),a.directive("navDirection",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextDirection(i.navDirection)})}}}]),a.directive("ionNavTitle",["$document",function(e){return{require:"^ionNavBar",restrict:"E",compile:function(t,n){var i="title",o=e[0].createElement("span");for(var r in n.$attr)o.setAttribute(n.$attr[r],n[r]);return o.classList.add("nav-bar-title"),o.innerHTML=t.html(),t.attr("class","hide"),t.empty(),{pre:function(e,t,n,r){var a=t.parent().data("$ionViewController");a?a.navElement(i,o.outerHTML):r.navElement(i,o.outerHTML),o=null}}}}}]),a.directive("navTransition",["$ionicViewSwitcher",function(e){return{restrict:"A",priority:1e3,link:function(t,n,i){n.bind("click",function(){e.nextTransition(i.navTransition)})}}}]),a.directive("ionNavView",["$state","$ionicConfig",function(e,t){return{restrict:"E",terminal:!0,priority:2e3,transclude:!0,controller:"$ionicNavView",compile:function(n,i,o){return n.addClass("view-container"),ionic.DomUtil.cachedAttr(n,"nav-view-transition",t.views.transition()),function(t,n,i,r){function a(t){var n=e.$current&&e.$current.locals[s.name];n&&(t||n!==c)&&(c=n,s.state=n.$$state,r.register(n))}var c;o(t,function(e){n.append(e)});var s=r.init();t.$on("$stateChangeSuccess",function(){a(!1)}),t.$on("$viewContentLoading",function(){a(!1)}),a(!0)}}}}]),a.config(["$provide",function(e){e.decorator("ngClickDirective",["$delegate",function(e){return e.shift(),e}])}]).factory("$ionicNgClick",["$parse",function(e){return function(t,n,i){var o=angular.isFunction(i)?i:e(i);n.on("click",function(e){t.$apply(function(){o(t,{$event:e})})}),n.onclick=h}}]).directive("ngClick",["$ionicNgClick",function(e){return function(t,n,i){e(t,n,i.ngClick)}}]).directive("ionStopEvent",function(){return{restrict:"A",link:function(e,t,n){t.bind(n.ionStopEvent,r)}}}),a.directive("ionPane",function(){return{restrict:"E",link:function(e,t){t.addClass("pane")}}}),a.directive("ionPopover",[function(){return{restrict:"E",transclude:!0,replace:!0,controller:[function(){}],template:'<div class="popover-backdrop"><div class="popover-wrapper" ng-transclude></div></div>'}}]),a.directive("ionPopoverView",function(){return{restrict:"E",compile:function(e){e.append(f('<div class="popover-arrow">')),e.addClass("popover")}}}),a.directive("ionRadio",function(){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<label class="item item-radio"><input type="radio" name="radio-group"><div class="radio-content"><div class="item-content disable-pointer-events" ng-transclude></div><i class="radio-icon disable-pointer-events icon ion-checkmark"></i></div></label>',compile:function(e,t){if(t.icon){var n=e.find("i");n.removeClass("ion-checkmark").addClass(t.icon)}var i=e.find("input");return s({name:t.name,value:t.value,disabled:t.disabled,"ng-value":t.ngValue,"ng-model":t.ngModel,"ng-disabled":t.ngDisabled,"ng-change":t.ngChange,"ng-required":t.ngRequired,required:t.required},function(e,t){l(e)&&i.attr(t,e)}),function(e,t,n){e.getValue=function(){return e.ngValue||n.value}}}}}),a.directive("ionRefresher",[function(){return{restrict:"E",replace:!0,require:["?^$ionicScroll","ionRefresher"],controller:"$ionicRefresher",template:'<div class="scroll-refresher invisible" collection-repeat-ignore><div class="ionic-refresher-content" ng-class="{\'ionic-refresher-with-text\': pullingText || refreshingText}"><div class="icon-pulling" ng-class="{\'pulling-rotation-disabled\':disablePullingRotation}"><i class="icon {{pullingIcon}}"></i></div><div class="text-pulling" ng-bind-html="pullingText"></div><div class="icon-refreshing"><ion-spinner ng-if="showSpinner" icon="{{spinner}}"></ion-spinner><i ng-if="showIcon" class="icon {{refreshingIcon}}"></i></div><div class="text-refreshing" ng-bind-html="refreshingText"></div></div></div>',link:function(e,t,n,i){var o=i[0],r=i[1];!o||o.isNative()?r.init():(t[0].classList.add("js-scrolling"),o._setRefresher(e,t[0],r.getRefresherDomMethods()),e.$on("scroll.refreshComplete",function(){e.$evalAsync(function(){o.scrollView.finishPullToRefresh()})}))}}}]),a.directive("ionScroll",["$timeout","$controller","$ionicBind","$ionicConfig",function(e,t,n,i){return{restrict:"E",scope:!0,controller:function(){},compile:function(e,o){function r(e,i,o){n(e,o,{direction:"@",paging:"@",$onScroll:"&onScroll",scroll:"@",scrollbarX:"@",scrollbarY:"@",zooming:"@",minZoom:"@",maxZoom:"@"}),e.direction=e.direction||"y",l(o.padding)&&e.$watch(o.padding,function(e){a.toggleClass("padding",!!e)}),e.$eval(e.paging)===!0&&a.addClass("scroll-paging"),e.direction||(e.direction="y");var r=e.$eval(e.paging)===!0;c&&i.addClass("overflow-scroll"),i.addClass("scroll-"+e.direction);var s={el:i[0],delegateHandle:o.delegateHandle,locking:"true"===(o.locking||"true"),bouncing:e.$eval(o.hasBouncing),paging:r,scrollbarX:e.$eval(e.scrollbarX)!==!1,scrollbarY:e.$eval(e.scrollbarY)!==!1,scrollingX:e.direction.indexOf("x")>=0,scrollingY:e.direction.indexOf("y")>=0,zooming:e.$eval(e.zooming)===!0,maxZoom:e.$eval(e.maxZoom)||3,minZoom:e.$eval(e.minZoom)||.5,preventDefault:!0,nativeScrolling:c};r&&(s.speedMultiplier=.8,s.bouncing=!1),t("$ionicScroll",{$scope:e,scrollViewOptions:s})}e.addClass("scroll-view ionic-scroll");var a=f('<div class="scroll"></div>');a.append(e.contents()),e.append(a);var c="false"!==o.overflowScroll&&("true"===o.overflowScroll||!i.scrolling.jsScrolling());return{pre:r}}}}]),a.directive("ionSideMenu",function(){return{restrict:"E",require:"^ionSideMenus",scope:!0,compile:function(e,t){return angular.isUndefined(t.isEnabled)&&t.$set("isEnabled","true"),angular.isUndefined(t.width)&&t.$set("width","275"),e.addClass("menu menu-"+t.side),function(e,n,i,o){e.side=i.side||"left";var r=o[e.side]=new ionic.views.SideMenu({width:t.width,el:n[0],isEnabled:!0});e.$watch(i.width,function(e){var t=+e;t&&t==e&&r.setWidth(+e)}),e.$watch(i.isEnabled,function(e){r.setIsEnabled(!!e)})}}}}),a.directive("ionSideMenuContent",["$timeout","$ionicGesture","$window",function(e,t,n){return{restrict:"EA",require:"^ionSideMenus",scope:!0,compile:function(i,o){function r(r,a,c,s){function u(e){0!==s.getOpenAmount()?(s.close(),e.gesture.srcEvent.preventDefault(),v=null,g=null):v||(v=ionic.tap.pointerCoord(e.gesture.srcEvent))}function d(e){s.isDraggableTarget(e)&&"x"==p(e)&&(s._handleDrag(e),e.gesture.srcEvent.preventDefault())}function f(e){"x"==p(e)&&e.gesture.srcEvent.preventDefault()}function h(e){s._endDrag(e),v=null,g=null}function p(e){if(g)return g;if(e&&e.gesture){if(v){var t=ionic.tap.pointerCoord(e.gesture.srcEvent),n=Math.abs(t.x-v.x),i=Math.abs(t.y-v.y),o=i>n?"y":"x";return Math.max(n,i)>30&&(g=o),o}v=ionic.tap.pointerCoord(e.gesture.srcEvent)}return"y"}var v=null,g=null;l(o.dragContent)?r.$watch(o.dragContent,function(e){s.canDragContent(e)}):s.canDragContent(!0),l(o.edgeDragThreshold)&&r.$watch(o.edgeDragThreshold,function(e){s.edgeDragThreshold(e)});var m={element:i[0],onDrag:function(){},endDrag:function(){},setCanScroll:function(e){var t=a[0].querySelector(".scroll");if(t){var n=angular.element(t.parentElement);if(n){var i=n.scope();i.scrollCtrl&&i.scrollCtrl.freezeScrollShut(!e)}}},getTranslateX:function(){return r.sideMenuContentTranslateX||0},setTranslateX:ionic.animationFrameThrottle(function(t){var n=m.offsetX+t;a[0].style[ionic.CSS.TRANSFORM]="translate3d("+n+"px,0,0)",e(function(){r.sideMenuContentTranslateX=t})}),setMarginLeft:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style[ionic.CSS.TRANSFORM]="translate3d("+e+"px,0,0)",a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)",a[0].style.width="",m.offsetX=0)}),setMarginRight:ionic.animationFrameThrottle(function(e){e?(e=parseInt(e,10),a[0].style.width=n.innerWidth-e+"px",m.offsetX=e):(a[0].style.width="",m.offsetX=0),a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)"}),setMarginLeftAndRight:ionic.animationFrameThrottle(function(e,t){e=e&&parseInt(e,10)||0,t=t&&parseInt(t,10)||0;var i=e+t;i>0?(a[0].style[ionic.CSS.TRANSFORM]="translate3d("+e+"px,0,0)",a[0].style.width=n.innerWidth-i+"px",m.offsetX=e):(a[0].style[ionic.CSS.TRANSFORM]="translate3d(0,0,0)",a[0].style.width="",m.offsetX=0)}),enableAnimation:function(){r.animationEnabled=!0,a[0].classList.add("menu-animated")},disableAnimation:function(){r.animationEnabled=!1,a[0].classList.remove("menu-animated")},offsetX:0};s.setContent(m);var $={stop_browser_behavior:!1};$.prevent_default_directions=["left","right"];var w=t.on("tap",u,a,$),b=t.on("dragright",d,a,$),y=t.on("dragleft",d,a,$),S=t.on("dragup",f,a,$),k=t.on("dragdown",f,a,$),C=t.on("release",h,a,$);r.$on("$destroy",function(){m&&(m.element=null,m=null),t.off(y,"dragleft",d),t.off(b,"dragright",d),t.off(S,"dragup",f),t.off(k,"dragdown",f),t.off(C,"release",h),t.off(w,"tap",u)})}return i.addClass("menu-content pane"),{pre:r}}}}]),a.directive("ionSideMenus",["$ionicBody",function(e){return{restrict:"ECA",controller:"$ionicSideMenus",compile:function(t,n){function i(t,n,i,o){o.enableMenuWithBackViews(t.$eval(i.enableMenuWithBackViews)),t.$on("$ionicExposeAside",function(n,i){t.$exposeAside||(t.$exposeAside={}),t.$exposeAside.active=i,e.enableClass(i,"aside-open")}),t.$on("$ionicView.beforeEnter",function(e,n){n.historyId&&(t.$activeHistoryId=n.historyId)}),t.$on("$destroy",function(){e.removeClass("menu-open","aside-open")})}return n.$set("class",(n["class"]||"")+" view"),{pre:i}}}}]),a.directive("ionSlideBox",["$animate","$timeout","$compile","$ionicSlideBoxDelegate","$ionicHistory","$ionicScrollDelegate",function(e,t,n,i,o,r){return{restrict:"E",replace:!0,transclude:!0,scope:{autoPlay:"=",doesContinue:"@",slideInterval:"@",showPager:"@",pagerClick:"&",disableScroll:"@",onSlideChanged:"&",activeSlide:"=?",bounce:"@"},controller:["$scope","$element","$attrs",function(e,n,a){function c(e){e&&!s.isScrollFreeze?r.freezeAllScrolls(e):!e&&s.isScrollFreeze&&r.freezeAllScrolls(!1),s.isScrollFreeze=e}var s=this,u=e.$eval(e.doesContinue)===!0,d=e.$eval(e.bounce)!==!1,f=l(a.autoPlay)?!!e.autoPlay:!1,h=f?e.$eval(e.slideInterval)||4e3:0,p=new ionic.views.Slider({el:n[0],auto:h,continuous:u,startSlide:e.activeSlide,bouncing:d,slidesChanged:function(){e.currentSlide=p.currentIndex(),t(function(){})},callback:function(n){e.currentSlide=n,e.onSlideChanged({index:e.currentSlide,$index:e.currentSlide}),e.$parent.$broadcast("slideBox.slideChanged",n),e.activeSlide=n,t(function(){})},onDrag:function(){c(!0)},onDragEnd:function(){c(!1)}});p.enableSlide(e.$eval(a.disableScroll)!==!0),e.$watch("activeSlide",function(e){l(e)&&p.slide(e)}),e.$on("slideBox.nextSlide",function(){p.next()}),e.$on("slideBox.prevSlide",function(){p.prev()}),e.$on("slideBox.setSlide",function(e,t){p.slide(t)}),this.__slider=p;var v=i._registerInstance(p,a.delegateHandle,function(){return o.isActiveScope(e)});e.$on("$destroy",function(){v(),p.kill()}),this.slidesCount=function(){return p.slidesCount()},this.onPagerClick=function(t){e.pagerClick({index:t})},t(function(){p.load()})}],template:'<div class="slider"><div class="slider-slides" ng-transclude></div></div>',link:function(t,i,o){function r(){if(!a){var e=t.$new();a=f("<ion-pager></ion-pager>"),i.append(a),a=n(a)(e)}return a}e.enabled(!1,i),l(o.showPager)||(t.showPager=!0,r().toggleClass("hide",!1)),o.$observe("showPager",function(e){void 0!==e&&(e=t.$eval(e),r().toggleClass("hide",!e))});var a}}}]).directive("ionSlide",function(){return{restrict:"E",require:"?^ionSlideBox",compile:function(e){e.addClass("slider-slide")}}}).directive("ionPager",function(){return{restrict:"E",replace:!0,require:"^ionSlideBox",template:'<div class="slider-pager"><span class="slider-pager-page" ng-repeat="slide in numSlides() track by $index" ng-class="{active: $index == currentSlide}" ng-click="pagerClick($index)"><i class="icon ion-record"></i></span></div>',link:function(e,t,n,i){var o=function(e){for(var n=t[0].children,i=n.length,o=0;i>o;o++)o==e?n[o].classList.add("active"):n[o].classList.remove("active")};e.pagerClick=function(e){i.onPagerClick(e)},e.numSlides=function(){return new Array(i.slidesCount())},e.$watch("currentSlide",function(e){o(e)})}}}),a.directive("ionSlides",["$animate","$timeout","$compile",function(e,t,n){return{restrict:"E",transclude:!0,scope:{options:"=",slider:"="},template:'<div class="swiper-container"><div class="swiper-wrapper" ng-transclude></div><div ng-hide="!showPager" class="swiper-pagination"></div></div>',controller:["$scope","$element",function(e,i){var o=this;this.update=function(){t(function(){o.__slider&&(o.__slider.update(),o._options.loop&&o.__slider.createLoop(),o.__slider.slides.length>10&&(e.showPager=!1))})},this.rapidUpdate=ionic.debounce(function(){o.update()},50),this.getSlider=function(){return o.__slider};var r=e.options||{},a=angular.extend({pagination:".swiper-pagination",paginationClickable:!0,lazyLoading:!0,preloadImages:!1},r);this._options=a,t(function(){var t=new ionic.views.Swiper(i.children()[0],a,e,n);o.__slider=t,e.slider=o.__slider,e.$on("$destroy",function(){t.destroy()})})}],link:function(e){e.showPager=!0}}}]).directive("ionSlidePage",[function(){return{restrict:"E",require:"?^ionSlides",transclude:!0,replace:!0,template:'<div class="swiper-slide" ng-transclude></div>',link:function(e,t,n,i){i.rapidUpdate()}}}]),a.directive("ionSpinner",function(){return{restrict:"E",controller:"$ionicSpinner",link:function(e,t,n,i){var o=i.init();t.addClass("spinner spinner-"+o),t.on("$destroy",function(){i.stop()})}}}),a.directive("ionTab",["$compile","$ionicConfig","$ionicBind","$ionicViewSwitcher",function(e,t,n,i){function o(e,t){return l(t)?" "+e+'="'+t+'"':""}return{restrict:"E",require:["^ionTabs","ionTab"],controller:"$ionicTab",scope:!0,compile:function(r,a){for(var c="<ion-tab-nav"+o("ng-click",a.ngClick)+o("title",a.title)+o("icon",a.icon)+o("icon-on",a.iconOn)+o("icon-off",a.iconOff)+o("badge",a.badge)+o("badge-style",a.badgeStyle)+o("hidden",a.hidden)+o("disabled",a.disabled)+o("class",a["class"])+"></ion-tab-nav>",s=document.createElement("div"),l=0;l<r[0].children.length;l++)s.appendChild(r[0].children[l].cloneNode(!0));var u=s.childElementCount;r.empty();var d,h;return u&&("ION-NAV-VIEW"===s.children[0].tagName&&(d=s.children[0].getAttribute("name"),s.children[0].classList.add("view-container"),h=!0),1===u&&(s=s.children[0]),h||s.classList.add("pane"),s.classList.add("tab-content")),function(o,r,a,l){function h(){w.tabMatchesState()&&$.select(o,!1)}function p(n){n&&u?(b||(g=o.$new(),m=f(s),i.viewEleIsActive(m,!0),$.$element.append(m),e(m)(g),b=!0),i.viewEleIsActive(m,!0)):b&&m&&(t.views.maxCache()>0?i.viewEleIsActive(m,!1):v())}function v(){g&&g.$destroy(),b&&m&&m.remove(),s.innerHTML="",b=g=m=null}var g,m,$=l[0],w=l[1],b=!1;o.$tabSelected=!1,n(o,a,{onSelect:"&",onDeselect:"&",title:"@",uiSref:"@",href:"@"}),$.add(o),o.$on("$destroy",function(){o.$tabsDestroy||$.remove(o),y.isolateScope().$destroy(),y.remove(),y=s=m=null}),r[0].removeAttribute("title"),d&&(w.navViewName=o.navViewName=d),o.$on("$stateChangeSuccess",h),h();var y=f(c);y.data("$ionTabsController",$),y.data("$ionTabController",w),$.$tabsElement.append(e(y)(o)),o.$watch("$tabSelected",p),o.$on("$ionicView.afterEnter",function(){i.viewEleIsActive(m,o.$tabSelected)}),o.$on("$ionicView.clearCache",function(){o.$tabSelected||v()})}}}}]),a.directive("ionTabNav",[function(){return{restrict:"E",replace:!0,require:["^ionTabs","^ionTab"],template:"<a ng-class=\"{'tab-item-active': isTabActive(), 'has-badge':badge, 'tab-hidden':isHidden()}\" "+' ng-disabled="disabled()" class="tab-item"><span class="badge {{badgeStyle}}" ng-if="badge">{{badge}}</span><i class="icon {{getIconOn()}}" ng-if="getIconOn() && isTabActive()"></i><i class="icon {{getIconOff()}}" ng-if="getIconOff() && !isTabActive()"></i><span class="tab-title" ng-bind-html="title"></span></a>',scope:{title:"@",icon:"@",iconOn:"@",iconOff:"@",badge:"=",hidden:"@",disabled:"&",badgeStyle:"@","class":"@"},link:function(e,t,n,i){var o=i[0],r=i[1];t[0].removeAttribute("title"),e.selectTab=function(e){e.preventDefault(),o.select(r.$scope,!0)},n.ngClick||t.on("click",function(t){e.$apply(function(){e.selectTab(t)})}),e.isHidden=function(){return"true"===n.hidden||n.hidden===!0?!0:!1},e.getIconOn=function(){return e.iconOn||e.icon},e.getIconOff=function(){return e.iconOff||e.icon},e.isTabActive=function(){return o.selectedTab()===r.$scope}}}}]),a.directive("ionTabs",["$ionicTabsDelegate","$ionicConfig",function(e,t){return{restrict:"E",scope:!0,controller:"$ionicTabs",compile:function(n){function i(t,n,i,o){function a(e,t){e.stopPropagation();var n=o.previousSelectedTab();n&&n.$broadcast(e.name.replace("NavView","Tabs"),t)}var c=e._registerInstance(o,i.delegateHandle,o.hasActiveScope);o.$scope=t,o.$element=n,o.$tabsElement=f(n[0].querySelector(".tabs")),t.$watch(function(){return n[0].className},function(e){var n=-1!==e.indexOf("tabs-top"),i=-1!==e.indexOf("tabs-item-hide");t.$hasTabs=!n&&!i,t.$hasTabsTop=n&&!i,t.$emit("$ionicTabs.top",t.$hasTabsTop)}),t.$on("$ionicNavView.beforeLeave",a),t.$on("$ionicNavView.afterLeave",a),t.$on("$ionicNavView.leave",a),t.$on("$destroy",function(){t.$tabsDestroy=!0,c(),o.$tabsElement=o.$element=o.$scope=r=null,delete t.$hasTabs,delete t.$hasTabsTop})}function o(e,t,n,i){i.selectedTab()||i.select(0)}var r=f('<div class="tab-nav tabs">');return r.append(n.contents()),n.append(r).addClass("tabs-"+t.tabs.position()+" tabs-"+t.tabs.style()),{pre:i,post:o}}}}]),a.directive("ionTitle",[function(){return{restrict:"E",compile:function(e){e.addClass("title")}}}]),a.directive("ionToggle",["$timeout","$ionicConfig",function(e,t){return{restrict:"E",replace:!0,require:"?ngModel",transclude:!0,template:'<div class="item item-toggle"><div ng-transclude></div><label class="toggle"><input type="checkbox"><div class="track"><div class="handle"></div></div></label></div>',compile:function(e,n){var i=e.find("input");return s({name:n.name,"ng-value":n.ngValue,"ng-model":n.ngModel,"ng-checked":n.ngChecked,"ng-disabled":n.ngDisabled,"ng-true-value":n.ngTrueValue,"ng-false-value":n.ngFalseValue,"ng-change":n.ngChange,"ng-required":n.ngRequired,required:n.required},function(e,t){l(e)&&i.attr(t,e)}),n.toggleClass&&e[0].getElementsByTagName("label")[0].classList.add(n.toggleClass),e.addClass("toggle-"+t.form.toggle()),function(e,t){var n=t[0].getElementsByTagName("label")[0],i=n.children[0],o=n.children[1],r=o.children[0],a=f(i).controller("ngModel");e.toggle=new ionic.views.Toggle({el:n,track:o,checkbox:i,handle:r,onChange:function(){a&&(a.$setViewValue(i.checked),e.$apply())}}),e.$on("$destroy",function(){e.toggle.destroy()})}}}}]),a.directive("ionView",function(){return{restrict:"EA",priority:1e3,controller:"$ionicView",compile:function(e){return e.addClass("pane"),e[0].removeAttribute("title"),function(e,t,n,i){i.init()}}}})}(); \ No newline at end of file diff --git a/www/lib/ionic/js/ionic.js b/www/lib/ionic/js/ionic.js index c0bc8be851ea25c0f28af5d879546007d460e501..e2beb6d25349840a65bf00f2fbc6fc2ac0ab26c1 100644 --- a/www/lib/ionic/js/ionic.js +++ b/www/lib/ionic/js/ionic.js @@ -1,8 +1,8 @@ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -18,7 +18,7 @@ // build processes may have already created an ionic obj window.ionic = window.ionic || {}; window.ionic.views = {}; -window.ionic.version = '1.0.1'; +window.ionic.version = '1.2.4'; (function (ionic) { @@ -237,6 +237,17 @@ window.ionic.version = '1.0.1'; }; }, + getOffsetTop: function(el) { + var curtop = 0; + if (el.offsetParent) { + do { + curtop += el.offsetTop; + el = el.offsetParent; + } while (el) + return curtop; + } + }, + /** * @ngdoc method * @name ionic.DomUtil#ready @@ -1621,7 +1632,7 @@ window.ionic.version = '1.0.1'; index: 10, defaults: { hold_timeout: 500, - hold_threshold: 1 + hold_threshold: 9 }, timer: null, handler: function holdGesture(ev, inst) { @@ -1778,8 +1789,8 @@ window.ionic.version = '1.0.1'; } else if (!this.preventedFirstMove && ev.srcEvent.type == 'touchmove') { // Prevent gestures that are not intended for this event handler from firing subsequent times - if (inst.options.prevent_default_directions.length === 0 - || inst.options.prevent_default_directions.indexOf(ev.direction) != -1) { + if (inst.options.prevent_default_directions.length > 0 + && inst.options.prevent_default_directions.indexOf(ev.direction) != -1) { ev.srcEvent.preventDefault(); } this.preventedFirstMove = true; @@ -2029,6 +2040,8 @@ window.ionic.version = '1.0.1'; var IOS = 'ios'; var ANDROID = 'android'; var WINDOWS_PHONE = 'windowsphone'; + var EDGE = 'edge'; + var CROSSWALK = 'crosswalk'; var requestAnimationFrame = ionic.requestAnimationFrame; /** @@ -2248,6 +2261,18 @@ window.ionic.version = '1.0.1'; isWindowsPhone: function() { return self.is(WINDOWS_PHONE); }, + /** + * @ngdoc method + * @name ionic.Platform#isEdge + * @returns {boolean} Whether we are running on MS Edge/Windows 10 (inc. Phone) + */ + isEdge: function() { + return self.is(EDGE); + }, + + isCrosswalk: function() { + return self.is(CROSSWALK); + }, /** * @ngdoc method @@ -2268,12 +2293,14 @@ window.ionic.version = '1.0.1'; platformName = n.toLowerCase(); } else if (getParameterByName('ionicplatform')) { platformName = getParameterByName('ionicplatform'); + } else if (self.ua.indexOf('Edge') > -1) { + platformName = EDGE; + } else if (self.ua.indexOf('Windows Phone') > -1) { + platformName = WINDOWS_PHONE; } else if (self.ua.indexOf('Android') > 0) { platformName = ANDROID; } else if (/iPhone|iPad|iPod/.test(self.ua)) { platformName = IOS; - } else if (self.ua.indexOf('Windows Phone') > -1) { - platformName = WINDOWS_PHONE; } else { platformName = self.navigator.platform && navigator.platform.toLowerCase().split(' ')[0] || ''; } @@ -2320,7 +2347,12 @@ window.ionic.version = '1.0.1'; } }, - // Check if the platform is the one detected by cordova + /** + * @ngdoc method + * @name ionic.Platform#is + * @param {string} Platform name. + * @returns {boolean} Whether the platform name provided is detected. + */ is: function(type) { type = type.toLowerCase(); // check if it has an array of platforms @@ -2407,7 +2439,19 @@ window.ionic.version = '1.0.1'; var platformName = null, // just the name, like iOS or Android platformVersion = null, // a float of the major and minor, like 7.1 readyCallbacks = [], - windowLoadListenderAttached; + windowLoadListenderAttached, + platformReadyTimer = 2000; // How long to wait for platform ready before emitting a warning + + verifyPlatformReady(); + + // Warn the user if deviceready did not fire in a reasonable amount of time, and how to fix it. + function verifyPlatformReady() { + setTimeout(function() { + if(!self.isReady && self.isWebView()) { + void 0; + } + }, platformReadyTimer); + } // setup listeners to know when the device is ready to go function onWindowLoad() { @@ -2447,13 +2491,17 @@ window.ionic.version = '1.0.1'; }); } -})(this, document, ionic); +})(window, document, ionic); (function(document, ionic) { 'use strict'; // Ionic CSS polyfills ionic.CSS = {}; + ionic.CSS.TRANSITION = []; + ionic.CSS.TRANSFORM = []; + + ionic.EVENTS = {}; (function() { @@ -2477,6 +2525,9 @@ window.ionic.version = '1.0.1'; } } + // Fallback in case the keys don't exist at all + ionic.CSS.TRANSITION = ionic.CSS.TRANSITION || 'transition'; + // The only prefix we care about is webkit for transitions. var isWebkit = ionic.CSS.TRANSITION.indexOf('webkit') > -1; @@ -2487,6 +2538,30 @@ window.ionic.version = '1.0.1'; ionic.CSS.TRANSITIONEND = (isWebkit ? 'webkitTransitionEnd ' : '') + 'transitionend'; })(); + (function() { + var touchStartEvent = 'touchstart'; + var touchMoveEvent = 'touchmove'; + var touchEndEvent = 'touchend'; + var touchCancelEvent = 'touchcancel'; + + if (window.navigator.pointerEnabled) { + touchStartEvent = 'pointerdown'; + touchMoveEvent = 'pointermove'; + touchEndEvent = 'pointerup'; + touchCancelEvent = 'pointercancel'; + } else if (window.navigator.msPointerEnabled) { + touchStartEvent = 'MSPointerDown'; + touchMoveEvent = 'MSPointerMove'; + touchEndEvent = 'MSPointerUp'; + touchCancelEvent = 'MSPointerCancel'; + } + + ionic.EVENTS.touchstart = touchStartEvent; + ionic.EVENTS.touchmove = touchMoveEvent; + ionic.EVENTS.touchend = touchEndEvent; + ionic.EVENTS.touchcancel = touchCancelEvent; + })(); + // classList polyfill for them older Androids // https://gist.github.com/devongovett/1381839 if (!("classList" in document.documentElement) && Object.defineProperty && typeof HTMLElement !== 'undefined') { @@ -2655,7 +2730,7 @@ ionic.tap = { if (window.navigator.pointerEnabled) { tapEventListener('pointerdown'); tapEventListener('pointerup'); - tapEventListener('pointcancel'); + tapEventListener('pointercancel'); tapTouchMoveListener = 'pointermove'; } else if (window.navigator.msPointerEnabled) { @@ -2705,6 +2780,11 @@ ionic.tap = { (ele.tagName == 'INPUT' && (/^(date|time|datetime-local|month|week)$/i).test(ele.type)); }, + isVideo: function(ele) { + return !!ele && + (ele.tagName == 'VIDEO'); + }, + isKeyboardElement: function(ele) { if ( !ionic.Platform.isIOS() || ionic.Platform.isIPad() ) { return ionic.tap.isTextInput(ele) && !ionic.tap.isDateInput(ele); @@ -2771,6 +2851,9 @@ ionic.tap = { }, requiresNativeClick: function(ele) { + if (ionic.Platform.isWindowsPhone() && (ele.tagName == 'A' || ele.tagName == 'BUTTON' || ele.hasAttribute('ng-click') || (ele.tagName == 'INPUT' && (ele.type == 'button' || ele.type == 'submit')))) { + return true; //Windows Phone edge case, prevent ng-click (and similar) events from firing twice on this platform + } if (!ele || ele.disabled || (/^(file|range)$/i).test(ele.type) || (/^(object|video)$/i).test(ele.tagName) || ionic.tap.isLabelContainingFileInput(ele)) { return true; } @@ -2789,7 +2872,7 @@ ionic.tap = { if (ele && ele.nodeType === 1) { var element = ele; while (element) { - if ((element.dataset ? element.dataset.tapDisabled : element.getAttribute('data-tap-disabled')) == 'true') { + if ((element.dataset ? element.dataset.tapDisabled : element.getAttribute && element.getAttribute('data-tap-disabled')) == 'true') { return true; } element = element.parentElement; @@ -2885,14 +2968,17 @@ function tapMouseDown(e) { if (e.isIonicTap || tapIgnoreEvent(e)) return null; if (tapEnabledTouchEvents) { - void 0; + //console.log('mousedown', 'stop event'); e.stopPropagation(); - if ((!ionic.tap.isTextInput(e.target) || tapLastTouchTarget !== e.target) && !(/^(select|option)$/i).test(e.target.tagName)) { + if (!ionic.Platform.isEdge() && (!ionic.tap.isTextInput(e.target) || tapLastTouchTarget !== e.target) && + !isSelectOrOption(e.target.tagName) && !ionic.tap.isVideo(e.target)) { // If you preventDefault on a text input then you cannot move its text caret/cursor. // Allow through only the text input default. However, without preventDefault on an // input the 300ms delay can change focus on inputs after the keyboard shows up. // The focusin event handles the chance of focus changing after the keyboard shows. + // Windows Phone - if you preventDefault on a video element then you cannot operate + // its native controls. e.preventDefault(); } @@ -2914,7 +3000,7 @@ function tapMouseUp(e) { return false; } - if (tapIgnoreEvent(e) || (/^(select|option)$/i).test(e.target.tagName)) return false; + if (tapIgnoreEvent(e) || isSelectOrOption(e.target.tagName)) return false; if (!tapHasPointerMoved(e)) { tapClick(e); @@ -2956,6 +3042,7 @@ function tapTouchStart(e) { var textInput = tapTargetElement(tapContainingElement(e.target)); if (textInput !== tapActiveEle) { // don't preventDefault on an already focused input or else iOS's text caret isn't usable + //console.log('Would prevent default here'); e.preventDefault(); } } @@ -2969,7 +3056,7 @@ function tapTouchEnd(e) { if (!tapHasPointerMoved(e)) { tapClick(e); - if ((/^(select|option)$/i).test(e.target.tagName)) { + if (isSelectOrOption(e.target.tagName)) { e.preventDefault(); } } @@ -3005,6 +3092,10 @@ function tapIgnoreEvent(e) { if (e.isTapHandled) return true; e.isTapHandled = true; + if(ionic.tap.isElementTapDisabled(e.target)) { + return true; + } + if (ionic.scroll.isScrolling && ionic.tap.containsOrIsTextInput(e.target)) { e.preventDefault(); return true; @@ -3026,7 +3117,7 @@ function tapHandleFocus(ele) { // already is the active element and has focus triggerFocusIn = true; - } else if ((/^(input|textarea)$/i).test(ele.tagName) || ele.isContentEditable) { + } else if ((/^(input|textarea|ion-label)$/i).test(ele.tagName) || ele.isContentEditable) { triggerFocusIn = true; ele.focus && ele.focus(); ele.value = ele.value; @@ -3049,7 +3140,7 @@ function tapHandleFocus(ele) { function tapFocusOutActive() { var ele = tapActiveElement(); if (ele && ((/^(input|textarea|select)$/i).test(ele.tagName) || ele.isContentEditable)) { - void 0; + //console.log('tapFocusOutActive', ele.tagName); ele.blur(); } tapActiveElement(null); @@ -3070,7 +3161,7 @@ function tapFocusIn(e) { // 2) There is an active element which is a text input // 3) A text input was just set to be focused on by a touch event // 4) A new focus has been set, however the target isn't the one the touch event wanted - void 0; + //console.log('focusin', 'tapTouchFocusedInput'); tapTouchFocusedInput.focus(); tapTouchFocusedInput = null; } @@ -3128,6 +3219,10 @@ function tapTargetElement(ele) { return ele; } +function isSelectOrOption(tagName){ + return (/^(select|option)$/i).test(tagName); +} + ionic.DomUtil.ready(function() { var ng = typeof angular !== 'undefined' ? angular : null; //do nothing for e2e tests @@ -3548,6 +3643,12 @@ var keyboardLandscapeViewportHeight = 0; */ var keyboardActiveElement; +/** + * The previously focused input used to reset keyboard after focusing on a + * new non-keyboard element + */ +var lastKeyboardActiveElement; + /** * The scroll view containing the currently focused input. */ @@ -3764,6 +3865,9 @@ function keyboardFocusIn(e) { e.target.readOnly || !ionic.tap.isKeyboardElement(e.target) || !(scrollView = ionic.DomUtil.getParentWithClass(e.target, SCROLL_CONTAINER_CSS))) { + if (keyboardActiveElement) { + lastKeyboardActiveElement = keyboardActiveElement; + } keyboardActiveElement = null; return; } @@ -3999,9 +4103,9 @@ function keyboardHide() { ionic.keyboard.isOpen = false; ionic.keyboard.isClosing = false; - if (keyboardActiveElement) { + if (keyboardActiveElement || lastKeyboardActiveElement) { ionic.trigger('resetScrollView', { - target: keyboardActiveElement + target: keyboardActiveElement || lastKeyboardActiveElement }, true); } @@ -4025,6 +4129,7 @@ function keyboardHide() { } keyboardActiveElement = null; + lastKeyboardActiveElement = null; } /** @@ -4612,7 +4717,7 @@ var zyngaCore = { effect: {} }; return id; } }; -})(this); +})(window); /* * Scroller @@ -4793,6 +4898,9 @@ ionic.views.Scroll = ionic.views.View.inherit({ return self.options.freeze; }; + // We can just use the standard freeze pop in our mouth + self.freezeShut = self.freeze; + self.setScrollStart = function() { ionic.scroll.isScrolling = Math.abs(ionic.scroll.lastTop - self.__scrollTop) > 1; clearTimeout(self.scrollTimer); @@ -5267,6 +5375,7 @@ ionic.views.Scroll = ionic.views.View.inherit({ document.addEventListener("touchmove", self.touchMove, false); document.addEventListener("touchend", self.touchEnd, false); document.addEventListener("touchcancel", self.touchEnd, false); + document.addEventListener("wheel", self.mouseWheel, false); } else if (window.navigator.pointerEnabled) { // Pointer Events @@ -6865,7 +6974,7 @@ ionic.scroll = { (function(ionic) { var NOOP = function() {}; - var depreciated = function(name) { + var deprecated = function(name) { void 0; }; ionic.views.ScrollNative = ionic.views.View.inherit({ @@ -6874,6 +6983,8 @@ ionic.scroll = { var self = this; self.__container = self.el = options.el; self.__content = options.el.firstElementChild; + // Whether scrolling is frozen or not + self.__frozen = false; self.isNative = true; self.__scrollTop = self.el.scrollTop; @@ -6883,6 +6994,16 @@ ionic.scroll = { self.__maxScrollTop = Math.max((self.__contentHeight) - self.__clientHeight, 0); self.__maxScrollLeft = Math.max((self.__contentWidth) - self.__clientWidth, 0); + if(options.startY >= 0 || options.startX >= 0) { + ionic.requestAnimationFrame(function() { + self.el.scrollTop = options.startY || 0; + self.el.scrollLeft = options.startX || 0; + + self.__scrollTop = self.el.scrollTop; + self.__scrollLeft = self.el.scrollLeft; + }); + } + self.options = { freeze: false, @@ -6915,16 +7036,22 @@ ionic.scroll = { }, 80); }; - self.freeze = NOOP; + self.freeze = function(shouldFreeze) { + self.__frozen = shouldFreeze; + }; + // A more powerful freeze pop that dominates all other freeze pops + self.freezeShut = function(shouldFreezeShut) { + self.__frozenShut = shouldFreezeShut; + }; self.__initEventHandlers(); }, /** Methods not used in native scrolling */ - __callback: function() { depreciated('__callback'); }, - zoomTo: function() { depreciated('zoomTo'); }, - zoomBy: function() { depreciated('zoomBy'); }, - activatePullToRefresh: function() { depreciated('activatePullToRefresh'); }, + __callback: function() { deprecated('__callback'); }, + zoomTo: function() { deprecated('zoomTo'); }, + zoomBy: function() { deprecated('zoomBy'); }, + activatePullToRefresh: function() { deprecated('activatePullToRefresh'); }, /** * Returns the scroll position and zooming values @@ -7064,6 +7191,19 @@ ionic.scroll = { self.resize(); return; } + + var oldOverflowX = self.el.style.overflowX; + var oldOverflowY = self.el.style.overflowY; + + clearTimeout(self.__scrollToCleanupTimeout); + self.__scrollToCleanupTimeout = setTimeout(function() { + self.el.style.overflowX = oldOverflowX; + self.el.style.overflowY = oldOverflowY; + }, 500); + + self.el.style.overflowY = 'hidden'; + self.el.style.overflowX = 'hidden'; + animateScroll(top, left); function animateScroll(Y, X) { @@ -7075,6 +7215,8 @@ ionic.scroll = { fromX = self.el.scrollLeft; if (fromY === Y && fromX === X) { + self.el.style.overflowX = oldOverflowX; + self.el.style.overflowY = oldOverflowY; self.resize(); return; /* Prevent scrolling to the Y point if already there */ } @@ -7105,6 +7247,8 @@ ionic.scroll = { } else { // done ionic.tap.removeClonedInputs(self.__container, self); + self.el.style.overflowX = oldOverflowX; + self.el.style.overflowY = oldOverflowY; self.resize(); } } @@ -7162,21 +7306,29 @@ ionic.scroll = { // save height when scroll view is shrunk so we don't need to reflow var scrollViewOffsetHeight; + var lastKeyboardHeight; + /** * Shrink the scroll view when the keyboard is up if necessary and if the * focused input is below the bottom of the shrunk scroll view, scroll it * into view. */ self.scrollChildIntoView = function(e) { - //console.log("scrollChildIntoView at: " + Date.now()); + var rect = container.getBoundingClientRect(); + if(!self.__originalContainerHeight) { + self.__originalContainerHeight = rect.height; + } // D - var scrollBottomOffsetToTop = container.getBoundingClientRect().bottom; + //var scrollBottomOffsetToTop = rect.bottom; // D - A - scrollViewOffsetHeight = container.offsetHeight; + scrollViewOffsetHeight = self.__originalContainerHeight; + //console.log('Scroll view offset height', scrollViewOffsetHeight); + //console.dir(container); var alreadyShrunk = self.isShrunkForKeyboard; var isModal = container.parentNode.classList.contains('modal'); + var isPopover = container.parentNode.classList.contains('popover'); // 680px is when the media query for 60% modal width kicks in var isInsetModal = isModal && window.innerWidth >= 680; @@ -7192,24 +7344,41 @@ ionic.scroll = { * All commented calculations relative to the top of the viewport (ie E * is the viewport height, not 0) */ - if (!alreadyShrunk) { + + + var changedKeyboardHeight = lastKeyboardHeight && (lastKeyboardHeight !== e.detail.keyboardHeight); + + if (!alreadyShrunk || changedKeyboardHeight) { // shrink scrollview so we can actually scroll if the input is hidden // if it isn't shrink so we can scroll to inputs under the keyboard // inset modals won't shrink on Android on their own when the keyboard appears - if ( ionic.Platform.isIOS() || ionic.Platform.isFullScreen || isInsetModal ) { + if ( !isPopover && (ionic.Platform.isIOS() || ionic.Platform.isFullScreen || isInsetModal) ) { // if there are things below the scroll view account for them and // subtract them from the keyboard height when resizing // E - D E D - var scrollBottomOffsetToBottom = e.detail.viewportHeight - scrollBottomOffsetToTop; + //var scrollBottomOffsetToBottom = e.detail.viewportHeight - scrollBottomOffsetToTop; // 0 or D - B if D > B E - B E - D - var keyboardOffset = Math.max(0, e.detail.keyboardHeight - scrollBottomOffsetToBottom); + //var keyboardOffset = e.detail.keyboardHeight - scrollBottomOffsetToBottom; ionic.requestAnimationFrame(function(){ // D - A or B - A if D > B D - A max(0, D - B) - scrollViewOffsetHeight = scrollViewOffsetHeight - keyboardOffset; + scrollViewOffsetHeight = Math.max(0, Math.min(self.__originalContainerHeight, self.__originalContainerHeight - (e.detail.keyboardHeight - 43)));//keyboardOffset >= 0 ? scrollViewOffsetHeight - keyboardOffset : scrollViewOffsetHeight + keyboardOffset; + + //console.log('Old container height', self.__originalContainerHeight, 'New container height', scrollViewOffsetHeight, 'Keyboard height', e.detail.keyboardHeight); + container.style.height = scrollViewOffsetHeight + "px"; + /* + if (ionic.Platform.isIOS()) { + // Force redraw to avoid disappearing content + var disp = container.style.display; + container.style.display = 'none'; + var trick = container.offsetHeight; + container.style.display = disp; + } + */ + container.classList.add('keyboard-up'); //update scroll view self.resize(); }); @@ -7218,6 +7387,8 @@ ionic.scroll = { self.isShrunkForKeyboard = true; } + lastKeyboardHeight = e.detail.keyboardHeight; + /* * _______ * |---A---| <- top of scroll view @@ -7234,26 +7405,42 @@ ionic.scroll = { if (e.detail.isElementUnderKeyboard) { ionic.requestAnimationFrame(function(){ + var pos = ionic.DomUtil.getOffsetTop(e.detail.target); + setTimeout(function() { + if (ionic.Platform.isIOS()) { + ionic.tap.cloneFocusedInput(container, self); + } + // Scroll the input into view, with a 100px buffer + self.scrollTo(0, pos - (rect.top + 100), true); + self.onScroll(); + }, 32); + + /* // update D if we shrunk if (self.isShrunkForKeyboard && !alreadyShrunk) { scrollBottomOffsetToTop = container.getBoundingClientRect().bottom; + console.log('Scroll bottom', scrollBottomOffsetToTop); } // middle of the scrollview, this is where we want to scroll to // (D - A) / 2 var scrollMidpointOffset = scrollViewOffsetHeight * 0.5; + console.log('Midpoint', scrollMidpointOffset); //console.log("container.offsetHeight: " + scrollViewOffsetHeight); // middle of the input we want to scroll into view // C var inputMidpoint = ((e.detail.elementBottom + e.detail.elementTop) / 2); + console.log('Input midpoint'); // distance from middle of input to the bottom of the scroll view // C - D C D var inputMidpointOffsetToScrollBottom = inputMidpoint - scrollBottomOffsetToTop; + console.log('Input midpoint offset', inputMidpointOffsetToScrollBottom); //C - D + (D - A)/2 C - D (D - A)/ 2 var scrollTop = inputMidpointOffsetToScrollBottom + scrollMidpointOffset; + console.log('Scroll top', scrollTop); if ( scrollTop > 0) { if (ionic.Platform.isIOS()) { @@ -7268,6 +7455,7 @@ ionic.scroll = { self.onScroll(); } } + */ }); } @@ -7281,16 +7469,46 @@ ionic.scroll = { if (self.isShrunkForKeyboard) { self.isShrunkForKeyboard = false; container.style.height = ""; + + /* + if (ionic.Platform.isIOS()) { + // Force redraw to avoid disappearing content + var disp = container.style.display; + container.style.display = 'none'; + var trick = container.offsetHeight; + container.style.display = disp; + } + */ + + self.__originalContainerHeight = container.getBoundingClientRect().height; + + if (ionic.Platform.isIOS()) { + ionic.requestAnimationFrame(function() { + container.classList.remove('keyboard-up'); + }); + } + } self.resize(); }; + self.handleTouchMove = function(e) { + if(self.__frozenShut) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + }; + container.addEventListener('scroll', self.onScroll); //Broadcasted when keyboard is shown on some platforms. //See js/utils/keyboard.js container.addEventListener('scrollChildIntoView', self.scrollChildIntoView); + container.addEventListener(ionic.EVENTS.touchstart, self.handleTouchMove); + container.addEventListener(ionic.EVENTS.touchmove, self.handleTouchMove); + // Listen on document because container may not have had the last // keyboardActiveElement, for example after closing a modal with a focused // input and returning to a previously resized scroll view in an ion-content. @@ -7309,6 +7527,9 @@ ionic.scroll = { container.removeEventListener('scrollChildIntoView', self.scrollChildIntoView); container.removeEventListener('resetScrollView', self.resetScrollView); + container.removeEventListener(ionic.EVENTS.touchstart, self.handleTouchMove); + container.removeEventListener(ionic.EVENTS.touchmove, self.handleTouchMove); + ionic.tap.removeClonedInputs(container, self); delete self.__container; @@ -7325,7 +7546,6 @@ ionic.scroll = { })(ionic); - (function(ionic) { 'use strict'; @@ -8066,6 +8286,25 @@ ionic.views.Slider = ionic.views.View.inherit({ initialize: function (options) { var slider = this; + var touchStartEvent, touchMoveEvent, touchEndEvent; + if (window.navigator.pointerEnabled) { + touchStartEvent = 'pointerdown'; + touchMoveEvent = 'pointermove'; + touchEndEvent = 'pointerup'; + } else if (window.navigator.msPointerEnabled) { + touchStartEvent = 'MSPointerDown'; + touchMoveEvent = 'MSPointerMove'; + touchEndEvent = 'MSPointerUp'; + } else { + touchStartEvent = 'touchstart'; + touchMoveEvent = 'touchmove'; + touchEndEvent = 'touchend'; + } + + var mouseStartEvent = 'mousedown'; + var mouseMoveEvent = 'mousemove'; + var mouseEndEvent = 'mouseup'; + // utilities var noop = function() {}; // simple no operation function var offloadFn = function(fn) { setTimeout(fn || noop, 0); }; // offload a functions execution @@ -8073,7 +8312,6 @@ ionic.views.Slider = ionic.views.View.inherit({ // check browser capabilities var browser = { addEventListener: !!window.addEventListener, - touch: ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch, transitions: (function(temp) { var props = ['transitionProperty', 'WebkitTransition', 'MozTransition', 'OTransition', 'msTransition']; for ( var i in props ) if (temp.style[ props[i] ] !== undefined) return true; @@ -8177,6 +8415,11 @@ ionic.views.Slider = ionic.views.View.inherit({ // do nothing if already on requested slide if (index == to) return; + if (!slides) { + index = to; + return; + } + if (browser.transitions) { var direction = Math.abs(index - to) / (index - to); // 1: backward, -1: forward @@ -8304,7 +8547,7 @@ ionic.views.Slider = ionic.views.View.inherit({ var events = { handleEvent: function(event) { - if(event.type == 'mousedown' || event.type == 'mouseup' || event.type == 'mousemove') { + if(!event.touches && event.pageX && event.pageY) { event.touches = [{ pageX: event.pageX, pageY: event.pageY @@ -8312,12 +8555,12 @@ ionic.views.Slider = ionic.views.View.inherit({ } switch (event.type) { - case 'mousedown': this.start(event); break; - case 'touchstart': this.start(event); break; - case 'touchmove': this.touchmove(event); break; - case 'mousemove': this.touchmove(event); break; - case 'touchend': offloadFn(this.end(event)); break; - case 'mouseup': offloadFn(this.end(event)); break; + case touchStartEvent: this.start(event); break; + case mouseStartEvent: this.start(event); break; + case touchMoveEvent: this.touchmove(event); break; + case mouseMoveEvent: this.touchmove(event); break; + case touchEndEvent: offloadFn(this.end(event)); break; + case mouseEndEvent: offloadFn(this.end(event)); break; case 'webkitTransitionEnd': case 'msTransitionEnd': case 'oTransitionEnd': @@ -8331,6 +8574,11 @@ ionic.views.Slider = ionic.views.View.inherit({ }, start: function(event) { + // prevent to start if there is no valid event + if (!event.touches) { + return; + } + var touches = event.touches[0]; // measure start values @@ -8352,20 +8600,22 @@ ionic.views.Slider = ionic.views.View.inherit({ delta = {}; // attach touchmove and touchend listeners - if(browser.touch) { - element.addEventListener('touchmove', this, false); - element.addEventListener('touchend', this, false); - } else { - element.addEventListener('mousemove', this, false); - element.addEventListener('mouseup', this, false); - document.addEventListener('mouseup', this, false); - } + element.addEventListener(touchMoveEvent, this, false); + element.addEventListener(mouseMoveEvent, this, false); + + element.addEventListener(touchEndEvent, this, false); + element.addEventListener(mouseEndEvent, this, false); + + document.addEventListener(touchEndEvent, this, false); + document.addEventListener(mouseEndEvent, this, false); }, touchmove: function(event) { + // ensure there is a valid event // ensure swiping with one touch and not pinching // ensure sliding is enabled - if (event.touches.length > 1 || + if (!event.touches || + event.touches.length > 1 || event.scale && event.scale !== 1 || slider.slideIsDisabled) { return; @@ -8403,15 +8653,24 @@ ionic.views.Slider = ionic.views.View.inherit({ translate(circle(index + 1), delta.x + slidePos[circle(index + 1)], 0); } else { - - delta.x = - delta.x / - ( (!index && delta.x > 0 || // if first slide and sliding left - index == slides.length - 1 && // or if last slide and sliding right - delta.x < 0 // and if sliding at all - ) ? - ( Math.abs(delta.x) / width + 1 ) // determine resistance level - : 1 ); // no resistance if false + // If the slider bounces, do the bounce! + if(options.bouncing) { + delta.x = + delta.x / + ( (!index && delta.x > 0 || // if first slide and sliding left + index == slides.length - 1 && // or if last slide and sliding right + delta.x < 0 // and if sliding at all + ) ? + ( Math.abs(delta.x) / width + 1 ) // determine resistance level + : 1 ); // no resistance if false + } else { + if(width * index - delta.x < 0) { //We are trying scroll past left boundary + delta.x = Math.min(delta.x, width * index); //Set delta.x so we don't go past left screen + } + if(Math.abs(delta.x) > width * (slides.length - index - 1)){ //We are trying to scroll past right bondary + delta.x = Math.max( -width * (slides.length - index - 1), delta.x); //Set delta.x so we don't go past right screen + } + } // translate 1:1 translate(index - 1, delta.x + slidePos[index - 1], 0); @@ -8501,14 +8760,14 @@ ionic.views.Slider = ionic.views.View.inherit({ } // kill touchmove and touchend event listeners until touchstart called again - if(browser.touch) { - element.removeEventListener('touchmove', events, false); - element.removeEventListener('touchend', events, false); - } else { - element.removeEventListener('mousemove', events, false); - element.removeEventListener('mouseup', events, false); - document.removeEventListener('mouseup', events, false); - } + element.removeEventListener(touchMoveEvent, events, false); + element.removeEventListener(mouseMoveEvent, events, false); + + element.removeEventListener(touchEndEvent, events, false); + element.removeEventListener(mouseEndEvent, events, false); + + document.removeEventListener(touchEndEvent, events, false); + document.removeEventListener(mouseEndEvent, events, false); options.onDragEnd && options.onDragEnd(); }, @@ -8610,7 +8869,8 @@ ionic.views.Slider = ionic.views.View.inherit({ if (browser.addEventListener) { // remove current event listeners - element.removeEventListener('touchstart', events, false); + element.removeEventListener(touchStartEvent, events, false); + element.removeEventListener(mouseStartEvent, events, false); element.removeEventListener('webkitTransitionEnd', events, false); element.removeEventListener('msTransitionEnd', events, false); element.removeEventListener('oTransitionEnd', events, false); @@ -8638,11 +8898,8 @@ ionic.views.Slider = ionic.views.View.inherit({ if (browser.addEventListener) { // set touchstart event on element - if (browser.touch) { - element.addEventListener('touchstart', events, false); - } else { - element.addEventListener('mousedown', events, false); - } + element.addEventListener(touchStartEvent, events, false); + element.addEventListener(mouseStartEvent, events, false); if (browser.transitions) { element.addEventListener('webkitTransitionEnd', events, false); @@ -8667,6 +8924,4234 @@ ionic.views.Slider = ionic.views.View.inherit({ })(ionic); +/*eslint space-after-keywords: 0*/ + +/** + * Swiper 3.2.7 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/swiper/ + * + * Copyright 2015, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: December 7, 2015 + */ +(function () { + 'use strict'; + var $; + /*=========================== + Swiper + ===========================*/ + var Swiper = function (container, params, _scope, $compile) { + + if (!(this instanceof Swiper)) return new Swiper(container, params); + + var defaults = { + direction: 'horizontal', + touchEventsTarget: 'container', + initialSlide: 0, + speed: 300, + // autoplay + autoplay: false, + autoplayDisableOnInteraction: true, + // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView). + iOSEdgeSwipeDetection: false, + iOSEdgeSwipeThreshold: 20, + // Free mode + freeMode: false, + freeModeMomentum: true, + freeModeMomentumRatio: 1, + freeModeMomentumBounce: true, + freeModeMomentumBounceRatio: 1, + freeModeSticky: false, + freeModeMinimumVelocity: 0.02, + // Autoheight + autoHeight: false, + // Set wrapper width + setWrapperSize: false, + // Virtual Translate + virtualTranslate: false, + // Effects + effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' + coverflow: { + rotate: 50, + stretch: 0, + depth: 100, + modifier: 1, + slideShadows : true + }, + cube: { + slideShadows: true, + shadow: true, + shadowOffset: 20, + shadowScale: 0.94 + }, + fade: { + crossFade: false + }, + // Parallax + parallax: false, + // Scrollbar + scrollbar: null, + scrollbarHide: true, + scrollbarDraggable: false, + scrollbarSnapOnRelease: false, + // Keyboard Mousewheel + keyboardControl: false, + mousewheelControl: false, + mousewheelReleaseOnEdges: false, + mousewheelInvert: false, + mousewheelForceToAxis: false, + mousewheelSensitivity: 1, + // Hash Navigation + hashnav: false, + // Breakpoints + breakpoints: undefined, + // Slides grid + spaceBetween: 0, + slidesPerView: 1, + slidesPerColumn: 1, + slidesPerColumnFill: 'column', + slidesPerGroup: 1, + centeredSlides: false, + slidesOffsetBefore: 0, // in px + slidesOffsetAfter: 0, // in px + // Round length + roundLengths: false, + // Touches + touchRatio: 1, + touchAngle: 45, + simulateTouch: true, + shortSwipes: true, + longSwipes: true, + longSwipesRatio: 0.5, + longSwipesMs: 300, + followFinger: true, + onlyExternal: false, + threshold: 0, + touchMoveStopPropagation: true, + // Pagination + pagination: null, + paginationElement: 'span', + paginationClickable: false, + paginationHide: false, + paginationBulletRender: null, + // Resistance + resistance: true, + resistanceRatio: 0.85, + // Next/prev buttons + nextButton: null, + prevButton: null, + // Progress + watchSlidesProgress: false, + watchSlidesVisibility: false, + // Cursor + grabCursor: false, + // Clicks + preventClicks: true, + preventClicksPropagation: true, + slideToClickedSlide: false, + // Lazy Loading + lazyLoading: false, + lazyLoadingInPrevNext: false, + lazyLoadingOnTransitionStart: false, + // Images + preloadImages: true, + updateOnImagesReady: true, + // loop + loop: false, + loopAdditionalSlides: 0, + loopedSlides: null, + // Control + control: undefined, + controlInverse: false, + controlBy: 'slide', //or 'container' + // Swiping/no swiping + allowSwipeToPrev: true, + allowSwipeToNext: true, + swipeHandler: null, //'.swipe-handler', + noSwiping: true, + noSwipingClass: 'swiper-no-swiping', + // NS + slideClass: 'swiper-slide', + slideActiveClass: 'swiper-slide-active', + slideVisibleClass: 'swiper-slide-visible', + slideDuplicateClass: 'swiper-slide-duplicate', + slideNextClass: 'swiper-slide-next', + slidePrevClass: 'swiper-slide-prev', + wrapperClass: 'swiper-wrapper', + bulletClass: 'swiper-pagination-bullet', + bulletActiveClass: 'swiper-pagination-bullet-active', + buttonDisabledClass: 'swiper-button-disabled', + paginationHiddenClass: 'swiper-pagination-hidden', + // Observer + observer: false, + observeParents: false, + // Accessibility + a11y: false, + prevSlideMessage: 'Previous slide', + nextSlideMessage: 'Next slide', + firstSlideMessage: 'This is the first slide', + lastSlideMessage: 'This is the last slide', + paginationBulletMessage: 'Go to slide {{index}}', + // Callbacks + runCallbacksOnInit: true + /* + Callbacks: + onInit: function (swiper) + onDestroy: function (swiper) + onClick: function (swiper, e) + onTap: function (swiper, e) + onDoubleTap: function (swiper, e) + onSliderMove: function (swiper, e) + onSlideChangeStart: function (swiper) + onSlideChangeEnd: function (swiper) + onTransitionStart: function (swiper) + onTransitionEnd: function (swiper) + onImagesReady: function (swiper) + onProgress: function (swiper, progress) + onTouchStart: function (swiper, e) + onTouchMove: function (swiper, e) + onTouchMoveOpposite: function (swiper, e) + onTouchEnd: function (swiper, e) + onReachBeginning: function (swiper) + onReachEnd: function (swiper) + onSetTransition: function (swiper, duration) + onSetTranslate: function (swiper, translate) + onAutoplayStart: function (swiper) + onAutoplayStop: function (swiper), + onLazyImageLoad: function (swiper, slide, image) + onLazyImageReady: function (swiper, slide, image) + */ + + }; + var initialVirtualTranslate = params && params.virtualTranslate; + + params = params || {}; + var originalParams = {}; + for (var param in params) { + if (typeof params[param] === 'object' && !(params[param].nodeType || params[param] === window || params[param] === document || (typeof Dom7 !== 'undefined' && params[param] instanceof Dom7) || (typeof jQuery !== 'undefined' && params[param] instanceof jQuery))) { + originalParams[param] = {}; + for (var deepParam in params[param]) { + originalParams[param][deepParam] = params[param][deepParam]; + } + } + else { + originalParams[param] = params[param]; + } + } + for (var def in defaults) { + if (typeof params[def] === 'undefined') { + params[def] = defaults[def]; + } + else if (typeof params[def] === 'object') { + for (var deepDef in defaults[def]) { + if (typeof params[def][deepDef] === 'undefined') { + params[def][deepDef] = defaults[def][deepDef]; + } + } + } + } + + // Swiper + var s = this; + + // Params + s.params = params; + s.originalParams = originalParams; + + // Classname + s.classNames = []; + /*========================= + Dom Library and plugins + ===========================*/ + if (typeof $ !== 'undefined' && typeof Dom7 !== 'undefined'){ + $ = Dom7; + } + if (typeof $ === 'undefined') { + if (typeof Dom7 === 'undefined') { + $ = window.Dom7 || window.Zepto || window.jQuery; + } + else { + $ = Dom7; + } + if (!$) return; + } + // Export it to Swiper instance + s.$ = $; + + /*========================= + Breakpoints + ===========================*/ + s.currentBreakpoint = undefined; + s.getActiveBreakpoint = function () { + //Get breakpoint for window width + if (!s.params.breakpoints) return false; + var breakpoint = false; + var points = [], point; + for ( point in s.params.breakpoints ) { + if (s.params.breakpoints.hasOwnProperty(point)) { + points.push(point); + } + } + points.sort(function (a, b) { + return parseInt(a, 10) > parseInt(b, 10); + }); + for (var i = 0; i < points.length; i++) { + point = points[i]; + if (point >= window.innerWidth && !breakpoint) { + breakpoint = point; + } + } + return breakpoint || 'max'; + }; + s.setBreakpoint = function () { + //Set breakpoint for window width and update parameters + var breakpoint = s.getActiveBreakpoint(); + if (breakpoint && s.currentBreakpoint !== breakpoint) { + var breakPointsParams = breakpoint in s.params.breakpoints ? s.params.breakpoints[breakpoint] : s.originalParams; + for ( var param in breakPointsParams ) { + s.params[param] = breakPointsParams[param]; + } + s.currentBreakpoint = breakpoint; + } + }; + // Set breakpoint on load + if (s.params.breakpoints) { + s.setBreakpoint(); + } + + /*========================= + Preparation - Define Container, Wrapper and Pagination + ===========================*/ + s.container = $(container); + if (s.container.length === 0) return; + if (s.container.length > 1) { + s.container.each(function () { + new Swiper(this, params); + }); + return; + } + + // Save instance in container HTML Element and in data + s.container[0].swiper = s; + s.container.data('swiper', s); + + s.classNames.push('swiper-container-' + s.params.direction); + + if (s.params.freeMode) { + s.classNames.push('swiper-container-free-mode'); + } + if (!s.support.flexbox) { + s.classNames.push('swiper-container-no-flexbox'); + s.params.slidesPerColumn = 1; + } + if (s.params.autoHeight) { + s.classNames.push('swiper-container-autoheight'); + } + // Enable slides progress when required + if (s.params.parallax || s.params.watchSlidesVisibility) { + s.params.watchSlidesProgress = true; + } + // Coverflow / 3D + if (['cube', 'coverflow'].indexOf(s.params.effect) >= 0) { + if (s.support.transforms3d) { + s.params.watchSlidesProgress = true; + s.classNames.push('swiper-container-3d'); + } + else { + s.params.effect = 'slide'; + } + } + if (s.params.effect !== 'slide') { + s.classNames.push('swiper-container-' + s.params.effect); + } + if (s.params.effect === 'cube') { + s.params.resistanceRatio = 0; + s.params.slidesPerView = 1; + s.params.slidesPerColumn = 1; + s.params.slidesPerGroup = 1; + s.params.centeredSlides = false; + s.params.spaceBetween = 0; + s.params.virtualTranslate = true; + s.params.setWrapperSize = false; + } + if (s.params.effect === 'fade') { + s.params.slidesPerView = 1; + s.params.slidesPerColumn = 1; + s.params.slidesPerGroup = 1; + s.params.watchSlidesProgress = true; + s.params.spaceBetween = 0; + if (typeof initialVirtualTranslate === 'undefined') { + s.params.virtualTranslate = true; + } + } + + // Grab Cursor + if (s.params.grabCursor && s.support.touch) { + s.params.grabCursor = false; + } + + // Wrapper + s.wrapper = s.container.children('.' + s.params.wrapperClass); + + // Pagination + if (s.params.pagination) { + s.paginationContainer = $(s.params.pagination); + if (s.params.paginationClickable) { + s.paginationContainer.addClass('swiper-pagination-clickable'); + } + } + + // Is Horizontal + function isH() { + return s.params.direction === 'horizontal'; + } + + // RTL + s.rtl = isH() && (s.container[0].dir.toLowerCase() === 'rtl' || s.container.css('direction') === 'rtl'); + if (s.rtl) { + s.classNames.push('swiper-container-rtl'); + } + + // Wrong RTL support + if (s.rtl) { + s.wrongRTL = s.wrapper.css('display') === '-webkit-box'; + } + + // Columns + if (s.params.slidesPerColumn > 1) { + s.classNames.push('swiper-container-multirow'); + } + + // Check for Android + if (s.device.android) { + s.classNames.push('swiper-container-android'); + } + + // Add classes + s.container.addClass(s.classNames.join(' ')); + + // Translate + s.translate = 0; + + // Progress + s.progress = 0; + + // Velocity + s.velocity = 0; + + /*========================= + Locks, unlocks + ===========================*/ + s.lockSwipeToNext = function () { + s.params.allowSwipeToNext = false; + }; + s.lockSwipeToPrev = function () { + s.params.allowSwipeToPrev = false; + }; + s.lockSwipes = function () { + s.params.allowSwipeToNext = s.params.allowSwipeToPrev = false; + }; + s.unlockSwipeToNext = function () { + s.params.allowSwipeToNext = true; + }; + s.unlockSwipeToPrev = function () { + s.params.allowSwipeToPrev = true; + }; + s.unlockSwipes = function () { + s.params.allowSwipeToNext = s.params.allowSwipeToPrev = true; + }; + + /*========================= + Round helper + ===========================*/ + function round(a) { + return Math.floor(a); + } + /*========================= + Set grab cursor + ===========================*/ + if (s.params.grabCursor) { + s.container[0].style.cursor = 'move'; + s.container[0].style.cursor = '-webkit-grab'; + s.container[0].style.cursor = '-moz-grab'; + s.container[0].style.cursor = 'grab'; + } + /*========================= + Update on Images Ready + ===========================*/ + s.imagesToLoad = []; + s.imagesLoaded = 0; + + s.loadImage = function (imgElement, src, srcset, checkForComplete, callback) { + var image; + function onReady () { + if (callback) callback(); + } + if (!imgElement.complete || !checkForComplete) { + if (src) { + image = new window.Image(); + image.onload = onReady; + image.onerror = onReady; + if (srcset) { + image.srcset = srcset; + } + if (src) { + image.src = src; + } + } else { + onReady(); + } + + } else {//image already loaded... + onReady(); + } + }; + s.preloadImages = function () { + s.imagesToLoad = s.container.find('img'); + function _onReady() { + if (typeof s === 'undefined' || s === null) return; + if (s.imagesLoaded !== undefined) s.imagesLoaded++; + if (s.imagesLoaded === s.imagesToLoad.length) { + if (s.params.updateOnImagesReady) s.update(); + s.emit('onImagesReady', s); + } + } + for (var i = 0; i < s.imagesToLoad.length; i++) { + s.loadImage(s.imagesToLoad[i], (s.imagesToLoad[i].currentSrc || s.imagesToLoad[i].getAttribute('src')), (s.imagesToLoad[i].srcset || s.imagesToLoad[i].getAttribute('srcset')), true, _onReady); + } + }; + + /*========================= + Autoplay + ===========================*/ + s.autoplayTimeoutId = undefined; + s.autoplaying = false; + s.autoplayPaused = false; + function autoplay() { + s.autoplayTimeoutId = setTimeout(function () { + if (s.params.loop) { + s.fixLoop(); + s._slideNext(); + } + else { + if (!s.isEnd) { + s._slideNext(); + } + else { + if (!params.autoplayStopOnLast) { + s._slideTo(0); + } + else { + s.stopAutoplay(); + } + } + } + }, s.params.autoplay); + } + s.startAutoplay = function () { + if (typeof s.autoplayTimeoutId !== 'undefined') return false; + if (!s.params.autoplay) return false; + if (s.autoplaying) return false; + s.autoplaying = true; + s.emit('onAutoplayStart', s); + autoplay(); + }; + s.stopAutoplay = function (internal) { + if (!s.autoplayTimeoutId) return; + if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId); + s.autoplaying = false; + s.autoplayTimeoutId = undefined; + s.emit('onAutoplayStop', s); + }; + s.pauseAutoplay = function (speed) { + if (s.autoplayPaused) return; + if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId); + s.autoplayPaused = true; + if (speed === 0) { + s.autoplayPaused = false; + autoplay(); + } + else { + s.wrapper.transitionEnd(function () { + if (!s) return; + s.autoplayPaused = false; + if (!s.autoplaying) { + s.stopAutoplay(); + } + else { + autoplay(); + } + }); + } + }; + /*========================= + Min/Max Translate + ===========================*/ + s.minTranslate = function () { + return (-s.snapGrid[0]); + }; + s.maxTranslate = function () { + return (-s.snapGrid[s.snapGrid.length - 1]); + }; + /*========================= + Slider/slides sizes + ===========================*/ + s.updateAutoHeight = function () { + // Update Height + var newHeight = s.slides.eq(s.activeIndex)[0].offsetHeight; + if (newHeight) s.wrapper.css('height', s.slides.eq(s.activeIndex)[0].offsetHeight + 'px'); + }; + s.updateContainerSize = function () { + var width, height; + if (typeof s.params.width !== 'undefined') { + width = s.params.width; + } + else { + width = s.container[0].clientWidth; + } + if (typeof s.params.height !== 'undefined') { + height = s.params.height; + } + else { + height = s.container[0].clientHeight; + } + if (width === 0 && isH() || height === 0 && !isH()) { + return; + } + + //Subtract paddings + width = width - parseInt(s.container.css('padding-left'), 10) - parseInt(s.container.css('padding-right'), 10); + height = height - parseInt(s.container.css('padding-top'), 10) - parseInt(s.container.css('padding-bottom'), 10); + + // Store values + s.width = width; + s.height = height; + s.size = isH() ? s.width : s.height; + }; + + s.updateSlidesSize = function () { + s.slides = s.wrapper.children('.' + s.params.slideClass); + s.snapGrid = []; + s.slidesGrid = []; + s.slidesSizesGrid = []; + + var spaceBetween = s.params.spaceBetween, + slidePosition = -s.params.slidesOffsetBefore, + i, + prevSlideSize = 0, + index = 0; + if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) { + spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * s.size; + } + + s.virtualSize = -spaceBetween; + // reset margins + if (s.rtl) s.slides.css({marginLeft: '', marginTop: ''}); + else s.slides.css({marginRight: '', marginBottom: ''}); + + var slidesNumberEvenToRows; + if (s.params.slidesPerColumn > 1) { + if (Math.floor(s.slides.length / s.params.slidesPerColumn) === s.slides.length / s.params.slidesPerColumn) { + slidesNumberEvenToRows = s.slides.length; + } + else { + slidesNumberEvenToRows = Math.ceil(s.slides.length / s.params.slidesPerColumn) * s.params.slidesPerColumn; + } + if (s.params.slidesPerView !== 'auto' && s.params.slidesPerColumnFill === 'row') { + slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, s.params.slidesPerView * s.params.slidesPerColumn); + } + } + + // Calc slides + var slideSize; + var slidesPerColumn = s.params.slidesPerColumn; + var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn; + var numFullColumns = slidesPerRow - (s.params.slidesPerColumn * slidesPerRow - s.slides.length); + for (i = 0; i < s.slides.length; i++) { + slideSize = 0; + var slide = s.slides.eq(i); + if (s.params.slidesPerColumn > 1) { + // Set slides order + var newSlideOrderIndex; + var column, row; + if (s.params.slidesPerColumnFill === 'column') { + column = Math.floor(i / slidesPerColumn); + row = i - column * slidesPerColumn; + if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn-1)) { + if (++row >= slidesPerColumn) { + row = 0; + column++; + } + } + newSlideOrderIndex = column + row * slidesNumberEvenToRows / slidesPerColumn; + slide + .css({ + '-webkit-box-ordinal-group': newSlideOrderIndex, + '-moz-box-ordinal-group': newSlideOrderIndex, + '-ms-flex-order': newSlideOrderIndex, + '-webkit-order': newSlideOrderIndex, + 'order': newSlideOrderIndex + }); + } + else { + row = Math.floor(i / slidesPerRow); + column = i - row * slidesPerRow; + } + slide + .css({ + 'margin-top': (row !== 0 && s.params.spaceBetween) && (s.params.spaceBetween + 'px') + }) + .attr('data-swiper-column', column) + .attr('data-swiper-row', row); + + } + if (slide.css('display') === 'none') continue; + if (s.params.slidesPerView === 'auto') { + slideSize = isH() ? slide.outerWidth(true) : slide.outerHeight(true); + if (s.params.roundLengths) slideSize = round(slideSize); + } + else { + slideSize = (s.size - (s.params.slidesPerView - 1) * spaceBetween) / s.params.slidesPerView; + if (s.params.roundLengths) slideSize = round(slideSize); + + if (isH()) { + s.slides[i].style.width = slideSize + 'px'; + } + else { + s.slides[i].style.height = slideSize + 'px'; + } + } + s.slides[i].swiperSlideSize = slideSize; + s.slidesSizesGrid.push(slideSize); + + + if (s.params.centeredSlides) { + slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween; + if (i === 0) slidePosition = slidePosition - s.size / 2 - spaceBetween; + if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0; + if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition); + s.slidesGrid.push(slidePosition); + } + else { + if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition); + s.slidesGrid.push(slidePosition); + slidePosition = slidePosition + slideSize + spaceBetween; + } + + s.virtualSize += slideSize + spaceBetween; + + prevSlideSize = slideSize; + + index ++; + } + s.virtualSize = Math.max(s.virtualSize, s.size) + s.params.slidesOffsetAfter; + var newSlidesGrid; + + if ( + s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) { + s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); + } + if (!s.support.flexbox || s.params.setWrapperSize) { + if (isH()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); + else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'}); + } + + if (s.params.slidesPerColumn > 1) { + s.virtualSize = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows; + s.virtualSize = Math.ceil(s.virtualSize / s.params.slidesPerColumn) - s.params.spaceBetween; + s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'}); + if (s.params.centeredSlides) { + newSlidesGrid = []; + for (i = 0; i < s.snapGrid.length; i++) { + if (s.snapGrid[i] < s.virtualSize + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]); + } + s.snapGrid = newSlidesGrid; + } + } + + // Remove last grid elements depending on width + if (!s.params.centeredSlides) { + newSlidesGrid = []; + for (i = 0; i < s.snapGrid.length; i++) { + if (s.snapGrid[i] <= s.virtualSize - s.size) { + newSlidesGrid.push(s.snapGrid[i]); + } + } + s.snapGrid = newSlidesGrid; + if (Math.floor(s.virtualSize - s.size) > Math.floor(s.snapGrid[s.snapGrid.length - 1])) { + s.snapGrid.push(s.virtualSize - s.size); + } + } + if (s.snapGrid.length === 0) s.snapGrid = [0]; + + if (s.params.spaceBetween !== 0) { + if (isH()) { + if (s.rtl) s.slides.css({marginLeft: spaceBetween + 'px'}); + else s.slides.css({marginRight: spaceBetween + 'px'}); + } + else s.slides.css({marginBottom: spaceBetween + 'px'}); + } + if (s.params.watchSlidesProgress) { + s.updateSlidesOffset(); + } + }; + s.updateSlidesOffset = function () { + for (var i = 0; i < s.slides.length; i++) { + s.slides[i].swiperSlideOffset = isH() ? s.slides[i].offsetLeft : s.slides[i].offsetTop; + } + }; + + /*========================= + Slider/slides progress + ===========================*/ + s.updateSlidesProgress = function (translate) { + if (typeof translate === 'undefined') { + translate = s.translate || 0; + } + if (s.slides.length === 0) return; + if (typeof s.slides[0].swiperSlideOffset === 'undefined') s.updateSlidesOffset(); + + var offsetCenter = -translate; + if (s.rtl) offsetCenter = translate; + + // Visible Slides + s.slides.removeClass(s.params.slideVisibleClass); + for (var i = 0; i < s.slides.length; i++) { + var slide = s.slides[i]; + var slideProgress = (offsetCenter - slide.swiperSlideOffset) / (slide.swiperSlideSize + s.params.spaceBetween); + if (s.params.watchSlidesVisibility) { + var slideBefore = -(offsetCenter - slide.swiperSlideOffset); + var slideAfter = slideBefore + s.slidesSizesGrid[i]; + var isVisible = + (slideBefore >= 0 && slideBefore < s.size) || + (slideAfter > 0 && slideAfter <= s.size) || + (slideBefore <= 0 && slideAfter >= s.size); + if (isVisible) { + s.slides.eq(i).addClass(s.params.slideVisibleClass); + } + } + slide.progress = s.rtl ? -slideProgress : slideProgress; + } + }; + s.updateProgress = function (translate) { + if (typeof translate === 'undefined') { + translate = s.translate || 0; + } + var translatesDiff = s.maxTranslate() - s.minTranslate(); + var wasBeginning = s.isBeginning; + var wasEnd = s.isEnd; + if (translatesDiff === 0) { + s.progress = 0; + s.isBeginning = s.isEnd = true; + } + else { + s.progress = (translate - s.minTranslate()) / (translatesDiff); + s.isBeginning = s.progress <= 0; + s.isEnd = s.progress >= 1; + } + if (s.isBeginning && !wasBeginning) s.emit('onReachBeginning', s); + if (s.isEnd && !wasEnd) s.emit('onReachEnd', s); + + if (s.params.watchSlidesProgress) s.updateSlidesProgress(translate); + s.emit('onProgress', s, s.progress); + }; + s.updateActiveIndex = function () { + var translate = s.rtl ? s.translate : -s.translate; + var newActiveIndex, i, snapIndex; + for (i = 0; i < s.slidesGrid.length; i ++) { + if (typeof s.slidesGrid[i + 1] !== 'undefined') { + if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1] - (s.slidesGrid[i + 1] - s.slidesGrid[i]) / 2) { + newActiveIndex = i; + } + else if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1]) { + newActiveIndex = i + 1; + } + } + else { + if (translate >= s.slidesGrid[i]) { + newActiveIndex = i; + } + } + } + // Normalize slideIndex + if (newActiveIndex < 0 || typeof newActiveIndex === 'undefined') newActiveIndex = 0; + // for (i = 0; i < s.slidesGrid.length; i++) { + // if (- translate >= s.slidesGrid[i]) { + // newActiveIndex = i; + // } + // } + snapIndex = Math.floor(newActiveIndex / s.params.slidesPerGroup); + if (snapIndex >= s.snapGrid.length) snapIndex = s.snapGrid.length - 1; + + if (newActiveIndex === s.activeIndex) { + return; + } + s.snapIndex = snapIndex; + s.previousIndex = s.activeIndex; + s.activeIndex = newActiveIndex; + s.updateClasses(); + }; + + /*========================= + Classes + ===========================*/ + s.updateClasses = function () { + s.slides.removeClass(s.params.slideActiveClass + ' ' + s.params.slideNextClass + ' ' + s.params.slidePrevClass); + var activeSlide = s.slides.eq(s.activeIndex); + // Active classes + activeSlide.addClass(s.params.slideActiveClass); + activeSlide.next('.' + s.params.slideClass).addClass(s.params.slideNextClass); + activeSlide.prev('.' + s.params.slideClass).addClass(s.params.slidePrevClass); + + // Pagination + if (s.bullets && s.bullets.length > 0) { + s.bullets.removeClass(s.params.bulletActiveClass); + var bulletIndex; + if (s.params.loop) { + bulletIndex = Math.ceil(s.activeIndex - s.loopedSlides)/s.params.slidesPerGroup; + if (bulletIndex > s.slides.length - 1 - s.loopedSlides * 2) { + bulletIndex = bulletIndex - (s.slides.length - s.loopedSlides * 2); + } + if (bulletIndex > s.bullets.length - 1) bulletIndex = bulletIndex - s.bullets.length; + } + else { + if (typeof s.snapIndex !== 'undefined') { + bulletIndex = s.snapIndex; + } + else { + bulletIndex = s.activeIndex || 0; + } + } + if (s.paginationContainer.length > 1) { + s.bullets.each(function () { + if ($(this).index() === bulletIndex) $(this).addClass(s.params.bulletActiveClass); + }); + } + else { + s.bullets.eq(bulletIndex).addClass(s.params.bulletActiveClass); + } + } + + // Next/active buttons + if (!s.params.loop) { + if (s.params.prevButton) { + if (s.isBeginning) { + $(s.params.prevButton).addClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.disable($(s.params.prevButton)); + } + else { + $(s.params.prevButton).removeClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.enable($(s.params.prevButton)); + } + } + if (s.params.nextButton) { + if (s.isEnd) { + $(s.params.nextButton).addClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.disable($(s.params.nextButton)); + } + else { + $(s.params.nextButton).removeClass(s.params.buttonDisabledClass); + if (s.params.a11y && s.a11y) s.a11y.enable($(s.params.nextButton)); + } + } + } + }; + + /*========================= + Pagination + ===========================*/ + s.updatePagination = function () { + if (!s.params.pagination) return; + if (s.paginationContainer && s.paginationContainer.length > 0) { + var bulletsHTML = ''; + var numberOfBullets = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length; + for (var i = 0; i < numberOfBullets; i++) { + if (s.params.paginationBulletRender) { + bulletsHTML += s.params.paginationBulletRender(i, s.params.bulletClass); + } + else { + bulletsHTML += '<' + s.params.paginationElement+' class="' + s.params.bulletClass + '"></' + s.params.paginationElement + '>'; + } + } + s.paginationContainer.html(bulletsHTML); + s.bullets = s.paginationContainer.find('.' + s.params.bulletClass); + if (s.params.paginationClickable && s.params.a11y && s.a11y) { + s.a11y.initPagination(); + } + } + }; + /*========================= + Common update method + ===========================*/ + s.update = function (updateTranslate) { + s.updateContainerSize(); + s.updateSlidesSize(); + s.updateProgress(); + s.updatePagination(); + s.updateClasses(); + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.set(); + } + function forceSetTranslate() { + newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate()); + s.setWrapperTranslate(newTranslate); + s.updateActiveIndex(); + s.updateClasses(); + } + if (updateTranslate) { + var translated, newTranslate; + if (s.controller && s.controller.spline) { + s.controller.spline = undefined; + } + if (s.params.freeMode) { + forceSetTranslate(); + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + } + else { + if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) { + translated = s.slideTo(s.slides.length - 1, 0, false, true); + } + else { + translated = s.slideTo(s.activeIndex, 0, false, true); + } + if (!translated) { + forceSetTranslate(); + } + } + } + else if (s.params.autoHeight) { + s.updateAutoHeight(); + } + }; + + /*========================= + Resize Handler + ===========================*/ + s.onResize = function (forceUpdatePagination) { + //Breakpoints + if (s.params.breakpoints) { + s.setBreakpoint(); + } + + // Disable locks on resize + var allowSwipeToPrev = s.params.allowSwipeToPrev; + var allowSwipeToNext = s.params.allowSwipeToNext; + s.params.allowSwipeToPrev = s.params.allowSwipeToNext = true; + + s.updateContainerSize(); + s.updateSlidesSize(); + if (s.params.slidesPerView === 'auto' || s.params.freeMode || forceUpdatePagination) s.updatePagination(); + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.set(); + } + if (s.controller && s.controller.spline) { + s.controller.spline = undefined; + } + if (s.params.freeMode) { + var newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate()); + s.setWrapperTranslate(newTranslate); + s.updateActiveIndex(); + s.updateClasses(); + + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + } + else { + s.updateClasses(); + if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) { + s.slideTo(s.slides.length - 1, 0, false, true); + } + else { + s.slideTo(s.activeIndex, 0, false, true); + } + } + // Return locks after resize + s.params.allowSwipeToPrev = allowSwipeToPrev; + s.params.allowSwipeToNext = allowSwipeToNext; + }; + + /*========================= + Events + ===========================*/ + + //Define Touch Events + var desktopEvents = ['mousedown', 'mousemove', 'mouseup']; + if (window.navigator.pointerEnabled) desktopEvents = ['pointerdown', 'pointermove', 'pointerup']; + else if (window.navigator.msPointerEnabled) desktopEvents = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp']; + s.touchEvents = { + start : s.support.touch || !s.params.simulateTouch ? 'touchstart' : desktopEvents[0], + move : s.support.touch || !s.params.simulateTouch ? 'touchmove' : desktopEvents[1], + end : s.support.touch || !s.params.simulateTouch ? 'touchend' : desktopEvents[2] + }; + + + // WP8 Touch Events Fix + if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) { + (s.params.touchEventsTarget === 'container' ? s.container : s.wrapper).addClass('swiper-wp8-' + s.params.direction); + } + + // Attach/detach events + s.initEvents = function (detach) { + var actionDom = detach ? 'off' : 'on'; + var action = detach ? 'removeEventListener' : 'addEventListener'; + var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container[0] : s.wrapper[0]; + var target = s.support.touch ? touchEventsTarget : document; + + var moveCapture = s.params.nested ? true : false; + + //Touch Events + if (s.browser.ie) { + touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false); + target[action](s.touchEvents.move, s.onTouchMove, moveCapture); + target[action](s.touchEvents.end, s.onTouchEnd, false); + } + else { + if (s.support.touch) { + touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false); + touchEventsTarget[action](s.touchEvents.move, s.onTouchMove, moveCapture); + touchEventsTarget[action](s.touchEvents.end, s.onTouchEnd, false); + } + if (params.simulateTouch && !s.device.ios && !s.device.android) { + touchEventsTarget[action]('mousedown', s.onTouchStart, false); + document[action]('mousemove', s.onTouchMove, moveCapture); + document[action]('mouseup', s.onTouchEnd, false); + } + } + window[action]('resize', s.onResize); + + // Next, Prev, Index + if (s.params.nextButton) { + $(s.params.nextButton)[actionDom]('click', s.onClickNext); + if (s.params.a11y && s.a11y) $(s.params.nextButton)[actionDom]('keydown', s.a11y.onEnterKey); + } + if (s.params.prevButton) { + $(s.params.prevButton)[actionDom]('click', s.onClickPrev); + if (s.params.a11y && s.a11y) $(s.params.prevButton)[actionDom]('keydown', s.a11y.onEnterKey); + } + if (s.params.pagination && s.params.paginationClickable) { + $(s.paginationContainer)[actionDom]('click', '.' + s.params.bulletClass, s.onClickIndex); + if (s.params.a11y && s.a11y) $(s.paginationContainer)[actionDom]('keydown', '.' + s.params.bulletClass, s.a11y.onEnterKey); + } + + // Prevent Links Clicks + if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[action]('click', s.preventClicks, true); + }; + s.attachEvents = function (detach) { + s.initEvents(); + }; + s.detachEvents = function () { + s.initEvents(true); + }; + + /*========================= + Handle Clicks + ===========================*/ + // Prevent Clicks + s.allowClick = true; + s.preventClicks = function (e) { + if (!s.allowClick) { + if (s.params.preventClicks) e.preventDefault(); + if (s.params.preventClicksPropagation && s.animating) { + e.stopPropagation(); + e.stopImmediatePropagation(); + } + } + }; + // Clicks + s.onClickNext = function (e) { + e.preventDefault(); + if (s.isEnd && !s.params.loop) return; + s.slideNext(); + }; + s.onClickPrev = function (e) { + e.preventDefault(); + if (s.isBeginning && !s.params.loop) return; + s.slidePrev(); + }; + s.onClickIndex = function (e) { + e.preventDefault(); + var index = $(this).index() * s.params.slidesPerGroup; + if (s.params.loop) index = index + s.loopedSlides; + s.slideTo(index); + }; + + /*========================= + Handle Touches + ===========================*/ + function findElementInEvent(e, selector) { + var el = $(e.target); + if (!el.is(selector)) { + if (typeof selector === 'string') { + el = el.parents(selector); + } + else if (selector.nodeType) { + var found; + el.parents().each(function (index, _el) { + if (_el === selector) found = selector; + }); + if (!found) return undefined; + else return selector; + } + } + if (el.length === 0) { + return undefined; + } + return el[0]; + } + s.updateClickedSlide = function (e) { + var slide = findElementInEvent(e, '.' + s.params.slideClass); + var slideFound = false; + if (slide) { + for (var i = 0; i < s.slides.length; i++) { + if (s.slides[i] === slide) slideFound = true; + } + } + + if (slide && slideFound) { + s.clickedSlide = slide; + s.clickedIndex = $(slide).index(); + } + else { + s.clickedSlide = undefined; + s.clickedIndex = undefined; + return; + } + if (s.params.slideToClickedSlide && s.clickedIndex !== undefined && s.clickedIndex !== s.activeIndex) { + var slideToIndex = s.clickedIndex, + realIndex, + duplicatedSlides; + if (s.params.loop) { + if (s.animating) return; + realIndex = $(s.clickedSlide).attr('data-swiper-slide-index'); + if (s.params.centeredSlides) { + if ((slideToIndex < s.loopedSlides - s.params.slidesPerView/2) || (slideToIndex > s.slides.length - s.loopedSlides + s.params.slidesPerView/2)) { + s.fixLoop(); + slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index(); + setTimeout(function () { + s.slideTo(slideToIndex); + }, 0); + } + else { + s.slideTo(slideToIndex); + } + } + else { + if (slideToIndex > s.slides.length - s.params.slidesPerView) { + s.fixLoop(); + slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.swiper-slide-duplicate)').eq(0).index(); + setTimeout(function () { + s.slideTo(slideToIndex); + }, 0); + } + else { + s.slideTo(slideToIndex); + } + } + } + else { + s.slideTo(slideToIndex); + } + } + }; + + var isTouched, + isMoved, + allowTouchCallbacks, + touchStartTime, + isScrolling, + currentTranslate, + startTranslate, + allowThresholdMove, + // Form elements to match + formElements = 'input, select, textarea, button', + // Last click time + lastClickTime = Date.now(), clickTimeout, + //Velocities + velocities = [], + allowMomentumBounce; + + // Animating Flag + s.animating = false; + + // Touches information + s.touches = { + startX: 0, + startY: 0, + currentX: 0, + currentY: 0, + diff: 0 + }; + + // Touch handlers + var isTouchEvent, startMoving; + s.onTouchStart = function (e) { + if (e.originalEvent) e = e.originalEvent; + isTouchEvent = e.type === 'touchstart'; + if (!isTouchEvent && 'which' in e && e.which === 3) return; + if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) { + s.allowClick = true; + return; + } + if (s.params.swipeHandler) { + if (!findElementInEvent(e, s.params.swipeHandler)) return; + } + + var startX = s.touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; + var startY = s.touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY; + + // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore + if(s.device.ios && s.params.iOSEdgeSwipeDetection && startX <= s.params.iOSEdgeSwipeThreshold) { + return; + } + + isTouched = true; + isMoved = false; + allowTouchCallbacks = true; + isScrolling = undefined; + startMoving = undefined; + s.touches.startX = startX; + s.touches.startY = startY; + touchStartTime = Date.now(); + s.allowClick = true; + s.updateContainerSize(); + s.swipeDirection = undefined; + if (s.params.threshold > 0) allowThresholdMove = false; + if (e.type !== 'touchstart') { + var preventDefault = true; + if ($(e.target).is(formElements)) preventDefault = false; + if (document.activeElement && $(document.activeElement).is(formElements)) { + document.activeElement.blur(); + } + if (preventDefault) { + e.preventDefault(); + } + } + s.emit('onTouchStart', s, e); + }; + + s.onTouchMove = function (e) { + if (e.originalEvent) e = e.originalEvent; + if (isTouchEvent && e.type === 'mousemove') return; + if (e.preventedByNestedSwiper) return; + if (s.params.onlyExternal) { + // isMoved = true; + s.allowClick = false; + if (isTouched) { + s.touches.startX = s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; + s.touches.startY = s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; + touchStartTime = Date.now(); + } + return; + } + if (isTouchEvent && document.activeElement) { + if (e.target === document.activeElement && $(e.target).is(formElements)) { + isMoved = true; + s.allowClick = false; + return; + } + } + if (allowTouchCallbacks) { + s.emit('onTouchMove', s, e); + } + if (e.targetTouches && e.targetTouches.length > 1) return; + + s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; + s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; + + if (typeof isScrolling === 'undefined') { + var touchAngle = Math.atan2(Math.abs(s.touches.currentY - s.touches.startY), Math.abs(s.touches.currentX - s.touches.startX)) * 180 / Math.PI; + isScrolling = isH() ? touchAngle > s.params.touchAngle : (90 - touchAngle > s.params.touchAngle); + } + if (isScrolling) { + s.emit('onTouchMoveOpposite', s, e); + } + if (typeof startMoving === 'undefined' && s.browser.ieTouch) { + if (s.touches.currentX !== s.touches.startX || s.touches.currentY !== s.touches.startY) { + startMoving = true; + } + } + if (!isTouched) return; + if (isScrolling) { + isTouched = false; + return; + } + if (!startMoving && s.browser.ieTouch) { + return; + } + s.allowClick = false; + s.emit('onSliderMove', s, e); + e.preventDefault(); + if (s.params.touchMoveStopPropagation && !s.params.nested) { + e.stopPropagation(); + } + + if (!isMoved) { + if (params.loop) { + s.fixLoop(); + } + startTranslate = s.getWrapperTranslate(); + s.setWrapperTransition(0); + if (s.animating) { + s.wrapper.trigger('webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd'); + } + if (s.params.autoplay && s.autoplaying) { + if (s.params.autoplayDisableOnInteraction) { + s.stopAutoplay(); + } + else { + s.pauseAutoplay(); + } + } + allowMomentumBounce = false; + //Grab Cursor + if (s.params.grabCursor) { + s.container[0].style.cursor = 'move'; + s.container[0].style.cursor = '-webkit-grabbing'; + s.container[0].style.cursor = '-moz-grabbin'; + s.container[0].style.cursor = 'grabbing'; + } + } + isMoved = true; + + var diff = s.touches.diff = isH() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY; + + diff = diff * s.params.touchRatio; + if (s.rtl) diff = -diff; + + s.swipeDirection = diff > 0 ? 'prev' : 'next'; + currentTranslate = diff + startTranslate; + + var disableParentSwiper = true; + if ((diff > 0 && currentTranslate > s.minTranslate())) { + disableParentSwiper = false; + if (s.params.resistance) currentTranslate = s.minTranslate() - 1 + Math.pow(-s.minTranslate() + startTranslate + diff, s.params.resistanceRatio); + } + else if (diff < 0 && currentTranslate < s.maxTranslate()) { + disableParentSwiper = false; + if (s.params.resistance) currentTranslate = s.maxTranslate() + 1 - Math.pow(s.maxTranslate() - startTranslate - diff, s.params.resistanceRatio); + } + + if (disableParentSwiper) { + e.preventedByNestedSwiper = true; + } + + // Directions locks + if (!s.params.allowSwipeToNext && s.swipeDirection === 'next' && currentTranslate < startTranslate) { + currentTranslate = startTranslate; + } + if (!s.params.allowSwipeToPrev && s.swipeDirection === 'prev' && currentTranslate > startTranslate) { + currentTranslate = startTranslate; + } + + if (!s.params.followFinger) return; + + // Threshold + if (s.params.threshold > 0) { + if (Math.abs(diff) > s.params.threshold || allowThresholdMove) { + if (!allowThresholdMove) { + allowThresholdMove = true; + s.touches.startX = s.touches.currentX; + s.touches.startY = s.touches.currentY; + currentTranslate = startTranslate; + s.touches.diff = isH() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY; + return; + } + } + else { + currentTranslate = startTranslate; + return; + } + } + // Update active index in free mode + if (s.params.freeMode || s.params.watchSlidesProgress) { + s.updateActiveIndex(); + } + if (s.params.freeMode) { + //Velocity + if (velocities.length === 0) { + velocities.push({ + position: s.touches[isH() ? 'startX' : 'startY'], + time: touchStartTime + }); + } + velocities.push({ + position: s.touches[isH() ? 'currentX' : 'currentY'], + time: (new window.Date()).getTime() + }); + } + // Update progress + s.updateProgress(currentTranslate); + // Update translate + s.setWrapperTranslate(currentTranslate); + }; + s.onTouchEnd = function (e) { + if (e.originalEvent) e = e.originalEvent; + if (allowTouchCallbacks) { + s.emit('onTouchEnd', s, e); + } + allowTouchCallbacks = false; + if (!isTouched) return; + //Return Grab Cursor + if (s.params.grabCursor && isMoved && isTouched) { + s.container[0].style.cursor = 'move'; + s.container[0].style.cursor = '-webkit-grab'; + s.container[0].style.cursor = '-moz-grab'; + s.container[0].style.cursor = 'grab'; + } + + // Time diff + var touchEndTime = Date.now(); + var timeDiff = touchEndTime - touchStartTime; + + // Tap, doubleTap, Click + if (s.allowClick) { + s.updateClickedSlide(e); + s.emit('onTap', s, e); + if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) { + if (clickTimeout) clearTimeout(clickTimeout); + clickTimeout = setTimeout(function () { + if (!s) return; + if (s.params.paginationHide && s.paginationContainer.length > 0 && !$(e.target).hasClass(s.params.bulletClass)) { + s.paginationContainer.toggleClass(s.params.paginationHiddenClass); + } + s.emit('onClick', s, e); + }, 300); + + } + if (timeDiff < 300 && (touchEndTime - lastClickTime) < 300) { + if (clickTimeout) clearTimeout(clickTimeout); + s.emit('onDoubleTap', s, e); + } + } + + lastClickTime = Date.now(); + setTimeout(function () { + if (s) s.allowClick = true; + }, 0); + + if (!isTouched || !isMoved || !s.swipeDirection || s.touches.diff === 0 || currentTranslate === startTranslate) { + isTouched = isMoved = false; + return; + } + isTouched = isMoved = false; + + var currentPos; + if (s.params.followFinger) { + currentPos = s.rtl ? s.translate : -s.translate; + } + else { + currentPos = -currentTranslate; + } + if (s.params.freeMode) { + if (currentPos < -s.minTranslate()) { + s.slideTo(s.activeIndex); + return; + } + else if (currentPos > -s.maxTranslate()) { + if (s.slides.length < s.snapGrid.length) { + s.slideTo(s.snapGrid.length - 1); + } + else { + s.slideTo(s.slides.length - 1); + } + return; + } + + if (s.params.freeModeMomentum) { + if (velocities.length > 1) { + var lastMoveEvent = velocities.pop(), velocityEvent = velocities.pop(); + + var distance = lastMoveEvent.position - velocityEvent.position; + var time = lastMoveEvent.time - velocityEvent.time; + s.velocity = distance / time; + s.velocity = s.velocity / 2; + if (Math.abs(s.velocity) < s.params.freeModeMinimumVelocity) { + s.velocity = 0; + } + // this implies that the user stopped moving a finger then released. + // There would be no events with distance zero, so the last event is stale. + if (time > 150 || (new window.Date().getTime() - lastMoveEvent.time) > 300) { + s.velocity = 0; + } + } else { + s.velocity = 0; + } + + velocities.length = 0; + var momentumDuration = 1000 * s.params.freeModeMomentumRatio; + var momentumDistance = s.velocity * momentumDuration; + + var newPosition = s.translate + momentumDistance; + if (s.rtl) newPosition = - newPosition; + var doBounce = false; + var afterBouncePosition; + var bounceAmount = Math.abs(s.velocity) * 20 * s.params.freeModeMomentumBounceRatio; + if (newPosition < s.maxTranslate()) { + if (s.params.freeModeMomentumBounce) { + if (newPosition + s.maxTranslate() < -bounceAmount) { + newPosition = s.maxTranslate() - bounceAmount; + } + afterBouncePosition = s.maxTranslate(); + doBounce = true; + allowMomentumBounce = true; + } + else { + newPosition = s.maxTranslate(); + } + } + else if (newPosition > s.minTranslate()) { + if (s.params.freeModeMomentumBounce) { + if (newPosition - s.minTranslate() > bounceAmount) { + newPosition = s.minTranslate() + bounceAmount; + } + afterBouncePosition = s.minTranslate(); + doBounce = true; + allowMomentumBounce = true; + } + else { + newPosition = s.minTranslate(); + } + } + else if (s.params.freeModeSticky) { + var j = 0, + nextSlide; + for (j = 0; j < s.snapGrid.length; j += 1) { + if (s.snapGrid[j] > -newPosition) { + nextSlide = j; + break; + } + + } + if (Math.abs(s.snapGrid[nextSlide] - newPosition) < Math.abs(s.snapGrid[nextSlide - 1] - newPosition) || s.swipeDirection === 'next') { + newPosition = s.snapGrid[nextSlide]; + } else { + newPosition = s.snapGrid[nextSlide - 1]; + } + if (!s.rtl) newPosition = - newPosition; + } + //Fix duration + if (s.velocity !== 0) { + if (s.rtl) { + momentumDuration = Math.abs((-newPosition - s.translate) / s.velocity); + } + else { + momentumDuration = Math.abs((newPosition - s.translate) / s.velocity); + } + } + else if (s.params.freeModeSticky) { + s.slideReset(); + return; + } + + if (s.params.freeModeMomentumBounce && doBounce) { + s.updateProgress(afterBouncePosition); + s.setWrapperTransition(momentumDuration); + s.setWrapperTranslate(newPosition); + s.onTransitionStart(); + s.animating = true; + s.wrapper.transitionEnd(function () { + if (!s || !allowMomentumBounce) return; + s.emit('onMomentumBounce', s); + + s.setWrapperTransition(s.params.speed); + s.setWrapperTranslate(afterBouncePosition); + s.wrapper.transitionEnd(function () { + if (!s) return; + s.onTransitionEnd(); + }); + }); + } else if (s.velocity) { + s.updateProgress(newPosition); + s.setWrapperTransition(momentumDuration); + s.setWrapperTranslate(newPosition); + s.onTransitionStart(); + if (!s.animating) { + s.animating = true; + s.wrapper.transitionEnd(function () { + if (!s) return; + s.onTransitionEnd(); + }); + } + + } else { + s.updateProgress(newPosition); + } + + s.updateActiveIndex(); + } + if (!s.params.freeModeMomentum || timeDiff >= s.params.longSwipesMs) { + s.updateProgress(); + s.updateActiveIndex(); + } + return; + } + + // Find current slide + var i, stopIndex = 0, groupSize = s.slidesSizesGrid[0]; + for (i = 0; i < s.slidesGrid.length; i += s.params.slidesPerGroup) { + if (typeof s.slidesGrid[i + s.params.slidesPerGroup] !== 'undefined') { + if (currentPos >= s.slidesGrid[i] && currentPos < s.slidesGrid[i + s.params.slidesPerGroup]) { + stopIndex = i; + groupSize = s.slidesGrid[i + s.params.slidesPerGroup] - s.slidesGrid[i]; + } + } + else { + if (currentPos >= s.slidesGrid[i]) { + stopIndex = i; + groupSize = s.slidesGrid[s.slidesGrid.length - 1] - s.slidesGrid[s.slidesGrid.length - 2]; + } + } + } + + // Find current slide size + var ratio = (currentPos - s.slidesGrid[stopIndex]) / groupSize; + + if (timeDiff > s.params.longSwipesMs) { + // Long touches + if (!s.params.longSwipes) { + s.slideTo(s.activeIndex); + return; + } + if (s.swipeDirection === 'next') { + if (ratio >= s.params.longSwipesRatio) s.slideTo(stopIndex + s.params.slidesPerGroup); + else s.slideTo(stopIndex); + + } + if (s.swipeDirection === 'prev') { + if (ratio > (1 - s.params.longSwipesRatio)) s.slideTo(stopIndex + s.params.slidesPerGroup); + else s.slideTo(stopIndex); + } + } + else { + // Short swipes + if (!s.params.shortSwipes) { + s.slideTo(s.activeIndex); + return; + } + if (s.swipeDirection === 'next') { + s.slideTo(stopIndex + s.params.slidesPerGroup); + + } + if (s.swipeDirection === 'prev') { + s.slideTo(stopIndex); + } + } + }; + /*========================= + Transitions + ===========================*/ + s._slideTo = function (slideIndex, speed) { + return s.slideTo(slideIndex, speed, true, true); + }; + s.slideTo = function (slideIndex, speed, runCallbacks, internal) { + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (typeof slideIndex === 'undefined') slideIndex = 0; + if (slideIndex < 0) slideIndex = 0; + s.snapIndex = Math.floor(slideIndex / s.params.slidesPerGroup); + if (s.snapIndex >= s.snapGrid.length) s.snapIndex = s.snapGrid.length - 1; + + var translate = - s.snapGrid[s.snapIndex]; + // Stop autoplay + if (s.params.autoplay && s.autoplaying) { + if (internal || !s.params.autoplayDisableOnInteraction) { + s.pauseAutoplay(speed); + } + else { + s.stopAutoplay(); + } + } + // Update progress + s.updateProgress(translate); + + // Normalize slideIndex + for (var i = 0; i < s.slidesGrid.length; i++) { + if (- Math.floor(translate * 100) >= Math.floor(s.slidesGrid[i] * 100)) { + slideIndex = i; + } + } + + // Directions locks + if (!s.params.allowSwipeToNext && translate < s.translate && translate < s.minTranslate()) { + return false; + } + if (!s.params.allowSwipeToPrev && translate > s.translate && translate > s.maxTranslate()) { + if ((s.activeIndex || 0) !== slideIndex ) return false; + } + + // Update Index + if (typeof speed === 'undefined') speed = s.params.speed; + s.previousIndex = s.activeIndex || 0; + s.activeIndex = slideIndex; + + if ((s.rtl && -translate === s.translate) || (!s.rtl && translate === s.translate)) { + // Update Height + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + s.updateClasses(); + if (s.params.effect !== 'slide') { + s.setWrapperTranslate(translate); + } + return false; + } + s.updateClasses(); + s.onTransitionStart(runCallbacks); + + if (speed === 0) { + s.setWrapperTranslate(translate); + s.setWrapperTransition(0); + s.onTransitionEnd(runCallbacks); + } + else { + s.setWrapperTranslate(translate); + s.setWrapperTransition(speed); + if (!s.animating) { + s.animating = true; + s.wrapper.transitionEnd(function () { + if (!s) return; + s.onTransitionEnd(runCallbacks); + }); + } + + } + + return true; + }; + + s.onTransitionStart = function (runCallbacks) { + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (s.params.autoHeight) { + s.updateAutoHeight(); + } + if (s.lazy) s.lazy.onTransitionStart(); + if (runCallbacks) { + s.emit('onTransitionStart', s); + if (s.activeIndex !== s.previousIndex) { + s.emit('onSlideChangeStart', s); + if (s.activeIndex > s.previousIndex) { + s.emit('onSlideNextStart', s); + } + else { + s.emit('onSlidePrevStart', s); + } + } + + } + }; + s.onTransitionEnd = function (runCallbacks) { + s.animating = false; + s.setWrapperTransition(0); + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (s.lazy) s.lazy.onTransitionEnd(); + if (runCallbacks) { + s.emit('onTransitionEnd', s); + if (s.activeIndex !== s.previousIndex) { + s.emit('onSlideChangeEnd', s); + if (s.activeIndex > s.previousIndex) { + s.emit('onSlideNextEnd', s); + } + else { + s.emit('onSlidePrevEnd', s); + } + } + } + if (s.params.hashnav && s.hashnav) { + s.hashnav.setHash(); + } + + }; + s.slideNext = function (runCallbacks, speed, internal) { + if (s.params.loop) { + if (s.animating) return false; + s.fixLoop(); + var clientLeft = s.container[0].clientLeft; + return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal); + } + else return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal); + }; + s._slideNext = function (speed) { + return s.slideNext(true, speed, true); + }; + s.slidePrev = function (runCallbacks, speed, internal) { + if (s.params.loop) { + if (s.animating) return false; + s.fixLoop(); + var clientLeft = s.container[0].clientLeft; + return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal); + } + else return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal); + }; + s._slidePrev = function (speed) { + return s.slidePrev(true, speed, true); + }; + s.slideReset = function (runCallbacks, speed, internal) { + return s.slideTo(s.activeIndex, speed, runCallbacks); + }; + + /*========================= + Translate/transition helpers + ===========================*/ + s.setWrapperTransition = function (duration, byController) { + s.wrapper.transition(duration); + if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { + s.effects[s.params.effect].setTransition(duration); + } + if (s.params.parallax && s.parallax) { + s.parallax.setTransition(duration); + } + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.setTransition(duration); + } + if (s.params.control && s.controller) { + s.controller.setTransition(duration, byController); + } + s.emit('onSetTransition', s, duration); + }; + s.setWrapperTranslate = function (translate, updateActiveIndex, byController) { + var x = 0, y = 0, z = 0; + if (isH()) { + x = s.rtl ? -translate : translate; + } + else { + y = translate; + } + + if (s.params.roundLengths) { + x = round(x); + y = round(y); + } + + if (!s.params.virtualTranslate) { + if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)'); + else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)'); + } + + s.translate = isH() ? x : y; + + // Check if we need to update progress + var progress; + var translatesDiff = s.maxTranslate() - s.minTranslate(); + if (translatesDiff === 0) { + progress = 0; + } + else { + progress = (translate - s.minTranslate()) / (translatesDiff); + } + if (progress !== s.progress) { + s.updateProgress(translate); + } + + if (updateActiveIndex) s.updateActiveIndex(); + if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { + s.effects[s.params.effect].setTranslate(s.translate); + } + if (s.params.parallax && s.parallax) { + s.parallax.setTranslate(s.translate); + } + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.setTranslate(s.translate); + } + if (s.params.control && s.controller) { + s.controller.setTranslate(s.translate, byController); + } + s.emit('onSetTranslate', s, s.translate); + }; + + s.getTranslate = function (el, axis) { + var matrix, curTransform, curStyle, transformMatrix; + + // automatic axis detection + if (typeof axis === 'undefined') { + axis = 'x'; + } + + if (s.params.virtualTranslate) { + return s.rtl ? -s.translate : s.translate; + } + + curStyle = window.getComputedStyle(el, null); + if (window.WebKitCSSMatrix) { + curTransform = curStyle.transform || curStyle.webkitTransform; + if (curTransform.split(',').length > 6) { + curTransform = curTransform.split(', ').map(function(a){ + return a.replace(',','.'); + }).join(', '); + } + // Some old versions of Webkit choke when 'none' is passed; pass + // empty string instead in this case + transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform); + } + else { + transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,'); + matrix = transformMatrix.toString().split(','); + } + + if (axis === 'x') { + //Latest Chrome and webkits Fix + if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m41; + //Crazy IE10 Matrix + else if (matrix.length === 16) + curTransform = parseFloat(matrix[12]); + //Normal Browsers + else + curTransform = parseFloat(matrix[4]); + } + if (axis === 'y') { + //Latest Chrome and webkits Fix + if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m42; + //Crazy IE10 Matrix + else if (matrix.length === 16) + curTransform = parseFloat(matrix[13]); + //Normal Browsers + else + curTransform = parseFloat(matrix[5]); + } + if (s.rtl && curTransform) curTransform = -curTransform; + return curTransform || 0; + }; + s.getWrapperTranslate = function (axis) { + if (typeof axis === 'undefined') { + axis = isH() ? 'x' : 'y'; + } + return s.getTranslate(s.wrapper[0], axis); + }; + + /*========================= + Observer + ===========================*/ + s.observers = []; + function initObserver(target, options) { + options = options || {}; + // create an observer instance + var ObserverFunc = window.MutationObserver || window.WebkitMutationObserver; + var observer = new ObserverFunc(function (mutations) { + mutations.forEach(function (mutation) { + s.onResize(true); + s.emit('onObserverUpdate', s, mutation); + }); + }); + + observer.observe(target, { + attributes: typeof options.attributes === 'undefined' ? true : options.attributes, + childList: typeof options.childList === 'undefined' ? true : options.childList, + characterData: typeof options.characterData === 'undefined' ? true : options.characterData + }); + + s.observers.push(observer); + } + s.initObservers = function () { + if (s.params.observeParents) { + var containerParents = s.container.parents(); + for (var i = 0; i < containerParents.length; i++) { + initObserver(containerParents[i]); + } + } + + // Observe container + initObserver(s.container[0], {childList: false}); + + // Observe wrapper + initObserver(s.wrapper[0], {attributes: false}); + }; + s.disconnectObservers = function () { + for (var i = 0; i < s.observers.length; i++) { + s.observers[i].disconnect(); + } + s.observers = []; + }; + /*========================= + Loop + ===========================*/ + // Create looped slides + s.createLoop = function () { + + var toRemove = s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass); + angular.element(toRemove).remove(); + + var slides = s.wrapper.children('.' + s.params.slideClass); + + if(s.params.slidesPerView === 'auto' && !s.params.loopedSlides) s.params.loopedSlides = slides.length; + + s.loopedSlides = parseInt(s.params.loopedSlides || s.params.slidesPerView, 10); + s.loopedSlides = s.loopedSlides + s.params.loopAdditionalSlides; + if (s.loopedSlides > slides.length) { + s.loopedSlides = slides.length; + } + + var prependSlides = [], appendSlides = [], i, scope, newNode; + slides.each(function (index, el) { + var slide = $(this); + if (index < s.loopedSlides) appendSlides.push(el); + if (index < slides.length && index >= slides.length - s.loopedSlides) prependSlides.push(el); + slide.attr('data-swiper-slide-index', index); + }); + for (i = 0; i < appendSlides.length; i++) { + newNode = angular.element(appendSlides[i]).clone().addClass(s.params.slideDuplicateClass); + newNode.removeAttr('ng-transclude'); + newNode.removeAttr('ng-repeat'); + scope = angular.element(appendSlides[i]).scope(); + newNode = $compile(newNode)(scope); + angular.element(s.wrapper).append(newNode); + //s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); + } + for (i = prependSlides.length - 1; i >= 0; i--) { + //s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass)); + + newNode = angular.element(prependSlides[i]).clone().addClass(s.params.slideDuplicateClass); + newNode.removeAttr('ng-transclude'); + newNode.removeAttr('ng-repeat'); + + scope = angular.element(prependSlides[i]).scope(); + newNode = $compile(newNode)(scope); + angular.element(s.wrapper).prepend(newNode); + } + }; + s.destroyLoop = function () { + s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove(); + s.slides.removeAttr('data-swiper-slide-index'); + }; + s.fixLoop = function () { + var newIndex; + //Fix For Negative Oversliding + if (s.activeIndex < s.loopedSlides) { + newIndex = s.slides.length - s.loopedSlides * 3 + s.activeIndex; + newIndex = newIndex + s.loopedSlides; + s.slideTo(newIndex, 0, false, true); + } + //Fix For Positive Oversliding + else if ((s.params.slidesPerView === 'auto' && s.activeIndex >= s.loopedSlides * 2) || (s.activeIndex > s.slides.length - s.params.slidesPerView * 2)) { + newIndex = -s.slides.length + s.activeIndex + s.loopedSlides; + newIndex = newIndex + s.loopedSlides; + s.slideTo(newIndex, 0, false, true); + } + }; + /*========================= + Append/Prepend/Remove Slides + ===========================*/ + s.appendSlide = function (slides) { + if (s.params.loop) { + s.destroyLoop(); + } + if (typeof slides === 'object' && slides.length) { + for (var i = 0; i < slides.length; i++) { + if (slides[i]) s.wrapper.append(slides[i]); + } + } + else { + s.wrapper.append(slides); + } + if (s.params.loop) { + s.createLoop(); + } + if (!(s.params.observer && s.support.observer)) { + s.update(true); + } + }; + s.prependSlide = function (slides) { + if (s.params.loop) { + s.destroyLoop(); + } + var newActiveIndex = s.activeIndex + 1; + if (typeof slides === 'object' && slides.length) { + for (var i = 0; i < slides.length; i++) { + if (slides[i]) s.wrapper.prepend(slides[i]); + } + newActiveIndex = s.activeIndex + slides.length; + } + else { + s.wrapper.prepend(slides); + } + if (s.params.loop) { + s.createLoop(); + } + if (!(s.params.observer && s.support.observer)) { + s.update(true); + } + s.slideTo(newActiveIndex, 0, false); + }; + s.removeSlide = function (slidesIndexes) { + if (s.params.loop) { + s.destroyLoop(); + s.slides = s.wrapper.children('.' + s.params.slideClass); + } + var newActiveIndex = s.activeIndex, + indexToRemove; + if (typeof slidesIndexes === 'object' && slidesIndexes.length) { + for (var i = 0; i < slidesIndexes.length; i++) { + indexToRemove = slidesIndexes[i]; + if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove(); + if (indexToRemove < newActiveIndex) newActiveIndex--; + } + newActiveIndex = Math.max(newActiveIndex, 0); + } + else { + indexToRemove = slidesIndexes; + if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove(); + if (indexToRemove < newActiveIndex) newActiveIndex--; + newActiveIndex = Math.max(newActiveIndex, 0); + } + + if (s.params.loop) { + s.createLoop(); + } + + if (!(s.params.observer && s.support.observer)) { + s.update(true); + } + if (s.params.loop) { + s.slideTo(newActiveIndex + s.loopedSlides, 0, false); + } + else { + s.slideTo(newActiveIndex, 0, false); + } + + }; + s.removeAllSlides = function () { + var slidesIndexes = []; + for (var i = 0; i < s.slides.length; i++) { + slidesIndexes.push(i); + } + s.removeSlide(slidesIndexes); + }; + + + /*========================= + Effects + ===========================*/ + s.effects = { + fade: { + setTranslate: function () { + for (var i = 0; i < s.slides.length; i++) { + var slide = s.slides.eq(i); + var offset = slide[0].swiperSlideOffset; + var tx = -offset; + if (!s.params.virtualTranslate) tx = tx - s.translate; + var ty = 0; + if (!isH()) { + ty = tx; + tx = 0; + } + var slideOpacity = s.params.fade.crossFade ? + Math.max(1 - Math.abs(slide[0].progress), 0) : + 1 + Math.min(Math.max(slide[0].progress, -1), 0); + slide + .css({ + opacity: slideOpacity + }) + .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px)'); + + } + + }, + setTransition: function (duration) { + s.slides.transition(duration); + if (s.params.virtualTranslate && duration !== 0) { + var eventTriggered = false; + s.slides.transitionEnd(function () { + if (eventTriggered) return; + if (!s) return; + eventTriggered = true; + s.animating = false; + var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd']; + for (var i = 0; i < triggerEvents.length; i++) { + s.wrapper.trigger(triggerEvents[i]); + } + }); + } + } + }, + cube: { + setTranslate: function () { + var wrapperRotate = 0, cubeShadow; + if (s.params.cube.shadow) { + if (isH()) { + cubeShadow = s.wrapper.find('.swiper-cube-shadow'); + if (cubeShadow.length === 0) { + cubeShadow = $('<div class="swiper-cube-shadow"></div>'); + s.wrapper.append(cubeShadow); + } + cubeShadow.css({height: s.width + 'px'}); + } + else { + cubeShadow = s.container.find('.swiper-cube-shadow'); + if (cubeShadow.length === 0) { + cubeShadow = $('<div class="swiper-cube-shadow"></div>'); + s.container.append(cubeShadow); + } + } + } + for (var i = 0; i < s.slides.length; i++) { + var slide = s.slides.eq(i); + var slideAngle = i * 90; + var round = Math.floor(slideAngle / 360); + if (s.rtl) { + slideAngle = -slideAngle; + round = Math.floor(-slideAngle / 360); + } + var progress = Math.max(Math.min(slide[0].progress, 1), -1); + var tx = 0, ty = 0, tz = 0; + if (i % 4 === 0) { + tx = - round * 4 * s.size; + tz = 0; + } + else if ((i - 1) % 4 === 0) { + tx = 0; + tz = - round * 4 * s.size; + } + else if ((i - 2) % 4 === 0) { + tx = s.size + round * 4 * s.size; + tz = s.size; + } + else if ((i - 3) % 4 === 0) { + tx = - s.size; + tz = 3 * s.size + s.size * 4 * round; + } + if (s.rtl) { + tx = -tx; + } + + if (!isH()) { + ty = tx; + tx = 0; + } + + var transform = 'rotateX(' + (isH() ? 0 : -slideAngle) + 'deg) rotateY(' + (isH() ? slideAngle : 0) + 'deg) translate3d(' + tx + 'px, ' + ty + 'px, ' + tz + 'px)'; + if (progress <= 1 && progress > -1) { + wrapperRotate = i * 90 + progress * 90; + if (s.rtl) wrapperRotate = -i * 90 - progress * 90; + } + slide.transform(transform); + if (s.params.cube.slideShadows) { + //Set shadows + var shadowBefore = isH() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top'); + var shadowAfter = isH() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom'); + if (shadowBefore.length === 0) { + shadowBefore = $('<div class="swiper-slide-shadow-' + (isH() ? 'left' : 'top') + '"></div>'); + slide.append(shadowBefore); + } + if (shadowAfter.length === 0) { + shadowAfter = $('<div class="swiper-slide-shadow-' + (isH() ? 'right' : 'bottom') + '"></div>'); + slide.append(shadowAfter); + } + var shadowOpacity = slide[0].progress; + if (shadowBefore.length) shadowBefore[0].style.opacity = -slide[0].progress; + if (shadowAfter.length) shadowAfter[0].style.opacity = slide[0].progress; + } + } + s.wrapper.css({ + '-webkit-transform-origin': '50% 50% -' + (s.size / 2) + 'px', + '-moz-transform-origin': '50% 50% -' + (s.size / 2) + 'px', + '-ms-transform-origin': '50% 50% -' + (s.size / 2) + 'px', + 'transform-origin': '50% 50% -' + (s.size / 2) + 'px' + }); + + if (s.params.cube.shadow) { + if (isH()) { + cubeShadow.transform('translate3d(0px, ' + (s.width / 2 + s.params.cube.shadowOffset) + 'px, ' + (-s.width / 2) + 'px) rotateX(90deg) rotateZ(0deg) scale(' + (s.params.cube.shadowScale) + ')'); + } + else { + var shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90; + var multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2); + var scale1 = s.params.cube.shadowScale, + scale2 = s.params.cube.shadowScale / multiplier, + offset = s.params.cube.shadowOffset; + cubeShadow.transform('scale3d(' + scale1 + ', 1, ' + scale2 + ') translate3d(0px, ' + (s.height / 2 + offset) + 'px, ' + (-s.height / 2 / scale2) + 'px) rotateX(-90deg)'); + } + } + var zFactor = (s.isSafari || s.isUiWebView) ? (-s.size / 2) : 0; + s.wrapper.transform('translate3d(0px,0,' + zFactor + 'px) rotateX(' + (isH() ? 0 : wrapperRotate) + 'deg) rotateY(' + (isH() ? -wrapperRotate : 0) + 'deg)'); + }, + setTransition: function (duration) { + s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration); + if (s.params.cube.shadow && !isH()) { + s.container.find('.swiper-cube-shadow').transition(duration); + } + } + }, + coverflow: { + setTranslate: function () { + var transform = s.translate; + var center = isH() ? -transform + s.width / 2 : -transform + s.height / 2; + var rotate = isH() ? s.params.coverflow.rotate: -s.params.coverflow.rotate; + var translate = s.params.coverflow.depth; + //Each slide offset from center + for (var i = 0, length = s.slides.length; i < length; i++) { + var slide = s.slides.eq(i); + var slideSize = s.slidesSizesGrid[i]; + var slideOffset = slide[0].swiperSlideOffset; + var offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * s.params.coverflow.modifier; + + var rotateY = isH() ? rotate * offsetMultiplier : 0; + var rotateX = isH() ? 0 : rotate * offsetMultiplier; + // var rotateZ = 0 + var translateZ = -translate * Math.abs(offsetMultiplier); + + var translateY = isH() ? 0 : s.params.coverflow.stretch * (offsetMultiplier); + var translateX = isH() ? s.params.coverflow.stretch * (offsetMultiplier) : 0; + + //Fix for ultra small values + if (Math.abs(translateX) < 0.001) translateX = 0; + if (Math.abs(translateY) < 0.001) translateY = 0; + if (Math.abs(translateZ) < 0.001) translateZ = 0; + if (Math.abs(rotateY) < 0.001) rotateY = 0; + if (Math.abs(rotateX) < 0.001) rotateX = 0; + + var slideTransform = 'translate3d(' + translateX + 'px,' + translateY + 'px,' + translateZ + 'px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)'; + + slide.transform(slideTransform); + slide[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1; + if (s.params.coverflow.slideShadows) { + //Set shadows + var shadowBefore = isH() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top'); + var shadowAfter = isH() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom'); + if (shadowBefore.length === 0) { + shadowBefore = $('<div class="swiper-slide-shadow-' + (isH() ? 'left' : 'top') + '"></div>'); + slide.append(shadowBefore); + } + if (shadowAfter.length === 0) { + shadowAfter = $('<div class="swiper-slide-shadow-' + (isH() ? 'right' : 'bottom') + '"></div>'); + slide.append(shadowAfter); + } + if (shadowBefore.length) shadowBefore[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0; + if (shadowAfter.length) shadowAfter[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0; + } + } + + //Set correct perspective for IE10 + if (s.browser.ie) { + var ws = s.wrapper[0].style; + ws.perspectiveOrigin = center + 'px 50%'; + } + }, + setTransition: function (duration) { + s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration); + } + } + }; + + /*========================= + Images Lazy Loading + ===========================*/ + s.lazy = { + initialImageLoaded: false, + loadImageInSlide: function (index, loadInDuplicate) { + if (typeof index === 'undefined') return; + if (typeof loadInDuplicate === 'undefined') loadInDuplicate = true; + if (s.slides.length === 0) return; + + var slide = s.slides.eq(index); + var img = slide.find('.swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)'); + if (slide.hasClass('swiper-lazy') && !slide.hasClass('swiper-lazy-loaded') && !slide.hasClass('swiper-lazy-loading')) { + img = img.add(slide[0]); + } + if (img.length === 0) return; + + img.each(function () { + var _img = $(this); + _img.addClass('swiper-lazy-loading'); + var background = _img.attr('data-background'); + var src = _img.attr('data-src'), + srcset = _img.attr('data-srcset'); + s.loadImage(_img[0], (src || background), srcset, false, function () { + if (background) { + _img.css('background-image', 'url(' + background + ')'); + _img.removeAttr('data-background'); + } + else { + if (srcset) { + _img.attr('srcset', srcset); + _img.removeAttr('data-srcset'); + } + if (src) { + _img.attr('src', src); + _img.removeAttr('data-src'); + } + + } + + _img.addClass('swiper-lazy-loaded').removeClass('swiper-lazy-loading'); + slide.find('.swiper-lazy-preloader, .preloader').remove(); + if (s.params.loop && loadInDuplicate) { + var slideOriginalIndex = slide.attr('data-swiper-slide-index'); + if (slide.hasClass(s.params.slideDuplicateClass)) { + var originalSlide = s.wrapper.children('[data-swiper-slide-index="' + slideOriginalIndex + '"]:not(.' + s.params.slideDuplicateClass + ')'); + s.lazy.loadImageInSlide(originalSlide.index(), false); + } + else { + var duplicatedSlide = s.wrapper.children('.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + slideOriginalIndex + '"]'); + s.lazy.loadImageInSlide(duplicatedSlide.index(), false); + } + } + s.emit('onLazyImageReady', s, slide[0], _img[0]); + }); + + s.emit('onLazyImageLoad', s, slide[0], _img[0]); + }); + + }, + load: function () { + var i; + if (s.params.watchSlidesVisibility) { + s.wrapper.children('.' + s.params.slideVisibleClass).each(function () { + s.lazy.loadImageInSlide($(this).index()); + }); + } + else { + if (s.params.slidesPerView > 1) { + for (i = s.activeIndex; i < s.activeIndex + s.params.slidesPerView ; i++) { + if (s.slides[i]) s.lazy.loadImageInSlide(i); + } + } + else { + s.lazy.loadImageInSlide(s.activeIndex); + } + } + if (s.params.lazyLoadingInPrevNext) { + if (s.params.slidesPerView > 1) { + // Next Slides + for (i = s.activeIndex + s.params.slidesPerView; i < s.activeIndex + s.params.slidesPerView + s.params.slidesPerView; i++) { + if (s.slides[i]) s.lazy.loadImageInSlide(i); + } + // Prev Slides + for (i = s.activeIndex - s.params.slidesPerView; i < s.activeIndex ; i++) { + if (s.slides[i]) s.lazy.loadImageInSlide(i); + } + } + else { + var nextSlide = s.wrapper.children('.' + s.params.slideNextClass); + if (nextSlide.length > 0) s.lazy.loadImageInSlide(nextSlide.index()); + + var prevSlide = s.wrapper.children('.' + s.params.slidePrevClass); + if (prevSlide.length > 0) s.lazy.loadImageInSlide(prevSlide.index()); + } + } + }, + onTransitionStart: function () { + if (s.params.lazyLoading) { + if (s.params.lazyLoadingOnTransitionStart || (!s.params.lazyLoadingOnTransitionStart && !s.lazy.initialImageLoaded)) { + s.lazy.load(); + } + } + }, + onTransitionEnd: function () { + if (s.params.lazyLoading && !s.params.lazyLoadingOnTransitionStart) { + s.lazy.load(); + } + } + }; + + + /*========================= + Scrollbar + ===========================*/ + s.scrollbar = { + isTouched: false, + setDragPosition: function (e) { + var sb = s.scrollbar; + var x = 0, y = 0; + var translate; + var pointerPosition = isH() ? + ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageX : e.pageX || e.clientX) : + ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageY : e.pageY || e.clientY) ; + var position = (pointerPosition) - sb.track.offset()[isH() ? 'left' : 'top'] - sb.dragSize / 2; + var positionMin = -s.minTranslate() * sb.moveDivider; + var positionMax = -s.maxTranslate() * sb.moveDivider; + if (position < positionMin) { + position = positionMin; + } + else if (position > positionMax) { + position = positionMax; + } + position = -position / sb.moveDivider; + s.updateProgress(position); + s.setWrapperTranslate(position, true); + }, + dragStart: function (e) { + var sb = s.scrollbar; + sb.isTouched = true; + e.preventDefault(); + e.stopPropagation(); + + sb.setDragPosition(e); + clearTimeout(sb.dragTimeout); + + sb.track.transition(0); + if (s.params.scrollbarHide) { + sb.track.css('opacity', 1); + } + s.wrapper.transition(100); + sb.drag.transition(100); + s.emit('onScrollbarDragStart', s); + }, + dragMove: function (e) { + var sb = s.scrollbar; + if (!sb.isTouched) return; + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + sb.setDragPosition(e); + s.wrapper.transition(0); + sb.track.transition(0); + sb.drag.transition(0); + s.emit('onScrollbarDragMove', s); + }, + dragEnd: function (e) { + var sb = s.scrollbar; + if (!sb.isTouched) return; + sb.isTouched = false; + if (s.params.scrollbarHide) { + clearTimeout(sb.dragTimeout); + sb.dragTimeout = setTimeout(function () { + sb.track.css('opacity', 0); + sb.track.transition(400); + }, 1000); + + } + s.emit('onScrollbarDragEnd', s); + if (s.params.scrollbarSnapOnRelease) { + s.slideReset(); + } + }, + enableDraggable: function () { + var sb = s.scrollbar; + var target = s.support.touch ? sb.track : document; + $(sb.track).on(s.touchEvents.start, sb.dragStart); + $(target).on(s.touchEvents.move, sb.dragMove); + $(target).on(s.touchEvents.end, sb.dragEnd); + }, + disableDraggable: function () { + var sb = s.scrollbar; + var target = s.support.touch ? sb.track : document; + $(sb.track).off(s.touchEvents.start, sb.dragStart); + $(target).off(s.touchEvents.move, sb.dragMove); + $(target).off(s.touchEvents.end, sb.dragEnd); + }, + set: function () { + if (!s.params.scrollbar) return; + var sb = s.scrollbar; + sb.track = $(s.params.scrollbar); + sb.drag = sb.track.find('.swiper-scrollbar-drag'); + if (sb.drag.length === 0) { + sb.drag = $('<div class="swiper-scrollbar-drag"></div>'); + sb.track.append(sb.drag); + } + sb.drag[0].style.width = ''; + sb.drag[0].style.height = ''; + sb.trackSize = isH() ? sb.track[0].offsetWidth : sb.track[0].offsetHeight; + + sb.divider = s.size / s.virtualSize; + sb.moveDivider = sb.divider * (sb.trackSize / s.size); + sb.dragSize = sb.trackSize * sb.divider; + + if (isH()) { + sb.drag[0].style.width = sb.dragSize + 'px'; + } + else { + sb.drag[0].style.height = sb.dragSize + 'px'; + } + + if (sb.divider >= 1) { + sb.track[0].style.display = 'none'; + } + else { + sb.track[0].style.display = ''; + } + if (s.params.scrollbarHide) { + sb.track[0].style.opacity = 0; + } + }, + setTranslate: function () { + if (!s.params.scrollbar) return; + var diff; + var sb = s.scrollbar; + var translate = s.translate || 0; + var newPos; + + var newSize = sb.dragSize; + newPos = (sb.trackSize - sb.dragSize) * s.progress; + if (s.rtl && isH()) { + newPos = -newPos; + if (newPos > 0) { + newSize = sb.dragSize - newPos; + newPos = 0; + } + else if (-newPos + sb.dragSize > sb.trackSize) { + newSize = sb.trackSize + newPos; + } + } + else { + if (newPos < 0) { + newSize = sb.dragSize + newPos; + newPos = 0; + } + else if (newPos + sb.dragSize > sb.trackSize) { + newSize = sb.trackSize - newPos; + } + } + if (isH()) { + if (s.support.transforms3d) { + sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)'); + } + else { + sb.drag.transform('translateX(' + (newPos) + 'px)'); + } + sb.drag[0].style.width = newSize + 'px'; + } + else { + if (s.support.transforms3d) { + sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)'); + } + else { + sb.drag.transform('translateY(' + (newPos) + 'px)'); + } + sb.drag[0].style.height = newSize + 'px'; + } + if (s.params.scrollbarHide) { + clearTimeout(sb.timeout); + sb.track[0].style.opacity = 1; + sb.timeout = setTimeout(function () { + sb.track[0].style.opacity = 0; + sb.track.transition(400); + }, 1000); + } + }, + setTransition: function (duration) { + if (!s.params.scrollbar) return; + s.scrollbar.drag.transition(duration); + } + }; + + /*========================= + Controller + ===========================*/ + s.controller = { + LinearSpline: function (x, y) { + this.x = x; + this.y = y; + this.lastIndex = x.length - 1; + // Given an x value (x2), return the expected y2 value: + // (x1,y1) is the known point before given value, + // (x3,y3) is the known point after given value. + var i1, i3; + var l = this.x.length; + + this.interpolate = function (x2) { + if (!x2) return 0; + + // Get the indexes of x1 and x3 (the array indexes before and after given x2): + i3 = binarySearch(this.x, x2); + i1 = i3 - 1; + + // We have our indexes i1 & i3, so we can calculate already: + // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1 + return ((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1]; + }; + + var binarySearch = (function() { + var maxIndex, minIndex, guess; + return function(array, val) { + minIndex = -1; + maxIndex = array.length; + while (maxIndex - minIndex > 1) + if (array[guess = maxIndex + minIndex >> 1] <= val) { + minIndex = guess; + } else { + maxIndex = guess; + } + return maxIndex; + }; + })(); + }, + //xxx: for now i will just save one spline function to to + getInterpolateFunction: function(c){ + if(!s.controller.spline) s.controller.spline = s.params.loop ? + new s.controller.LinearSpline(s.slidesGrid, c.slidesGrid) : + new s.controller.LinearSpline(s.snapGrid, c.snapGrid); + }, + setTranslate: function (translate, byController) { + var controlled = s.params.control; + var multiplier, controlledTranslate; + function setControlledTranslate(c) { + // this will create an Interpolate function based on the snapGrids + // x is the Grid of the scrolled scroller and y will be the controlled scroller + // it makes sense to create this only once and recall it for the interpolation + // the function does a lot of value caching for performance + translate = c.rtl && c.params.direction === 'horizontal' ? -s.translate : s.translate; + if (s.params.controlBy === 'slide') { + s.controller.getInterpolateFunction(c); + // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid + // but it did not work out + controlledTranslate = -s.controller.spline.interpolate(-translate); + } + + if(!controlledTranslate || s.params.controlBy === 'container'){ + multiplier = (c.maxTranslate() - c.minTranslate()) / (s.maxTranslate() - s.minTranslate()); + controlledTranslate = (translate - s.minTranslate()) * multiplier + c.minTranslate(); + } + + if (s.params.controlInverse) { + controlledTranslate = c.maxTranslate() - controlledTranslate; + } + c.updateProgress(controlledTranslate); + c.setWrapperTranslate(controlledTranslate, false, s); + c.updateActiveIndex(); + } + if (s.isArray(controlled)) { + for (var i = 0; i < controlled.length; i++) { + if (controlled[i] !== byController && controlled[i] instanceof Swiper) { + setControlledTranslate(controlled[i]); + } + } + } + else if (controlled instanceof Swiper && byController !== controlled) { + + setControlledTranslate(controlled); + } + }, + setTransition: function (duration, byController) { + var controlled = s.params.control; + var i; + function setControlledTransition(c) { + c.setWrapperTransition(duration, s); + if (duration !== 0) { + c.onTransitionStart(); + c.wrapper.transitionEnd(function(){ + if (!controlled) return; + if (c.params.loop && s.params.controlBy === 'slide') { + c.fixLoop(); + } + c.onTransitionEnd(); + + }); + } + } + if (s.isArray(controlled)) { + for (i = 0; i < controlled.length; i++) { + if (controlled[i] !== byController && controlled[i] instanceof Swiper) { + setControlledTransition(controlled[i]); + } + } + } + else if (controlled instanceof Swiper && byController !== controlled) { + setControlledTransition(controlled); + } + } + }; + + /*========================= + Hash Navigation + ===========================*/ + s.hashnav = { + init: function () { + if (!s.params.hashnav) return; + s.hashnav.initialized = true; + var hash = document.location.hash.replace('#', ''); + if (!hash) return; + var speed = 0; + for (var i = 0, length = s.slides.length; i < length; i++) { + var slide = s.slides.eq(i); + var slideHash = slide.attr('data-hash'); + if (slideHash === hash && !slide.hasClass(s.params.slideDuplicateClass)) { + var index = slide.index(); + s.slideTo(index, speed, s.params.runCallbacksOnInit, true); + } + } + }, + setHash: function () { + if (!s.hashnav.initialized || !s.params.hashnav) return; + document.location.hash = s.slides.eq(s.activeIndex).attr('data-hash') || ''; + } + }; + + /*========================= + Keyboard Control + ===========================*/ + function handleKeyboard(e) { + if (e.originalEvent) e = e.originalEvent; //jquery fix + var kc = e.keyCode || e.charCode; + // Directions locks + if (!s.params.allowSwipeToNext && (isH() && kc === 39 || !isH() && kc === 40)) { + return false; + } + if (!s.params.allowSwipeToPrev && (isH() && kc === 37 || !isH() && kc === 38)) { + return false; + } + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) { + return; + } + if (document.activeElement && document.activeElement.nodeName && (document.activeElement.nodeName.toLowerCase() === 'input' || document.activeElement.nodeName.toLowerCase() === 'textarea')) { + return; + } + if (kc === 37 || kc === 39 || kc === 38 || kc === 40) { + var inView = false; + //Check that swiper should be inside of visible area of window + if (s.container.parents('.swiper-slide').length > 0 && s.container.parents('.swiper-slide-active').length === 0) { + return; + } + var windowScroll = { + left: window.pageXOffset, + top: window.pageYOffset + }; + var windowWidth = window.innerWidth; + var windowHeight = window.innerHeight; + var swiperOffset = s.container.offset(); + if (s.rtl) swiperOffset.left = swiperOffset.left - s.container[0].scrollLeft; + var swiperCoord = [ + [swiperOffset.left, swiperOffset.top], + [swiperOffset.left + s.width, swiperOffset.top], + [swiperOffset.left, swiperOffset.top + s.height], + [swiperOffset.left + s.width, swiperOffset.top + s.height] + ]; + for (var i = 0; i < swiperCoord.length; i++) { + var point = swiperCoord[i]; + if ( + point[0] >= windowScroll.left && point[0] <= windowScroll.left + windowWidth && + point[1] >= windowScroll.top && point[1] <= windowScroll.top + windowHeight + ) { + inView = true; + } + + } + if (!inView) return; + } + if (isH()) { + if (kc === 37 || kc === 39) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if ((kc === 39 && !s.rtl) || (kc === 37 && s.rtl)) s.slideNext(); + if ((kc === 37 && !s.rtl) || (kc === 39 && s.rtl)) s.slidePrev(); + } + else { + if (kc === 38 || kc === 40) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if (kc === 40) s.slideNext(); + if (kc === 38) s.slidePrev(); + } + } + s.disableKeyboardControl = function () { + s.params.keyboardControl = false; + $(document).off('keydown', handleKeyboard); + }; + s.enableKeyboardControl = function () { + s.params.keyboardControl = true; + $(document).on('keydown', handleKeyboard); + }; + + + /*========================= + Mousewheel Control + ===========================*/ + s.mousewheel = { + event: false, + lastScrollTime: (new window.Date()).getTime() + }; + if (s.params.mousewheelControl) { + try { + new window.WheelEvent('wheel'); + s.mousewheel.event = 'wheel'; + } catch (e) {} + + if (!s.mousewheel.event && document.onmousewheel !== undefined) { + s.mousewheel.event = 'mousewheel'; + } + if (!s.mousewheel.event) { + s.mousewheel.event = 'DOMMouseScroll'; + } + } + function handleMousewheel(e) { + if (e.originalEvent) e = e.originalEvent; //jquery fix + var we = s.mousewheel.event; + var delta = 0; + var rtlFactor = s.rtl ? -1 : 1; + //Opera & IE + if (e.detail) delta = -e.detail; + //WebKits + else if (we === 'mousewheel') { + if (s.params.mousewheelForceToAxis) { + if (isH()) { + if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) delta = e.wheelDeltaX * rtlFactor; + else return; + } + else { + if (Math.abs(e.wheelDeltaY) > Math.abs(e.wheelDeltaX)) delta = e.wheelDeltaY; + else return; + } + } + else { + delta = Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY) ? - e.wheelDeltaX * rtlFactor : - e.wheelDeltaY; + } + } + //Old FireFox + else if (we === 'DOMMouseScroll') delta = -e.detail; + //New FireFox + else if (we === 'wheel') { + if (s.params.mousewheelForceToAxis) { + if (isH()) { + if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) delta = -e.deltaX * rtlFactor; + else return; + } + else { + if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) delta = -e.deltaY; + else return; + } + } + else { + delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? - e.deltaX * rtlFactor : - e.deltaY; + } + } + if (delta === 0) return; + + if (s.params.mousewheelInvert) delta = -delta; + + if (!s.params.freeMode) { + if ((new window.Date()).getTime() - s.mousewheel.lastScrollTime > 60) { + if (delta < 0) { + if ((!s.isEnd || s.params.loop) && !s.animating) s.slideNext(); + else if (s.params.mousewheelReleaseOnEdges) return true; + } + else { + if ((!s.isBeginning || s.params.loop) && !s.animating) s.slidePrev(); + else if (s.params.mousewheelReleaseOnEdges) return true; + } + } + s.mousewheel.lastScrollTime = (new window.Date()).getTime(); + + } + else { + //Freemode or scrollContainer: + var position = s.getWrapperTranslate() + delta * s.params.mousewheelSensitivity; + var wasBeginning = s.isBeginning, + wasEnd = s.isEnd; + + if (position >= s.minTranslate()) position = s.minTranslate(); + if (position <= s.maxTranslate()) position = s.maxTranslate(); + + s.setWrapperTransition(0); + s.setWrapperTranslate(position); + s.updateProgress(); + s.updateActiveIndex(); + + if (!wasBeginning && s.isBeginning || !wasEnd && s.isEnd) { + s.updateClasses(); + } + + if (s.params.freeModeSticky) { + clearTimeout(s.mousewheel.timeout); + s.mousewheel.timeout = setTimeout(function () { + s.slideReset(); + }, 300); + } + + // Return page scroll on edge positions + if (position === 0 || position === s.maxTranslate()) return; + } + if (s.params.autoplay) s.stopAutoplay(); + + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + return false; + } + s.disableMousewheelControl = function () { + if (!s.mousewheel.event) return false; + s.container.off(s.mousewheel.event, handleMousewheel); + return true; + }; + + s.enableMousewheelControl = function () { + if (!s.mousewheel.event) return false; + s.container.on(s.mousewheel.event, handleMousewheel); + return true; + }; + + + /*========================= + Parallax + ===========================*/ + function setParallaxTransform(el, progress) { + el = $(el); + var p, pX, pY; + var rtlFactor = s.rtl ? -1 : 1; + + p = el.attr('data-swiper-parallax') || '0'; + pX = el.attr('data-swiper-parallax-x'); + pY = el.attr('data-swiper-parallax-y'); + if (pX || pY) { + pX = pX || '0'; + pY = pY || '0'; + } + else { + if (isH()) { + pX = p; + pY = '0'; + } + else { + pY = p; + pX = '0'; + } + } + + if ((pX).indexOf('%') >= 0) { + pX = parseInt(pX, 10) * progress * rtlFactor + '%'; + } + else { + pX = pX * progress * rtlFactor + 'px' ; + } + if ((pY).indexOf('%') >= 0) { + pY = parseInt(pY, 10) * progress + '%'; + } + else { + pY = pY * progress + 'px' ; + } + + el.transform('translate3d(' + pX + ', ' + pY + ',0px)'); + } + s.parallax = { + setTranslate: function () { + s.container.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){ + setParallaxTransform(this, s.progress); + + }); + s.slides.each(function () { + var slide = $(this); + slide.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function () { + var progress = Math.min(Math.max(slide[0].progress, -1), 1); + setParallaxTransform(this, progress); + }); + }); + }, + setTransition: function (duration) { + if (typeof duration === 'undefined') duration = s.params.speed; + s.container.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){ + var el = $(this); + var parallaxDuration = parseInt(el.attr('data-swiper-parallax-duration'), 10) || duration; + if (duration === 0) parallaxDuration = 0; + el.transition(parallaxDuration); + }); + } + }; + + + /*========================= + Plugins API. Collect all and init all plugins + ===========================*/ + s._plugins = []; + for (var plugin in s.plugins) { + var p = s.plugins[plugin](s, s.params[plugin]); + if (p) s._plugins.push(p); + } + // Method to call all plugins event/method + s.callPlugins = function (eventName) { + for (var i = 0; i < s._plugins.length; i++) { + if (eventName in s._plugins[i]) { + s._plugins[i][eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + } + }; + + /*========================= + Events/Callbacks/Plugins Emitter + ===========================*/ + function normalizeEventName (eventName) { + if (eventName.indexOf('on') !== 0) { + if (eventName[0] !== eventName[0].toUpperCase()) { + eventName = 'on' + eventName[0].toUpperCase() + eventName.substring(1); + } + else { + eventName = 'on' + eventName; + } + } + return eventName; + } + s.emitterEventListeners = { + + }; + s.emit = function (eventName) { + // Trigger callbacks + if (s.params[eventName]) { + s.params[eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + var i; + // Trigger events + if (s.emitterEventListeners[eventName]) { + for (i = 0; i < s.emitterEventListeners[eventName].length; i++) { + s.emitterEventListeners[eventName][i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + } + // Trigger plugins + if (s.callPlugins) s.callPlugins(eventName, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + }; + s.on = function (eventName, handler) { + eventName = normalizeEventName(eventName); + if (!s.emitterEventListeners[eventName]) s.emitterEventListeners[eventName] = []; + s.emitterEventListeners[eventName].push(handler); + return s; + }; + s.off = function (eventName, handler) { + var i; + eventName = normalizeEventName(eventName); + if (typeof handler === 'undefined') { + // Remove all handlers for such event + s.emitterEventListeners[eventName] = []; + return s; + } + if (!s.emitterEventListeners[eventName] || s.emitterEventListeners[eventName].length === 0) return; + for (i = 0; i < s.emitterEventListeners[eventName].length; i++) { + if(s.emitterEventListeners[eventName][i] === handler) s.emitterEventListeners[eventName].splice(i, 1); + } + return s; + }; + s.once = function (eventName, handler) { + eventName = normalizeEventName(eventName); + var _handler = function () { + handler(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); + s.off(eventName, _handler); + }; + s.on(eventName, _handler); + return s; + }; + + // Accessibility tools + s.a11y = { + makeFocusable: function ($el) { + $el.attr('tabIndex', '0'); + return $el; + }, + addRole: function ($el, role) { + $el.attr('role', role); + return $el; + }, + + addLabel: function ($el, label) { + $el.attr('aria-label', label); + return $el; + }, + + disable: function ($el) { + $el.attr('aria-disabled', true); + return $el; + }, + + enable: function ($el) { + $el.attr('aria-disabled', false); + return $el; + }, + + onEnterKey: function (event) { + if (event.keyCode !== 13) return; + if ($(event.target).is(s.params.nextButton)) { + s.onClickNext(event); + if (s.isEnd) { + s.a11y.notify(s.params.lastSlideMessage); + } + else { + s.a11y.notify(s.params.nextSlideMessage); + } + } + else if ($(event.target).is(s.params.prevButton)) { + s.onClickPrev(event); + if (s.isBeginning) { + s.a11y.notify(s.params.firstSlideMessage); + } + else { + s.a11y.notify(s.params.prevSlideMessage); + } + } + if ($(event.target).is('.' + s.params.bulletClass)) { + $(event.target)[0].click(); + } + }, + + liveRegion: $('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'), + + notify: function (message) { + var notification = s.a11y.liveRegion; + if (notification.length === 0) return; + notification.html(''); + notification.html(message); + }, + init: function () { + // Setup accessibility + if (s.params.nextButton) { + var nextButton = $(s.params.nextButton); + s.a11y.makeFocusable(nextButton); + s.a11y.addRole(nextButton, 'button'); + s.a11y.addLabel(nextButton, s.params.nextSlideMessage); + } + if (s.params.prevButton) { + var prevButton = $(s.params.prevButton); + s.a11y.makeFocusable(prevButton); + s.a11y.addRole(prevButton, 'button'); + s.a11y.addLabel(prevButton, s.params.prevSlideMessage); + } + + $(s.container).append(s.a11y.liveRegion); + }, + initPagination: function () { + if (s.params.pagination && s.params.paginationClickable && s.bullets && s.bullets.length) { + s.bullets.each(function () { + var bullet = $(this); + s.a11y.makeFocusable(bullet); + s.a11y.addRole(bullet, 'button'); + s.a11y.addLabel(bullet, s.params.paginationBulletMessage.replace(/{{index}}/, bullet.index() + 1)); + }); + } + }, + destroy: function () { + if (s.a11y.liveRegion && s.a11y.liveRegion.length > 0) s.a11y.liveRegion.remove(); + } + }; + + + /*========================= + Init/Destroy + ===========================*/ + s.init = function () { + if (s.params.loop) s.createLoop(); + s.updateContainerSize(); + s.updateSlidesSize(); + s.updatePagination(); + if (s.params.scrollbar && s.scrollbar) { + s.scrollbar.set(); + if (s.params.scrollbarDraggable) { + s.scrollbar.enableDraggable(); + } + } + if (s.params.effect !== 'slide' && s.effects[s.params.effect]) { + if (!s.params.loop) s.updateProgress(); + s.effects[s.params.effect].setTranslate(); + } + if (s.params.loop) { + s.slideTo(s.params.initialSlide + s.loopedSlides, 0, s.params.runCallbacksOnInit); + } + else { + s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit); + if (s.params.initialSlide === 0) { + if (s.parallax && s.params.parallax) s.parallax.setTranslate(); + if (s.lazy && s.params.lazyLoading) { + s.lazy.load(); + s.lazy.initialImageLoaded = true; + } + } + } + s.attachEvents(); + if (s.params.observer && s.support.observer) { + s.initObservers(); + } + if (s.params.preloadImages && !s.params.lazyLoading) { + s.preloadImages(); + } + if (s.params.autoplay) { + s.startAutoplay(); + } + if (s.params.keyboardControl) { + if (s.enableKeyboardControl) s.enableKeyboardControl(); + } + if (s.params.mousewheelControl) { + if (s.enableMousewheelControl) s.enableMousewheelControl(); + } + if (s.params.hashnav) { + if (s.hashnav) s.hashnav.init(); + } + if (s.params.a11y && s.a11y) s.a11y.init(); + s.emit('onInit', s); + }; + + // Cleanup dynamic styles + s.cleanupStyles = function () { + // Container + s.container.removeClass(s.classNames.join(' ')).removeAttr('style'); + + // Wrapper + s.wrapper.removeAttr('style'); + + // Slides + if (s.slides && s.slides.length) { + s.slides + .removeClass([ + s.params.slideVisibleClass, + s.params.slideActiveClass, + s.params.slideNextClass, + s.params.slidePrevClass + ].join(' ')) + .removeAttr('style') + .removeAttr('data-swiper-column') + .removeAttr('data-swiper-row'); + } + + // Pagination/Bullets + if (s.paginationContainer && s.paginationContainer.length) { + s.paginationContainer.removeClass(s.params.paginationHiddenClass); + } + if (s.bullets && s.bullets.length) { + s.bullets.removeClass(s.params.bulletActiveClass); + } + + // Buttons + if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass); + if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass); + + // Scrollbar + if (s.params.scrollbar && s.scrollbar) { + if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style'); + if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style'); + } + }; + + // Destroy + s.destroy = function (deleteInstance, cleanupStyles) { + // Detach evebts + s.detachEvents(); + // Stop autoplay + s.stopAutoplay(); + // Disable draggable + if (s.params.scrollbar && s.scrollbar) { + if (s.params.scrollbarDraggable) { + s.scrollbar.disableDraggable(); + } + } + // Destroy loop + if (s.params.loop) { + s.destroyLoop(); + } + // Cleanup styles + if (cleanupStyles) { + s.cleanupStyles(); + } + // Disconnect observer + s.disconnectObservers(); + // Disable keyboard/mousewheel + if (s.params.keyboardControl) { + if (s.disableKeyboardControl) s.disableKeyboardControl(); + } + if (s.params.mousewheelControl) { + if (s.disableMousewheelControl) s.disableMousewheelControl(); + } + // Disable a11y + if (s.params.a11y && s.a11y) s.a11y.destroy(); + // Destroy callback + s.emit('onDestroy'); + // Delete instance + if (deleteInstance !== false) s = null; + }; + + s.init(); + + + + // Return swiper instance + return s; + }; + + + /*================================================== + Prototype + ====================================================*/ + Swiper.prototype = { + isSafari: (function () { + var ua = navigator.userAgent.toLowerCase(); + return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0); + })(), + isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent), + isArray: function (arr) { + return Object.prototype.toString.apply(arr) === '[object Array]'; + }, + /*================================================== + Browser + ====================================================*/ + browser: { + ie: window.navigator.pointerEnabled || window.navigator.msPointerEnabled, + ieTouch: (window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 1) || (window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 1) + }, + /*================================================== + Devices + ====================================================*/ + device: (function () { + var ua = navigator.userAgent; + var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); + var ipad = ua.match(/(iPad).*OS\s([\d_]+)/); + var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/); + var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/); + return { + ios: ipad || iphone || ipod, + android: android + }; + })(), + /*================================================== + Feature Detection + ====================================================*/ + support: { + touch : (window.Modernizr && Modernizr.touch === true) || (function () { + return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); + })(), + + transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () { + var div = document.createElement('div').style; + return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div); + })(), + + flexbox: (function () { + var div = document.createElement('div').style; + var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' '); + for (var i = 0; i < styles.length; i++) { + if (styles[i] in div) return true; + } + })(), + + observer: (function () { + return ('MutationObserver' in window || 'WebkitMutationObserver' in window); + })() + }, + /*================================================== + Plugins + ====================================================*/ + plugins: {} + }; + + + /*=========================== + Dom7 Library + ===========================*/ + var Dom7 = (function () { + var Dom7 = function (arr) { + var _this = this, i = 0; + // Create array-like object + for (i = 0; i < arr.length; i++) { + _this[i] = arr[i]; + } + _this.length = arr.length; + // Return collection with methods + return this; + }; + var $ = function (selector, context) { + var arr = [], i = 0; + if (selector && !context) { + if (selector instanceof Dom7) { + return selector; + } + } + if (selector) { + // String + if (typeof selector === 'string') { + var els, tempParent, html = selector.trim(); + if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) { + var toCreate = 'div'; + if (html.indexOf('<li') === 0) toCreate = 'ul'; + if (html.indexOf('<tr') === 0) toCreate = 'tbody'; + if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr'; + if (html.indexOf('<tbody') === 0) toCreate = 'table'; + if (html.indexOf('<option') === 0) toCreate = 'select'; + tempParent = document.createElement(toCreate); + tempParent.innerHTML = selector; + for (i = 0; i < tempParent.childNodes.length; i++) { + arr.push(tempParent.childNodes[i]); + } + } + else { + if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) { + // Pure ID selector + els = [document.getElementById(selector.split('#')[1])]; + } + else { + // Other selectors + els = (context || document).querySelectorAll(selector); + } + for (i = 0; i < els.length; i++) { + if (els[i]) arr.push(els[i]); + } + } + } + // Node/element + else if (selector.nodeType || selector === window || selector === document) { + arr.push(selector); + } + //Array of elements or instance of Dom + else if (selector.length > 0 && selector[0].nodeType) { + for (i = 0; i < selector.length; i++) { + arr.push(selector[i]); + } + } + } + return new Dom7(arr); + }; + Dom7.prototype = { + // Classes and attriutes + addClass: function (className) { + if (typeof className === 'undefined') { + return this; + } + var classes = className.split(' '); + for (var i = 0; i < classes.length; i++) { + for (var j = 0; j < this.length; j++) { + this[j].classList.add(classes[i]); + } + } + return this; + }, + removeClass: function (className) { + var classes = className.split(' '); + for (var i = 0; i < classes.length; i++) { + for (var j = 0; j < this.length; j++) { + this[j].classList.remove(classes[i]); + } + } + return this; + }, + hasClass: function (className) { + if (!this[0]) return false; + else return this[0].classList.contains(className); + }, + toggleClass: function (className) { + var classes = className.split(' '); + for (var i = 0; i < classes.length; i++) { + for (var j = 0; j < this.length; j++) { + this[j].classList.toggle(classes[i]); + } + } + return this; + }, + attr: function (attrs, value) { + if (arguments.length === 1 && typeof attrs === 'string') { + // Get attr + if (this[0]) return this[0].getAttribute(attrs); + else return undefined; + } + else { + // Set attrs + for (var i = 0; i < this.length; i++) { + if (arguments.length === 2) { + // String + this[i].setAttribute(attrs, value); + } + else { + // Object + for (var attrName in attrs) { + this[i][attrName] = attrs[attrName]; + this[i].setAttribute(attrName, attrs[attrName]); + } + } + } + return this; + } + }, + removeAttr: function (attr) { + for (var i = 0; i < this.length; i++) { + this[i].removeAttribute(attr); + } + return this; + }, + data: function (key, value) { + if (typeof value === 'undefined') { + // Get value + if (this[0]) { + var dataKey = this[0].getAttribute('data-' + key); + if (dataKey) return dataKey; + else if (this[0].dom7ElementDataStorage && (key in this[0].dom7ElementDataStorage)) return this[0].dom7ElementDataStorage[key]; + else return undefined; + } + else return undefined; + } + else { + // Set value + for (var i = 0; i < this.length; i++) { + var el = this[i]; + if (!el.dom7ElementDataStorage) el.dom7ElementDataStorage = {}; + el.dom7ElementDataStorage[key] = value; + } + return this; + } + }, + // Transforms + transform : function (transform) { + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform; + } + return this; + }, + transition: function (duration) { + if (typeof duration !== 'string') { + duration = duration + 'ms'; + } + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration; + } + return this; + }, + //Events + on: function (eventName, targetSelector, listener, capture) { + function handleLiveEvent(e) { + var target = e.target; + if ($(target).is(targetSelector)) listener.call(target, e); + else { + var parents = $(target).parents(); + for (var k = 0; k < parents.length; k++) { + if ($(parents[k]).is(targetSelector)) listener.call(parents[k], e); + } + } + } + var events = eventName.split(' '); + var i, j; + for (i = 0; i < this.length; i++) { + if (typeof targetSelector === 'function' || targetSelector === false) { + // Usual events + if (typeof targetSelector === 'function') { + listener = arguments[1]; + capture = arguments[2] || false; + } + for (j = 0; j < events.length; j++) { + this[i].addEventListener(events[j], listener, capture); + } + } + else { + //Live events + for (j = 0; j < events.length; j++) { + if (!this[i].dom7LiveListeners) this[i].dom7LiveListeners = []; + this[i].dom7LiveListeners.push({listener: listener, liveListener: handleLiveEvent}); + this[i].addEventListener(events[j], handleLiveEvent, capture); + } + } + } + + return this; + }, + off: function (eventName, targetSelector, listener, capture) { + var events = eventName.split(' '); + for (var i = 0; i < events.length; i++) { + for (var j = 0; j < this.length; j++) { + if (typeof targetSelector === 'function' || targetSelector === false) { + // Usual events + if (typeof targetSelector === 'function') { + listener = arguments[1]; + capture = arguments[2] || false; + } + this[j].removeEventListener(events[i], listener, capture); + } + else { + // Live event + if (this[j].dom7LiveListeners) { + for (var k = 0; k < this[j].dom7LiveListeners.length; k++) { + if (this[j].dom7LiveListeners[k].listener === listener) { + this[j].removeEventListener(events[i], this[j].dom7LiveListeners[k].liveListener, capture); + } + } + } + } + } + } + return this; + }, + once: function (eventName, targetSelector, listener, capture) { + var dom = this; + if (typeof targetSelector === 'function') { + targetSelector = false; + listener = arguments[1]; + capture = arguments[2]; + } + function proxy(e) { + listener(e); + dom.off(eventName, targetSelector, proxy, capture); + } + dom.on(eventName, targetSelector, proxy, capture); + }, + trigger: function (eventName, eventData) { + for (var i = 0; i < this.length; i++) { + var evt; + try { + evt = new window.CustomEvent(eventName, {detail: eventData, bubbles: true, cancelable: true}); + } + catch (e) { + evt = document.createEvent('Event'); + evt.initEvent(eventName, true, true); + evt.detail = eventData; + } + this[i].dispatchEvent(evt); + } + return this; + }, + transitionEnd: function (callback) { + var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'], + i, j, dom = this; + function fireCallBack(e) { + /*jshint validthis:true */ + if (e.target !== this) return; + callback.call(this, e); + for (i = 0; i < events.length; i++) { + dom.off(events[i], fireCallBack); + } + } + if (callback) { + for (i = 0; i < events.length; i++) { + dom.on(events[i], fireCallBack); + } + } + return this; + }, + // Sizing/Styles + width: function () { + if (this[0] === window) { + return window.innerWidth; + } + else { + if (this.length > 0) { + return parseFloat(this.css('width')); + } + else { + return null; + } + } + }, + outerWidth: function (includeMargins) { + if (this.length > 0) { + if (includeMargins) + return this[0].offsetWidth + parseFloat(this.css('margin-right')) + parseFloat(this.css('margin-left')); + else + return this[0].offsetWidth; + } + else return null; + }, + height: function () { + if (this[0] === window) { + return window.innerHeight; + } + else { + if (this.length > 0) { + return parseFloat(this.css('height')); + } + else { + return null; + } + } + }, + outerHeight: function (includeMargins) { + if (this.length > 0) { + if (includeMargins) + return this[0].offsetHeight + parseFloat(this.css('margin-top')) + parseFloat(this.css('margin-bottom')); + else + return this[0].offsetHeight; + } + else return null; + }, + offset: function () { + if (this.length > 0) { + var el = this[0]; + var box = el.getBoundingClientRect(); + var body = document.body; + var clientTop = el.clientTop || body.clientTop || 0; + var clientLeft = el.clientLeft || body.clientLeft || 0; + var scrollTop = window.pageYOffset || el.scrollTop; + var scrollLeft = window.pageXOffset || el.scrollLeft; + return { + top: box.top + scrollTop - clientTop, + left: box.left + scrollLeft - clientLeft + }; + } + else { + return null; + } + }, + css: function (props, value) { + var i; + if (arguments.length === 1) { + if (typeof props === 'string') { + if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props); + } + else { + for (i = 0; i < this.length; i++) { + for (var prop in props) { + this[i].style[prop] = props[prop]; + } + } + return this; + } + } + if (arguments.length === 2 && typeof props === 'string') { + for (i = 0; i < this.length; i++) { + this[i].style[props] = value; + } + return this; + } + return this; + }, + + //Dom manipulation + each: function (callback) { + for (var i = 0; i < this.length; i++) { + callback.call(this[i], i, this[i]); + } + return this; + }, + html: function (html) { + if (typeof html === 'undefined') { + return this[0] ? this[0].innerHTML : undefined; + } + else { + for (var i = 0; i < this.length; i++) { + this[i].innerHTML = html; + } + return this; + } + }, + is: function (selector) { + if (!this[0]) return false; + var compareWith, i; + if (typeof selector === 'string') { + var el = this[0]; + if (el === document) return selector === document; + if (el === window) return selector === window; + + if (el.matches) return el.matches(selector); + else if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector); + else if (el.mozMatchesSelector) return el.mozMatchesSelector(selector); + else if (el.msMatchesSelector) return el.msMatchesSelector(selector); + else { + compareWith = $(selector); + for (i = 0; i < compareWith.length; i++) { + if (compareWith[i] === this[0]) return true; + } + return false; + } + } + else if (selector === document) return this[0] === document; + else if (selector === window) return this[0] === window; + else { + if (selector.nodeType || selector instanceof Dom7) { + compareWith = selector.nodeType ? [selector] : selector; + for (i = 0; i < compareWith.length; i++) { + if (compareWith[i] === this[0]) return true; + } + return false; + } + return false; + } + + }, + index: function () { + if (this[0]) { + var child = this[0]; + var i = 0; + while ((child = child.previousSibling) !== null) { + if (child.nodeType === 1) i++; + } + return i; + } + else return undefined; + }, + eq: function (index) { + if (typeof index === 'undefined') return this; + var length = this.length; + var returnIndex; + if (index > length - 1) { + return new Dom7([]); + } + if (index < 0) { + returnIndex = length + index; + if (returnIndex < 0) return new Dom7([]); + else return new Dom7([this[returnIndex]]); + } + return new Dom7([this[index]]); + }, + append: function (newChild) { + var i, j; + for (i = 0; i < this.length; i++) { + if (typeof newChild === 'string') { + var tempDiv = document.createElement('div'); + tempDiv.innerHTML = newChild; + while (tempDiv.firstChild) { + this[i].appendChild(tempDiv.firstChild); + } + } + else if (newChild instanceof Dom7) { + for (j = 0; j < newChild.length; j++) { + this[i].appendChild(newChild[j]); + } + } + else { + this[i].appendChild(newChild); + } + } + return this; + }, + prepend: function (newChild) { + var i, j; + for (i = 0; i < this.length; i++) { + if (typeof newChild === 'string') { + var tempDiv = document.createElement('div'); + tempDiv.innerHTML = newChild; + for (j = tempDiv.childNodes.length - 1; j >= 0; j--) { + this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]); + } + // this[i].insertAdjacentHTML('afterbegin', newChild); + } + else if (newChild instanceof Dom7) { + for (j = 0; j < newChild.length; j++) { + this[i].insertBefore(newChild[j], this[i].childNodes[0]); + } + } + else { + this[i].insertBefore(newChild, this[i].childNodes[0]); + } + } + return this; + }, + insertBefore: function (selector) { + var before = $(selector); + for (var i = 0; i < this.length; i++) { + if (before.length === 1) { + before[0].parentNode.insertBefore(this[i], before[0]); + } + else if (before.length > 1) { + for (var j = 0; j < before.length; j++) { + before[j].parentNode.insertBefore(this[i].cloneNode(true), before[j]); + } + } + } + }, + insertAfter: function (selector) { + var after = $(selector); + for (var i = 0; i < this.length; i++) { + if (after.length === 1) { + after[0].parentNode.insertBefore(this[i], after[0].nextSibling); + } + else if (after.length > 1) { + for (var j = 0; j < after.length; j++) { + after[j].parentNode.insertBefore(this[i].cloneNode(true), after[j].nextSibling); + } + } + } + }, + next: function (selector) { + if (this.length > 0) { + if (selector) { + if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) return new Dom7([this[0].nextElementSibling]); + else return new Dom7([]); + } + else { + if (this[0].nextElementSibling) return new Dom7([this[0].nextElementSibling]); + else return new Dom7([]); + } + } + else return new Dom7([]); + }, + nextAll: function (selector) { + var nextEls = []; + var el = this[0]; + if (!el) return new Dom7([]); + while (el.nextElementSibling) { + var next = el.nextElementSibling; + if (selector) { + if($(next).is(selector)) nextEls.push(next); + } + else nextEls.push(next); + el = next; + } + return new Dom7(nextEls); + }, + prev: function (selector) { + if (this.length > 0) { + if (selector) { + if (this[0].previousElementSibling && $(this[0].previousElementSibling).is(selector)) return new Dom7([this[0].previousElementSibling]); + else return new Dom7([]); + } + else { + if (this[0].previousElementSibling) return new Dom7([this[0].previousElementSibling]); + else return new Dom7([]); + } + } + else return new Dom7([]); + }, + prevAll: function (selector) { + var prevEls = []; + var el = this[0]; + if (!el) return new Dom7([]); + while (el.previousElementSibling) { + var prev = el.previousElementSibling; + if (selector) { + if($(prev).is(selector)) prevEls.push(prev); + } + else prevEls.push(prev); + el = prev; + } + return new Dom7(prevEls); + }, + parent: function (selector) { + var parents = []; + for (var i = 0; i < this.length; i++) { + if (selector) { + if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode); + } + else { + parents.push(this[i].parentNode); + } + } + return $($.unique(parents)); + }, + parents: function (selector) { + var parents = []; + for (var i = 0; i < this.length; i++) { + var parent = this[i].parentNode; + while (parent) { + if (selector) { + if ($(parent).is(selector)) parents.push(parent); + } + else { + parents.push(parent); + } + parent = parent.parentNode; + } + } + return $($.unique(parents)); + }, + find : function (selector) { + var foundElements = []; + for (var i = 0; i < this.length; i++) { + var found = this[i].querySelectorAll(selector); + for (var j = 0; j < found.length; j++) { + foundElements.push(found[j]); + } + } + return new Dom7(foundElements); + }, + children: function (selector) { + var children = []; + for (var i = 0; i < this.length; i++) { + var childNodes = this[i].childNodes; + + for (var j = 0; j < childNodes.length; j++) { + if (!selector) { + if (childNodes[j].nodeType === 1) children.push(childNodes[j]); + } + else { + if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) children.push(childNodes[j]); + } + } + } + return new Dom7($.unique(children)); + }, + remove: function () { + for (var i = 0; i < this.length; i++) { + if (this[i].parentNode) this[i].parentNode.removeChild(this[i]); + } + return this; + }, + add: function () { + var dom = this; + var i, j; + for (i = 0; i < arguments.length; i++) { + var toAdd = $(arguments[i]); + for (j = 0; j < toAdd.length; j++) { + dom[dom.length] = toAdd[j]; + dom.length++; + } + } + return dom; + } + }; + $.fn = Dom7.prototype; + $.unique = function (arr) { + var unique = []; + for (var i = 0; i < arr.length; i++) { + if (unique.indexOf(arr[i]) === -1) unique.push(arr[i]); + } + return unique; + }; + + return $; + })(); + + + /*=========================== + Get Dom libraries + ===========================*/ + var swiperDomPlugins = ['jQuery', 'Zepto', 'Dom7']; + for (var i = 0; i < swiperDomPlugins.length; i++) { + if (window[swiperDomPlugins[i]]) { + addLibraryPlugin(window[swiperDomPlugins[i]]); + } + } + // Required DOM Plugins + var domLib; + if (typeof Dom7 === 'undefined') { + domLib = window.Dom7 || window.Zepto || window.jQuery; + } + else { + domLib = Dom7; + } + + /*=========================== + Add .swiper plugin from Dom libraries + ===========================*/ + function addLibraryPlugin(lib) { + lib.fn.swiper = function (params) { + var firstInstance; + lib(this).each(function () { + var s = new Swiper(this, params); + if (!firstInstance) firstInstance = s; + }); + return firstInstance; + }; + } + + if (domLib) { + if (!('transitionEnd' in domLib.fn)) { + domLib.fn.transitionEnd = function (callback) { + var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'], + i, j, dom = this; + function fireCallBack(e) { + /*jshint validthis:true */ + if (e.target !== this) return; + callback.call(this, e); + for (i = 0; i < events.length; i++) { + dom.off(events[i], fireCallBack); + } + } + if (callback) { + for (i = 0; i < events.length; i++) { + dom.on(events[i], fireCallBack); + } + } + return this; + }; + } + if (!('transform' in domLib.fn)) { + domLib.fn.transform = function (transform) { + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform; + } + return this; + }; + } + if (!('transition' in domLib.fn)) { + domLib.fn.transition = function (duration) { + if (typeof duration !== 'string') { + duration = duration + 'ms'; + } + for (var i = 0; i < this.length; i++) { + var elStyle = this[i].style; + elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration; + } + return this; + }; + } + } + + ionic.views.Swiper = Swiper; +})(); + (function(ionic) { 'use strict'; diff --git a/www/lib/ionic/js/ionic.material.js b/www/lib/ionic/js/ionic.material.js new file mode 100644 index 0000000000000000000000000000000000000000..cc39d3b6818aa3aea7564f78d2b5f3c3c6ad0e9e --- /dev/null +++ b/www/lib/ionic/js/ionic.material.js @@ -0,0 +1,957 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory((function webpackLoadOptionalExternalModule() { try { return require("angular"); } catch(e) {} }())); + else if(typeof define === 'function' && define.amd) + define(["angular"], factory); + else if(typeof exports === 'object') + exports["ionicMaterial"] = factory((function webpackLoadOptionalExternalModule() { try { return require("angular"); } catch(e) {} }())); + else + root["ionicMaterial"] = factory(root["angular"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { + + /** + * Ionic Material + * "Bundle Index" / "Entryfile" + * https://github.com/zachsoft/ionic-material + * + * Recommended: use a compiled version, especially in production! + */ + + 'use strict'; + + module.exports = (function(){ + + var angular; + + try { + angular = __webpack_require__(1); + } catch(err){ } + + if(!angular || !angular.version){ + /*global window: true*/ + angular = window.angular; + /*global window: false*/ + } + + if(!angular || !angular.version){ + throw new Error('ionic-material could not load angular module :('); + } + + // set up angular module + var app = angular.module('ionic-material', ['ionic']); + + // Import Dependencies + __webpack_require__(2)(app); + __webpack_require__(3)(app); + + return 'ionic-material'; + })(); + + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + if(typeof __WEBPACK_EXTERNAL_MODULE_1__ === 'undefined') {var e = new Error("Cannot find module \"angular\""); e.code = 'MODULE_NOT_FOUND'; throw e;} + module.exports = __WEBPACK_EXTERNAL_MODULE_1__; + +/***/ }, +/* 2 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + /*! + * Fork by Zach Fitzgerald and other contributors of Ionic Material + * + * Waves v0.5.4 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + * + */ + module.exports = function (angularApp) { + + angularApp.factory('ionicMaterialInk', ink); + + function ink (){ + /*global document*/ + var Ink = Ink || {}; + + // all DOM nodes + var $$; + + // phantomJS throws an error when you try to use document.querySelectorAll.bind + if(document && document.querySelectorAll && document.querySelectorAll.bind){ + try{ + // all DOM nodes + $$ = document.querySelectorAll.bind(document); + + } catch(e){} + } else if (window && window.angular && window.angular.element) { + // we can use angular.element instead + $$ = window.angular.element; + } else { + + + /** + * mout.js 0.11.0 bind and slice polyfills (substitutes?) + * TODO: pull out mout.js bind and slice molyfills and inject into material.ink + */ + + /** + * Create slice of source array or array-like object + */ + var slicePolyfill = function moutslicePolyfill(arr, start, end){ + var len = arr.length; + /*jshint eqnull:true */ + if (start == null) { + start = 0; + } else if (start < 0) { + start = Math.max(len + start, 0); + } else { + start = Math.min(start, len); + } + + + if (end == null) { + + end = len; + } else if (end < 0) { + end = Math.max(len + end, 0); + } else { + end = Math.min(end, len); + } + + var result = []; + while (start < end) { + result.push(arr[start++]); + } + + return result; + }; + + + + /** + * Return a function that will execute in the given context, optionally adding any additional supplied parameters to the beginning of the arguments collection. + * @param {Function} fn Function. + * @param {object} context Execution context. + * @param {rest} args Arguments (0...n arguments). + * @return {Function} Wrapped Function. + */ + var bindPolyfill = function moutBind(fn, context, args){ + var argsArr = slicePolyfill(arguments, 2); //curried args + return function(){ + return fn.apply(context, argsArr.concat(slicePolyfill(arguments))); + }; + }; + + $$ = bindPolyfill(document.querySelectorAll, document); + /*jshint ignore:end */ + } + + if (!$$){ + throw new Error('ionic material ink module could not create reference of DOM nodes'); + } + + // Find exact position of element + function isWindow(obj) { + return obj !== null && obj === obj.window; + } + + function getWindow(elem) { + return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView; + } + + function offset(elem) { + var docElem, win, + box = { + top: 0, + left: 0 + }, + doc = elem && elem.ownerDocument; + + docElem = doc.documentElement; + + if (typeof elem.getBoundingClientRect !== typeof undefined) { + box = elem.getBoundingClientRect(); + } + win = getWindow(doc); + return { + top: box.top + win.pageYOffset - docElem.clientTop, + left: box.left + win.pageXOffset - docElem.clientLeft + }; + } + + function hexToRgb(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; + } + + function convertStyle(obj) { + var style = ''; + + for (var a in obj) { + if (obj.hasOwnProperty(a)) { + style += (a + ':' + obj[a] + ';'); + } + } + + return style; + } + + var Effect = { + + // Effect delay + duration: 500, + + show: function(e) { + + // Disable right click + if (e.button === 2) { + return false; + } + + var el = this; + + // Create ripple + var ripple = document.createElement('div'); + var customColor = this.dataset.inkColor; + var customOpacity = this.dataset.inkOpacity; + var hasCustomRipple = customColor || customOpacity; + ripple.className = 'ink-ripple'; + el.appendChild(ripple); + + // Get click coordinate and element witdh + var pos = offset(el); + var relativeY = (e.pageY - pos.top); + var relativeX = (e.pageX - pos.left); + var scale = 'scale(' + ((el.clientWidth / 100) * 2.5) + ')'; + + // Support for touch devices + if ('touches' in e) { + relativeY = (e.touches[0].pageY - pos.top); + relativeX = (e.touches[0].pageX - pos.left); + } + + // Attach data to element + ripple.setAttribute('data-hold', Date.now()); + ripple.setAttribute('data-scale', scale); + ripple.setAttribute('data-x', relativeX); + ripple.setAttribute('data-y', relativeY); + + // Set ripple position + var rippleStyle = { + 'top': relativeY + 'px', + 'left': relativeX + 'px' + }; + + ripple.className = ripple.className + ' ink-notransition'; + + if (hasCustomRipple) { + var colorRgb; + if (customColor) { + var fromHex = hexToRgb(customColor); + colorRgb = fromHex.r + ',' + fromHex.g + ',' + fromHex.b; + } else { + colorRgb = '0,0,0'; + } + if (!customOpacity) { + customOpacity = 0.2; + } + var bg = 'rgba(' + colorRgb + ',' + customOpacity + ')'; + rippleStyle['background-color'] = bg; + } + + ripple.setAttribute('style', convertStyle(rippleStyle)); + ripple.className = ripple.className.replace('ink-notransition', ''); + + // Scale the ripple + rippleStyle['-webkit-transform'] = scale; + rippleStyle['-moz-transform'] = scale; + rippleStyle['-ms-transform'] = scale; + rippleStyle['-o-transform'] = scale; + rippleStyle.transform = scale; + rippleStyle.opacity = '1'; + + rippleStyle['-webkit-transition-duration'] = Effect.duration + 'ms'; + rippleStyle['-moz-transition-duration'] = Effect.duration + 'ms'; + rippleStyle['-o-transition-duration'] = Effect.duration + 'ms'; + rippleStyle['transition-duration'] = Effect.duration + 'ms'; + + ripple.setAttribute('style', convertStyle(rippleStyle)); + }, + + hide: function() { + + var el = this; + + var width = el.clientWidth * 1.4; + + // Get first ripple + var ripple = null; + + var childrenLength = el.children.length; + + for (var a = 0; a < childrenLength; a++) { + if (el.children[a].className.indexOf('ink-ripple') !== -1) { + ripple = el.children[a]; + continue; + } + } + + if (!ripple) { + return false; + } + + var relativeX = ripple.getAttribute('data-x'); + var relativeY = ripple.getAttribute('data-y'); + var scale = ripple.getAttribute('data-scale'); + + // Get delay beetween mousedown and mouse leave + var diff = Date.now() - Number(ripple.getAttribute('data-hold')); + var delay = 500 - diff; + + if (delay < 0) { + delay = 0; + } + + // Fade out ripple after delay + setTimeout(function() { + + var style = { + 'top': relativeY + 'px', + 'left': relativeX + 'px', + 'opacity': '0', + + // Duration + '-webkit-transition-duration': Effect.duration + 'ms', + '-moz-transition-duration': Effect.duration + 'ms', + '-o-transition-duration': Effect.duration + 'ms', + 'transition-duration': Effect.duration + 'ms', + '-webkit-transform': scale, + '-moz-transform': scale, + '-ms-transform': scale, + '-o-transform': scale, + 'transform': scale, + }; + + ripple.setAttribute('style', convertStyle(style)); + + setTimeout(function() { + try { + el.removeChild(ripple); + } catch (e) { + return false; + } + }, Effect.duration); + }, delay); + }, + + // Little hack to make <input> can perform ink effect + wrapInput: function(elements) { + + for (var a = 0; a < elements.length; a++) { + + var el = elements[a]; + + if (el.tagName.toLowerCase() === 'input') { + + var parent = el.parentNode; + + // If input already have parent just pass through + if (parent.tagName.toLowerCase() === 'i' && + parent.className.indexOf('ink') !== -1 && + parent.className.indexOf('tab-item') !== -1 && + parent.className.indexOf('button-fab') !== -1 && + parent.className.indexOf('button-raised') !== -1 && + parent.className.indexOf('button-flat') !== -1 && + parent.className.indexOf('button-clear') !== -1 && + parent.className.indexOf('button') !== -1 && + parent.className.indexOf('item') !== -1) { + return false; + } + + // Put element class and style to the specified parent + var wrapper = document.createElement('i'); + wrapper.className = el.className + ' ink-input-wrapper'; + + var elementStyle = el.getAttribute('style'); + + if (!elementStyle) { + elementStyle = ''; + } + + wrapper.setAttribute('style', elementStyle); + + el.className = 'ink-button-input'; + el.removeAttribute('style'); + + // Put element as child + parent.replaceChild(wrapper, el); + wrapper.appendChild(el); + } + } + } + }; + + Ink.displayEffect = function(options) { + options = options || {}; + + if ('duration' in options) { + Effect.duration = options.duration; + } + + //Wrap input inside <i> tag + var selectors = '.ink,.tab-item,.button-fab,.button-raised,.button-flat,.button-clear,a.item,.popup .button'; + Effect.wrapInput($$(selectors)); + + Array.prototype.forEach.call($$(selectors), function(i) { + if ('ontouchstart' in window) { + i.addEventListener('touchstart', Effect.show, false); + i.addEventListener('touchend', Effect.hide, false); + i.addEventListener('touchcancel', Effect.hide, false); + } else { + i.addEventListener('mousedown', Effect.show, false); + i.addEventListener('mouseup', Effect.hide, false); + i.addEventListener('mouseleave', Effect.hide, false); + } + }); + }; + + return Ink; + } + + ink.inject = []; + }; + + +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = function(angularApp) { + angularApp.factory('ionicMaterialMotion', Motion); + + function Motion() { + /*global document, window*/ + + 'use strict'; + + /*============================================================================*/ + /* HELPERS (non-exports) + /=============================================================================* + / Abstract common lookups and manipulations in case better alternatives + / arise or future cross-platform differences warrant separate handling + /=============================================================================*/ + + function getViewportHeight() { + return window.innerHeight; + } + + function getBoundingClientRect(domNode) { + return domNode.getBoundingClientRect; + } + + function showNotAnimatedElements(elements, total) { + // Load the elements without effect + for (var i = 0; i < total; i++) { + var child = elements[i]; + child.className += ' in'; + child.className += ' done'; + } + } + + + + /*============================================================================*/ + /* MOTION (EXPORT) + /=============================================================================* + / Animation methods for the library + /=============================================================================*/ + + var motion = { + blinds: blinds, + fadeSlideIn: fadeSlideIn, + fadeSlideInRight: fadeSlideInRight, + panInLeft: panInLeft, + pushDown: pushDown, + ripple: ripple, + slideUp: slideUp + }; + + function blinds(options) { + + // Declare our defaults + var defaults = { + finishDelayThrottle: 2, + finishSpeedPercent: 0.5, + leftOffsetPercentage: 0.8, + selector: '.animate-blinds .item', + startVelocity: 1100 + }; + + // Apply defaults if properties are not passed + if (typeof options === 'undefined') { + options = {}; + } + + options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle; + options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent; + options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage; + options.startVelocity = options.startVelocity || defaults.startVelocity; + + if (typeof options.selector == 'undefined') { + options.selector = defaults.selector; + } + + // Fail early & silently log + var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === ''; + + if (isInvalidSelector) { + console.log('invalid blinds selector'); + return false; + } + + var animateBlindsDom = document.querySelectorAll(options.selector); + var elementsCount = animateBlindsDom.length; + var elementAnimationCount = 0; + + // Count the elements within the starting viewport so we're not exacting + // more effort than required... + // + // We use css visiblity: hidden instead of display: none so the elements + // maintain their DOM flow + + var viewportHeight = getViewportHeight(); + for (var i = 0; i < elementsCount; i++) { + if (animateBlindsDom[i].offsetTop < viewportHeight) { + elementAnimationCount += 1; + continue; + } + break; + } + + // Sequentially animate with a delay based on proximity + var speed = options.startVelocity; + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateBlindsDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delay = parseFloat(offset / speed).toFixed(2); + child.style.webkitTransitionDelay = delay + "s"; + child.style.transitionDelay = delay + "s"; + child.className += ' in'; + } + + // When we're done animating, switch the class to 'done' + setTimeout(function() { + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateBlindsDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delay = parseFloat(offset / speed / options.finishDelayThrottle).toFixed(2); + //child.querySelector('img').style.webkitTransitionDelay = delay + "s"; + //child.querySelector('img').style.transitionDelay = delay + "s"; + //child.querySelector('img').className += ' in'; + animateBlindsDom[i].className += ' done'; + } + + }, speed * options.finishSpeedPercent); + + // Load the elements without effect + showNotAnimatedElements(animateBlindsDom, elementsCount); + } + + function fadeSlideIn(options) { + + // Declare our defaults + var defaults = { + finishDelayThrottle: 2, + finishSpeedPercent: 0.72, + leftOffsetPercentage: 0.8, + selector: '.animate-fade-slide-in .item', + startVelocity: 1100 + }; + + // Apply defaults if properties are not passed + if (typeof options === 'undefined') { + options = {}; + } + + options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle; + options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent; + options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage; + options.startVelocity = options.startVelocity || defaults.startVelocity; + + if (typeof options.selector == 'undefined') { + options.selector = defaults.selector; + } + + // Fail early & silently log + var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === ''; + + if (isInvalidSelector) { + console.log('invalid fadeSlideIn selector'); + return false; + } + + var animateFadeSlideInDom = document.querySelectorAll(options.selector); + var elementsCount = animateFadeSlideInDom.length; + var elementAnimationCount = 0; + + // Count the elements within the starting viewport so we're not exacting + // more effort than required... + // + // We use css visiblity: hidden instead of display: none so the elements + // maintain their DOM flow + + var viewportHeight = getViewportHeight(); + for (var i = 0; i < elementsCount; i++) { + if (animateFadeSlideInDom[i].offsetTop < viewportHeight) { + elementAnimationCount += 1; + continue; + } + break; + } + + // Sequentially animate with a delay based on proximity + var speed = options.startVelocity; + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateFadeSlideInDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delay = parseFloat(offset / speed).toFixed(2); + child.style.webkitTransitionDelay = delay + "s"; + child.style.transitionDelay = delay + "s"; + child.className += ' in'; + } + + // When we're done animating, switch the class to 'done' + setTimeout(function() { + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateFadeSlideInDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delayValue = offset / speed / options.finishDelayThrottle; + var delay = parseFloat(delayValue).toFixed(2); + } + animateFadeSlideInDom[0].className += ' done'; + + }, speed * options.finishSpeedPercent); + + // Load the elements without effect + showNotAnimatedElements(animateFadeSlideInDom, elementsCount); + } + + function fadeSlideInRight(options) { + + // Declare our defaults + var defaults = { + finishDelayThrottle: 2, + finishSpeedPercent: 0.72, + leftOffsetPercentage: 0.8, + selector: '.animate-fade-slide-in-right .item', + startVelocity: 1100 + }; + + // Apply defaults if properties are not passed + if (typeof options === 'undefined') { + options = {}; + } + + options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle; + options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent; + options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage; + options.startVelocity = options.startVelocity || defaults.startVelocity; + + if (typeof options.selector == 'undefined') { + options.selector = defaults.selector; + } + + // Fail early & silently log + var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === ''; + + if (isInvalidSelector) { + console.log('invalid fadeSlideInRight selector'); + return false; + } + + var animateSlideInRightDom = document.querySelectorAll(options.selector); + var elementsCount = animateSlideInRightDom.length; + var elementAnimationCount = 0; + + // Count the elements within the starting viewport so we're not + // exacting more effort than required... + // + // We use css visiblity: hidden instead of display: none so the + // elements maintain their DOM flow + + var viewportHeight = getViewportHeight(); + for (var i = 0; i < elementsCount; i++) { + if (animateSlideInRightDom[i].offsetTop < viewportHeight) { + elementAnimationCount += 1; + continue; + } + break; + } + + // Sequentially animate with a delay based on proximity + var speed = options.startVelocity; + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateSlideInRightDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delay = parseFloat(offset / speed).toFixed(2); + child.style.webkitTransitionDelay = delay + "s"; + child.style.transitionDelay = delay + "s"; + child.className += ' in'; + } + + // When we're done animating, switch the class to 'done' + setTimeout(function() { + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateSlideInRightDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delayValue = offset / speed / options.finishDelayThrottle; + var delay = parseFloat(delayValue).toFixed(2); + } + animateSlideInRightDom[0].className += ' done'; + + }, speed * options.finishSpeedPercent); + + // Load the elements without effect + showNotAnimatedElements(animateSlideInRightDom, elementsCount); + + } + + function ripple(options) { + + // Declare our defaults + var defaults = { + finishDelayThrottle: 2, + finishSpeedPercent: 0.72, + leftOffsetPercentage: 0.8, + selector: '.animate-ripple .item', + startVelocity: 1100 + }; + + // Apply defaults if properties are not passed + if (typeof options === 'undefined') { + options = {}; + } + + options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle; + options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent; + options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage; + options.startVelocity = options.startVelocity || defaults.startVelocity; + + if (typeof options.selector == 'undefined') { + options.selector = defaults.selector; + } + + // Fail early & silently log + var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === ''; + + if (isInvalidSelector) { + console.log('invalid ripple selector'); + return false; + } + + var animateRippleDom = document.querySelectorAll(options.selector); + var elementsCount = animateRippleDom.length; + var elementAnimationCount = 0; + + // Count the elements within the starting viewport so we're not + // exacting more effort than required... + // + // We use css visiblity: hidden instead of display: none so the + // elements maintain their DOM flow + + var viewportHeight = getViewportHeight(); + for (var i = 0; i < animateRippleDom.length; i++) { + if (animateRippleDom[i].offsetTop < viewportHeight) { + elementAnimationCount += 1; + continue; + } + break; + } + + // Sequentially animate with a delay based on proximity + var speed = options.startVelocity; + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateRippleDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delay = parseFloat(offset / speed).toFixed(2); + child.style.webkitTransitionDelay = delay + "s"; + child.style.transitionDelay = delay + "s"; + child.className += ' in'; + } + + // When we're done animating, switch the class to 'done' + setTimeout(function() { + for (var i = 0; i < elementAnimationCount; i++) { + var child = animateRippleDom[i]; + var childOffset = child.getBoundingClientRect(); + var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top; + var delayValue = offset / speed / options.finishDelayThrottle; + var delay = parseFloat(delayValue).toFixed(2); + } + animateRippleDom[0].className += ' done'; + + }, speed * options.finishSpeedPercent); + + // Load the elements without effect + showNotAnimatedElements(animateRippleDom, elementsCount); + } + + function panInLeft(options) { + + // We have a single option, so it may be passed as a string or property + if (typeof options === 'string') { + options = { + selector: options + }; + } + + // Fail early & silently log + var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === ''; + + if (isInvalidSelector) { + console.log('invalid pushDown selector'); + return false; + } + + var animatePanInLeftDom = document.querySelectorAll(options.selector); + var elementAnimationCount = animatePanInLeftDom.length; + for (var i = 0; i < elementAnimationCount; i++) { + var element = animatePanInLeftDom[i]; + var classNameToRemove = 'animate-pan-in-left'; + var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove); + element.className = element.className.substr(0, indexOfClassNameToRemove); + } + } + + function pushDown(options) { + + // We have a single option, so it may be passed as a string or property + if (typeof options === 'string') { + options = { + selector: options + }; + } + + // Fail early & silently log + var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === ''; + + if (isInvalidSelector) { + console.log('invalid pushDown selector'); + return false; + } + + var animatePushDownDom = document.querySelectorAll(options.selector); + var elementAnimationCount = animatePushDownDom.length; + for (var i = 0; i < elementAnimationCount; i++) { + var element = animatePushDownDom[i]; + var classNameToRemove = options.selector.split('.')[1]; + var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove); + element.className = element.className.substr(0, indexOfClassNameToRemove); + } + } + + function slideUp(options) { + + // We have a single option, so it may be passed as a string or property + if (typeof options === 'string') { + options = { + selector: options + }; + } + + // Fail early & silently log + var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === ''; + + if (isInvalidSelector) { + console.log('invalid pushDown selector'); + return false; + } + + var animateSlideUpDom = document.querySelectorAll(options.selector); + var elementAnimationCount = animateSlideUpDom.length; + for (var i = 0; i < elementAnimationCount; i++) { + var element = animateSlideUpDom[i]; + var classNameToRemove = options.selector.split('.')[1]; + var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove); + element.className = element.className.substr(0, indexOfClassNameToRemove); + } + } + + /* Export object + /============================================================================*/ + return motion; + } + + Motion.$inject = []; + }; + + +/***/ } +/******/ ]) +}); +; +//# sourceMappingURL=ionic.material.min.js.map \ No newline at end of file diff --git a/www/lib/ionic/js/ionic.material.min.js b/www/lib/ionic/js/ionic.material.min.js new file mode 100644 index 0000000000000000000000000000000000000000..a53b4430ff8121b7a7e4a4b7aa8a589ad2294213 --- /dev/null +++ b/www/lib/ionic/js/ionic.material.min.js @@ -0,0 +1,14 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(function(){try{return require("angular")}catch(e){}}()):"function"==typeof define&&define.amd?define(["angular"],t):"object"==typeof exports?exports.ionicMaterial=t(function(){try{return require("angular")}catch(e){}}()):e.ionicMaterial=t(e.angular)}(this,function(e){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";e.exports=function(){var e;try{e=n(1)}catch(t){}if(e&&e.version||(e=window.angular),!e||!e.version)throw new Error("ionic-material could not load angular module :(");var r=e.module("ionic-material",["ionic"]);return n(2)(r),n(3)(r),"ionic-material"}()},function(t,n,r){if("undefined"==typeof e){var i=new Error('Cannot find module "angular"');throw i.code="MODULE_NOT_FOUND",i}t.exports=e},function(e,t,n){"use strict";/*! + * Fork by Zach Fitzgerald and other contributors of Ionic Material + * + * Waves v0.5.4 + * http://fian.my.id/Waves + * + * Copyright 2014 Alfiana E. Sibuea and other contributors + * + * Released under the MIT license + * https://github.com/fians/Waves/blob/master/LICENSE + * + */ +e.exports=function(e){function t(){function e(e){return null!==e&&e===e.window}function t(t){return e(t)?t:9===t.nodeType&&t.defaultView}function n(e){var n,r,i={top:0,left:0},o=e&&e.ownerDocument;return n=o.documentElement,"undefined"!=typeof e.getBoundingClientRect&&(i=e.getBoundingClientRect()),r=t(o),{top:i.top+r.pageYOffset-n.clientTop,left:i.left+r.pageXOffset-n.clientLeft}}function r(e){var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?{r:parseInt(t[1],16),g:parseInt(t[2],16),b:parseInt(t[3],16)}:null}function i(e){var t="";for(var n in e)e.hasOwnProperty(n)&&(t+=n+":"+e[n]+";");return t}var o,a=a||{};if(document&&document.querySelectorAll&&document.querySelectorAll.bind)try{o=document.querySelectorAll.bind(document)}catch(l){}else if(window&&window.angular&&window.angular.element)o=window.angular.element;else{var s=function(e,t,n){var r=e.length;t=null==t?0:0>t?Math.max(r+t,0):Math.min(t,r),n=null==n?r:0>n?Math.max(r+n,0):Math.min(n,r);for(var i=[];n>t;)i.push(e[t++]);return i},f=function(e,t,n){var r=s(arguments,2);return function(){return e.apply(t,r.concat(s(arguments)))}};o=f(document.querySelectorAll,document)}if(!o)throw new Error("ionic material ink module could not create reference of DOM nodes");var c={duration:500,show:function(e){if(2===e.button)return!1;var t=this,o=document.createElement("div"),a=this.dataset.inkColor,l=this.dataset.inkOpacity,s=a||l;o.className="ink-ripple",t.appendChild(o);var f=n(t),u=e.pageY-f.top,d=e.pageX-f.left,p="scale("+t.clientWidth/100*2.5+")";"touches"in e&&(u=e.touches[0].pageY-f.top,d=e.touches[0].pageX-f.left),o.setAttribute("data-hold",Date.now()),o.setAttribute("data-scale",p),o.setAttribute("data-x",d),o.setAttribute("data-y",u);var m={top:u+"px",left:d+"px"};if(o.className=o.className+" ink-notransition",s){var h;if(a){var y=r(a);h=y.r+","+y.g+","+y.b}else h="0,0,0";l||(l=.2);var g="rgba("+h+","+l+")";m["background-color"]=g}o.setAttribute("style",i(m)),o.className=o.className.replace("ink-notransition",""),m["-webkit-transform"]=p,m["-moz-transform"]=p,m["-ms-transform"]=p,m["-o-transform"]=p,m.transform=p,m.opacity="1",m["-webkit-transition-duration"]=c.duration+"ms",m["-moz-transition-duration"]=c.duration+"ms",m["-o-transition-duration"]=c.duration+"ms",m["transition-duration"]=c.duration+"ms",o.setAttribute("style",i(m))},hide:function(){for(var e=this,t=(1.4*e.clientWidth,null),n=e.children.length,r=0;n>r;r++)-1===e.children[r].className.indexOf("ink-ripple")||(t=e.children[r]);if(!t)return!1;var o=t.getAttribute("data-x"),a=t.getAttribute("data-y"),l=t.getAttribute("data-scale"),s=Date.now()-Number(t.getAttribute("data-hold")),f=500-s;0>f&&(f=0),setTimeout(function(){var n={top:a+"px",left:o+"px",opacity:"0","-webkit-transition-duration":c.duration+"ms","-moz-transition-duration":c.duration+"ms","-o-transition-duration":c.duration+"ms","transition-duration":c.duration+"ms","-webkit-transform":l,"-moz-transform":l,"-ms-transform":l,"-o-transform":l,transform:l};t.setAttribute("style",i(n)),setTimeout(function(){try{e.removeChild(t)}catch(n){return!1}},c.duration)},f)},wrapInput:function(e){for(var t=0;t<e.length;t++){var n=e[t];if("input"===n.tagName.toLowerCase()){var r=n.parentNode;if("i"===r.tagName.toLowerCase()&&-1!==r.className.indexOf("ink")&&-1!==r.className.indexOf("tab-item")&&-1!==r.className.indexOf("button-fab")&&-1!==r.className.indexOf("button-raised")&&-1!==r.className.indexOf("button-flat")&&-1!==r.className.indexOf("button-clear")&&-1!==r.className.indexOf("button")&&-1!==r.className.indexOf("item"))return!1;var i=document.createElement("i");i.className=n.className+" ink-input-wrapper";var o=n.getAttribute("style");o||(o=""),i.setAttribute("style",o),n.className="ink-button-input",n.removeAttribute("style"),r.replaceChild(i,n),i.appendChild(n)}}}};return a.displayEffect=function(e){e=e||{},"duration"in e&&(c.duration=e.duration);var t=".ink,.tab-item,.button-fab,.button-raised,.button-flat,.button-clear,a.item,.popup .button";c.wrapInput(o(t)),Array.prototype.forEach.call(o(t),function(e){"ontouchstart"in window?(e.addEventListener("touchstart",c.show,!1),e.addEventListener("touchend",c.hide,!1),e.addEventListener("touchcancel",c.hide,!1)):(e.addEventListener("mousedown",c.show,!1),e.addEventListener("mouseup",c.hide,!1),e.addEventListener("mouseleave",c.hide,!1))})},a}e.factory("ionicMaterialInk",t),t.inject=[]}},function(e,t,n){e.exports=function(e){function t(){"use strict";function e(){return window.innerHeight}function t(e,t){for(var n=0;t>n;n++){var r=e[n];r.className+=" in",r.className+=" done"}}function n(n){var r={finishDelayThrottle:2,finishSpeedPercent:.5,leftOffsetPercentage:.8,selector:".animate-blinds .item",startVelocity:1100};"undefined"==typeof n&&(n={}),n.finishDelayThrottle=n.finishDelayThrottle||r.finishDelayThrottle,n.finishSpeedPercent=n.finishSpeedPercent||r.finishSpeedPercent,n.leftOffsetPercentage=n.leftOffsetPercentage||r.leftOffsetPercentage,n.startVelocity=n.startVelocity||r.startVelocity,"undefined"==typeof n.selector&&(n.selector=r.selector);var i="undefined"==typeof n.selector||""===n.selector;if(i)return console.log("invalid blinds selector"),!1;for(var o=document.querySelectorAll(n.selector),a=o.length,l=0,s=e(),f=0;a>f&&o[f].offsetTop<s;f++)l+=1;for(var c=n.startVelocity,f=0;l>f;f++){var u=o[f],d=u.getBoundingClientRect(),p=d.left*n.leftOffsetPercentage+d.top,m=parseFloat(p/c).toFixed(2);u.style.webkitTransitionDelay=m+"s",u.style.transitionDelay=m+"s",u.className+=" in"}setTimeout(function(){for(var e=0;l>e;e++){var t=o[e],r=t.getBoundingClientRect(),i=r.left*n.leftOffsetPercentage+r.top;parseFloat(i/c/n.finishDelayThrottle).toFixed(2);o[e].className+=" done"}},c*n.finishSpeedPercent),t(o,a)}function r(n){var r={finishDelayThrottle:2,finishSpeedPercent:.72,leftOffsetPercentage:.8,selector:".animate-fade-slide-in .item",startVelocity:1100};"undefined"==typeof n&&(n={}),n.finishDelayThrottle=n.finishDelayThrottle||r.finishDelayThrottle,n.finishSpeedPercent=n.finishSpeedPercent||r.finishSpeedPercent,n.leftOffsetPercentage=n.leftOffsetPercentage||r.leftOffsetPercentage,n.startVelocity=n.startVelocity||r.startVelocity,"undefined"==typeof n.selector&&(n.selector=r.selector);var i="undefined"==typeof n.selector||""===n.selector;if(i)return console.log("invalid fadeSlideIn selector"),!1;for(var o=document.querySelectorAll(n.selector),a=o.length,l=0,s=e(),f=0;a>f&&o[f].offsetTop<s;f++)l+=1;for(var c=n.startVelocity,f=0;l>f;f++){var u=o[f],d=u.getBoundingClientRect(),p=d.left*n.leftOffsetPercentage+d.top,m=parseFloat(p/c).toFixed(2);u.style.webkitTransitionDelay=m+"s",u.style.transitionDelay=m+"s",u.className+=" in"}setTimeout(function(){for(var e=0;l>e;e++){var t=o[e],r=t.getBoundingClientRect(),i=r.left*n.leftOffsetPercentage+r.top,a=i/c/n.finishDelayThrottle;parseFloat(a).toFixed(2)}o[0].className+=" done"},c*n.finishSpeedPercent),t(o,a)}function i(n){var r={finishDelayThrottle:2,finishSpeedPercent:.72,leftOffsetPercentage:.8,selector:".animate-fade-slide-in-right .item",startVelocity:1100};"undefined"==typeof n&&(n={}),n.finishDelayThrottle=n.finishDelayThrottle||r.finishDelayThrottle,n.finishSpeedPercent=n.finishSpeedPercent||r.finishSpeedPercent,n.leftOffsetPercentage=n.leftOffsetPercentage||r.leftOffsetPercentage,n.startVelocity=n.startVelocity||r.startVelocity,"undefined"==typeof n.selector&&(n.selector=r.selector);var i="undefined"==typeof n.selector||""===n.selector;if(i)return console.log("invalid fadeSlideInRight selector"),!1;for(var o=document.querySelectorAll(n.selector),a=o.length,l=0,s=e(),f=0;a>f&&o[f].offsetTop<s;f++)l+=1;for(var c=n.startVelocity,f=0;l>f;f++){var u=o[f],d=u.getBoundingClientRect(),p=d.left*n.leftOffsetPercentage+d.top,m=parseFloat(p/c).toFixed(2);u.style.webkitTransitionDelay=m+"s",u.style.transitionDelay=m+"s",u.className+=" in"}setTimeout(function(){for(var e=0;l>e;e++){var t=o[e],r=t.getBoundingClientRect(),i=r.left*n.leftOffsetPercentage+r.top,a=i/c/n.finishDelayThrottle;parseFloat(a).toFixed(2)}o[0].className+=" done"},c*n.finishSpeedPercent),t(o,a)}function o(n){var r={finishDelayThrottle:2,finishSpeedPercent:.72,leftOffsetPercentage:.8,selector:".animate-ripple .item",startVelocity:1100};"undefined"==typeof n&&(n={}),n.finishDelayThrottle=n.finishDelayThrottle||r.finishDelayThrottle,n.finishSpeedPercent=n.finishSpeedPercent||r.finishSpeedPercent,n.leftOffsetPercentage=n.leftOffsetPercentage||r.leftOffsetPercentage,n.startVelocity=n.startVelocity||r.startVelocity,"undefined"==typeof n.selector&&(n.selector=r.selector);var i="undefined"==typeof n.selector||""===n.selector;if(i)return console.log("invalid ripple selector"),!1;for(var o=document.querySelectorAll(n.selector),a=o.length,l=0,s=e(),f=0;f<o.length&&o[f].offsetTop<s;f++)l+=1;for(var c=n.startVelocity,f=0;l>f;f++){var u=o[f],d=u.getBoundingClientRect(),p=d.left*n.leftOffsetPercentage+d.top,m=parseFloat(p/c).toFixed(2);u.style.webkitTransitionDelay=m+"s",u.style.transitionDelay=m+"s",u.className+=" in"}setTimeout(function(){for(var e=0;l>e;e++){var t=o[e],r=t.getBoundingClientRect(),i=r.left*n.leftOffsetPercentage+r.top,a=i/c/n.finishDelayThrottle;parseFloat(a).toFixed(2)}o[0].className+=" done"},c*n.finishSpeedPercent),t(o,a)}function a(e){"string"==typeof e&&(e={selector:e});var t="undefined"==typeof e.selector||""===e.selector;if(t)return console.log("invalid pushDown selector"),!1;for(var n=document.querySelectorAll(e.selector),r=n.length,i=0;r>i;i++){var o=n[i],a="animate-pan-in-left",l=o.className.lastIndexOf(a);o.className=o.className.substr(0,l)}}function l(e){"string"==typeof e&&(e={selector:e});var t="undefined"==typeof e.selector||""===e.selector;if(t)return console.log("invalid pushDown selector"),!1;for(var n=document.querySelectorAll(e.selector),r=n.length,i=0;r>i;i++){var o=n[i],a=e.selector.split(".")[1],l=o.className.lastIndexOf(a);o.className=o.className.substr(0,l)}}function s(e){"string"==typeof e&&(e={selector:e});var t="undefined"==typeof e.selector||""===e.selector;if(t)return console.log("invalid pushDown selector"),!1;for(var n=document.querySelectorAll(e.selector),r=n.length,i=0;r>i;i++){var o=n[i],a=e.selector.split(".")[1],l=o.className.lastIndexOf(a);o.className=o.className.substr(0,l)}}var f={blinds:n,fadeSlideIn:r,fadeSlideInRight:i,panInLeft:a,pushDown:l,ripple:o,slideUp:s};return f}e.factory("ionicMaterialMotion",t),t.$inject=[]}}])}); +//# sourceMappingURL=ionic.material.min.js.map \ No newline at end of file diff --git a/www/lib/ionic/js/ionic.material.min.js.map b/www/lib/ionic/js/ionic.material.min.js.map new file mode 100644 index 0000000000000000000000000000000000000000..b582062aa73c27003b2fbf368af24e81d0f653bb --- /dev/null +++ b/www/lib/ionic/js/ionic.material.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///ionic.material.min.js","webpack:///webpack/bootstrap aca4d68e3e47af1bef6a","webpack:///./src/js/ionic-material.js","webpack:///external \"angular\"","webpack:///./src/js/lib/_ink.js","webpack:///./src/js/lib/_motion.js"],"names":["root","factory","exports","module","require","e","define","amd","this","__WEBPACK_EXTERNAL_MODULE_1__","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","angular","err","version","window","Error","app","code","angularApp","ink","isWindow","obj","getWindow","elem","nodeType","defaultView","offset","docElem","win","box","top","left","doc","ownerDocument","documentElement","getBoundingClientRect","pageYOffset","clientTop","pageXOffset","clientLeft","hexToRgb","hex","result","exec","r","parseInt","g","b","convertStyle","style","a","hasOwnProperty","$$","Ink","document","querySelectorAll","bind","element","slicePolyfill","arr","start","end","len","length","Math","max","min","push","bindPolyfill","fn","context","args","argsArr","arguments","apply","concat","Effect","duration","show","button","el","ripple","createElement","customColor","dataset","inkColor","customOpacity","inkOpacity","hasCustomRipple","className","appendChild","pos","relativeY","pageY","relativeX","pageX","scale","clientWidth","touches","setAttribute","Date","now","rippleStyle","colorRgb","fromHex","bg","replace","transform","opacity","hide","childrenLength","children","indexOf","getAttribute","diff","Number","delay","setTimeout","-webkit-transition-duration","-moz-transition-duration","-o-transition-duration","transition-duration","-webkit-transform","-moz-transform","-ms-transform","-o-transform","removeChild","wrapInput","elements","tagName","toLowerCase","parent","parentNode","wrapper","elementStyle","removeAttribute","replaceChild","displayEffect","options","selectors","Array","prototype","forEach","i","addEventListener","inject","Motion","getViewportHeight","innerHeight","showNotAnimatedElements","total","child","blinds","defaults","finishDelayThrottle","finishSpeedPercent","leftOffsetPercentage","selector","startVelocity","isInvalidSelector","console","log","animateBlindsDom","elementsCount","elementAnimationCount","viewportHeight","offsetTop","speed","childOffset","parseFloat","toFixed","webkitTransitionDelay","transitionDelay","fadeSlideIn","animateFadeSlideInDom","delayValue","fadeSlideInRight","animateSlideInRightDom","animateRippleDom","panInLeft","animatePanInLeftDom","classNameToRemove","indexOfClassNameToRemove","lastIndexOf","substr","pushDown","animatePushDownDom","split","slideUp","animateSlideUpDom","motion","$inject"],"mappings":"CAAA,SAAAA,EAAAC,GACA,gBAAAC,UAAA,gBAAAC,QACAA,OAAAD,QAAAD,EAAA,WAA0E,IAAM,MAAAG,SAAA,WAA6B,MAAAC,SAC7G,kBAAAC,gBAAAC,IACAD,QAAA,WAAAL,GACA,gBAAAC,SACAA,QAAA,cAAAD,EAAA,WAAoF,IAAM,MAAAG,SAAA,WAA6B,MAAAC,SAEvHL,EAAA,cAAAC,EAAAD,EAAA,UACCQ,KAAA,SAAAC,GACD,MCAgB,UAAUC,GCN1B,QAAAC,GAAAC,GAGA,GAAAC,EAAAD,GACA,MAAAC,GAAAD,GAAAV,OAGA,IAAAC,GAAAU,EAAAD,IACAV,WACAY,GAAAF,EACAG,QAAA,EAUA,OANAL,GAAAE,GAAAI,KAAAb,EAAAD,QAAAC,IAAAD,QAAAS,GAGAR,EAAAY,QAAA,EAGAZ,EAAAD,QAvBA,GAAAW,KAqCA,OATAF,GAAAM,EAAAP,EAGAC,EAAAO,EAAAL,EAGAF,EAAAQ,EAAA,GAGAR,EAAA,KDgBM,SAASR,EAAQD,EAASS,GE9ChC,YAEAR,GAAAD,QAAA,WAEA,GAAAkB,EAEA,KACAA,EAAAT,EAAA,GACK,MAAAU,IAQL,GANAD,KAAAE,UAEAF,EAAAG,OAAAH,UAIAA,MAAAE,QACA,SAAAE,OAAA,kDAIA,IAAAC,GAAAL,EAAAjB,OAAA,2BAMA,OAHAQ,GAAA,GAAAc,GACAd,EAAA,GAAAc,GAEA,qBF8DM,SAAStB,EAAQD,EAASS,GGjGhC,sBAAAF,GAAA,CAA0D,GAAAJ,GAAA,GAAAmB,OAAA,+BAAiF,MAA7BnB,GAAAqB,KAAA,mBAA6BrB,EAC3IF,EAAAD,QAAAO,GHuGM,SAASN,EAAQD,EAASS,GIxGhC;;;;;;;;;;;;AAcAR,EAAAD,QAAA,SAAAyB,GAIA,QAAAC,KAkFA,QAAAC,GAAAC,GACA,cAAAA,SAAAP,OAGA,QAAAQ,GAAAC,GACA,MAAAH,GAAAG,KAAA,IAAAA,EAAAC,UAAAD,EAAAE,YAGA,QAAAC,GAAAH,GACA,GAAAI,GAAAC,EACAC,GACAC,IAAA,EACAC,KAAA,GAEAC,EAAAT,KAAAU,aAQA,OANAN,GAAAK,EAAAE,gBAEA,mBAAAX,GAAAY,wBACAN,EAAAN,EAAAY,yBAEAP,EAAAN,EAAAU,IAEAF,IAAAD,EAAAC,IAAAF,EAAAQ,YAAAT,EAAAU,UACAN,KAAAF,EAAAE,KAAAH,EAAAU,YAAAX,EAAAY,YAIA,QAAAC,GAAAC,GACA,GAAAC,GAAA,4CAAoEC,KAAAF,EACpE,OAAAC,IACAE,EAAAC,SAAAH,EAAA,OACAI,EAAAD,SAAAH,EAAA,OACAK,EAAAF,SAAAH,EAAA,QACiB,KAGjB,QAAAM,GAAA3B,GACA,GAAA4B,GAAA,EAEA,QAAAC,KAAA7B,GACAA,EAAA8B,eAAAD,KACAD,GAAAC,EAAA,IAAA7B,EAAA6B,GAAA,IAIA,OAAAD,GA9HA,GAGAG,GAHAC,OAMA,IAAAC,mBAAAC,kBAAAD,SAAAC,iBAAAC,KACA,IAEAJ,EAAAE,SAAAC,iBAAAC,KAAAF,UAEiB,MAAA1D,QACJ,IAAAkB,eAAAH,SAAAG,OAAAH,QAAA8C,QAEbL,EAAAtC,OAAAH,QAAA8C,YACa,CAWb,GAAAC,GAAA,SAAAC,EAAAC,EAAAC,GACA,GAAAC,GAAAH,EAAAI,MAGAH,GADA,MAAAA,EACA,EACyB,EAAAA,EACzBI,KAAAC,IAAAH,EAAAF,EAAA,GAEAI,KAAAE,IAAAN,EAAAE,GAMAD,EAFA,MAAAA,EAEAC,EACyB,EAAAD,EACzBG,KAAAC,IAAAH,EAAAD,EAAA,GAEAG,KAAAE,IAAAL,EAAAC,EAIA,KADA,GAAApB,MACAmB,EAAAD,GACAlB,EAAAyB,KAAAR,EAAAC,KAGA,OAAAlB,IAYA0B,EAAA,SAAAC,EAAAC,EAAAC,GACA,GAAAC,GAAAd,EAAAe,UAAA,EACA,mBACA,MAAAJ,GAAAK,MAAAJ,EAAAE,EAAAG,OAAAjB,EAAAe,cAIArB,GAAAgB,EAAAd,SAAAC,iBAAAD,UAIA,IAAAF,EACA,SAAArC,OAAA,oEAqDA,IAAA6D,IAGAC,SAAA,IAEAC,KAAA,SAAAlF,GAGA,OAAAA,EAAAmF,OACA,QAGA,IAAAC,GAAAjF,KAGAkF,EAAA3B,SAAA4B,cAAA,OACAC,EAAApF,KAAAqF,QAAAC,SACAC,EAAAvF,KAAAqF,QAAAG,WACAC,EAAAL,GAAAG,CACAL,GAAAQ,UAAA,aACAT,EAAAU,YAAAT,EAGA,IAAAU,GAAAjE,EAAAsD,GACAY,EAAAhG,EAAAiG,MAAAF,EAAA7D,IACAgE,EAAAlG,EAAAmG,MAAAJ,EAAA5D,KACAiE,EAAA,SAAAhB,EAAAiB,YAAA,WAGA,YAAArG,KACAgG,EAAAhG,EAAAsG,QAAA,GAAAL,MAAAF,EAAA7D,IACAgE,EAAAlG,EAAAsG,QAAA,GAAAH,MAAAJ,EAAA5D,MAIAkD,EAAAkB,aAAA,YAAAC,KAAAC,OACApB,EAAAkB,aAAA,aAAAH,GACAf,EAAAkB,aAAA,SAAAL,GACAb,EAAAkB,aAAA,SAAAP,EAGA,IAAAU,IACAxE,IAAA8D,EAAA,KACA7D,KAAA+D,EAAA,KAKA,IAFAb,EAAAQ,UAAAR,EAAAQ,UAAA,oBAEAD,EAAA,CACA,GAAAe,EACA,IAAApB,EAAA,CACA,GAAAqB,GAAAhE,EAAA2C,EACAoB,GAAAC,EAAA5D,EAAA,IAAA4D,EAAA1D,EAAA,IAAA0D,EAAAzD,MAEAwD,GAAA,OAEAjB,KACAA,EAAA,GAEA,IAAAmB,GAAA,QAAAF,EAAA,IAAAjB,EAAA,GACAgB,GAAA,oBAAAG,EAGAxB,EAAAkB,aAAA,QAAAnD,EAAAsD,IACArB,EAAAQ,UAAAR,EAAAQ,UAAAiB,QAAA,uBAGAJ,EAAA,qBAAAN,EACAM,EAAA,kBAAAN,EACAM,EAAA,iBAAAN,EACAM,EAAA,gBAAAN,EACAM,EAAAK,UAAAX,EACAM,EAAAM,QAAA,IAEAN,EAAA,+BAAA1B,EAAAC,SAAA,KACAyB,EAAA,4BAAA1B,EAAAC,SAAA,KACAyB,EAAA,0BAAA1B,EAAAC,SAAA,KACAyB,EAAA,uBAAA1B,EAAAC,SAAA,KAEAI,EAAAkB,aAAA,QAAAnD,EAAAsD,KAGAO,KAAA,WAWA,OATA7B,GAAAjF,KAKAkF,GAHA,IAAAD,EAAAiB,YAGA,MAEAa,EAAA9B,EAAA+B,SAAAhD,OAEAb,EAAA,EAAmC4D,EAAA5D,EAAoBA,IACvD,KAAA8B,EAAA+B,SAAA7D,GAAAuC,UAAAuB,QAAA,gBACA/B,EAAAD,EAAA+B,SAAA7D,GAKA,KAAA+B,EACA,QAGA,IAAAa,GAAAb,EAAAgC,aAAA,UACArB,EAAAX,EAAAgC,aAAA,UACAjB,EAAAf,EAAAgC,aAAA,cAGAC,EAAAd,KAAAC,MAAAc,OAAAlC,EAAAgC,aAAA,cACAG,EAAA,IAAAF,CAEA,GAAAE,IACAA,EAAA,GAIAC,WAAA,WAEA,GAAApE,IACAnB,IAAA8D,EAAA,KACA7D,KAAA+D,EAAA,KACAc,QAAA,IAGAU,8BAAA1C,EAAAC,SAAA,KACA0C,2BAAA3C,EAAAC,SAAA,KACA2C,yBAAA5C,EAAAC,SAAA,KACA4C,sBAAA7C,EAAAC,SAAA,KACA6C,oBAAA1B,EACA2B,iBAAA3B,EACA4B,gBAAA5B,EACA6B,eAAA7B,EACAW,UAAAX,EAGAf,GAAAkB,aAAA,QAAAnD,EAAAC,IAEAoE,WAAA,WACA,IACArC,EAAA8C,YAAA7C,GAC6B,MAAArF,GAC7B,WAEyBgF,EAAAC,WACJuC,IAIrBW,UAAA,SAAAC,GAEA,OAAA9E,GAAA,EAAmCA,EAAA8E,EAAAjE,OAAqBb,IAAA,CAExD,GAAA8B,GAAAgD,EAAA9E,EAEA,cAAA8B,EAAAiD,QAAAC,cAAA,CAEA,GAAAC,GAAAnD,EAAAoD,UAGA,UAAAD,EAAAF,QAAAC,eACA,KAAAC,EAAA1C,UAAAuB,QAAA,QACA,KAAAmB,EAAA1C,UAAAuB,QAAA,aACA,KAAAmB,EAAA1C,UAAAuB,QAAA,eACA,KAAAmB,EAAA1C,UAAAuB,QAAA,kBACA,KAAAmB,EAAA1C,UAAAuB,QAAA,gBACA,KAAAmB,EAAA1C,UAAAuB,QAAA,iBACA,KAAAmB,EAAA1C,UAAAuB,QAAA,WACA,KAAAmB,EAAA1C,UAAAuB,QAAA,QACA,QAIA,IAAAqB,GAAA/E,SAAA4B,cAAA,IACAmD,GAAA5C,UAAAT,EAAAS,UAAA,oBAEA,IAAA6C,GAAAtD,EAAAiC,aAAA,QAEAqB,KACAA,EAAA,IAGAD,EAAAlC,aAAA,QAAAmC,GAEAtD,EAAAS,UAAA,mBACAT,EAAAuD,gBAAA,SAGAJ,EAAAK,aAAAH,EAAArD,GACAqD,EAAA3C,YAAAV,MA8BA,OAxBA3B,GAAAoF,cAAA,SAAAC,GACAA,QAEA,YAAAA,KACA9D,EAAAC,SAAA6D,EAAA7D,SAIA,IAAA8D,GAAA,4FACA/D,GAAAmD,UAAA3E,EAAAuF,IAEAC,MAAAC,UAAAC,QAAAvI,KAAA6C,EAAAuF,GAAA,SAAAI,GACA,gBAAAjI,SACAiI,EAAAC,iBAAA,aAAApE,EAAAE,MAAA,GACAiE,EAAAC,iBAAA,WAAApE,EAAAiC,MAAA,GACAkC,EAAAC,iBAAA,cAAApE,EAAAiC,MAAA,KAEAkC,EAAAC,iBAAA,YAAApE,EAAAE,MAAA,GACAiE,EAAAC,iBAAA,UAAApE,EAAAiC,MAAA,GACAkC,EAAAC,iBAAA,aAAApE,EAAAiC,MAAA,OAKAxD,EAhWAnC,EAAA1B,QAAA,mBAAA2B,GAmWAA,EAAA8H,YJgHM,SAASvJ,EAAQD,EAASS,GKnehCR,EAAAD,QAAA,SAAAyB,GAGA,QAAAgI,KAGA,YASA,SAAAC,KACA,MAAArI,QAAAsI,YAOA,QAAAC,GAAArB,EAAAsB,GAEA,OAAAP,GAAA,EAA2BO,EAAAP,EAAWA,IAAA,CACtC,GAAAQ,GAAAvB,EAAAe,EACAQ,GAAA9D,WAAA,MACA8D,EAAA9D,WAAA,SAsBA,QAAA+D,GAAAd,GAGA,GAAAe,IACAC,oBAAA,EACAC,mBAAA,GACAC,qBAAA,GACAC,SAAA,wBACAC,cAAA,KAIA,oBAAApB,KACAA,MAGAA,EAAAgB,oBAAAhB,EAAAgB,qBAAAD,EAAAC,oBACAhB,EAAAiB,mBAAAjB,EAAAiB,oBAAAF,EAAAE,mBACAjB,EAAAkB,qBAAAlB,EAAAkB,sBAAAH,EAAAG,qBACAlB,EAAAoB,cAAApB,EAAAoB,eAAAL,EAAAK,cAEA,mBAAApB,GAAAmB,WACAnB,EAAAmB,SAAAJ,EAAAI,SAIA,IAAAE,GAAA,mBAAArB,GAAAmB,UAAA,KAAAnB,EAAAmB,QAEA,IAAAE,EAEA,MADAC,SAAAC,IAAA,4BACA,CAcA,QAXAC,GAAA5G,SAAAC,iBAAAmF,EAAAmB,UACAM,EAAAD,EAAAnG,OACAqG,EAAA,EAQAC,EAAAlB,IACAJ,EAAA,EAA2BoB,EAAApB,GAC3BmB,EAAAnB,GAAAuB,UAAAD,EAD8CtB,IAE9CqB,GAAA,CAQA,QADAG,GAAA7B,EAAAoB,cACAf,EAAA,EAA2BqB,EAAArB,EAA2BA,IAAA,CACtD,GAAAQ,GAAAW,EAAAnB,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,IACAsF,EAAAqD,WAAA/I,EAAA6I,GAAAG,QAAA,EACAnB,GAAAtG,MAAA0H,sBAAAvD,EAAA,IACAmC,EAAAtG,MAAA2H,gBAAAxD,EAAA,IACAmC,EAAA9D,WAAA,MAIA4B,WAAA,WACA,OAAA0B,GAAA,EAA+BqB,EAAArB,EAA2BA,IAAA,CAC1D,GAAAQ,GAAAW,EAAAnB,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,GACA2I,YAAA/I,EAAA6I,EAAA7B,EAAAgB,qBAAAgB,QAAA,EAIAR,GAAAnB,GAAAtD,WAAA,UAGa8E,EAAA7B,EAAAiB,oBAGbN,EAAAa,EAAAC,GAGA,QAAAU,GAAAnC,GAGA,GAAAe,IACAC,oBAAA,EACAC,mBAAA,IACAC,qBAAA,GACAC,SAAA,+BACAC,cAAA,KAIA,oBAAApB,KACAA,MAGAA,EAAAgB,oBAAAhB,EAAAgB,qBAAAD,EAAAC,oBACAhB,EAAAiB,mBAAAjB,EAAAiB,oBAAAF,EAAAE,mBACAjB,EAAAkB,qBAAAlB,EAAAkB,sBAAAH,EAAAG,qBACAlB,EAAAoB,cAAApB,EAAAoB,eAAAL,EAAAK,cAEA,mBAAApB,GAAAmB,WACAnB,EAAAmB,SAAAJ,EAAAI,SAIA,IAAAE,GAAA,mBAAArB,GAAAmB,UAAA,KAAAnB,EAAAmB,QAEA,IAAAE,EAEA,MADAC,SAAAC,IAAA,iCACA,CAcA,QAXAa,GAAAxH,SAAAC,iBAAAmF,EAAAmB,UACAM,EAAAW,EAAA/G,OACAqG,EAAA,EAQAC,EAAAlB,IACAJ,EAAA,EAA2BoB,EAAApB,GAC3B+B,EAAA/B,GAAAuB,UAAAD,EAD8CtB,IAE9CqB,GAAA,CAQA,QADAG,GAAA7B,EAAAoB,cACAf,EAAA,EAA2BqB,EAAArB,EAA2BA,IAAA,CACtD,GAAAQ,GAAAuB,EAAA/B,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,IACAsF,EAAAqD,WAAA/I,EAAA6I,GAAAG,QAAA,EACAnB,GAAAtG,MAAA0H,sBAAAvD,EAAA,IACAmC,EAAAtG,MAAA2H,gBAAAxD,EAAA,IACAmC,EAAA9D,WAAA,MAIA4B,WAAA,WACA,OAAA0B,GAAA,EAA+BqB,EAAArB,EAA2BA,IAC1D,IAAAQ,GAAAuB,EAAA/B,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,IACAiJ,EAAArJ,EAAA6I,EAAA7B,EAAAgB,mBACAe,YAAAM,GAAAL,QAAA,GAEAI,EAAA,GAAArF,WAAA,SAEa8E,EAAA7B,EAAAiB,oBAGbN,EAAAyB,EAAAX,GAGA,QAAAa,GAAAtC,GAGA,GAAAe,IACAC,oBAAA,EACAC,mBAAA,IACAC,qBAAA,GACAC,SAAA,qCACAC,cAAA,KAIA,oBAAApB,KACAA,MAGAA,EAAAgB,oBAAAhB,EAAAgB,qBAAAD,EAAAC,oBACAhB,EAAAiB,mBAAAjB,EAAAiB,oBAAAF,EAAAE,mBACAjB,EAAAkB,qBAAAlB,EAAAkB,sBAAAH,EAAAG,qBACAlB,EAAAoB,cAAApB,EAAAoB,eAAAL,EAAAK,cAEA,mBAAApB,GAAAmB,WACAnB,EAAAmB,SAAAJ,EAAAI,SAIA,IAAAE,GAAA,mBAAArB,GAAAmB,UAAA,KAAAnB,EAAAmB,QAEA,IAAAE,EAEA,MADAC,SAAAC,IAAA,sCACA,CAcA,QAXAgB,GAAA3H,SAAAC,iBAAAmF,EAAAmB,UACAM,EAAAc,EAAAlH,OACAqG,EAAA,EAQAC,EAAAlB,IACAJ,EAAA,EAA2BoB,EAAApB,GAC3BkC,EAAAlC,GAAAuB,UAAAD,EAD8CtB,IAE9CqB,GAAA,CAQA,QADAG,GAAA7B,EAAAoB,cACAf,EAAA,EAA2BqB,EAAArB,EAA2BA,IAAA,CACtD,GAAAQ,GAAA0B,EAAAlC,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,IACAsF,EAAAqD,WAAA/I,EAAA6I,GAAAG,QAAA,EACAnB,GAAAtG,MAAA0H,sBAAAvD,EAAA,IACAmC,EAAAtG,MAAA2H,gBAAAxD,EAAA,IACAmC,EAAA9D,WAAA,MAIA4B,WAAA,WACA,OAAA0B,GAAA,EAA+BqB,EAAArB,EAA2BA,IAC1D,IAAAQ,GAAA0B,EAAAlC,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,IACAiJ,EAAArJ,EAAA6I,EAAA7B,EAAAgB,mBACAe,YAAAM,GAAAL,QAAA,GAEAO,EAAA,GAAAxF,WAAA,SAEa8E,EAAA7B,EAAAiB,oBAGbN,EAAA4B,EAAAd,GAIA,QAAAlF,GAAAyD,GAGA,GAAAe,IACAC,oBAAA,EACAC,mBAAA,IACAC,qBAAA,GACAC,SAAA,wBACAC,cAAA,KAIA,oBAAApB,KACAA,MAGAA,EAAAgB,oBAAAhB,EAAAgB,qBAAAD,EAAAC,oBACAhB,EAAAiB,mBAAAjB,EAAAiB,oBAAAF,EAAAE,mBACAjB,EAAAkB,qBAAAlB,EAAAkB,sBAAAH,EAAAG,qBACAlB,EAAAoB,cAAApB,EAAAoB,eAAAL,EAAAK,cAEA,mBAAApB,GAAAmB,WACAnB,EAAAmB,SAAAJ,EAAAI,SAIA,IAAAE,GAAA,mBAAArB,GAAAmB,UAAA,KAAAnB,EAAAmB,QAEA,IAAAE,EAEA,MADAC,SAAAC,IAAA,4BACA,CAcA,QAXAiB,GAAA5H,SAAAC,iBAAAmF,EAAAmB,UACAM,EAAAe,EAAAnH,OACAqG,EAAA,EAQAC,EAAAlB,IACAJ,EAAA,EAA2BA,EAAAmC,EAAAnH,QAC3BmH,EAAAnC,GAAAuB,UAAAD,EADwDtB,IAExDqB,GAAA,CAQA,QADAG,GAAA7B,EAAAoB,cACAf,EAAA,EAA2BqB,EAAArB,EAA2BA,IAAA,CACtD,GAAAQ,GAAA2B,EAAAnC,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,IACAsF,EAAAqD,WAAA/I,EAAA6I,GAAAG,QAAA,EACAnB,GAAAtG,MAAA0H,sBAAAvD,EAAA,IACAmC,EAAAtG,MAAA2H,gBAAAxD,EAAA,IACAmC,EAAA9D,WAAA,MAIA4B,WAAA,WACA,OAAA0B,GAAA,EAA+BqB,EAAArB,EAA2BA,IAC1D,IAAAQ,GAAA2B,EAAAnC,GACAyB,EAAAjB,EAAApH,wBACAT,EAAA8I,EAAAzI,KAAA2G,EAAAkB,qBAAAY,EAAA1I,IACAiJ,EAAArJ,EAAA6I,EAAA7B,EAAAgB,mBACAe,YAAAM,GAAAL,QAAA,GAEAQ,EAAA,GAAAzF,WAAA,SAEa8E,EAAA7B,EAAAiB,oBAGbN,EAAA6B,EAAAf,GAGA,QAAAgB,GAAAzC,GAGA,gBAAAA,KACAA,GACAmB,SAAAnB,GAKA,IAAAqB,GAAA,mBAAArB,GAAAmB,UAAA,KAAAnB,EAAAmB,QAEA,IAAAE,EAEA,MADAC,SAAAC,IAAA,8BACA,CAKA,QAFAmB,GAAA9H,SAAAC,iBAAAmF,EAAAmB,UACAO,EAAAgB,EAAArH,OACAgF,EAAA,EAA2BqB,EAAArB,EAA2BA,IAAA,CACtD,GAAAtF,GAAA2H,EAAArC,GACAsC,EAAA,sBACAC,EAAA7H,EAAAgC,UAAA8F,YAAAF,EACA5H,GAAAgC,UAAAhC,EAAAgC,UAAA+F,OAAA,EAAAF,IAIA,QAAAG,GAAA/C,GAGA,gBAAAA,KACAA,GACAmB,SAAAnB,GAKA,IAAAqB,GAAA,mBAAArB,GAAAmB,UAAA,KAAAnB,EAAAmB,QAEA,IAAAE,EAEA,MADAC,SAAAC,IAAA,8BACA,CAKA,QAFAyB,GAAApI,SAAAC,iBAAAmF,EAAAmB,UACAO,EAAAsB,EAAA3H,OACAgF,EAAA,EAA2BqB,EAAArB,EAA2BA,IAAA,CACtD,GAAAtF,GAAAiI,EAAA3C,GACAsC,EAAA3C,EAAAmB,SAAA8B,MAAA,QACAL,EAAA7H,EAAAgC,UAAA8F,YAAAF,EACA5H,GAAAgC,UAAAhC,EAAAgC,UAAA+F,OAAA,EAAAF,IAIA,QAAAM,GAAAlD,GAGA,gBAAAA,KACAA,GACAmB,SAAAnB,GAKA,IAAAqB,GAAA,mBAAArB,GAAAmB,UAAA,KAAAnB,EAAAmB,QAEA,IAAAE,EAEA,MADAC,SAAAC,IAAA,8BACA,CAKA,QAFA4B,GAAAvI,SAAAC,iBAAAmF,EAAAmB,UACAO,EAAAyB,EAAA9H,OACAgF,EAAA,EAA2BqB,EAAArB,EAA2BA,IAAA,CACtD,GAAAtF,GAAAoI,EAAA9C,GACAsC,EAAA3C,EAAAmB,SAAA8B,MAAA,QACAL,EAAA7H,EAAAgC,UAAA8F,YAAAF,EACA5H,GAAAgC,UAAAhC,EAAAgC,UAAA+F,OAAA,EAAAF,IA9ZA,GAAAQ,IACAtC,SACAqB,cACAG,mBACAG,YACAM,WACAxG,SACA2G,UA6ZA,OAAAE,GA3cA5K,EAAA1B,QAAA,sBAAA0J,GA8cAA,EAAA6C","file":"ionic.material.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory((function webpackLoadOptionalExternalModule() { try { return require(\"angular\"); } catch(e) {} }()));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"angular\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ionicMaterial\"] = factory((function webpackLoadOptionalExternalModule() { try { return require(\"angular\"); } catch(e) {} }()));\n\telse\n\t\troot[\"ionicMaterial\"] = factory(root[\"angular\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory((function webpackLoadOptionalExternalModule() { try { return require(\"angular\"); } catch(e) {} }()));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"angular\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ionicMaterial\"] = factory((function webpackLoadOptionalExternalModule() { try { return require(\"angular\"); } catch(e) {} }()));\n\telse\n\t\troot[\"ionicMaterial\"] = factory(root[\"angular\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/**\n\t * Ionic Material\n\t * \"Bundle Index\" / \"Entryfile\"\n\t * https://github.com/zachsoft/ionic-material\n\t *\n\t * Recommended: use a compiled version, especially in production!\n\t */\n\t\n\t'use strict';\n\t\n\tmodule.exports = (function(){\n\t\n\t var angular;\n\t\n\t try {\n\t angular = __webpack_require__(1);\n\t } catch(err){ }\n\t\n\t if(!angular || !angular.version){\n\t /*global window: true*/\n\t angular = window.angular;\n\t /*global window: false*/\n\t }\n\t\n\t if(!angular || !angular.version){\n\t throw new Error('ionic-material could not load angular module :(');\n\t }\n\t\n\t // set up angular module\n\t var app = angular.module('ionic-material', ['ionic']);\n\t\n\t // Import Dependencies\n\t __webpack_require__(2)(app);\n\t __webpack_require__(3)(app);\n\t\n\t return 'ionic-material';\n\t})();\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tif(typeof __WEBPACK_EXTERNAL_MODULE_1__ === 'undefined') {var e = new Error(\"Cannot find module \\\"angular\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e;}\n\tmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n/***/ },\n/* 2 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\t/*!\n\t * Fork by Zach Fitzgerald and other contributors of Ionic Material\n\t *\n\t * Waves v0.5.4\n\t * http://fian.my.id/Waves\n\t *\n\t * Copyright 2014 Alfiana E. Sibuea and other contributors\n\t *\n\t * Released under the MIT license\n\t * https://github.com/fians/Waves/blob/master/LICENSE\n\t *\n\t */\n\tmodule.exports = function (angularApp) {\n\t\n\t angularApp.factory('ionicMaterialInk', ink);\n\t\n\t function ink (){\n\t /*global document*/\n\t var Ink = Ink || {};\n\t\n\t // all DOM nodes\n\t var $$;\n\t\n\t // phantomJS throws an error when you try to use document.querySelectorAll.bind\n\t if(document && document.querySelectorAll && document.querySelectorAll.bind){\n\t try{\n\t // all DOM nodes\n\t $$ = document.querySelectorAll.bind(document);\n\t\n\t } catch(e){}\n\t } else if (window && window.angular && window.angular.element) {\n\t // we can use angular.element instead\n\t $$ = window.angular.element;\n\t } else {\n\t\n\t\n\t /**\n\t * mout.js 0.11.0 bind and slice polyfills (substitutes?)\n\t * TODO: pull out mout.js bind and slice molyfills and inject into material.ink\n\t */\n\t\n\t /**\n\t * Create slice of source array or array-like object\n\t */\n\t var slicePolyfill = function moutslicePolyfill(arr, start, end){\n\t var len = arr.length;\n\t /*jshint eqnull:true */\n\t if (start == null) {\n\t start = 0;\n\t } else if (start < 0) {\n\t start = Math.max(len + start, 0);\n\t } else {\n\t start = Math.min(start, len);\n\t }\n\t\n\t\n\t if (end == null) {\n\t\n\t end = len;\n\t } else if (end < 0) {\n\t end = Math.max(len + end, 0);\n\t } else {\n\t end = Math.min(end, len);\n\t }\n\t\n\t var result = [];\n\t while (start < end) {\n\t result.push(arr[start++]);\n\t }\n\t\n\t return result;\n\t };\n\t\n\t\n\t\n\t /**\n\t * Return a function that will execute in the given context, optionally adding any additional supplied parameters to the beginning of the arguments collection.\n\t * @param {Function} fn Function.\n\t * @param {object} context Execution context.\n\t * @param {rest} args Arguments (0...n arguments).\n\t * @return {Function} Wrapped Function.\n\t */\n\t var bindPolyfill = function moutBind(fn, context, args){\n\t var argsArr = slicePolyfill(arguments, 2); //curried args\n\t return function(){\n\t return fn.apply(context, argsArr.concat(slicePolyfill(arguments)));\n\t };\n\t };\n\t\n\t $$ = bindPolyfill(document.querySelectorAll, document);\n\t /*jshint ignore:end */\n\t }\n\t\n\t if (!$$){\n\t throw new Error('ionic material ink module could not create reference of DOM nodes');\n\t }\n\t\n\t // Find exact position of element\n\t function isWindow(obj) {\n\t return obj !== null && obj === obj.window;\n\t }\n\t\n\t function getWindow(elem) {\n\t return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;\n\t }\n\t\n\t function offset(elem) {\n\t var docElem, win,\n\t box = {\n\t top: 0,\n\t left: 0\n\t },\n\t doc = elem && elem.ownerDocument;\n\t\n\t docElem = doc.documentElement;\n\t\n\t if (typeof elem.getBoundingClientRect !== typeof undefined) {\n\t box = elem.getBoundingClientRect();\n\t }\n\t win = getWindow(doc);\n\t return {\n\t top: box.top + win.pageYOffset - docElem.clientTop,\n\t left: box.left + win.pageXOffset - docElem.clientLeft\n\t };\n\t }\n\t\n\t function hexToRgb(hex) {\n\t var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\t return result ? {\n\t r: parseInt(result[1], 16),\n\t g: parseInt(result[2], 16),\n\t b: parseInt(result[3], 16)\n\t } : null;\n\t }\n\t\n\t function convertStyle(obj) {\n\t var style = '';\n\t\n\t for (var a in obj) {\n\t if (obj.hasOwnProperty(a)) {\n\t style += (a + ':' + obj[a] + ';');\n\t }\n\t }\n\t\n\t return style;\n\t }\n\t\n\t var Effect = {\n\t\n\t // Effect delay\n\t duration: 500,\n\t\n\t show: function(e) {\n\t\n\t // Disable right click\n\t if (e.button === 2) {\n\t return false;\n\t }\n\t\n\t var el = this;\n\t\n\t // Create ripple\n\t var ripple = document.createElement('div');\n\t var customColor = this.dataset.inkColor;\n\t var customOpacity = this.dataset.inkOpacity;\n\t var hasCustomRipple = customColor || customOpacity;\n\t ripple.className = 'ink-ripple';\n\t el.appendChild(ripple);\n\t\n\t // Get click coordinate and element witdh\n\t var pos = offset(el);\n\t var relativeY = (e.pageY - pos.top);\n\t var relativeX = (e.pageX - pos.left);\n\t var scale = 'scale(' + ((el.clientWidth / 100) * 2.5) + ')';\n\t\n\t // Support for touch devices\n\t if ('touches' in e) {\n\t relativeY = (e.touches[0].pageY - pos.top);\n\t relativeX = (e.touches[0].pageX - pos.left);\n\t }\n\t\n\t // Attach data to element\n\t ripple.setAttribute('data-hold', Date.now());\n\t ripple.setAttribute('data-scale', scale);\n\t ripple.setAttribute('data-x', relativeX);\n\t ripple.setAttribute('data-y', relativeY);\n\t\n\t // Set ripple position\n\t var rippleStyle = {\n\t 'top': relativeY + 'px',\n\t 'left': relativeX + 'px'\n\t };\n\t\n\t ripple.className = ripple.className + ' ink-notransition';\n\t\n\t if (hasCustomRipple) {\n\t var colorRgb;\n\t if (customColor) {\n\t var fromHex = hexToRgb(customColor);\n\t colorRgb = fromHex.r + ',' + fromHex.g + ',' + fromHex.b;\n\t } else {\n\t colorRgb = '0,0,0';\n\t }\n\t if (!customOpacity) {\n\t customOpacity = 0.2;\n\t }\n\t var bg = 'rgba(' + colorRgb + ',' + customOpacity + ')';\n\t rippleStyle['background-color'] = bg;\n\t }\n\t\n\t ripple.setAttribute('style', convertStyle(rippleStyle));\n\t ripple.className = ripple.className.replace('ink-notransition', '');\n\t\n\t // Scale the ripple\n\t rippleStyle['-webkit-transform'] = scale;\n\t rippleStyle['-moz-transform'] = scale;\n\t rippleStyle['-ms-transform'] = scale;\n\t rippleStyle['-o-transform'] = scale;\n\t rippleStyle.transform = scale;\n\t rippleStyle.opacity = '1';\n\t\n\t rippleStyle['-webkit-transition-duration'] = Effect.duration + 'ms';\n\t rippleStyle['-moz-transition-duration'] = Effect.duration + 'ms';\n\t rippleStyle['-o-transition-duration'] = Effect.duration + 'ms';\n\t rippleStyle['transition-duration'] = Effect.duration + 'ms';\n\t\n\t ripple.setAttribute('style', convertStyle(rippleStyle));\n\t },\n\t\n\t hide: function() {\n\t\n\t var el = this;\n\t\n\t var width = el.clientWidth * 1.4;\n\t\n\t // Get first ripple\n\t var ripple = null;\n\t\n\t var childrenLength = el.children.length;\n\t\n\t for (var a = 0; a < childrenLength; a++) {\n\t if (el.children[a].className.indexOf('ink-ripple') !== -1) {\n\t ripple = el.children[a];\n\t continue;\n\t }\n\t }\n\t\n\t if (!ripple) {\n\t return false;\n\t }\n\t\n\t var relativeX = ripple.getAttribute('data-x');\n\t var relativeY = ripple.getAttribute('data-y');\n\t var scale = ripple.getAttribute('data-scale');\n\t\n\t // Get delay beetween mousedown and mouse leave\n\t var diff = Date.now() - Number(ripple.getAttribute('data-hold'));\n\t var delay = 500 - diff;\n\t\n\t if (delay < 0) {\n\t delay = 0;\n\t }\n\t\n\t // Fade out ripple after delay\n\t setTimeout(function() {\n\t\n\t var style = {\n\t 'top': relativeY + 'px',\n\t 'left': relativeX + 'px',\n\t 'opacity': '0',\n\t\n\t // Duration\n\t '-webkit-transition-duration': Effect.duration + 'ms',\n\t '-moz-transition-duration': Effect.duration + 'ms',\n\t '-o-transition-duration': Effect.duration + 'ms',\n\t 'transition-duration': Effect.duration + 'ms',\n\t '-webkit-transform': scale,\n\t '-moz-transform': scale,\n\t '-ms-transform': scale,\n\t '-o-transform': scale,\n\t 'transform': scale,\n\t };\n\t\n\t ripple.setAttribute('style', convertStyle(style));\n\t\n\t setTimeout(function() {\n\t try {\n\t el.removeChild(ripple);\n\t } catch (e) {\n\t return false;\n\t }\n\t }, Effect.duration);\n\t }, delay);\n\t },\n\t\n\t // Little hack to make <input> can perform ink effect\n\t wrapInput: function(elements) {\n\t\n\t for (var a = 0; a < elements.length; a++) {\n\t\n\t var el = elements[a];\n\t\n\t if (el.tagName.toLowerCase() === 'input') {\n\t\n\t var parent = el.parentNode;\n\t\n\t // If input already have parent just pass through\n\t if (parent.tagName.toLowerCase() === 'i' &&\n\t parent.className.indexOf('ink') !== -1 &&\n\t parent.className.indexOf('tab-item') !== -1 &&\n\t parent.className.indexOf('button-fab') !== -1 &&\n\t parent.className.indexOf('button-raised') !== -1 &&\n\t parent.className.indexOf('button-flat') !== -1 &&\n\t parent.className.indexOf('button-clear') !== -1 &&\n\t parent.className.indexOf('button') !== -1 &&\n\t parent.className.indexOf('item') !== -1) {\n\t return false;\n\t }\n\t\n\t // Put element class and style to the specified parent\n\t var wrapper = document.createElement('i');\n\t wrapper.className = el.className + ' ink-input-wrapper';\n\t\n\t var elementStyle = el.getAttribute('style');\n\t\n\t if (!elementStyle) {\n\t elementStyle = '';\n\t }\n\t\n\t wrapper.setAttribute('style', elementStyle);\n\t\n\t el.className = 'ink-button-input';\n\t el.removeAttribute('style');\n\t\n\t // Put element as child\n\t parent.replaceChild(wrapper, el);\n\t wrapper.appendChild(el);\n\t }\n\t }\n\t }\n\t };\n\t\n\t Ink.displayEffect = function(options) {\n\t options = options || {};\n\t\n\t if ('duration' in options) {\n\t Effect.duration = options.duration;\n\t }\n\t\n\t //Wrap input inside <i> tag\n\t var selectors = '.ink,.tab-item,.button-fab,.button-raised,.button-flat,.button-clear,a.item,.popup .button';\n\t Effect.wrapInput($$(selectors));\n\t\n\t Array.prototype.forEach.call($$(selectors), function(i) {\n\t if ('ontouchstart' in window) {\n\t i.addEventListener('touchstart', Effect.show, false);\n\t i.addEventListener('touchend', Effect.hide, false);\n\t i.addEventListener('touchcancel', Effect.hide, false);\n\t } else {\n\t i.addEventListener('mousedown', Effect.show, false);\n\t i.addEventListener('mouseup', Effect.hide, false);\n\t i.addEventListener('mouseleave', Effect.hide, false);\n\t }\n\t });\n\t };\n\t\n\t return Ink;\n\t }\n\t\n\t ink.inject = [];\n\t};\n\n\n/***/ },\n/* 3 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tmodule.exports = function(angularApp) {\n\t angularApp.factory('ionicMaterialMotion', Motion);\n\t\n\t function Motion() {\n\t /*global document, window*/\n\t\n\t 'use strict';\n\t\n\t /*============================================================================*/\n\t /* HELPERS (non-exports)\n\t /=============================================================================*\n\t / Abstract common lookups and manipulations in case better alternatives\n\t / arise or future cross-platform differences warrant separate handling\n\t /=============================================================================*/\n\t\n\t function getViewportHeight() {\n\t return window.innerHeight;\n\t }\n\t\n\t function getBoundingClientRect(domNode) {\n\t return domNode.getBoundingClientRect;\n\t }\n\t\n\t function showNotAnimatedElements(elements, total) {\n\t // Load the elements without effect\n\t for (var i = 0; i < total; i++) {\n\t var child = elements[i];\n\t child.className += ' in';\n\t child.className += ' done';\n\t }\n\t }\n\t\n\t\n\t\n\t /*============================================================================*/\n\t /* MOTION (EXPORT)\n\t /=============================================================================*\n\t / Animation methods for the library\n\t /=============================================================================*/\n\t\n\t var motion = {\n\t blinds: blinds,\n\t fadeSlideIn: fadeSlideIn,\n\t fadeSlideInRight: fadeSlideInRight,\n\t panInLeft: panInLeft,\n\t pushDown: pushDown,\n\t ripple: ripple,\n\t slideUp: slideUp\n\t };\n\t\n\t function blinds(options) {\n\t\n\t // Declare our defaults\n\t var defaults = {\n\t finishDelayThrottle: 2,\n\t finishSpeedPercent: 0.5,\n\t leftOffsetPercentage: 0.8,\n\t selector: '.animate-blinds .item',\n\t startVelocity: 1100\n\t };\n\t\n\t // Apply defaults if properties are not passed\n\t if (typeof options === 'undefined') {\n\t options = {};\n\t }\n\t\n\t options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n\t options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n\t options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n\t options.startVelocity = options.startVelocity || defaults.startVelocity;\n\t\n\t if (typeof options.selector == 'undefined') {\n\t options.selector = defaults.selector;\n\t }\n\t\n\t // Fail early & silently log\n\t var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\t\n\t if (isInvalidSelector) {\n\t console.log('invalid blinds selector');\n\t return false;\n\t }\n\t\n\t var animateBlindsDom = document.querySelectorAll(options.selector);\n\t var elementsCount = animateBlindsDom.length;\n\t var elementAnimationCount = 0;\n\t\n\t // Count the elements within the starting viewport so we're not exacting\n\t // more effort than required...\n\t //\n\t // We use css visiblity: hidden instead of display: none so the elements\n\t // maintain their DOM flow\n\t\n\t var viewportHeight = getViewportHeight();\n\t for (var i = 0; i < elementsCount; i++) {\n\t if (animateBlindsDom[i].offsetTop < viewportHeight) {\n\t elementAnimationCount += 1;\n\t continue;\n\t }\n\t break;\n\t }\n\t\n\t // Sequentially animate with a delay based on proximity\n\t var speed = options.startVelocity;\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateBlindsDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delay = parseFloat(offset / speed).toFixed(2);\n\t child.style.webkitTransitionDelay = delay + \"s\";\n\t child.style.transitionDelay = delay + \"s\";\n\t child.className += ' in';\n\t }\n\t\n\t // When we're done animating, switch the class to 'done'\n\t setTimeout(function() {\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateBlindsDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delay = parseFloat(offset / speed / options.finishDelayThrottle).toFixed(2);\n\t //child.querySelector('img').style.webkitTransitionDelay = delay + \"s\";\n\t //child.querySelector('img').style.transitionDelay = delay + \"s\";\n\t //child.querySelector('img').className += ' in';\n\t animateBlindsDom[i].className += ' done';\n\t }\n\t\n\t }, speed * options.finishSpeedPercent);\n\t\n\t // Load the elements without effect\n\t showNotAnimatedElements(animateBlindsDom, elementsCount);\n\t }\n\t\n\t function fadeSlideIn(options) {\n\t\n\t // Declare our defaults\n\t var defaults = {\n\t finishDelayThrottle: 2,\n\t finishSpeedPercent: 0.72,\n\t leftOffsetPercentage: 0.8,\n\t selector: '.animate-fade-slide-in .item',\n\t startVelocity: 1100\n\t };\n\t\n\t // Apply defaults if properties are not passed\n\t if (typeof options === 'undefined') {\n\t options = {};\n\t }\n\t\n\t options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n\t options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n\t options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n\t options.startVelocity = options.startVelocity || defaults.startVelocity;\n\t\n\t if (typeof options.selector == 'undefined') {\n\t options.selector = defaults.selector;\n\t }\n\t\n\t // Fail early & silently log\n\t var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\t\n\t if (isInvalidSelector) {\n\t console.log('invalid fadeSlideIn selector');\n\t return false;\n\t }\n\t\n\t var animateFadeSlideInDom = document.querySelectorAll(options.selector);\n\t var elementsCount = animateFadeSlideInDom.length;\n\t var elementAnimationCount = 0;\n\t\n\t // Count the elements within the starting viewport so we're not exacting\n\t // more effort than required...\n\t //\n\t // We use css visiblity: hidden instead of display: none so the elements\n\t // maintain their DOM flow\n\t\n\t var viewportHeight = getViewportHeight();\n\t for (var i = 0; i < elementsCount; i++) {\n\t if (animateFadeSlideInDom[i].offsetTop < viewportHeight) {\n\t elementAnimationCount += 1;\n\t continue;\n\t }\n\t break;\n\t }\n\t\n\t // Sequentially animate with a delay based on proximity\n\t var speed = options.startVelocity;\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateFadeSlideInDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delay = parseFloat(offset / speed).toFixed(2);\n\t child.style.webkitTransitionDelay = delay + \"s\";\n\t child.style.transitionDelay = delay + \"s\";\n\t child.className += ' in';\n\t }\n\t\n\t // When we're done animating, switch the class to 'done'\n\t setTimeout(function() {\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateFadeSlideInDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delayValue = offset / speed / options.finishDelayThrottle;\n\t var delay = parseFloat(delayValue).toFixed(2);\n\t }\n\t animateFadeSlideInDom[0].className += ' done';\n\t\n\t }, speed * options.finishSpeedPercent);\n\t\n\t // Load the elements without effect\n\t showNotAnimatedElements(animateFadeSlideInDom, elementsCount);\n\t }\n\t\n\t function fadeSlideInRight(options) {\n\t\n\t // Declare our defaults\n\t var defaults = {\n\t finishDelayThrottle: 2,\n\t finishSpeedPercent: 0.72,\n\t leftOffsetPercentage: 0.8,\n\t selector: '.animate-fade-slide-in-right .item',\n\t startVelocity: 1100\n\t };\n\t\n\t // Apply defaults if properties are not passed\n\t if (typeof options === 'undefined') {\n\t options = {};\n\t }\n\t\n\t options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n\t options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n\t options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n\t options.startVelocity = options.startVelocity || defaults.startVelocity;\n\t\n\t if (typeof options.selector == 'undefined') {\n\t options.selector = defaults.selector;\n\t }\n\t\n\t // Fail early & silently log\n\t var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\t\n\t if (isInvalidSelector) {\n\t console.log('invalid fadeSlideInRight selector');\n\t return false;\n\t }\n\t\n\t var animateSlideInRightDom = document.querySelectorAll(options.selector);\n\t var elementsCount = animateSlideInRightDom.length;\n\t var elementAnimationCount = 0;\n\t\n\t // Count the elements within the starting viewport so we're not\n\t // exacting more effort than required...\n\t //\n\t // We use css visiblity: hidden instead of display: none so the\n\t // elements maintain their DOM flow\n\t\n\t var viewportHeight = getViewportHeight();\n\t for (var i = 0; i < elementsCount; i++) {\n\t if (animateSlideInRightDom[i].offsetTop < viewportHeight) {\n\t elementAnimationCount += 1;\n\t continue;\n\t }\n\t break;\n\t }\n\t\n\t // Sequentially animate with a delay based on proximity\n\t var speed = options.startVelocity;\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateSlideInRightDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delay = parseFloat(offset / speed).toFixed(2);\n\t child.style.webkitTransitionDelay = delay + \"s\";\n\t child.style.transitionDelay = delay + \"s\";\n\t child.className += ' in';\n\t }\n\t\n\t // When we're done animating, switch the class to 'done'\n\t setTimeout(function() {\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateSlideInRightDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delayValue = offset / speed / options.finishDelayThrottle;\n\t var delay = parseFloat(delayValue).toFixed(2);\n\t }\n\t animateSlideInRightDom[0].className += ' done';\n\t\n\t }, speed * options.finishSpeedPercent);\n\t\n\t // Load the elements without effect\n\t showNotAnimatedElements(animateSlideInRightDom, elementsCount);\n\t\n\t }\n\t\n\t function ripple(options) {\n\t\n\t // Declare our defaults\n\t var defaults = {\n\t finishDelayThrottle: 2,\n\t finishSpeedPercent: 0.72,\n\t leftOffsetPercentage: 0.8,\n\t selector: '.animate-ripple .item',\n\t startVelocity: 1100\n\t };\n\t\n\t // Apply defaults if properties are not passed\n\t if (typeof options === 'undefined') {\n\t options = {};\n\t }\n\t\n\t options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n\t options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n\t options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n\t options.startVelocity = options.startVelocity || defaults.startVelocity;\n\t\n\t if (typeof options.selector == 'undefined') {\n\t options.selector = defaults.selector;\n\t }\n\t\n\t // Fail early & silently log\n\t var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\t\n\t if (isInvalidSelector) {\n\t console.log('invalid ripple selector');\n\t return false;\n\t }\n\t\n\t var animateRippleDom = document.querySelectorAll(options.selector);\n\t var elementsCount = animateRippleDom.length;\n\t var elementAnimationCount = 0;\n\t\n\t // Count the elements within the starting viewport so we're not\n\t // exacting more effort than required...\n\t //\n\t // We use css visiblity: hidden instead of display: none so the\n\t // elements maintain their DOM flow\n\t\n\t var viewportHeight = getViewportHeight();\n\t for (var i = 0; i < animateRippleDom.length; i++) {\n\t if (animateRippleDom[i].offsetTop < viewportHeight) {\n\t elementAnimationCount += 1;\n\t continue;\n\t }\n\t break;\n\t }\n\t\n\t // Sequentially animate with a delay based on proximity\n\t var speed = options.startVelocity;\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateRippleDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delay = parseFloat(offset / speed).toFixed(2);\n\t child.style.webkitTransitionDelay = delay + \"s\";\n\t child.style.transitionDelay = delay + \"s\";\n\t child.className += ' in';\n\t }\n\t\n\t // When we're done animating, switch the class to 'done'\n\t setTimeout(function() {\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var child = animateRippleDom[i];\n\t var childOffset = child.getBoundingClientRect();\n\t var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n\t var delayValue = offset / speed / options.finishDelayThrottle;\n\t var delay = parseFloat(delayValue).toFixed(2);\n\t }\n\t animateRippleDom[0].className += ' done';\n\t\n\t }, speed * options.finishSpeedPercent);\n\t\n\t // Load the elements without effect\n\t showNotAnimatedElements(animateRippleDom, elementsCount);\n\t }\n\t\n\t function panInLeft(options) {\n\t\n\t // We have a single option, so it may be passed as a string or property\n\t if (typeof options === 'string') {\n\t options = {\n\t selector: options\n\t };\n\t }\n\t\n\t // Fail early & silently log\n\t var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\t\n\t if (isInvalidSelector) {\n\t console.log('invalid pushDown selector');\n\t return false;\n\t }\n\t\n\t var animatePanInLeftDom = document.querySelectorAll(options.selector);\n\t var elementAnimationCount = animatePanInLeftDom.length;\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var element = animatePanInLeftDom[i];\n\t var classNameToRemove = 'animate-pan-in-left';\n\t var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove);\n\t element.className = element.className.substr(0, indexOfClassNameToRemove);\n\t }\n\t }\n\t\n\t function pushDown(options) {\n\t\n\t // We have a single option, so it may be passed as a string or property\n\t if (typeof options === 'string') {\n\t options = {\n\t selector: options\n\t };\n\t }\n\t\n\t // Fail early & silently log\n\t var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\t\n\t if (isInvalidSelector) {\n\t console.log('invalid pushDown selector');\n\t return false;\n\t }\n\t\n\t var animatePushDownDom = document.querySelectorAll(options.selector);\n\t var elementAnimationCount = animatePushDownDom.length;\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var element = animatePushDownDom[i];\n\t var classNameToRemove = options.selector.split('.')[1];\n\t var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove);\n\t element.className = element.className.substr(0, indexOfClassNameToRemove);\n\t }\n\t }\n\t\n\t function slideUp(options) {\n\t\n\t // We have a single option, so it may be passed as a string or property\n\t if (typeof options === 'string') {\n\t options = {\n\t selector: options\n\t };\n\t }\n\t\n\t // Fail early & silently log\n\t var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\t\n\t if (isInvalidSelector) {\n\t console.log('invalid pushDown selector');\n\t return false;\n\t }\n\t\n\t var animateSlideUpDom = document.querySelectorAll(options.selector);\n\t var elementAnimationCount = animateSlideUpDom.length;\n\t for (var i = 0; i < elementAnimationCount; i++) {\n\t var element = animateSlideUpDom[i];\n\t var classNameToRemove = options.selector.split('.')[1];\n\t var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove);\n\t element.className = element.className.substr(0, indexOfClassNameToRemove);\n\t }\n\t }\n\t\n\t /* Export object\n\t /============================================================================*/\n\t return motion;\n\t }\n\t\n\t Motion.$inject = [];\n\t};\n\n\n/***/ }\n/******/ ])\n});\n;\n\n\n/** WEBPACK FOOTER **\n ** ionic.material.min.js\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap aca4d68e3e47af1bef6a\n **/","/**\n * Ionic Material\n * \"Bundle Index\" / \"Entryfile\"\n * https://github.com/zachsoft/ionic-material\n *\n * Recommended: use a compiled version, especially in production!\n */\n\n'use strict';\n\nmodule.exports = (function(){\n\n var angular;\n\n try {\n angular = require('angular');\n } catch(err){ }\n\n if(!angular || !angular.version){\n /*global window: true*/\n angular = window.angular;\n /*global window: false*/\n }\n\n if(!angular || !angular.version){\n throw new Error('ionic-material could not load angular module :(');\n }\n\n // set up angular module\n var app = angular.module('ionic-material', ['ionic']);\n\n // Import Dependencies\n require('./lib/_ink')(app);\n require('./lib/_motion')(app);\n\n return 'ionic-material';\n})();\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/js/ionic-material.js\n ** module id = 0\n ** module chunks = 0\n **/","if(typeof __WEBPACK_EXTERNAL_MODULE_1__ === 'undefined') {var e = new Error(\"Cannot find module \\\"angular\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e;}\nmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n\n/*****************\n ** WEBPACK FOOTER\n ** external \"angular\"\n ** module id = 1\n ** module chunks = 0\n **/","'use strict';\n\n/*!\n * Fork by Zach Fitzgerald and other contributors of Ionic Material\n *\n * Waves v0.5.4\n * http://fian.my.id/Waves\n *\n * Copyright 2014 Alfiana E. Sibuea and other contributors\n *\n * Released under the MIT license\n * https://github.com/fians/Waves/blob/master/LICENSE\n *\n */\nmodule.exports = function (angularApp) {\n\n angularApp.factory('ionicMaterialInk', ink);\n\n function ink (){\n /*global document*/\n var Ink = Ink || {};\n\n // all DOM nodes\n var $$;\n\n // phantomJS throws an error when you try to use document.querySelectorAll.bind\n if(document && document.querySelectorAll && document.querySelectorAll.bind){\n try{\n // all DOM nodes\n $$ = document.querySelectorAll.bind(document);\n\n } catch(e){}\n } else if (window && window.angular && window.angular.element) {\n // we can use angular.element instead\n $$ = window.angular.element;\n } else {\n\n\n /**\n * mout.js 0.11.0 bind and slice polyfills (substitutes?)\n * TODO: pull out mout.js bind and slice molyfills and inject into material.ink\n */\n\n /**\n * Create slice of source array or array-like object\n */\n var slicePolyfill = function moutslicePolyfill(arr, start, end){\n var len = arr.length;\n /*jshint eqnull:true */\n if (start == null) {\n start = 0;\n } else if (start < 0) {\n start = Math.max(len + start, 0);\n } else {\n start = Math.min(start, len);\n }\n\n\n if (end == null) {\n\n end = len;\n } else if (end < 0) {\n end = Math.max(len + end, 0);\n } else {\n end = Math.min(end, len);\n }\n\n var result = [];\n while (start < end) {\n result.push(arr[start++]);\n }\n\n return result;\n };\n\n\n\n /**\n * Return a function that will execute in the given context, optionally adding any additional supplied parameters to the beginning of the arguments collection.\n * @param {Function} fn Function.\n * @param {object} context Execution context.\n * @param {rest} args Arguments (0...n arguments).\n * @return {Function} Wrapped Function.\n */\n var bindPolyfill = function moutBind(fn, context, args){\n var argsArr = slicePolyfill(arguments, 2); //curried args\n return function(){\n return fn.apply(context, argsArr.concat(slicePolyfill(arguments)));\n };\n };\n\n $$ = bindPolyfill(document.querySelectorAll, document);\n /*jshint ignore:end */\n }\n\n if (!$$){\n throw new Error('ionic material ink module could not create reference of DOM nodes');\n }\n\n // Find exact position of element\n function isWindow(obj) {\n return obj !== null && obj === obj.window;\n }\n\n function getWindow(elem) {\n return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;\n }\n\n function offset(elem) {\n var docElem, win,\n box = {\n top: 0,\n left: 0\n },\n doc = elem && elem.ownerDocument;\n\n docElem = doc.documentElement;\n\n if (typeof elem.getBoundingClientRect !== typeof undefined) {\n box = elem.getBoundingClientRect();\n }\n win = getWindow(doc);\n return {\n top: box.top + win.pageYOffset - docElem.clientTop,\n left: box.left + win.pageXOffset - docElem.clientLeft\n };\n }\n\n function hexToRgb(hex) {\n var result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16)\n } : null;\n }\n\n function convertStyle(obj) {\n var style = '';\n\n for (var a in obj) {\n if (obj.hasOwnProperty(a)) {\n style += (a + ':' + obj[a] + ';');\n }\n }\n\n return style;\n }\n\n var Effect = {\n\n // Effect delay\n duration: 500,\n\n show: function(e) {\n\n // Disable right click\n if (e.button === 2) {\n return false;\n }\n\n var el = this;\n\n // Create ripple\n var ripple = document.createElement('div');\n var customColor = this.dataset.inkColor;\n var customOpacity = this.dataset.inkOpacity;\n var hasCustomRipple = customColor || customOpacity;\n ripple.className = 'ink-ripple';\n el.appendChild(ripple);\n\n // Get click coordinate and element witdh\n var pos = offset(el);\n var relativeY = (e.pageY - pos.top);\n var relativeX = (e.pageX - pos.left);\n var scale = 'scale(' + ((el.clientWidth / 100) * 2.5) + ')';\n\n // Support for touch devices\n if ('touches' in e) {\n relativeY = (e.touches[0].pageY - pos.top);\n relativeX = (e.touches[0].pageX - pos.left);\n }\n\n // Attach data to element\n ripple.setAttribute('data-hold', Date.now());\n ripple.setAttribute('data-scale', scale);\n ripple.setAttribute('data-x', relativeX);\n ripple.setAttribute('data-y', relativeY);\n\n // Set ripple position\n var rippleStyle = {\n 'top': relativeY + 'px',\n 'left': relativeX + 'px'\n };\n\n ripple.className = ripple.className + ' ink-notransition';\n\n if (hasCustomRipple) {\n var colorRgb;\n if (customColor) {\n var fromHex = hexToRgb(customColor);\n colorRgb = fromHex.r + ',' + fromHex.g + ',' + fromHex.b;\n } else {\n colorRgb = '0,0,0';\n }\n if (!customOpacity) {\n customOpacity = 0.2;\n }\n var bg = 'rgba(' + colorRgb + ',' + customOpacity + ')';\n rippleStyle['background-color'] = bg;\n }\n\n ripple.setAttribute('style', convertStyle(rippleStyle));\n ripple.className = ripple.className.replace('ink-notransition', '');\n\n // Scale the ripple\n rippleStyle['-webkit-transform'] = scale;\n rippleStyle['-moz-transform'] = scale;\n rippleStyle['-ms-transform'] = scale;\n rippleStyle['-o-transform'] = scale;\n rippleStyle.transform = scale;\n rippleStyle.opacity = '1';\n\n rippleStyle['-webkit-transition-duration'] = Effect.duration + 'ms';\n rippleStyle['-moz-transition-duration'] = Effect.duration + 'ms';\n rippleStyle['-o-transition-duration'] = Effect.duration + 'ms';\n rippleStyle['transition-duration'] = Effect.duration + 'ms';\n\n ripple.setAttribute('style', convertStyle(rippleStyle));\n },\n\n hide: function() {\n\n var el = this;\n\n var width = el.clientWidth * 1.4;\n\n // Get first ripple\n var ripple = null;\n\n var childrenLength = el.children.length;\n\n for (var a = 0; a < childrenLength; a++) {\n if (el.children[a].className.indexOf('ink-ripple') !== -1) {\n ripple = el.children[a];\n continue;\n }\n }\n\n if (!ripple) {\n return false;\n }\n\n var relativeX = ripple.getAttribute('data-x');\n var relativeY = ripple.getAttribute('data-y');\n var scale = ripple.getAttribute('data-scale');\n\n // Get delay beetween mousedown and mouse leave\n var diff = Date.now() - Number(ripple.getAttribute('data-hold'));\n var delay = 500 - diff;\n\n if (delay < 0) {\n delay = 0;\n }\n\n // Fade out ripple after delay\n setTimeout(function() {\n\n var style = {\n 'top': relativeY + 'px',\n 'left': relativeX + 'px',\n 'opacity': '0',\n\n // Duration\n '-webkit-transition-duration': Effect.duration + 'ms',\n '-moz-transition-duration': Effect.duration + 'ms',\n '-o-transition-duration': Effect.duration + 'ms',\n 'transition-duration': Effect.duration + 'ms',\n '-webkit-transform': scale,\n '-moz-transform': scale,\n '-ms-transform': scale,\n '-o-transform': scale,\n 'transform': scale,\n };\n\n ripple.setAttribute('style', convertStyle(style));\n\n setTimeout(function() {\n try {\n el.removeChild(ripple);\n } catch (e) {\n return false;\n }\n }, Effect.duration);\n }, delay);\n },\n\n // Little hack to make <input> can perform ink effect\n wrapInput: function(elements) {\n\n for (var a = 0; a < elements.length; a++) {\n\n var el = elements[a];\n\n if (el.tagName.toLowerCase() === 'input') {\n\n var parent = el.parentNode;\n\n // If input already have parent just pass through\n if (parent.tagName.toLowerCase() === 'i' &&\n parent.className.indexOf('ink') !== -1 &&\n parent.className.indexOf('tab-item') !== -1 &&\n parent.className.indexOf('button-fab') !== -1 &&\n parent.className.indexOf('button-raised') !== -1 &&\n parent.className.indexOf('button-flat') !== -1 &&\n parent.className.indexOf('button-clear') !== -1 &&\n parent.className.indexOf('button') !== -1 &&\n parent.className.indexOf('item') !== -1) {\n return false;\n }\n\n // Put element class and style to the specified parent\n var wrapper = document.createElement('i');\n wrapper.className = el.className + ' ink-input-wrapper';\n\n var elementStyle = el.getAttribute('style');\n\n if (!elementStyle) {\n elementStyle = '';\n }\n\n wrapper.setAttribute('style', elementStyle);\n\n el.className = 'ink-button-input';\n el.removeAttribute('style');\n\n // Put element as child\n parent.replaceChild(wrapper, el);\n wrapper.appendChild(el);\n }\n }\n }\n };\n\n Ink.displayEffect = function(options) {\n options = options || {};\n\n if ('duration' in options) {\n Effect.duration = options.duration;\n }\n\n //Wrap input inside <i> tag\n var selectors = '.ink,.tab-item,.button-fab,.button-raised,.button-flat,.button-clear,a.item,.popup .button';\n Effect.wrapInput($$(selectors));\n\n Array.prototype.forEach.call($$(selectors), function(i) {\n if ('ontouchstart' in window) {\n i.addEventListener('touchstart', Effect.show, false);\n i.addEventListener('touchend', Effect.hide, false);\n i.addEventListener('touchcancel', Effect.hide, false);\n } else {\n i.addEventListener('mousedown', Effect.show, false);\n i.addEventListener('mouseup', Effect.hide, false);\n i.addEventListener('mouseleave', Effect.hide, false);\n }\n });\n };\n\n return Ink;\n }\n\n ink.inject = [];\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/js/lib/_ink.js\n ** module id = 2\n ** module chunks = 0\n **/","module.exports = function(angularApp) {\n angularApp.factory('ionicMaterialMotion', Motion);\n\n function Motion() {\n /*global document, window*/\n\n 'use strict';\n\n /*============================================================================*/\n /* HELPERS (non-exports)\n /=============================================================================*\n / Abstract common lookups and manipulations in case better alternatives\n / arise or future cross-platform differences warrant separate handling\n /=============================================================================*/\n\n function getViewportHeight() {\n return window.innerHeight;\n }\n\n function getBoundingClientRect(domNode) {\n return domNode.getBoundingClientRect;\n }\n\n function showNotAnimatedElements(elements, total) {\n // Load the elements without effect\n for (var i = 0; i < total; i++) {\n var child = elements[i];\n child.className += ' in';\n child.className += ' done';\n }\n }\n\n\n\n /*============================================================================*/\n /* MOTION (EXPORT)\n /=============================================================================*\n / Animation methods for the library\n /=============================================================================*/\n\n var motion = {\n blinds: blinds,\n fadeSlideIn: fadeSlideIn,\n fadeSlideInRight: fadeSlideInRight,\n panInLeft: panInLeft,\n pushDown: pushDown,\n ripple: ripple,\n slideUp: slideUp\n };\n\n function blinds(options) {\n\n // Declare our defaults\n var defaults = {\n finishDelayThrottle: 2,\n finishSpeedPercent: 0.5,\n leftOffsetPercentage: 0.8,\n selector: '.animate-blinds .item',\n startVelocity: 1100\n };\n\n // Apply defaults if properties are not passed\n if (typeof options === 'undefined') {\n options = {};\n }\n\n options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n options.startVelocity = options.startVelocity || defaults.startVelocity;\n\n if (typeof options.selector == 'undefined') {\n options.selector = defaults.selector;\n }\n\n // Fail early & silently log\n var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\n if (isInvalidSelector) {\n console.log('invalid blinds selector');\n return false;\n }\n\n var animateBlindsDom = document.querySelectorAll(options.selector);\n var elementsCount = animateBlindsDom.length;\n var elementAnimationCount = 0;\n\n // Count the elements within the starting viewport so we're not exacting\n // more effort than required...\n //\n // We use css visiblity: hidden instead of display: none so the elements\n // maintain their DOM flow\n\n var viewportHeight = getViewportHeight();\n for (var i = 0; i < elementsCount; i++) {\n if (animateBlindsDom[i].offsetTop < viewportHeight) {\n elementAnimationCount += 1;\n continue;\n }\n break;\n }\n\n // Sequentially animate with a delay based on proximity\n var speed = options.startVelocity;\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateBlindsDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delay = parseFloat(offset / speed).toFixed(2);\n child.style.webkitTransitionDelay = delay + \"s\";\n child.style.transitionDelay = delay + \"s\";\n child.className += ' in';\n }\n\n // When we're done animating, switch the class to 'done'\n setTimeout(function() {\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateBlindsDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delay = parseFloat(offset / speed / options.finishDelayThrottle).toFixed(2);\n //child.querySelector('img').style.webkitTransitionDelay = delay + \"s\";\n //child.querySelector('img').style.transitionDelay = delay + \"s\";\n //child.querySelector('img').className += ' in';\n animateBlindsDom[i].className += ' done';\n }\n\n }, speed * options.finishSpeedPercent);\n\n // Load the elements without effect\n showNotAnimatedElements(animateBlindsDom, elementsCount);\n }\n\n function fadeSlideIn(options) {\n\n // Declare our defaults\n var defaults = {\n finishDelayThrottle: 2,\n finishSpeedPercent: 0.72,\n leftOffsetPercentage: 0.8,\n selector: '.animate-fade-slide-in .item',\n startVelocity: 1100\n };\n\n // Apply defaults if properties are not passed\n if (typeof options === 'undefined') {\n options = {};\n }\n\n options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n options.startVelocity = options.startVelocity || defaults.startVelocity;\n\n if (typeof options.selector == 'undefined') {\n options.selector = defaults.selector;\n }\n\n // Fail early & silently log\n var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\n if (isInvalidSelector) {\n console.log('invalid fadeSlideIn selector');\n return false;\n }\n\n var animateFadeSlideInDom = document.querySelectorAll(options.selector);\n var elementsCount = animateFadeSlideInDom.length;\n var elementAnimationCount = 0;\n\n // Count the elements within the starting viewport so we're not exacting\n // more effort than required...\n //\n // We use css visiblity: hidden instead of display: none so the elements\n // maintain their DOM flow\n\n var viewportHeight = getViewportHeight();\n for (var i = 0; i < elementsCount; i++) {\n if (animateFadeSlideInDom[i].offsetTop < viewportHeight) {\n elementAnimationCount += 1;\n continue;\n }\n break;\n }\n\n // Sequentially animate with a delay based on proximity\n var speed = options.startVelocity;\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateFadeSlideInDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delay = parseFloat(offset / speed).toFixed(2);\n child.style.webkitTransitionDelay = delay + \"s\";\n child.style.transitionDelay = delay + \"s\";\n child.className += ' in';\n }\n\n // When we're done animating, switch the class to 'done'\n setTimeout(function() {\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateFadeSlideInDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delayValue = offset / speed / options.finishDelayThrottle;\n var delay = parseFloat(delayValue).toFixed(2);\n }\n animateFadeSlideInDom[0].className += ' done';\n\n }, speed * options.finishSpeedPercent);\n\n // Load the elements without effect\n showNotAnimatedElements(animateFadeSlideInDom, elementsCount);\n }\n\n function fadeSlideInRight(options) {\n\n // Declare our defaults\n var defaults = {\n finishDelayThrottle: 2,\n finishSpeedPercent: 0.72,\n leftOffsetPercentage: 0.8,\n selector: '.animate-fade-slide-in-right .item',\n startVelocity: 1100\n };\n\n // Apply defaults if properties are not passed\n if (typeof options === 'undefined') {\n options = {};\n }\n\n options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n options.startVelocity = options.startVelocity || defaults.startVelocity;\n\n if (typeof options.selector == 'undefined') {\n options.selector = defaults.selector;\n }\n\n // Fail early & silently log\n var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\n if (isInvalidSelector) {\n console.log('invalid fadeSlideInRight selector');\n return false;\n }\n\n var animateSlideInRightDom = document.querySelectorAll(options.selector);\n var elementsCount = animateSlideInRightDom.length;\n var elementAnimationCount = 0;\n\n // Count the elements within the starting viewport so we're not\n // exacting more effort than required...\n //\n // We use css visiblity: hidden instead of display: none so the\n // elements maintain their DOM flow\n\n var viewportHeight = getViewportHeight();\n for (var i = 0; i < elementsCount; i++) {\n if (animateSlideInRightDom[i].offsetTop < viewportHeight) {\n elementAnimationCount += 1;\n continue;\n }\n break;\n }\n\n // Sequentially animate with a delay based on proximity\n var speed = options.startVelocity;\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateSlideInRightDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delay = parseFloat(offset / speed).toFixed(2);\n child.style.webkitTransitionDelay = delay + \"s\";\n child.style.transitionDelay = delay + \"s\";\n child.className += ' in';\n }\n\n // When we're done animating, switch the class to 'done'\n setTimeout(function() {\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateSlideInRightDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delayValue = offset / speed / options.finishDelayThrottle;\n var delay = parseFloat(delayValue).toFixed(2);\n }\n animateSlideInRightDom[0].className += ' done';\n\n }, speed * options.finishSpeedPercent);\n\n // Load the elements without effect\n showNotAnimatedElements(animateSlideInRightDom, elementsCount);\n\n }\n\n function ripple(options) {\n\n // Declare our defaults\n var defaults = {\n finishDelayThrottle: 2,\n finishSpeedPercent: 0.72,\n leftOffsetPercentage: 0.8,\n selector: '.animate-ripple .item',\n startVelocity: 1100\n };\n\n // Apply defaults if properties are not passed\n if (typeof options === 'undefined') {\n options = {};\n }\n\n options.finishDelayThrottle = options.finishDelayThrottle || defaults.finishDelayThrottle;\n options.finishSpeedPercent = options.finishSpeedPercent || defaults.finishSpeedPercent;\n options.leftOffsetPercentage = options.leftOffsetPercentage || defaults.leftOffsetPercentage;\n options.startVelocity = options.startVelocity || defaults.startVelocity;\n\n if (typeof options.selector == 'undefined') {\n options.selector = defaults.selector;\n }\n\n // Fail early & silently log\n var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\n if (isInvalidSelector) {\n console.log('invalid ripple selector');\n return false;\n }\n\n var animateRippleDom = document.querySelectorAll(options.selector);\n var elementsCount = animateRippleDom.length;\n var elementAnimationCount = 0;\n\n // Count the elements within the starting viewport so we're not\n // exacting more effort than required...\n //\n // We use css visiblity: hidden instead of display: none so the\n // elements maintain their DOM flow\n\n var viewportHeight = getViewportHeight();\n for (var i = 0; i < animateRippleDom.length; i++) {\n if (animateRippleDom[i].offsetTop < viewportHeight) {\n elementAnimationCount += 1;\n continue;\n }\n break;\n }\n\n // Sequentially animate with a delay based on proximity\n var speed = options.startVelocity;\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateRippleDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delay = parseFloat(offset / speed).toFixed(2);\n child.style.webkitTransitionDelay = delay + \"s\";\n child.style.transitionDelay = delay + \"s\";\n child.className += ' in';\n }\n\n // When we're done animating, switch the class to 'done'\n setTimeout(function() {\n for (var i = 0; i < elementAnimationCount; i++) {\n var child = animateRippleDom[i];\n var childOffset = child.getBoundingClientRect();\n var offset = childOffset.left * options.leftOffsetPercentage + childOffset.top;\n var delayValue = offset / speed / options.finishDelayThrottle;\n var delay = parseFloat(delayValue).toFixed(2);\n }\n animateRippleDom[0].className += ' done';\n\n }, speed * options.finishSpeedPercent);\n\n // Load the elements without effect\n showNotAnimatedElements(animateRippleDom, elementsCount);\n }\n\n function panInLeft(options) {\n\n // We have a single option, so it may be passed as a string or property\n if (typeof options === 'string') {\n options = {\n selector: options\n };\n }\n\n // Fail early & silently log\n var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\n if (isInvalidSelector) {\n console.log('invalid pushDown selector');\n return false;\n }\n\n var animatePanInLeftDom = document.querySelectorAll(options.selector);\n var elementAnimationCount = animatePanInLeftDom.length;\n for (var i = 0; i < elementAnimationCount; i++) {\n var element = animatePanInLeftDom[i];\n var classNameToRemove = 'animate-pan-in-left';\n var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove);\n element.className = element.className.substr(0, indexOfClassNameToRemove);\n }\n }\n\n function pushDown(options) {\n\n // We have a single option, so it may be passed as a string or property\n if (typeof options === 'string') {\n options = {\n selector: options\n };\n }\n\n // Fail early & silently log\n var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\n if (isInvalidSelector) {\n console.log('invalid pushDown selector');\n return false;\n }\n\n var animatePushDownDom = document.querySelectorAll(options.selector);\n var elementAnimationCount = animatePushDownDom.length;\n for (var i = 0; i < elementAnimationCount; i++) {\n var element = animatePushDownDom[i];\n var classNameToRemove = options.selector.split('.')[1];\n var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove);\n element.className = element.className.substr(0, indexOfClassNameToRemove);\n }\n }\n\n function slideUp(options) {\n\n // We have a single option, so it may be passed as a string or property\n if (typeof options === 'string') {\n options = {\n selector: options\n };\n }\n\n // Fail early & silently log\n var isInvalidSelector = typeof options.selector === 'undefined' || options.selector === '';\n\n if (isInvalidSelector) {\n console.log('invalid pushDown selector');\n return false;\n }\n\n var animateSlideUpDom = document.querySelectorAll(options.selector);\n var elementAnimationCount = animateSlideUpDom.length;\n for (var i = 0; i < elementAnimationCount; i++) {\n var element = animateSlideUpDom[i];\n var classNameToRemove = options.selector.split('.')[1];\n var indexOfClassNameToRemove = element.className.lastIndexOf(classNameToRemove);\n element.className = element.className.substr(0, indexOfClassNameToRemove);\n }\n }\n\n /* Export object\n /============================================================================*/\n return motion;\n }\n\n Motion.$inject = [];\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./src/js/lib/_motion.js\n ** module id = 3\n ** module chunks = 0\n **/"],"sourceRoot":""} \ No newline at end of file diff --git a/www/lib/ionic/js/ionic.min.js b/www/lib/ionic/js/ionic.min.js index 81efd4dffbcc53b4b861fea1e01688b19742831b..8fd42028e05d094d6ba92d9f54df70f5ee083a15 100644 --- a/www/lib/ionic/js/ionic.min.js +++ b/www/lib/ionic/js/ionic.min.js @@ -1,8 +1,8 @@ /*! - * Copyright 2014 Drifty Co. + * Copyright 2015 Drifty Co. * http://drifty.com/ * - * Ionic, v1.0.1 + * Ionic, v1.2.4 * A powerful HTML5 mobile app framework. * http://ionicframework.com/ * @@ -12,6 +12,9 @@ * */ -!function(){function e(e,t,n){t!==!1?F.addEventListener(e,J[e],n):F.removeEventListener(e,J[e])}function t(e){var t=T(e.target),i=E(t);if(ionic.tap.requiresNativeClick(i)||$)return!1;var o=ionic.tap.pointerCoord(e);n("click",i,o.x,o.y),h(i)}function n(e,t,n,i){var o=document.createEvent("MouseEvents");o.initMouseEvent(e,!0,!0,window,1,0,0,n,i,!1,!1,!1,!1,0,null),o.isIonicTap=!0,t.dispatchEvent(o)}function i(e){return"submit"==e.target.type&&0===e.detail?null:ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)||!e.isIonicTap&&!ionic.tap.requiresNativeClick(e.target)?(e.stopPropagation(),ionic.tap.isLabelWithTextInput(e.target)||e.preventDefault(),!1):void 0}function o(t){return t.isIonicTap||_(t)?null:X?(t.stopPropagation(),ionic.tap.isTextInput(t.target)&&B===t.target||/^(select|option)$/i.test(t.target.tagName)||t.preventDefault(),!1):($=!1,U=ionic.tap.pointerCoord(t),e("mousemove"),void ionic.activator.start(t))}function r(n){return X?(n.stopPropagation(),n.preventDefault(),!1):_(n)||/^(select|option)$/i.test(n.target.tagName)?!1:(v(n)||t(n),e("mousemove",!1),ionic.activator.end(),void($=!1))}function s(t){return v(t)?(e("mousemove",!1),ionic.activator.end(),$=!0,!1):void 0}function a(t){if(!_(t)&&($=!1,d(),U=ionic.tap.pointerCoord(t),e(K),ionic.activator.start(t),ionic.Platform.isIOS()&&ionic.tap.isLabelWithTextInput(t.target))){var n=E(T(t.target));n!==Y&&t.preventDefault()}}function l(e){_(e)||(d(),v(e)||(t(e),/^(select|option)$/i.test(e.target.tagName)&&e.preventDefault()),B=e.target,u())}function c(t){return v(t)?($=!0,e(K,!1),ionic.activator.end(),!1):void 0}function u(){e(K,!1),ionic.activator.end(),$=!1}function d(){X=!0,clearTimeout(W),W=setTimeout(function(){X=!1},600)}function _(e){return e.isTapHandled?!0:(e.isTapHandled=!0,ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)?(e.preventDefault(),!0):void 0)}function h(e){q=null;var t=!1;"SELECT"==e.tagName?(n("mousedown",e,0,0),e.focus&&e.focus(),t=!0):g()===e?t=!0:/^(input|textarea)$/i.test(e.tagName)||e.isContentEditable?(t=!0,e.focus&&e.focus(),e.value=e.value,X&&(q=e)):f(),t&&(g(e),ionic.trigger("ionic.focusin",{target:e},!0))}function f(){var e=g();e&&(/^(input|textarea|select)$/i.test(e.tagName)||e.isContentEditable)&&e.blur(),g(null)}function p(e){X&&ionic.tap.isTextInput(g())&&ionic.tap.isTextInput(q)&&q!==e.target&&(q.focus(),q=null),ionic.scroll.isScrolling=!1}function m(){g(null)}function g(e){return arguments.length&&(Y=e),Y||document.activeElement}function v(e){if(!e||1!==e.target.nodeType||!U||0===U.x&&0===U.y)return!1;var t=ionic.tap.pointerCoord(e),n=!(!e.target.classList||!e.target.classList.contains||"function"!=typeof e.target.classList.contains),i=n&&e.target.classList.contains("button")?j:Z;return Math.abs(U.x-t.x)>i||Math.abs(U.y-t.y)>i}function T(e,t){for(var n=e,i=0;6>i&&n;i++){if("LABEL"===n.tagName)return n;n=n.parentElement}return t!==!1?e:void 0}function E(e){if(e&&"LABEL"===e.tagName){if(e.control)return e.control;if(e.querySelector){var t=e.querySelector("input,textarea,select");if(t)return t}}return e}function S(){ionic.keyboard.isInitialized||(V()?(window.addEventListener("native.keyboardshow",ue),window.addEventListener("native.keyboardhide",y)):document.body.addEventListener("focusout",y),document.body.addEventListener("ionic.focusin",ce),document.body.addEventListener("focusin",ce),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!0)}function b(e){clearTimeout(ne),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),ionic.keyboard.height=e.keyboardHeight,se?M(A,!0):M(I,!0)}function w(e){return clearTimeout(ne),e.target&&!e.target.readOnly&&ionic.tap.isKeyboardElement(e.target)&&(ee=ionic.DomUtil.getParentWithClass(e.target,le))?(Q=e.target,ee.classList.contains("overflow-scroll")||(document.body.scrollTop=0,ee.scrollTop=0,ionic.requestAnimationFrame(function(){document.body.scrollTop=0,ee.scrollTop=0}),window.navigator.msPointerEnabled?document.addEventListener("MSPointerMove",x,!1):document.addEventListener("touchmove",x,!1)),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),document.addEventListener("keydown",L,!1),void(ionic.keyboard.isOpen||V()?ionic.keyboard.isOpen&&I():M(I,!0))):void(Q=null)}function y(){clearTimeout(ne),(ionic.keyboard.isOpen||ionic.keyboard.isOpening)&&(ionic.keyboard.isClosing=!0,ionic.keyboard.isOpening=!1),ne=setTimeout(function(){ionic.requestAnimationFrame(function(){se?M(function(){A(),N()},!1):M(N,!1)})},50)}function D(){ionic.keyboard.isLandscape=!ionic.keyboard.isLandscape,ionic.Platform.isIOS()&&A(),ionic.Platform.isAndroid()&&(ionic.keyboard.isOpen&&V()?se=!0:M(A,!1))}function L(e){ionic.scroll.isScrolling&&x(e)}function x(e){"TEXTAREA"!==e.target.tagName&&e.preventDefault()}function M(e,t){clearInterval(te);var n,i=0,o=k(),r=o;return n=ionic.Platform.isAndroid()&&ionic.Platform.version()<4.4?30:ionic.Platform.isAndroid()?10:1,te=setInterval(function(){r=k(),(!(++i<n)||(O(r)||P(r))&&ionic.keyboard.height)&&(V()||(ionic.keyboard.height=Math.abs(o-window.innerHeight)),ionic.keyboard.isOpen=t,clearInterval(te),e())},50),n}function N(){clearTimeout(ne),ionic.keyboard.isOpen=!1,ionic.keyboard.isClosing=!1,Q&&ionic.trigger("resetScrollView",{target:Q},!0),ionic.requestAnimationFrame(function(){document.body.classList.remove(ae)}),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerMove",x):document.removeEventListener("touchmove",x),document.removeEventListener("keydown",L),ionic.Platform.isAndroid()&&(V()&&cordova.plugins.Keyboard.close(),Q&&Q.blur()),Q=null}function I(){ionic.keyboard.isOpen=!0,ionic.keyboard.isOpening=!1;var e={keyboardHeight:C(),viewportHeight:ie};if(Q){e.target=Q;var t=Q.getBoundingClientRect();e.elementTop=Math.round(t.top),e.elementBottom=Math.round(t.bottom),e.windowHeight=e.viewportHeight-e.keyboardHeight,e.isElementUnderKeyboard=e.elementBottom>e.windowHeight,ionic.trigger("scrollChildIntoView",e,!0)}return setTimeout(function(){document.body.classList.add(ae)},400),e}function C(){if(ionic.keyboard.height)return ionic.keyboard.height;if(ionic.Platform.isAndroid()){if(ionic.Platform.isFullScreen)return 275;var e=window.innerHeight;return ie>e?ie-e:0}return ionic.Platform.isIOS()?ionic.keyboard.isLandscape?206:ionic.Platform.isWebView()?260:216:275}function O(e){return!!(!ionic.keyboard.isLandscape&&oe&&Math.abs(oe-e)<2)}function P(e){return!!(ionic.keyboard.isLandscape&&re&&Math.abs(re-e)<2)}function A(){se=!1,ie=k(),ionic.keyboard.isLandscape&&!re?re=ie:ionic.keyboard.isLandscape||oe||(oe=ie),Q&&ionic.trigger("resetScrollView",{target:Q},!0),ionic.keyboard.isOpen&&ionic.tap.isTextInput(Q)&&I()}function G(){var e=k();e/window.innerWidth<1&&(ionic.keyboard.isLandscape=!0),ie=e,ionic.keyboard.isLandscape&&!re?re=ie:ionic.keyboard.isLandscape||oe||(oe=ie)}function k(){var e=window.innerHeight;return ionic.Platform.isAndroid()&&ionic.Platform.isFullScreen||!ionic.keyboard.isOpen&&!ionic.keyboard.isOpening||ionic.keyboard.isClosing?e:e+C()}function V(){return!!(window.cordova&&cordova.plugins&&cordova.plugins.Keyboard)}function R(){var e;for(e=0;e<document.head.children.length;e++)if("viewport"==document.head.children[e].name){de=document.head.children[e];break}if(de){var t,n=de.content.toLowerCase().replace(/\s+/g,"").split(",");for(e=0;e<n.length;e++)n[e]&&(t=n[e].split("="),_e[t[0]]=t.length>1?t[1]:"_");z()}}function z(){var e=_e.width,t=_e.height,n=ionic.Platform,i=n.version(),o="device-width",r="device-height",s=ionic.viewport.orientation();delete _e.height,_e.width=o,n.isIPad()?i>7?delete _e.width:n.isWebView()?90==s?_e.height="0":7==i&&(_e.height=r):7>i&&(_e.height="0"):n.isIOS()&&(n.isWebView()?i>7?delete _e.width:7>i?t&&(_e.height="0"):7==i&&(_e.height=r):7>i&&t&&(_e.height="0")),(e!==_e.width||t!==_e.height)&&H()}function H(){var e,t=[];for(e in _e)_e[e]&&t.push(e+("_"==_e[e]?"":"="+_e[e]));de.content=t.join(", ")}window.ionic=window.ionic||{},window.ionic.views={},window.ionic.version="1.0.1",function(e){e.DelegateService=function(e){function t(){return!0}if(e.indexOf("$getByHandle")>-1)throw new Error("Method '$getByHandle' is implicitly added to each delegate service. Do not list it as a method.");return["$log",function(n){function i(e,t){this._instances=e,this.handle=t}function o(){this._instances=[]}function r(e){return function(){var t,i=this.handle,o=arguments,r=0;return this._instances.forEach(function(n){if((!i||i==n.$$delegateHandle)&&n.$$filterFn(n)){r++;var s=n[e].apply(n,o);1===r&&(t=s)}}),!r&&i?n.warn('Delegate for handle "'+i+'" could not find a corresponding element with delegate-handle="'+i+'"! '+e+"() was not called!\nPossible cause: If you are calling "+e+'() immediately, and your element with delegate-handle="'+i+'" is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to '+e+"() and try again."):t}}return e.forEach(function(e){i.prototype[e]=r(e)}),o.prototype=i.prototype,o.prototype._registerInstance=function(e,n,i){var o=this._instances;return e.$$delegateHandle=n,e.$$filterFn=i||t,o.push(e),function(){var t=o.indexOf(e);-1!==t&&o.splice(t,1)}},o.prototype.$getByHandle=function(e){return new i(this._instances,e)},new o}]}}(window.ionic),function(e,t,n){function i(){r=!0;for(var e=0;e<o.length;e++)n.requestAnimationFrame(o[e]);o=[],t.removeEventListener("DOMContentLoaded",i)}var o=[],r="complete"===t.readyState||"interactive"===t.readyState;r||t.addEventListener("DOMContentLoaded",i),e._rAF=function(){return e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||function(t){e.setTimeout(t,16)}}();var s=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame;n.DomUtil={requestAnimationFrame:function(t){return e._rAF(t)},cancelAnimationFrame:function(e){s(e)},animationFrameThrottle:function(e){var t,i,o;return function(){t=arguments,o=this,i||(i=!0,n.requestAnimationFrame(function(){e.apply(o,t),i=!1}))}},contains:function(e,t){for(var n=t;n;){if(n===e)return!0;n=n.parentNode}},getPositionInParent:function(e){return{left:e.offsetLeft,top:e.offsetTop}},ready:function(e){r?n.requestAnimationFrame(e):o.push(e)},getTextBounds:function(n){if(t.createRange){var i=t.createRange();if(i.selectNodeContents(n),i.getBoundingClientRect){var o=i.getBoundingClientRect();if(o){var r=e.scrollX,s=e.scrollY;return{top:o.top+s,left:o.left+r,right:o.left+r+o.width,bottom:o.top+s+o.height,width:o.width,height:o.height}}}}return null},getChildIndex:function(e,t){if(t)for(var n,i=e.parentNode.children,o=0,r=0,s=i.length;s>o;o++)if(n=i[o],n.nodeName&&n.nodeName.toLowerCase()==t){if(n==e)return r;r++}return Array.prototype.slice.call(e.parentNode.children).indexOf(e)},swapNodes:function(e,t){t.parentNode.insertBefore(e,t)},elementIsDescendant:function(e,t,n){var i=e;do{if(i===t)return!0;i=i.parentNode}while(i&&i!==n);return!1},getParentWithClass:function(e,t,n){for(n=n||10;e.parentNode&&n--;){if(e.parentNode.classList&&e.parentNode.classList.contains(t))return e.parentNode;e=e.parentNode}return null},getParentOrSelfWithClass:function(e,t,n){for(n=n||10;e&&n--;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},rectContains:function(e,t,n,i,o,r){return n>e||e>o?!1:i>t||t>r?!1:!0},blurAll:function(){return t.activeElement&&t.activeElement!=t.body?(t.activeElement.blur(),t.activeElement):null},cachedAttr:function(e,t,n){if(e=e&&e.length&&e[0]||e,e&&e.setAttribute){var i="$attr-"+t;return arguments.length>2?e[i]!==n&&(e.setAttribute(t,n),e[i]=n):"undefined"==typeof e[i]&&(e[i]=e.getAttribute(t)),e[i]}},cachedStyles:function(e,t){if(e=e&&e.length&&e[0]||e,e&&e.style)for(var n in t)e["$style-"+n]!==t[n]&&(e.style[n]=e["$style-"+n]=t[n])}},n.requestAnimationFrame=n.DomUtil.requestAnimationFrame,n.cancelAnimationFrame=n.DomUtil.cancelAnimationFrame,n.animationFrameThrottle=n.DomUtil.animationFrameThrottle}(window,document,ionic),function(e){e.CustomEvent=function(){if("function"==typeof window.CustomEvent)return CustomEvent;var e=function(e,t){var n;t=t||{bubbles:!1,cancelable:!1,detail:void 0};try{n=document.createEvent("CustomEvent"),n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail)}catch(i){n=document.createEvent("Event");for(var o in t)n[o]=t[o];n.initEvent(e,t.bubbles,t.cancelable)}return n};return e.prototype=window.Event.prototype,e}(),e.EventController={VIRTUALIZED_EVENTS:["tap","swipe","swiperight","swipeleft","drag","hold","release"],trigger:function(t,n,i,o){var r=new e.CustomEvent(t,{detail:n,bubbles:!!i,cancelable:!!o});n&&n.target&&n.target.dispatchEvent&&n.target.dispatchEvent(r)||window.dispatchEvent(r)},on:function(t,n,i){for(var o=i||window,r=0,s=this.VIRTUALIZED_EVENTS.length;s>r;r++)if(t==this.VIRTUALIZED_EVENTS[r]){var a=new e.Gesture(i);return a.on(t,n),a}o.addEventListener(t,n)},off:function(e,t,n){n.removeEventListener(e,t)},onGesture:function(t,n,i,o){var r=new e.Gesture(i,o);return r.on(t,n),r},offGesture:function(e,t,n){e&&e.off(t,n)},handlePopState:function(){}},e.on=function(){e.EventController.on.apply(e.EventController,arguments)},e.off=function(){e.EventController.off.apply(e.EventController,arguments)},e.trigger=e.EventController.trigger,e.onGesture=function(){return e.EventController.onGesture.apply(e.EventController.onGesture,arguments)},e.offGesture=function(){return e.EventController.offGesture.apply(e.EventController.offGesture,arguments)}}(window.ionic),function(e){function t(){if(!e.Gestures.READY){e.Gestures.event.determineEventTypes();for(var t in e.Gestures.gestures)e.Gestures.gestures.hasOwnProperty(t)&&e.Gestures.detection.register(e.Gestures.gestures[t]);e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_MOVE,e.Gestures.detection.detect),e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_END,e.Gestures.detection.detect),e.Gestures.READY=!0}}e.Gesture=function(t,n){return new e.Gestures.Instance(t,n||{})},e.Gestures={},e.Gestures.defaults={stop_browser_behavior:"disable-user-behavior"},e.Gestures.HAS_POINTEREVENTS=window.navigator.pointerEnabled||window.navigator.msPointerEnabled,e.Gestures.HAS_TOUCHEVENTS="ontouchstart"in window,e.Gestures.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android|silk/i,e.Gestures.NO_MOUSEEVENTS=e.Gestures.HAS_TOUCHEVENTS&&window.navigator.userAgent.match(e.Gestures.MOBILE_REGEX),e.Gestures.EVENT_TYPES={},e.Gestures.DIRECTION_DOWN="down",e.Gestures.DIRECTION_LEFT="left",e.Gestures.DIRECTION_UP="up",e.Gestures.DIRECTION_RIGHT="right",e.Gestures.POINTER_MOUSE="mouse",e.Gestures.POINTER_TOUCH="touch",e.Gestures.POINTER_PEN="pen",e.Gestures.EVENT_START="start",e.Gestures.EVENT_MOVE="move",e.Gestures.EVENT_END="end",e.Gestures.DOCUMENT=window.document,e.Gestures.plugins={},e.Gestures.READY=!1,e.Gestures.Instance=function(n,i){var o=this;return null===n?this:(t(),this.element=n,this.enabled=!0,this.options=e.Gestures.utils.extend(e.Gestures.utils.extend({},e.Gestures.defaults),i||{}),this.options.stop_browser_behavior&&e.Gestures.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),e.Gestures.event.onTouch(n,e.Gestures.EVENT_START,function(t){o.enabled&&e.Gestures.detection.startDetect(o,t)}),this)},e.Gestures.Instance.prototype={on:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.addEventListener(n[i],t,!1);return this},off:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.removeEventListener(n[i],t,!1);return this},trigger:function(t,n){var i=e.Gestures.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=n;var o=this.element;return e.Gestures.utils.hasParent(n.target,o)&&(o=n.target),o.dispatchEvent(i),this},enable:function(e){return this.enabled=e,this}};var n=null,i=!1,o=!1;e.Gestures.event={bindDom:function(e,t,n){for(var i=t.split(" "),o=0;o<i.length;o++)e.addEventListener(i[o],n,!1)},onTouch:function(t,r,s){var a=this;this.bindDom(t,e.Gestures.EVENT_TYPES[r],function(l){var c=l.type.toLowerCase();if(!c.match(/mouse/)||!o){c.match(/touch/)||c.match(/pointerdown/)||c.match(/mouse/)&&1===l.which?i=!0:c.match(/mouse/)&&1!==l.which&&(i=!1),c.match(/touch|pointer/)&&(o=!0);var u=0;i&&(e.Gestures.HAS_POINTEREVENTS&&r!=e.Gestures.EVENT_END?u=e.Gestures.PointerEvent.updatePointer(r,l):c.match(/touch/)?u=l.touches.length:o||(u=c.match(/up/)?0:1),u>0&&r==e.Gestures.EVENT_END?r=e.Gestures.EVENT_MOVE:u||(r=e.Gestures.EVENT_END),(u||null===n)&&(n=l),s.call(e.Gestures.detection,a.collectEventData(t,r,a.getTouchList(n,r),l)),e.Gestures.HAS_POINTEREVENTS&&r==e.Gestures.EVENT_END&&(u=e.Gestures.PointerEvent.updatePointer(r,l))),u||(n=null,i=!1,o=!1,e.Gestures.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getEvents():e.Gestures.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_START]=t[0],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_MOVE]=t[1],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_END]=t[2]},getTouchList:function(t){return e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getTouchList():t.touches?t.touches:(t.identifier=1,[t])},collectEventData:function(t,n,i,o){var r=e.Gestures.POINTER_TOUCH;return(o.type.match(/mouse/)||e.Gestures.PointerEvent.matchType(e.Gestures.POINTER_MOUSE,o))&&(r=e.Gestures.POINTER_MOUSE),{center:e.Gestures.utils.getCenter(i),timeStamp:(new Date).getTime(),target:o.target,touches:i,eventType:n,pointerType:r,srcEvent:o,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return e.Gestures.detection.stopDetect()}}}},e.Gestures.PointerEvent={pointers:{},getTouchList:function(){var e=this,t=[];return Object.keys(e.pointers).sort().forEach(function(n){t.push(e.pointers[n])}),t},updatePointer:function(t,n){return t==e.Gestures.EVENT_END?this.pointers={}:(n.identifier=n.pointerId,this.pointers[n.pointerId]=n),Object.keys(this.pointers).length},matchType:function(t,n){if(!n.pointerType)return!1;var i={};return i[e.Gestures.POINTER_MOUSE]=n.pointerType==n.MSPOINTER_TYPE_MOUSE||n.pointerType==e.Gestures.POINTER_MOUSE,i[e.Gestures.POINTER_TOUCH]=n.pointerType==n.MSPOINTER_TYPE_TOUCH||n.pointerType==e.Gestures.POINTER_TOUCH,i[e.Gestures.POINTER_PEN]=n.pointerType==n.MSPOINTER_TYPE_PEN||n.pointerType==e.Gestures.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},e.Gestures.utils={extend:function(e,t,n){for(var i in t)void 0!==e[i]&&n||(e[i]=t[i]);return e},hasParent:function(e,t){for(;e;){if(e==t)return!0;e=e.parentNode}return!1},getCenter:function(e){for(var t=[],n=[],i=0,o=e.length;o>i;i++)t.push(e[i].pageX),n.push(e[i].pageY);return{pageX:(Math.min.apply(Math,t)+Math.max.apply(Math,t))/2,pageY:(Math.min.apply(Math,n)+Math.max.apply(Math,n))/2}},getVelocity:function(e,t,n){return{x:Math.abs(t/e)||0,y:Math.abs(n/e)||0}},getAngle:function(e,t){var n=t.pageY-e.pageY,i=t.pageX-e.pageX;return 180*Math.atan2(n,i)/Math.PI},getDirection:function(t,n){var i=Math.abs(t.pageX-n.pageX),o=Math.abs(t.pageY-n.pageY);return i>=o?t.pageX-n.pageX>0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT:t.pageY-n.pageY>0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN},getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},getScale:function(e,t){return e.length>=2&&t.length>=2?this.getDistance(t[0],t[1])/this.getDistance(e[0],e[1]):1},getRotation:function(e,t){return e.length>=2&&t.length>=2?this.getAngle(t[1],t[0])-this.getAngle(e[1],e[0]):0},isVertical:function(t){return t==e.Gestures.DIRECTION_UP||t==e.Gestures.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(e,t){e&&e.classList&&(e.classList.add(t),e.onselectstart=function(){return!1})}},e.Gestures.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,n){this.current||(this.stopped=!1,this.current={inst:t,startEvent:e.Gestures.utils.extend({},n),lastEvent:!1,name:""},this.detect(n))},detect:function(t){if(!this.current||this.stopped)return null;t=this.extendEventData(t);for(var n=this.current.inst.options,i=0,o=this.gestures.length;o>i;i++){var r=this.gestures[i];if(!this.stopped&&n[r.name]!==!1&&r.handler.call(r,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==e.Gestures.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t},stopDetect:function(){this.previous=e.Gestures.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var n=this.current.startEvent;if(n&&(t.touches.length!=n.touches.length||t.touches===n.touches)){n.touches=[];for(var i=0,o=t.touches.length;o>i;i++)n.touches.push(e.Gestures.utils.extend({},t.touches[i]))}var r=t.timeStamp-n.timeStamp,s=t.center.pageX-n.center.pageX,a=t.center.pageY-n.center.pageY,l=e.Gestures.utils.getVelocity(r,s,a);return e.Gestures.utils.extend(t,{deltaTime:r,deltaX:s,deltaY:a,velocityX:l.x,velocityY:l.y,distance:e.Gestures.utils.getDistance(n.center,t.center),angle:e.Gestures.utils.getAngle(n.center,t.center),direction:e.Gestures.utils.getDirection(n.center,t.center),scale:e.Gestures.utils.getScale(n.touches,t.touches),rotation:e.Gestures.utils.getRotation(n.touches,t.touches),startEvent:n}),t},register:function(t){var n=t.defaults||{};return void 0===n[t.name]&&(n[t.name]=!0),e.Gestures.utils.extend(e.Gestures.defaults,n,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(e,t){return e.index<t.index?-1:e.index>t.index?1:0}),this.gestures}},e.Gestures.gestures=e.Gestures.gestures||{},e.Gestures.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:1},timer:null,handler:function(t,n){switch(t.eventType){case e.Gestures.EVENT_START:clearTimeout(this.timer),e.Gestures.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==e.Gestures.detection.current.name&&(e.tap.cancelClick(),n.trigger("hold",t))},n.options.hold_timeout);break;case e.Gestures.EVENT_MOVE:t.distance>n.options.hold_threshold&&clearTimeout(this.timer);break;case e.Gestures.EVENT_END:clearTimeout(this.timer)}}},e.Gestures.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END&&"touchcancel"!=t.srcEvent.type){var i=e.Gestures.detection.previous,o=!1;if(t.deltaTime>n.options.tap_max_touchtime||t.distance>n.options.tap_max_distance)return;i&&"tap"==i.name&&t.timeStamp-i.lastEvent.timeStamp<n.options.doubletap_interval&&t.distance<n.options.doubletap_distance&&(n.trigger("doubletap",t),o=!0),(!o||n.options.tap_always)&&(e.Gestures.detection.current.name="tap",n.trigger("tap",t))}}},e.Gestures.gestures.Swipe={name:"swipe",index:40,defaults:{swipe_max_touches:1,swipe_velocity:.4},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END){if(n.options.swipe_max_touches>0&&t.touches.length>n.options.swipe_max_touches)return;(t.velocityX>n.options.swipe_velocity||t.velocityY>n.options.swipe_velocity)&&(n.trigger(this.name,t),n.trigger(this.name+t.direction,t))}}},e.Gestures.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,correct_for_drag_min_distance:!0,drag_max_touches:1,drag_block_horizontal:!0,drag_block_vertical:!0,drag_lock_to_axis:!1,drag_lock_min_distance:25,prevent_default_directions:[]},triggered:!1,handler:function(t,n){if("touchstart"==t.srcEvent.type||"touchend"==t.srcEvent.type?this.preventedFirstMove=!1:this.preventedFirstMove||"touchmove"!=t.srcEvent.type||((0===n.options.prevent_default_directions.length||-1!=n.options.prevent_default_directions.indexOf(t.direction))&&t.srcEvent.preventDefault(),this.preventedFirstMove=!0),e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(n.options.drag_max_touches>0&&t.touches.length>n.options.drag_max_touches))switch(t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:if(t.distance<n.options.drag_min_distance&&e.Gestures.detection.current.name!=this.name)return;if(e.Gestures.detection.current.name!=this.name&&(e.Gestures.detection.current.name=this.name,n.options.correct_for_drag_min_distance)){var i=Math.abs(n.options.drag_min_distance/t.distance);e.Gestures.detection.current.startEvent.center.pageX+=t.deltaX*i,e.Gestures.detection.current.startEvent.center.pageY+=t.deltaY*i,t=e.Gestures.detection.extendEventData(t)}(e.Gestures.detection.current.lastEvent.drag_locked_to_axis||n.options.drag_lock_to_axis&&n.options.drag_lock_min_distance<=t.distance)&&(t.drag_locked_to_axis=!0);var o=e.Gestures.detection.current.lastEvent.direction;t.drag_locked_to_axis&&o!==t.direction&&(e.Gestures.utils.isVertical(o)?t.direction=t.deltaY<0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN:t.direction=t.deltaX<0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT),this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),n.trigger(this.name+t.direction,t),(n.options.drag_block_vertical&&e.Gestures.utils.isVertical(t.direction)||n.options.drag_block_horizontal&&!e.Gestures.utils.isVertical(t.direction))&&t.preventDefault();break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,n){if(e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(t.touches.length<2))switch(n.options.transform_always_block&&t.preventDefault(),t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:var i=Math.abs(1-t.scale),o=Math.abs(t.rotation);if(i<n.options.transform_min_scale&&o<n.options.transform_min_rotation)return;e.Gestures.detection.current.name=this.name,this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),o>n.options.transform_min_rotation&&n.trigger("rotate",t),i>n.options.transform_min_scale&&(n.trigger("pinch",t),n.trigger("pinch"+(t.scale<1?"in":"out"),t));break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Touch={name:"touch",index:-(1/0),defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,n){return n.options.prevent_mouseevents&&t.pointerType==e.Gestures.POINTER_MOUSE?void t.stopDetect():(n.options.prevent_default&&t.preventDefault(),void(t.eventType==e.Gestures.EVENT_START&&n.trigger(this.name,t)))}},e.Gestures.gestures.Release={name:"release",index:1/0,handler:function(t,n){t.eventType==e.Gestures.EVENT_END&&n.trigger(this.name,t)}}}(window.ionic),function(e,t,n){function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=new RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null===n?"":decodeURIComponent(n[1].replace(/\+/g," "))}function o(){d.isWebView()?t.addEventListener("deviceready",r,!1):r(),s&&e.removeEventListener("load",o,!1)}function r(){d.isReady=!0,d.detect();for(var e=0;e<f.length;e++)f[e]();f=[],n.trigger("platformready",{target:t}),u(function(){t.body.classList.add("platform-ready")})}var s,a="ios",l="android",c="windowsphone",u=n.requestAnimationFrame,d=n.Platform={navigator:e.navigator,isReady:!1,isFullScreen:!1,platforms:null,grade:null,ua:navigator.userAgent,ready:function(e){d.isReady?e():f.push(e)},detect:function(){d._checkPlatforms(),u(function(){for(var e=0;e<d.platforms.length;e++)t.body.classList.add("platform-"+d.platforms[e])})},setGrade:function(e){var n=d.grade;d.grade=e,u(function(){n&&t.body.classList.remove("grade-"+n),t.body.classList.add("grade-"+e)})},device:function(){return e.device||{}},_checkPlatforms:function(){d.platforms=[];var t="a";d.isWebView()?(d.platforms.push("webview"),e.cordova||e.PhoneGap||e.phonegap?d.platforms.push("cordova"):e.forge&&d.platforms.push("trigger")):d.platforms.push("browser"),d.isIPad()&&d.platforms.push("ipad");var n=d.platform();if(n){d.platforms.push(n);var i=d.version();if(i){var o=i.toString();o.indexOf(".")>0?o=o.replace(".","_"):o+="_0",d.platforms.push(n+o.split("_")[0]),d.platforms.push(n+o),d.isAndroid()&&4.4>i?t=4>i?"c":"b":d.isWindowsPhone()&&(t="b")}}d.setGrade(t)},isWebView:function(){return!!(e.cordova||e.PhoneGap||e.phonegap||e.forge)},isIPad:function(){return/iPad/i.test(d.navigator.platform)?!0:/iPad/i.test(d.ua)},isIOS:function(){return d.is(a)},isAndroid:function(){return d.is(l)},isWindowsPhone:function(){return d.is(c)},platform:function(){return null===_&&d.setPlatform(d.device().platform),_},setPlatform:function(e){_="undefined"!=typeof e&&null!==e&&e.length?e.toLowerCase():i("ionicplatform")?i("ionicplatform"):d.ua.indexOf("Android")>0?l:/iPhone|iPad|iPod/.test(d.ua)?a:d.ua.indexOf("Windows Phone")>-1?c:d.navigator.platform&&navigator.platform.toLowerCase().split(" ")[0]||""},version:function(){return null===h&&d.setVersion(d.device().version),h},setVersion:function(e){if("undefined"!=typeof e&&null!==e&&(e=e.split("."),e=parseFloat(e[0]+"."+(e.length>1?e[1]:0)),!isNaN(e)))return void(h=e);h=0;var t=d.platform(),n={android:/Android (\d+).(\d+)?/,ios:/OS (\d+)_(\d+)?/,windowsphone:/Windows Phone (\d+).(\d+)?/};n[t]&&(e=d.ua.match(n[t]),e&&e.length>2&&(h=parseFloat(e[1]+"."+e[2])))},is:function(e){if(e=e.toLowerCase(),d.platforms)for(var t=0;t<d.platforms.length;t++)if(d.platforms[t]===e)return!0;var n=d.platform();return n?n===e.toLowerCase():d.ua.toLowerCase().indexOf(e)>=0},exitApp:function(){d.ready(function(){navigator.app&&navigator.app.exitApp&&navigator.app.exitApp()})},showStatusBar:function(n){d._showStatusBar=n,d.ready(function(){u(function(){d._showStatusBar?(e.StatusBar&&e.StatusBar.show(),t.body.classList.remove("status-bar-hide")):(e.StatusBar&&e.StatusBar.hide(),t.body.classList.add("status-bar-hide"))})})},fullScreen:function(e,i){d.isFullScreen=e!==!1,n.DomUtil.ready(function(){u(function(){d.isFullScreen?t.body.classList.add("fullscreen"):t.body.classList.remove("fullscreen")}),d.showStatusBar(i===!0)})}},_=null,h=null,f=[];"complete"===t.readyState?o():(s=!0,e.addEventListener("load",o,!1))}(this,document,ionic),function(e,t){"use strict";t.CSS={},function(){var n,i=["webkitTransform","transform","-webkit-transform","webkit-transform","-moz-transform","moz-transform","MozTransform","mozTransform","msTransform"];for(n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSFORM=i[n];break}for(i=["webkitTransition","mozTransition","msTransition","transition"],n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSITION=i[n];break}var o=t.CSS.TRANSITION.indexOf("webkit")>-1;t.CSS.TRANSITION_DURATION=(o?"-webkit-":"")+"transition-duration",t.CSS.TRANSITIONEND=(o?"webkitTransitionEnd ":"")+"transitionend"}(),"classList"in e.documentElement||!Object.defineProperty||"undefined"==typeof HTMLElement||Object.defineProperty(HTMLElement.prototype,"classList",{get:function(){function e(e){return function(){var n,i=t.className.split(/\s+/);for(n=0;n<arguments.length;n++)e(i,i.indexOf(arguments[n]),arguments[n]);t.className=i.join(" ")}}var t=this;return{add:e(function(e,t,n){~t||e.push(n)}),remove:e(function(e,t){~t&&e.splice(t,1)}),toggle:e(function(e,t,n){~t?e.splice(t,1):e.push(n)}),contains:function(e){return!!~t.className.split(/\s+/).indexOf(e)},item:function(e){return t.className.split(/\s+/)[e]||null}}}})}(document,ionic);var F,Y,X,W,$,U,q,B,K="touchmove",Z=12,j=50,J={ -click:i,mousedown:o,mouseup:r,mousemove:s,touchstart:a,touchend:l,touchcancel:u,touchmove:c,pointerdown:a,pointerup:l,pointercancel:u,pointermove:c,MSPointerDown:a,MSPointerUp:l,MSPointerCancel:u,MSPointerMove:c,focusin:p,focusout:m};ionic.tap={register:function(t){return F=t,e("click",!0,!0),e("mouseup"),e("mousedown"),window.navigator.pointerEnabled?(e("pointerdown"),e("pointerup"),e("pointcancel"),K="pointermove"):window.navigator.msPointerEnabled?(e("MSPointerDown"),e("MSPointerUp"),e("MSPointerCancel"),K="MSPointerMove"):(e("touchstart"),e("touchend"),e("touchcancel")),e("focusin"),e("focusout"),function(){for(var t in J)e(t,!1);F=null,Y=null,X=!1,$=!1,U=null}},ignoreScrollStart:function(e){return e.defaultPrevented||/^(file|range)$/i.test(e.target.type)||"true"==(e.target.dataset?e.target.dataset.preventScroll:e.target.getAttribute("data-prevent-scroll"))||!!/^(object|embed)$/i.test(e.target.tagName)||ionic.tap.isElementTapDisabled(e.target)},isTextInput:function(e){return!!e&&("TEXTAREA"==e.tagName||"true"===e.contentEditable||"INPUT"==e.tagName&&!/^(radio|checkbox|range|file|submit|reset|color|image|button)$/i.test(e.type))},isDateInput:function(e){return!!e&&"INPUT"==e.tagName&&/^(date|time|datetime-local|month|week)$/i.test(e.type)},isKeyboardElement:function(e){return!ionic.Platform.isIOS()||ionic.Platform.isIPad()?ionic.tap.isTextInput(e)&&!ionic.tap.isDateInput(e):ionic.tap.isTextInput(e)||!!e&&"SELECT"==e.tagName},isLabelWithTextInput:function(e){var t=T(e,!1);return!!t&&ionic.tap.isTextInput(E(t))},containsOrIsTextInput:function(e){return ionic.tap.isTextInput(e)||ionic.tap.isLabelWithTextInput(e)},cloneFocusedInput:function(e){ionic.tap.hasCheckedClone||(ionic.tap.hasCheckedClone=!0,ionic.requestAnimationFrame(function(){var t=e.querySelector(":focus");if(ionic.tap.isTextInput(t)&&!ionic.tap.isDateInput(t)){var n=t.cloneNode(!0);n.value=t.value,n.classList.add("cloned-text-input"),n.readOnly=!0,t.isContentEditable&&(n.contentEditable=t.contentEditable,n.innerHTML=t.innerHTML),t.parentElement.insertBefore(n,t),t.classList.add("previous-input-focus"),n.scrollTop=t.scrollTop}}))},hasCheckedClone:!1,removeClonedInputs:function(e){ionic.tap.hasCheckedClone=!1,ionic.requestAnimationFrame(function(){var t,n=e.querySelectorAll(".cloned-text-input"),i=e.querySelectorAll(".previous-input-focus");for(t=0;t<n.length;t++)n[t].parentElement.removeChild(n[t]);for(t=0;t<i.length;t++)i[t].classList.remove("previous-input-focus"),i[t].style.top="",ionic.keyboard.isOpen&&!ionic.keyboard.isClosing&&i[t].focus()})},requiresNativeClick:function(e){return!e||e.disabled||/^(file|range)$/i.test(e.type)||/^(object|video)$/i.test(e.tagName)||ionic.tap.isLabelContainingFileInput(e)?!0:ionic.tap.isElementTapDisabled(e)},isLabelContainingFileInput:function(e){var t=T(e);if("LABEL"!==t.tagName)return!1;var n=t.querySelector("input[type=file]");return n&&n.disabled===!1?!0:!1},isElementTapDisabled:function(e){if(e&&1===e.nodeType)for(var t=e;t;){if("true"==(t.dataset?t.dataset.tapDisabled:t.getAttribute("data-tap-disabled")))return!0;t=t.parentElement}return!1},setTolerance:function(e,t){Z=e,j=t},cancelClick:function(){$=!0},pointerCoord:function(e){var t={x:0,y:0};if(e){var n=e.touches&&e.touches.length?e.touches:[e],i=e.changedTouches&&e.changedTouches[0]||n[0];i&&(t.x=i.clientX||i.pageX||0,t.y=i.clientY||i.pageY||0)}return t}},ionic.DomUtil.ready(function(){var e="undefined"!=typeof angular?angular:null;(!e||e&&!e.scenario)&&ionic.tap.register(document)}),function(e,t){"use strict";function n(){r={},t.requestAnimationFrame(o)}function i(){for(var e in r)r[e]&&(r[e].classList.add(l),s[e]=r[e]);r={}}function o(){if(t.transition&&t.transition.isActive)return void setTimeout(o,400);for(var e in s)s[e]&&(s[e].classList.remove(l),delete s[e])}var r={},s={},a=0,l="activated";t.activator={start:function(e){var n=t.tap.pointerCoord(e).x;n>0&&30>n||t.requestAnimationFrame(function(){if(!(t.scroll&&t.scroll.isScrolling||t.tap.requiresNativeClick(e.target))){for(var n,o=e.target,s=0;6>s&&(o&&1===o.nodeType);s++){if(n&&o.classList&&o.classList.contains("item")){n=o;break}if("A"==o.tagName||"BUTTON"==o.tagName||o.hasAttribute("ng-click")){n=o;break}if(o.classList.contains("button")){n=o;break}if("ION-CONTENT"==o.tagName||o.classList&&o.classList.contains("pane")||"BODY"==o.tagName)break;o=o.parentElement}n&&(r[a]=n,t.requestAnimationFrame(i),a=a>29?0:a+1)}})},end:function(){setTimeout(n,200)}}}(document,ionic),function(e){var t=0;e.Utils={arrayMove:function(e,t,n){if(n>=e.length)for(var i=n-e.length;i--+1;)e.push(void 0);return e.splice(n,0,e.splice(t,1)[0]),e},proxy:function(e,t){var n=Array.prototype.slice.call(arguments,2);return function(){return e.apply(t,n.concat(Array.prototype.slice.call(arguments)))}},debounce:function(e,t,n){var i,o,r,s,a;return function(){r=this,o=arguments,s=new Date;var l=function(){var c=new Date-s;t>c?i=setTimeout(l,t-c):(i=null,n||(a=e.apply(r,o)))},c=n&&!i;return i||(i=setTimeout(l,t)),c&&(a=e.apply(r,o)),a}},throttle:function(e,t,n){var i,o,r,s=null,a=0;n||(n={});var l=function(){a=n.leading===!1?0:Date.now(),s=null,r=e.apply(i,o)};return function(){var c=Date.now();a||n.leading!==!1||(a=c);var u=t-(c-a);return i=this,o=arguments,0>=u?(clearTimeout(s),s=null,a=c,r=e.apply(i,o)):s||n.trailing===!1||(s=setTimeout(l,u)),r}},inherit:function(t,n){var i,o=this;i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return o.apply(this,arguments)},e.extend(i,o,n);var r=function(){this.constructor=i};return r.prototype=o.prototype,i.prototype=new r,t&&e.extend(i.prototype,t),i.__super__=o.prototype,i},extend:function(e){for(var t=Array.prototype.slice.call(arguments,1),n=0;n<t.length;n++){var i=t[n];if(i)for(var o in i)e[o]=i[o]}return e},nextUid:function(){return"ion"+t++},disconnectScope:function(e){if(e&&e.$root!==e){var t=e.$parent;e.$$disconnected=!0,e.$broadcast("$ionic.disconnectScope",e),t.$$childHead===e&&(t.$$childHead=e.$$nextSibling),t.$$childTail===e&&(t.$$childTail=e.$$prevSibling),e.$$prevSibling&&(e.$$prevSibling.$$nextSibling=e.$$nextSibling),e.$$nextSibling&&(e.$$nextSibling.$$prevSibling=e.$$prevSibling),e.$$nextSibling=e.$$prevSibling=null}},reconnectScope:function(e){if(e&&e.$root!==e&&e.$$disconnected){var t=e.$parent;e.$$disconnected=!1,e.$broadcast("$ionic.reconnectScope",e),e.$$prevSibling=t.$$childTail,t.$$childHead?(t.$$childTail.$$nextSibling=e,t.$$childTail=e):t.$$childHead=t.$$childTail=e}},isScopeDisconnected:function(e){for(var t=e;t;){if(t.$$disconnected)return!0;t=t.$parent}return!1}},e.inherit=e.Utils.inherit,e.extend=e.Utils.extend,e.throttle=e.Utils.throttle,e.proxy=e.Utils.proxy,e.debounce=e.Utils.debounce}(window.ionic);var Q,ee,te,ne,ie=0,oe=0,re=0,se=!1,ae="keyboard-open",le="scroll-content",ce=ionic.debounce(w,200,!0),ue=ionic.debounce(b,100,!0);ionic.keyboard={isOpen:!1,isClosing:!1,isOpening:!1,height:0,isLandscape:!1,isInitialized:!1,hide:function(){V()&&cordova.plugins.Keyboard.close(),Q&&Q.blur()},show:function(){V()&&cordova.plugins.Keyboard.show()},disable:function(){V()?(window.removeEventListener("native.keyboardshow",ue),window.removeEventListener("native.keyboardhide",y)):document.body.removeEventListener("focusout",y),document.body.removeEventListener("ionic.focusin",ce),document.body.removeEventListener("focusin",ce),window.removeEventListener("orientationchange",D),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!1},enable:function(){S()}},ie=k(),ionic.Platform.ready(function(){G(),window.addEventListener("orientationchange",D),setTimeout(G,999),window.navigator.msPointerEnabled?document.addEventListener("MSPointerDown",S,!1):document.addEventListener("touchstart",S,!1)});var de,_e={};ionic.viewport={orientation:function(){return window.innerWidth>window.innerHeight?90:0}},ionic.Platform.ready(function(){R(),window.addEventListener("orientationchange",function(){setTimeout(z,1e3)},!1)}),function(e){"use strict";e.views.View=function(){this.initialize.apply(this,arguments)},e.views.View.inherit=e.inherit,e.extend(e.views.View.prototype,{initialize:function(){}})}(window.ionic);var he={effect:{}};!function(e){var t=Date.now||function(){return+new Date},n=60,i=1e3,o={},r=1;he.effect.Animate={requestAnimationFrame:function(){var t=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame,n=!!t;if(t&&!/requestAnimationFrame\(\)\s*\{\s*\[native code\]\s*\}/i.test(t.toString())&&(n=!1),n)return function(e,n){t(e,n)};var i=60,o={},r=0,s=1,a=null,l=+new Date;return function(e){var t=s++;return o[t]=e,r++,null===a&&(a=setInterval(function(){var e=+new Date,t=o;o={},r=0;for(var n in t)t.hasOwnProperty(n)&&(t[n](e),l=e);e-l>2500&&(clearInterval(a),a=null)},1e3/i)),t}}(),stop:function(e){var t=null!=o[e];return t&&(o[e]=null),t},isRunning:function(e){return null!=o[e]},start:function(e,s,a,l,c,u){var d=t(),_=d,h=0,f=0,p=r++;if(u||(u=document.body),p%20===0){var m={};for(var g in o)m[g]=!0;o=m}var v=function(r){var m=r!==!0,g=t();if(!o[p]||s&&!s(p))return o[p]=null,void(a&&a(n-f/((g-d)/i),p,!1));if(m)for(var T=Math.round((g-_)/(i/n))-1,E=0;E<Math.min(T,4);E++)v(!0),f++;l&&(h=(g-d)/l,h>1&&(h=1));var S=c?c(h):h;e(S,g,m)!==!1&&1!==h||!m?m&&(_=g,he.effect.Animate.requestAnimationFrame(v,u)):(o[p]=null,a&&a(n-f/((g-d)/i),p,1===h||null==l))};return o[p]=!0,he.effect.Animate.requestAnimationFrame(v,u),p}}}(this),function(e){var t=function(){},n=function(e){return Math.pow(e-1,3)+1},i=function(e){return(e/=.5)<1?.5*Math.pow(e,3):.5*(Math.pow(e-2,3)+2)};e.views.Scroll=e.views.View.inherit({initialize:function(n){var i=this;i.__container=n.el,i.__content=n.el.firstElementChild,setTimeout(function(){i.__container&&i.__content&&(i.__container.scrollTop=0,i.__content.scrollTop=0)}),i.options={scrollingX:!1,scrollbarX:!0,scrollingY:!0,scrollbarY:!0,startX:0,startY:0,wheelDampen:6,minScrollbarSizeX:5,minScrollbarSizeY:5,scrollbarsFade:!0,scrollbarFadeDelay:300,scrollbarResizeFadeDelay:1e3,animating:!0,animationDuration:250,decelVelocityThreshold:4,decelVelocityThresholdPaging:4,bouncing:!0,locking:!0,paging:!1,snapping:!1,zooming:!1,minZoom:.5,maxZoom:3,speedMultiplier:1,deceleration:.97,preventDefault:!1,scrollingComplete:t,penetrationDeceleration:.03,penetrationAcceleration:.08,scrollEventInterval:10,freeze:!1,getContentWidth:function(){return Math.max(i.__content.scrollWidth,i.__content.offsetWidth)},getContentHeight:function(){return Math.max(i.__content.scrollHeight,i.__content.offsetHeight+2*i.__content.offsetTop)}};for(var o in n)i.options[o]=n[o];i.hintResize=e.debounce(function(){i.resize()},1e3,!0),i.onScroll=function(){e.scroll.isScrolling?(clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)):setTimeout(i.setScrollStart,50)},i.freeze=function(e){return arguments.length&&(i.options.freeze=e),i.options.freeze},i.setScrollStart=function(){e.scroll.isScrolling=Math.abs(e.scroll.lastTop-i.__scrollTop)>1,clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)},i.setScrollStop=function(){e.scroll.isScrolling=!1,e.scroll.lastTop=i.__scrollTop},i.triggerScrollEvent=e.throttle(function(){i.onScroll(),e.trigger("scroll",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.options.scrollEventInterval),i.triggerScrollEndEvent=function(){e.trigger("scrollend",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.__scrollLeft=i.options.startX,i.__scrollTop=i.options.startY,i.__callback=i.getRenderFn(),i.__initEventHandlers(),i.__createScrollbars()},run:function(){this.resize(),this.__fadeScrollbars("out",this.options.scrollbarResizeFadeDelay)},__isSingleTouch:!1,__isTracking:!1,__didDecelerationComplete:!1,__isGesturing:!1,__isDragging:!1,__isDecelerating:!1,__isAnimating:!1,__clientLeft:0,__clientTop:0,__clientWidth:0,__clientHeight:0,__contentWidth:0,__contentHeight:0,__snapWidth:100,__snapHeight:100,__refreshHeight:null,__refreshActive:!1,__refreshActivate:null,__refreshDeactivate:null,__refreshStart:null,__zoomLevel:1,__scrollLeft:0,__scrollTop:0,__maxScrollLeft:0,__maxScrollTop:0,__scheduledLeft:0,__scheduledTop:0,__scheduledZoom:0,__lastTouchLeft:null,__lastTouchTop:null,__lastTouchMove:null,__positions:null,__minDecelerationScrollLeft:null,__minDecelerationScrollTop:null,__maxDecelerationScrollLeft:null,__maxDecelerationScrollTop:null,__decelerationVelocityX:null,__decelerationVelocityY:null,__transformProperty:null,__perspectiveProperty:null,__indicatorX:null,__indicatorY:null,__scrollbarFadeTimeout:null,__didWaitForSize:null,__sizerTimeout:null,__initEventHandlers:function(){function t(e){return e.touches&&e.touches.length?e.touches:[{pageX:e.pageX,pageY:e.pageY}]}var n,i=this,o=i.__container;if(i.scrollChildIntoView=function(t){var r=o.getBoundingClientRect().bottom;n=o.offsetHeight;var s=i.isShrunkForKeyboard,a=o.parentNode.classList.contains("modal"),l=a&&window.innerWidth>=680;if(!s){if(e.Platform.isIOS()||e.Platform.isFullScreen||l){var c=t.detail.viewportHeight-r,u=Math.max(0,t.detail.keyboardHeight-c);e.requestAnimationFrame(function(){n-=u,o.style.height=n+"px",o.style.overflow="visible",i.resize()})}i.isShrunkForKeyboard=!0}t.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){o.scrollTop=0,i.isShrunkForKeyboard&&!s&&(r=o.getBoundingClientRect().bottom);var a=.5*n,l=(t.detail.elementBottom+t.detail.elementTop)/2,c=l-r,u=c+a;u>0&&(e.Platform.isIOS()&&e.tap.cloneFocusedInput(o,i),i.scrollBy(0,u,!0),i.onScroll())}),t.stopPropagation()},i.resetScrollView=function(){i.isShrunkForKeyboard&&(i.isShrunkForKeyboard=!1,o.style.height="",o.style.overflow=""),i.resize()},o.addEventListener("scrollChildIntoView",i.scrollChildIntoView),document.addEventListener("resetScrollView",i.resetScrollView),i.touchStart=function(n){if(i.startCoordinates=e.tap.pointerCoord(n),!e.tap.ignoreScrollStart(n)){if(i.__isDown=!0,e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName)return void(i.__hasStarted=!1);i.__isSelectable=!0,i.__enableScrollY=!0,i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),n.preventDefault()}},i.touchMove=function(n){if(!(i.options.freeze||!i.__isDown||!i.__isDown&&n.defaultPrevented||"TEXTAREA"===n.target.tagName&&n.target.parentElement.querySelector(":focus"))){if(!i.__hasStarted&&(e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName))return i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),void n.preventDefault();if(i.startCoordinates){var r=e.tap.pointerCoord(n);i.__isSelectable&&e.tap.isTextInput(n.target)&&Math.abs(i.startCoordinates.x-r.x)>20&&(i.__enableScrollY=!1,i.__isSelectable=!0),i.__enableScrollY&&Math.abs(i.startCoordinates.y-r.y)>10&&(i.__isSelectable=!1,e.tap.cloneFocusedInput(o,i))}i.doTouchMove(t(n),n.timeStamp,n.scale),i.__isDown=!0}},i.touchMoveBubble=function(e){i.__isDown&&i.options.preventDefault&&e.preventDefault()},i.touchEnd=function(t){i.__isDown&&(i.doTouchEnd(t,t.timeStamp),i.__isDown=!1,i.__hasStarted=!1,i.__isSelectable=!0,i.__enableScrollY=!0,i.__isDragging||i.__isDecelerating||i.__isAnimating||e.tap.removeClonedInputs(o,i))},i.mouseWheel=e.animationFrameThrottle(function(t){var n=e.DomUtil.getParentOrSelfWithClass(t.target,"ionic-scroll");i.options.freeze||n!==i.__container||(i.hintResize(),i.scrollBy((t.wheelDeltaX||t.deltaX||0)/i.options.wheelDampen,(-t.wheelDeltaY||t.deltaY||0)/i.options.wheelDampen),i.__fadeScrollbars("in"),clearTimeout(i.__wheelHideBarTimeout),i.__wheelHideBarTimeout=setTimeout(function(){i.__fadeScrollbars("out")},100))}),"ontouchstart"in window)o.addEventListener("touchstart",i.touchStart,!1),i.options.preventDefault&&o.addEventListener("touchmove",i.touchMoveBubble,!1),document.addEventListener("touchmove",i.touchMove,!1),document.addEventListener("touchend",i.touchEnd,!1),document.addEventListener("touchcancel",i.touchEnd,!1);else if(window.navigator.pointerEnabled)o.addEventListener("pointerdown",i.touchStart,!1),i.options.preventDefault&&o.addEventListener("pointermove",i.touchMoveBubble,!1),document.addEventListener("pointermove",i.touchMove,!1),document.addEventListener("pointerup",i.touchEnd,!1),document.addEventListener("pointercancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else if(window.navigator.msPointerEnabled)o.addEventListener("MSPointerDown",i.touchStart,!1),i.options.preventDefault&&o.addEventListener("MSPointerMove",i.touchMoveBubble,!1),document.addEventListener("MSPointerMove",i.touchMove,!1),document.addEventListener("MSPointerUp",i.touchEnd,!1),document.addEventListener("MSPointerCancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else{var r=!1;i.mouseDown=function(n){e.tap.ignoreScrollStart(n)||"SELECT"===n.target.tagName||(i.doTouchStart(t(n),n.timeStamp),e.tap.isTextInput(n.target)||n.preventDefault(),r=!0)},i.mouseMove=function(e){i.options.freeze||!r||!r&&e.defaultPrevented||(i.doTouchMove(t(e),e.timeStamp),r=!0)},i.mouseMoveBubble=function(e){r&&i.options.preventDefault&&e.preventDefault()},i.mouseUp=function(e){r&&(i.doTouchEnd(e,e.timeStamp),r=!1)},o.addEventListener("mousedown",i.mouseDown,!1),i.options.preventDefault&&o.addEventListener("mousemove",i.mouseMoveBubble,!1),document.addEventListener("mousemove",i.mouseMove,!1),document.addEventListener("mouseup",i.mouseUp,!1),document.addEventListener("mousewheel",i.mouseWheel,!1),document.addEventListener("wheel",i.mouseWheel,!1)}},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("touchstart",n.touchStart),i.removeEventListener("touchmove",n.touchMoveBubble),document.removeEventListener("touchmove",n.touchMove),document.removeEventListener("touchend",n.touchEnd),document.removeEventListener("touchcancel",n.touchEnd),i.removeEventListener("pointerdown",n.touchStart),i.removeEventListener("pointermove",n.touchMoveBubble),document.removeEventListener("pointermove",n.touchMove),document.removeEventListener("pointerup",n.touchEnd),document.removeEventListener("pointercancel",n.touchEnd),i.removeEventListener("MSPointerDown",n.touchStart),i.removeEventListener("MSPointerMove",n.touchMoveBubble),document.removeEventListener("MSPointerMove",n.touchMove),document.removeEventListener("MSPointerUp",n.touchEnd),document.removeEventListener("MSPointerCancel",n.touchEnd),i.removeEventListener("mousedown",n.mouseDown),i.removeEventListener("mousemove",n.mouseMoveBubble),document.removeEventListener("mousemove",n.mouseMove),document.removeEventListener("mouseup",n.mouseUp),document.removeEventListener("mousewheel",n.mouseWheel),document.removeEventListener("wheel",n.mouseWheel),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),document.removeEventListener("resetScrollView",n.resetScrollView),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.__callback=n.scrollChildIntoView=n.resetScrollView=t,n.mouseMove=n.mouseDown=n.mouseUp=n.mouseWheel=n.touchStart=n.touchMove=n.touchEnd=n.touchCancel=t,n.resize=n.scrollTo=n.zoomTo=n.__scrollingComplete=t,i=null},__createScrollbar:function(e){var t=document.createElement("div"),n=document.createElement("div");return n.className="scroll-bar-indicator scroll-bar-fade-out","h"==e?t.className="scroll-bar scroll-bar-h":t.className="scroll-bar scroll-bar-v",t.appendChild(n),t},__createScrollbars:function(){var e,t,n=this;n.options.scrollingX&&(e={el:n.__createScrollbar("h"),sizeRatio:1},e.indicator=e.el.children[0],n.options.scrollbarX&&n.__container.appendChild(e.el),n.__indicatorX=e),n.options.scrollingY&&(t={el:n.__createScrollbar("v"),sizeRatio:1},t.indicator=t.el.children[0],n.options.scrollbarY&&n.__container.appendChild(t.el),n.__indicatorY=t)},__resizeScrollbars:function(){var t=this;if(t.__indicatorX){var n=Math.max(Math.round(t.__clientWidth*t.__clientWidth/t.__contentWidth),20);n>t.__contentWidth&&(n=0),n!==t.__indicatorX.size&&e.requestAnimationFrame(function(){t.__indicatorX.indicator.style.width=n+"px"}),t.__indicatorX.size=n,t.__indicatorX.minScale=t.options.minScrollbarSizeX/n,t.__indicatorX.maxPos=t.__clientWidth-n,t.__indicatorX.sizeRatio=t.__maxScrollLeft?t.__indicatorX.maxPos/t.__maxScrollLeft:1}if(t.__indicatorY){var i=Math.max(Math.round(t.__clientHeight*t.__clientHeight/t.__contentHeight),20);i>t.__contentHeight&&(i=0),i!==t.__indicatorY.size&&e.requestAnimationFrame(function(){t.__indicatorY&&(t.__indicatorY.indicator.style.height=i+"px")}),t.__indicatorY.size=i,t.__indicatorY.minScale=t.options.minScrollbarSizeY/i,t.__indicatorY.maxPos=t.__clientHeight-i,t.__indicatorY.sizeRatio=t.__maxScrollTop?t.__indicatorY.maxPos/t.__maxScrollTop:1}},__repositionScrollbars:function(){var e,t,n,i,o,r,s=this,a=0,l=0;if(s.__indicatorX){s.__indicatorY&&(a=10),o=Math.round(s.__indicatorX.sizeRatio*s.__scrollLeft)||0,n=s.__scrollLeft-(s.__maxScrollLeft-a),s.__scrollLeft<0?(t=Math.max(s.__indicatorX.minScale,(s.__indicatorX.size-Math.abs(s.__scrollLeft))/s.__indicatorX.size),o=0,s.__indicatorX.indicator.style[s.__transformOriginProperty]="left center"):n>0?(t=Math.max(s.__indicatorX.minScale,(s.__indicatorX.size-n)/s.__indicatorX.size),o=s.__indicatorX.maxPos-a,s.__indicatorX.indicator.style[s.__transformOriginProperty]="right center"):(o=Math.min(s.__maxScrollLeft,Math.max(0,o)),t=1);var c="translate3d("+o+"px, 0, 0) scaleX("+t+")";s.__indicatorX.transformProp!==c&&(s.__indicatorX.indicator.style[s.__transformProperty]=c,s.__indicatorX.transformProp=c)}if(s.__indicatorY){r=Math.round(s.__indicatorY.sizeRatio*s.__scrollTop)||0,s.__indicatorX&&(l=10),i=s.__scrollTop-(s.__maxScrollTop-l),s.__scrollTop<0?(e=Math.max(s.__indicatorY.minScale,(s.__indicatorY.size-Math.abs(s.__scrollTop))/s.__indicatorY.size),r=0,"center top"!==s.__indicatorY.originProp&&(s.__indicatorY.indicator.style[s.__transformOriginProperty]="center top",s.__indicatorY.originProp="center top")):i>0?(e=Math.max(s.__indicatorY.minScale,(s.__indicatorY.size-i)/s.__indicatorY.size),r=s.__indicatorY.maxPos-l,"center bottom"!==s.__indicatorY.originProp&&(s.__indicatorY.indicator.style[s.__transformOriginProperty]="center bottom",s.__indicatorY.originProp="center bottom")):(r=Math.min(s.__maxScrollTop,Math.max(0,r)),e=1);var u="translate3d(0,"+r+"px, 0) scaleY("+e+")";s.__indicatorY.transformProp!==u&&(s.__indicatorY.indicator.style[s.__transformProperty]=u,s.__indicatorY.transformProp=u)}},__fadeScrollbars:function(e,t){var n=this;if(n.options.scrollbarsFade){var i="scroll-bar-fade-out";n.options.scrollbarsFade===!0&&(clearTimeout(n.__scrollbarFadeTimeout),"in"==e?(n.__indicatorX&&n.__indicatorX.indicator.classList.remove(i),n.__indicatorY&&n.__indicatorY.indicator.classList.remove(i)):n.__scrollbarFadeTimeout=setTimeout(function(){n.__indicatorX&&n.__indicatorX.indicator.classList.add(i),n.__indicatorY&&n.__indicatorY.indicator.classList.add(i)},t||n.options.scrollbarFadeDelay))}},__scrollingComplete:function(){this.options.scrollingComplete(),e.tap.removeClonedInputs(this.__container,this),this.__fadeScrollbars("out")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},getRenderFn:function(){var e,t=this,n=t.__content,i=document.documentElement.style;"MozAppearance"in i?e="gecko":"WebkitAppearance"in i?e="webkit":"string"==typeof navigator.cpuClass&&(e="trident");var o,r={trident:"ms",gecko:"Moz",webkit:"Webkit",presto:"O"}[e],s=document.createElement("div"),a=r+"Perspective",l=r+"Transform",c=r+"TransformOrigin";return t.__perspectiveProperty=l,t.__transformProperty=l,t.__transformOriginProperty=c,s.style[a]!==o?function(e,i,o,r){var s="translate3d("+-e+"px,"+-i+"px,0) scale("+o+")";s!==t.contentTransform&&(n.style[l]=s,t.contentTransform=s),t.__repositionScrollbars(),r||t.triggerScrollEvent()}:s.style[l]!==o?function(e,i,o,r){n.style[l]="translate("+-e+"px,"+-i+"px) scale("+o+")",t.__repositionScrollbars(),r||t.triggerScrollEvent()}:function(e,i,o,r){n.style.marginLeft=e?-e/o+"px":"",n.style.marginTop=i?-i/o+"px":"",n.style.zoom=o||"",t.__repositionScrollbars(),r||t.triggerScrollEvent()}},setDimensions:function(e,t,n,i,o){var r=this;(e||t||n||i)&&(e===+e&&(r.__clientWidth=e),t===+t&&(r.__clientHeight=t),n===+n&&(r.__contentWidth=n),i===+i&&(r.__contentHeight=i),r.__computeScrollMax(),r.__resizeScrollbars(),o||r.scrollTo(r.__scrollLeft,r.__scrollTop,!0,null,!0))},setPosition:function(e,t){this.__clientLeft=e||0,this.__clientTop=t||0},setSnapSize:function(e,t){this.__snapWidth=e,this.__snapHeight=t},activatePullToRefresh:function(t,n){var i=this;i.__refreshHeight=t,i.__refreshActivate=function(){e.requestAnimationFrame(n.activate)},i.__refreshDeactivate=function(){e.requestAnimationFrame(n.deactivate)},i.__refreshStart=function(){e.requestAnimationFrame(n.start)},i.__refreshShow=function(){e.requestAnimationFrame(n.show)},i.__refreshHide=function(){e.requestAnimationFrame(n.hide)},i.__refreshTail=function(){e.requestAnimationFrame(n.tail)},i.__refreshTailTime=100,i.__minSpinTime=600},triggerPullToRefresh:function(){this.__publish(this.__scrollLeft,-this.__refreshHeight,this.__zoomLevel,!0);var e=new Date;this.refreshStartTime=e.getTime(),this.__refreshStart&&this.__refreshStart()},finishPullToRefresh:function(){var e=this,t=new Date,n=0;e.refreshStartTime+e.__minSpinTime>t.getTime()&&(n=e.refreshStartTime+e.__minSpinTime-t.getTime()),setTimeout(function(){e.__refreshTail&&e.__refreshTail(),setTimeout(function(){e.__refreshActive=!1,e.__refreshDeactivate&&e.__refreshDeactivate(),e.__refreshHide&&e.__refreshHide(),e.scrollTo(e.__scrollLeft,e.__scrollTop,!0)},e.__refreshTailTime)},n)},getValues:function(){return{left:this.__scrollLeft,top:this.__scrollTop,zoom:this.__zoomLevel}},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},zoomTo:function(e,t,n,i){var o=this;if(!o.options.zooming)throw new Error("Zooming is not enabled!");o.__isDecelerating&&(he.effect.Animate.stop(o.__isDecelerating),o.__isDecelerating=!1);var r=o.__zoomLevel;null==n&&(n=o.__clientWidth/2),null==i&&(i=o.__clientHeight/2),e=Math.max(Math.min(e,o.options.maxZoom),o.options.minZoom),o.__computeScrollMax(e);var s=(n+o.__scrollLeft)*e/r-n,a=(i+o.__scrollTop)*e/r-i;s>o.__maxScrollLeft?s=o.__maxScrollLeft:0>s&&(s=0),a>o.__maxScrollTop?a=o.__maxScrollTop:0>a&&(a=0),o.__publish(s,a,e,t)},zoomBy:function(e,t,n,i){this.zoomTo(this.__zoomLevel*e,t,n,i)},scrollTo:function(e,t,n,i,o){var r=this;if(r.__isDecelerating&&(he.effect.Animate.stop(r.__isDecelerating),r.__isDecelerating=!1),null!=i&&i!==r.__zoomLevel){if(!r.options.zooming)throw new Error("Zooming is not enabled!");e*=i,t*=i,r.__computeScrollMax(i)}else i=r.__zoomLevel;r.options.scrollingX?r.options.paging?e=Math.round(e/r.__clientWidth)*r.__clientWidth:r.options.snapping&&(e=Math.round(e/r.__snapWidth)*r.__snapWidth):e=r.__scrollLeft,r.options.scrollingY?r.options.paging?t=Math.round(t/r.__clientHeight)*r.__clientHeight:r.options.snapping&&(t=Math.round(t/r.__snapHeight)*r.__snapHeight):t=r.__scrollTop,e=Math.max(Math.min(r.__maxScrollLeft,e),0),t=Math.max(Math.min(r.__maxScrollTop,t),0),e===r.__scrollLeft&&t===r.__scrollTop&&(n=!1),r.__publish(e,t,i,n,o)},scrollBy:function(e,t,n){var i=this,o=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,r=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(o+(e||0),r+(t||0),n)},doMouseZoom:function(e,t,n,i){var o=e>0?.97:1.03;return this.zoomTo(this.__zoomLevel*o,!1,n-this.__clientLeft,i-this.__clientTop)},doTouchStart:function(e,t){var n=this;n.__decStopped=!(!n.__isDecelerating&&!n.__isAnimating),n.hintResize(),t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now()),n.__interruptedAnimation=!0,n.__isDecelerating&&(he.effect.Animate.stop(n.__isDecelerating),n.__isDecelerating=!1,n.__interruptedAnimation=!0),n.__isAnimating&&(he.effect.Animate.stop(n.__isAnimating),n.__isAnimating=!1,n.__interruptedAnimation=!0);var i,o,r=1===e.length;r?(i=e[0].pageX,o=e[0].pageY):(i=Math.abs(e[0].pageX+e[1].pageX)/2,o=Math.abs(e[0].pageY+e[1].pageY)/2),n.__initialTouchLeft=i,n.__initialTouchTop=o,n.__initialTouches=e,n.__zoomLevelStart=n.__zoomLevel,n.__lastTouchLeft=i,n.__lastTouchTop=o,n.__lastTouchMove=t,n.__lastScale=1,n.__enableScrollX=!r&&n.options.scrollingX,n.__enableScrollY=!r&&n.options.scrollingY,n.__isTracking=!0,n.__didDecelerationComplete=!1,n.__isDragging=!r,n.__isSingleTouch=r,n.__positions=[]},doTouchMove:function(e,t,n){t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now());var i=this;if(i.__isTracking){var o,r;2===e.length?(o=Math.abs(e[0].pageX+e[1].pageX)/2,r=Math.abs(e[0].pageY+e[1].pageY)/2,!n&&i.options.zooming&&(n=i.__getScale(i.__initialTouches,e))):(o=e[0].pageX,r=e[0].pageY);var s=i.__positions;if(i.__isDragging){i.__decStopped=!1;var a=o-i.__lastTouchLeft,l=r-i.__lastTouchTop,c=i.__scrollLeft,u=i.__scrollTop,d=i.__zoomLevel;if(null!=n&&i.options.zooming){var _=d;if(d=d/i.__lastScale*n,d=Math.max(Math.min(d,i.options.maxZoom),i.options.minZoom),_!==d){var h=o-i.__clientLeft,f=r-i.__clientTop;c=(h+c)*d/_-h,u=(f+u)*d/_-f,i.__computeScrollMax(d)}}if(i.__enableScrollX){c-=a*i.options.speedMultiplier;var p=i.__maxScrollLeft;(c>p||0>c)&&(i.options.bouncing?c+=a/2*i.options.speedMultiplier:c=c>p?p:0)}if(i.__enableScrollY){u-=l*i.options.speedMultiplier;var m=i.__maxScrollTop;u>m||0>u?i.options.bouncing||i.__refreshHeight&&0>u?(u+=l/2*i.options.speedMultiplier,i.__enableScrollX||null==i.__refreshHeight||(0>u?(i.__refreshHidden=!1,i.__refreshShow()):(i.__refreshHide(),i.__refreshHidden=!0),!i.__refreshActive&&u<=-i.__refreshHeight?(i.__refreshActive=!0,i.__refreshActivate&&i.__refreshActivate()):i.__refreshActive&&u>-i.__refreshHeight&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate()))):u=u>m?m:0:i.__refreshHeight&&!i.__refreshHidden&&(i.__refreshHide(),i.__refreshHidden=!0)}s.length>60&&s.splice(0,30),s.push(c,u,t),i.__publish(c,u,d)}else{var g=i.options.locking?3:0,v=5,T=Math.abs(o-i.__initialTouchLeft),E=Math.abs(r-i.__initialTouchTop);i.__enableScrollX=i.options.scrollingX&&T>=g,i.__enableScrollY=i.options.scrollingY&&E>=g,s.push(i.__scrollLeft,i.__scrollTop,t),i.__isDragging=(i.__enableScrollX||i.__enableScrollY)&&(T>=v||E>=v),i.__isDragging&&(i.__interruptedAnimation=!1,i.__fadeScrollbars("in"))}i.__lastTouchLeft=o,i.__lastTouchTop=r,i.__lastTouchMove=t,i.__lastScale=n}},doTouchEnd:function(t,n){n instanceof Date&&(n=n.valueOf()),"number"!=typeof n&&(n=Date.now());var i=this;if(i.__isTracking){if(i.__isTracking=!1,i.__isDragging)if(i.__isDragging=!1,i.__isSingleTouch&&i.options.animating&&n-i.__lastTouchMove<=100){for(var o=i.__positions,r=o.length-1,s=r,a=r;a>0&&o[a]>i.__lastTouchMove-100;a-=3)s=a;if(s!==r){var l=o[r]-o[s],c=i.__scrollLeft-o[s-2],u=i.__scrollTop-o[s-1];i.__decelerationVelocityX=c/l*(1e3/60),i.__decelerationVelocityY=u/l*(1e3/60);var d=i.options.paging||i.options.snapping?i.options.decelVelocityThresholdPaging:i.options.decelVelocityThreshold;(Math.abs(i.__decelerationVelocityX)>d||Math.abs(i.__decelerationVelocityY)>d)&&(i.__refreshActive||i.__startDeceleration(n))}else i.__scrollingComplete()}else n-i.__lastTouchMove>100&&i.__scrollingComplete();else i.__decStopped&&(t.isTapHandled=!0,i.__decStopped=!1);if(!i.__isDecelerating)if(i.__refreshActive&&i.__refreshStart){i.__publish(i.__scrollLeft,-i.__refreshHeight,i.__zoomLevel,!0);var _=new Date;i.refreshStartTime=_.getTime(),i.__refreshStart&&i.__refreshStart(),e.Platform.isAndroid()||i.__startDeceleration()}else(i.__interruptedAnimation||i.__isDragging)&&i.__scrollingComplete(),i.scrollTo(i.__scrollLeft,i.__scrollTop,!0,i.__zoomLevel),i.__refreshActive&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate());i.__positions.length=0}},__publish:function(e,t,o,r,s){var a=this,l=a.__isAnimating;if(l&&(he.effect.Animate.stop(l),a.__isAnimating=!1),r&&a.options.animating){a.__scheduledLeft=e,a.__scheduledTop=t, -a.__scheduledZoom=o;var c=a.__scrollLeft,u=a.__scrollTop,d=a.__zoomLevel,_=e-c,h=t-u,f=o-d,p=function(e,t,n){n&&(a.__scrollLeft=c+_*e,a.__scrollTop=u+h*e,a.__zoomLevel=d+f*e,a.__callback&&a.__callback(a.__scrollLeft,a.__scrollTop,a.__zoomLevel,s))},m=function(e){return a.__isAnimating===e},g=function(e,t,n){t===a.__isAnimating&&(a.__isAnimating=!1),(a.__didDecelerationComplete||n)&&a.__scrollingComplete(),a.options.zooming&&a.__computeScrollMax()};a.__isAnimating=he.effect.Animate.start(p,m,g,a.options.animationDuration,l?n:i)}else a.__scheduledLeft=a.__scrollLeft=e,a.__scheduledTop=a.__scrollTop=t,a.__scheduledZoom=a.__zoomLevel=o,a.__callback&&a.__callback(e,t,o,s),a.options.zooming&&a.__computeScrollMax()},__computeScrollMax:function(e){var t=this;null==e&&(e=t.__zoomLevel),t.__maxScrollLeft=Math.max(t.__contentWidth*e-t.__clientWidth,0),t.__maxScrollTop=Math.max(t.__contentHeight*e-t.__clientHeight,0),t.__didWaitForSize||t.__maxScrollLeft||t.__maxScrollTop||(t.__didWaitForSize=!0,t.__waitForSize())},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__startDeceleration:function(){var e=this;if(e.options.paging){var t=Math.max(Math.min(e.__scrollLeft,e.__maxScrollLeft),0),n=Math.max(Math.min(e.__scrollTop,e.__maxScrollTop),0),i=e.__clientWidth,o=e.__clientHeight;e.__minDecelerationScrollLeft=Math.floor(t/i)*i,e.__minDecelerationScrollTop=Math.floor(n/o)*o,e.__maxDecelerationScrollLeft=Math.ceil(t/i)*i,e.__maxDecelerationScrollTop=Math.ceil(n/o)*o}else e.__minDecelerationScrollLeft=0,e.__minDecelerationScrollTop=0,e.__maxDecelerationScrollLeft=e.__maxScrollLeft,e.__maxDecelerationScrollTop=e.__maxScrollTop,e.__refreshActive&&(e.__minDecelerationScrollTop=-1*e.__refreshHeight);var r=function(t,n,i){e.__stepThroughDeceleration(i)};e.__minVelocityToKeepDecelerating=e.options.snapping?4:.1;var s=function(){var t=Math.abs(e.__decelerationVelocityX)>=e.__minVelocityToKeepDecelerating||Math.abs(e.__decelerationVelocityY)>=e.__minVelocityToKeepDecelerating;return t||(e.__didDecelerationComplete=!0,e.options.bouncing&&!e.__refreshActive&&e.scrollTo(Math.min(Math.max(e.__scrollLeft,0),e.__maxScrollLeft),Math.min(Math.max(e.__scrollTop,0),e.__maxScrollTop),e.__refreshActive)),t},a=function(){e.__isDecelerating=!1,e.__didDecelerationComplete&&e.__scrollingComplete(),e.options.paging&&e.scrollTo(e.__scrollLeft,e.__scrollTop,e.options.snapping)};e.__isDecelerating=he.effect.Animate.start(r,s,a)},__stepThroughDeceleration:function(e){var t=this,n=t.__scrollLeft+t.__decelerationVelocityX,i=t.__scrollTop+t.__decelerationVelocityY;if(!t.options.bouncing){var o=Math.max(Math.min(t.__maxDecelerationScrollLeft,n),t.__minDecelerationScrollLeft);o!==n&&(n=o,t.__decelerationVelocityX=0);var r=Math.max(Math.min(t.__maxDecelerationScrollTop,i),t.__minDecelerationScrollTop);r!==i&&(i=r,t.__decelerationVelocityY=0)}if(e?t.__publish(n,i,t.__zoomLevel):(t.__scrollLeft=n,t.__scrollTop=i),!t.options.paging){var s=t.options.deceleration;t.__decelerationVelocityX*=s,t.__decelerationVelocityY*=s}if(t.options.bouncing){var a=0,l=0,c=t.options.penetrationDeceleration,u=t.options.penetrationAcceleration;if(n<t.__minDecelerationScrollLeft?a=t.__minDecelerationScrollLeft-n:n>t.__maxDecelerationScrollLeft&&(a=t.__maxDecelerationScrollLeft-n),i<t.__minDecelerationScrollTop?l=t.__minDecelerationScrollTop-i:i>t.__maxDecelerationScrollTop&&(l=t.__maxDecelerationScrollTop-i),0!==a){var d=a*t.__decelerationVelocityX<=t.__minDecelerationScrollLeft;d&&(t.__decelerationVelocityX+=a*c);var _=Math.abs(t.__decelerationVelocityX)<=t.__minVelocityToKeepDecelerating;(!d||_)&&(t.__decelerationVelocityX=a*u)}if(0!==l){var h=l*t.__decelerationVelocityY<=t.__minDecelerationScrollTop;h&&(t.__decelerationVelocityY+=l*c);var f=Math.abs(t.__decelerationVelocityY)<=t.__minVelocityToKeepDecelerating;(!h||f)&&(t.__decelerationVelocityY=l*u)}}},__getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},__getScale:function(e,t){return e.length>=2&&t.length>=2?this.__getDistance(t[0],t[1])/this.__getDistance(e[0],e[1]):1}}),e.scroll={isScrolling:!1,lastTop:0}}(ionic),function(e){var t=function(){},n=function(e){};e.views.ScrollNative=e.views.View.inherit({initialize:function(n){var i=this;i.__container=i.el=n.el,i.__content=n.el.firstElementChild,i.isNative=!0,i.__scrollTop=i.el.scrollTop,i.__scrollLeft=i.el.scrollLeft,i.__clientHeight=i.__content.clientHeight,i.__clientWidth=i.__content.clientWidth,i.__maxScrollTop=Math.max(i.__contentHeight-i.__clientHeight,0),i.__maxScrollLeft=Math.max(i.__contentWidth-i.__clientWidth,0),i.options={freeze:!1,getContentWidth:function(){return Math.max(i.__content.scrollWidth,i.__content.offsetWidth)},getContentHeight:function(){return Math.max(i.__content.scrollHeight,i.__content.offsetHeight+2*i.__content.offsetTop)}};for(var o in n)i.options[o]=n[o];i.onScroll=function(){e.scroll.isScrolling||(e.scroll.isScrolling=!0),clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(function(){e.scroll.isScrolling=!1},80)},i.freeze=t,i.__initEventHandlers()},__callback:function(){n("__callback")},zoomTo:function(){n("zoomTo")},zoomBy:function(){n("zoomBy")},activatePullToRefresh:function(){n("activatePullToRefresh")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},run:function(){this.resize()},getValues:function(){var e=this;return e.update(),{left:e.__scrollLeft,top:e.__scrollTop,zoom:1}},update:function(){var e=this;e.__scrollLeft=e.el.scrollLeft,e.__scrollTop=e.el.scrollTop},setDimensions:function(e,t,n,i){var o=this;(e||t||n||i)&&(e===+e&&(o.__clientWidth=e),t===+t&&(o.__clientHeight=t),n===+n&&(o.__contentWidth=n),i===+i&&(o.__contentHeight=i),o.__computeScrollMax())},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},scrollBy:function(e,t,n){var i=this;i.update();var o=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,r=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(o+(e||0),r+(t||0),n)},scrollTo:function(t,n,i){function o(t,n){function i(e){return--e*e*e+1}function o(){var u=Date.now(),d=Math.min(1,(u-s)/a),_=i(d);l!=t&&(r.el.scrollTop=parseInt(_*(t-l)+l,10)),c!=n&&(r.el.scrollLeft=parseInt(_*(n-c)+c,10)),1>d?e.requestAnimationFrame(o):(e.tap.removeClonedInputs(r.__container,r),r.resize())}var s=Date.now(),a=250,l=r.el.scrollTop,c=r.el.scrollLeft;return l===t&&c===n?void r.resize():void e.requestAnimationFrame(o)}var r=this;return i?void o(n,t):(r.el.scrollTop=n,r.el.scrollLeft=t,void r.resize())},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__computeScrollMax:function(){var e=this;e.__maxScrollLeft=Math.max(e.__contentWidth-e.__clientWidth,0),e.__maxScrollTop=Math.max(e.__contentHeight-e.__clientHeight,0),e.__didWaitForSize||e.__maxScrollLeft||e.__maxScrollTop||(e.__didWaitForSize=!0,e.__waitForSize())},__initEventHandlers:function(){var t,n=this,i=n.__container;n.scrollChildIntoView=function(o){var r=i.getBoundingClientRect().bottom;t=i.offsetHeight;var s=n.isShrunkForKeyboard,a=i.parentNode.classList.contains("modal"),l=a&&window.innerWidth>=680;if(!s){if(e.Platform.isIOS()||e.Platform.isFullScreen||l){var c=o.detail.viewportHeight-r,u=Math.max(0,o.detail.keyboardHeight-c);e.requestAnimationFrame(function(){t-=u,i.style.height=t+"px",n.resize()})}n.isShrunkForKeyboard=!0}o.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){n.isShrunkForKeyboard&&!s&&(r=i.getBoundingClientRect().bottom);var a=.5*t,l=(o.detail.elementBottom+o.detail.elementTop)/2,c=l-r,u=c+a;u>0&&(e.Platform.isIOS()?setTimeout(function(){e.tap.cloneFocusedInput(i,n),n.scrollBy(0,u,!0),n.onScroll()},32):(n.scrollBy(0,u,!0),n.onScroll()))}),o.stopPropagation()},n.resetScrollView=function(){n.isShrunkForKeyboard&&(n.isShrunkForKeyboard=!1,i.style.height=""),n.resize()},i.addEventListener("scroll",n.onScroll),i.addEventListener("scrollChildIntoView",n.scrollChildIntoView),document.addEventListener("resetScrollView",n.resetScrollView)},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("resetScrollView",n.resetScrollView),i.removeEventListener("scroll",n.onScroll),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),i.removeEventListener("resetScrollView",n.resetScrollView),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.resize=n.scrollTo=n.onScroll=n.resetScrollView=t,n.scrollChildIntoView=t,i=null}})}(ionic),function(e){"use strict";var t="item",n="item-content",i="item-sliding",o="item-options",r="item-placeholder",s="item-reordering",a="item-reorder",l=function(){};l.prototype={start:function(){},drag:function(){},end:function(){},isSameItem:function(){return!1}};var c=function(e){this.dragThresholdX=e.dragThresholdX||10,this.el=e.el,this.item=e.item,this.canSwipe=e.canSwipe};c.prototype=new l,c.prototype.start=function(r){var s,a,l,c;this.canSwipe()&&(s=r.target.classList.contains(n)?r.target:r.target.classList.contains(t)?r.target.querySelector("."+n):e.DomUtil.getParentWithClass(r.target,n),s&&(s.classList.remove(i),l=parseFloat(s.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])||0,a=s.parentNode.querySelector("."+o),a&&(a.classList.remove("invisible"),c=a.offsetWidth,this._currentDrag={buttons:a,buttonsWidth:c,content:s,startOffsetX:l})))},c.prototype.isSameItem=function(e){return e._lastDrag&&this._currentDrag?this._currentDrag.content==e._lastDrag.content:!1},c.prototype.clean=function(t){function n(){i.buttons&&i.buttons.classList.add("invisible")}var i=this._lastDrag;i&&i.content&&(i.content.style[e.CSS.TRANSITION]="",i.content.style[e.CSS.TRANSFORM]="",t?(i.content.style[e.CSS.TRANSITION]="none",n(),e.requestAnimationFrame(function(){i.content.style[e.CSS.TRANSITION]=""})):e.requestAnimationFrame(function(){setTimeout(n,250)}))},c.prototype.drag=e.animationFrameThrottle(function(t){var n;if(this._currentDrag&&(!this._isDragging&&(Math.abs(t.gesture.deltaX)>this.dragThresholdX||Math.abs(this._currentDrag.startOffsetX)>0)&&(this._isDragging=!0),this._isDragging)){n=this._currentDrag.buttonsWidth;var i=Math.min(0,this._currentDrag.startOffsetX+t.gesture.deltaX);-n>i&&(i=Math.min(-n,-n+.4*(t.gesture.deltaX+n))),this._currentDrag.content.$$ionicOptionsOpen=0!==i,this._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+i+"px, 0, 0)",this._currentDrag.content.style[e.CSS.TRANSITION]="none"}}),c.prototype.end=function(t,n){var i=this;if(!i._currentDrag)return void(n&&n());var o=-i._currentDrag.buttonsWidth;t.gesture.deltaX>-(i._currentDrag.buttonsWidth/2)&&("left"==t.gesture.direction&&Math.abs(t.gesture.velocityX)<.3?o=0:"right"==t.gesture.direction&&(o=0)),e.requestAnimationFrame(function(){if(0===o){i._currentDrag.content.style[e.CSS.TRANSFORM]="";var t=i._currentDrag.buttons;setTimeout(function(){t&&t.classList.add("invisible")},250)}else i._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+o+"px,0,0)";i._currentDrag.content.style[e.CSS.TRANSITION]="",i._lastDrag||(i._lastDrag={}),e.extend(i._lastDrag,i._currentDrag),i._currentDrag&&(i._currentDrag.buttons=null,i._currentDrag.content=null),i._currentDrag=null,n&&n()})};var u=function(e){var t=this;if(t.dragThresholdY=e.dragThresholdY||0,t.onReorder=e.onReorder,t.listEl=e.listEl,t.el=t.item=e.el,t.scrollEl=e.scrollEl,t.scrollView=e.scrollView,t.listElTrueTop=0,t.listEl.offsetParent){var n=t.listEl;do t.listElTrueTop+=n.offsetTop,n=n.offsetParent;while(n)}};u.prototype=new l,u.prototype._moveElement=function(t){var n=t.gesture.center.pageY+this.scrollView.getValues().top-this._currentDrag.elementHeight/2-this.listElTrueTop;this.el.style[e.CSS.TRANSFORM]="translate3d(0, "+n+"px, 0)"},u.prototype.deregister=function(){this.listEl=this.el=this.scrollEl=this.scrollView=null},u.prototype.start=function(t){var n=e.DomUtil.getChildIndex(this.el,this.el.nodeName.toLowerCase()),i=this.el.scrollHeight,o=this.el.cloneNode(!0);o.classList.add(r),this.el.parentNode.insertBefore(o,this.el),this.el.classList.add(s),this._currentDrag={elementHeight:i,startIndex:n,placeholder:o,scrollHeight:scroll,list:o.parentNode},this._moveElement(t)},u.prototype.drag=e.animationFrameThrottle(function(t){var n=this;if(this._currentDrag){var i=0,o=t.gesture.center.pageY,r=this.listElTrueTop;if(this.scrollView){var s=this.scrollView.__container;i=this.scrollView.getValues().top;var a=s.offsetTop,l=a-o+this._currentDrag.elementHeight/2,c=o+this._currentDrag.elementHeight/2-a-s.offsetHeight;t.gesture.deltaY<0&&l>0&&i>0&&(this.scrollView.scrollBy(null,-l),e.requestAnimationFrame(function(){n.drag(t)})),t.gesture.deltaY>0&&c>0&&i<this.scrollView.getScrollMax().top&&(this.scrollView.scrollBy(null,c),e.requestAnimationFrame(function(){n.drag(t)}))}!this._isDragging&&Math.abs(t.gesture.deltaY)>this.dragThresholdY&&(this._isDragging=!0),this._isDragging&&(this._moveElement(t),this._currentDrag.currentY=i+o-r)}}),u.prototype._getReorderIndex=function(){for(var e,t=this,n=Array.prototype.slice.call(t._currentDrag.placeholder.parentNode.children).filter(function(e){return e.nodeName===t.el.nodeName&&e!==t.el}),i=t._currentDrag.currentY,o=0,r=n.length;r>o;o++)if(e=n[o],o===r-1){if(i>e.offsetTop)return o}else if(0===o){if(i<e.offsetTop+e.offsetHeight)return o}else if(i>e.offsetTop-e.offsetHeight/2&&i<e.offsetTop+e.offsetHeight)return o;return t._currentDrag.startIndex},u.prototype.end=function(t,n){if(!this._currentDrag)return void(n&&n());var i=this._currentDrag.placeholder,o=this._getReorderIndex();this.el.classList.remove(s),this.el.style[e.CSS.TRANSFORM]="",i.parentNode.insertBefore(this.el,i),i.parentNode.removeChild(i),this.onReorder&&this.onReorder(this.el,this._currentDrag.startIndex,o),this._currentDrag={placeholder:null,content:null},this._currentDrag=null,n&&n()},e.views.ListView=e.views.View.inherit({initialize:function(t){var n=this;t=e.extend({onReorder:function(){},virtualRemoveThreshold:-200,virtualAddThreshold:200,canSwipe:function(){return!0}},t),e.extend(n,t),!n.itemHeight&&n.listEl&&(n.itemHeight=n.listEl.children[0]&&parseInt(n.listEl.children[0].style.height,10)),n.onRefresh=t.onRefresh||function(){},n.onRefreshOpening=t.onRefreshOpening||function(){},n.onRefreshHolding=t.onRefreshHolding||function(){};var i={};e.DomUtil.getParentOrSelfWithClass(n.el,"overflow-scroll")&&(i.prevent_default_directions=["left","right"]),window.ionic.onGesture("release",function(e){n._handleEndDrag(e)},n.el,i),window.ionic.onGesture("drag",function(e){n._handleDrag(e)},n.el,i),n._initDrag()},deregister:function(){this.el=this.listEl=this.scrollEl=this.scrollView=null,this.isScrollFreeze&&self.scrollView.freeze(!1)},stopRefreshing:function(){var e=this.el.querySelector(".list-refresher");e.style.height="0"},didScroll:function(e){var t=this;if(t.isVirtual){var n=t.itemHeight,i=e.target.scrollHeight,o=t.el.parentNode.offsetHeight,r=Math.max(0,e.scrollTop+t.virtualRemoveThreshold),s=Math.min(i,Math.abs(e.scrollTop)+o+t.virtualAddThreshold),a=parseInt(Math.abs(r/n),10),l=parseInt(Math.abs(s/n),10);t._virtualItemsToRemove=Array.prototype.slice.call(t.listEl.children,0,a),t.renderViewport&&t.renderViewport(r,s,a,l)}},didStopScrolling:function(){if(this.isVirtual)for(var e=0;e<this._virtualItemsToRemove.length;e++)this.didHideItem&&this.didHideItem(e)},clearDragEffects:function(e){this._lastDragOp&&(this._lastDragOp.clean&&this._lastDragOp.clean(e),this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=null)},_initDrag:function(){this._lastDragOp&&this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=this._dragOp,this._dragOp=null},_getItem:function(e){for(;e;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},_startDrag:function(t){var n=this;n._isDragging=!1;var i,o=n._lastDragOp;n._didDragUpOrDown&&o instanceof c&&o.clean&&o.clean(),!e.DomUtil.getParentOrSelfWithClass(t.target,a)||"up"!=t.gesture.direction&&"down"!=t.gesture.direction?!n._didDragUpOrDown&&("left"==t.gesture.direction||"right"==t.gesture.direction)&&Math.abs(t.gesture.deltaX)>5&&(i=n._getItem(t.target),i&&i.querySelector(".item-options")&&(n._dragOp=new c({el:n.el,item:i,canSwipe:n.canSwipe}),n._dragOp.start(t),t.preventDefault(),n.isScrollFreeze=n.scrollView.freeze(!0))):(i=n._getItem(t.target),i&&(n._dragOp=new u({listEl:n.el,el:i,scrollEl:n.scrollEl,scrollView:n.scrollView,onReorder:function(e,t,i){n.onReorder&&n.onReorder(e,t,i)}}),n._dragOp.start(t),t.preventDefault())),o&&n._dragOp&&!n._dragOp.isSameItem(o)&&t.defaultPrevented&&o.clean&&o.clean()},_handleEndDrag:function(e){var t=this;t.scrollView&&(t.isScrollFreeze=t.scrollView.freeze(!1)),t._didDragUpOrDown=!1,t._dragOp&&t._dragOp.end(e,function(){t._initDrag()})},_handleDrag:function(e){var t=this;Math.abs(e.gesture.deltaY)>5&&(t._didDragUpOrDown=!0),t.isDragging||t._dragOp||t._startDrag(e),t._dragOp&&(e.gesture.srcEvent.preventDefault(),t._dragOp.drag(e))}})}(ionic),function(e){"use strict";e.views.Modal=e.views.View.inherit({initialize:function(t){t=e.extend({focusFirstInput:!1,unfocusOnHide:!0,focusFirstDelay:600,backdropClickToClose:!0,hardwareBackButtonClose:!0},t),e.extend(this,t),this.el=t.el},show:function(){var e=this;e.focusFirstInput&&window.setTimeout(function(){var t=e.el.querySelector("input, textarea");t&&t.focus&&t.focus()},e.focusFirstDelay)},hide:function(){if(this.unfocusOnHide){var e=this.el.querySelectorAll("input, textarea");window.setTimeout(function(){for(var t=0;t<e.length;t++)e[t].blur&&e[t].blur()})}}})}(ionic),function(e){"use strict";e.views.SideMenu=e.views.View.inherit({initialize:function(e){this.el=e.el,this.isEnabled="undefined"==typeof e.isEnabled?!0:e.isEnabled,this.setWidth(e.width)},getFullWidth:function(){return this.width},setWidth:function(e){this.width=e,this.el.style.width=e+"px"},setIsEnabled:function(e){this.isEnabled=e},bringUp:function(){"0"!==this.el.style.zIndex&&(this.el.style.zIndex="0")},pushDown:function(){"-1"!==this.el.style.zIndex&&(this.el.style.zIndex="-1")}}),e.views.SideMenuContent=e.views.View.inherit({initialize:function(t){e.extend(this,{animationClass:"menu-animated",onDrag:function(){},onEndDrag:function(){}},t),e.onGesture("drag",e.proxy(this._onDrag,this),this.el),e.onGesture("release",e.proxy(this._onEndDrag,this),this.el)},_onDrag:function(e){this.onDrag&&this.onDrag(e)},_onEndDrag:function(e){this.onEndDrag&&this.onEndDrag(e)},disableAnimation:function(){this.el.classList.remove(this.animationClass)},enableAnimation:function(){this.el.classList.add(this.animationClass)},getTranslateX:function(){return parseFloat(this.el.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])},setTranslateX:e.animationFrameThrottle(function(t){this.el.style[e.CSS.TRANSFORM]="translate3d("+t+"px, 0, 0)"})})}(ionic),function(e){"use strict";e.views.Slider=e.views.View.inherit({initialize:function(e){function t(){if(p.offsetWidth){m=E.children,T=m.length,m.length<2&&(e.continuous=!1),f.transitions&&e.continuous&&m.length<3&&(E.appendChild(m[0].cloneNode(!0)),E.appendChild(E.children[1].cloneNode(!0)),m=E.children),g=new Array(m.length),v=p.offsetWidth||p.getBoundingClientRect().width,E.style.width=m.length*v+"px";for(var t=m.length;t--;){var n=m[t];n.style.width=v+"px",n.setAttribute("data-index",t),f.transitions&&(n.style.left=t*-v+"px",s(t,S>t?-v:t>S?v:0,0))}e.continuous&&f.transitions&&(s(o(S-1),-v,0),s(o(S+1),v,0)),f.transitions||(E.style.left=S*-v+"px"),p.style.visibility="visible",e.slidesChanged&&e.slidesChanged()}}function n(t){e.continuous?r(S-1,t):S&&r(S-1,t)}function i(t){e.continuous?r(S+1,t):S<m.length-1&&r(S+1,t)}function o(e){return(m.length+e%m.length)%m.length}function r(t,n){if(S!=t){if(f.transitions){var i=Math.abs(S-t)/(S-t);if(e.continuous){var r=i;i=-g[o(t)]/v,i!==r&&(t=-i*m.length+t)}for(var a=Math.abs(S-t)-1;a--;)s(o((t>S?t:S)-a-1),v*i,0);t=o(t),s(S,v*i,n||b),s(t,0,n||b),e.continuous&&s(o(t-i),-(v*i),0)}else t=o(t),l(S*-v,t*-v,n||b);S=t,h(e.callback&&e.callback(S,m[S]))}}function s(e,t,n){a(e,t,n),g[e]=t}function a(e,t,n){var i=m[e],o=i&&i.style;o&&(o.webkitTransitionDuration=o.MozTransitionDuration=o.msTransitionDuration=o.OTransitionDuration=o.transitionDuration=n+"ms",o.webkitTransform="translate("+t+"px,0)translateZ(0)",o.msTransform=o.MozTransform=o.OTransform="translateX("+t+"px)")}function l(t,n,i){if(!i)return void(E.style.left=n+"px");var o=+new Date,r=setInterval(function(){var s=+new Date-o;return s>i?(E.style.left=n+"px",D&&c(),e.transitionEnd&&e.transitionEnd.call(event,S,m[S]),void clearInterval(r)):void(E.style.left=(n-t)*(Math.floor(s/i*100)/100)+t+"px")},4)}function c(){w=setTimeout(i,D)}function u(){D=e.auto||0,clearTimeout(w)}var d=this,_=function(){},h=function(e){setTimeout(e||_,0)},f={addEventListener:!!window.addEventListener,touch:"ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch,transitions:function(e){var t=["transitionProperty","WebkitTransition","MozTransition","OTransition","msTransition"];for(var n in t)if(void 0!==e.style[t[n]])return!0;return!1}(document.createElement("swipe"))},p=e.el;if(p){var m,g,v,T,E=p.children[0];e=e||{};var S=parseInt(e.startSlide,10)||0,b=e.speed||300;e.continuous=void 0!==e.continuous?e.continuous:!0;var w,y,D=e.auto||0,L={},x={},M={handleEvent:function(n){switch(("mousedown"==n.type||"mouseup"==n.type||"mousemove"==n.type)&&(n.touches=[{pageX:n.pageX,pageY:n.pageY}]),n.type){case"mousedown":this.start(n);break;case"touchstart":this.start(n);break;case"touchmove":this.touchmove(n);break;case"mousemove":this.touchmove(n);break;case"touchend":h(this.end(n));break;case"mouseup":h(this.end(n));break;case"webkitTransitionEnd":case"msTransitionEnd":case"oTransitionEnd":case"otransitionend":case"transitionend":h(this.transitionEnd(n));break;case"resize":h(t)}e.stopPropagation&&n.stopPropagation()},start:function(e){var t=e.touches[0];L={x:t.pageX,y:t.pageY,time:+new Date},y=void 0,x={},f.touch?(E.addEventListener("touchmove",this,!1),E.addEventListener("touchend",this,!1)):(E.addEventListener("mousemove",this,!1),E.addEventListener("mouseup",this,!1),document.addEventListener("mouseup",this,!1))},touchmove:function(t){if(!(t.touches.length>1||t.scale&&1!==t.scale||d.slideIsDisabled)){e.disableScroll&&t.preventDefault();var n=t.touches[0];x={x:n.pageX-L.x,y:n.pageY-L.y},"undefined"==typeof y&&(y=!!(y||Math.abs(x.x)<Math.abs(x.y))),y||(t.preventDefault(),u(),e.continuous?(a(o(S-1),x.x+g[o(S-1)],0),a(S,x.x+g[S],0),a(o(S+1),x.x+g[o(S+1)],0)):(x.x=x.x/(!S&&x.x>0||S==m.length-1&&x.x<0?Math.abs(x.x)/v+1:1),a(S-1,x.x+g[S-1],0),a(S,x.x+g[S],0),a(S+1,x.x+g[S+1],0)),e.onDrag&&e.onDrag())}},end:function(){var t=+new Date-L.time,n=Number(t)<250&&Math.abs(x.x)>20||Math.abs(x.x)>v/2,i=!S&&x.x>0||S==m.length-1&&x.x<0;e.continuous&&(i=!1);var r=x.x<0;y||(n&&!i?(r?(e.continuous?(s(o(S-1),-v,0),s(o(S+2),v,0)):s(S-1,-v,0),s(S,g[S]-v,b),s(o(S+1),g[o(S+1)]-v,b),S=o(S+1)):(e.continuous?(s(o(S+1),v,0),s(o(S-2),-v,0)):s(S+1,v,0),s(S,g[S]+v,b),s(o(S-1),g[o(S-1)]+v,b),S=o(S-1)),e.callback&&e.callback(S,m[S])):e.continuous?(s(o(S-1),-v,b),s(S,0,b),s(o(S+1),v,b)):(s(S-1,-v,b),s(S,0,b),s(S+1,v,b))),f.touch?(E.removeEventListener("touchmove",M,!1),E.removeEventListener("touchend",M,!1)):(E.removeEventListener("mousemove",M,!1),E.removeEventListener("mouseup",M,!1),document.removeEventListener("mouseup",M,!1)),e.onDragEnd&&e.onDragEnd()},transitionEnd:function(t){parseInt(t.target.getAttribute("data-index"),10)==S&&(D&&c(),e.transitionEnd&&e.transitionEnd.call(t,S,m[S]))}};this.update=function(){setTimeout(t)},this.setup=function(){t()},this.loop=function(t){return arguments.length&&(e.continuous=!!t),e.continuous},this.enableSlide=function(e){return arguments.length&&(this.slideIsDisabled=!e),!this.slideIsDisabled},this.slide=this.select=function(e,t){u(),r(e,t)},this.prev=this.previous=function(){u(),n()},this.next=function(){u(),i()},this.stop=function(){u()},this.start=function(){c()},this.autoPlay=function(e){!D||0>D?u():(D=e,c())},this.currentIndex=this.selected=function(){return S},this.slidesCount=this.count=function(){return T},this.kill=function(){u(),E.style.width="",E.style.left="",m&&(m=[]),f.addEventListener?(E.removeEventListener("touchstart",M,!1),E.removeEventListener("webkitTransitionEnd",M,!1),E.removeEventListener("msTransitionEnd",M,!1),E.removeEventListener("oTransitionEnd",M,!1),E.removeEventListener("otransitionend",M,!1),E.removeEventListener("transitionend",M,!1),window.removeEventListener("resize",M,!1)):window.onresize=null},this.load=function(){t(),D&&c(),f.addEventListener?(f.touch?E.addEventListener("touchstart",M,!1):E.addEventListener("mousedown",M,!1),f.transitions&&(E.addEventListener("webkitTransitionEnd",M,!1),E.addEventListener("msTransitionEnd",M,!1),E.addEventListener("oTransitionEnd",M,!1),E.addEventListener("otransitionend",M,!1),E.addEventListener("transitionend",M,!1)),window.addEventListener("resize",M,!1)):window.onresize=function(){t()}}}}})}(ionic),function(e){"use strict";e.views.Toggle=e.views.View.inherit({initialize:function(t){var n=this;this.el=t.el,this.checkbox=t.checkbox,this.track=t.track,this.handle=t.handle,this.openPercent=-1,this.onChange=t.onChange||function(){},this.triggerThreshold=t.triggerThreshold||20,this.dragStartHandler=function(e){n.dragStart(e)},this.dragHandler=function(e){n.drag(e)},this.holdHandler=function(e){n.hold(e)},this.releaseHandler=function(e){n.release(e)},this.dragStartGesture=e.onGesture("dragstart",this.dragStartHandler,this.el),this.dragGesture=e.onGesture("drag",this.dragHandler,this.el),this.dragHoldGesture=e.onGesture("hold",this.holdHandler,this.el),this.dragReleaseGesture=e.onGesture("release",this.releaseHandler,this.el)},destroy:function(){e.offGesture(this.dragStartGesture,"dragstart",this.dragStartGesture),e.offGesture(this.dragGesture,"drag",this.dragGesture),e.offGesture(this.dragHoldGesture,"hold",this.holdHandler),e.offGesture(this.dragReleaseGesture,"release",this.releaseHandler)},tap:function(){"disabled"!==this.el.getAttribute("disabled")&&this.val(!this.checkbox.checked)},dragStart:function(e){this.checkbox.disabled||(this._dragInfo={width:this.el.offsetWidth,left:this.el.offsetLeft,right:this.el.offsetLeft+this.el.offsetWidth,triggerX:this.el.offsetWidth/2,initialState:this.checkbox.checked},e.gesture.srcEvent.preventDefault(),this.hold(e))},drag:function(t){var n=this;this._dragInfo&&(t.gesture.srcEvent.preventDefault(),e.requestAnimationFrame(function(){if(n._dragInfo){var e=t.gesture.touches[0].pageX-n._dragInfo.left,i=n._dragInfo.width-n.triggerThreshold;n._dragInfo.initialState?e<n.triggerThreshold?n.setOpenPercent(0):e>n._dragInfo.triggerX&&n.setOpenPercent(100):e<n._dragInfo.triggerX?n.setOpenPercent(0):e>i&&n.setOpenPercent(100)}}))},endDrag:function(){this._dragInfo=null},hold:function(){this.el.classList.add("dragging")},release:function(e){this.el.classList.remove("dragging"),this.endDrag(e)},setOpenPercent:function(t){if(this.openPercent<0||t<this.openPercent-3||t>this.openPercent+3)if(this.openPercent=t,0===t)this.val(!1);else if(100===t)this.val(!0);else{var n=Math.round(t/100*this.track.offsetWidth-this.handle.offsetWidth);n=1>n?0:n,this.handle.style[e.CSS.TRANSFORM]="translate3d("+n+"px,0,0)"}},val:function(t){return(t===!0||t===!1)&&(""!==this.handle.style[e.CSS.TRANSFORM]&&(this.handle.style[e.CSS.TRANSFORM]=""),this.checkbox.checked=t,this.openPercent=t?100:0,this.onChange&&this.onChange()),this.checkbox.checked}})}(ionic)}(); \ No newline at end of file +!function(){function e(e,t,n){t!==!1?X.addEventListener(e,J[e],n):X.removeEventListener(e,J[e])}function t(e){var t=w(e.target),i=T(t);if(ionic.tap.requiresNativeClick(i)||$)return!1;var r=ionic.tap.pointerCoord(e);n("click",i,r.x,r.y),h(i)}function n(e,t,n,i){var r=document.createEvent("MouseEvents");r.initMouseEvent(e,!0,!0,window,1,0,0,n,i,!1,!1,!1,!1,0,null),r.isIonicTap=!0,t.dispatchEvent(r)}function i(e){return"submit"==e.target.type&&0===e.detail?null:ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)||!e.isIonicTap&&!ionic.tap.requiresNativeClick(e.target)?(e.stopPropagation(),ionic.tap.isLabelWithTextInput(e.target)||e.preventDefault(),!1):void 0}function r(t){return t.isIonicTap||p(t)?null:B?(t.stopPropagation(),ionic.Platform.isEdge()||ionic.tap.isTextInput(t.target)&&K===t.target||b(t.target.tagName)||ionic.tap.isVideo(t.target)||t.preventDefault(),!1):($=!1,q=ionic.tap.pointerCoord(t),e("mousemove"),void ionic.activator.start(t))}function a(n){return B?(n.stopPropagation(),n.preventDefault(),!1):p(n)||b(n.target.tagName)?!1:(_(n)||t(n),e("mousemove",!1),ionic.activator.end(),void($=!1))}function o(t){return _(t)?(e("mousemove",!1),ionic.activator.end(),$=!0,!1):void 0}function s(t){if(!p(t)&&($=!1,u(),q=ionic.tap.pointerCoord(t),e(j),ionic.activator.start(t),ionic.Platform.isIOS()&&ionic.tap.isLabelWithTextInput(t.target))){var n=T(w(t.target));n!==F&&t.preventDefault()}}function l(e){p(e)||(u(),_(e)||(t(e),b(e.target.tagName)&&e.preventDefault()),K=e.target,d())}function c(t){return _(t)?($=!0,e(j,!1),ionic.activator.end(),!1):void 0}function d(){e(j,!1),ionic.activator.end(),$=!1}function u(){B=!0,clearTimeout(W),W=setTimeout(function(){B=!1},600)}function p(e){return e.isTapHandled?!0:(e.isTapHandled=!0,ionic.tap.isElementTapDisabled(e.target)?!0:ionic.scroll.isScrolling&&ionic.tap.containsOrIsTextInput(e.target)?(e.preventDefault(),!0):void 0)}function h(e){U=null;var t=!1;"SELECT"==e.tagName?(n("mousedown",e,0,0),e.focus&&e.focus(),t=!0):v()===e?t=!0:/^(input|textarea|ion-label)$/i.test(e.tagName)||e.isContentEditable?(t=!0,e.focus&&e.focus(),e.value=e.value,B&&(U=e)):f(),t&&(v(e),ionic.trigger("ionic.focusin",{target:e},!0))}function f(){var e=v();e&&(/^(input|textarea|select)$/i.test(e.tagName)||e.isContentEditable)&&e.blur(),v(null)}function m(e){B&&ionic.tap.isTextInput(v())&&ionic.tap.isTextInput(U)&&U!==e.target&&(U.focus(),U=null),ionic.scroll.isScrolling=!1}function g(){v(null)}function v(e){return arguments.length&&(F=e),F||document.activeElement}function _(e){if(!e||1!==e.target.nodeType||!q||0===q.x&&0===q.y)return!1;var t=ionic.tap.pointerCoord(e),n=!(!e.target.classList||!e.target.classList.contains||"function"!=typeof e.target.classList.contains),i=n&&e.target.classList.contains("button")?Q:Z;return Math.abs(q.x-t.x)>i||Math.abs(q.y-t.y)>i}function w(e,t){for(var n=e,i=0;6>i&&n;i++){if("LABEL"===n.tagName)return n;n=n.parentElement}return t!==!1?e:void 0}function T(e){if(e&&"LABEL"===e.tagName){if(e.control)return e.control;if(e.querySelector){var t=e.querySelector("input,textarea,select");if(t)return t}}return e}function b(e){return/^(select|option)$/i.test(e)}function S(){ionic.keyboard.isInitialized||(V()?(window.addEventListener("native.keyboardshow",pe),window.addEventListener("native.keyboardhide",x)):document.body.addEventListener("focusout",x),document.body.addEventListener("ionic.focusin",ue),document.body.addEventListener("focusin",ue),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!0)}function y(e){clearTimeout(re),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),ionic.keyboard.height=e.keyboardHeight,le?C(O,!0):C(I,!0)}function E(e){return clearTimeout(re),e.target&&!e.target.readOnly&&ionic.tap.isKeyboardElement(e.target)&&(ne=ionic.DomUtil.getParentWithClass(e.target,de))?(ee=e.target,ne.classList.contains("overflow-scroll")||(document.body.scrollTop=0,ne.scrollTop=0,ionic.requestAnimationFrame(function(){document.body.scrollTop=0,ne.scrollTop=0}),window.navigator.msPointerEnabled?document.addEventListener("MSPointerMove",L,!1):document.addEventListener("touchmove",L,!1)),(!ionic.keyboard.isOpen||ionic.keyboard.isClosing)&&(ionic.keyboard.isOpening=!0,ionic.keyboard.isClosing=!1),document.addEventListener("keydown",M,!1),void(ionic.keyboard.isOpen||V()?ionic.keyboard.isOpen&&I():C(I,!0))):(ee&&(te=ee),void(ee=null))}function x(){clearTimeout(re),(ionic.keyboard.isOpen||ionic.keyboard.isOpening)&&(ionic.keyboard.isClosing=!0,ionic.keyboard.isOpening=!1),re=setTimeout(function(){ionic.requestAnimationFrame(function(){le?C(function(){O(),P()},!1):C(P,!1)})},50)}function D(){ionic.keyboard.isLandscape=!ionic.keyboard.isLandscape,ionic.Platform.isIOS()&&O(),ionic.Platform.isAndroid()&&(ionic.keyboard.isOpen&&V()?le=!0:C(O,!1))}function M(e){ionic.scroll.isScrolling&&L(e)}function L(e){"TEXTAREA"!==e.target.tagName&&e.preventDefault()}function C(e,t){clearInterval(ie);var n,i=0,r=G(),a=r;return n=ionic.Platform.isAndroid()&&ionic.Platform.version()<4.4?30:ionic.Platform.isAndroid()?10:1,ie=setInterval(function(){a=G(),(!(++i<n)||(N(a)||z(a))&&ionic.keyboard.height)&&(V()||(ionic.keyboard.height=Math.abs(r-window.innerHeight)),ionic.keyboard.isOpen=t,clearInterval(ie),e())},50),n}function P(){clearTimeout(re),ionic.keyboard.isOpen=!1,ionic.keyboard.isClosing=!1,(ee||te)&&ionic.trigger("resetScrollView",{target:ee||te},!0),ionic.requestAnimationFrame(function(){document.body.classList.remove(ce)}),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerMove",L):document.removeEventListener("touchmove",L),document.removeEventListener("keydown",M),ionic.Platform.isAndroid()&&(V()&&cordova.plugins.Keyboard.close(),ee&&ee.blur()),ee=null,te=null}function I(){ionic.keyboard.isOpen=!0,ionic.keyboard.isOpening=!1;var e={keyboardHeight:k(),viewportHeight:ae};if(ee){e.target=ee;var t=ee.getBoundingClientRect();e.elementTop=Math.round(t.top),e.elementBottom=Math.round(t.bottom),e.windowHeight=e.viewportHeight-e.keyboardHeight,e.isElementUnderKeyboard=e.elementBottom>e.windowHeight,ionic.trigger("scrollChildIntoView",e,!0)}return setTimeout(function(){document.body.classList.add(ce)},400),e}function k(){if(ionic.keyboard.height)return ionic.keyboard.height;if(ionic.Platform.isAndroid()){if(ionic.Platform.isFullScreen)return 275;var e=window.innerHeight;return ae>e?ae-e:0}return ionic.Platform.isIOS()?ionic.keyboard.isLandscape?206:ionic.Platform.isWebView()?260:216:275}function N(e){return!!(!ionic.keyboard.isLandscape&&oe&&Math.abs(oe-e)<2)}function z(e){return!!(ionic.keyboard.isLandscape&&se&&Math.abs(se-e)<2)}function O(){le=!1,ae=G(),ionic.keyboard.isLandscape&&!se?se=ae:ionic.keyboard.isLandscape||oe||(oe=ae),ee&&ionic.trigger("resetScrollView",{target:ee},!0),ionic.keyboard.isOpen&&ionic.tap.isTextInput(ee)&&I()}function A(){var e=G();e/window.innerWidth<1&&(ionic.keyboard.isLandscape=!0),ae=e,ionic.keyboard.isLandscape&&!se?se=ae:ionic.keyboard.isLandscape||oe||(oe=ae)}function G(){var e=window.innerHeight;return ionic.Platform.isAndroid()&&ionic.Platform.isFullScreen||!ionic.keyboard.isOpen&&!ionic.keyboard.isOpening||ionic.keyboard.isClosing?e:e+k()}function V(){return!!(window.cordova&&cordova.plugins&&cordova.plugins.Keyboard)}function R(){var e;for(e=0;e<document.head.children.length;e++)if("viewport"==document.head.children[e].name){he=document.head.children[e];break}if(he){var t,n=he.content.toLowerCase().replace(/\s+/g,"").split(",");for(e=0;e<n.length;e++)n[e]&&(t=n[e].split("="),fe[t[0]]=t.length>1?t[1]:"_");H()}}function H(){var e=fe.width,t=fe.height,n=ionic.Platform,i=n.version(),r="device-width",a="device-height",o=ionic.viewport.orientation();delete fe.height,fe.width=r,n.isIPad()?i>7?delete fe.width:n.isWebView()?90==o?fe.height="0":7==i&&(fe.height=a):7>i&&(fe.height="0"):n.isIOS()&&(n.isWebView()?i>7?delete fe.width:7>i?t&&(fe.height="0"):7==i&&(fe.height=a):7>i&&t&&(fe.height="0")),(e!==fe.width||t!==fe.height)&&Y()}function Y(){var e,t=[];for(e in fe)fe[e]&&t.push(e+("_"==fe[e]?"":"="+fe[e]));he.content=t.join(", ")}window.ionic=window.ionic||{},window.ionic.views={},window.ionic.version="1.2.4",function(e){e.DelegateService=function(e){function t(){return!0}if(e.indexOf("$getByHandle")>-1)throw new Error("Method '$getByHandle' is implicitly added to each delegate service. Do not list it as a method.");return["$log",function(n){function i(e,t){this._instances=e,this.handle=t}function r(){this._instances=[]}function a(e){return function(){var t,i=this.handle,r=arguments,a=0;return this._instances.forEach(function(n){if((!i||i==n.$$delegateHandle)&&n.$$filterFn(n)){a++;var o=n[e].apply(n,r);1===a&&(t=o)}}),!a&&i?n.warn('Delegate for handle "'+i+'" could not find a corresponding element with delegate-handle="'+i+'"! '+e+"() was not called!\nPossible cause: If you are calling "+e+'() immediately, and your element with delegate-handle="'+i+'" is a child of your controller, then your element may not be compiled yet. Put a $timeout around your call to '+e+"() and try again."):t}}return e.forEach(function(e){i.prototype[e]=a(e)}),r.prototype=i.prototype,r.prototype._registerInstance=function(e,n,i){var r=this._instances;return e.$$delegateHandle=n,e.$$filterFn=i||t,r.push(e),function(){var t=r.indexOf(e);-1!==t&&r.splice(t,1)}},r.prototype.$getByHandle=function(e){return new i(this._instances,e)},new r}]}}(window.ionic),function(e,t,n){function i(){a=!0;for(var e=0;e<r.length;e++)n.requestAnimationFrame(r[e]);r=[],t.removeEventListener("DOMContentLoaded",i)}var r=[],a="complete"===t.readyState||"interactive"===t.readyState;a||t.addEventListener("DOMContentLoaded",i),e._rAF=function(){return e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||function(t){e.setTimeout(t,16)}}();var o=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame;n.DomUtil={requestAnimationFrame:function(t){return e._rAF(t)},cancelAnimationFrame:function(e){o(e)},animationFrameThrottle:function(e){var t,i,r;return function(){t=arguments,r=this,i||(i=!0,n.requestAnimationFrame(function(){e.apply(r,t),i=!1}))}},contains:function(e,t){for(var n=t;n;){if(n===e)return!0;n=n.parentNode}},getPositionInParent:function(e){return{left:e.offsetLeft,top:e.offsetTop}},getOffsetTop:function(e){var t=0;if(e.offsetParent){do t+=e.offsetTop,e=e.offsetParent;while(e);return t}},ready:function(e){a?n.requestAnimationFrame(e):r.push(e)},getTextBounds:function(n){if(t.createRange){var i=t.createRange();if(i.selectNodeContents(n),i.getBoundingClientRect){var r=i.getBoundingClientRect();if(r){var a=e.scrollX,o=e.scrollY;return{top:r.top+o,left:r.left+a,right:r.left+a+r.width,bottom:r.top+o+r.height,width:r.width,height:r.height}}}}return null},getChildIndex:function(e,t){if(t)for(var n,i=e.parentNode.children,r=0,a=0,o=i.length;o>r;r++)if(n=i[r],n.nodeName&&n.nodeName.toLowerCase()==t){if(n==e)return a;a++}return Array.prototype.slice.call(e.parentNode.children).indexOf(e)},swapNodes:function(e,t){t.parentNode.insertBefore(e,t)},elementIsDescendant:function(e,t,n){var i=e;do{if(i===t)return!0;i=i.parentNode}while(i&&i!==n);return!1},getParentWithClass:function(e,t,n){for(n=n||10;e.parentNode&&n--;){if(e.parentNode.classList&&e.parentNode.classList.contains(t))return e.parentNode;e=e.parentNode}return null},getParentOrSelfWithClass:function(e,t,n){for(n=n||10;e&&n--;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},rectContains:function(e,t,n,i,r,a){return n>e||e>r?!1:i>t||t>a?!1:!0},blurAll:function(){return t.activeElement&&t.activeElement!=t.body?(t.activeElement.blur(),t.activeElement):null},cachedAttr:function(e,t,n){if(e=e&&e.length&&e[0]||e,e&&e.setAttribute){var i="$attr-"+t;return arguments.length>2?e[i]!==n&&(e.setAttribute(t,n),e[i]=n):"undefined"==typeof e[i]&&(e[i]=e.getAttribute(t)),e[i]}},cachedStyles:function(e,t){if(e=e&&e.length&&e[0]||e,e&&e.style)for(var n in t)e["$style-"+n]!==t[n]&&(e.style[n]=e["$style-"+n]=t[n])}},n.requestAnimationFrame=n.DomUtil.requestAnimationFrame,n.cancelAnimationFrame=n.DomUtil.cancelAnimationFrame,n.animationFrameThrottle=n.DomUtil.animationFrameThrottle}(window,document,ionic),function(e){e.CustomEvent=function(){if("function"==typeof window.CustomEvent)return CustomEvent;var e=function(e,t){var n;t=t||{bubbles:!1,cancelable:!1,detail:void 0};try{n=document.createEvent("CustomEvent"),n.initCustomEvent(e,t.bubbles,t.cancelable,t.detail)}catch(i){n=document.createEvent("Event");for(var r in t)n[r]=t[r];n.initEvent(e,t.bubbles,t.cancelable)}return n};return e.prototype=window.Event.prototype,e}(),e.EventController={VIRTUALIZED_EVENTS:["tap","swipe","swiperight","swipeleft","drag","hold","release"],trigger:function(t,n,i,r){var a=new e.CustomEvent(t,{detail:n,bubbles:!!i,cancelable:!!r});n&&n.target&&n.target.dispatchEvent&&n.target.dispatchEvent(a)||window.dispatchEvent(a)},on:function(t,n,i){for(var r=i||window,a=0,o=this.VIRTUALIZED_EVENTS.length;o>a;a++)if(t==this.VIRTUALIZED_EVENTS[a]){var s=new e.Gesture(i);return s.on(t,n),s}r.addEventListener(t,n)},off:function(e,t,n){n.removeEventListener(e,t)},onGesture:function(t,n,i,r){var a=new e.Gesture(i,r);return a.on(t,n),a},offGesture:function(e,t,n){e&&e.off(t,n)},handlePopState:function(){}},e.on=function(){e.EventController.on.apply(e.EventController,arguments)},e.off=function(){e.EventController.off.apply(e.EventController,arguments)},e.trigger=e.EventController.trigger,e.onGesture=function(){return e.EventController.onGesture.apply(e.EventController.onGesture,arguments)},e.offGesture=function(){return e.EventController.offGesture.apply(e.EventController.offGesture,arguments)}}(window.ionic),function(e){function t(){if(!e.Gestures.READY){e.Gestures.event.determineEventTypes();for(var t in e.Gestures.gestures)e.Gestures.gestures.hasOwnProperty(t)&&e.Gestures.detection.register(e.Gestures.gestures[t]);e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_MOVE,e.Gestures.detection.detect),e.Gestures.event.onTouch(e.Gestures.DOCUMENT,e.Gestures.EVENT_END,e.Gestures.detection.detect),e.Gestures.READY=!0}}e.Gesture=function(t,n){return new e.Gestures.Instance(t,n||{})},e.Gestures={},e.Gestures.defaults={stop_browser_behavior:"disable-user-behavior"},e.Gestures.HAS_POINTEREVENTS=window.navigator.pointerEnabled||window.navigator.msPointerEnabled,e.Gestures.HAS_TOUCHEVENTS="ontouchstart"in window,e.Gestures.MOBILE_REGEX=/mobile|tablet|ip(ad|hone|od)|android|silk/i,e.Gestures.NO_MOUSEEVENTS=e.Gestures.HAS_TOUCHEVENTS&&window.navigator.userAgent.match(e.Gestures.MOBILE_REGEX),e.Gestures.EVENT_TYPES={},e.Gestures.DIRECTION_DOWN="down",e.Gestures.DIRECTION_LEFT="left",e.Gestures.DIRECTION_UP="up",e.Gestures.DIRECTION_RIGHT="right",e.Gestures.POINTER_MOUSE="mouse",e.Gestures.POINTER_TOUCH="touch",e.Gestures.POINTER_PEN="pen",e.Gestures.EVENT_START="start",e.Gestures.EVENT_MOVE="move",e.Gestures.EVENT_END="end",e.Gestures.DOCUMENT=window.document,e.Gestures.plugins={},e.Gestures.READY=!1,e.Gestures.Instance=function(n,i){var r=this;return null===n?this:(t(),this.element=n,this.enabled=!0,this.options=e.Gestures.utils.extend(e.Gestures.utils.extend({},e.Gestures.defaults),i||{}),this.options.stop_browser_behavior&&e.Gestures.utils.stopDefaultBrowserBehavior(this.element,this.options.stop_browser_behavior),e.Gestures.event.onTouch(n,e.Gestures.EVENT_START,function(t){r.enabled&&e.Gestures.detection.startDetect(r,t)}),this)},e.Gestures.Instance.prototype={on:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.addEventListener(n[i],t,!1);return this},off:function(e,t){for(var n=e.split(" "),i=0;i<n.length;i++)this.element.removeEventListener(n[i],t,!1);return this},trigger:function(t,n){var i=e.Gestures.DOCUMENT.createEvent("Event");i.initEvent(t,!0,!0),i.gesture=n;var r=this.element;return e.Gestures.utils.hasParent(n.target,r)&&(r=n.target),r.dispatchEvent(i),this},enable:function(e){return this.enabled=e,this}};var n=null,i=!1,r=!1;e.Gestures.event={bindDom:function(e,t,n){for(var i=t.split(" "),r=0;r<i.length;r++)e.addEventListener(i[r],n,!1)},onTouch:function(t,a,o){var s=this;this.bindDom(t,e.Gestures.EVENT_TYPES[a],function(l){var c=l.type.toLowerCase();if(!c.match(/mouse/)||!r){c.match(/touch/)||c.match(/pointerdown/)||c.match(/mouse/)&&1===l.which?i=!0:c.match(/mouse/)&&1!==l.which&&(i=!1),c.match(/touch|pointer/)&&(r=!0);var d=0;i&&(e.Gestures.HAS_POINTEREVENTS&&a!=e.Gestures.EVENT_END?d=e.Gestures.PointerEvent.updatePointer(a,l):c.match(/touch/)?d=l.touches.length:r||(d=c.match(/up/)?0:1),d>0&&a==e.Gestures.EVENT_END?a=e.Gestures.EVENT_MOVE:d||(a=e.Gestures.EVENT_END),(d||null===n)&&(n=l),o.call(e.Gestures.detection,s.collectEventData(t,a,s.getTouchList(n,a),l)),e.Gestures.HAS_POINTEREVENTS&&a==e.Gestures.EVENT_END&&(d=e.Gestures.PointerEvent.updatePointer(a,l))),d||(n=null,i=!1,r=!1,e.Gestures.PointerEvent.reset())}})},determineEventTypes:function(){var t;t=e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getEvents():e.Gestures.NO_MOUSEEVENTS?["touchstart","touchmove","touchend touchcancel"]:["touchstart mousedown","touchmove mousemove","touchend touchcancel mouseup"],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_START]=t[0],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_MOVE]=t[1],e.Gestures.EVENT_TYPES[e.Gestures.EVENT_END]=t[2]},getTouchList:function(t){return e.Gestures.HAS_POINTEREVENTS?e.Gestures.PointerEvent.getTouchList():t.touches?t.touches:(t.identifier=1,[t])},collectEventData:function(t,n,i,r){var a=e.Gestures.POINTER_TOUCH;return(r.type.match(/mouse/)||e.Gestures.PointerEvent.matchType(e.Gestures.POINTER_MOUSE,r))&&(a=e.Gestures.POINTER_MOUSE),{center:e.Gestures.utils.getCenter(i),timeStamp:(new Date).getTime(),target:r.target,touches:i,eventType:n,pointerType:a,srcEvent:r,preventDefault:function(){this.srcEvent.preventManipulation&&this.srcEvent.preventManipulation(),this.srcEvent.preventDefault},stopPropagation:function(){this.srcEvent.stopPropagation()},stopDetect:function(){return e.Gestures.detection.stopDetect()}}}},e.Gestures.PointerEvent={pointers:{},getTouchList:function(){var e=this,t=[];return Object.keys(e.pointers).sort().forEach(function(n){t.push(e.pointers[n])}),t},updatePointer:function(t,n){return t==e.Gestures.EVENT_END?this.pointers={}:(n.identifier=n.pointerId,this.pointers[n.pointerId]=n),Object.keys(this.pointers).length},matchType:function(t,n){if(!n.pointerType)return!1;var i={};return i[e.Gestures.POINTER_MOUSE]=n.pointerType==n.MSPOINTER_TYPE_MOUSE||n.pointerType==e.Gestures.POINTER_MOUSE,i[e.Gestures.POINTER_TOUCH]=n.pointerType==n.MSPOINTER_TYPE_TOUCH||n.pointerType==e.Gestures.POINTER_TOUCH,i[e.Gestures.POINTER_PEN]=n.pointerType==n.MSPOINTER_TYPE_PEN||n.pointerType==e.Gestures.POINTER_PEN,i[t]},getEvents:function(){return["pointerdown MSPointerDown","pointermove MSPointerMove","pointerup pointercancel MSPointerUp MSPointerCancel"]},reset:function(){this.pointers={}}},e.Gestures.utils={extend:function(e,t,n){for(var i in t)void 0!==e[i]&&n||(e[i]=t[i]);return e},hasParent:function(e,t){for(;e;){if(e==t)return!0;e=e.parentNode}return!1},getCenter:function(e){for(var t=[],n=[],i=0,r=e.length;r>i;i++)t.push(e[i].pageX),n.push(e[i].pageY);return{pageX:(Math.min.apply(Math,t)+Math.max.apply(Math,t))/2,pageY:(Math.min.apply(Math,n)+Math.max.apply(Math,n))/2}},getVelocity:function(e,t,n){return{x:Math.abs(t/e)||0,y:Math.abs(n/e)||0}},getAngle:function(e,t){var n=t.pageY-e.pageY,i=t.pageX-e.pageX;return 180*Math.atan2(n,i)/Math.PI},getDirection:function(t,n){var i=Math.abs(t.pageX-n.pageX),r=Math.abs(t.pageY-n.pageY);return i>=r?t.pageX-n.pageX>0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT:t.pageY-n.pageY>0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN},getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},getScale:function(e,t){return e.length>=2&&t.length>=2?this.getDistance(t[0],t[1])/this.getDistance(e[0],e[1]):1},getRotation:function(e,t){return e.length>=2&&t.length>=2?this.getAngle(t[1],t[0])-this.getAngle(e[1],e[0]):0},isVertical:function(t){return t==e.Gestures.DIRECTION_UP||t==e.Gestures.DIRECTION_DOWN},stopDefaultBrowserBehavior:function(e,t){e&&e.classList&&(e.classList.add(t),e.onselectstart=function(){return!1})}},e.Gestures.detection={gestures:[],current:null,previous:null,stopped:!1,startDetect:function(t,n){this.current||(this.stopped=!1,this.current={inst:t,startEvent:e.Gestures.utils.extend({},n),lastEvent:!1,name:""},this.detect(n))},detect:function(t){if(!this.current||this.stopped)return null;t=this.extendEventData(t);for(var n=this.current.inst.options,i=0,r=this.gestures.length;r>i;i++){var a=this.gestures[i];if(!this.stopped&&n[a.name]!==!1&&a.handler.call(a,t,this.current.inst)===!1){this.stopDetect();break}}return this.current&&(this.current.lastEvent=t),t.eventType==e.Gestures.EVENT_END&&!t.touches.length-1&&this.stopDetect(),t},stopDetect:function(){this.previous=e.Gestures.utils.extend({},this.current),this.current=null,this.stopped=!0},extendEventData:function(t){var n=this.current.startEvent;if(n&&(t.touches.length!=n.touches.length||t.touches===n.touches)){n.touches=[];for(var i=0,r=t.touches.length;r>i;i++)n.touches.push(e.Gestures.utils.extend({},t.touches[i]))}var a=t.timeStamp-n.timeStamp,o=t.center.pageX-n.center.pageX,s=t.center.pageY-n.center.pageY,l=e.Gestures.utils.getVelocity(a,o,s);return e.Gestures.utils.extend(t,{deltaTime:a,deltaX:o,deltaY:s,velocityX:l.x,velocityY:l.y,distance:e.Gestures.utils.getDistance(n.center,t.center),angle:e.Gestures.utils.getAngle(n.center,t.center),direction:e.Gestures.utils.getDirection(n.center,t.center),scale:e.Gestures.utils.getScale(n.touches,t.touches),rotation:e.Gestures.utils.getRotation(n.touches,t.touches),startEvent:n}),t},register:function(t){var n=t.defaults||{};return void 0===n[t.name]&&(n[t.name]=!0),e.Gestures.utils.extend(e.Gestures.defaults,n,!0),t.index=t.index||1e3,this.gestures.push(t),this.gestures.sort(function(e,t){return e.index<t.index?-1:e.index>t.index?1:0}),this.gestures}},e.Gestures.gestures=e.Gestures.gestures||{},e.Gestures.gestures.Hold={name:"hold",index:10,defaults:{hold_timeout:500,hold_threshold:9},timer:null,handler:function(t,n){switch(t.eventType){case e.Gestures.EVENT_START:clearTimeout(this.timer),e.Gestures.detection.current.name=this.name,this.timer=setTimeout(function(){"hold"==e.Gestures.detection.current.name&&(e.tap.cancelClick(),n.trigger("hold",t))},n.options.hold_timeout);break;case e.Gestures.EVENT_MOVE:t.distance>n.options.hold_threshold&&clearTimeout(this.timer);break;case e.Gestures.EVENT_END:clearTimeout(this.timer)}}},e.Gestures.gestures.Tap={name:"tap",index:100,defaults:{tap_max_touchtime:250,tap_max_distance:10,tap_always:!0,doubletap_distance:20,doubletap_interval:300},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END&&"touchcancel"!=t.srcEvent.type){var i=e.Gestures.detection.previous,r=!1;if(t.deltaTime>n.options.tap_max_touchtime||t.distance>n.options.tap_max_distance)return;i&&"tap"==i.name&&t.timeStamp-i.lastEvent.timeStamp<n.options.doubletap_interval&&t.distance<n.options.doubletap_distance&&(n.trigger("doubletap",t),r=!0),(!r||n.options.tap_always)&&(e.Gestures.detection.current.name="tap",n.trigger("tap",t))}}},e.Gestures.gestures.Swipe={name:"swipe",index:40,defaults:{swipe_max_touches:1,swipe_velocity:.4},handler:function(t,n){if(t.eventType==e.Gestures.EVENT_END){if(n.options.swipe_max_touches>0&&t.touches.length>n.options.swipe_max_touches)return;(t.velocityX>n.options.swipe_velocity||t.velocityY>n.options.swipe_velocity)&&(n.trigger(this.name,t),n.trigger(this.name+t.direction,t))}}},e.Gestures.gestures.Drag={name:"drag",index:50,defaults:{drag_min_distance:10,correct_for_drag_min_distance:!0,drag_max_touches:1,drag_block_horizontal:!0,drag_block_vertical:!0,drag_lock_to_axis:!1,drag_lock_min_distance:25,prevent_default_directions:[]},triggered:!1,handler:function(t,n){if("touchstart"==t.srcEvent.type||"touchend"==t.srcEvent.type?this.preventedFirstMove=!1:this.preventedFirstMove||"touchmove"!=t.srcEvent.type||(n.options.prevent_default_directions.length>0&&-1!=n.options.prevent_default_directions.indexOf(t.direction)&&t.srcEvent.preventDefault(),this.preventedFirstMove=!0),e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(n.options.drag_max_touches>0&&t.touches.length>n.options.drag_max_touches))switch(t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:if(t.distance<n.options.drag_min_distance&&e.Gestures.detection.current.name!=this.name)return;if(e.Gestures.detection.current.name!=this.name&&(e.Gestures.detection.current.name=this.name,n.options.correct_for_drag_min_distance)){var i=Math.abs(n.options.drag_min_distance/t.distance);e.Gestures.detection.current.startEvent.center.pageX+=t.deltaX*i,e.Gestures.detection.current.startEvent.center.pageY+=t.deltaY*i,t=e.Gestures.detection.extendEventData(t)}(e.Gestures.detection.current.lastEvent.drag_locked_to_axis||n.options.drag_lock_to_axis&&n.options.drag_lock_min_distance<=t.distance)&&(t.drag_locked_to_axis=!0);var r=e.Gestures.detection.current.lastEvent.direction;t.drag_locked_to_axis&&r!==t.direction&&(e.Gestures.utils.isVertical(r)?t.direction=t.deltaY<0?e.Gestures.DIRECTION_UP:e.Gestures.DIRECTION_DOWN:t.direction=t.deltaX<0?e.Gestures.DIRECTION_LEFT:e.Gestures.DIRECTION_RIGHT),this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),n.trigger(this.name+t.direction,t),(n.options.drag_block_vertical&&e.Gestures.utils.isVertical(t.direction)||n.options.drag_block_horizontal&&!e.Gestures.utils.isVertical(t.direction))&&t.preventDefault();break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Transform={name:"transform",index:45,defaults:{transform_min_scale:.01,transform_min_rotation:1,transform_always_block:!1},triggered:!1,handler:function(t,n){if(e.Gestures.detection.current.name!=this.name&&this.triggered)return n.trigger(this.name+"end",t),void(this.triggered=!1);if(!(t.touches.length<2))switch(n.options.transform_always_block&&t.preventDefault(),t.eventType){case e.Gestures.EVENT_START:this.triggered=!1;break;case e.Gestures.EVENT_MOVE:var i=Math.abs(1-t.scale),r=Math.abs(t.rotation);if(i<n.options.transform_min_scale&&r<n.options.transform_min_rotation)return;e.Gestures.detection.current.name=this.name,this.triggered||(n.trigger(this.name+"start",t),this.triggered=!0),n.trigger(this.name,t),r>n.options.transform_min_rotation&&n.trigger("rotate",t),i>n.options.transform_min_scale&&(n.trigger("pinch",t),n.trigger("pinch"+(t.scale<1?"in":"out"),t));break;case e.Gestures.EVENT_END:this.triggered&&n.trigger(this.name+"end",t),this.triggered=!1}}},e.Gestures.gestures.Touch={name:"touch",index:-(1/0),defaults:{prevent_default:!1,prevent_mouseevents:!1},handler:function(t,n){return n.options.prevent_mouseevents&&t.pointerType==e.Gestures.POINTER_MOUSE?void t.stopDetect():(n.options.prevent_default&&t.preventDefault(),void(t.eventType==e.Gestures.EVENT_START&&n.trigger(this.name,t)))}},e.Gestures.gestures.Release={name:"release",index:1/0,handler:function(t,n){t.eventType==e.Gestures.EVENT_END&&n.trigger(this.name,t)}}}(window.ionic),function(e,t,n){function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=new RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null===n?"":decodeURIComponent(n[1].replace(/\+/g," "))}function r(){setTimeout(function(){!f.isReady&&f.isWebView()},_)}function a(){f.isWebView()?t.addEventListener("deviceready",o,!1):o(),s&&e.removeEventListener("load",a,!1)}function o(){f.isReady=!0,f.detect();for(var e=0;e<v.length;e++)v[e]();v=[],n.trigger("platformready",{target:t}),h(function(){t.body.classList.add("platform-ready")})}var s,l="ios",c="android",d="windowsphone",u="edge",p="crosswalk",h=n.requestAnimationFrame,f=n.Platform={navigator:e.navigator,isReady:!1,isFullScreen:!1,platforms:null,grade:null,ua:navigator.userAgent,ready:function(e){f.isReady?e():v.push(e)},detect:function(){f._checkPlatforms(),h(function(){for(var e=0;e<f.platforms.length;e++)t.body.classList.add("platform-"+f.platforms[e])})},setGrade:function(e){var n=f.grade;f.grade=e,h(function(){n&&t.body.classList.remove("grade-"+n),t.body.classList.add("grade-"+e)})},device:function(){return e.device||{}},_checkPlatforms:function(){f.platforms=[];var t="a";f.isWebView()?(f.platforms.push("webview"),e.cordova||e.PhoneGap||e.phonegap?f.platforms.push("cordova"):e.forge&&f.platforms.push("trigger")):f.platforms.push("browser"),f.isIPad()&&f.platforms.push("ipad");var n=f.platform();if(n){f.platforms.push(n);var i=f.version();if(i){var r=i.toString();r.indexOf(".")>0?r=r.replace(".","_"):r+="_0",f.platforms.push(n+r.split("_")[0]),f.platforms.push(n+r),f.isAndroid()&&4.4>i?t=4>i?"c":"b":f.isWindowsPhone()&&(t="b")}}f.setGrade(t)},isWebView:function(){return!!(e.cordova||e.PhoneGap||e.phonegap||e.forge)},isIPad:function(){return/iPad/i.test(f.navigator.platform)?!0:/iPad/i.test(f.ua)},isIOS:function(){return f.is(l)},isAndroid:function(){return f.is(c)},isWindowsPhone:function(){return f.is(d)},isEdge:function(){return f.is(u)},isCrosswalk:function(){return f.is(p)},platform:function(){return null===m&&f.setPlatform(f.device().platform),m},setPlatform:function(e){m="undefined"!=typeof e&&null!==e&&e.length?e.toLowerCase():i("ionicplatform")?i("ionicplatform"):f.ua.indexOf("Edge")>-1?u:f.ua.indexOf("Windows Phone")>-1?d:f.ua.indexOf("Android")>0?c:/iPhone|iPad|iPod/.test(f.ua)?l:f.navigator.platform&&navigator.platform.toLowerCase().split(" ")[0]||""},version:function(){return null===g&&f.setVersion(f.device().version),g},setVersion:function(e){if("undefined"!=typeof e&&null!==e&&(e=e.split("."),e=parseFloat(e[0]+"."+(e.length>1?e[1]:0)),!isNaN(e)))return void(g=e);g=0;var t=f.platform(),n={android:/Android (\d+).(\d+)?/,ios:/OS (\d+)_(\d+)?/,windowsphone:/Windows Phone (\d+).(\d+)?/};n[t]&&(e=f.ua.match(n[t]),e&&e.length>2&&(g=parseFloat(e[1]+"."+e[2])))},is:function(e){if(e=e.toLowerCase(),f.platforms)for(var t=0;t<f.platforms.length;t++)if(f.platforms[t]===e)return!0;var n=f.platform();return n?n===e.toLowerCase():f.ua.toLowerCase().indexOf(e)>=0},exitApp:function(){f.ready(function(){navigator.app&&navigator.app.exitApp&&navigator.app.exitApp()})},showStatusBar:function(n){f._showStatusBar=n,f.ready(function(){h(function(){f._showStatusBar?(e.StatusBar&&e.StatusBar.show(),t.body.classList.remove("status-bar-hide")):(e.StatusBar&&e.StatusBar.hide(),t.body.classList.add("status-bar-hide"))})})},fullScreen:function(e,i){f.isFullScreen=e!==!1,n.DomUtil.ready(function(){h(function(){f.isFullScreen?t.body.classList.add("fullscreen"):t.body.classList.remove("fullscreen")}),f.showStatusBar(i===!0)})}},m=null,g=null,v=[],_=2e3;r(),"complete"===t.readyState?a():(s=!0,e.addEventListener("load",a,!1))}(window,document,ionic),function(e,t){"use strict";t.CSS={},t.CSS.TRANSITION=[],t.CSS.TRANSFORM=[],t.EVENTS={},function(){var n,i=["webkitTransform","transform","-webkit-transform","webkit-transform","-moz-transform","moz-transform","MozTransform","mozTransform","msTransform"];for(n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSFORM=i[n];break}for(i=["webkitTransition","mozTransition","msTransition","transition"],n=0;n<i.length;n++)if(void 0!==e.documentElement.style[i[n]]){t.CSS.TRANSITION=i[n];break}t.CSS.TRANSITION=t.CSS.TRANSITION||"transition";var r=t.CSS.TRANSITION.indexOf("webkit")>-1;t.CSS.TRANSITION_DURATION=(r?"-webkit-":"")+"transition-duration",t.CSS.TRANSITIONEND=(r?"webkitTransitionEnd ":"")+"transitionend"}(),function(){var e="touchstart",n="touchmove",i="touchend",r="touchcancel";window.navigator.pointerEnabled?(e="pointerdown", +n="pointermove",i="pointerup",r="pointercancel"):window.navigator.msPointerEnabled&&(e="MSPointerDown",n="MSPointerMove",i="MSPointerUp",r="MSPointerCancel"),t.EVENTS.touchstart=e,t.EVENTS.touchmove=n,t.EVENTS.touchend=i,t.EVENTS.touchcancel=r}(),"classList"in e.documentElement||!Object.defineProperty||"undefined"==typeof HTMLElement||Object.defineProperty(HTMLElement.prototype,"classList",{get:function(){function e(e){return function(){var n,i=t.className.split(/\s+/);for(n=0;n<arguments.length;n++)e(i,i.indexOf(arguments[n]),arguments[n]);t.className=i.join(" ")}}var t=this;return{add:e(function(e,t,n){~t||e.push(n)}),remove:e(function(e,t){~t&&e.splice(t,1)}),toggle:e(function(e,t,n){~t?e.splice(t,1):e.push(n)}),contains:function(e){return!!~t.className.split(/\s+/).indexOf(e)},item:function(e){return t.className.split(/\s+/)[e]||null}}}})}(document,ionic);var X,F,B,W,$,q,U,K,j="touchmove",Z=12,Q=50,J={click:i,mousedown:r,mouseup:a,mousemove:o,touchstart:s,touchend:l,touchcancel:d,touchmove:c,pointerdown:s,pointerup:l,pointercancel:d,pointermove:c,MSPointerDown:s,MSPointerUp:l,MSPointerCancel:d,MSPointerMove:c,focusin:m,focusout:g};ionic.tap={register:function(t){return X=t,e("click",!0,!0),e("mouseup"),e("mousedown"),window.navigator.pointerEnabled?(e("pointerdown"),e("pointerup"),e("pointercancel"),j="pointermove"):window.navigator.msPointerEnabled?(e("MSPointerDown"),e("MSPointerUp"),e("MSPointerCancel"),j="MSPointerMove"):(e("touchstart"),e("touchend"),e("touchcancel")),e("focusin"),e("focusout"),function(){for(var t in J)e(t,!1);X=null,F=null,B=!1,$=!1,q=null}},ignoreScrollStart:function(e){return e.defaultPrevented||/^(file|range)$/i.test(e.target.type)||"true"==(e.target.dataset?e.target.dataset.preventScroll:e.target.getAttribute("data-prevent-scroll"))||!!/^(object|embed)$/i.test(e.target.tagName)||ionic.tap.isElementTapDisabled(e.target)},isTextInput:function(e){return!!e&&("TEXTAREA"==e.tagName||"true"===e.contentEditable||"INPUT"==e.tagName&&!/^(radio|checkbox|range|file|submit|reset|color|image|button)$/i.test(e.type))},isDateInput:function(e){return!!e&&"INPUT"==e.tagName&&/^(date|time|datetime-local|month|week)$/i.test(e.type)},isVideo:function(e){return!!e&&"VIDEO"==e.tagName},isKeyboardElement:function(e){return!ionic.Platform.isIOS()||ionic.Platform.isIPad()?ionic.tap.isTextInput(e)&&!ionic.tap.isDateInput(e):ionic.tap.isTextInput(e)||!!e&&"SELECT"==e.tagName},isLabelWithTextInput:function(e){var t=w(e,!1);return!!t&&ionic.tap.isTextInput(T(t))},containsOrIsTextInput:function(e){return ionic.tap.isTextInput(e)||ionic.tap.isLabelWithTextInput(e)},cloneFocusedInput:function(e){ionic.tap.hasCheckedClone||(ionic.tap.hasCheckedClone=!0,ionic.requestAnimationFrame(function(){var t=e.querySelector(":focus");if(ionic.tap.isTextInput(t)&&!ionic.tap.isDateInput(t)){var n=t.cloneNode(!0);n.value=t.value,n.classList.add("cloned-text-input"),n.readOnly=!0,t.isContentEditable&&(n.contentEditable=t.contentEditable,n.innerHTML=t.innerHTML),t.parentElement.insertBefore(n,t),t.classList.add("previous-input-focus"),n.scrollTop=t.scrollTop}}))},hasCheckedClone:!1,removeClonedInputs:function(e){ionic.tap.hasCheckedClone=!1,ionic.requestAnimationFrame(function(){var t,n=e.querySelectorAll(".cloned-text-input"),i=e.querySelectorAll(".previous-input-focus");for(t=0;t<n.length;t++)n[t].parentElement.removeChild(n[t]);for(t=0;t<i.length;t++)i[t].classList.remove("previous-input-focus"),i[t].style.top="",ionic.keyboard.isOpen&&!ionic.keyboard.isClosing&&i[t].focus()})},requiresNativeClick:function(e){return ionic.Platform.isWindowsPhone()&&("A"==e.tagName||"BUTTON"==e.tagName||e.hasAttribute("ng-click")||"INPUT"==e.tagName&&("button"==e.type||"submit"==e.type))?!0:!e||e.disabled||/^(file|range)$/i.test(e.type)||/^(object|video)$/i.test(e.tagName)||ionic.tap.isLabelContainingFileInput(e)?!0:ionic.tap.isElementTapDisabled(e)},isLabelContainingFileInput:function(e){var t=w(e);if("LABEL"!==t.tagName)return!1;var n=t.querySelector("input[type=file]");return n&&n.disabled===!1?!0:!1},isElementTapDisabled:function(e){if(e&&1===e.nodeType)for(var t=e;t;){if("true"==(t.dataset?t.dataset.tapDisabled:t.getAttribute&&t.getAttribute("data-tap-disabled")))return!0;t=t.parentElement}return!1},setTolerance:function(e,t){Z=e,Q=t},cancelClick:function(){$=!0},pointerCoord:function(e){var t={x:0,y:0};if(e){var n=e.touches&&e.touches.length?e.touches:[e],i=e.changedTouches&&e.changedTouches[0]||n[0];i&&(t.x=i.clientX||i.pageX||0,t.y=i.clientY||i.pageY||0)}return t}},ionic.DomUtil.ready(function(){var e="undefined"!=typeof angular?angular:null;(!e||e&&!e.scenario)&&ionic.tap.register(document)}),function(e,t){"use strict";function n(){a={},t.requestAnimationFrame(r)}function i(){for(var e in a)a[e]&&(a[e].classList.add(l),o[e]=a[e]);a={}}function r(){if(t.transition&&t.transition.isActive)return void setTimeout(r,400);for(var e in o)o[e]&&(o[e].classList.remove(l),delete o[e])}var a={},o={},s=0,l="activated";t.activator={start:function(e){var n=t.tap.pointerCoord(e).x;n>0&&30>n||t.requestAnimationFrame(function(){if(!(t.scroll&&t.scroll.isScrolling||t.tap.requiresNativeClick(e.target))){for(var n,r=e.target,o=0;6>o&&(r&&1===r.nodeType);o++){if(n&&r.classList&&r.classList.contains("item")){n=r;break}if("A"==r.tagName||"BUTTON"==r.tagName||r.hasAttribute("ng-click")){n=r;break}if(r.classList.contains("button")){n=r;break}if("ION-CONTENT"==r.tagName||r.classList&&r.classList.contains("pane")||"BODY"==r.tagName)break;r=r.parentElement}n&&(a[s]=n,t.requestAnimationFrame(i),s=s>29?0:s+1)}})},end:function(){setTimeout(n,200)}}}(document,ionic),function(e){var t=0;e.Utils={arrayMove:function(e,t,n){if(n>=e.length)for(var i=n-e.length;i--+1;)e.push(void 0);return e.splice(n,0,e.splice(t,1)[0]),e},proxy:function(e,t){var n=Array.prototype.slice.call(arguments,2);return function(){return e.apply(t,n.concat(Array.prototype.slice.call(arguments)))}},debounce:function(e,t,n){var i,r,a,o,s;return function(){a=this,r=arguments,o=new Date;var l=function(){var c=new Date-o;t>c?i=setTimeout(l,t-c):(i=null,n||(s=e.apply(a,r)))},c=n&&!i;return i||(i=setTimeout(l,t)),c&&(s=e.apply(a,r)),s}},throttle:function(e,t,n){var i,r,a,o=null,s=0;n||(n={});var l=function(){s=n.leading===!1?0:Date.now(),o=null,a=e.apply(i,r)};return function(){var c=Date.now();s||n.leading!==!1||(s=c);var d=t-(c-s);return i=this,r=arguments,0>=d?(clearTimeout(o),o=null,s=c,a=e.apply(i,r)):o||n.trailing===!1||(o=setTimeout(l,d)),a}},inherit:function(t,n){var i,r=this;i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return r.apply(this,arguments)},e.extend(i,r,n);var a=function(){this.constructor=i};return a.prototype=r.prototype,i.prototype=new a,t&&e.extend(i.prototype,t),i.__super__=r.prototype,i},extend:function(e){for(var t=Array.prototype.slice.call(arguments,1),n=0;n<t.length;n++){var i=t[n];if(i)for(var r in i)e[r]=i[r]}return e},nextUid:function(){return"ion"+t++},disconnectScope:function(e){if(e&&e.$root!==e){var t=e.$parent;e.$$disconnected=!0,e.$broadcast("$ionic.disconnectScope",e),t.$$childHead===e&&(t.$$childHead=e.$$nextSibling),t.$$childTail===e&&(t.$$childTail=e.$$prevSibling),e.$$prevSibling&&(e.$$prevSibling.$$nextSibling=e.$$nextSibling),e.$$nextSibling&&(e.$$nextSibling.$$prevSibling=e.$$prevSibling),e.$$nextSibling=e.$$prevSibling=null}},reconnectScope:function(e){if(e&&e.$root!==e&&e.$$disconnected){var t=e.$parent;e.$$disconnected=!1,e.$broadcast("$ionic.reconnectScope",e),e.$$prevSibling=t.$$childTail,t.$$childHead?(t.$$childTail.$$nextSibling=e,t.$$childTail=e):t.$$childHead=t.$$childTail=e}},isScopeDisconnected:function(e){for(var t=e;t;){if(t.$$disconnected)return!0;t=t.$parent}return!1}},e.inherit=e.Utils.inherit,e.extend=e.Utils.extend,e.throttle=e.Utils.throttle,e.proxy=e.Utils.proxy,e.debounce=e.Utils.debounce}(window.ionic);var ee,te,ne,ie,re,ae=0,oe=0,se=0,le=!1,ce="keyboard-open",de="scroll-content",ue=ionic.debounce(E,200,!0),pe=ionic.debounce(y,100,!0);ionic.keyboard={isOpen:!1,isClosing:!1,isOpening:!1,height:0,isLandscape:!1,isInitialized:!1,hide:function(){V()&&cordova.plugins.Keyboard.close(),ee&&ee.blur()},show:function(){V()&&cordova.plugins.Keyboard.show()},disable:function(){V()?(window.removeEventListener("native.keyboardshow",pe),window.removeEventListener("native.keyboardhide",x)):document.body.removeEventListener("focusout",x),document.body.removeEventListener("ionic.focusin",ue),document.body.removeEventListener("focusin",ue),window.removeEventListener("orientationchange",D),window.navigator.msPointerEnabled?document.removeEventListener("MSPointerDown",S):document.removeEventListener("touchstart",S),ionic.keyboard.isInitialized=!1},enable:function(){S()}},ae=G(),ionic.Platform.ready(function(){A(),window.addEventListener("orientationchange",D),setTimeout(A,999),window.navigator.msPointerEnabled?document.addEventListener("MSPointerDown",S,!1):document.addEventListener("touchstart",S,!1)});var he,fe={};ionic.viewport={orientation:function(){return window.innerWidth>window.innerHeight?90:0}},ionic.Platform.ready(function(){R(),window.addEventListener("orientationchange",function(){setTimeout(H,1e3)},!1)}),function(e){"use strict";e.views.View=function(){this.initialize.apply(this,arguments)},e.views.View.inherit=e.inherit,e.extend(e.views.View.prototype,{initialize:function(){}})}(window.ionic);var me={effect:{}};!function(e){var t=Date.now||function(){return+new Date},n=60,i=1e3,r={},a=1;me.effect.Animate={requestAnimationFrame:function(){var t=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame,n=!!t;if(t&&!/requestAnimationFrame\(\)\s*\{\s*\[native code\]\s*\}/i.test(t.toString())&&(n=!1),n)return function(e,n){t(e,n)};var i=60,r={},a=0,o=1,s=null,l=+new Date;return function(e){var t=o++;return r[t]=e,a++,null===s&&(s=setInterval(function(){var e=+new Date,t=r;r={},a=0;for(var n in t)t.hasOwnProperty(n)&&(t[n](e),l=e);e-l>2500&&(clearInterval(s),s=null)},1e3/i)),t}}(),stop:function(e){var t=null!=r[e];return t&&(r[e]=null),t},isRunning:function(e){return null!=r[e]},start:function(e,o,s,l,c,d){var u=t(),p=u,h=0,f=0,m=a++;if(d||(d=document.body),m%20===0){var g={};for(var v in r)g[v]=!0;r=g}var _=function(a){var g=a!==!0,v=t();if(!r[m]||o&&!o(m))return r[m]=null,void(s&&s(n-f/((v-u)/i),m,!1));if(g)for(var w=Math.round((v-p)/(i/n))-1,T=0;T<Math.min(w,4);T++)_(!0),f++;l&&(h=(v-u)/l,h>1&&(h=1));var b=c?c(h):h;e(b,v,g)!==!1&&1!==h||!g?g&&(p=v,me.effect.Animate.requestAnimationFrame(_,d)):(r[m]=null,s&&s(n-f/((v-u)/i),m,1===h||null==l))};return r[m]=!0,me.effect.Animate.requestAnimationFrame(_,d),m}}}(window),function(e){var t=function(){},n=function(e){return Math.pow(e-1,3)+1},i=function(e){return(e/=.5)<1?.5*Math.pow(e,3):.5*(Math.pow(e-2,3)+2)};e.views.Scroll=e.views.View.inherit({initialize:function(n){var i=this;i.__container=n.el,i.__content=n.el.firstElementChild,setTimeout(function(){i.__container&&i.__content&&(i.__container.scrollTop=0,i.__content.scrollTop=0)}),i.options={scrollingX:!1,scrollbarX:!0,scrollingY:!0,scrollbarY:!0,startX:0,startY:0,wheelDampen:6,minScrollbarSizeX:5,minScrollbarSizeY:5,scrollbarsFade:!0,scrollbarFadeDelay:300,scrollbarResizeFadeDelay:1e3,animating:!0,animationDuration:250,decelVelocityThreshold:4,decelVelocityThresholdPaging:4,bouncing:!0,locking:!0,paging:!1,snapping:!1,zooming:!1,minZoom:.5,maxZoom:3,speedMultiplier:1,deceleration:.97,preventDefault:!1,scrollingComplete:t,penetrationDeceleration:.03,penetrationAcceleration:.08,scrollEventInterval:10,freeze:!1,getContentWidth:function(){return Math.max(i.__content.scrollWidth,i.__content.offsetWidth)},getContentHeight:function(){return Math.max(i.__content.scrollHeight,i.__content.offsetHeight+2*i.__content.offsetTop)}};for(var r in n)i.options[r]=n[r];i.hintResize=e.debounce(function(){i.resize()},1e3,!0),i.onScroll=function(){e.scroll.isScrolling?(clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)):setTimeout(i.setScrollStart,50)},i.freeze=function(e){return arguments.length&&(i.options.freeze=e),i.options.freeze},i.freezeShut=i.freeze,i.setScrollStart=function(){e.scroll.isScrolling=Math.abs(e.scroll.lastTop-i.__scrollTop)>1,clearTimeout(i.scrollTimer),i.scrollTimer=setTimeout(i.setScrollStop,80)},i.setScrollStop=function(){e.scroll.isScrolling=!1,e.scroll.lastTop=i.__scrollTop},i.triggerScrollEvent=e.throttle(function(){i.onScroll(),e.trigger("scroll",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.options.scrollEventInterval),i.triggerScrollEndEvent=function(){e.trigger("scrollend",{scrollTop:i.__scrollTop,scrollLeft:i.__scrollLeft,target:i.__container})},i.__scrollLeft=i.options.startX,i.__scrollTop=i.options.startY,i.__callback=i.getRenderFn(),i.__initEventHandlers(),i.__createScrollbars()},run:function(){this.resize(),this.__fadeScrollbars("out",this.options.scrollbarResizeFadeDelay)},__isSingleTouch:!1,__isTracking:!1,__didDecelerationComplete:!1,__isGesturing:!1,__isDragging:!1,__isDecelerating:!1,__isAnimating:!1,__clientLeft:0,__clientTop:0,__clientWidth:0,__clientHeight:0,__contentWidth:0,__contentHeight:0,__snapWidth:100,__snapHeight:100,__refreshHeight:null,__refreshActive:!1,__refreshActivate:null,__refreshDeactivate:null,__refreshStart:null,__zoomLevel:1,__scrollLeft:0,__scrollTop:0,__maxScrollLeft:0,__maxScrollTop:0,__scheduledLeft:0,__scheduledTop:0,__scheduledZoom:0,__lastTouchLeft:null,__lastTouchTop:null,__lastTouchMove:null,__positions:null,__minDecelerationScrollLeft:null,__minDecelerationScrollTop:null,__maxDecelerationScrollLeft:null,__maxDecelerationScrollTop:null,__decelerationVelocityX:null,__decelerationVelocityY:null,__transformProperty:null,__perspectiveProperty:null,__indicatorX:null,__indicatorY:null,__scrollbarFadeTimeout:null,__didWaitForSize:null,__sizerTimeout:null,__initEventHandlers:function(){function t(e){return e.touches&&e.touches.length?e.touches:[{pageX:e.pageX,pageY:e.pageY}]}var n,i=this,r=i.__container;if(i.scrollChildIntoView=function(t){var a=r.getBoundingClientRect().bottom;n=r.offsetHeight;var o=i.isShrunkForKeyboard,s=r.parentNode.classList.contains("modal"),l=s&&window.innerWidth>=680;if(!o){if(e.Platform.isIOS()||e.Platform.isFullScreen||l){var c=t.detail.viewportHeight-a,d=Math.max(0,t.detail.keyboardHeight-c);e.requestAnimationFrame(function(){n-=d,r.style.height=n+"px",r.style.overflow="visible",i.resize()})}i.isShrunkForKeyboard=!0}t.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){r.scrollTop=0,i.isShrunkForKeyboard&&!o&&(a=r.getBoundingClientRect().bottom);var s=.5*n,l=(t.detail.elementBottom+t.detail.elementTop)/2,c=l-a,d=c+s;d>0&&(e.Platform.isIOS()&&e.tap.cloneFocusedInput(r,i),i.scrollBy(0,d,!0),i.onScroll())}),t.stopPropagation()},i.resetScrollView=function(){i.isShrunkForKeyboard&&(i.isShrunkForKeyboard=!1,r.style.height="",r.style.overflow=""),i.resize()},r.addEventListener("scrollChildIntoView",i.scrollChildIntoView),document.addEventListener("resetScrollView",i.resetScrollView),i.touchStart=function(n){if(i.startCoordinates=e.tap.pointerCoord(n),!e.tap.ignoreScrollStart(n)){if(i.__isDown=!0,e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName)return void(i.__hasStarted=!1);i.__isSelectable=!0,i.__enableScrollY=!0,i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),n.preventDefault()}},i.touchMove=function(n){if(!(i.options.freeze||!i.__isDown||!i.__isDown&&n.defaultPrevented||"TEXTAREA"===n.target.tagName&&n.target.parentElement.querySelector(":focus"))){if(!i.__hasStarted&&(e.tap.containsOrIsTextInput(n.target)||"SELECT"===n.target.tagName))return i.__hasStarted=!0,i.doTouchStart(t(n),n.timeStamp),void n.preventDefault();if(i.startCoordinates){var a=e.tap.pointerCoord(n);i.__isSelectable&&e.tap.isTextInput(n.target)&&Math.abs(i.startCoordinates.x-a.x)>20&&(i.__enableScrollY=!1,i.__isSelectable=!0),i.__enableScrollY&&Math.abs(i.startCoordinates.y-a.y)>10&&(i.__isSelectable=!1,e.tap.cloneFocusedInput(r,i))}i.doTouchMove(t(n),n.timeStamp,n.scale),i.__isDown=!0}},i.touchMoveBubble=function(e){i.__isDown&&i.options.preventDefault&&e.preventDefault()},i.touchEnd=function(t){i.__isDown&&(i.doTouchEnd(t,t.timeStamp),i.__isDown=!1,i.__hasStarted=!1,i.__isSelectable=!0,i.__enableScrollY=!0,i.__isDragging||i.__isDecelerating||i.__isAnimating||e.tap.removeClonedInputs(r,i))},i.mouseWheel=e.animationFrameThrottle(function(t){var n=e.DomUtil.getParentOrSelfWithClass(t.target,"ionic-scroll");i.options.freeze||n!==i.__container||(i.hintResize(),i.scrollBy((t.wheelDeltaX||t.deltaX||0)/i.options.wheelDampen,(-t.wheelDeltaY||t.deltaY||0)/i.options.wheelDampen),i.__fadeScrollbars("in"),clearTimeout(i.__wheelHideBarTimeout),i.__wheelHideBarTimeout=setTimeout(function(){i.__fadeScrollbars("out")},100))}),"ontouchstart"in window)r.addEventListener("touchstart",i.touchStart,!1),i.options.preventDefault&&r.addEventListener("touchmove",i.touchMoveBubble,!1),document.addEventListener("touchmove",i.touchMove,!1),document.addEventListener("touchend",i.touchEnd,!1),document.addEventListener("touchcancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else if(window.navigator.pointerEnabled)r.addEventListener("pointerdown",i.touchStart,!1),i.options.preventDefault&&r.addEventListener("pointermove",i.touchMoveBubble,!1),document.addEventListener("pointermove",i.touchMove,!1),document.addEventListener("pointerup",i.touchEnd,!1),document.addEventListener("pointercancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else if(window.navigator.msPointerEnabled)r.addEventListener("MSPointerDown",i.touchStart,!1),i.options.preventDefault&&r.addEventListener("MSPointerMove",i.touchMoveBubble,!1),document.addEventListener("MSPointerMove",i.touchMove,!1),document.addEventListener("MSPointerUp",i.touchEnd,!1),document.addEventListener("MSPointerCancel",i.touchEnd,!1),document.addEventListener("wheel",i.mouseWheel,!1);else{var a=!1;i.mouseDown=function(n){e.tap.ignoreScrollStart(n)||"SELECT"===n.target.tagName||(i.doTouchStart(t(n),n.timeStamp),e.tap.isTextInput(n.target)||n.preventDefault(),a=!0)},i.mouseMove=function(e){i.options.freeze||!a||!a&&e.defaultPrevented||(i.doTouchMove(t(e),e.timeStamp),a=!0)},i.mouseMoveBubble=function(e){a&&i.options.preventDefault&&e.preventDefault()},i.mouseUp=function(e){a&&(i.doTouchEnd(e,e.timeStamp),a=!1)},r.addEventListener("mousedown",i.mouseDown,!1),i.options.preventDefault&&r.addEventListener("mousemove",i.mouseMoveBubble,!1),document.addEventListener("mousemove",i.mouseMove,!1),document.addEventListener("mouseup",i.mouseUp,!1),document.addEventListener("mousewheel",i.mouseWheel,!1),document.addEventListener("wheel",i.mouseWheel,!1)}},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("touchstart",n.touchStart),i.removeEventListener("touchmove",n.touchMoveBubble),document.removeEventListener("touchmove",n.touchMove),document.removeEventListener("touchend",n.touchEnd),document.removeEventListener("touchcancel",n.touchEnd),i.removeEventListener("pointerdown",n.touchStart),i.removeEventListener("pointermove",n.touchMoveBubble),document.removeEventListener("pointermove",n.touchMove),document.removeEventListener("pointerup",n.touchEnd),document.removeEventListener("pointercancel",n.touchEnd),i.removeEventListener("MSPointerDown",n.touchStart),i.removeEventListener("MSPointerMove",n.touchMoveBubble),document.removeEventListener("MSPointerMove",n.touchMove),document.removeEventListener("MSPointerUp",n.touchEnd),document.removeEventListener("MSPointerCancel",n.touchEnd),i.removeEventListener("mousedown",n.mouseDown),i.removeEventListener("mousemove",n.mouseMoveBubble),document.removeEventListener("mousemove",n.mouseMove),document.removeEventListener("mouseup",n.mouseUp),document.removeEventListener("mousewheel",n.mouseWheel),document.removeEventListener("wheel",n.mouseWheel),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),document.removeEventListener("resetScrollView",n.resetScrollView),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.__callback=n.scrollChildIntoView=n.resetScrollView=t,n.mouseMove=n.mouseDown=n.mouseUp=n.mouseWheel=n.touchStart=n.touchMove=n.touchEnd=n.touchCancel=t,n.resize=n.scrollTo=n.zoomTo=n.__scrollingComplete=t,i=null},__createScrollbar:function(e){var t=document.createElement("div"),n=document.createElement("div");return n.className="scroll-bar-indicator scroll-bar-fade-out","h"==e?t.className="scroll-bar scroll-bar-h":t.className="scroll-bar scroll-bar-v",t.appendChild(n),t},__createScrollbars:function(){var e,t,n=this;n.options.scrollingX&&(e={el:n.__createScrollbar("h"),sizeRatio:1},e.indicator=e.el.children[0],n.options.scrollbarX&&n.__container.appendChild(e.el),n.__indicatorX=e),n.options.scrollingY&&(t={el:n.__createScrollbar("v"),sizeRatio:1},t.indicator=t.el.children[0],n.options.scrollbarY&&n.__container.appendChild(t.el),n.__indicatorY=t)},__resizeScrollbars:function(){var t=this;if(t.__indicatorX){var n=Math.max(Math.round(t.__clientWidth*t.__clientWidth/t.__contentWidth),20);n>t.__contentWidth&&(n=0),n!==t.__indicatorX.size&&e.requestAnimationFrame(function(){t.__indicatorX.indicator.style.width=n+"px"}),t.__indicatorX.size=n,t.__indicatorX.minScale=t.options.minScrollbarSizeX/n,t.__indicatorX.maxPos=t.__clientWidth-n,t.__indicatorX.sizeRatio=t.__maxScrollLeft?t.__indicatorX.maxPos/t.__maxScrollLeft:1}if(t.__indicatorY){var i=Math.max(Math.round(t.__clientHeight*t.__clientHeight/t.__contentHeight),20);i>t.__contentHeight&&(i=0),i!==t.__indicatorY.size&&e.requestAnimationFrame(function(){t.__indicatorY&&(t.__indicatorY.indicator.style.height=i+"px")}),t.__indicatorY.size=i,t.__indicatorY.minScale=t.options.minScrollbarSizeY/i,t.__indicatorY.maxPos=t.__clientHeight-i,t.__indicatorY.sizeRatio=t.__maxScrollTop?t.__indicatorY.maxPos/t.__maxScrollTop:1}},__repositionScrollbars:function(){var e,t,n,i,r,a,o=this,s=0,l=0;if(o.__indicatorX){o.__indicatorY&&(s=10),r=Math.round(o.__indicatorX.sizeRatio*o.__scrollLeft)||0,n=o.__scrollLeft-(o.__maxScrollLeft-s),o.__scrollLeft<0?(t=Math.max(o.__indicatorX.minScale,(o.__indicatorX.size-Math.abs(o.__scrollLeft))/o.__indicatorX.size),r=0,o.__indicatorX.indicator.style[o.__transformOriginProperty]="left center"):n>0?(t=Math.max(o.__indicatorX.minScale,(o.__indicatorX.size-n)/o.__indicatorX.size),r=o.__indicatorX.maxPos-s,o.__indicatorX.indicator.style[o.__transformOriginProperty]="right center"):(r=Math.min(o.__maxScrollLeft,Math.max(0,r)),t=1);var c="translate3d("+r+"px, 0, 0) scaleX("+t+")";o.__indicatorX.transformProp!==c&&(o.__indicatorX.indicator.style[o.__transformProperty]=c,o.__indicatorX.transformProp=c)}if(o.__indicatorY){a=Math.round(o.__indicatorY.sizeRatio*o.__scrollTop)||0,o.__indicatorX&&(l=10),i=o.__scrollTop-(o.__maxScrollTop-l),o.__scrollTop<0?(e=Math.max(o.__indicatorY.minScale,(o.__indicatorY.size-Math.abs(o.__scrollTop))/o.__indicatorY.size),a=0,"center top"!==o.__indicatorY.originProp&&(o.__indicatorY.indicator.style[o.__transformOriginProperty]="center top",o.__indicatorY.originProp="center top")):i>0?(e=Math.max(o.__indicatorY.minScale,(o.__indicatorY.size-i)/o.__indicatorY.size),a=o.__indicatorY.maxPos-l,"center bottom"!==o.__indicatorY.originProp&&(o.__indicatorY.indicator.style[o.__transformOriginProperty]="center bottom",o.__indicatorY.originProp="center bottom")):(a=Math.min(o.__maxScrollTop,Math.max(0,a)),e=1);var d="translate3d(0,"+a+"px, 0) scaleY("+e+")";o.__indicatorY.transformProp!==d&&(o.__indicatorY.indicator.style[o.__transformProperty]=d,o.__indicatorY.transformProp=d)}},__fadeScrollbars:function(e,t){var n=this;if(n.options.scrollbarsFade){var i="scroll-bar-fade-out";n.options.scrollbarsFade===!0&&(clearTimeout(n.__scrollbarFadeTimeout),"in"==e?(n.__indicatorX&&n.__indicatorX.indicator.classList.remove(i),n.__indicatorY&&n.__indicatorY.indicator.classList.remove(i)):n.__scrollbarFadeTimeout=setTimeout(function(){n.__indicatorX&&n.__indicatorX.indicator.classList.add(i),n.__indicatorY&&n.__indicatorY.indicator.classList.add(i)},t||n.options.scrollbarFadeDelay))}},__scrollingComplete:function(){this.options.scrollingComplete(),e.tap.removeClonedInputs(this.__container,this),this.__fadeScrollbars("out")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},getRenderFn:function(){var e,t=this,n=t.__content,i=document.documentElement.style;"MozAppearance"in i?e="gecko":"WebkitAppearance"in i?e="webkit":"string"==typeof navigator.cpuClass&&(e="trident");var r,a={trident:"ms",gecko:"Moz",webkit:"Webkit",presto:"O"}[e],o=document.createElement("div"),s=a+"Perspective",l=a+"Transform",c=a+"TransformOrigin";return t.__perspectiveProperty=l,t.__transformProperty=l,t.__transformOriginProperty=c,o.style[s]!==r?function(e,i,r,a){var o="translate3d("+-e+"px,"+-i+"px,0) scale("+r+")";o!==t.contentTransform&&(n.style[l]=o,t.contentTransform=o),t.__repositionScrollbars(),a||t.triggerScrollEvent()}:o.style[l]!==r?function(e,i,r,a){n.style[l]="translate("+-e+"px,"+-i+"px) scale("+r+")",t.__repositionScrollbars(),a||t.triggerScrollEvent()}:function(e,i,r,a){n.style.marginLeft=e?-e/r+"px":"",n.style.marginTop=i?-i/r+"px":"",n.style.zoom=r||"",t.__repositionScrollbars(),a||t.triggerScrollEvent()}},setDimensions:function(e,t,n,i,r){var a=this;(e||t||n||i)&&(e===+e&&(a.__clientWidth=e),t===+t&&(a.__clientHeight=t),n===+n&&(a.__contentWidth=n),i===+i&&(a.__contentHeight=i),a.__computeScrollMax(),a.__resizeScrollbars(),r||a.scrollTo(a.__scrollLeft,a.__scrollTop,!0,null,!0))},setPosition:function(e,t){this.__clientLeft=e||0,this.__clientTop=t||0},setSnapSize:function(e,t){this.__snapWidth=e,this.__snapHeight=t},activatePullToRefresh:function(t,n){var i=this;i.__refreshHeight=t,i.__refreshActivate=function(){e.requestAnimationFrame(n.activate)},i.__refreshDeactivate=function(){e.requestAnimationFrame(n.deactivate)},i.__refreshStart=function(){e.requestAnimationFrame(n.start)},i.__refreshShow=function(){e.requestAnimationFrame(n.show)},i.__refreshHide=function(){e.requestAnimationFrame(n.hide)},i.__refreshTail=function(){e.requestAnimationFrame(n.tail)},i.__refreshTailTime=100,i.__minSpinTime=600},triggerPullToRefresh:function(){this.__publish(this.__scrollLeft,-this.__refreshHeight,this.__zoomLevel,!0);var e=new Date;this.refreshStartTime=e.getTime(),this.__refreshStart&&this.__refreshStart()},finishPullToRefresh:function(){var e=this,t=new Date,n=0;e.refreshStartTime+e.__minSpinTime>t.getTime()&&(n=e.refreshStartTime+e.__minSpinTime-t.getTime()),setTimeout(function(){e.__refreshTail&&e.__refreshTail(),setTimeout(function(){e.__refreshActive=!1,e.__refreshDeactivate&&e.__refreshDeactivate(),e.__refreshHide&&e.__refreshHide(),e.scrollTo(e.__scrollLeft,e.__scrollTop,!0)},e.__refreshTailTime)},n)},getValues:function(){return{left:this.__scrollLeft,top:this.__scrollTop,zoom:this.__zoomLevel}},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},zoomTo:function(e,t,n,i){var r=this;if(!r.options.zooming)throw new Error("Zooming is not enabled!");r.__isDecelerating&&(me.effect.Animate.stop(r.__isDecelerating),r.__isDecelerating=!1);var a=r.__zoomLevel;null==n&&(n=r.__clientWidth/2),null==i&&(i=r.__clientHeight/2),e=Math.max(Math.min(e,r.options.maxZoom),r.options.minZoom),r.__computeScrollMax(e);var o=(n+r.__scrollLeft)*e/a-n,s=(i+r.__scrollTop)*e/a-i;o>r.__maxScrollLeft?o=r.__maxScrollLeft:0>o&&(o=0),s>r.__maxScrollTop?s=r.__maxScrollTop:0>s&&(s=0),r.__publish(o,s,e,t)},zoomBy:function(e,t,n,i){this.zoomTo(this.__zoomLevel*e,t,n,i)},scrollTo:function(e,t,n,i,r){var a=this;if(a.__isDecelerating&&(me.effect.Animate.stop(a.__isDecelerating),a.__isDecelerating=!1),null!=i&&i!==a.__zoomLevel){if(!a.options.zooming)throw new Error("Zooming is not enabled!");e*=i,t*=i,a.__computeScrollMax(i)}else i=a.__zoomLevel;a.options.scrollingX?a.options.paging?e=Math.round(e/a.__clientWidth)*a.__clientWidth:a.options.snapping&&(e=Math.round(e/a.__snapWidth)*a.__snapWidth):e=a.__scrollLeft,a.options.scrollingY?a.options.paging?t=Math.round(t/a.__clientHeight)*a.__clientHeight:a.options.snapping&&(t=Math.round(t/a.__snapHeight)*a.__snapHeight):t=a.__scrollTop,e=Math.max(Math.min(a.__maxScrollLeft,e),0),t=Math.max(Math.min(a.__maxScrollTop,t),0),e===a.__scrollLeft&&t===a.__scrollTop&&(n=!1),a.__publish(e,t,i,n,r)},scrollBy:function(e,t,n){var i=this,r=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,a=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(r+(e||0),a+(t||0),n)},doMouseZoom:function(e,t,n,i){var r=e>0?.97:1.03;return this.zoomTo(this.__zoomLevel*r,!1,n-this.__clientLeft,i-this.__clientTop)},doTouchStart:function(e,t){var n=this;n.__decStopped=!(!n.__isDecelerating&&!n.__isAnimating),n.hintResize(),t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now()),n.__interruptedAnimation=!0,n.__isDecelerating&&(me.effect.Animate.stop(n.__isDecelerating),n.__isDecelerating=!1,n.__interruptedAnimation=!0),n.__isAnimating&&(me.effect.Animate.stop(n.__isAnimating),n.__isAnimating=!1,n.__interruptedAnimation=!0);var i,r,a=1===e.length;a?(i=e[0].pageX,r=e[0].pageY):(i=Math.abs(e[0].pageX+e[1].pageX)/2,r=Math.abs(e[0].pageY+e[1].pageY)/2),n.__initialTouchLeft=i,n.__initialTouchTop=r,n.__initialTouches=e,n.__zoomLevelStart=n.__zoomLevel,n.__lastTouchLeft=i,n.__lastTouchTop=r,n.__lastTouchMove=t,n.__lastScale=1,n.__enableScrollX=!a&&n.options.scrollingX,n.__enableScrollY=!a&&n.options.scrollingY,n.__isTracking=!0,n.__didDecelerationComplete=!1,n.__isDragging=!a,n.__isSingleTouch=a,n.__positions=[]},doTouchMove:function(e,t,n){t instanceof Date&&(t=t.valueOf()),"number"!=typeof t&&(t=Date.now());var i=this;if(i.__isTracking){var r,a;2===e.length?(r=Math.abs(e[0].pageX+e[1].pageX)/2,a=Math.abs(e[0].pageY+e[1].pageY)/2,!n&&i.options.zooming&&(n=i.__getScale(i.__initialTouches,e))):(r=e[0].pageX,a=e[0].pageY);var o=i.__positions;if(i.__isDragging){i.__decStopped=!1;var s=r-i.__lastTouchLeft,l=a-i.__lastTouchTop,c=i.__scrollLeft,d=i.__scrollTop,u=i.__zoomLevel;if(null!=n&&i.options.zooming){var p=u;if(u=u/i.__lastScale*n,u=Math.max(Math.min(u,i.options.maxZoom),i.options.minZoom),p!==u){var h=r-i.__clientLeft,f=a-i.__clientTop;c=(h+c)*u/p-h,d=(f+d)*u/p-f,i.__computeScrollMax(u)}}if(i.__enableScrollX){c-=s*i.options.speedMultiplier;var m=i.__maxScrollLeft;(c>m||0>c)&&(i.options.bouncing?c+=s/2*i.options.speedMultiplier:c=c>m?m:0)}if(i.__enableScrollY){d-=l*i.options.speedMultiplier;var g=i.__maxScrollTop;d>g||0>d?i.options.bouncing||i.__refreshHeight&&0>d?(d+=l/2*i.options.speedMultiplier,i.__enableScrollX||null==i.__refreshHeight||(0>d?(i.__refreshHidden=!1,i.__refreshShow()):(i.__refreshHide(),i.__refreshHidden=!0),!i.__refreshActive&&d<=-i.__refreshHeight?(i.__refreshActive=!0,i.__refreshActivate&&i.__refreshActivate()):i.__refreshActive&&d>-i.__refreshHeight&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate()))):d=d>g?g:0:i.__refreshHeight&&!i.__refreshHidden&&(i.__refreshHide(),i.__refreshHidden=!0)}o.length>60&&o.splice(0,30),o.push(c,d,t),i.__publish(c,d,u)}else{var v=i.options.locking?3:0,_=5,w=Math.abs(r-i.__initialTouchLeft),T=Math.abs(a-i.__initialTouchTop);i.__enableScrollX=i.options.scrollingX&&w>=v,i.__enableScrollY=i.options.scrollingY&&T>=v,o.push(i.__scrollLeft,i.__scrollTop,t),i.__isDragging=(i.__enableScrollX||i.__enableScrollY)&&(w>=_||T>=_),i.__isDragging&&(i.__interruptedAnimation=!1,i.__fadeScrollbars("in"))}i.__lastTouchLeft=r,i.__lastTouchTop=a,i.__lastTouchMove=t,i.__lastScale=n}},doTouchEnd:function(t,n){n instanceof Date&&(n=n.valueOf()),"number"!=typeof n&&(n=Date.now());var i=this;if(i.__isTracking){if(i.__isTracking=!1,i.__isDragging)if(i.__isDragging=!1,i.__isSingleTouch&&i.options.animating&&n-i.__lastTouchMove<=100){for(var r=i.__positions,a=r.length-1,o=a,s=a;s>0&&r[s]>i.__lastTouchMove-100;s-=3)o=s; +if(o!==a){var l=r[a]-r[o],c=i.__scrollLeft-r[o-2],d=i.__scrollTop-r[o-1];i.__decelerationVelocityX=c/l*(1e3/60),i.__decelerationVelocityY=d/l*(1e3/60);var u=i.options.paging||i.options.snapping?i.options.decelVelocityThresholdPaging:i.options.decelVelocityThreshold;(Math.abs(i.__decelerationVelocityX)>u||Math.abs(i.__decelerationVelocityY)>u)&&(i.__refreshActive||i.__startDeceleration(n))}else i.__scrollingComplete()}else n-i.__lastTouchMove>100&&i.__scrollingComplete();else i.__decStopped&&(t.isTapHandled=!0,i.__decStopped=!1);if(!i.__isDecelerating)if(i.__refreshActive&&i.__refreshStart){i.__publish(i.__scrollLeft,-i.__refreshHeight,i.__zoomLevel,!0);var p=new Date;i.refreshStartTime=p.getTime(),i.__refreshStart&&i.__refreshStart(),e.Platform.isAndroid()||i.__startDeceleration()}else(i.__interruptedAnimation||i.__isDragging)&&i.__scrollingComplete(),i.scrollTo(i.__scrollLeft,i.__scrollTop,!0,i.__zoomLevel),i.__refreshActive&&(i.__refreshActive=!1,i.__refreshDeactivate&&i.__refreshDeactivate());i.__positions.length=0}},__publish:function(e,t,r,a,o){var s=this,l=s.__isAnimating;if(l&&(me.effect.Animate.stop(l),s.__isAnimating=!1),a&&s.options.animating){s.__scheduledLeft=e,s.__scheduledTop=t,s.__scheduledZoom=r;var c=s.__scrollLeft,d=s.__scrollTop,u=s.__zoomLevel,p=e-c,h=t-d,f=r-u,m=function(e,t,n){n&&(s.__scrollLeft=c+p*e,s.__scrollTop=d+h*e,s.__zoomLevel=u+f*e,s.__callback&&s.__callback(s.__scrollLeft,s.__scrollTop,s.__zoomLevel,o))},g=function(e){return s.__isAnimating===e},v=function(e,t,n){t===s.__isAnimating&&(s.__isAnimating=!1),(s.__didDecelerationComplete||n)&&s.__scrollingComplete(),s.options.zooming&&s.__computeScrollMax()};s.__isAnimating=me.effect.Animate.start(m,g,v,s.options.animationDuration,l?n:i)}else s.__scheduledLeft=s.__scrollLeft=e,s.__scheduledTop=s.__scrollTop=t,s.__scheduledZoom=s.__zoomLevel=r,s.__callback&&s.__callback(e,t,r,o),s.options.zooming&&s.__computeScrollMax()},__computeScrollMax:function(e){var t=this;null==e&&(e=t.__zoomLevel),t.__maxScrollLeft=Math.max(t.__contentWidth*e-t.__clientWidth,0),t.__maxScrollTop=Math.max(t.__contentHeight*e-t.__clientHeight,0),t.__didWaitForSize||t.__maxScrollLeft||t.__maxScrollTop||(t.__didWaitForSize=!0,t.__waitForSize())},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__startDeceleration:function(){var e=this;if(e.options.paging){var t=Math.max(Math.min(e.__scrollLeft,e.__maxScrollLeft),0),n=Math.max(Math.min(e.__scrollTop,e.__maxScrollTop),0),i=e.__clientWidth,r=e.__clientHeight;e.__minDecelerationScrollLeft=Math.floor(t/i)*i,e.__minDecelerationScrollTop=Math.floor(n/r)*r,e.__maxDecelerationScrollLeft=Math.ceil(t/i)*i,e.__maxDecelerationScrollTop=Math.ceil(n/r)*r}else e.__minDecelerationScrollLeft=0,e.__minDecelerationScrollTop=0,e.__maxDecelerationScrollLeft=e.__maxScrollLeft,e.__maxDecelerationScrollTop=e.__maxScrollTop,e.__refreshActive&&(e.__minDecelerationScrollTop=-1*e.__refreshHeight);var a=function(t,n,i){e.__stepThroughDeceleration(i)};e.__minVelocityToKeepDecelerating=e.options.snapping?4:.1;var o=function(){var t=Math.abs(e.__decelerationVelocityX)>=e.__minVelocityToKeepDecelerating||Math.abs(e.__decelerationVelocityY)>=e.__minVelocityToKeepDecelerating;return t||(e.__didDecelerationComplete=!0,e.options.bouncing&&!e.__refreshActive&&e.scrollTo(Math.min(Math.max(e.__scrollLeft,0),e.__maxScrollLeft),Math.min(Math.max(e.__scrollTop,0),e.__maxScrollTop),e.__refreshActive)),t},s=function(){e.__isDecelerating=!1,e.__didDecelerationComplete&&e.__scrollingComplete(),e.options.paging&&e.scrollTo(e.__scrollLeft,e.__scrollTop,e.options.snapping)};e.__isDecelerating=me.effect.Animate.start(a,o,s)},__stepThroughDeceleration:function(e){var t=this,n=t.__scrollLeft+t.__decelerationVelocityX,i=t.__scrollTop+t.__decelerationVelocityY;if(!t.options.bouncing){var r=Math.max(Math.min(t.__maxDecelerationScrollLeft,n),t.__minDecelerationScrollLeft);r!==n&&(n=r,t.__decelerationVelocityX=0);var a=Math.max(Math.min(t.__maxDecelerationScrollTop,i),t.__minDecelerationScrollTop);a!==i&&(i=a,t.__decelerationVelocityY=0)}if(e?t.__publish(n,i,t.__zoomLevel):(t.__scrollLeft=n,t.__scrollTop=i),!t.options.paging){var o=t.options.deceleration;t.__decelerationVelocityX*=o,t.__decelerationVelocityY*=o}if(t.options.bouncing){var s=0,l=0,c=t.options.penetrationDeceleration,d=t.options.penetrationAcceleration;if(n<t.__minDecelerationScrollLeft?s=t.__minDecelerationScrollLeft-n:n>t.__maxDecelerationScrollLeft&&(s=t.__maxDecelerationScrollLeft-n),i<t.__minDecelerationScrollTop?l=t.__minDecelerationScrollTop-i:i>t.__maxDecelerationScrollTop&&(l=t.__maxDecelerationScrollTop-i),0!==s){var u=s*t.__decelerationVelocityX<=t.__minDecelerationScrollLeft;u&&(t.__decelerationVelocityX+=s*c);var p=Math.abs(t.__decelerationVelocityX)<=t.__minVelocityToKeepDecelerating;(!u||p)&&(t.__decelerationVelocityX=s*d)}if(0!==l){var h=l*t.__decelerationVelocityY<=t.__minDecelerationScrollTop;h&&(t.__decelerationVelocityY+=l*c);var f=Math.abs(t.__decelerationVelocityY)<=t.__minVelocityToKeepDecelerating;(!h||f)&&(t.__decelerationVelocityY=l*d)}}},__getDistance:function(e,t){var n=t.pageX-e.pageX,i=t.pageY-e.pageY;return Math.sqrt(n*n+i*i)},__getScale:function(e,t){return e.length>=2&&t.length>=2?this.__getDistance(t[0],t[1])/this.__getDistance(e[0],e[1]):1}}),e.scroll={isScrolling:!1,lastTop:0}}(ionic),function(e){var t=function(){},n=function(e){};e.views.ScrollNative=e.views.View.inherit({initialize:function(t){var n=this;n.__container=n.el=t.el,n.__content=t.el.firstElementChild,n.__frozen=!1,n.isNative=!0,n.__scrollTop=n.el.scrollTop,n.__scrollLeft=n.el.scrollLeft,n.__clientHeight=n.__content.clientHeight,n.__clientWidth=n.__content.clientWidth,n.__maxScrollTop=Math.max(n.__contentHeight-n.__clientHeight,0),n.__maxScrollLeft=Math.max(n.__contentWidth-n.__clientWidth,0),(t.startY>=0||t.startX>=0)&&e.requestAnimationFrame(function(){n.el.scrollTop=t.startY||0,n.el.scrollLeft=t.startX||0,n.__scrollTop=n.el.scrollTop,n.__scrollLeft=n.el.scrollLeft}),n.options={freeze:!1,getContentWidth:function(){return Math.max(n.__content.scrollWidth,n.__content.offsetWidth)},getContentHeight:function(){return Math.max(n.__content.scrollHeight,n.__content.offsetHeight+2*n.__content.offsetTop)}};for(var i in t)n.options[i]=t[i];n.onScroll=function(){e.scroll.isScrolling||(e.scroll.isScrolling=!0),clearTimeout(n.scrollTimer),n.scrollTimer=setTimeout(function(){e.scroll.isScrolling=!1},80)},n.freeze=function(e){n.__frozen=e},n.freezeShut=function(e){n.__frozenShut=e},n.__initEventHandlers()},__callback:function(){n("__callback")},zoomTo:function(){n("zoomTo")},zoomBy:function(){n("zoomBy")},activatePullToRefresh:function(){n("activatePullToRefresh")},resize:function(e){var t=this;t.__container&&t.options&&t.setDimensions(t.__container.clientWidth,t.__container.clientHeight,t.options.getContentWidth(),t.options.getContentHeight(),e)},run:function(){this.resize()},getValues:function(){var e=this;return e.update(),{left:e.__scrollLeft,top:e.__scrollTop,zoom:1}},update:function(){var e=this;e.__scrollLeft=e.el.scrollLeft,e.__scrollTop=e.el.scrollTop},setDimensions:function(e,t,n,i){var r=this;(e||t||n||i)&&(e===+e&&(r.__clientWidth=e),t===+t&&(r.__clientHeight=t),n===+n&&(r.__contentWidth=n),i===+i&&(r.__contentHeight=i),r.__computeScrollMax())},getScrollMax:function(){return{left:this.__maxScrollLeft,top:this.__maxScrollTop}},scrollBy:function(e,t,n){var i=this;i.update();var r=i.__isAnimating?i.__scheduledLeft:i.__scrollLeft,a=i.__isAnimating?i.__scheduledTop:i.__scrollTop;i.scrollTo(r+(e||0),a+(t||0),n)},scrollTo:function(t,n,i){function r(t,n){function i(e){return--e*e*e+1}function r(){var p=Date.now(),h=Math.min(1,(p-l)/c),f=i(h);d!=t&&(a.el.scrollTop=parseInt(f*(t-d)+d,10)),u!=n&&(a.el.scrollLeft=parseInt(f*(n-u)+u,10)),1>h?e.requestAnimationFrame(r):(e.tap.removeClonedInputs(a.__container,a),a.el.style.overflowX=o,a.el.style.overflowY=s,a.resize())}var l=Date.now(),c=250,d=a.el.scrollTop,u=a.el.scrollLeft;return d===t&&u===n?(a.el.style.overflowX=o,a.el.style.overflowY=s,void a.resize()):void e.requestAnimationFrame(r)}var a=this;if(!i)return a.el.scrollTop=n,a.el.scrollLeft=t,void a.resize();var o=a.el.style.overflowX,s=a.el.style.overflowY;clearTimeout(a.__scrollToCleanupTimeout),a.__scrollToCleanupTimeout=setTimeout(function(){a.el.style.overflowX=o,a.el.style.overflowY=s},500),a.el.style.overflowY="hidden",a.el.style.overflowX="hidden",r(n,t)},__waitForSize:function(){var e=this;clearTimeout(e.__sizerTimeout);var t=function(){e.resize(!0)};t(),e.__sizerTimeout=setTimeout(t,500)},__computeScrollMax:function(){var e=this;e.__maxScrollLeft=Math.max(e.__contentWidth-e.__clientWidth,0),e.__maxScrollTop=Math.max(e.__contentHeight-e.__clientHeight,0),e.__didWaitForSize||e.__maxScrollLeft||e.__maxScrollTop||(e.__didWaitForSize=!0,e.__waitForSize())},__initEventHandlers:function(){var t,n,i=this,r=i.__container;i.scrollChildIntoView=function(a){var o=r.getBoundingClientRect();i.__originalContainerHeight||(i.__originalContainerHeight=o.height),t=i.__originalContainerHeight;var s=i.isShrunkForKeyboard,l=r.parentNode.classList.contains("modal"),c=r.parentNode.classList.contains("popover"),d=l&&window.innerWidth>=680,u=n&&n!==a.detail.keyboardHeight;(!s||u)&&(!c&&(e.Platform.isIOS()||e.Platform.isFullScreen||d)&&e.requestAnimationFrame(function(){t=Math.max(0,Math.min(i.__originalContainerHeight,i.__originalContainerHeight-(a.detail.keyboardHeight-43))),r.style.height=t+"px",r.classList.add("keyboard-up"),i.resize()}),i.isShrunkForKeyboard=!0),n=a.detail.keyboardHeight,a.detail.isElementUnderKeyboard&&e.requestAnimationFrame(function(){var t=e.DomUtil.getOffsetTop(a.detail.target);setTimeout(function(){e.Platform.isIOS()&&e.tap.cloneFocusedInput(r,i),i.scrollTo(0,t-(o.top+100),!0),i.onScroll()},32)}),a.stopPropagation()},i.resetScrollView=function(){i.isShrunkForKeyboard&&(i.isShrunkForKeyboard=!1,r.style.height="",i.__originalContainerHeight=r.getBoundingClientRect().height,e.Platform.isIOS()&&e.requestAnimationFrame(function(){r.classList.remove("keyboard-up")})),i.resize()},i.handleTouchMove=function(e){return i.__frozenShut?(e.preventDefault(),e.stopPropagation(),!1):void 0},r.addEventListener("scroll",i.onScroll),r.addEventListener("scrollChildIntoView",i.scrollChildIntoView),r.addEventListener(e.EVENTS.touchstart,i.handleTouchMove),r.addEventListener(e.EVENTS.touchmove,i.handleTouchMove),document.addEventListener("resetScrollView",i.resetScrollView)},__cleanup:function(){var n=this,i=n.__container;i.removeEventListener("resetScrollView",n.resetScrollView),i.removeEventListener("scroll",n.onScroll),i.removeEventListener("scrollChildIntoView",n.scrollChildIntoView),i.removeEventListener("resetScrollView",n.resetScrollView),i.removeEventListener(e.EVENTS.touchstart,n.handleTouchMove),i.removeEventListener(e.EVENTS.touchmove,n.handleTouchMove),e.tap.removeClonedInputs(i,n),delete n.__container,delete n.__content,delete n.__indicatorX,delete n.__indicatorY,delete n.options.el,n.resize=n.scrollTo=n.onScroll=n.resetScrollView=t,n.scrollChildIntoView=t,i=null}})}(ionic),function(e){"use strict";var t="item",n="item-content",i="item-sliding",r="item-options",a="item-placeholder",o="item-reordering",s="item-reorder",l=function(){};l.prototype={start:function(){},drag:function(){},end:function(){},isSameItem:function(){return!1}};var c=function(e){this.dragThresholdX=e.dragThresholdX||10,this.el=e.el,this.item=e.item,this.canSwipe=e.canSwipe};c.prototype=new l,c.prototype.start=function(a){var o,s,l,c;this.canSwipe()&&(o=a.target.classList.contains(n)?a.target:a.target.classList.contains(t)?a.target.querySelector("."+n):e.DomUtil.getParentWithClass(a.target,n),o&&(o.classList.remove(i),l=parseFloat(o.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])||0,s=o.parentNode.querySelector("."+r),s&&(s.classList.remove("invisible"),c=s.offsetWidth,this._currentDrag={buttons:s,buttonsWidth:c,content:o,startOffsetX:l})))},c.prototype.isSameItem=function(e){return e._lastDrag&&this._currentDrag?this._currentDrag.content==e._lastDrag.content:!1},c.prototype.clean=function(t){function n(){i.buttons&&i.buttons.classList.add("invisible")}var i=this._lastDrag;i&&i.content&&(i.content.style[e.CSS.TRANSITION]="",i.content.style[e.CSS.TRANSFORM]="",t?(i.content.style[e.CSS.TRANSITION]="none",n(),e.requestAnimationFrame(function(){i.content.style[e.CSS.TRANSITION]=""})):e.requestAnimationFrame(function(){setTimeout(n,250)}))},c.prototype.drag=e.animationFrameThrottle(function(t){var n;if(this._currentDrag&&(!this._isDragging&&(Math.abs(t.gesture.deltaX)>this.dragThresholdX||Math.abs(this._currentDrag.startOffsetX)>0)&&(this._isDragging=!0),this._isDragging)){n=this._currentDrag.buttonsWidth;var i=Math.min(0,this._currentDrag.startOffsetX+t.gesture.deltaX);-n>i&&(i=Math.min(-n,-n+.4*(t.gesture.deltaX+n))),this._currentDrag.content.$$ionicOptionsOpen=0!==i,this._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+i+"px, 0, 0)",this._currentDrag.content.style[e.CSS.TRANSITION]="none"}}),c.prototype.end=function(t,n){var i=this;if(!i._currentDrag)return void(n&&n());var r=-i._currentDrag.buttonsWidth;t.gesture.deltaX>-(i._currentDrag.buttonsWidth/2)&&("left"==t.gesture.direction&&Math.abs(t.gesture.velocityX)<.3?r=0:"right"==t.gesture.direction&&(r=0)),e.requestAnimationFrame(function(){if(0===r){i._currentDrag.content.style[e.CSS.TRANSFORM]="";var t=i._currentDrag.buttons;setTimeout(function(){t&&t.classList.add("invisible")},250)}else i._currentDrag.content.style[e.CSS.TRANSFORM]="translate3d("+r+"px,0,0)";i._currentDrag.content.style[e.CSS.TRANSITION]="",i._lastDrag||(i._lastDrag={}),e.extend(i._lastDrag,i._currentDrag),i._currentDrag&&(i._currentDrag.buttons=null,i._currentDrag.content=null),i._currentDrag=null,n&&n()})};var d=function(e){var t=this;if(t.dragThresholdY=e.dragThresholdY||0,t.onReorder=e.onReorder,t.listEl=e.listEl,t.el=t.item=e.el,t.scrollEl=e.scrollEl,t.scrollView=e.scrollView,t.listElTrueTop=0,t.listEl.offsetParent){var n=t.listEl;do t.listElTrueTop+=n.offsetTop,n=n.offsetParent;while(n)}};d.prototype=new l,d.prototype._moveElement=function(t){var n=t.gesture.center.pageY+this.scrollView.getValues().top-this._currentDrag.elementHeight/2-this.listElTrueTop;this.el.style[e.CSS.TRANSFORM]="translate3d(0, "+n+"px, 0)"},d.prototype.deregister=function(){this.listEl=this.el=this.scrollEl=this.scrollView=null},d.prototype.start=function(t){var n=e.DomUtil.getChildIndex(this.el,this.el.nodeName.toLowerCase()),i=this.el.scrollHeight,r=this.el.cloneNode(!0);r.classList.add(a),this.el.parentNode.insertBefore(r,this.el),this.el.classList.add(o),this._currentDrag={elementHeight:i,startIndex:n,placeholder:r,scrollHeight:scroll,list:r.parentNode},this._moveElement(t)},d.prototype.drag=e.animationFrameThrottle(function(t){var n=this;if(this._currentDrag){var i=0,r=t.gesture.center.pageY,a=this.listElTrueTop;if(this.scrollView){var o=this.scrollView.__container;i=this.scrollView.getValues().top;var s=o.offsetTop,l=s-r+this._currentDrag.elementHeight/2,c=r+this._currentDrag.elementHeight/2-s-o.offsetHeight;t.gesture.deltaY<0&&l>0&&i>0&&(this.scrollView.scrollBy(null,-l),e.requestAnimationFrame(function(){n.drag(t)})),t.gesture.deltaY>0&&c>0&&i<this.scrollView.getScrollMax().top&&(this.scrollView.scrollBy(null,c),e.requestAnimationFrame(function(){n.drag(t)}))}!this._isDragging&&Math.abs(t.gesture.deltaY)>this.dragThresholdY&&(this._isDragging=!0),this._isDragging&&(this._moveElement(t),this._currentDrag.currentY=i+r-a)}}),d.prototype._getReorderIndex=function(){for(var e,t=this,n=Array.prototype.slice.call(t._currentDrag.placeholder.parentNode.children).filter(function(e){return e.nodeName===t.el.nodeName&&e!==t.el}),i=t._currentDrag.currentY,r=0,a=n.length;a>r;r++)if(e=n[r],r===a-1){if(i>e.offsetTop)return r}else if(0===r){if(i<e.offsetTop+e.offsetHeight)return r}else if(i>e.offsetTop-e.offsetHeight/2&&i<e.offsetTop+e.offsetHeight)return r;return t._currentDrag.startIndex},d.prototype.end=function(t,n){if(!this._currentDrag)return void(n&&n());var i=this._currentDrag.placeholder,r=this._getReorderIndex();this.el.classList.remove(o),this.el.style[e.CSS.TRANSFORM]="",i.parentNode.insertBefore(this.el,i),i.parentNode.removeChild(i),this.onReorder&&this.onReorder(this.el,this._currentDrag.startIndex,r),this._currentDrag={placeholder:null,content:null},this._currentDrag=null,n&&n()},e.views.ListView=e.views.View.inherit({initialize:function(t){var n=this;t=e.extend({onReorder:function(){},virtualRemoveThreshold:-200,virtualAddThreshold:200,canSwipe:function(){return!0}},t),e.extend(n,t),!n.itemHeight&&n.listEl&&(n.itemHeight=n.listEl.children[0]&&parseInt(n.listEl.children[0].style.height,10)),n.onRefresh=t.onRefresh||function(){},n.onRefreshOpening=t.onRefreshOpening||function(){},n.onRefreshHolding=t.onRefreshHolding||function(){};var i={};e.DomUtil.getParentOrSelfWithClass(n.el,"overflow-scroll")&&(i.prevent_default_directions=["left","right"]),window.ionic.onGesture("release",function(e){n._handleEndDrag(e)},n.el,i),window.ionic.onGesture("drag",function(e){n._handleDrag(e)},n.el,i),n._initDrag()},deregister:function(){this.el=this.listEl=this.scrollEl=this.scrollView=null,this.isScrollFreeze&&self.scrollView.freeze(!1)},stopRefreshing:function(){var e=this.el.querySelector(".list-refresher");e.style.height="0"},didScroll:function(e){var t=this;if(t.isVirtual){var n=t.itemHeight,i=e.target.scrollHeight,r=t.el.parentNode.offsetHeight,a=Math.max(0,e.scrollTop+t.virtualRemoveThreshold),o=Math.min(i,Math.abs(e.scrollTop)+r+t.virtualAddThreshold),s=parseInt(Math.abs(a/n),10),l=parseInt(Math.abs(o/n),10);t._virtualItemsToRemove=Array.prototype.slice.call(t.listEl.children,0,s),t.renderViewport&&t.renderViewport(a,o,s,l)}},didStopScrolling:function(){if(this.isVirtual)for(var e=0;e<this._virtualItemsToRemove.length;e++)this.didHideItem&&this.didHideItem(e)},clearDragEffects:function(e){this._lastDragOp&&(this._lastDragOp.clean&&this._lastDragOp.clean(e),this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=null)},_initDrag:function(){this._lastDragOp&&this._lastDragOp.deregister&&this._lastDragOp.deregister(),this._lastDragOp=this._dragOp,this._dragOp=null},_getItem:function(e){for(;e;){if(e.classList&&e.classList.contains(t))return e;e=e.parentNode}return null},_startDrag:function(t){var n=this;n._isDragging=!1;var i,r=n._lastDragOp;n._didDragUpOrDown&&r instanceof c&&r.clean&&r.clean(),!e.DomUtil.getParentOrSelfWithClass(t.target,s)||"up"!=t.gesture.direction&&"down"!=t.gesture.direction?!n._didDragUpOrDown&&("left"==t.gesture.direction||"right"==t.gesture.direction)&&Math.abs(t.gesture.deltaX)>5&&(i=n._getItem(t.target),i&&i.querySelector(".item-options")&&(n._dragOp=new c({el:n.el,item:i,canSwipe:n.canSwipe}),n._dragOp.start(t),t.preventDefault(),n.isScrollFreeze=n.scrollView.freeze(!0))):(i=n._getItem(t.target),i&&(n._dragOp=new d({listEl:n.el,el:i,scrollEl:n.scrollEl,scrollView:n.scrollView,onReorder:function(e,t,i){n.onReorder&&n.onReorder(e,t,i)}}),n._dragOp.start(t),t.preventDefault())),r&&n._dragOp&&!n._dragOp.isSameItem(r)&&t.defaultPrevented&&r.clean&&r.clean()},_handleEndDrag:function(e){var t=this;t.scrollView&&(t.isScrollFreeze=t.scrollView.freeze(!1)),t._didDragUpOrDown=!1,t._dragOp&&t._dragOp.end(e,function(){t._initDrag()})},_handleDrag:function(e){var t=this;Math.abs(e.gesture.deltaY)>5&&(t._didDragUpOrDown=!0),t.isDragging||t._dragOp||t._startDrag(e),t._dragOp&&(e.gesture.srcEvent.preventDefault(),t._dragOp.drag(e))}})}(ionic),function(e){"use strict";e.views.Modal=e.views.View.inherit({initialize:function(t){t=e.extend({focusFirstInput:!1,unfocusOnHide:!0,focusFirstDelay:600,backdropClickToClose:!0,hardwareBackButtonClose:!0},t),e.extend(this,t),this.el=t.el},show:function(){var e=this;e.focusFirstInput&&window.setTimeout(function(){var t=e.el.querySelector("input, textarea");t&&t.focus&&t.focus()},e.focusFirstDelay)},hide:function(){if(this.unfocusOnHide){var e=this.el.querySelectorAll("input, textarea");window.setTimeout(function(){for(var t=0;t<e.length;t++)e[t].blur&&e[t].blur()})}}})}(ionic),function(e){"use strict";e.views.SideMenu=e.views.View.inherit({initialize:function(e){this.el=e.el,this.isEnabled="undefined"==typeof e.isEnabled?!0:e.isEnabled,this.setWidth(e.width)},getFullWidth:function(){return this.width},setWidth:function(e){this.width=e,this.el.style.width=e+"px"},setIsEnabled:function(e){this.isEnabled=e},bringUp:function(){"0"!==this.el.style.zIndex&&(this.el.style.zIndex="0")},pushDown:function(){"-1"!==this.el.style.zIndex&&(this.el.style.zIndex="-1")}}),e.views.SideMenuContent=e.views.View.inherit({initialize:function(t){e.extend(this,{animationClass:"menu-animated",onDrag:function(){},onEndDrag:function(){}},t),e.onGesture("drag",e.proxy(this._onDrag,this),this.el),e.onGesture("release",e.proxy(this._onEndDrag,this),this.el)},_onDrag:function(e){this.onDrag&&this.onDrag(e)},_onEndDrag:function(e){this.onEndDrag&&this.onEndDrag(e)},disableAnimation:function(){this.el.classList.remove(this.animationClass)},enableAnimation:function(){this.el.classList.add(this.animationClass)},getTranslateX:function(){return parseFloat(this.el.style[e.CSS.TRANSFORM].replace("translate3d(","").split(",")[0])},setTranslateX:e.animationFrameThrottle(function(t){this.el.style[e.CSS.TRANSFORM]="translate3d("+t+"px, 0, 0)"})})}(ionic),function(e){"use strict";e.views.Slider=e.views.View.inherit({initialize:function(e){function t(){if(b.offsetWidth){S=D.children,x=S.length,S.length<2&&(e.continuous=!1),T.transitions&&e.continuous&&S.length<3&&(D.appendChild(S[0].cloneNode(!0)),D.appendChild(D.children[1].cloneNode(!0)),S=D.children),y=new Array(S.length),E=b.offsetWidth||b.getBoundingClientRect().width,D.style.width=S.length*E+"px";for(var t=S.length;t--;){var n=S[t];n.style.width=E+"px",n.setAttribute("data-index",t),T.transitions&&(n.style.left=t*-E+"px",o(t,M>t?-E:t>M?E:0,0))}e.continuous&&T.transitions&&(o(r(M-1),-E,0),o(r(M+1),E,0)),T.transitions||(D.style.left=M*-E+"px"),b.style.visibility="visible",e.slidesChanged&&e.slidesChanged()}}function n(t){e.continuous?a(M-1,t):M&&a(M-1,t)}function i(t){e.continuous?a(M+1,t):M<S.length-1&&a(M+1,t)}function r(e){return(S.length+e%S.length)%S.length}function a(t,n){if(M!=t){if(!S)return void(M=t);if(T.transitions){var i=Math.abs(M-t)/(M-t);if(e.continuous){var a=i;i=-y[r(t)]/E,i!==a&&(t=-i*S.length+t)}for(var s=Math.abs(M-t)-1;s--;)o(r((t>M?t:M)-s-1),E*i,0);t=r(t),o(M,E*i,n||L),o(t,0,n||L),e.continuous&&o(r(t-i),-(E*i),0)}else t=r(t),l(M*-E,t*-E,n||L);M=t,w(e.callback&&e.callback(M,S[M]))}}function o(e,t,n){s(e,t,n),y[e]=t}function s(e,t,n){var i=S[e],r=i&&i.style;r&&(r.webkitTransitionDuration=r.MozTransitionDuration=r.msTransitionDuration=r.OTransitionDuration=r.transitionDuration=n+"ms",r.webkitTransform="translate("+t+"px,0)translateZ(0)",r.msTransform=r.MozTransform=r.OTransform="translateX("+t+"px)")}function l(t,n,i){if(!i)return void(D.style.left=n+"px");var r=+new Date,a=setInterval(function(){var o=+new Date-r;return o>i?(D.style.left=n+"px",I&&c(),e.transitionEnd&&e.transitionEnd.call(event,M,S[M]),void clearInterval(a)):void(D.style.left=(n-t)*(Math.floor(o/i*100)/100)+t+"px")},4)}function c(){C=setTimeout(i,I)}function d(){I=e.auto||0,clearTimeout(C)}var u,p,h,f=this;window.navigator.pointerEnabled?(u="pointerdown",p="pointermove",h="pointerup"):window.navigator.msPointerEnabled?(u="MSPointerDown",p="MSPointerMove",h="MSPointerUp"):(u="touchstart",p="touchmove",h="touchend");var m="mousedown",g="mousemove",v="mouseup",_=function(){},w=function(e){setTimeout(e||_,0)},T={addEventListener:!!window.addEventListener,transitions:function(e){var t=["transitionProperty","WebkitTransition","MozTransition","OTransition","msTransition"];for(var n in t)if(void 0!==e.style[t[n]])return!0;return!1}(document.createElement("swipe"))},b=e.el;if(b){var S,y,E,x,D=b.children[0];e=e||{};var M=parseInt(e.startSlide,10)||0,L=e.speed||300;e.continuous=void 0!==e.continuous?e.continuous:!0;var C,P,I=e.auto||0,k={},N={},z={handleEvent:function(n){switch(!n.touches&&n.pageX&&n.pageY&&(n.touches=[{pageX:n.pageX,pageY:n.pageY}]),n.type){case u:this.start(n);break;case m:this.start(n);break;case p:this.touchmove(n);break;case g:this.touchmove(n);break;case h:w(this.end(n));break;case v:w(this.end(n));break;case"webkitTransitionEnd":case"msTransitionEnd":case"oTransitionEnd":case"otransitionend":case"transitionend":w(this.transitionEnd(n));break;case"resize":w(t)}e.stopPropagation&&n.stopPropagation()},start:function(e){if(e.touches){var t=e.touches[0];k={x:t.pageX,y:t.pageY,time:+new Date},P=void 0,N={},D.addEventListener(p,this,!1),D.addEventListener(g,this,!1),D.addEventListener(h,this,!1),D.addEventListener(v,this,!1),document.addEventListener(h,this,!1),document.addEventListener(v,this,!1)}},touchmove:function(t){if(!(!t.touches||t.touches.length>1||t.scale&&1!==t.scale||f.slideIsDisabled)){e.disableScroll&&t.preventDefault();var n=t.touches[0];N={x:n.pageX-k.x,y:n.pageY-k.y},"undefined"==typeof P&&(P=!!(P||Math.abs(N.x)<Math.abs(N.y))),P||(t.preventDefault(),d(),e.continuous?(s(r(M-1),N.x+y[r(M-1)],0),s(M,N.x+y[M],0),s(r(M+1),N.x+y[r(M+1)],0)):(e.bouncing?N.x=N.x/(!M&&N.x>0||M==S.length-1&&N.x<0?Math.abs(N.x)/E+1:1):(E*M-N.x<0&&(N.x=Math.min(N.x,E*M)),Math.abs(N.x)>E*(S.length-M-1)&&(N.x=Math.max(-E*(S.length-M-1),N.x))),s(M-1,N.x+y[M-1],0),s(M,N.x+y[M],0),s(M+1,N.x+y[M+1],0)),e.onDrag&&e.onDrag())}},end:function(){var t=+new Date-k.time,n=Number(t)<250&&Math.abs(N.x)>20||Math.abs(N.x)>E/2,i=!M&&N.x>0||M==S.length-1&&N.x<0;e.continuous&&(i=!1);var a=N.x<0;P||(n&&!i?(a?(e.continuous?(o(r(M-1),-E,0),o(r(M+2),E,0)):o(M-1,-E,0),o(M,y[M]-E,L),o(r(M+1),y[r(M+1)]-E,L),M=r(M+1)):(e.continuous?(o(r(M+1),E,0),o(r(M-2),-E,0)):o(M+1,E,0),o(M,y[M]+E,L),o(r(M-1),y[r(M-1)]+E,L),M=r(M-1)),e.callback&&e.callback(M,S[M])):e.continuous?(o(r(M-1),-E,L),o(M,0,L),o(r(M+1),E,L)):(o(M-1,-E,L),o(M,0,L),o(M+1,E,L))),D.removeEventListener(p,z,!1),D.removeEventListener(g,z,!1),D.removeEventListener(h,z,!1),D.removeEventListener(v,z,!1),document.removeEventListener(h,z,!1),document.removeEventListener(v,z,!1),e.onDragEnd&&e.onDragEnd()},transitionEnd:function(t){parseInt(t.target.getAttribute("data-index"),10)==M&&(I&&c(),e.transitionEnd&&e.transitionEnd.call(t,M,S[M]))}};this.update=function(){setTimeout(t)},this.setup=function(){t()},this.loop=function(t){return arguments.length&&(e.continuous=!!t),e.continuous},this.enableSlide=function(e){return arguments.length&&(this.slideIsDisabled=!e),!this.slideIsDisabled},this.slide=this.select=function(e,t){d(),a(e,t)},this.prev=this.previous=function(){d(),n()},this.next=function(){d(),i()},this.stop=function(){d()},this.start=function(){c()},this.autoPlay=function(e){!I||0>I?d():(I=e,c())},this.currentIndex=this.selected=function(){return M},this.slidesCount=this.count=function(){return x},this.kill=function(){d(),D.style.width="",D.style.left="",S&&(S=[]),T.addEventListener?(D.removeEventListener(u,z,!1),D.removeEventListener(m,z,!1),D.removeEventListener("webkitTransitionEnd",z,!1),D.removeEventListener("msTransitionEnd",z,!1),D.removeEventListener("oTransitionEnd",z,!1),D.removeEventListener("otransitionend",z,!1),D.removeEventListener("transitionend",z,!1),window.removeEventListener("resize",z,!1)):window.onresize=null},this.load=function(){t(),I&&c(),T.addEventListener?(D.addEventListener(u,z,!1),D.addEventListener(m,z,!1),T.transitions&&(D.addEventListener("webkitTransitionEnd",z,!1),D.addEventListener("msTransitionEnd",z,!1),D.addEventListener("oTransitionEnd",z,!1),D.addEventListener("otransitionend",z,!1),D.addEventListener("transitionend",z,!1)),window.addEventListener("resize",z,!1)):window.onresize=function(){t()}}}}})}(ionic),function(){"use strict";function e(e){e.fn.swiper=function(t){var i;return e(this).each(function(){var e=new n(this,t);i||(i=e)}),i}}var t,n=function(e,r,a,o){function s(){return"horizontal"===y.params.direction}function l(e){return Math.floor(e)}function c(){y.autoplayTimeoutId=setTimeout(function(){y.params.loop?(y.fixLoop(),y._slideNext()):y.isEnd?r.autoplayStopOnLast?y.stopAutoplay():y._slideTo(0):y._slideNext()},y.params.autoplay)}function d(e,n){var i=t(e.target);if(!i.is(n))if("string"==typeof n)i=i.parents(n);else if(n.nodeType){var r;return i.parents().each(function(e,t){t===n&&(r=n)}),r?n:void 0}return 0===i.length?void 0:i[0]}function u(e,t){t=t||{};var n=window.MutationObserver||window.WebkitMutationObserver,i=new n(function(e){e.forEach(function(e){y.onResize(!0),y.emit("onObserverUpdate",y,e)})});i.observe(e,{attributes:"undefined"==typeof t.attributes?!0:t.attributes,childList:"undefined"==typeof t.childList?!0:t.childList,characterData:"undefined"==typeof t.characterData?!0:t.characterData}),y.observers.push(i)}function p(e){e.originalEvent&&(e=e.originalEvent);var t=e.keyCode||e.charCode;if(!y.params.allowSwipeToNext&&(s()&&39===t||!s()&&40===t))return!1;if(!y.params.allowSwipeToPrev&&(s()&&37===t||!s()&&38===t))return!1;if(!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey||document.activeElement&&document.activeElement.nodeName&&("input"===document.activeElement.nodeName.toLowerCase()||"textarea"===document.activeElement.nodeName.toLowerCase()))){if(37===t||39===t||38===t||40===t){var n=!1;if(y.container.parents(".swiper-slide").length>0&&0===y.container.parents(".swiper-slide-active").length)return;var i={left:window.pageXOffset,top:window.pageYOffset},r=window.innerWidth,a=window.innerHeight,o=y.container.offset();y.rtl&&(o.left=o.left-y.container[0].scrollLeft);for(var l=[[o.left,o.top],[o.left+y.width,o.top],[o.left,o.top+y.height],[o.left+y.width,o.top+y.height]],c=0;c<l.length;c++){var d=l[c];d[0]>=i.left&&d[0]<=i.left+r&&d[1]>=i.top&&d[1]<=i.top+a&&(n=!0)}if(!n)return}s()?((37===t||39===t)&&(e.preventDefault?e.preventDefault():e.returnValue=!1),(39===t&&!y.rtl||37===t&&y.rtl)&&y.slideNext(),(37===t&&!y.rtl||39===t&&y.rtl)&&y.slidePrev()):((38===t||40===t)&&(e.preventDefault?e.preventDefault():e.returnValue=!1),40===t&&y.slideNext(),38===t&&y.slidePrev())}}function h(e){e.originalEvent&&(e=e.originalEvent);var t=y.mousewheel.event,n=0,i=y.rtl?-1:1;if(e.detail)n=-e.detail;else if("mousewheel"===t)if(y.params.mousewheelForceToAxis)if(s()){if(!(Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)))return;n=e.wheelDeltaX*i}else{if(!(Math.abs(e.wheelDeltaY)>Math.abs(e.wheelDeltaX)))return;n=e.wheelDeltaY}else n=Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)?-e.wheelDeltaX*i:-e.wheelDeltaY;else if("DOMMouseScroll"===t)n=-e.detail;else if("wheel"===t)if(y.params.mousewheelForceToAxis)if(s()){if(!(Math.abs(e.deltaX)>Math.abs(e.deltaY)))return;n=-e.deltaX*i}else{if(!(Math.abs(e.deltaY)>Math.abs(e.deltaX)))return;n=-e.deltaY}else n=Math.abs(e.deltaX)>Math.abs(e.deltaY)?-e.deltaX*i:-e.deltaY;if(0!==n){if(y.params.mousewheelInvert&&(n=-n),y.params.freeMode){var r=y.getWrapperTranslate()+n*y.params.mousewheelSensitivity,a=y.isBeginning,o=y.isEnd;if(r>=y.minTranslate()&&(r=y.minTranslate()),r<=y.maxTranslate()&&(r=y.maxTranslate()),y.setWrapperTransition(0),y.setWrapperTranslate(r),y.updateProgress(),y.updateActiveIndex(),(!a&&y.isBeginning||!o&&y.isEnd)&&y.updateClasses(),y.params.freeModeSticky&&(clearTimeout(y.mousewheel.timeout),y.mousewheel.timeout=setTimeout(function(){y.slideReset()},300)),0===r||r===y.maxTranslate())return}else{if((new window.Date).getTime()-y.mousewheel.lastScrollTime>60)if(0>n)if(y.isEnd&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slideNext();else if(y.isBeginning&&!y.params.loop||y.animating){if(y.params.mousewheelReleaseOnEdges)return!0}else y.slidePrev();y.mousewheel.lastScrollTime=(new window.Date).getTime()}return y.params.autoplay&&y.stopAutoplay(),e.preventDefault?e.preventDefault():e.returnValue=!1,!1}}function f(e,n){e=t(e);var i,r,a,o=y.rtl?-1:1;i=e.attr("data-swiper-parallax")||"0",r=e.attr("data-swiper-parallax-x"), +a=e.attr("data-swiper-parallax-y"),r||a?(r=r||"0",a=a||"0"):s()?(r=i,a="0"):(a=i,r="0"),r=r.indexOf("%")>=0?parseInt(r,10)*n*o+"%":r*n*o+"px",a=a.indexOf("%")>=0?parseInt(a,10)*n+"%":a*n+"px",e.transform("translate3d("+r+", "+a+",0px)")}function m(e){return 0!==e.indexOf("on")&&(e=e[0]!==e[0].toUpperCase()?"on"+e[0].toUpperCase()+e.substring(1):"on"+e),e}if(!(this instanceof n))return new n(e,r);var g={direction:"horizontal",touchEventsTarget:"container",initialSlide:0,speed:300,autoplay:!1,autoplayDisableOnInteraction:!0,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},cube:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fade:{crossFade:!1},parallax:!1,scrollbar:null,scrollbarHide:!0,scrollbarDraggable:!1,scrollbarSnapOnRelease:!1,keyboardControl:!1,mousewheelControl:!1,mousewheelReleaseOnEdges:!1,mousewheelInvert:!1,mousewheelForceToAxis:!1,mousewheelSensitivity:1,hashnav:!1,breakpoints:void 0,spaceBetween:0,slidesPerView:1,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,onlyExternal:!1,threshold:0,touchMoveStopPropagation:!0,pagination:null,paginationElement:"span",paginationClickable:!1,paginationHide:!1,paginationBulletRender:null,resistance:!0,resistanceRatio:.85,nextButton:null,prevButton:null,watchSlidesProgress:!1,watchSlidesVisibility:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,lazyLoading:!1,lazyLoadingInPrevNext:!1,lazyLoadingOnTransitionStart:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,control:void 0,controlInverse:!1,controlBy:"slide",allowSwipeToPrev:!0,allowSwipeToNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",slideClass:"swiper-slide",slideActiveClass:"swiper-slide-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slidePrevClass:"swiper-slide-prev",wrapperClass:"swiper-wrapper",bulletClass:"swiper-pagination-bullet",bulletActiveClass:"swiper-pagination-bullet-active",buttonDisabledClass:"swiper-button-disabled",paginationHiddenClass:"swiper-pagination-hidden",observer:!1,observeParents:!1,a11y:!1,prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",runCallbacksOnInit:!0},v=r&&r.virtualTranslate;r=r||{};var _={};for(var w in r)if("object"!=typeof r[w]||(r[w].nodeType||r[w]===window||r[w]===document||"undefined"!=typeof i&&r[w]instanceof i||"undefined"!=typeof jQuery&&r[w]instanceof jQuery))_[w]=r[w];else{_[w]={};for(var T in r[w])_[w][T]=r[w][T]}for(var b in g)if("undefined"==typeof r[b])r[b]=g[b];else if("object"==typeof r[b])for(var S in g[b])"undefined"==typeof r[b][S]&&(r[b][S]=g[b][S]);var y=this;if(y.params=r,y.originalParams=_,y.classNames=[],"undefined"!=typeof t&&"undefined"!=typeof i&&(t=i),("undefined"!=typeof t||(t="undefined"==typeof i?window.Dom7||window.Zepto||window.jQuery:i))&&(y.$=t,y.currentBreakpoint=void 0,y.getActiveBreakpoint=function(){if(!y.params.breakpoints)return!1;var e,t=!1,n=[];for(e in y.params.breakpoints)y.params.breakpoints.hasOwnProperty(e)&&n.push(e);n.sort(function(e,t){return parseInt(e,10)>parseInt(t,10)});for(var i=0;i<n.length;i++)e=n[i],e>=window.innerWidth&&!t&&(t=e);return t||"max"},y.setBreakpoint=function(){var e=y.getActiveBreakpoint();if(e&&y.currentBreakpoint!==e){var t=e in y.params.breakpoints?y.params.breakpoints[e]:y.originalParams;for(var n in t)y.params[n]=t[n];y.currentBreakpoint=e}},y.params.breakpoints&&y.setBreakpoint(),y.container=t(e),0!==y.container.length)){if(y.container.length>1)return void y.container.each(function(){new n(this,r)});y.container[0].swiper=y,y.container.data("swiper",y),y.classNames.push("swiper-container-"+y.params.direction),y.params.freeMode&&y.classNames.push("swiper-container-free-mode"),y.support.flexbox||(y.classNames.push("swiper-container-no-flexbox"),y.params.slidesPerColumn=1),y.params.autoHeight&&y.classNames.push("swiper-container-autoheight"),(y.params.parallax||y.params.watchSlidesVisibility)&&(y.params.watchSlidesProgress=!0),["cube","coverflow"].indexOf(y.params.effect)>=0&&(y.support.transforms3d?(y.params.watchSlidesProgress=!0,y.classNames.push("swiper-container-3d")):y.params.effect="slide"),"slide"!==y.params.effect&&y.classNames.push("swiper-container-"+y.params.effect),"cube"===y.params.effect&&(y.params.resistanceRatio=0,y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.centeredSlides=!1,y.params.spaceBetween=0,y.params.virtualTranslate=!0,y.params.setWrapperSize=!1),"fade"===y.params.effect&&(y.params.slidesPerView=1,y.params.slidesPerColumn=1,y.params.slidesPerGroup=1,y.params.watchSlidesProgress=!0,y.params.spaceBetween=0,"undefined"==typeof v&&(y.params.virtualTranslate=!0)),y.params.grabCursor&&y.support.touch&&(y.params.grabCursor=!1),y.wrapper=y.container.children("."+y.params.wrapperClass),y.params.pagination&&(y.paginationContainer=t(y.params.pagination),y.params.paginationClickable&&y.paginationContainer.addClass("swiper-pagination-clickable")),y.rtl=s()&&("rtl"===y.container[0].dir.toLowerCase()||"rtl"===y.container.css("direction")),y.rtl&&y.classNames.push("swiper-container-rtl"),y.rtl&&(y.wrongRTL="-webkit-box"===y.wrapper.css("display")),y.params.slidesPerColumn>1&&y.classNames.push("swiper-container-multirow"),y.device.android&&y.classNames.push("swiper-container-android"),y.container.addClass(y.classNames.join(" ")),y.translate=0,y.progress=0,y.velocity=0,y.lockSwipeToNext=function(){y.params.allowSwipeToNext=!1},y.lockSwipeToPrev=function(){y.params.allowSwipeToPrev=!1},y.lockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!1},y.unlockSwipeToNext=function(){y.params.allowSwipeToNext=!0},y.unlockSwipeToPrev=function(){y.params.allowSwipeToPrev=!0},y.unlockSwipes=function(){y.params.allowSwipeToNext=y.params.allowSwipeToPrev=!0},y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab"),y.imagesToLoad=[],y.imagesLoaded=0,y.loadImage=function(e,t,n,i,r){function a(){r&&r()}var o;e.complete&&i?a():t?(o=new window.Image,o.onload=a,o.onerror=a,n&&(o.srcset=n),t&&(o.src=t)):a()},y.preloadImages=function(){function e(){"undefined"!=typeof y&&null!==y&&(void 0!==y.imagesLoaded&&y.imagesLoaded++,y.imagesLoaded===y.imagesToLoad.length&&(y.params.updateOnImagesReady&&y.update(),y.emit("onImagesReady",y)))}y.imagesToLoad=y.container.find("img");for(var t=0;t<y.imagesToLoad.length;t++)y.loadImage(y.imagesToLoad[t],y.imagesToLoad[t].currentSrc||y.imagesToLoad[t].getAttribute("src"),y.imagesToLoad[t].srcset||y.imagesToLoad[t].getAttribute("srcset"),!0,e)},y.autoplayTimeoutId=void 0,y.autoplaying=!1,y.autoplayPaused=!1,y.startAutoplay=function(){return"undefined"!=typeof y.autoplayTimeoutId?!1:y.params.autoplay?y.autoplaying?!1:(y.autoplaying=!0,y.emit("onAutoplayStart",y),void c()):!1},y.stopAutoplay=function(e){y.autoplayTimeoutId&&(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplaying=!1,y.autoplayTimeoutId=void 0,y.emit("onAutoplayStop",y))},y.pauseAutoplay=function(e){y.autoplayPaused||(y.autoplayTimeoutId&&clearTimeout(y.autoplayTimeoutId),y.autoplayPaused=!0,0===e?(y.autoplayPaused=!1,c()):y.wrapper.transitionEnd(function(){y&&(y.autoplayPaused=!1,y.autoplaying?c():y.stopAutoplay())}))},y.minTranslate=function(){return-y.snapGrid[0]},y.maxTranslate=function(){return-y.snapGrid[y.snapGrid.length-1]},y.updateAutoHeight=function(){var e=y.slides.eq(y.activeIndex)[0].offsetHeight;e&&y.wrapper.css("height",y.slides.eq(y.activeIndex)[0].offsetHeight+"px")},y.updateContainerSize=function(){var e,t;e="undefined"!=typeof y.params.width?y.params.width:y.container[0].clientWidth,t="undefined"!=typeof y.params.height?y.params.height:y.container[0].clientHeight,0===e&&s()||0===t&&!s()||(e=e-parseInt(y.container.css("padding-left"),10)-parseInt(y.container.css("padding-right"),10),t=t-parseInt(y.container.css("padding-top"),10)-parseInt(y.container.css("padding-bottom"),10),y.width=e,y.height=t,y.size=s()?y.width:y.height)},y.updateSlidesSize=function(){y.slides=y.wrapper.children("."+y.params.slideClass),y.snapGrid=[],y.slidesGrid=[],y.slidesSizesGrid=[];var e,t=y.params.spaceBetween,n=-y.params.slidesOffsetBefore,i=0,r=0;"string"==typeof t&&t.indexOf("%")>=0&&(t=parseFloat(t.replace("%",""))/100*y.size),y.virtualSize=-t,y.rtl?y.slides.css({marginLeft:"",marginTop:""}):y.slides.css({marginRight:"",marginBottom:""});var a;y.params.slidesPerColumn>1&&(a=Math.floor(y.slides.length/y.params.slidesPerColumn)===y.slides.length/y.params.slidesPerColumn?y.slides.length:Math.ceil(y.slides.length/y.params.slidesPerColumn)*y.params.slidesPerColumn,"auto"!==y.params.slidesPerView&&"row"===y.params.slidesPerColumnFill&&(a=Math.max(a,y.params.slidesPerView*y.params.slidesPerColumn)));var o,c=y.params.slidesPerColumn,d=a/c,u=d-(y.params.slidesPerColumn*d-y.slides.length);for(e=0;e<y.slides.length;e++){o=0;var p=y.slides.eq(e);if(y.params.slidesPerColumn>1){var h,f,m;"column"===y.params.slidesPerColumnFill?(f=Math.floor(e/c),m=e-f*c,(f>u||f===u&&m===c-1)&&++m>=c&&(m=0,f++),h=f+m*a/c,p.css({"-webkit-box-ordinal-group":h,"-moz-box-ordinal-group":h,"-ms-flex-order":h,"-webkit-order":h,order:h})):(m=Math.floor(e/d),f=e-m*d),p.css({"margin-top":0!==m&&y.params.spaceBetween&&y.params.spaceBetween+"px"}).attr("data-swiper-column",f).attr("data-swiper-row",m)}"none"!==p.css("display")&&("auto"===y.params.slidesPerView?(o=s()?p.outerWidth(!0):p.outerHeight(!0),y.params.roundLengths&&(o=l(o))):(o=(y.size-(y.params.slidesPerView-1)*t)/y.params.slidesPerView,y.params.roundLengths&&(o=l(o)),s()?y.slides[e].style.width=o+"px":y.slides[e].style.height=o+"px"),y.slides[e].swiperSlideSize=o,y.slidesSizesGrid.push(o),y.params.centeredSlides?(n=n+o/2+i/2+t,0===e&&(n=n-y.size/2-t),Math.abs(n)<.001&&(n=0),r%y.params.slidesPerGroup===0&&y.snapGrid.push(n),y.slidesGrid.push(n)):(r%y.params.slidesPerGroup===0&&y.snapGrid.push(n),y.slidesGrid.push(n),n=n+o+t),y.virtualSize+=o+t,i=o,r++)}y.virtualSize=Math.max(y.virtualSize,y.size)+y.params.slidesOffsetAfter;var g;if(y.rtl&&y.wrongRTL&&("slide"===y.params.effect||"coverflow"===y.params.effect)&&y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),(!y.support.flexbox||y.params.setWrapperSize)&&(s()?y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}):y.wrapper.css({height:y.virtualSize+y.params.spaceBetween+"px"})),y.params.slidesPerColumn>1&&(y.virtualSize=(o+y.params.spaceBetween)*a,y.virtualSize=Math.ceil(y.virtualSize/y.params.slidesPerColumn)-y.params.spaceBetween,y.wrapper.css({width:y.virtualSize+y.params.spaceBetween+"px"}),y.params.centeredSlides)){for(g=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<y.virtualSize+y.snapGrid[0]&&g.push(y.snapGrid[e]);y.snapGrid=g}if(!y.params.centeredSlides){for(g=[],e=0;e<y.snapGrid.length;e++)y.snapGrid[e]<=y.virtualSize-y.size&&g.push(y.snapGrid[e]);y.snapGrid=g,Math.floor(y.virtualSize-y.size)>Math.floor(y.snapGrid[y.snapGrid.length-1])&&y.snapGrid.push(y.virtualSize-y.size)}0===y.snapGrid.length&&(y.snapGrid=[0]),0!==y.params.spaceBetween&&(s()?y.rtl?y.slides.css({marginLeft:t+"px"}):y.slides.css({marginRight:t+"px"}):y.slides.css({marginBottom:t+"px"})),y.params.watchSlidesProgress&&y.updateSlidesOffset()},y.updateSlidesOffset=function(){for(var e=0;e<y.slides.length;e++)y.slides[e].swiperSlideOffset=s()?y.slides[e].offsetLeft:y.slides[e].offsetTop},y.updateSlidesProgress=function(e){if("undefined"==typeof e&&(e=y.translate||0),0!==y.slides.length){"undefined"==typeof y.slides[0].swiperSlideOffset&&y.updateSlidesOffset();var t=-e;y.rtl&&(t=e),y.slides.removeClass(y.params.slideVisibleClass);for(var n=0;n<y.slides.length;n++){var i=y.slides[n],r=(t-i.swiperSlideOffset)/(i.swiperSlideSize+y.params.spaceBetween);if(y.params.watchSlidesVisibility){var a=-(t-i.swiperSlideOffset),o=a+y.slidesSizesGrid[n],s=a>=0&&a<y.size||o>0&&o<=y.size||0>=a&&o>=y.size;s&&y.slides.eq(n).addClass(y.params.slideVisibleClass)}i.progress=y.rtl?-r:r}}},y.updateProgress=function(e){"undefined"==typeof e&&(e=y.translate||0);var t=y.maxTranslate()-y.minTranslate(),n=y.isBeginning,i=y.isEnd;0===t?(y.progress=0,y.isBeginning=y.isEnd=!0):(y.progress=(e-y.minTranslate())/t,y.isBeginning=y.progress<=0,y.isEnd=y.progress>=1),y.isBeginning&&!n&&y.emit("onReachBeginning",y),y.isEnd&&!i&&y.emit("onReachEnd",y),y.params.watchSlidesProgress&&y.updateSlidesProgress(e),y.emit("onProgress",y,y.progress)},y.updateActiveIndex=function(){var e,t,n,i=y.rtl?y.translate:-y.translate;for(t=0;t<y.slidesGrid.length;t++)"undefined"!=typeof y.slidesGrid[t+1]?i>=y.slidesGrid[t]&&i<y.slidesGrid[t+1]-(y.slidesGrid[t+1]-y.slidesGrid[t])/2?e=t:i>=y.slidesGrid[t]&&i<y.slidesGrid[t+1]&&(e=t+1):i>=y.slidesGrid[t]&&(e=t);(0>e||"undefined"==typeof e)&&(e=0),n=Math.floor(e/y.params.slidesPerGroup),n>=y.snapGrid.length&&(n=y.snapGrid.length-1),e!==y.activeIndex&&(y.snapIndex=n,y.previousIndex=y.activeIndex,y.activeIndex=e,y.updateClasses())},y.updateClasses=function(){y.slides.removeClass(y.params.slideActiveClass+" "+y.params.slideNextClass+" "+y.params.slidePrevClass);var e=y.slides.eq(y.activeIndex);if(e.addClass(y.params.slideActiveClass),e.next("."+y.params.slideClass).addClass(y.params.slideNextClass),e.prev("."+y.params.slideClass).addClass(y.params.slidePrevClass),y.bullets&&y.bullets.length>0){y.bullets.removeClass(y.params.bulletActiveClass);var n;y.params.loop?(n=Math.ceil(y.activeIndex-y.loopedSlides)/y.params.slidesPerGroup,n>y.slides.length-1-2*y.loopedSlides&&(n-=y.slides.length-2*y.loopedSlides),n>y.bullets.length-1&&(n-=y.bullets.length)):n="undefined"!=typeof y.snapIndex?y.snapIndex:y.activeIndex||0,y.paginationContainer.length>1?y.bullets.each(function(){t(this).index()===n&&t(this).addClass(y.params.bulletActiveClass)}):y.bullets.eq(n).addClass(y.params.bulletActiveClass)}y.params.loop||(y.params.prevButton&&(y.isBeginning?(t(y.params.prevButton).addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(t(y.params.prevButton))):(t(y.params.prevButton).removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(t(y.params.prevButton)))),y.params.nextButton&&(y.isEnd?(t(y.params.nextButton).addClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.disable(t(y.params.nextButton))):(t(y.params.nextButton).removeClass(y.params.buttonDisabledClass),y.params.a11y&&y.a11y&&y.a11y.enable(t(y.params.nextButton)))))},y.updatePagination=function(){if(y.params.pagination&&y.paginationContainer&&y.paginationContainer.length>0){for(var e="",t=y.params.loop?Math.ceil((y.slides.length-2*y.loopedSlides)/y.params.slidesPerGroup):y.snapGrid.length,n=0;t>n;n++)e+=y.params.paginationBulletRender?y.params.paginationBulletRender(n,y.params.bulletClass):"<"+y.params.paginationElement+' class="'+y.params.bulletClass+'"></'+y.params.paginationElement+">";y.paginationContainer.html(e),y.bullets=y.paginationContainer.find("."+y.params.bulletClass),y.params.paginationClickable&&y.params.a11y&&y.a11y&&y.a11y.initPagination()}},y.update=function(e){function t(){i=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate()),y.setWrapperTranslate(i),y.updateActiveIndex(),y.updateClasses()}if(y.updateContainerSize(),y.updateSlidesSize(),y.updateProgress(),y.updatePagination(),y.updateClasses(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),e){var n,i;y.controller&&y.controller.spline&&(y.controller.spline=void 0),y.params.freeMode?(t(),y.params.autoHeight&&y.updateAutoHeight()):(n=("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0),n||t())}else y.params.autoHeight&&y.updateAutoHeight()},y.onResize=function(e){y.params.breakpoints&&y.setBreakpoint();var t=y.params.allowSwipeToPrev,n=y.params.allowSwipeToNext;if(y.params.allowSwipeToPrev=y.params.allowSwipeToNext=!0,y.updateContainerSize(),y.updateSlidesSize(),("auto"===y.params.slidesPerView||y.params.freeMode||e)&&y.updatePagination(),y.params.scrollbar&&y.scrollbar&&y.scrollbar.set(),y.controller&&y.controller.spline&&(y.controller.spline=void 0),y.params.freeMode){var i=Math.min(Math.max(y.translate,y.maxTranslate()),y.minTranslate());y.setWrapperTranslate(i),y.updateActiveIndex(),y.updateClasses(),y.params.autoHeight&&y.updateAutoHeight()}else y.updateClasses(),("auto"===y.params.slidesPerView||y.params.slidesPerView>1)&&y.isEnd&&!y.params.centeredSlides?y.slideTo(y.slides.length-1,0,!1,!0):y.slideTo(y.activeIndex,0,!1,!0);y.params.allowSwipeToPrev=t,y.params.allowSwipeToNext=n};var E=["mousedown","mousemove","mouseup"];window.navigator.pointerEnabled?E=["pointerdown","pointermove","pointerup"]:window.navigator.msPointerEnabled&&(E=["MSPointerDown","MSPointerMove","MSPointerUp"]),y.touchEvents={start:y.support.touch||!y.params.simulateTouch?"touchstart":E[0],move:y.support.touch||!y.params.simulateTouch?"touchmove":E[1],end:y.support.touch||!y.params.simulateTouch?"touchend":E[2]},(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&("container"===y.params.touchEventsTarget?y.container:y.wrapper).addClass("swiper-wp8-"+y.params.direction),y.initEvents=function(e){var n=e?"off":"on",i=e?"removeEventListener":"addEventListener",a="container"===y.params.touchEventsTarget?y.container[0]:y.wrapper[0],o=y.support.touch?a:document,s=y.params.nested?!0:!1;y.browser.ie?(a[i](y.touchEvents.start,y.onTouchStart,!1),o[i](y.touchEvents.move,y.onTouchMove,s),o[i](y.touchEvents.end,y.onTouchEnd,!1)):(y.support.touch&&(a[i](y.touchEvents.start,y.onTouchStart,!1),a[i](y.touchEvents.move,y.onTouchMove,s),a[i](y.touchEvents.end,y.onTouchEnd,!1)),!r.simulateTouch||y.device.ios||y.device.android||(a[i]("mousedown",y.onTouchStart,!1),document[i]("mousemove",y.onTouchMove,s),document[i]("mouseup",y.onTouchEnd,!1))),window[i]("resize",y.onResize),y.params.nextButton&&(t(y.params.nextButton)[n]("click",y.onClickNext),y.params.a11y&&y.a11y&&t(y.params.nextButton)[n]("keydown",y.a11y.onEnterKey)),y.params.prevButton&&(t(y.params.prevButton)[n]("click",y.onClickPrev),y.params.a11y&&y.a11y&&t(y.params.prevButton)[n]("keydown",y.a11y.onEnterKey)),y.params.pagination&&y.params.paginationClickable&&(t(y.paginationContainer)[n]("click","."+y.params.bulletClass,y.onClickIndex),y.params.a11y&&y.a11y&&t(y.paginationContainer)[n]("keydown","."+y.params.bulletClass,y.a11y.onEnterKey)),(y.params.preventClicks||y.params.preventClicksPropagation)&&a[i]("click",y.preventClicks,!0)},y.attachEvents=function(e){y.initEvents()},y.detachEvents=function(){y.initEvents(!0)},y.allowClick=!0,y.preventClicks=function(e){y.allowClick||(y.params.preventClicks&&e.preventDefault(),y.params.preventClicksPropagation&&y.animating&&(e.stopPropagation(),e.stopImmediatePropagation()))},y.onClickNext=function(e){e.preventDefault(),(!y.isEnd||y.params.loop)&&y.slideNext()},y.onClickPrev=function(e){e.preventDefault(),(!y.isBeginning||y.params.loop)&&y.slidePrev()},y.onClickIndex=function(e){e.preventDefault();var n=t(this).index()*y.params.slidesPerGroup;y.params.loop&&(n+=y.loopedSlides),y.slideTo(n)},y.updateClickedSlide=function(e){var n=d(e,"."+y.params.slideClass),i=!1;if(n)for(var r=0;r<y.slides.length;r++)y.slides[r]===n&&(i=!0);if(!n||!i)return y.clickedSlide=void 0,void(y.clickedIndex=void 0);if(y.clickedSlide=n,y.clickedIndex=t(n).index(),y.params.slideToClickedSlide&&void 0!==y.clickedIndex&&y.clickedIndex!==y.activeIndex){var a,o=y.clickedIndex;if(y.params.loop){if(y.animating)return;a=t(y.clickedSlide).attr("data-swiper-slide-index"),y.params.centeredSlides?o<y.loopedSlides-y.params.slidesPerView/2||o>y.slides.length-y.loopedSlides+y.params.slidesPerView/2?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+a+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o):o>y.slides.length-y.params.slidesPerView?(y.fixLoop(),o=y.wrapper.children("."+y.params.slideClass+'[data-swiper-slide-index="'+a+'"]:not(.swiper-slide-duplicate)').eq(0).index(),setTimeout(function(){y.slideTo(o)},0)):y.slideTo(o)}else y.slideTo(o)}};var x,D,M,L,C,P,I,k,N,z,O="input, select, textarea, button",A=Date.now(),G=[];y.animating=!1,y.touches={startX:0,startY:0,currentX:0,currentY:0,diff:0};var V,R;if(y.onTouchStart=function(e){if(e.originalEvent&&(e=e.originalEvent),V="touchstart"===e.type,V||!("which"in e)||3!==e.which){if(y.params.noSwiping&&d(e,"."+y.params.noSwipingClass))return void(y.allowClick=!0);if(!y.params.swipeHandler||d(e,y.params.swipeHandler)){var n=y.touches.currentX="touchstart"===e.type?e.targetTouches[0].pageX:e.pageX,i=y.touches.currentY="touchstart"===e.type?e.targetTouches[0].pageY:e.pageY;if(!(y.device.ios&&y.params.iOSEdgeSwipeDetection&&n<=y.params.iOSEdgeSwipeThreshold)){if(x=!0,D=!1,M=!0,C=void 0,R=void 0,y.touches.startX=n,y.touches.startY=i,L=Date.now(),y.allowClick=!0,y.updateContainerSize(),y.swipeDirection=void 0,y.params.threshold>0&&(k=!1),"touchstart"!==e.type){var r=!0;t(e.target).is(O)&&(r=!1),document.activeElement&&t(document.activeElement).is(O)&&document.activeElement.blur(),r&&e.preventDefault()}y.emit("onTouchStart",y,e)}}}},y.onTouchMove=function(e){if(e.originalEvent&&(e=e.originalEvent),!(V&&"mousemove"===e.type||e.preventedByNestedSwiper)){if(y.params.onlyExternal)return y.allowClick=!1,void(x&&(y.touches.startX=y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.startY=y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,L=Date.now()));if(V&&document.activeElement&&e.target===document.activeElement&&t(e.target).is(O))return D=!0,void(y.allowClick=!1);if(M&&y.emit("onTouchMove",y,e),!(e.targetTouches&&e.targetTouches.length>1)){if(y.touches.currentX="touchmove"===e.type?e.targetTouches[0].pageX:e.pageX,y.touches.currentY="touchmove"===e.type?e.targetTouches[0].pageY:e.pageY,"undefined"==typeof C){var n=180*Math.atan2(Math.abs(y.touches.currentY-y.touches.startY),Math.abs(y.touches.currentX-y.touches.startX))/Math.PI;C=s()?n>y.params.touchAngle:90-n>y.params.touchAngle}if(C&&y.emit("onTouchMoveOpposite",y,e),"undefined"==typeof R&&y.browser.ieTouch&&(y.touches.currentX!==y.touches.startX||y.touches.currentY!==y.touches.startY)&&(R=!0),x){if(C)return void(x=!1);if(R||!y.browser.ieTouch){y.allowClick=!1,y.emit("onSliderMove",y,e),e.preventDefault(),y.params.touchMoveStopPropagation&&!y.params.nested&&e.stopPropagation(),D||(r.loop&&y.fixLoop(),I=y.getWrapperTranslate(),y.setWrapperTransition(0),y.animating&&y.wrapper.trigger("webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd"),y.params.autoplay&&y.autoplaying&&(y.params.autoplayDisableOnInteraction?y.stopAutoplay():y.pauseAutoplay()),z=!1,y.params.grabCursor&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grabbing",y.container[0].style.cursor="-moz-grabbin",y.container[0].style.cursor="grabbing")),D=!0;var i=y.touches.diff=s()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY;i*=y.params.touchRatio,y.rtl&&(i=-i),y.swipeDirection=i>0?"prev":"next",P=i+I;var a=!0;if(i>0&&P>y.minTranslate()?(a=!1,y.params.resistance&&(P=y.minTranslate()-1+Math.pow(-y.minTranslate()+I+i,y.params.resistanceRatio))):0>i&&P<y.maxTranslate()&&(a=!1,y.params.resistance&&(P=y.maxTranslate()+1-Math.pow(y.maxTranslate()-I-i,y.params.resistanceRatio))),a&&(e.preventedByNestedSwiper=!0),!y.params.allowSwipeToNext&&"next"===y.swipeDirection&&I>P&&(P=I),!y.params.allowSwipeToPrev&&"prev"===y.swipeDirection&&P>I&&(P=I),y.params.followFinger){if(y.params.threshold>0){if(!(Math.abs(i)>y.params.threshold||k))return void(P=I);if(!k)return k=!0,y.touches.startX=y.touches.currentX,y.touches.startY=y.touches.currentY,P=I,void(y.touches.diff=s()?y.touches.currentX-y.touches.startX:y.touches.currentY-y.touches.startY)}(y.params.freeMode||y.params.watchSlidesProgress)&&y.updateActiveIndex(),y.params.freeMode&&(0===G.length&&G.push({position:y.touches[s()?"startX":"startY"],time:L}),G.push({position:y.touches[s()?"currentX":"currentY"],time:(new window.Date).getTime()})),y.updateProgress(P),y.setWrapperTranslate(P)}}}}}},y.onTouchEnd=function(e){if(e.originalEvent&&(e=e.originalEvent),M&&y.emit("onTouchEnd",y,e),M=!1,x){y.params.grabCursor&&D&&x&&(y.container[0].style.cursor="move",y.container[0].style.cursor="-webkit-grab",y.container[0].style.cursor="-moz-grab",y.container[0].style.cursor="grab");var n=Date.now(),i=n-L;if(y.allowClick&&(y.updateClickedSlide(e),y.emit("onTap",y,e),300>i&&n-A>300&&(N&&clearTimeout(N),N=setTimeout(function(){y&&(y.params.paginationHide&&y.paginationContainer.length>0&&!t(e.target).hasClass(y.params.bulletClass)&&y.paginationContainer.toggleClass(y.params.paginationHiddenClass),y.emit("onClick",y,e))},300)),300>i&&300>n-A&&(N&&clearTimeout(N),y.emit("onDoubleTap",y,e))),A=Date.now(),setTimeout(function(){y&&(y.allowClick=!0)},0),!x||!D||!y.swipeDirection||0===y.touches.diff||P===I)return void(x=D=!1);x=D=!1;var r;if(r=y.params.followFinger?y.rtl?y.translate:-y.translate:-P,y.params.freeMode){if(r<-y.minTranslate())return void y.slideTo(y.activeIndex);if(r>-y.maxTranslate())return void(y.slides.length<y.snapGrid.length?y.slideTo(y.snapGrid.length-1):y.slideTo(y.slides.length-1));if(y.params.freeModeMomentum){if(G.length>1){var a=G.pop(),o=G.pop(),s=a.position-o.position,l=a.time-o.time;y.velocity=s/l,y.velocity=y.velocity/2,Math.abs(y.velocity)<y.params.freeModeMinimumVelocity&&(y.velocity=0),(l>150||(new window.Date).getTime()-a.time>300)&&(y.velocity=0)}else y.velocity=0;G.length=0;var c=1e3*y.params.freeModeMomentumRatio,d=y.velocity*c,u=y.translate+d;y.rtl&&(u=-u);var p,h=!1,f=20*Math.abs(y.velocity)*y.params.freeModeMomentumBounceRatio;if(u<y.maxTranslate())y.params.freeModeMomentumBounce?(u+y.maxTranslate()<-f&&(u=y.maxTranslate()-f),p=y.maxTranslate(),h=!0,z=!0):u=y.maxTranslate();else if(u>y.minTranslate())y.params.freeModeMomentumBounce?(u-y.minTranslate()>f&&(u=y.minTranslate()+f),p=y.minTranslate(),h=!0,z=!0):u=y.minTranslate();else if(y.params.freeModeSticky){var m,g=0;for(g=0;g<y.snapGrid.length;g+=1)if(y.snapGrid[g]>-u){m=g;break}u=Math.abs(y.snapGrid[m]-u)<Math.abs(y.snapGrid[m-1]-u)||"next"===y.swipeDirection?y.snapGrid[m]:y.snapGrid[m-1],y.rtl||(u=-u)}if(0!==y.velocity)c=y.rtl?Math.abs((-u-y.translate)/y.velocity):Math.abs((u-y.translate)/y.velocity);else if(y.params.freeModeSticky)return void y.slideReset();y.params.freeModeMomentumBounce&&h?(y.updateProgress(p),y.setWrapperTransition(c),y.setWrapperTranslate(u),y.onTransitionStart(),y.animating=!0,y.wrapper.transitionEnd(function(){y&&z&&(y.emit("onMomentumBounce",y),y.setWrapperTransition(y.params.speed),y.setWrapperTranslate(p),y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))})):y.velocity?(y.updateProgress(u),y.setWrapperTransition(c),y.setWrapperTranslate(u),y.onTransitionStart(),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd()}))):y.updateProgress(u),y.updateActiveIndex()}return void((!y.params.freeModeMomentum||i>=y.params.longSwipesMs)&&(y.updateProgress(),y.updateActiveIndex()))}var v,_=0,w=y.slidesSizesGrid[0];for(v=0;v<y.slidesGrid.length;v+=y.params.slidesPerGroup)"undefined"!=typeof y.slidesGrid[v+y.params.slidesPerGroup]?r>=y.slidesGrid[v]&&r<y.slidesGrid[v+y.params.slidesPerGroup]&&(_=v,w=y.slidesGrid[v+y.params.slidesPerGroup]-y.slidesGrid[v]):r>=y.slidesGrid[v]&&(_=v,w=y.slidesGrid[y.slidesGrid.length-1]-y.slidesGrid[y.slidesGrid.length-2]);var T=(r-y.slidesGrid[_])/w;if(i>y.params.longSwipesMs){if(!y.params.longSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&(T>=y.params.longSwipesRatio?y.slideTo(_+y.params.slidesPerGroup):y.slideTo(_)),"prev"===y.swipeDirection&&(T>1-y.params.longSwipesRatio?y.slideTo(_+y.params.slidesPerGroup):y.slideTo(_))}else{if(!y.params.shortSwipes)return void y.slideTo(y.activeIndex);"next"===y.swipeDirection&&y.slideTo(_+y.params.slidesPerGroup),"prev"===y.swipeDirection&&y.slideTo(_)}}},y._slideTo=function(e,t){return y.slideTo(e,t,!0,!0)},y.slideTo=function(e,t,n,i){"undefined"==typeof n&&(n=!0),"undefined"==typeof e&&(e=0),0>e&&(e=0),y.snapIndex=Math.floor(e/y.params.slidesPerGroup),y.snapIndex>=y.snapGrid.length&&(y.snapIndex=y.snapGrid.length-1);var r=-y.snapGrid[y.snapIndex];y.params.autoplay&&y.autoplaying&&(i||!y.params.autoplayDisableOnInteraction?y.pauseAutoplay(t):y.stopAutoplay()),y.updateProgress(r);for(var a=0;a<y.slidesGrid.length;a++)-Math.floor(100*r)>=Math.floor(100*y.slidesGrid[a])&&(e=a);return!y.params.allowSwipeToNext&&r<y.translate&&r<y.minTranslate()?!1:!y.params.allowSwipeToPrev&&r>y.translate&&r>y.maxTranslate()&&(y.activeIndex||0)!==e?!1:("undefined"==typeof t&&(t=y.params.speed),y.previousIndex=y.activeIndex||0,y.activeIndex=e,y.rtl&&-r===y.translate||!y.rtl&&r===y.translate?(y.params.autoHeight&&y.updateAutoHeight(),y.updateClasses(),"slide"!==y.params.effect&&y.setWrapperTranslate(r),!1):(y.updateClasses(),y.onTransitionStart(n),0===t?(y.setWrapperTranslate(r),y.setWrapperTransition(0),y.onTransitionEnd(n)):(y.setWrapperTranslate(r),y.setWrapperTransition(t),y.animating||(y.animating=!0,y.wrapper.transitionEnd(function(){y&&y.onTransitionEnd(n)}))),!0))},y.onTransitionStart=function(e){"undefined"==typeof e&&(e=!0),y.params.autoHeight&&y.updateAutoHeight(),y.lazy&&y.lazy.onTransitionStart(),e&&(y.emit("onTransitionStart",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeStart",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextStart",y):y.emit("onSlidePrevStart",y)))},y.onTransitionEnd=function(e){y.animating=!1,y.setWrapperTransition(0),"undefined"==typeof e&&(e=!0),y.lazy&&y.lazy.onTransitionEnd(),e&&(y.emit("onTransitionEnd",y),y.activeIndex!==y.previousIndex&&(y.emit("onSlideChangeEnd",y),y.activeIndex>y.previousIndex?y.emit("onSlideNextEnd",y):y.emit("onSlidePrevEnd",y))),y.params.hashnav&&y.hashnav&&y.hashnav.setHash()},y.slideNext=function(e,t,n){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex+y.params.slidesPerGroup,t,e,n)}return y.slideTo(y.activeIndex+y.params.slidesPerGroup,t,e,n)},y._slideNext=function(e){return y.slideNext(!0,e,!0)},y.slidePrev=function(e,t,n){if(y.params.loop){if(y.animating)return!1;y.fixLoop();y.container[0].clientLeft;return y.slideTo(y.activeIndex-1,t,e,n)}return y.slideTo(y.activeIndex-1,t,e,n)},y._slidePrev=function(e){return y.slidePrev(!0,e,!0)},y.slideReset=function(e,t,n){return y.slideTo(y.activeIndex,t,e)},y.setWrapperTransition=function(e,t){y.wrapper.transition(e),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTransition(e),y.params.parallax&&y.parallax&&y.parallax.setTransition(e),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTransition(e),y.params.control&&y.controller&&y.controller.setTransition(e,t),y.emit("onSetTransition",y,e)},y.setWrapperTranslate=function(e,t,n){var i=0,r=0,a=0;s()?i=y.rtl?-e:e:r=e,y.params.roundLengths&&(i=l(i),r=l(r)),y.params.virtualTranslate||(y.support.transforms3d?y.wrapper.transform("translate3d("+i+"px, "+r+"px, "+a+"px)"):y.wrapper.transform("translate("+i+"px, "+r+"px)")),y.translate=s()?i:r;var o,c=y.maxTranslate()-y.minTranslate();o=0===c?0:(e-y.minTranslate())/c,o!==y.progress&&y.updateProgress(e), +t&&y.updateActiveIndex(),"slide"!==y.params.effect&&y.effects[y.params.effect]&&y.effects[y.params.effect].setTranslate(y.translate),y.params.parallax&&y.parallax&&y.parallax.setTranslate(y.translate),y.params.scrollbar&&y.scrollbar&&y.scrollbar.setTranslate(y.translate),y.params.control&&y.controller&&y.controller.setTranslate(y.translate,n),y.emit("onSetTranslate",y,y.translate)},y.getTranslate=function(e,t){var n,i,r,a;return"undefined"==typeof t&&(t="x"),y.params.virtualTranslate?y.rtl?-y.translate:y.translate:(r=window.getComputedStyle(e,null),window.WebKitCSSMatrix?(i=r.transform||r.webkitTransform,i.split(",").length>6&&(i=i.split(", ").map(function(e){return e.replace(",",".")}).join(", ")),a=new window.WebKitCSSMatrix("none"===i?"":i)):(a=r.MozTransform||r.OTransform||r.MsTransform||r.msTransform||r.transform||r.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),n=a.toString().split(",")),"x"===t&&(i=window.WebKitCSSMatrix?a.m41:16===n.length?parseFloat(n[12]):parseFloat(n[4])),"y"===t&&(i=window.WebKitCSSMatrix?a.m42:16===n.length?parseFloat(n[13]):parseFloat(n[5])),y.rtl&&i&&(i=-i),i||0)},y.getWrapperTranslate=function(e){return"undefined"==typeof e&&(e=s()?"x":"y"),y.getTranslate(y.wrapper[0],e)},y.observers=[],y.initObservers=function(){if(y.params.observeParents)for(var e=y.container.parents(),t=0;t<e.length;t++)u(e[t]);u(y.container[0],{childList:!1}),u(y.wrapper[0],{attributes:!1})},y.disconnectObservers=function(){for(var e=0;e<y.observers.length;e++)y.observers[e].disconnect();y.observers=[]},y.createLoop=function(){var e=y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass);angular.element(e).remove();var n=y.wrapper.children("."+y.params.slideClass);"auto"!==y.params.slidesPerView||y.params.loopedSlides||(y.params.loopedSlides=n.length),y.loopedSlides=parseInt(y.params.loopedSlides||y.params.slidesPerView,10),y.loopedSlides=y.loopedSlides+y.params.loopAdditionalSlides,y.loopedSlides>n.length&&(y.loopedSlides=n.length);var i,r,a,s=[],l=[];for(n.each(function(e,i){var r=t(this);e<y.loopedSlides&&l.push(i),e<n.length&&e>=n.length-y.loopedSlides&&s.push(i),r.attr("data-swiper-slide-index",e)}),i=0;i<l.length;i++)a=angular.element(l[i]).clone().addClass(y.params.slideDuplicateClass),a.removeAttr("ng-transclude"),a.removeAttr("ng-repeat"),r=angular.element(l[i]).scope(),a=o(a)(r),angular.element(y.wrapper).append(a);for(i=s.length-1;i>=0;i--)a=angular.element(s[i]).clone().addClass(y.params.slideDuplicateClass),a.removeAttr("ng-transclude"),a.removeAttr("ng-repeat"),r=angular.element(s[i]).scope(),a=o(a)(r),angular.element(y.wrapper).prepend(a)},y.destroyLoop=function(){y.wrapper.children("."+y.params.slideClass+"."+y.params.slideDuplicateClass).remove(),y.slides.removeAttr("data-swiper-slide-index")},y.fixLoop=function(){var e;y.activeIndex<y.loopedSlides?(e=y.slides.length-3*y.loopedSlides+y.activeIndex,e+=y.loopedSlides,y.slideTo(e,0,!1,!0)):("auto"===y.params.slidesPerView&&y.activeIndex>=2*y.loopedSlides||y.activeIndex>y.slides.length-2*y.params.slidesPerView)&&(e=-y.slides.length+y.activeIndex+y.loopedSlides,e+=y.loopedSlides,y.slideTo(e,0,!1,!0))},y.appendSlide=function(e){if(y.params.loop&&y.destroyLoop(),"object"==typeof e&&e.length)for(var t=0;t<e.length;t++)e[t]&&y.wrapper.append(e[t]);else y.wrapper.append(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0)},y.prependSlide=function(e){y.params.loop&&y.destroyLoop();var t=y.activeIndex+1;if("object"==typeof e&&e.length){for(var n=0;n<e.length;n++)e[n]&&y.wrapper.prepend(e[n]);t=y.activeIndex+e.length}else y.wrapper.prepend(e);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.slideTo(t,0,!1)},y.removeSlide=function(e){y.params.loop&&(y.destroyLoop(),y.slides=y.wrapper.children("."+y.params.slideClass));var t,n=y.activeIndex;if("object"==typeof e&&e.length){for(var i=0;i<e.length;i++)t=e[i],y.slides[t]&&y.slides.eq(t).remove(),n>t&&n--;n=Math.max(n,0)}else t=e,y.slides[t]&&y.slides.eq(t).remove(),n>t&&n--,n=Math.max(n,0);y.params.loop&&y.createLoop(),y.params.observer&&y.support.observer||y.update(!0),y.params.loop?y.slideTo(n+y.loopedSlides,0,!1):y.slideTo(n,0,!1)},y.removeAllSlides=function(){for(var e=[],t=0;t<y.slides.length;t++)e.push(t);y.removeSlide(e)},y.effects={fade:{setTranslate:function(){for(var e=0;e<y.slides.length;e++){var t=y.slides.eq(e),n=t[0].swiperSlideOffset,i=-n;y.params.virtualTranslate||(i-=y.translate);var r=0;s()||(r=i,i=0);var a=y.params.fade.crossFade?Math.max(1-Math.abs(t[0].progress),0):1+Math.min(Math.max(t[0].progress,-1),0);t.css({opacity:a}).transform("translate3d("+i+"px, "+r+"px, 0px)")}},setTransition:function(e){if(y.slides.transition(e),y.params.virtualTranslate&&0!==e){var t=!1;y.slides.transitionEnd(function(){if(!t&&y){t=!0,y.animating=!1;for(var e=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],n=0;n<e.length;n++)y.wrapper.trigger(e[n])}})}}},cube:{setTranslate:function(){var e,n=0;y.params.cube.shadow&&(s()?(e=y.wrapper.find(".swiper-cube-shadow"),0===e.length&&(e=t('<div class="swiper-cube-shadow"></div>'),y.wrapper.append(e)),e.css({height:y.width+"px"})):(e=y.container.find(".swiper-cube-shadow"),0===e.length&&(e=t('<div class="swiper-cube-shadow"></div>'),y.container.append(e))));for(var i=0;i<y.slides.length;i++){var r=y.slides.eq(i),a=90*i,o=Math.floor(a/360);y.rtl&&(a=-a,o=Math.floor(-a/360));var l=Math.max(Math.min(r[0].progress,1),-1),c=0,d=0,u=0;i%4===0?(c=4*-o*y.size,u=0):(i-1)%4===0?(c=0,u=4*-o*y.size):(i-2)%4===0?(c=y.size+4*o*y.size,u=y.size):(i-3)%4===0&&(c=-y.size,u=3*y.size+4*y.size*o),y.rtl&&(c=-c),s()||(d=c,c=0);var p="rotateX("+(s()?0:-a)+"deg) rotateY("+(s()?a:0)+"deg) translate3d("+c+"px, "+d+"px, "+u+"px)";if(1>=l&&l>-1&&(n=90*i+90*l,y.rtl&&(n=90*-i-90*l)),r.transform(p),y.params.cube.slideShadows){var h=s()?r.find(".swiper-slide-shadow-left"):r.find(".swiper-slide-shadow-top"),f=s()?r.find(".swiper-slide-shadow-right"):r.find(".swiper-slide-shadow-bottom");0===h.length&&(h=t('<div class="swiper-slide-shadow-'+(s()?"left":"top")+'"></div>'),r.append(h)),0===f.length&&(f=t('<div class="swiper-slide-shadow-'+(s()?"right":"bottom")+'"></div>'),r.append(f));r[0].progress;h.length&&(h[0].style.opacity=-r[0].progress),f.length&&(f[0].style.opacity=r[0].progress)}}if(y.wrapper.css({"-webkit-transform-origin":"50% 50% -"+y.size/2+"px","-moz-transform-origin":"50% 50% -"+y.size/2+"px","-ms-transform-origin":"50% 50% -"+y.size/2+"px","transform-origin":"50% 50% -"+y.size/2+"px"}),y.params.cube.shadow)if(s())e.transform("translate3d(0px, "+(y.width/2+y.params.cube.shadowOffset)+"px, "+-y.width/2+"px) rotateX(90deg) rotateZ(0deg) scale("+y.params.cube.shadowScale+")");else{var m=Math.abs(n)-90*Math.floor(Math.abs(n)/90),g=1.5-(Math.sin(2*m*Math.PI/360)/2+Math.cos(2*m*Math.PI/360)/2),v=y.params.cube.shadowScale,_=y.params.cube.shadowScale/g,w=y.params.cube.shadowOffset;e.transform("scale3d("+v+", 1, "+_+") translate3d(0px, "+(y.height/2+w)+"px, "+-y.height/2/_+"px) rotateX(-90deg)")}var T=y.isSafari||y.isUiWebView?-y.size/2:0;y.wrapper.transform("translate3d(0px,0,"+T+"px) rotateX("+(s()?0:n)+"deg) rotateY("+(s()?-n:0)+"deg)")},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),y.params.cube.shadow&&!s()&&y.container.find(".swiper-cube-shadow").transition(e)}},coverflow:{setTranslate:function(){for(var e=y.translate,n=s()?-e+y.width/2:-e+y.height/2,i=s()?y.params.coverflow.rotate:-y.params.coverflow.rotate,r=y.params.coverflow.depth,a=0,o=y.slides.length;o>a;a++){var l=y.slides.eq(a),c=y.slidesSizesGrid[a],d=l[0].swiperSlideOffset,u=(n-d-c/2)/c*y.params.coverflow.modifier,p=s()?i*u:0,h=s()?0:i*u,f=-r*Math.abs(u),m=s()?0:y.params.coverflow.stretch*u,g=s()?y.params.coverflow.stretch*u:0;Math.abs(g)<.001&&(g=0),Math.abs(m)<.001&&(m=0),Math.abs(f)<.001&&(f=0),Math.abs(p)<.001&&(p=0),Math.abs(h)<.001&&(h=0);var v="translate3d("+g+"px,"+m+"px,"+f+"px) rotateX("+h+"deg) rotateY("+p+"deg)";if(l.transform(v),l[0].style.zIndex=-Math.abs(Math.round(u))+1,y.params.coverflow.slideShadows){var _=s()?l.find(".swiper-slide-shadow-left"):l.find(".swiper-slide-shadow-top"),w=s()?l.find(".swiper-slide-shadow-right"):l.find(".swiper-slide-shadow-bottom");0===_.length&&(_=t('<div class="swiper-slide-shadow-'+(s()?"left":"top")+'"></div>'),l.append(_)),0===w.length&&(w=t('<div class="swiper-slide-shadow-'+(s()?"right":"bottom")+'"></div>'),l.append(w)),_.length&&(_[0].style.opacity=u>0?u:0),w.length&&(w[0].style.opacity=-u>0?-u:0)}}if(y.browser.ie){var T=y.wrapper[0].style;T.perspectiveOrigin=n+"px 50%"}},setTransition:function(e){y.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)}}},y.lazy={initialImageLoaded:!1,loadImageInSlide:function(e,n){if("undefined"!=typeof e&&("undefined"==typeof n&&(n=!0),0!==y.slides.length)){var i=y.slides.eq(e),r=i.find(".swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)");!i.hasClass("swiper-lazy")||i.hasClass("swiper-lazy-loaded")||i.hasClass("swiper-lazy-loading")||(r=r.add(i[0])),0!==r.length&&r.each(function(){var e=t(this);e.addClass("swiper-lazy-loading");var r=e.attr("data-background"),a=e.attr("data-src"),o=e.attr("data-srcset");y.loadImage(e[0],a||r,o,!1,function(){if(r?(e.css("background-image","url("+r+")"),e.removeAttr("data-background")):(o&&(e.attr("srcset",o),e.removeAttr("data-srcset")),a&&(e.attr("src",a),e.removeAttr("data-src"))),e.addClass("swiper-lazy-loaded").removeClass("swiper-lazy-loading"),i.find(".swiper-lazy-preloader, .preloader").remove(),y.params.loop&&n){var t=i.attr("data-swiper-slide-index");if(i.hasClass(y.params.slideDuplicateClass)){var s=y.wrapper.children('[data-swiper-slide-index="'+t+'"]:not(.'+y.params.slideDuplicateClass+")");y.lazy.loadImageInSlide(s.index(),!1)}else{var l=y.wrapper.children("."+y.params.slideDuplicateClass+'[data-swiper-slide-index="'+t+'"]');y.lazy.loadImageInSlide(l.index(),!1)}}y.emit("onLazyImageReady",y,i[0],e[0])}),y.emit("onLazyImageLoad",y,i[0],e[0])})}},load:function(){var e;if(y.params.watchSlidesVisibility)y.wrapper.children("."+y.params.slideVisibleClass).each(function(){y.lazy.loadImageInSlide(t(this).index())});else if(y.params.slidesPerView>1)for(e=y.activeIndex;e<y.activeIndex+y.params.slidesPerView;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);else y.lazy.loadImageInSlide(y.activeIndex);if(y.params.lazyLoadingInPrevNext)if(y.params.slidesPerView>1){for(e=y.activeIndex+y.params.slidesPerView;e<y.activeIndex+y.params.slidesPerView+y.params.slidesPerView;e++)y.slides[e]&&y.lazy.loadImageInSlide(e);for(e=y.activeIndex-y.params.slidesPerView;e<y.activeIndex;e++)y.slides[e]&&y.lazy.loadImageInSlide(e)}else{var n=y.wrapper.children("."+y.params.slideNextClass);n.length>0&&y.lazy.loadImageInSlide(n.index());var i=y.wrapper.children("."+y.params.slidePrevClass);i.length>0&&y.lazy.loadImageInSlide(i.index())}},onTransitionStart:function(){y.params.lazyLoading&&(y.params.lazyLoadingOnTransitionStart||!y.params.lazyLoadingOnTransitionStart&&!y.lazy.initialImageLoaded)&&y.lazy.load()},onTransitionEnd:function(){y.params.lazyLoading&&!y.params.lazyLoadingOnTransitionStart&&y.lazy.load()}},y.scrollbar={isTouched:!1,setDragPosition:function(e){var t=y.scrollbar,n=s()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageX:e.pageX||e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageY:e.pageY||e.clientY,i=n-t.track.offset()[s()?"left":"top"]-t.dragSize/2,r=-y.minTranslate()*t.moveDivider,a=-y.maxTranslate()*t.moveDivider;r>i?i=r:i>a&&(i=a),i=-i/t.moveDivider,y.updateProgress(i),y.setWrapperTranslate(i,!0)},dragStart:function(e){var t=y.scrollbar;t.isTouched=!0,e.preventDefault(),e.stopPropagation(),t.setDragPosition(e),clearTimeout(t.dragTimeout),t.track.transition(0),y.params.scrollbarHide&&t.track.css("opacity",1),y.wrapper.transition(100),t.drag.transition(100),y.emit("onScrollbarDragStart",y)},dragMove:function(e){var t=y.scrollbar;t.isTouched&&(e.preventDefault?e.preventDefault():e.returnValue=!1,t.setDragPosition(e),y.wrapper.transition(0),t.track.transition(0),t.drag.transition(0),y.emit("onScrollbarDragMove",y))},dragEnd:function(e){var t=y.scrollbar;t.isTouched&&(t.isTouched=!1,y.params.scrollbarHide&&(clearTimeout(t.dragTimeout),t.dragTimeout=setTimeout(function(){t.track.css("opacity",0),t.track.transition(400)},1e3)),y.emit("onScrollbarDragEnd",y),y.params.scrollbarSnapOnRelease&&y.slideReset())},enableDraggable:function(){var e=y.scrollbar,n=y.support.touch?e.track:document;t(e.track).on(y.touchEvents.start,e.dragStart),t(n).on(y.touchEvents.move,e.dragMove),t(n).on(y.touchEvents.end,e.dragEnd)},disableDraggable:function(){var e=y.scrollbar,n=y.support.touch?e.track:document;t(e.track).off(y.touchEvents.start,e.dragStart),t(n).off(y.touchEvents.move,e.dragMove),t(n).off(y.touchEvents.end,e.dragEnd)},set:function(){if(y.params.scrollbar){var e=y.scrollbar;e.track=t(y.params.scrollbar),e.drag=e.track.find(".swiper-scrollbar-drag"),0===e.drag.length&&(e.drag=t('<div class="swiper-scrollbar-drag"></div>'),e.track.append(e.drag)),e.drag[0].style.width="",e.drag[0].style.height="",e.trackSize=s()?e.track[0].offsetWidth:e.track[0].offsetHeight,e.divider=y.size/y.virtualSize,e.moveDivider=e.divider*(e.trackSize/y.size),e.dragSize=e.trackSize*e.divider,s()?e.drag[0].style.width=e.dragSize+"px":e.drag[0].style.height=e.dragSize+"px",e.divider>=1?e.track[0].style.display="none":e.track[0].style.display="",y.params.scrollbarHide&&(e.track[0].style.opacity=0)}},setTranslate:function(){if(y.params.scrollbar){var e,t=y.scrollbar,n=(y.translate||0,t.dragSize);e=(t.trackSize-t.dragSize)*y.progress,y.rtl&&s()?(e=-e,e>0?(n=t.dragSize-e,e=0):-e+t.dragSize>t.trackSize&&(n=t.trackSize+e)):0>e?(n=t.dragSize+e,e=0):e+t.dragSize>t.trackSize&&(n=t.trackSize-e),s()?(y.support.transforms3d?t.drag.transform("translate3d("+e+"px, 0, 0)"):t.drag.transform("translateX("+e+"px)"),t.drag[0].style.width=n+"px"):(y.support.transforms3d?t.drag.transform("translate3d(0px, "+e+"px, 0)"):t.drag.transform("translateY("+e+"px)"),t.drag[0].style.height=n+"px"),y.params.scrollbarHide&&(clearTimeout(t.timeout),t.track[0].style.opacity=1,t.timeout=setTimeout(function(){t.track[0].style.opacity=0,t.track.transition(400)},1e3))}},setTransition:function(e){y.params.scrollbar&&y.scrollbar.drag.transition(e)}},y.controller={LinearSpline:function(e,t){this.x=e,this.y=t,this.lastIndex=e.length-1;var n,i;this.x.length;this.interpolate=function(e){return e?(i=r(this.x,e),n=i-1,(e-this.x[n])*(this.y[i]-this.y[n])/(this.x[i]-this.x[n])+this.y[n]):0};var r=function(){var e,t,n;return function(i,r){for(t=-1,e=i.length;e-t>1;)i[n=e+t>>1]<=r?t=n:e=n;return e}}()},getInterpolateFunction:function(e){y.controller.spline||(y.controller.spline=y.params.loop?new y.controller.LinearSpline(y.slidesGrid,e.slidesGrid):new y.controller.LinearSpline(y.snapGrid,e.snapGrid))},setTranslate:function(e,t){function i(t){e=t.rtl&&"horizontal"===t.params.direction?-y.translate:y.translate,"slide"===y.params.controlBy&&(y.controller.getInterpolateFunction(t),a=-y.controller.spline.interpolate(-e)),a&&"container"!==y.params.controlBy||(r=(t.maxTranslate()-t.minTranslate())/(y.maxTranslate()-y.minTranslate()),a=(e-y.minTranslate())*r+t.minTranslate()),y.params.controlInverse&&(a=t.maxTranslate()-a),t.updateProgress(a),t.setWrapperTranslate(a,!1,y),t.updateActiveIndex()}var r,a,o=y.params.control;if(y.isArray(o))for(var s=0;s<o.length;s++)o[s]!==t&&o[s]instanceof n&&i(o[s]);else o instanceof n&&t!==o&&i(o)},setTransition:function(e,t){function i(t){t.setWrapperTransition(e,y),0!==e&&(t.onTransitionStart(),t.wrapper.transitionEnd(function(){a&&(t.params.loop&&"slide"===y.params.controlBy&&t.fixLoop(),t.onTransitionEnd())}))}var r,a=y.params.control;if(y.isArray(a))for(r=0;r<a.length;r++)a[r]!==t&&a[r]instanceof n&&i(a[r]);else a instanceof n&&t!==a&&i(a)}},y.hashnav={init:function(){if(y.params.hashnav){y.hashnav.initialized=!0;var e=document.location.hash.replace("#","");if(e)for(var t=0,n=0,i=y.slides.length;i>n;n++){var r=y.slides.eq(n),a=r.attr("data-hash");if(a===e&&!r.hasClass(y.params.slideDuplicateClass)){var o=r.index();y.slideTo(o,t,y.params.runCallbacksOnInit,!0)}}}},setHash:function(){y.hashnav.initialized&&y.params.hashnav&&(document.location.hash=y.slides.eq(y.activeIndex).attr("data-hash")||"")}},y.disableKeyboardControl=function(){y.params.keyboardControl=!1,t(document).off("keydown",p)},y.enableKeyboardControl=function(){y.params.keyboardControl=!0,t(document).on("keydown",p)},y.mousewheel={event:!1,lastScrollTime:(new window.Date).getTime()},y.params.mousewheelControl){try{new window.WheelEvent("wheel"),y.mousewheel.event="wheel"}catch(H){}y.mousewheel.event||void 0===document.onmousewheel||(y.mousewheel.event="mousewheel"),y.mousewheel.event||(y.mousewheel.event="DOMMouseScroll")}y.disableMousewheelControl=function(){return y.mousewheel.event?(y.container.off(y.mousewheel.event,h),!0):!1},y.enableMousewheelControl=function(){return y.mousewheel.event?(y.container.on(y.mousewheel.event,h),!0):!1},y.parallax={setTranslate:function(){y.container.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){f(this,y.progress)}),y.slides.each(function(){var e=t(this);e.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var t=Math.min(Math.max(e[0].progress,-1),1);f(this,t)})})},setTransition:function(e){"undefined"==typeof e&&(e=y.params.speed),y.container.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var n=t(this),i=parseInt(n.attr("data-swiper-parallax-duration"),10)||e;0===e&&(i=0),n.transition(i)})}},y._plugins=[];for(var Y in y.plugins){var X=y.plugins[Y](y,y.params[Y]);X&&y._plugins.push(X)}return y.callPlugins=function(e){for(var t=0;t<y._plugins.length;t++)e in y._plugins[t]&&y._plugins[t][e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.emitterEventListeners={},y.emit=function(e){y.params[e]&&y.params[e](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);var t;if(y.emitterEventListeners[e])for(t=0;t<y.emitterEventListeners[e].length;t++)y.emitterEventListeners[e][t](arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]);y.callPlugins&&y.callPlugins(e,arguments[1],arguments[2],arguments[3],arguments[4],arguments[5])},y.on=function(e,t){return e=m(e),y.emitterEventListeners[e]||(y.emitterEventListeners[e]=[]),y.emitterEventListeners[e].push(t),y},y.off=function(e,t){var n;if(e=m(e),"undefined"==typeof t)return y.emitterEventListeners[e]=[],y;if(y.emitterEventListeners[e]&&0!==y.emitterEventListeners[e].length){for(n=0;n<y.emitterEventListeners[e].length;n++)y.emitterEventListeners[e][n]===t&&y.emitterEventListeners[e].splice(n,1);return y}},y.once=function(e,t){e=m(e);var n=function(){t(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]),y.off(e,n)};return y.on(e,n),y},y.a11y={makeFocusable:function(e){return e.attr("tabIndex","0"),e},addRole:function(e,t){return e.attr("role",t),e},addLabel:function(e,t){return e.attr("aria-label",t),e},disable:function(e){return e.attr("aria-disabled",!0),e},enable:function(e){return e.attr("aria-disabled",!1),e},onEnterKey:function(e){13===e.keyCode&&(t(e.target).is(y.params.nextButton)?(y.onClickNext(e),y.isEnd?y.a11y.notify(y.params.lastSlideMessage):y.a11y.notify(y.params.nextSlideMessage)):t(e.target).is(y.params.prevButton)&&(y.onClickPrev(e),y.isBeginning?y.a11y.notify(y.params.firstSlideMessage):y.a11y.notify(y.params.prevSlideMessage)),t(e.target).is("."+y.params.bulletClass)&&t(e.target)[0].click())},liveRegion:t('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'),notify:function(e){var t=y.a11y.liveRegion;0!==t.length&&(t.html(""),t.html(e))},init:function(){if(y.params.nextButton){var e=t(y.params.nextButton);y.a11y.makeFocusable(e),y.a11y.addRole(e,"button"),y.a11y.addLabel(e,y.params.nextSlideMessage)}if(y.params.prevButton){var n=t(y.params.prevButton);y.a11y.makeFocusable(n),y.a11y.addRole(n,"button"),y.a11y.addLabel(n,y.params.prevSlideMessage)}t(y.container).append(y.a11y.liveRegion)},initPagination:function(){y.params.pagination&&y.params.paginationClickable&&y.bullets&&y.bullets.length&&y.bullets.each(function(){var e=t(this);y.a11y.makeFocusable(e),y.a11y.addRole(e,"button"),y.a11y.addLabel(e,y.params.paginationBulletMessage.replace(/{{index}}/,e.index()+1))})},destroy:function(){y.a11y.liveRegion&&y.a11y.liveRegion.length>0&&y.a11y.liveRegion.remove()}},y.init=function(){y.params.loop&&y.createLoop(),y.updateContainerSize(),y.updateSlidesSize(),y.updatePagination(),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.set(),y.params.scrollbarDraggable&&y.scrollbar.enableDraggable()),"slide"!==y.params.effect&&y.effects[y.params.effect]&&(y.params.loop||y.updateProgress(),y.effects[y.params.effect].setTranslate()),y.params.loop?y.slideTo(y.params.initialSlide+y.loopedSlides,0,y.params.runCallbacksOnInit):(y.slideTo(y.params.initialSlide,0,y.params.runCallbacksOnInit),0===y.params.initialSlide&&(y.parallax&&y.params.parallax&&y.parallax.setTranslate(),y.lazy&&y.params.lazyLoading&&(y.lazy.load(),y.lazy.initialImageLoaded=!0))),y.attachEvents(),y.params.observer&&y.support.observer&&y.initObservers(),y.params.preloadImages&&!y.params.lazyLoading&&y.preloadImages(),y.params.autoplay&&y.startAutoplay(),y.params.keyboardControl&&y.enableKeyboardControl&&y.enableKeyboardControl(),y.params.mousewheelControl&&y.enableMousewheelControl&&y.enableMousewheelControl(),y.params.hashnav&&y.hashnav&&y.hashnav.init(),y.params.a11y&&y.a11y&&y.a11y.init(),y.emit("onInit",y)},y.cleanupStyles=function(){y.container.removeClass(y.classNames.join(" ")).removeAttr("style"),y.wrapper.removeAttr("style"),y.slides&&y.slides.length&&y.slides.removeClass([y.params.slideVisibleClass,y.params.slideActiveClass,y.params.slideNextClass,y.params.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-column").removeAttr("data-swiper-row"),y.paginationContainer&&y.paginationContainer.length&&y.paginationContainer.removeClass(y.params.paginationHiddenClass),y.bullets&&y.bullets.length&&y.bullets.removeClass(y.params.bulletActiveClass),y.params.prevButton&&t(y.params.prevButton).removeClass(y.params.buttonDisabledClass),y.params.nextButton&&t(y.params.nextButton).removeClass(y.params.buttonDisabledClass),y.params.scrollbar&&y.scrollbar&&(y.scrollbar.track&&y.scrollbar.track.length&&y.scrollbar.track.removeAttr("style"),y.scrollbar.drag&&y.scrollbar.drag.length&&y.scrollbar.drag.removeAttr("style"))},y.destroy=function(e,t){y.detachEvents(),y.stopAutoplay(),y.params.scrollbar&&y.scrollbar&&y.params.scrollbarDraggable&&y.scrollbar.disableDraggable(),y.params.loop&&y.destroyLoop(),t&&y.cleanupStyles(),y.disconnectObservers(),y.params.keyboardControl&&y.disableKeyboardControl&&y.disableKeyboardControl(),y.params.mousewheelControl&&y.disableMousewheelControl&&y.disableMousewheelControl(),y.params.a11y&&y.a11y&&y.a11y.destroy(),y.emit("onDestroy"),e!==!1&&(y=null)},y.init(),y}};n.prototype={isSafari:function(){var e=navigator.userAgent.toLowerCase();return e.indexOf("safari")>=0&&e.indexOf("chrome")<0&&e.indexOf("android")<0}(),isUiWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent),isArray:function(e){return"[object Array]"===Object.prototype.toString.apply(e)},browser:{ie:window.navigator.pointerEnabled||window.navigator.msPointerEnabled,ieTouch:window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>1||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>1},device:function(){var e=navigator.userAgent,t=e.match(/(Android);?[\s\/]+([\d.]+)?/),n=e.match(/(iPad).*OS\s([\d_]+)/),i=e.match(/(iPod)(.*OS\s([\d_]+))?/),r=!n&&e.match(/(iPhone\sOS)\s([\d_]+)/);return{ios:n||r||i,android:t}}(),support:{touch:window.Modernizr&&Modernizr.touch===!0||function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)}(),transforms3d:window.Modernizr&&Modernizr.csstransforms3d===!0||function(){var e=document.createElement("div").style;return"webkitPerspective"in e||"MozPerspective"in e||"OPerspective"in e||"MsPerspective"in e||"perspective"in e}(),flexbox:function(){for(var e=document.createElement("div").style,t="alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient".split(" "),n=0;n<t.length;n++)if(t[n]in e)return!0}(),observer:function(){return"MutationObserver"in window||"WebkitMutationObserver"in window}()},plugins:{}};for(var i=(function(){var e=function(e){var t=this,n=0;for(n=0;n<e.length;n++)t[n]=e[n];return t.length=e.length,this},t=function(t,n){var i=[],r=0;if(t&&!n&&t instanceof e)return t;if(t)if("string"==typeof t){var a,o,s=t.trim();if(s.indexOf("<")>=0&&s.indexOf(">")>=0){var l="div";for(0===s.indexOf("<li")&&(l="ul"),0===s.indexOf("<tr")&&(l="tbody"),(0===s.indexOf("<td")||0===s.indexOf("<th"))&&(l="tr"),0===s.indexOf("<tbody")&&(l="table"),0===s.indexOf("<option")&&(l="select"),o=document.createElement(l),o.innerHTML=t,r=0;r<o.childNodes.length;r++)i.push(o.childNodes[r])}else for(a=n||"#"!==t[0]||t.match(/[ .<>:~]/)?(n||document).querySelectorAll(t):[document.getElementById(t.split("#")[1])],r=0;r<a.length;r++)a[r]&&i.push(a[r])}else if(t.nodeType||t===window||t===document)i.push(t);else if(t.length>0&&t[0].nodeType)for(r=0;r<t.length;r++)i.push(t[r]);return new e(i)};return e.prototype={addClass:function(e){if("undefined"==typeof e)return this;for(var t=e.split(" "),n=0;n<t.length;n++)for(var i=0;i<this.length;i++)this[i].classList.add(t[n]);return this},removeClass:function(e){for(var t=e.split(" "),n=0;n<t.length;n++)for(var i=0;i<this.length;i++)this[i].classList.remove(t[n]);return this},hasClass:function(e){return this[0]?this[0].classList.contains(e):!1},toggleClass:function(e){for(var t=e.split(" "),n=0;n<t.length;n++)for(var i=0;i<this.length;i++)this[i].classList.toggle(t[n]);return this},attr:function(e,t){if(1===arguments.length&&"string"==typeof e)return this[0]?this[0].getAttribute(e):void 0;for(var n=0;n<this.length;n++)if(2===arguments.length)this[n].setAttribute(e,t);else for(var i in e)this[n][i]=e[i],this[n].setAttribute(i,e[i]);return this},removeAttr:function(e){for(var t=0;t<this.length;t++)this[t].removeAttribute(e);return this},data:function(e,t){if("undefined"==typeof t){if(this[0]){var n=this[0].getAttribute("data-"+e);return n?n:this[0].dom7ElementDataStorage&&e in this[0].dom7ElementDataStorage?this[0].dom7ElementDataStorage[e]:void 0}return void 0}for(var i=0;i<this.length;i++){var r=this[i];r.dom7ElementDataStorage||(r.dom7ElementDataStorage={}),r.dom7ElementDataStorage[e]=t}return this},transform:function(e){for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransform=n.MsTransform=n.msTransform=n.MozTransform=n.OTransform=n.transform=e}return this},transition:function(e){"string"!=typeof e&&(e+="ms");for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransitionDuration=n.MsTransitionDuration=n.msTransitionDuration=n.MozTransitionDuration=n.OTransitionDuration=n.transitionDuration=e}return this},on:function(e,n,i,r){function a(e){var r=e.target;if(t(r).is(n))i.call(r,e);else for(var a=t(r).parents(),o=0;o<a.length;o++)t(a[o]).is(n)&&i.call(a[o],e)}var o,s,l=e.split(" ");for(o=0;o<this.length;o++)if("function"==typeof n||n===!1)for("function"==typeof n&&(i=arguments[1],r=arguments[2]||!1),s=0;s<l.length;s++)this[o].addEventListener(l[s],i,r);else for(s=0;s<l.length;s++)this[o].dom7LiveListeners||(this[o].dom7LiveListeners=[]),this[o].dom7LiveListeners.push({listener:i,liveListener:a}),this[o].addEventListener(l[s],a,r);return this},off:function(e,t,n,i){for(var r=e.split(" "),a=0;a<r.length;a++)for(var o=0;o<this.length;o++)if("function"==typeof t||t===!1)"function"==typeof t&&(n=arguments[1],i=arguments[2]||!1),this[o].removeEventListener(r[a],n,i);else if(this[o].dom7LiveListeners)for(var s=0;s<this[o].dom7LiveListeners.length;s++)this[o].dom7LiveListeners[s].listener===n&&this[o].removeEventListener(r[a],this[o].dom7LiveListeners[s].liveListener,i);return this},once:function(e,t,n,i){function r(o){n(o),a.off(e,t,r,i)}var a=this;"function"==typeof t&&(t=!1,n=arguments[1],i=arguments[2]),a.on(e,t,r,i)},trigger:function(e,t){for(var n=0;n<this.length;n++){var i;try{i=new window.CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0})}catch(r){i=document.createEvent("Event"),i.initEvent(e,!0,!0),i.detail=t}this[n].dispatchEvent(i)}return this},transitionEnd:function(e){function t(a){if(a.target===this)for(e.call(this,a),n=0;n<i.length;n++)r.off(i[n],t)}var n,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],r=this;if(e)for(n=0;n<i.length;n++)r.on(i[n],t);return this},width:function(){return this[0]===window?window.innerWidth:this.length>0?parseFloat(this.css("width")):null},outerWidth:function(e){return this.length>0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null},height:function(){return this[0]===window?window.innerHeight:this.length>0?parseFloat(this.css("height")):null},outerHeight:function(e){return this.length>0?e?this[0].offsetHeight+parseFloat(this.css("margin-top"))+parseFloat(this.css("margin-bottom")):this[0].offsetHeight:null},offset:function(){if(this.length>0){var e=this[0],t=e.getBoundingClientRect(),n=document.body,i=e.clientTop||n.clientTop||0,r=e.clientLeft||n.clientLeft||0,a=window.pageYOffset||e.scrollTop,o=window.pageXOffset||e.scrollLeft;return{top:t.top+a-i,left:t.left+o-r}}return null},css:function(e,t){var n;if(1===arguments.length){if("string"!=typeof e){for(n=0;n<this.length;n++)for(var i in e)this[n].style[i]=e[i];return this}if(this[0])return window.getComputedStyle(this[0],null).getPropertyValue(e)}if(2===arguments.length&&"string"==typeof e){for(n=0;n<this.length;n++)this[n].style[e]=t;return this}return this},each:function(e){for(var t=0;t<this.length;t++)e.call(this[t],t,this[t]);return this},html:function(e){if("undefined"==typeof e)return this[0]?this[0].innerHTML:void 0;for(var t=0;t<this.length;t++)this[t].innerHTML=e;return this},is:function(n){if(!this[0])return!1;var i,r;if("string"==typeof n){var a=this[0];if(a===document)return n===document;if(a===window)return n===window;if(a.matches)return a.matches(n);if(a.webkitMatchesSelector)return a.webkitMatchesSelector(n);if(a.mozMatchesSelector)return a.mozMatchesSelector(n);if(a.msMatchesSelector)return a.msMatchesSelector(n);for(i=t(n),r=0;r<i.length;r++)if(i[r]===this[0])return!0;return!1}if(n===document)return this[0]===document;if(n===window)return this[0]===window;if(n.nodeType||n instanceof e){for(i=n.nodeType?[n]:n,r=0;r<i.length;r++)if(i[r]===this[0])return!0;return!1}return!1},index:function(){if(this[0]){for(var e=this[0],t=0;null!==(e=e.previousSibling);)1===e.nodeType&&t++;return t}return void 0},eq:function(t){if("undefined"==typeof t)return this;var n,i=this.length;return t>i-1?new e([]):0>t?(n=i+t,new e(0>n?[]:[this[n]])):new e([this[t]])},append:function(t){var n,i;for(n=0;n<this.length;n++)if("string"==typeof t){var r=document.createElement("div");for(r.innerHTML=t;r.firstChild;)this[n].appendChild(r.firstChild)}else if(t instanceof e)for(i=0;i<t.length;i++)this[n].appendChild(t[i]);else this[n].appendChild(t);return this},prepend:function(t){var n,i;for(n=0;n<this.length;n++)if("string"==typeof t){var r=document.createElement("div");for(r.innerHTML=t,i=r.childNodes.length-1;i>=0;i--)this[n].insertBefore(r.childNodes[i],this[n].childNodes[0])}else if(t instanceof e)for(i=0;i<t.length;i++)this[n].insertBefore(t[i],this[n].childNodes[0]);else this[n].insertBefore(t,this[n].childNodes[0]); +return this},insertBefore:function(e){for(var n=t(e),i=0;i<this.length;i++)if(1===n.length)n[0].parentNode.insertBefore(this[i],n[0]);else if(n.length>1)for(var r=0;r<n.length;r++)n[r].parentNode.insertBefore(this[i].cloneNode(!0),n[r])},insertAfter:function(e){for(var n=t(e),i=0;i<this.length;i++)if(1===n.length)n[0].parentNode.insertBefore(this[i],n[0].nextSibling);else if(n.length>1)for(var r=0;r<n.length;r++)n[r].parentNode.insertBefore(this[i].cloneNode(!0),n[r].nextSibling)},next:function(n){return new e(this.length>0?n?this[0].nextElementSibling&&t(this[0].nextElementSibling).is(n)?[this[0].nextElementSibling]:[]:this[0].nextElementSibling?[this[0].nextElementSibling]:[]:[])},nextAll:function(n){var i=[],r=this[0];if(!r)return new e([]);for(;r.nextElementSibling;){var a=r.nextElementSibling;n?t(a).is(n)&&i.push(a):i.push(a),r=a}return new e(i)},prev:function(n){return new e(this.length>0?n?this[0].previousElementSibling&&t(this[0].previousElementSibling).is(n)?[this[0].previousElementSibling]:[]:this[0].previousElementSibling?[this[0].previousElementSibling]:[]:[])},prevAll:function(n){var i=[],r=this[0];if(!r)return new e([]);for(;r.previousElementSibling;){var a=r.previousElementSibling;n?t(a).is(n)&&i.push(a):i.push(a),r=a}return new e(i)},parent:function(e){for(var n=[],i=0;i<this.length;i++)e?t(this[i].parentNode).is(e)&&n.push(this[i].parentNode):n.push(this[i].parentNode);return t(t.unique(n))},parents:function(e){for(var n=[],i=0;i<this.length;i++)for(var r=this[i].parentNode;r;)e?t(r).is(e)&&n.push(r):n.push(r),r=r.parentNode;return t(t.unique(n))},find:function(t){for(var n=[],i=0;i<this.length;i++)for(var r=this[i].querySelectorAll(t),a=0;a<r.length;a++)n.push(r[a]);return new e(n)},children:function(n){for(var i=[],r=0;r<this.length;r++)for(var a=this[r].childNodes,o=0;o<a.length;o++)n?1===a[o].nodeType&&t(a[o]).is(n)&&i.push(a[o]):1===a[o].nodeType&&i.push(a[o]);return new e(t.unique(i))},remove:function(){for(var e=0;e<this.length;e++)this[e].parentNode&&this[e].parentNode.removeChild(this[e]);return this},add:function(){var e,n,i=this;for(e=0;e<arguments.length;e++){var r=t(arguments[e]);for(n=0;n<r.length;n++)i[i.length]=r[n],i.length++}return i}},t.fn=e.prototype,t.unique=function(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t},t}()),r=["jQuery","Zepto","Dom7"],a=0;a<r.length;a++)window[r[a]]&&e(window[r[a]]);var o;o="undefined"==typeof i?window.Dom7||window.Zepto||window.jQuery:i,o&&("transitionEnd"in o.fn||(o.fn.transitionEnd=function(e){function t(a){if(a.target===this)for(e.call(this,a),n=0;n<i.length;n++)r.off(i[n],t)}var n,i=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],r=this;if(e)for(n=0;n<i.length;n++)r.on(i[n],t);return this}),"transform"in o.fn||(o.fn.transform=function(e){for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransform=n.MsTransform=n.msTransform=n.MozTransform=n.OTransform=n.transform=e}return this}),"transition"in o.fn||(o.fn.transition=function(e){"string"!=typeof e&&(e+="ms");for(var t=0;t<this.length;t++){var n=this[t].style;n.webkitTransitionDuration=n.MsTransitionDuration=n.msTransitionDuration=n.MozTransitionDuration=n.OTransitionDuration=n.transitionDuration=e}return this})),ionic.views.Swiper=n}(),function(e){"use strict";e.views.Toggle=e.views.View.inherit({initialize:function(t){var n=this;this.el=t.el,this.checkbox=t.checkbox,this.track=t.track,this.handle=t.handle,this.openPercent=-1,this.onChange=t.onChange||function(){},this.triggerThreshold=t.triggerThreshold||20,this.dragStartHandler=function(e){n.dragStart(e)},this.dragHandler=function(e){n.drag(e)},this.holdHandler=function(e){n.hold(e)},this.releaseHandler=function(e){n.release(e)},this.dragStartGesture=e.onGesture("dragstart",this.dragStartHandler,this.el),this.dragGesture=e.onGesture("drag",this.dragHandler,this.el),this.dragHoldGesture=e.onGesture("hold",this.holdHandler,this.el),this.dragReleaseGesture=e.onGesture("release",this.releaseHandler,this.el)},destroy:function(){e.offGesture(this.dragStartGesture,"dragstart",this.dragStartGesture),e.offGesture(this.dragGesture,"drag",this.dragGesture),e.offGesture(this.dragHoldGesture,"hold",this.holdHandler),e.offGesture(this.dragReleaseGesture,"release",this.releaseHandler)},tap:function(){"disabled"!==this.el.getAttribute("disabled")&&this.val(!this.checkbox.checked)},dragStart:function(e){this.checkbox.disabled||(this._dragInfo={width:this.el.offsetWidth,left:this.el.offsetLeft,right:this.el.offsetLeft+this.el.offsetWidth,triggerX:this.el.offsetWidth/2,initialState:this.checkbox.checked},e.gesture.srcEvent.preventDefault(),this.hold(e))},drag:function(t){var n=this;this._dragInfo&&(t.gesture.srcEvent.preventDefault(),e.requestAnimationFrame(function(){if(n._dragInfo){var e=t.gesture.touches[0].pageX-n._dragInfo.left,i=n._dragInfo.width-n.triggerThreshold;n._dragInfo.initialState?e<n.triggerThreshold?n.setOpenPercent(0):e>n._dragInfo.triggerX&&n.setOpenPercent(100):e<n._dragInfo.triggerX?n.setOpenPercent(0):e>i&&n.setOpenPercent(100)}}))},endDrag:function(){this._dragInfo=null},hold:function(){this.el.classList.add("dragging")},release:function(e){this.el.classList.remove("dragging"),this.endDrag(e)},setOpenPercent:function(t){if(this.openPercent<0||t<this.openPercent-3||t>this.openPercent+3)if(this.openPercent=t,0===t)this.val(!1);else if(100===t)this.val(!0);else{var n=Math.round(t/100*this.track.offsetWidth-this.handle.offsetWidth);n=1>n?0:n,this.handle.style[e.CSS.TRANSFORM]="translate3d("+n+"px,0,0)"}},val:function(t){return(t===!0||t===!1)&&(""!==this.handle.style[e.CSS.TRANSFORM]&&(this.handle.style[e.CSS.TRANSFORM]=""),this.checkbox.checked=t,this.openPercent=t?100:0,this.onChange&&this.onChange()),this.checkbox.checked}})}(ionic)}(); \ No newline at end of file diff --git a/www/lib/ionic/scss/_bar.scss b/www/lib/ionic/scss/_bar.scss index ca9fdceb48d69d2f8077910c67c8e4c4f9569208..a6147d89ea22f7020607d61aaadd3caa8a64607d 100644 --- a/www/lib/ionic/scss/_bar.scss +++ b/www/lib/ionic/scss/_bar.scss @@ -123,6 +123,7 @@ // Title inside of a bar is centered .title { + display: block; position: absolute; top: 0; @@ -159,7 +160,7 @@ color: inherit; } - .button { + .button, button { z-index: $z-index-bar-button; padding: 0 $button-bar-button-padding; min-width: initial; @@ -401,4 +402,3 @@ .nav-bar-tabs-top .bar { background-image: none; } - diff --git a/www/lib/ionic/scss/_button-bar.scss b/www/lib/ionic/scss/_button-bar.scss index 0f0dc5197aafe73735829aaf5b271d834c54c192..57bb9c412ab085c191befeb758b99ac4834df712 100644 --- a/www/lib/ionic/scss/_button-bar.scss +++ b/www/lib/ionic/scss/_button-bar.scss @@ -51,6 +51,9 @@ border-right-width: 1px; border-radius: 0px $button-border-radius $button-border-radius 0px; } + &:only-child { + border-radius: $button-border-radius; + } } .button-bar > .button-small { diff --git a/www/lib/ionic/scss/_checkbox.scss b/www/lib/ionic/scss/_checkbox.scss index eb903ad0e8234ee3d1532e9ba97018c31245ebea..8321195aa52d2fd2b6befe8a5d7c4785a6269b43 100644 --- a/www/lib/ionic/scss/_checkbox.scss +++ b/www/lib/ionic/scss/_checkbox.scss @@ -127,6 +127,10 @@ input:checked + .checkbox-icon:before { height: 7px; } +.platform-android .item-checkbox-right .checkbox-square .checkbox-icon::after { + top: 31%; +} + .grade-c .checkbox input:after, .grade-c .checkbox-icon:after { @include rotate(0); diff --git a/www/lib/ionic/scss/_form.scss b/www/lib/ionic/scss/_form.scss index 5e22af52baecfd98aaac60dcb28885ce62db2fa6..288f633ded75bcb6b729ea00ab07620116c25614 100644 --- a/www/lib/ionic/scss/_form.scss +++ b/www/lib/ionic/scss/_form.scss @@ -156,6 +156,15 @@ textarea { height: $line-height-computed + $font-size-base + 12px; } +.item-select.item-stacked-label select { + position: relative; + padding: 0px; + max-width: 90%; + direction:ltr; + white-space: pre-wrap; + margin: -3px; +} + .item-floating-label { display: block; background-color: transparent; diff --git a/www/lib/ionic/scss/_grid.scss b/www/lib/ionic/scss/_grid.scss index 9129c42d836c5f8247102bd46cf07804e339b222..cb3a97b5b71c104d30219484b1812222397b4985 100644 --- a/www/lib/ionic/scss/_grid.scss +++ b/www/lib/ionic/scss/_grid.scss @@ -118,10 +118,18 @@ @include flex(0, 0, 33.3333%); max-width: 33.3333%; } +.col-40 { + @include flex(0, 0, 40%); + max-width: 40%; +} .col-50 { @include flex(0, 0, 50%); max-width: 50%; } +.col-60 { + @include flex(0, 0, 60%); + max-width: 60%; +} .col-66, .col-67 { @include flex(0, 0, 66.6666%); max-width: 66.6666%; diff --git a/www/lib/ionic/scss/_menu.scss b/www/lib/ionic/scss/_menu.scss index c2bf286a69ff119b76e4c2cb204bfae676d45b71..174667586b45f2aa67308a17c0280b560d4e003a 100644 --- a/www/lib/ionic/scss/_menu.scss +++ b/www/lib/ionic/scss/_menu.scss @@ -36,6 +36,12 @@ .menu-open .menu-content .scroll-content { pointer-events: none; } +.menu-open .menu-content .scroll-content .scroll { + pointer-events: none; +} +.menu-open .menu-content .scroll-content:not(.overflow-scroll) { + overflow: hidden; +} .grade-b .menu-content, .grade-c .menu-content { diff --git a/www/lib/ionic/scss/_mixins.scss b/www/lib/ionic/scss/_mixins.scss index b025ea905edc44ef7989e16e35f3ef944c62588a..c584a98a6d5cb301d624b427c1c72cf7e5e832a8 100644 --- a/www/lib/ionic/scss/_mixins.scss +++ b/www/lib/ionic/scss/_mixins.scss @@ -3,7 +3,7 @@ // -------------------------------------------------- @mixin button-style($bg-color, $border-color, $active-bg-color, $active-border-color, $color) { - border-color: $border-color; + border-color: transparent;//$border-color; background-color: $bg-color; color: $color; @@ -14,9 +14,9 @@ } &.active, &.activated { - border-color: $active-border-color; + //border-color: transparent;//$active-border-color; background-color: $active-bg-color; - box-shadow: inset 0 1px 4px rgba(0,0,0,0.1); + //box-shadow: inset 0 1px 4px rgba(0,0,0,0.1); } } @@ -100,6 +100,10 @@ @mixin item-active-style($active-bg-color, $active-border-color) { border-color: $active-border-color; background-color: $active-bg-color; + &.item-complex > .item-content { + border-color: $active-border-color; + background-color: $active-bg-color; + } } diff --git a/www/lib/ionic/scss/_popover.scss b/www/lib/ionic/scss/_popover.scss index 77025f400b3f42cc40e91bee6ae9808e3eb81d5b..00c150866abe19bdf58a4b1c991ef16a6b28e47e 100644 --- a/www/lib/ionic/scss/_popover.scss +++ b/www/lib/ionic/scss/_popover.scss @@ -163,5 +163,6 @@ @media (min-width: $popover-large-break-point) { .popover { width: $popover-large-width; + margin-left: -$popover-large-width / 2; } } diff --git a/www/lib/ionic/scss/_radio.scss b/www/lib/ionic/scss/_radio.scss index 0f75fa12aded182847e619ccb46e4431cf20b040..fa401c06e576d2f861da6814772899ad86c5cf4d 100644 --- a/www/lib/ionic/scss/_radio.scss +++ b/www/lib/ionic/scss/_radio.scss @@ -34,24 +34,14 @@ position: absolute; left: -9999px; - &:checked ~ .item-content { + &:checked + .radio-content .item-content { /* style the item content when its checked */ background: #f7f7f7; } - &:checked ~ .radio-icon { + &:checked + .radio-content .radio-icon { /* show the checkmark icon when its checked */ visibility: visible; } } -// Hack for Android to correctly display the checked item -// http://timpietrusky.com/advanced-checkbox-hack -.platform-android.grade-b .item-radio, -.platform-android.grade-c .item-radio { - -webkit-animation: androidCheckedbugfix infinite 1s; -} -@-webkit-keyframes androidCheckedbugfix { - from { padding: 0; } - to { padding: 0; } -} diff --git a/www/lib/ionic/scss/_range.scss b/www/lib/ionic/scss/_range.scss index cf531803c1447033f8c666e6f86f730dbf86df5a..54d4e187379e81b30236b21f471ff7c7dbdfb00f 100644 --- a/www/lib/ionic/scss/_range.scss +++ b/www/lib/ionic/scss/_range.scss @@ -21,6 +21,11 @@ background-repeat: no-repeat; -webkit-appearance: none; + &::-moz-focus-outer { + /* hide the focus outline in Firefox */ + border: 0; + } + &::-webkit-slider-thumb { position: relative; width: $range-slider-width; @@ -54,6 +59,11 @@ //background: red; //opacity: .5; } + &::-ms-fill-lower{ + height: $range-track-height; + background:$dark; + } + /* &::-ms-track{ background: transparent; border-color: transparent; @@ -72,14 +82,11 @@ margin-right:1px; outline:none; } - &::-ms-fill-lower{ - height: $range-track-height; - background:$dark; - } &::-ms-fill-upper { height: $range-track-height; background:$range-default-track-bg; } + */ } .range { @@ -150,4 +157,4 @@ .range input{ height:auto; } -} \ No newline at end of file +} diff --git a/www/lib/ionic/scss/_refresher.scss b/www/lib/ionic/scss/_refresher.scss index a6dbd29e903fb9cb4a42cb2764cdc99631eaf233..a3bfd1857677f4cecbdf3fb503ce9eb0ca9161fa 100644 --- a/www/lib/ionic/scss/_refresher.scss +++ b/www/lib/ionic/scss/_refresher.scss @@ -82,11 +82,16 @@ .overflow-scroll > .scroll{ &.overscroll{ position:fixed; + right: 0; + left: 0; } -webkit-overflow-scrolling:touch; width:100%; } +.overflow-scroll.padding > .scroll.overscroll{ + padding: 10px; +} @-webkit-keyframes refresh-spin { 0% { -webkit-transform: translate3d(0,0,0) rotate(0); } 100% { -webkit-transform: translate3d(0,0,0) rotate(180deg); } diff --git a/www/lib/ionic/scss/_scaffolding.scss b/www/lib/ionic/scss/_scaffolding.scss index 4c768c9f5fc3451d8472554a74369cb2fdd0db3c..d1caf7ab71dee1a8d01287a894cdaf651e9dad93 100644 --- a/www/lib/ionic/scss/_scaffolding.scss +++ b/www/lib/ionic/scss/_scaffolding.scss @@ -36,6 +36,7 @@ body, color: $base-color; word-wrap: break-word; font-size: $font-size-base; + font-family: -apple-system; font-family: $font-family-base; line-height: $line-height-computed; text-rendering: optimizeLegibility; @@ -83,6 +84,14 @@ body.grade-c { display: block; overflow: hidden; + &.overflow-scroll { + position: relative; + } + + &.scroll-x { overflow-x: scroll; overflow-y: hidden; } + &.scroll-y { overflow-x: hidden; overflow-y: scroll; } + &.scroll-xy { overflow-x: scroll; overflow-y: scroll; } + // Hide the top border if any margin-top: -1px; } @@ -185,17 +194,30 @@ ion-infinite-scroll { overflow-x: hidden; overflow-y: scroll; -webkit-overflow-scrolling: touch; + + // Make sure the scrollbar doesn't take up layout space on edge + -ms-overflow-style: -ms-autohiding-scrollbar; + top: 0; right: 0; bottom: 0; left: 0; position: absolute; + &.pane { + overflow-x: hidden; + overflow-y: scroll; + } + .scroll { position: static; height: 100%; -webkit-transform: translate3d(0, 0, 0); // fix iOS bug where relative children of scroller disapear while scrolling. see: http://stackoverflow.com/questions/9807620/ipad-safari-scrolling-causes-html-elements-to-disappear-and-reappear-with-a-dela } + + &.keyboard-up:not(.keyboard-up-confirm) { + overflow: hidden; + } } @@ -236,6 +258,10 @@ ion-infinite-scroll { } } +.bar-subfooter.has-tabs { + bottom: $tabs-height + $bar-footer-height; +} + .has-footer.has-tabs { bottom: $tabs-height + $bar-footer-height; } diff --git a/www/lib/ionic/scss/_select.scss b/www/lib/ionic/scss/_select.scss index a3bc34fc178985580acdde0fbcdb29445aed1221..02efaff681e86a4dae3796c0464bce1d957749a4 100644 --- a/www/lib/ionic/scss/_select.scss +++ b/www/lib/ionic/scss/_select.scss @@ -13,7 +13,7 @@ top: 0; bottom: 0; right: 0; - padding: ($item-padding - 2) ($item-padding * 3) ($item-padding) $item-padding; + padding: 0 ($item-padding * 3) 0 $item-padding; max-width: 65%; border: none; diff --git a/www/lib/ionic/scss/_slide-box.scss b/www/lib/ionic/scss/_slide-box.scss index f6dfa113a091949f73efb4d3a64a0e06c47a540c..f3da4d3ee97444c3099f9d829f11a92544c58edf 100644 --- a/www/lib/ionic/scss/_slide-box.scss +++ b/www/lib/ionic/scss/_slide-box.scss @@ -54,3 +54,18 @@ } } } + +//Disable animate service animations +.slider-slide, +.slider-pager-page { + &.ng-enter, + &.ng-leave, + &.ng-animate { + -webkit-transition: none !important; + transition: none !important; + } + &.ng-animate { + -webkit-animation: none 0s; + animation: none 0s; + } +} diff --git a/www/lib/ionic/scss/_slides.scss b/www/lib/ionic/scss/_slides.scss new file mode 100644 index 0000000000000000000000000000000000000000..0e469a932136cb9496c670a247bb0504abb97cee --- /dev/null +++ b/www/lib/ionic/scss/_slides.scss @@ -0,0 +1,529 @@ +/** + * Swiper 3.2.7 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/swiper/ + * + * Copyright 2015, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: December 7, 2015 + */ +.swiper-container { + margin: 0 auto; + position: relative; + overflow: hidden; + /* Fix of Webkit flickering */ + z-index: 1; +} +.swiper-container-no-flexbox .swiper-slide { + float: left; +} +.swiper-container-vertical > .swiper-wrapper { + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; +} +.swiper-wrapper { + position: relative; + width: 100%; + height: 100%; + z-index: 1; + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -webkit-transition-property: -webkit-transform; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +.swiper-container-android .swiper-slide, +.swiper-wrapper { + -webkit-transform: translate3d(0px, 0, 0); + -moz-transform: translate3d(0px, 0, 0); + -o-transform: translate(0px, 0px); + -ms-transform: translate3d(0px, 0, 0); + transform: translate3d(0px, 0, 0); +} +.swiper-container-multirow > .swiper-wrapper { + -webkit-box-lines: multiple; + -moz-box-lines: multiple; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; +} +.swiper-container-free-mode > .swiper-wrapper { + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; + margin: 0 auto; +} +.swiper-slide { + display: block; + -webkit-flex-shrink: 0; + -ms-flex: 0 0 auto; + flex-shrink: 0; + width: 100%; + height: 100%; + position: relative; +} +/* Auto Height */ +.swiper-container-autoheight, +.swiper-container-autoheight .swiper-slide { + height: auto; +} +.swiper-container-autoheight .swiper-wrapper { + -webkit-box-align: start; + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + -webkit-transition-property: -webkit-transform, height; + -moz-transition-property: -moz-transform; + -o-transition-property: -o-transform; + -ms-transition-property: -ms-transform; + transition-property: transform, height; +} +/* a11y */ +.swiper-container .swiper-notification { + position: absolute; + left: 0; + top: 0; + pointer-events: none; + opacity: 0; + z-index: -1000; +} +/* IE10 Windows Phone 8 Fixes */ +.swiper-wp8-horizontal { + -ms-touch-action: pan-y; + touch-action: pan-y; +} +.swiper-wp8-vertical { + -ms-touch-action: pan-x; + touch-action: pan-x; +} +/* Arrows */ +.swiper-button-prev, +.swiper-button-next { + position: absolute; + top: 50%; + width: 27px; + height: 44px; + margin-top: -22px; + z-index: 10; + cursor: pointer; + -moz-background-size: 27px 44px; + -webkit-background-size: 27px 44px; + background-size: 27px 44px; + background-position: center; + background-repeat: no-repeat; +} +.swiper-button-prev.swiper-button-disabled, +.swiper-button-next.swiper-button-disabled { + opacity: 0.35; + cursor: auto; + pointer-events: none; +} +.swiper-button-prev, +.swiper-container-rtl .swiper-button-next { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); + left: 10px; + right: auto; +} +.swiper-button-prev.swiper-button-black, +.swiper-container-rtl .swiper-button-next.swiper-button-black { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E"); +} +.swiper-button-prev.swiper-button-white, +.swiper-container-rtl .swiper-button-next.swiper-button-white { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E"); +} +.swiper-button-next, +.swiper-container-rtl .swiper-button-prev { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E"); + right: 10px; + left: auto; +} +.swiper-button-next.swiper-button-black, +.swiper-container-rtl .swiper-button-prev.swiper-button-black { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E"); +} +.swiper-button-next.swiper-button-white, +.swiper-container-rtl .swiper-button-prev.swiper-button-white { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E"); +} +/* Pagination Styles */ +.swiper-pagination { + position: absolute; + text-align: center; + -webkit-transition: 300ms; + -moz-transition: 300ms; + -o-transition: 300ms; + transition: 300ms; + -webkit-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + z-index: 10; +} +.swiper-pagination.swiper-pagination-hidden { + opacity: 0; +} +.swiper-pagination-bullet { + width: 8px; + height: 8px; + display: inline-block; + border-radius: 100%; + background: #000; + opacity: 0.2; +} +button.swiper-pagination-bullet { + border: none; + margin: 0; + padding: 0; + box-shadow: none; + -moz-appearance: none; + -ms-appearance: none; + -webkit-appearance: none; + appearance: none; +} +.swiper-pagination-clickable .swiper-pagination-bullet { + cursor: pointer; +} +.swiper-pagination-white .swiper-pagination-bullet { + background: #fff; +} +.swiper-pagination-bullet-active { + opacity: 1; +} +.swiper-pagination-white .swiper-pagination-bullet-active { + background: #fff; +} +.swiper-pagination-black .swiper-pagination-bullet-active { + background: #000; +} +.swiper-container-vertical > .swiper-pagination { + right: 10px; + top: 50%; + -webkit-transform: translate3d(0px, -50%, 0); + -moz-transform: translate3d(0px, -50%, 0); + -o-transform: translate(0px, -50%); + -ms-transform: translate3d(0px, -50%, 0); + transform: translate3d(0px, -50%, 0); +} +.swiper-container-vertical > .swiper-pagination .swiper-pagination-bullet { + margin: 5px 0; + display: block; +} +.swiper-container-horizontal > .swiper-pagination { + bottom: 10px; + left: 0; + width: 100%; +} +.swiper-container-horizontal > .swiper-pagination .swiper-pagination-bullet { + margin: 0 5px; +} +/* 3D Container */ +.swiper-container-3d { + -webkit-perspective: 1200px; + -moz-perspective: 1200px; + -o-perspective: 1200px; + perspective: 1200px; +} +.swiper-container-3d .swiper-wrapper, +.swiper-container-3d .swiper-slide, +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top, +.swiper-container-3d .swiper-slide-shadow-bottom, +.swiper-container-3d .swiper-cube-shadow { + -webkit-transform-style: preserve-3d; + -moz-transform-style: preserve-3d; + -ms-transform-style: preserve-3d; + transform-style: preserve-3d; +} +.swiper-container-3d .swiper-slide-shadow-left, +.swiper-container-3d .swiper-slide-shadow-right, +.swiper-container-3d .swiper-slide-shadow-top, +.swiper-container-3d .swiper-slide-shadow-bottom { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 10; +} +.swiper-container-3d .swiper-slide-shadow-left { + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 16+, IE10, Opera 12.50+ */ +} +.swiper-container-3d .swiper-slide-shadow-right { + background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 16+, IE10, Opera 12.50+ */ +} +.swiper-container-3d .swiper-slide-shadow-top { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 16+, IE10, Opera 12.50+ */ +} +.swiper-container-3d .swiper-slide-shadow-bottom { + background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0))); + /* Safari 4+, Chrome */ + background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Chrome 10+, Safari 5.1+, iOS 5+ */ + background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 3.6-15 */ + background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Opera 11.10-12.00 */ + background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + /* Firefox 16+, IE10, Opera 12.50+ */ +} +/* Coverflow */ +.swiper-container-coverflow .swiper-wrapper { + /* Windows 8 IE 10 fix */ + -ms-perspective: 1200px; +} +/* Fade */ +.swiper-container-fade.swiper-container-free-mode .swiper-slide { + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; +} +.swiper-container-fade .swiper-slide { + pointer-events: none; +} +.swiper-container-fade .swiper-slide .swiper-slide { + pointer-events: none; +} +.swiper-container-fade .swiper-slide-active, +.swiper-container-fade .swiper-slide-active .swiper-slide-active { + pointer-events: auto; +} +/* Cube */ +.swiper-container-cube { + overflow: visible; +} +.swiper-container-cube .swiper-slide { + pointer-events: none; + visibility: hidden; + -webkit-transform-origin: 0 0; + -moz-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; + width: 100%; + height: 100%; + z-index: 1; +} +.swiper-container-cube.swiper-container-rtl .swiper-slide { + -webkit-transform-origin: 100% 0; + -moz-transform-origin: 100% 0; + -ms-transform-origin: 100% 0; + transform-origin: 100% 0; +} +.swiper-container-cube .swiper-slide-active, +.swiper-container-cube .swiper-slide-next, +.swiper-container-cube .swiper-slide-prev, +.swiper-container-cube .swiper-slide-next + .swiper-slide { + pointer-events: auto; + visibility: visible; +} +.swiper-container-cube .swiper-slide-shadow-top, +.swiper-container-cube .swiper-slide-shadow-bottom, +.swiper-container-cube .swiper-slide-shadow-left, +.swiper-container-cube .swiper-slide-shadow-right { + z-index: 0; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + -ms-backface-visibility: hidden; + backface-visibility: hidden; +} +.swiper-container-cube .swiper-cube-shadow { + position: absolute; + left: 0; + bottom: 0px; + width: 100%; + height: 100%; + background: #000; + opacity: 0.6; + -webkit-filter: blur(50px); + filter: blur(50px); + z-index: 0; +} +/* Scrollbar */ +.swiper-scrollbar { + border-radius: 10px; + position: relative; + -ms-touch-action: none; + background: rgba(0, 0, 0, 0.1); +} +.swiper-container-horizontal > .swiper-scrollbar { + position: absolute; + left: 1%; + bottom: 3px; + z-index: 50; + height: 5px; + width: 98%; +} +.swiper-container-vertical > .swiper-scrollbar { + position: absolute; + right: 3px; + top: 1%; + z-index: 50; + width: 5px; + height: 98%; +} +.swiper-scrollbar-drag { + height: 100%; + width: 100%; + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 10px; + left: 0; + top: 0; +} +.swiper-scrollbar-cursor-drag { + cursor: move; +} +/* Preloader */ +.swiper-lazy-preloader { + width: 42px; + height: 42px; + position: absolute; + left: 50%; + top: 50%; + margin-left: -21px; + margin-top: -21px; + z-index: 10; + -webkit-transform-origin: 50%; + -moz-transform-origin: 50%; + transform-origin: 50%; + -webkit-animation: swiper-preloader-spin 1s steps(12, end) infinite; + -moz-animation: swiper-preloader-spin 1s steps(12, end) infinite; + animation: swiper-preloader-spin 1s steps(12, end) infinite; +} +.swiper-lazy-preloader:after { + display: block; + content: ""; + width: 100%; + height: 100%; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); + background-position: 50%; + -webkit-background-size: 100%; + background-size: 100%; + background-repeat: no-repeat; +} +.swiper-lazy-preloader-white:after { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E"); +} +@-webkit-keyframes swiper-preloader-spin { + 100% { + -webkit-transform: rotate(360deg); + } +} +@keyframes swiper-preloader-spin { + 100% { + transform: rotate(360deg); + } +} + + +ion-slides { + width: 100%; + height: 100%; + display: block; +} +.slide-zoom { + display: block; + width: 100%; + text-align: center; +} + +.swiper-container { + //position: absolute; + //left: 0; + //top: 0; + width: 100%; + height: 100%; + padding: 0; + //display: flex; + overflow: hidden; +} + +.swiper-wrapper { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + padding: 0; + //display: flex; +} + +.swiper-container { + //width: 100%; + //height: 100%; +} + +.swiper-slide { + width: 100%; + height: 100%; + + box-sizing: border-box; + + //text-align: center; + //font-size: 18px; + //background: #fff; + /* Center slide text vertically */ + //display: flex; + //justify-content: center; + //align-items: center; + + img { + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; + } +} diff --git a/www/lib/ionic/scss/_tabs.scss b/www/lib/ionic/scss/_tabs.scss index a99a9d96c4ea7c48b692797733905d8f400b5bf6..47454105569802de1fa00263af1ae1d320d30b1a 100644 --- a/www/lib/ionic/scss/_tabs.scss +++ b/www/lib/ionic/scss/_tabs.scss @@ -519,3 +519,10 @@ ion-tabs { pointer-events: none; } +.nav-bar-tabs-top.hide ~ .view-container .tabs-top .tabs{ + top: 0 +} +.pane[hide-nav-bar="true"] .has-tabs-top{ + top:$tabs-height +} + diff --git a/www/lib/ionic/scss/_type.scss b/www/lib/ionic/scss/_type.scss index fda6ed8df160556ee05043aa30e47c07c6308d25..7ad62fa47174eac3529ec30624562880c4202367 100644 --- a/www/lib/ionic/scss/_type.scss +++ b/www/lib/ionic/scss/_type.scss @@ -103,13 +103,13 @@ blockquote { margin: 0 0 $line-height-computed; padding: ($line-height-computed / 2) $line-height-computed; border-left: 5px solid gray; - + p { font-weight: 300; font-size: ($font-size-base * 1.25); line-height: 1.25; } - + p:last-child { margin-bottom: 0; } @@ -148,6 +148,9 @@ address { // Links // ------------------------- +a { + color: $link-color; +} a.subdued { padding-right: 10px; diff --git a/www/lib/ionic/scss/_variables.scss b/www/lib/ionic/scss/_variables.scss index edbb6f9297c5d8af6a92b246d9279c2ce4828960..52674293edbe928250cc618844605d3a01e1b7d2 100644 --- a/www/lib/ionic/scss/_variables.scss +++ b/www/lib/ionic/scss/_variables.scss @@ -16,8 +16,9 @@ $dark: #444 !default; // Base // ------------------------------- -$font-family-sans-serif: "Helvetica Neue", "Roboto", "Segoe UI", sans-serif !default; -$font-family-light-sans-serif: "HelveticaNeue-Light", "Roboto-Light", "Segoe UI-Light", sans-serif-light !default; +$font-family-sans-serif: '-apple-system', "Helvetica Neue", "Roboto", "Segoe UI", sans-serif !default; + +$font-family-light-sans-serif: '-apple-system', "HelveticaNeue-Light", "Roboto-Light", "Segoe UI-Light", sans-serif-light !default; $font-family-serif: serif !default; $font-family-monospace: monospace !default; @@ -69,7 +70,7 @@ $scroll-refresh-icon-color: #666666 !default; $button-color: #222 !default; $button-block-margin: 10px !default; $button-clear-padding: 6px !default; -$button-border-radius: 2px !default; +$button-border-radius: 4px !default; $button-border-width: 1px !default; $button-font-size: 16px !default; diff --git a/www/lib/ionic/scss/ionic.scss b/www/lib/ionic/scss/ionic.scss index a5110f93efe973a518955afa55767c5e9ee36594..e3465b714f29ff405165beea4c82b257fe4af488 100644 --- a/www/lib/ionic/scss/ionic.scss +++ b/www/lib/ionic/scss/ionic.scss @@ -27,6 +27,7 @@ "list", "badge", "slide-box", + "slides", "refresher", "spinner", diff --git a/www/lib/ionic/version.json b/www/lib/ionic/version.json index fb2d6aae13140ba102617cce290864b263de1643..1cbefcc58739bb5e2fc2b8b7a0071886a5155e3a 100644 --- a/www/lib/ionic/version.json +++ b/www/lib/ionic/version.json @@ -1,6 +1,6 @@ { - "version": "1.0.1", - "codename": "vanadium-vaquita", - "date": "2015-06-30", - "time": "16:26:56" + "version": "1.2.4", + "codename": "", + "date": "2016-01-03", + "time": "19:55:51" } diff --git a/www/templates/account/view_transfer.html b/www/templates/account/view_transfer.html deleted file mode 100644 index 45975b126de39d21161ec9d5377fe9b78c26f8e9..0000000000000000000000000000000000000000 --- a/www/templates/account/view_transfer.html +++ /dev/null @@ -1,52 +0,0 @@ -<ion-view view-title="{{'TRANSFER.TITLE' | translate}}" left-buttons="leftButtons"> - <ion-nav-buttons side="secondary"> - <button class="button button-positive" ng-click="doTransfer()"> - <i class="icon ion-android-send"></i> - </button> - </ion-nav-buttons> - - <ion-content> - <div class="scroll"> - <div class="list"> - <span class="item item-icon-left"> - <i class="icon ion-key"></i> - {{'TRANSFER.FROM' | translate}} - <span class="badge badge-calm">{{walletData.pubkey.substr(0,8)}}</span> - </span> - - <span class="item item-icon-left item-button-right" ng-click="openSearch()"> - <i class="icon ion-person"></i> - {{'TRANSFER.TO' | translate}} - <span class="badge badge-royal">{{dest}}</span> - <i class="button button-clear ion-chevron-right"></i> - </span> - - <div class="item item-input item-floating-label" ng-if="!walletData.useRelative"> - <span class="input-label">{{'TRANSFER.AMOUNT' | translate}} ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> - <input type="number" placeholder="{{'TRANSFER.AMOUNT_HELP' | translate}} ({{unit | abbreviate}}{{udUnit | abbreviate}})" ng-model="formData.amount" > - </div> - - <div class="item item-input item-floating-label" ng-if="walletData.useRelative"> - <span class="input-label">{{'TRANSFER.AMOUNT' | translate}} ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> - <input type="text" placeholder="{{'TRANSFER.AMOUNT_HELP' | translate}} ({{unit | abbreviate}}{{udUnit | abbreviate}})" ng-model="formData.amount" > - </div> - - <div class="item item-toggle dark"> - {{'COMMON.BTN_RELATIVE_UNIT' | translate}} - <label class="toggle toggle-royal"> - <input type="checkbox" ng-model="walletData.useRelative"> - <div class="track"> - <div class="handle"></div> - </div> - </label> - </div> - - <label class="item item-input"> - <textarea placeholder="{{'TRANSFER.COMMENTS_HELP' | translate}}" ng-model="formData.comments"></textarea> - </label> - </div> - - <div class="scroll-bar scroll-bar-v"></div> - </div> - </ion-content> -</ion-view> \ No newline at end of file diff --git a/www/templates/account/view_wallet.html b/www/templates/account/view_wallet.html deleted file mode 100644 index 7a87eb763b1f16e990c15fb2162b57d36a818b15..0000000000000000000000000000000000000000 --- a/www/templates/account/view_wallet.html +++ /dev/null @@ -1,71 +0,0 @@ -<ion-view view-title="{{'ACCOUNT.TITLE' | translate}}" left-buttons="leftButtons"> - <ion-content> - <div class="scroll"> - <div class="list"> - - <span class="item item-icon-left" ng-if="isMember"> - <i class="icon ion-person"></i> - <h2>{{walletData.uid}}</h2> - <p>{{'COMMON.PUBKEY' | translate}}: {{walletData.pubkey | formatPubkey}}</p> - </span> - - <span class="item item-icon-left" ng-if="!isMember"> - <i class="icon ion-key"></i> - {{'COMMON.PUBKEY' | translate}} - <span class="badge">{{walletData.pubkey | formatPubkey}}</span> - </span> - - <span class="item item-icon-left"> - <i class="icon ion-card"></i> - {{'ACCOUNT.BALANCE' | translate}} - <span class="badge badge-balanced" ng-if="!walletData.useRelative">{{convertedBalance | formatInteger}} {{unit | abbreviate}}</span> - <span class="badge badge-balanced" ng-if="walletData.useRelative">{{convertedBalance | formatDecimal}} {{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub></span> - </span> - - <div class="item item-toggle dark"> - {{'COMMON.BTN_RELATIVE_UNIT' | translate}} - <label class="toggle toggle-royal"> - <input type="checkbox" ng-model="walletData.useRelative"> - <div class="track"> - <div class="handle"></div> - </div> - </label> - </div> - - <div class="item"> - - </div> - - <div class="item item-button-right positive" ng-if="hasCredit" ng-click="transfer()"> - {{'ACCOUNT.BTN_SEND_MONEY' | translate}} - <a class="button button-clear button-positive" > - <i class="icon-right ion-chevron-right"></i> - </a> - </div> - - <div class="item item-button-right positive" ng-if="!isMember" ng-click="self()"> - {{'ACCOUNT.BTN_REGISTER' | translate}} - <a class="button button-clear button-positive" > - <i class="icon-right ion-chevron-right"></i> - </a> - </div> - - <div class="item"> - - </div> - - <div class="item item-divider"> - {{'ACCOUNT.LAST_TX' | translate}} - </div> - - <a href="#" class="item" ng-repeat="tx in walletData.history" ng-if="walletData.history"> - <h3>{{tx.time | formatDate}}</h3> - <p ng-if="tx.issuer">{{'COMMON.PUBKEY' | translate}}: {{tx.issuer | formatPubkey}}</p> - <span class="badge item-note" ng-if="!walletData.useRelative">{{tx.amount | formatInteger}}</span> - <span class="badge item-note" ng-if="walletData.useRelative">{{tx.amount/walletData.currentUD | formatDecimal}}</span> - </a> - </div> - <div class="scroll-bar scroll-bar-v"></div> - </div> - </ion-content> -</ion-view> \ No newline at end of file diff --git a/www/templates/currency/lookup.html b/www/templates/currency/lookup.html new file mode 100644 index 0000000000000000000000000000000000000000..3424c1aa6d6140f8e08b6df4a3cb30a9dde12d92 --- /dev/null +++ b/www/templates/currency/lookup.html @@ -0,0 +1,7 @@ +<ion-view view-title="{{'CURRENCY.SELECT.TITLE' | translate}}"> + <ion-content class="padding no-padding-xs"> + <h4 class="content double-padding-x" translate>CURRENCY.SELECT.CURRENCIES</h4> + + <ng-include src="'templates/currency/lookup_form.html'"/> + </ion-content> +</ion-view> diff --git a/www/templates/currency/lookup_form.html b/www/templates/currency/lookup_form.html new file mode 100644 index 0000000000000000000000000000000000000000..850d2e807e85c259190c9ba386f2de19517b985d --- /dev/null +++ b/www/templates/currency/lookup_form.html @@ -0,0 +1,22 @@ + + +<ion-list> + + <div class="item center" ng-if="search.looking"> + <ion-spinner icon="android"></ion-spinner> + </div> + + <div ng-repeat="currency in knownCurrencies" + ng-class="{ selected: selectedCurrency == currency }"> + <a class="item hidden-xs hidden-sm ink" ng-click="selectCurrency(currency.id, true)" + ng-class="{ selected: selectedCurrency == currency }"> + <h3>{{currency.id}}</h3> + <h4 class="gray">{{currency.peer}}</h4> + </a> + <a class="item item-text-wrap visible-xs visible-sm ink" ng-click="selectCurrency(currency.id, false)" + ng-class="{ selected: selectedCurrency == currency }"> + <h3>{{currency.id}}</h3> + <h4 class="gray">{{currency.peer}}</h4> + </a> + </div> +</ion-list> diff --git a/www/templates/explore/tabs/explore_tab_network.html b/www/templates/currency/tabs/view_network.html similarity index 84% rename from www/templates/explore/tabs/explore_tab_network.html rename to www/templates/currency/tabs/view_network.html index ada8aec455d010a7803e8934e423d6b2d26b5f96..ee491a9e73446825ee5d141ccc30259e57dda4f1 100644 --- a/www/templates/explore/tabs/explore_tab_network.html +++ b/www/templates/currency/tabs/view_network.html @@ -1,5 +1,4 @@ -<ion-content class="has-header padding"> <div class="list"> <div class="item item-divider item-icon-right"> @@ -12,9 +11,8 @@ ng-class="{ assertive: !peer.online, balanced: (peer.online && peer.hasMainConsensusBlock), energized: (peer.online && !peer.hasMainConsensusBlock) }" ui-sref="app.view_peer(peer)"> <i class="icon ion-android-globe"></i> - <h3><span ng-class="{ positive: peer.uid }">{{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="light">{{peer.dns && ' | ' + peer.dns}}</span></h3> + <h3><span ng-class="{ positive: peer.uid }">{{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="gray">{{peer.dns && ' | ' + peer.dns}}</span></h3> <h4>{{peer.getURL()}}</h4> <span class="badge" ng-class="{ 'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock }">{{peer.current.number}}</span> </a> </div> -</ion-content> \ No newline at end of file diff --git a/www/templates/explore/tabs/explore_tab_currency.html b/www/templates/currency/tabs/view_parameters.html similarity index 95% rename from www/templates/explore/tabs/explore_tab_currency.html rename to www/templates/currency/tabs/view_parameters.html index 52e128e8a9fed876bb88d83b894e3c524e255d70..e453f4dec2aec93bf085f51f0686dc961eb3de46 100644 --- a/www/templates/explore/tabs/explore_tab_currency.html +++ b/www/templates/currency/tabs/view_parameters.html @@ -1,10 +1,10 @@ -<ion-content class="has-header"> + <div class="list"> <a href="#" class="item item-icon-left"> <i class="icon ion-android-bookmark"></i> <span translate>CURRENCY.VIEW.CURRENCY_NAME</span> - <span class="item-note">{{selectedCurrency}} meta_brouzouf ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> + <span class="item-note">{{selectedCurrency}} super_currency ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> </a> <a class="item item-icon-left" href="#"> @@ -91,4 +91,3 @@ <span class="item-note">MAX(UD<sub>t-1</sub>, c*M/N)</span> </a> </div> -</ion-content> \ No newline at end of file diff --git a/www/templates/currency/view_currency.html b/www/templates/currency/view_currency.html new file mode 100644 index 0000000000000000000000000000000000000000..4d91717576fa8e44feb9aa1528395178a3134343 --- /dev/null +++ b/www/templates/currency/view_currency.html @@ -0,0 +1,48 @@ +<ion-view view-title="{{id}}" left-buttons="leftButtons" class="pane"> + <ion-nav-buttons side="secondary"> + <button class="button button-icon button-clear icon ion-loop" ng-click="doUpdate()"> + </button> + </ion-nav-buttons> + <!-- + TODO : use a ng-if to show/hide when small/large + <div class="scroll visible-xs">--> + <div class="scroll"> + <ion-tabs class="tabs-icon-top tabs-positive has-header"> + + <ion-tab title="{{'CURRENCY.VIEW.TAB_CURRENCY'|translate}}" icon="ion-stats-bars"> + <ion-nav-view name="currency-tab"/> + <ion-content> + <ng-include src="'templates/currency/tabs/view_parameters.html'"/> + </ion-content> + </ion-tab> + + <ion-tab title="{{'CURRENCY.VIEW.TAB_WOT'|translate}}" icon="ion-person-stalker"> + <ion-nav-view name="wot-tab"/> + <ion-content class="padding no-padding-xs"> + <ng-include src="'templates/wot/lookup_form.html'"></ng-include> + </ion-content> + </ion-tab> + + <ion-tab title="{{'CURRENCY.VIEW.TAB_NETWORK'|translate}}" icon="ion-network" > + <ion-nav-view name="network-tab"/> + <ion-content class="padding no-padding-xs"> + <ng-include src="'templates/currency/tabs/view_network.html'"/> + </ion-content> + </ion-tab> + + </ion-tab> + </ion-tabs> + </div> + + <!--<ion-content class="has-header hidden-xs"> + <div class="row scroll"> + <div class="col-50 "> + <ng-include src="'templates/explore/tabs/explore_tab_currency.html'"/> + </div> + <div class="col-50 "> + <ng-include src="'templates/explore/tabs/explore_tab_network.html'"/> + </div> + </div> + <div class="scroll-bar scroll-bar-v"></div> + </ion-content>--> +</ion-view> diff --git a/www/templates/currency/view_currency_lg.html b/www/templates/currency/view_currency_lg.html new file mode 100644 index 0000000000000000000000000000000000000000..7baedaf06adfca1ab44551b0b3a38896974aa4d6 --- /dev/null +++ b/www/templates/currency/view_currency_lg.html @@ -0,0 +1,27 @@ +<ion-view view-title="{{'CURRENCY.VIEW.TITLE' | translate}} {{id}}" left-buttons="leftButtons" class="pane"> + <ion-nav-buttons side="secondary"> + <button class="button button-icon button-clear icon ion-loop" ng-click="doUpdate()"> + </button> + </ion-nav-buttons> + + <ion-content> + <div class="scroll"> + <div class="row"> + </div> + </div> + <div class="row responsive-sm"> + <div class="col col-50 "> + <ng-include src="'templates/currency/tabs/view_parameters.html'"></ng-include> + </div> + <div class="col col-50"> + <div class="item item-divider" translate> + CURRENCY.VIEW.TAB_WOT + </div> + <ng-include src="'templates/wot/lookup_form.html'"></ng-include> + <ng-include src="'templates/currency/tabs/view_network.html'"></ng-include> + </div> + </div> + <div class="scroll-bar scroll-bar-v"></div> + </div> + </ion-content> +</ion-view> diff --git a/www/templates/explore/view_peer.html b/www/templates/currency/view_peer.html similarity index 80% rename from www/templates/explore/view_peer.html rename to www/templates/currency/view_peer.html index bed9943b660af36e5064ad6200b76af7b440ce17..23951f3b4d5c89cd8094c5be45150632cf3c27ef 100644 --- a/www/templates/explore/view_peer.html +++ b/www/templates/currency/view_peer.html @@ -15,8 +15,8 @@ ng-class="{ assertive: !peer.online, balanced: peer.online }" ng-href="http://{{peer.getURL()}}/blockchain/current"> <i class="icon ion-android-globe"></i> - <h3><span ng-class="{ positive: peer.uid }">{{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="light">{{peer.dns && ' | ' + peer.dns}}</span></h3> - <h4>{{peer.getURL()}} <span class="light">| {{'PEER.SIGNED_ON_BLOCK' | translate}}</span> #{{peer.blockNumber}}</h4> + <h3><span ng-class="{ positive: peer.uid }">{{peer.uid || peer.pubkey.substr(0,8)}}</span> <span class="gray">{{peer.dns && ' | ' + peer.dns}}</span></h3> + <h4>{{peer.getURL()}} <span class="gray">| {{'PEER.SIGNED_ON_BLOCK' | translate}}</span> #{{peer.blockNumber}}</h4> <span class="badge" ng-class="{ 'badge-balanced': peer.hasMainConsensusBlock, 'badge-energized': peer.hasConsensusBlock }">{{peer.current.number}}</span> </a> </div> diff --git a/www/templates/explore/tabs/explore_tab_wot.html b/www/templates/explore/tabs/explore_tab_wot.html deleted file mode 100644 index 4df204938b29c66d8b648d08d75b7273610ca8a8..0000000000000000000000000000000000000000 --- a/www/templates/explore/tabs/explore_tab_wot.html +++ /dev/null @@ -1,2 +0,0 @@ - -<ng-include src="'templates/wot/lookup.html'"></ng-include> \ No newline at end of file diff --git a/www/templates/home/home.html b/www/templates/home/home.html new file mode 100644 index 0000000000000000000000000000000000000000..e7e872c3fc8ebab5825e3b02b9c37a52498288cd --- /dev/null +++ b/www/templates/home/home.html @@ -0,0 +1,32 @@ +<ion-view view-title="{{'HOME.TITLE'|translate}}"> + <!--<ion-nav-title> + <img src="img/logo.png"> + </ion-nav-title>--> + + <ion-content class="has-header center padding positive-900-bg" id="home"> + + <!--img class="center" src="img/lesou-120px.png"/--> + <h2 translate>HOME.WELCOME</h2> + <h4 translate>HOME.MESSAGE</h4> + + <div class="row no-padding"> + <div class="col-25 hidden-xs hidden-sm"> + </div> + <div class="col"> + <button type="button" + class="button button-block button-stable button-raised icon icon-left ion-ios-world-outline ink-dark" + ui-sref="app.currency_lookup" translate>HOME.BTN_CURRENCIES</button> + <button type="button" + class="button button-block button-stable button-raised icon icon-left ion-locked ink-dark" + ng-click="login()" ng-show="!isLogged()" translate>COMMON.BTN_LOGIN</button> + <button type="button" + class="button button-block button-light ink button-clear" + ng-click="newAccount()" ng-show="!isLogged()" translate>COMMON.BTN_ADD_ACCOUNT</button> + </div> + <div class="col-25 hidden-xs hidden-sm"> + </div> + </div> + + </ion-content> + +</ion-view> diff --git a/www/templates/account/new_account.html b/www/templates/home/new_account_wizard.html similarity index 81% rename from www/templates/account/new_account.html rename to www/templates/home/new_account_wizard.html index 91bd5c84e3bf5db01e613d0977ca076856fd6cfe..2e202e3be3aaeaef6ae8966cc90fc16178493c22 100644 --- a/www/templates/account/new_account.html +++ b/www/templates/home/new_account_wizard.html @@ -2,37 +2,41 @@ <ion-header-bar class="bar-positive"> - <button class="button button-positive icon icon-left ion-chevron-left" ng-click="previous()" ng-show="slideIndex > 0" translate>COMMON.BTN_BACK</button> - <button class="button button-positive" ng-click="cancel()" ng-show="slideIndex == 0" translate>COMMON.BTN_CANCEL</button> + <button class="button button-icon button-clear icon ion-ios-arrow-back buttons header-item" ng-click="slidePrev()" ng-show="slides.slider.activeIndex > 0"> + </button> + <button class="button button-clear text-no-wrap" ng-click="cancel()" ng-show="slides.slider.activeIndex == 0" translate>COMMON.BTN_CANCEL</button> <h1 class="title" translate>ACCOUNT.NEW.TITLE</h1> - <button class="button button-positive button-icon ion-android-send" ng-click="doNewAccount()" ng-show="slideIndex == 2"></button> + <button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doNewAccount()" ng-show="slides.slider.activeIndex == 2"></button> </ion-nav-buttons> </ion-header-bar> - <ion-slide-box on-slide-changed="slideChanged(index)" id="newAccount" class="has-header"> - <ion-slide> - <div class="padding"> - <ng-include src="'templates/currency/select_currency.html'"></ng-include> - </div> - </ion-slide> - <ion-slide> - <div class="padding"> - <h1 translate>ACCOUNT.NEW.SLIDE_2_TITLE</h1> + <ion-slides options="slides.options" slider="slides.slider"> + <ion-slide-page> + <ion-content class="has-header padding"> + <h3 translate>ACCOUNT.NEW.SLIDE_1_TITLE</h3> + <ng-include src="'templates/currency/lookup_form.html'"></ng-include> + </ion-content> + </ion-slide-page> + <ion-slide-page> + <ion-content class="has-header padding"> + <h3 translate>ACCOUNT.NEW.SLIDE_2_TITLE</h3> <button class="button button-block button-stable icon icon-left ion-person" ng-click="selectAccountTypeMember(true)" ng-class="{ selected: accountTypeMember != null && accountTypeMember }" translate>ACCOUNT.NEW.MEMBER_ACCOUNT</button> <button class="button button-block button-stable icon icon-left ion-card" ng-click="selectAccountTypeMember(false)" ng-class="{ selected: accountTypeMember != null && !accountTypeMember }" translate>ACCOUNT.NEW.WALLET_ACCOUNT</button> - </div> - </ion-slide> - <ion-slide> + </ion-content> + </ion-slide-page> + <ion-slide-page> + <ion-content class="has-header"> <form name="accountForm" novalidate="" ng-submit="doNewAccount()"> <div class="list" ng-init="setAccountForm(accountForm)"> <!-- pseudo --> <label class="item item-input" + ng-if="accountData.isMember" ng-class="{'item-input-error': accountForm.$submitted && accountForm.pseudo.$invalid}"> <span class="input-label" translate>ACCOUNT.NEW.PSEUDO</span> <input name="pseudo" type="text" placeholder="{{'ACCOUNT.NEW.PSEUDO_HELP' | translate}}" @@ -41,7 +45,7 @@ required> </label> <div class="form-errors" - ng-if="accountForm.$submitted && accountForm.pseudo.$error" + ng-if="accountData.isMember && accountForm.$submitted && accountForm.pseudo.$error" ng-messages="accountForm.pseudo.$error"> <div class="form-error" ng-message="required"> <span translate="ERROR.FIELD_REQUIRED"></span> @@ -117,21 +121,22 @@ ng-click="showAccountPubkey()" ng-if="!accountData.pubkey && accountForm.$valid" class="animate-if" translate> - COMMON.BTN_SHOW + COMMON.BTN_SHOW_PUBKEY </a> - <span class="badge badge-energized" ng-if="accountData.pubkey"> - {{accountData.pubkey | formatPubkey}} + <span class="item-input" ng-if="accountData.pubkey"> + {{accountData.pubkey}} </span> </div> </div> - <div class="padding"> + <div class="padding hidden-xs"> <button class="button button-block button-positive" type="submit"> {{'COMMON.BTN_OK' | translate}} </button> </div> </form> - </ion-slide> + </ion-content> + </ion-slide-page> </ion-slide-box> </ion-view> @@ -144,4 +149,4 @@ <i class="ion-information-circled"></i> <div translate="ERROR.FIELD_TOO_SHORT"></div> </div> -</script> \ No newline at end of file +</script> diff --git a/www/templates/login.html b/www/templates/login.html index 632523cd7d4b7d115a5e3f063a1159252ae43762..ee6657649e99c30bc71333938419c8acdc06d2b7 100644 --- a/www/templates/login.html +++ b/www/templates/login.html @@ -1,15 +1,19 @@ -<ion-modal-view> +<ion-modal-view class="login"> <ion-header-bar class="bar-positive"> - <button class="button button-positive" ng-click="cancelLogin()" translate>COMMON.BTN_CANCEL + <button class="button button-clear visible-xs" ng-click="cancelLogin()" translate>COMMON.BTN_CANCEL </button> <h1 class="title" translate>LOGIN.TITLE</h1> - <button class="button button-positive button-icon ion-android-done" ng-click="doLogin()"></button> + <div class="buttons buttons-right"> + <span class="secondary-buttons"> + <button class="button button-positive button-icon button-clear icon ion-android-done visible-xs" ng-click="doLogin()"> + </button> + </span></div> </ion-header-bar> - <ion-content scroll="false"> + <ion-content > <form name="loginForm" novalidate="" ng-submit="doLogin()"> - <div class="list" - ng-init="setLoginForm(loginForm)"> + + <div class="list" ng-init="setLoginForm(loginForm)"> <!-- username --> <label class="item item-input" @@ -18,6 +22,7 @@ <input name="username" type="text" placeholder="{{'LOGIN.USERNAME_HELP' | translate}}" ng-model="loginData.username" ng-change="loginDataChanged()" + class="highlight-light" required> </label> <div class="form-errors" @@ -45,24 +50,32 @@ </div> </div> - <!-- show public key --> - <div class="item item-icon-left item-button-right"> - <i class="icon ion-key"/> - <span translate>COMMON.PUBKEY</span> - <a class="button button-light button-small" ng-click="showLoginPubkey()" ng-if="!(loginData.pubkey || loginData.computing || !loginData.username || !loginData.password)" - class="animate-if"> - {{'COMMON.BTN_SHOW' | translate}} - </a> - <span class="badge badge-energized" ng-if="loginData.pubkey"> - {{loginData.pubkey | formatPubkey}} - </span> + <!-- Show public key --> + <div class="item item-icon-left item-button-right left"> + <span class="input-label" translate>COMMON.PUBKEY</span> + <a class="button button-light button-small ink" + ng-click="showLoginPubkey()" + ng-if="!(loginData.pubkey || loginData.computing || !loginData.username || !loginData.password)" + class="animate-if"> + {{'COMMON.BTN_SHOW_PUBKEY' | translate}} + </a> + <h3 class="gray text-no-wrap" ng-if="loginData.pubkey"> + {{loginData.pubkey}} + </h3> </div> </div> - <div class="padding"> - <button class="button button-block button-positive" type="submit"> - {{'COMMON.BTN_OK' | translate}} + + <div class="padding hidden-xs text-right"> + <button class="button button-small button-clear button-dark ink" ng-click="cancelLogin()" type="button" translate>COMMON.BTN_CANCEL + </button> + <button class="button button-small button-positive ink" type="submit"> + {{'COMMON.BTN_LOGIN' | translate}} </button> </div> + <!--div class="padding hidden-xs text-right"> + <a class="assertive ink" ng-click="openNewAccount()" type="button" translate>COMMON.NO_ACOUNT_QUESTION + </a> + </div--> </form> </ion-content> </ion-modal-view> diff --git a/www/templates/menu.html b/www/templates/menu.html index 63cb9d4d0394a3eb939796fbca48fae486a06c33..75e48b29902b2f7dd7927aca2b3b3b66a92bbd6a 100644 --- a/www/templates/menu.html +++ b/www/templates/menu.html @@ -1,46 +1,57 @@ <ion-side-menus enable-menu-with-back-views="true"> <!-- MENU --> - <ion-side-menu side="left"> - <ion-header-bar class="bar-royal"> + <ion-side-menu side="left" id="menu" expose-aside-when="large" enable-menu-with-back-views="false"> + <ion-header-bar class="bar"> <h1 class="title" translate> MENU.TITLE </h1> - <button class="button button-assertive" ng-click="logout()" ng-if="isLogged()"> - <i class="icon ion-log-out"></i> - <span translate>COMMON.BTN_LOGOUT</span> - </button> </ion-header-bar> <ion-content scroll="false"> - <ion-item menu-close href="#/app/home"> + <ion-list class="list animate-rip"> + <ion-item menu-close class="item-icon-left" href="#/app/home"> + <i class="icon ion-home"></i> <span translate>MENU.HOME</span> </ion-item> - <ion-item menu-close href="#/app/currency"> + <ion-item menu-close class="item item-icon-left" href="#/app/currency"> + <i class="icon ion-ios-world-outline"></i> <span translate>MENU.CURRENCIES</span> </ion-item> - <ion-item menu-close ng-click="login()" ng-if="!isLogged()"> + <div class="item item-divider"></div> + + <ion-item menu-close class="item item-icon-left" ng-click="login()" ng-if="!isLogged()"> + <i class="icon ion-card"></i> <span translate>MENU.ACCOUNT</span> </ion-item> - <ion-item menu-close href="#" ui-sref="app.view_wallet" ng-if="isLogged()"> + <ion-item menu-close class="item item-icon-left" href="#" ui-sref="app.view_wallet" ng-if="isLogged()"> + <i class="icon ion-card"></i> <span translate>MENU.ACCOUNT</span> </ion-item> <!-- <ion-item menu-close ng-click="addAccount()"> Add account </ion-item> --> + <ion-item menu-close class="item item-icon-left" href="#/app/settings"> + <i class="icon ion-wrench"></i> + <span translate>MENU.SETTINGS</span> + </ion-item> + <ion-item menu-close class="item item-assertive item-icon-left" ng-click="logout()" ng-if="isLogged()"> + <i class="icon ion-log-out"></i> + <span translate>COMMON.BTN_LOGOUT</span> + </ion-item> + </ion-list> </ion-content> </ion-side-menu> <!-- HEADER --> <ion-side-menu-content> - <ion-nav-bar class="bar-stable"> - <ion-nav-back-button> - {{'COMMON.BTN_BACK'|translate}} + <ion-nav-bar class="bar-dark" title-align="left"> + <ion-nav-back-button class="no-text"> </ion-nav-back-button> <ion-nav-buttons side="left"> - <button class="button button-icon button-clear ion-navicon" menu-toggle="left"></button> + <button class="button button-icon button-clear icon ion-navicon visible-xs" menu-toggle="left" ></button> </ion-nav-buttons> </ion-nav-bar> <ion-nav-view name="menuContent"></ion-nav-view> diff --git a/www/templates/settings/settings.html b/www/templates/settings/settings.html new file mode 100644 index 0000000000000000000000000000000000000000..fc3753ae408b7613a08c0c9dc0acb23e45777f59 --- /dev/null +++ b/www/templates/settings/settings.html @@ -0,0 +1,17 @@ +<ion-view left-buttons="leftButtons" + view-title="Settings"> + + <ion-content > + <div class="positive-900-bg item item-content item-toggle dark"> + <h4 class="gray"> + {{'COMMON.BTN_RELATIVE_UNIT' | translate}} + </h4> + <label class="toggle toggle-royal"> + <input type="checkbox" ng-model="walletData.useRelative"> + <div class="track"> + <div class="handle"></div> + </div> + </label> + </div> + </ion-content> +</ion-view> diff --git a/www/templates/wallet/modal_transfer.html b/www/templates/wallet/modal_transfer.html new file mode 100644 index 0000000000000000000000000000000000000000..31c4d2c8a7c48dd13015ea2a30c9a04eed88e55c --- /dev/null +++ b/www/templates/wallet/modal_transfer.html @@ -0,0 +1,12 @@ +<ion-modal-view id="transfer"> + <ion-header-bar class="bar-positive"> + <button class="button button-clear visible-xs" ng-click="closeTransfer()" translate>COMMON.BTN_CANCEL</button> + <h1 class="title" translate>TRANSFER.MODAL.TITLE</h1> + <button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doTransfer()"> + </button> + </ion-header-bar> + + <ion-content scroll="false"> + <ng-include src="'templates/wallet/transfer_form.html'"></ng-include> + </ion-content> +</ion-modal-view> diff --git a/www/templates/wallet/new_transfer.html b/www/templates/wallet/new_transfer.html new file mode 100644 index 0000000000000000000000000000000000000000..5bd8b9bb95f15bdf9a72ca6d283a0d919035e3c3 --- /dev/null +++ b/www/templates/wallet/new_transfer.html @@ -0,0 +1,14 @@ +<ion-view view-title="{{'TRANSFER.TITLE' | translate}}" left-buttons="leftButtons"> + <ion-nav-buttons side="secondary"> + <button class="button button-icon button-clear icon ion-android-send visible-xs" ng-click="doTransfer()"> + </button> + </ion-nav-buttons> + + <ion-content class="no-padding-xs"> + <div class="scroll"> + <ng-include src="'templates/wallet/transfer_form.html'"></ng-include> + + <div class="scroll-bar scroll-bar-v"></div> + </div> + </ion-content> +</ion-view> diff --git a/www/templates/account/popup_register.html b/www/templates/wallet/popup_register.html similarity index 100% rename from www/templates/account/popup_register.html rename to www/templates/wallet/popup_register.html diff --git a/www/templates/wallet/transfer_form.html b/www/templates/wallet/transfer_form.html new file mode 100644 index 0000000000000000000000000000000000000000..69f46d3e778ceb289d0b33273fb5637d38a08c74 --- /dev/null +++ b/www/templates/wallet/transfer_form.html @@ -0,0 +1,57 @@ + <form name="transferForm" novalidate="" ng-submit="doTransfer()"> + + <div class="list" ng-init="setTransferForm(transferForm)"> + + <a class="item item-button-right gray ink" ng-click="openWotLookup()"> + <span class="gray" translate>TRANSFER.TO</span> + <span class="badge badge-royal">{{dest | formatPubkey}}</span> + <i class="button button-clear ion-chevron-right"></i> + </a> + + <span class="item item-text-wrap"> + <span class="gray" translate>TRANSFER.FROM</span> + <span class="badge" + ng-class="{'badge-assertive': (convertedBalance <= 0 || (formData.amount && convertedBalance < formData.amount)), 'badge-balanced': (convertedBalance > 0 && (!formData.amount || convertedBalance >= formData.amount)) }"> + {{walletData.pubkey| formatPubkey}} / + <span ng-if="!walletData.useRelative">{{convertedBalance | formatInteger}} {{unit | abbreviate}}</span> + <span ng-if="walletData.useRelative">{{convertedBalance | formatDecimal}} {{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub></span> + </span> + </span> + + <div class="item item-input item-floating-label" ng-if="!walletData.useRelative"> + <span class="input-label">{{'TRANSFER.AMOUNT' | translate}} ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> + <input type="number" placeholder="{{'TRANSFER.AMOUNT_HELP' | translate}} ({{unit | abbreviate}}{{udUnit | abbreviate}})" + ng-model="formData.amount" required> + </div> + + <div class="item item-input item-floating-label" ng-if="walletData.useRelative"> + <span class="input-label">{{'TRANSFER.AMOUNT' | translate}} ({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> + <input type="text" placeholder="{{'TRANSFER.AMOUNT_HELP' | translate}} ({{unit | abbreviate}}{{udUnit | abbreviate}})" ng-model="formData.amount" + required> + </div> + + + <div class="item item-content item-toggle dark"> + <h4 class="gray">{{'TRANSFER.BTN_RELATIVE_UNIT' | translate}}</h4> + <label class="toggle toggle-royal"> + <input type="checkbox" ng-model="walletData.useRelative"> + <div class="track"> + <div class="handle"></div> + </div> + </label> + </div> + + <label class="item item-input"> + <textarea placeholder="{{'TRANSFER.COMMENTS_HELP' | translate}}" ng-model="formData.comments"></textarea> + </label> + </div> + + <div class="padding hidden-xs text-right"> + <button class="button button-small button-clear button-dark ink" ng-click="closeTransfer()" type="button" translate>COMMON.BTN_CANCEL + </button> + <button class="button button-small button-positive ink" type="submit"> + {{'TRANSFER.BTN_SEND' | translate}} + </button> + </div> + </form> + diff --git a/www/templates/wallet/view_wallet.html b/www/templates/wallet/view_wallet.html new file mode 100644 index 0000000000000000000000000000000000000000..bd78a813c07e3aee6a3a440da1881d5bfe895e95 --- /dev/null +++ b/www/templates/wallet/view_wallet.html @@ -0,0 +1,109 @@ +<ion-view left-buttons="leftButtons" + view-title="" + id="wallet"> + + + <ion-nav-buttons side="secondary"> + <button class="button button-icon button-clear icon ion-loop" ng-click="doUpdate()"> + </button> + <button class="button button-icon button-clear icon ion-android-more-vertical visible-xs visible-sm" ng-click="showActionsheet()"> + </button> + </ion-nav-buttons> + + <ion-content + ng-class="{expanded:isExpanded}"> + <div class="scroll"> + + <div class="positive-900-bg hero"> + <div class="content"> + <div class="avatar" + ng-if="!!walletData.avatar" + style="background-image: url({{walletData.avatar}});"></div> + <i class="avatar" ng-class="{'avatar-wallet': !isMember, 'avatar-member': isMember}" ng-if="!walletData.avatar"></i> + <h3 class="light" ng-if="isMember">{{walletData.uid}}</h3> + <h3 class="light" ng-if="!isMember">{{walletData.pubkey | formatPubkey}}</h3> + <h4 class="light"> + <span ng-if="!walletData.useRelative">{{convertedBalance | formatInteger}} {{unit | abbreviate}}</span> + <span ng-if="walletData.useRelative">{{convertedBalance | formatDecimal}} {{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub></span> + </h4> + </div> + </div> + + <div class="hidden-xs hidden-sm padding" style="text-align:center"> + <button class="button button-raised button-assertive ink-dark" + ng-click="openTransfer()"> + {{'ACCOUNT.BTN_SEND_MONEY' | translate}} + </button> + + <button class="button button-raised icon-left ion-person ink" + ng-if="needMembership" + ng-click="membershipIn()"> + {{'ACCOUNT.BTN_MEMBERSHIP_IN' | translate}} + </button> + + <button class="button button-raised icon-left ion-loop ink" + ng-if="needRenew" + ng-click="membershipRenew()"> + {{'ACCOUNT.BTN_MEMBERSHIP_RENEW' | translate}} + </button> + + <button class="button button-raised icon-left ion-log-out ink" + ng-if="needMembershipOut" + ng-click="membershipOut()"> + {{'ACCOUNT.BTN_MEMBERSHIP_OUT' | translate}} + </button> + + <button class="button button-raised icon-left ion-flag ink" + ng-if="needSelf" + ng-click="self()"> + {{'ACCOUNT.BTN_SEND_IDENTITY' | translate}} + </button> + </div> + + <!-- Last Transactions --> + <div class="row no-padding"> + <div class="col col-20 hidden-xs hidden-sm"> + </div> + + <div class="col list animate-fade-slide-in-right" > + <span class="item item-divider"> + {{'ACCOUNT.LAST_TX' | translate}} + <div class="badge item-note"> + <span ng-if="!walletData.useRelative">({{unit | abbreviate}})</span> + <span ng-if="walletData.useRelative">({{unit | abbreviate}}<sub>{{udUnit | abbreviate}}</sub>)</span> + </div> + </span> + + <span class="item" ng-if="!walletData.history || walletData.history.length == 0"> + <h3 translate>ACCOUNT.NO_TX</h3> + </span> + + <span class="item ink" ng-repeat="tx in walletData.history" ng-if="walletData.history && walletData.history.length > 0"> + <h3><i class="icon ion-clock" ng-if="!tx.block_number"> </i>{{tx.time | formatFromNow}} + <span class="gray hidden-xs">| {{tx.time | formatDate}}</span> + </h3> + <h4 class="gray"> + <span class="positive" ng-if="tx.issuer" ui-sref="app.view_identity({pub:tx.issuer})">{{tx.issuer | formatPubkey}}</span> + <span class="positive" ng-if="tx.receiver" ui-sref="app.view_identity({pub:tx.receiver})">{{tx.receiver | formatPubkey}}</span> + <span ng-if="tx.comment" class="comment">| {{tx.comment}}</span> + </h4> + <div class="badge item-note" + ng-class="{'badge-balanced': tx.amount > 0}"> + <span ng-if="!walletData.useRelative">{{tx.amount | formatInteger}}</span> + <span ng-if="walletData.useRelative">{{tx.amount/walletData.currentUD | formatDecimal}}</span> + </div > + </span> + </div> + + <div class="col col-20 hidden-xs hidden-sm"> + </div> + </div> + <div class="scroll-bar scroll-bar-v"></div> + </div> + + </ion-content> + + <button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send hidden-md hidden-lg" + ng-click="openTransfer()"> + </button> +</ion-view> diff --git a/www/templates/wot/lookup_form.html b/www/templates/wot/lookup_form.html new file mode 100644 index 0000000000000000000000000000000000000000..a7c8dc19f1a8a55bbc0b2ac1cfb6d02cd425f02e --- /dev/null +++ b/www/templates/wot/lookup_form.html @@ -0,0 +1,27 @@ + <div class="lookupForm padding no-padding-xs"> + <label class="item item-input"> + <i class="icon ion-search placeholder-icon"></i> + <input type="text" placeholder="{{'WOT.SEARCH_HELP'|translate}}" + ng-model="search.text" + ng-model-options="{ debounce: 250 }" + ng-change="searchChanged()" id="searchWot"> + </label> + + <div class="list" + ng-class="{'list-inset': search.options.listInset}" + ng-if="search.text && search.text.length > 0"> + + <label class="item center text-left" ng-if="search.looking"> + <ion-spinner icon="android"></ion-spinner> + </label> + + <a ng-if="!search.looking" + ng-repeat="found in search.results" + class="item item-icon-left item-avatar ink" + ng-click="doSelectIdentity('{{found.pub}}', '{{found.uid}}')"> + <i class="icon ion-person"></i> + <h2>{{found.uid}}</h2> + <span class="badge">{{found.pub | formatPubkey}}</span> + </a> + </div> + </div> diff --git a/www/templates/wot/modal_lookup.html b/www/templates/wot/modal_lookup.html index f8e9db03bce1507c8c2e0095c39e4ec0c9b95d82..d4a26cfb41061d66d45a0e325c2ff8f6fe6588a5 100644 --- a/www/templates/wot/modal_lookup.html +++ b/www/templates/wot/modal_lookup.html @@ -1,26 +1,15 @@ -<ion-modal-view> +<ion-modal-view id="wotLookup"> <ion-header-bar class="bar-positive"> - <h1 class="title" translate>WOT.MODAL.TITLE</h1> - <button class="button button-positive" ng-click="closeLookup()" translate>COMMON.BTN_CANCEL</button> - </ion-header-bar> - - <ion-content class="lookupForm"> - <div class="list"> - <label class="item item-input"> - <i class="icon ion-search placeholder-icon"></i> - <input type="text" placeholder="{{'WOT.SEARCH_HELP'|translate}}" ng-model="search.text" ng-change="searchChanged()"> - </label> + <button class="button button-clear" ng-click="closeLookup()" translate>COMMON.BTN_CANCEL</button> + <h1 class="title" translate>WOT.MODAL.TITLE</h1> - <label class="item center" ng-if="search.looking"> - <ion-spinner icon="android"></ion-spinner> - </label> + <button class="button button-icon button-clear icon ion-qr-scanner visible-xs" + ng-show="system.camera.enable" + ng-click="scanQrCode()"> + </button> + </ion-header-bar> - <a class="item item-icon-left" ng-repeat="found in search.results" ng-click="doSelectIdentity('{{found.pub}}', '{{found.uid}}')"> - <i class="icon ion-person"></i> - <h2>{{found.uid}}</h2> - <p>{{'COMMON.PUBKEY'|translate}}: {{found.pub.substr(0,24)}}</p> - <span class="badge item-note">{{found.sigDate | formatDate}}</span> - </a> - </div> -</ion-content> -</ion-modal-view> \ No newline at end of file + <ion-content> + <ng-include src="'templates/wot/lookup_form.html'"></ng-include> + </ion-content> +</ion-modal-view> diff --git a/www/templates/wot/view_identity.html b/www/templates/wot/view_identity.html index d8cf130e76429858b168d130ccf6ceb5f8fbdef7..b3765ba78f5503d7b54a4a852afce6f3ee99be55 100644 --- a/www/templates/wot/view_identity.html +++ b/www/templates/wot/view_identity.html @@ -1,44 +1,59 @@ <ion-view view-title="{{identity.uid}}" left-buttons="leftButtons"> -<ion-content> + + + + <ion-content> + <div class="positive-900-bg hero"> + <div class="content"> + <div class="avatar" + ng-if="!!identity.avatar" + style="background-image: url({{identity.avatar}});"></div> + <i class="avatar avatar-member" ng-if="!identity.avatar"></i> + <h3 class="light">{{identity.uid}}</h3> + <h4 class="light"> + {{identity.pub | formatPubkey}} + </h4> + </div> + </div> <div class="scroll"> - <div class="list"> - <span class="item item-icon-left"> - <i class="icon ion-person"></i> - <h2>{{identity.uid}}</h2> - <p>public key: {{identity.pub | formatPubkey}}</p> - <span class="badge"></span> - </span> - - <span class="item item-icon-left"> - <i class="icon ion-calendar"></i> - Registration date - <span class="badge badge-calm">{{identity.sigDate | formatDate}}</span> - </span> - - <div class="item "> - - </div> - - <div class="item item-button-right positive" ng-click="transfer()"> - Send money - <a class="button button-clear button-positive" > - <i class="icon-right ion-chevron-right"></i> - </a> - </div> - - <div class="item item-button-right positive" ng-click="signIdentity()" ng-if="hasSelf"> - Certify - <a class="button button-clear button-positive" > - <i class="icon-right ion-chevron-right"></i> - </a> - </div> - - <!--div class="item item-divider" ng-if="isLogged()"> - Last transactions - </div--> - - </div> - <div class="scroll-bar scroll-bar-v"></div> + + + <div class="hidden-xs hidden-sm padding" style="text-align:center"> + <button class="button button-raised button-assertive ink-dark" + ng-click="transfer(identity.pub, identity.uid)"> + {{'ACCOUNT.BTN_SEND_MONEY' | translate}} + </button> + + <button class="button button-raised icon-left ion-person" ng-click="signIdentity()" ng-if="hasSelf"> + {{'WOT.BTN_CERTIFY' | translate}} + </button> + </div> + + <div class="list animate-fade-slide-in"> + <span class="item item-icon-left"> + <i class="icon ion-calendar"></i> + <span>{{'WOT.REGISTERED_SINCE' | translate}} {{identity.sigDate | formatDate}}</span> + <span class="badge badge-balanced">{{identity.sigDate | formatFromNow}}</span> + </span> + + <ion-item href="#" class="item-icon-left ink" + ng-class="{'ink': system.clipboard.enable}" + on-hold="system.clipboard.copy(identity.pub)"> + <i class="icon ion-key"></i> + <h4 class="gray">{{identity.pub}}</h4> + </span> + </div> + <div class="scroll-bar scroll-bar-v"></div> </div> -</ion-content> + </ion-content> + + <button class="button button-fab button-fab-bottom-right button-assertive icon ion-android-send visible-xs visible-sm" + ng-click="transfer(identity.pub, identity.uid)"> + </button> + + <button class="button button-fab button-fab-bottom-right button-assertive icon ion-ribbon-b visible-xs visible-sm" + ng-click="signIdentity()" + ng-if="hasSelf" + style="bottom:78px;"> + </button> </ion-view>